Index: stable/9/contrib/libpcap/CHANGES =================================================================== --- stable/9/contrib/libpcap/CHANGES (revision 252280) +++ stable/9/contrib/libpcap/CHANGES (revision 252281) @@ -1,672 +1,704 @@ +Monday March 18, 2013 guy@alum.mit.edu +Summary for 1.4.0 libpcap release + Add netfilter/nfqueue interface. + If we don't have support for IPv6 address resolution, support, + in filter expressions, what IPv6 stuff we can. + Checks added for malloc()/realloc()/etc. failures. + Fix pcap-config to include -lpthread if canusb support is + present + Try to fix "pcap_parse not defined" problems when --without-flex + and --without-bison are used when you have Flex and Bison + Fix some issues with the pcap_loop man page. + Fix pcap_getnonblock() and pcap_setnonblock() to fill in the + supplied error message buffer + Fix typo that, it appeared, would cause pcap-libdlpi.c not to + compile (perhaps systems with libdlpi also have BPF and use + that instead) + Catch attempts to call pcap_compile() on a non-activated pcap_t + Fix crash on Linux with CAN-USB support without usbfs + Fix addition of VLAN tags for Linux cooked captures + Check for both EOPNOTSUPP and EINVAL after SIOCETHTOOL ioctl, so + that the driver can report either one if it doesn't support + SIOCETHTOOL + Add DLT_INFINIBAND and DLT_SCTP + Describe "proto XXX" and "protochain XXX" in the pcap-filter man + page + Handle either directories, or symlinks to directories, that + correspond to interfaces in /sys/class/net + Fix handling of VLAN tag insertion to check, on Linux 3.x + kernels, for VLAN tag valid flag + Clean up some man pages + Support libnl3 as well as libnl1 and libnl2 on Linux + Friday March 30, 2012. mcr@sandelman.ca Summary for 1.3.0 libpcap release Handle DLT_PFSYNC in {FreeBSD, other *BSD+Mac OS X, other}. Linux: Don't fail if netfilter isn't enabled in the kernel. Add new link-layer type for NFC Forum LLCP. Put the CANUSB stuff into EXTRA_DIST, so it shows up in the release tarball. Add LINKTYPE_NG40/DLT_NG40. Add DLT_MPEG_2_TS/LINKTYPE_MPEG_2_TS for MPEG-2 transport streams. [PATCH] Fix AIX-3.5 crash with read failure during stress AIX fixes. Introduce --disable-shared configure option. Added initial support for canusb devices. Include the pcap(3PCAP) additions as 1.2.1 changes. many updates to documentation: pcap.3pcap.in Improve 'inbound'/'outbound' capture filters under Linux. Note the cleanup of handling of new DLT_/LINKTYPE_ values. On Lion, don't build for PPC. For mac80211 devices we need to clean up monitor mode on exit. Friday December 9, 2011. guy@alum.mit.edu. Summary for 1.2.1 libpcap release Update README file. Fix typoes in README.linux file. Clean up some compiler warnings. Fix Linux compile problems and tests for ethtool.h. Treat Debian/kFreeBSD and GNU/Hurd as systems with GNU toolchains. Support 802.1 QinQ as a form of VLAN in filters. Treat "carp" as equivalent to "vrrp" in filters. Fix code generated for "ip6 protochain". Add some new link-layer header types. Support capturing NetFilter log messages on Linux. Clean up some error messages. Turn off monitor mode on exit for mac80211 interfaces on Linux. Fix problems turning monitor mode on for non-mac80211 interfaces on Linux. Properly fail if /sys/class/net or /proc/net/dev exist but can't be opened. Fail if pcap_activate() is called on an already-activated pcap_t, and add a test program for that. Fix filtering in pcap-ng files. Don't build for PowerPC on Mac OS X Lion. Simplify handling of new DLT_/LINKTYPE_ values. Expand pcap(3PCAP) man page. Sunday July 24, 2011. mcr@sandelman.ca. Summary for 1.2 libpcap release All of the changes listed below for 1.1.1 and 1.1.2. Changes to error handling for pcap_findalldevs(). Fix the calculation of the frame size in memory-mapped captures. Add a link-layer header type for STANAG 5066 D_PDUs. Add a link-layer type for a variant of 3GPP TS 27.010. Noted real nature of LINKTYPE_ARCNET. Add a link-layer type for DVB-CI. Fix configure-script discovery of VLAN acceleration support. see http://netoptimizer.blogspot.com/2010/09/tcpdump-vs-vlan-tags.html Linux, HP-UX, AIX, NetBSD and OpenBSD compilation/conflict fixes. Protect against including AIX 5.x's having been included. Add DLT_DBUS, for raw D-Bus messages. Treat either EPERM or EACCES as "no soup for you". Changes to permissions on DLPI systems. Add DLT_IEEE802_15_4_NOFCS for 802.15.4 interfaces. Fri. August 6, 2010. guy@alum.mit.edu. Summary for 1.1.2 libpcap release Return DLT_ values, not raw LINKTYPE_ values from pcap_datalink() when reading pcap-ng files Add support for "wlan ra" and "wlan ta", to check the RA and TA of WLAN frames that have them Don't crash if "wlan addr{1,2,3,4}" are used without 802.11 headers Do filtering on USB and Bluetooth capturing On FreeBSD/SPARC64, use -fPIC - it's apparently necessary Check for valid port numbers (fit in a 16-bit unsigned field) in "port" filters Reject attempts to put savefiles into non-blocking mode Check for "no such device" for the "get the media types" ioctl in *BSD Improve error messages from bpf_open(), and let it do the error handling Return more specific errors from pcap_can_set_rfmon(); fix documentation Update description fetching code for FreeBSD, fix code for OpenBSD Ignore /sys/net/dev files if we get ENODEV for them, not just ENXIO; fixes handling of bonding devices on Linux Fix check for a constant 0 argument to BPF_DIV Use the right version of ar when cross-building Free any filter set on a savefile when the savefile is closed Include the CFLAGS setting when configure was run in the compiler flags Add support for 802.15.4 interfaces on Linux Thu. April 1, 2010. guy@alum.mit.edu. Summary for 1.1.1 libpcap release Update CHANGES to reflect more of the changes in 1.1.0. Fix build on RHEL5. Fix shared library build on AIX. Thu. March 11, 2010. ken@netfunctional.ca/guy@alum.mit.edu. Summary for 1.1.0 libpcap release Add SocketCAN capture support Add Myricom SNF API support Update Endace DAG and ERF support Add support for shared libraries on Solaris, HP-UX, and AIX Build, install, and un-install shared libraries by default; don't build/install shared libraries on platforms we don't support Fix building from a directory other than the source directory Fix compiler warnings and builds on some platforms Update config.guess and config.sub Support monitor mode on mac80211 devices on Linux Fix USB memory-mapped capturing on Linux; it requires a new DLT_ value On Linux, scan /sys/class/net for devices if we have it; scan it, or /proc/net/dev if we don't have /sys/class/net, even if we have getifaddrs(), as it'll find interfaces with no addresses Add limited support for reading pcap-ng files Fix BPF driver-loading error handling on AIX Support getting the full-length interface description on FreeBSD In the lexical analyzer, free up any addrinfo structure we got back from getaddrinfo(). Add support for BPF and libdlpi in OpenSolaris (and SXCE) Hyphenate "link-layer" everywhere Add /sys/kernel/debug/usb/usbmon to the list of usbmon locations In pcap_read_linux_mmap(), if there are no frames available, call poll() even if we're in non-blocking mode, so we pick up errors, and check for the errors in question. Note that poll() works on BPF devices is Snow Leopard If an ENXIO or ENETDOWN is received, it may mean the device has gone away. Deal with it. For BPF, raise the default capture buffer size to from 32k to 512k Support ps_ifdrop on Linux Added a bunch of #ifdef directives to make wpcap.dll (WinPcap) compile under cygwin. Changes to Linux mmapped captures. Fix bug where create_ring would fail for particular snaplen and buffer size combinations Update pcap-config so that it handles libpcap requiring additional libraries Add workaround for threadsafeness on Windows Add missing mapping for DLT_ENC <-> LINKTYPE_ENC DLT: Add DLT_CAN_SOCKETCAN DLT: Add Solaris ipnet Don't check for DLT_IPNET if it's not defined Add link-layer types for Fibre Channel FC-2 Add link-layer types for Wireless HART Add link-layer types for AOS Add link-layer types for DECT Autoconf fixes (AIX, HP-UX, OSF/1, Tru64 cleanups) Install headers unconditionally, and include vlan.h/bluetooth.h if enabled Autoconf fixes+cleanup Support enabling/disabling bluetooth (--{en,dis}able-bluetooth) Support disabling SITA support (--without-sita) Return -1 on failure to create packet ring (if supported but creation failed) Fix handling of 'any' device, so that it can be opened, and no longer attempt to open it in Monitor mode Add support for snapshot length for USB Memory-Mapped Interface Fix configure and build on recent Linux kernels Fix memory-mapped Linux capture to support pcap_next() and pcap_next_ex() Fixes for Linux USB capture DLT: Add DLT_LINUX_EVDEV DLT: Add DLT_GSMTAP_UM DLT: Add DLT_GSMTAP_ABIS Mon. October 27, 2008. ken@netfunctional.ca. Summary for 1.0.0 libpcap release Compile with IPv6 support by default Compile with large file support on by default Add pcap-config script, which deals with -I/-L flags for compiling DLT: Add IPMB DLT: Add LAPD DLT: Add AX25 (AX.25 w/KISS header) DLT: Add JUNIPER_ST 802.15.4 support Variable length 802.11 header support X2E data type support SITA ACN Interface support - see README.sita Support for memory-mapped capture on Linux Support for zerocopy BPF on platforms that support it Support for setting buffer size when opening devices Support for setting monitor mode when opening 802.11 devices Better support for dealing with VLAN tagging/stripping on Linux Fix dynamic library support on OSX Return PCAP_ERROR_IFACE_NOT_UP if the interface isn't 'UP', so applications can print better diagnostic information Return PCAP_ERROR_PERM_DENIED if we don't have permission to open a device, so applications can tell the user they need to go play with permissions On Linux, ignore ENETDOWN so we can continue to capture packets if the interface goes down and comes back up again. On Linux, support new tpacket frame headers (2.6.27+) On Mac OS X, add scripts for changing permissions on /dev/bpf* and launchd plist On Solaris, support 'passive mode' on systems that support it Fixes to autoconf and general build environment Man page reorganization + cleanup Autogenerate VERSION numbers better Mon. September 10, 2007. ken@xelerance.com. Summary for 0.9.8 libpcap release Change build process to put public libpcap headers into pcap subir DLT: Add value for IPMI IPMB packets DLT: Add value for u10 Networks boards Require for pf definitions - allows reading of pflog formatted libpcap files on an OS other than where the file was generated Wed. April 25, 2007. ken@xelerance.com. Summary for 0.9.6 libpcap release Put the public libpcap headers into a pcap subdirectory in both the source directory and the target include directory, and have include files at the top-level directory to include those headers, for backwards compatibility. Add Bluetooth support Add USB capturing support on Linux Add support for the binary USB sniffing interface in Linux Add support for new FreeBSD BIOCSDIRECTION ioctl Add additional filter operations for 802.11 frame types Add support for filtering on MTP2 frame types Propagate some changes from the main branch, so the x.9 branch has all the DLT_ and LINKTYPE_ values that the main branch does Reserved a DLT_ and SAVEFILE_ value for PPI (Per Packet Info) encapsulated packets Add LINKTYPE_ for IEEE 802.15.4, with address fields padded as done by Linux drivers Add LINKTYPE_ value corresponding to DLT_IEEE802_16_MAC_CPS. Add DLT for IEEE 802.16 (WiMAX) MAC Common Part Sublayer Add DLT for Bluetooth HCI UART transport layer When building a shared library, build with "-fPIC" on Linux to support x86_64 Link with "$(CC) -shared" rather than "ld -shared" when building a ".so" shared library Add support for autoconf 2.60 Fixes to discard unread packets when changing filters Changes to handle name changes in the DAG library resulting from switching to libtool. Add support for new DAG ERF types. Add an explicit "-ldag" when building the shared library, so the DAG library dependency is explicit. Mac OSX fixes for dealing with "wlt" devices Fixes in add_or_find_if() & pcap_findalldevs() to optimize generating device lists Fixed a bug in pcap_open_live(). The return value of PacketSetHwFilter was not checked. Tue. September 19, 2006. ken@xelerance.com. Summary for 0.9.5 libpcap release Support for LAPD frames with vISDN Support for ERF on channelized T1/E1 cards via DAG API Fix capitalization that caused issues crossc compiling on Linux Better failure detection on PacketGetAdapterNames() Fixes for MPLS packet generation (link layer) OP_PACKET now matches the beginning of the packet, instead of beginning+link-layer Add DLT/LINKTYPE for carrying FRF.16 Multi-link Frame Relay Fix allocation of buffer for list of link-layer types Added a new DLT and LINKTYPE value for ARINC 653 Interpartition Communcation Messages Fixed a typo in a DLT value: it should start with DLT_ and not LINKTYPE_ Redefined DLT_CAN20B and LINKTYPE_CAN20B as #190 (as this is the right value for CAN). Added definition for DLT_A429 and LINKTYPE_A429 as #184. Added a new DLT and LINKTYPE value for CAN v2.0B frames. Add support for DLT_JUNIPER_VP. Don't double-count received packets on Linux systems that support the PACKET_STATISTICS getsockopt() argument on PF_PACKET sockets. Add support for DLT_IEEE802_11 and DLT_IEEE802_11_RADIO link layers in Windows Add support to build libpcap.lib and wpcap.dll under Cygnus and MingW32. Mon. September 5, 2005. ken@xelerance.com. Summary for 0.9.4 libpcap release Support for radiotap on Linux (Mike Kershaw) Fixes for HP-UX Support for additional Juniper link-layer types Fixes for filters on MPLS-encapsulated packets "vlan" filter fixed "pppoed" and "pppoes" filters added; the latter modifies later parts of the filter expression to look at the PPP headers and headers in the PPP payload Tue. July 5, 2005. ken@xelerance.com. Summary for 0.9.3 libpcap release Fixes for compiling on nearly every platform, including improved 64bit support MSDOS Support Add support for sending packets OpenBSD pf format support IrDA capture (Linux only) Tue. March 30, 2004. mcr@sandelman.ottawa.on.ca. Summary for 3.8.3 release Fixed minor problem in gencode.c that would appear on 64-bit platforms. Version number is now sane. Mon. March 29, 2004. mcr@sandelman.ottawa.on.ca. Summary for 3.8.2 release updates for autoconf 2.5 fixes for ppp interfaces for freebsd 4.1 pcap gencode can generate code for 802.11, IEEE1394, and pflog. Wed. November 12, 2003. mcr@sandelman.ottawa.on.ca. Summary for 0.8 release added pcap_findalldevs() Win32 patches from NetGroup, Politecnico di Torino (Italy) OpenBSD pf, DLT_PFLOG added Many changes to ATM support. lookup pcap_lookupnet() Added DLT_ARCNET_LINUX, DLT_ENC, DLT_IEEE802_11_RADIO, DLT_SUNATM, DLT_IP_OVER_FC, DLT_FRELAY, others. Sigh. More AIX wonderfulness. Document updates. Changes to API: pcap_next_ex(), pcap_breakloop(), pcap_dump_flush(), pcap_list_datalinks(), pcap_set_datalink(), pcap_lib_version(), pcap_datalink_val_to_name(), pcap_datalink_name_to_val(), new error returns. Tuesday, February 25, 2003. fenner@research.att.com. 0.7.2 release Support link types that use 802.2 always, never, and sometimes. Don't decrease the size of the BPF buffer from the default. Support frame relay. Handle 32-bit timestamps in DLPI, and pass the right buffer size. Handle Linux systems with modern kernel but without SOL_PACKET in the userland headers. Linux support for ARPHRD_RAWHDLC. Handle 32-bit timestamps in snoop. Support eg (Octane/O2xxx/O3xxx Gigabit) devices. Add new reserved DLT types. 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 New Linux libpcap implementation, which, in 2.2 and later kernels, uses PF_PACKET sockets and supports kernel packet filtering (if compiled into the kernel), and supports the "any" device for capturing on all interfaces. Cleans up promiscuous mode better on pre-2.2 kernels, and has various other fixes (handles 2.4 ARPHRD_IEEE802_TR, handles ISDN devices better, doesn't show duplicate packets on loopback interface, etc.). Fixed HP-UX libpcap implementation to correctly get the PPA for an interface, to allow interfaces to be opened by interface name. libpcap savefiles have system-independent link-layer type values in the header, rather than sometimes platform-dependent DLT_ values, to make it easier to exchange capture files between different OSes. Non-standard capture files produced by some Linux tcpdumps, e.g. the one from Red Hat Linux 6.2 and later, can now be read. Updated autoconf stock files. Filter expressions can filter on VLAN IDs and various OSI protocols, and work on Token Ring (with non-source-routed packets). "pcap_open_dead()" added to allow compiling filter expressions to pcap code without opening a capture device or capture file. Header files fixed to allow use in C++ programs. Removed dependancy on native headers for packet layout. Removed Linux specific headers that were shipped. Security fixes: Strcpy replaced with strlcpy, sprintf replaced with snprintf. Fixed bug that could cause subsequent "pcap_compile()"s to fail erroneously after one compile failed. Assorted other bug fixes. README.aix and README.linux files added to describe platform-specific issues. "getifaddrs()" rather than SIOCGIFCONF used, if available. v0.5 Sat Jun 10 11:09:15 PDT 2000 itojun@iijlab.net - Brought in KAME IPv6/IPsec bpf compiler. - Fixes for NetBSD. - Support added for OpenBSD DLT_LOOP and BSD/OS DLT_C_HDLC (Cisco HDLC), and changes to work around different BSDs having different DLT_ types with the same numeric value. Assar Westerlund - Building outside the source code tree fixed. - Changed to write out time stamps with 32-bit seconds and microseconds fields, regardless of whether those fields are 32 bits or 64 bits in the OS's native "struct timeval". - Changed "pcap_lookupdev()" to dynamically grow the buffer into which the list of interfaces is read as necessary in order to hold the entire list. Greg Troxel - Added a new "pcap_compile_nopcap()", which lets you compile a filter expression into a BPF program without having an open live capture or capture file. v0.4 Sat Jul 25 12:40:09 PDT 1998 - Fix endian problem with DLT_NULL devices. From FreeBSD via Bill Fenner (fenner@parc.xerox.com) - Fix alignment problem with FDDI under DLPI. This was causing core dumps under Solaris. - Added configure options to disable flex and bison. Resulted from a bug report by barnett@grymoire.crd.ge.com (Bruce Barnett). Also added options to disable gcc and to force a particular packet capture type. - Added support for Fore ATM interfaces (qaa and fa) under IRIX. Thanks to John Hawkinson (jhawk@mit.edu) - Change Linux PPP and SLIP to use DLT_RAW since the kernel does not supply any "link layer" data. - Change Linux to use SIOCGIFHWADDR ioctl to determine link layer type. Thanks to Thomas Sailer (sailer@ife.ee.ethz.ch) - Change IRIX PPP to use DLT_RAW since the kernel does not supply any "link layer" data. - Modified to support the new BSD/OS 2.1 PPP and SLIP link layer header formats. - Added some new SGI snoop interface types. Thanks to Steve Alexander (sca@refugee.engr.sgi.com) - Fixes for HP-UX 10.20 (which is similar to HP-UX 9). Thanks to Richard Allen (ra@hp.is) and Steinar Haug (sthaug@nethelp.no) - Fddi supports broadcast as reported by Jeff Macdonald (jeff@iacnet.com). Also correct ieee802 and arcnet. - Determine Linux pcap buffer size at run time or else it might not be big enough for some interface types (e.g. FDDI). Thanks to Jes Sorensen (Jes.Sorensen@cern.ch) - Fix some linux alignment problems. - Document promisc argument to pcap_open_live(). Reported by Ian Marsh (ianm@sics.se) - Support Metricom radio packets under Linux. Thanks to Kevin Lai (laik@gunpowder.stanford.edu) - Bind to interface name under Linux to avoid packets from multiple interfaces on multi-homed hosts. Thanks to Kevin Lai (laik@gunpowder.stanford.edu) - Change L_SET to SEEK_SET for HP-UX. Thanks to Roland Roberts (rroberts@muller.com) - Fixed an uninitialized memory reference found by Kent Vander Velden (graphix@iastate.edu) - Fixed lex pattern for IDs to allow leading digits. As reported by Theo de Raadt (deraadt@cvs.openbsd.org) - Fixed Linux include file problems when using GNU libc. - Ifdef ARPHRD_FDDI since not all versions of the Linux kernel have it. Reported reported by Eric Jacksch (jacksch@tenebris.ca) - Fixed bug in pcap_dispatch() that kept it from returning on packet timeouts. - Changed ISLOOPBACK() macro when IFF_LOOPBACK isn't available to check for "lo" followed by an eos or digit (newer versions of Linux apparently call the loopback "lo" instead of "lo0"). - Fixed Linux networking include files to use ints instead of longs to avoid problems with 64 bit longs on the alpha. Thanks to Cristian Gafton (gafton@redhat.com) v0.3 Sat Nov 30 20:56:27 PST 1996 - Added Linux support. - Fixed savefile bugs. - Solaris x86 fix from Tim Rylance (t.rylance@elsevier.nl) - Add support for bpf kernel port filters. - Remove duplicate atalk protocol table entry. Thanks to Christian Hopps (chopps@water.emich.edu) - Fixed pcap_lookupdev() to ignore nonexistent devices. This was reported to happen under BSD/OS by David Vincenzetti (vince@cryptonet.it) - Avoid solaris compiler warnings. Thanks to Bruce Barnett (barnett@grymoire.crd.ge.com) v0.2.1 Sun Jul 14 03:02:26 PDT 1996 - Fixes for HP-UX 10. Thanks in part to to Thomas Wolfram (wolf@prz.tu-berlin.de) and Rick Jones (raj@hpisrdq.cup.hp.com) - Added support for SINIX. Thanks to Andrej Borsenkow (borsenkow.msk@sni.de) - Fixes for AIX (although this system is not yet supported). Thanks to John Hawkinson (jhawk@mit.edu) - Use autoconf's idea of the top level directory in install targets. Thanks to John Hawkinson. - Add missing autoconf packet capture result message. Thanks to Bill Fenner (fenner@parc.xerox.com) - Fixed padding problems in the pf module. - Fixed some more alignment problems on the alpha. - Added explicit netmask support. Thanks to Steve Nuchia (steve@research.oknet.com) - Fixed to handle raw ip addresses such as 0.0.0.1 without "left justifing" - Add "sca" keyword (for DEC cluster services) as suggested by Terry Kennedy (terry@spcvxa.spc.edu) - Add "atalk" keyword as suggested by John Hawkinson. - Add "igrp" keyword. - Fixed HID definition in grammar.y to be a string, not a value. - Use $CC when checking gcc version. Thanks to Carl Lindberg (carl_lindberg@blacksmith.com) - Removed obsolete reference to pcap_immediate() from the man page. Michael Stolarchuk (mts@terminator.rs.itd.umich.edu) - DLT_NULL has a 4 byte family header. Thanks to Jeffrey Honig (jch@bsdi.com) v0.2 Sun Jun 23 02:28:42 PDT 1996 - Add support for HP-UX. Resulted from code contributed by Tom Murray (tmurray@hpindck.cup.hp.com) and Philippe-Andri Prindeville (philipp@res.enst.fr) - Update INSTALL with a reminder to install include files. Thanks to Mark Andrews (mandrews@aw.sgi.com) - Fix bpf compiler alignment bug on the alpha. - Use autoconf to detect architectures that can't handle misaligned accesses. - Added loopback support for snoop. Resulted from report Steve Alexander (sca@engr.sgi.com) v0.1 Fri Apr 28 18:11:03 PDT 1995 - Fixed compiler and optimizer bugs. The BPF filter engine uses unsigned comparison operators, while the code generator and optimizer assumed signed semantics in several places. Thanks to Charlie Slater (cslater@imatek.com) for pointing this out. - Removed FDDI ifdef's, they aren't really needed. Resulted from report by Gary Veum (veum@boa.gsfc.nasa.gov). - Add pcap-null.c which allows offline use of libpcap on systems that don't support live package capture. This feature resulting from a request from Jan van Oorschot (j.p.m.voorschot@et.tudelft.nl). - Make bpf_compile() reentrant. Fix thanks to Pascal Hennequin (Pascal.Hennequin@hugo.int-evry.fr). - Port to GNU autoconf. - Fix pcap-dlpi.c to work with isdn. Resulted from report by Flemming Johansen (fsj@csd.cri.dk). - Handle multi-digit interface unit numbers (aka ppa's) under dlpi. Resulted from report by Daniel Ehrlich (ehrlich@cse.psu.edu). - Fix pcap-dlpi.c to work in non-promiscuous mode. Resulted from report by Jeff Murphy (jcmurphy@acsu.buffalo.edu). - Add support for "long jumps". Thanks to Jeffrey Mogul (mogul@pa.dec.com). - Fix minor problems when compiling with BDEBUG as noticed by Scott Bertilson (scott@unet.umn.edu). - Declare sys_errlist "const char *const" to avoid problems under FreeBSD. Resulted from report by jher@eden.com. v0.0.6 Fri Apr 28 04:07:13 PDT 1995 - Add missing variable declaration missing from 0.0.6 v0.0.5 Fri Apr 28 00:22:21 PDT 1995 - Workaround for problems when pcap_read() returns 0 due to the timeout expiring. v0.0.4 Thu Apr 20 20:41:48 PDT 1995 - Change configuration to not use gcc v2 flags with gcc v1. - Fixed a bug in pcap_next(); if pcap_dispatch() returns 0, pcap_next() should also return 0. Thanks to Richard Stevens (rstevens@noao.edu). - Fixed configure to test for snoop before dlpi to avoid problems under IRIX 5. Thanks to J. Eric Townsend (jet@abulafia.genmagic.com). - Hack around deficiency in Ultrix's make. - Fix two bugs related to the Solaris pre-5.3.2 bufmod bug; handle savefiles that have more than snapshot bytes of data in them (so we can read old savefiles) and avoid writing such files. - Added checkioctl which is used with gcc to check that the "fixincludes" script has been run. v0.0.3 Tue Oct 18 18:13:46 PDT 1994 - Fixed configure to test for snoop before dlpi to avoid problems under IRIX 5. Thanks to J. Eric Townsend (jet@abulafia.genmagic.com). v0.0.2 Wed Oct 12 20:56:37 PDT 1994 - Implement timeout in the dlpi pcap_open_live(). Thanks to Richard Stevens. - Determine pcap link type from dlpi media type. Resulted from report by Mahesh Jethanandani (mahesh@npix.com). v0.0.1 Fri Jun 24 14:50:57 PDT 1994 - Fixed bug in nit_setflags() in pcap-snit.c. The streams ioctl timeout wasn't being initialized sometimes resulting in an "NIOCSFLAGS: Invalid argument" error under OSF/1. Reported by Matt Day (mday@artisoft.com) and Danny Mitzel (dmitzel@whitney.hitc.com). - Turn on FDDI support by default. v0.0 Mon Jun 20 19:20:16 PDT 1994 - Initial release. - Fixed bug with greater/less keywords, reported by Mark Andrews (mandrews@alias.com). - Fix bug where '|' was defined as BPF_AND instead of BPF_OR, reported by Elan Amir (elan@leeb.cs.berkeley.edu). - Machines with little-endian byte ordering are supported thanks to Jeff Mogul. - Add hack for version 2.3 savefiles which don't have caplen and len swapped thanks to Vern Paxson. - Added "&&" and "||" aliases for "and" and "or" thanks to Vern Paxson. - Added length, inbound and outbound keywords. Index: stable/9/contrib/libpcap/CREDITS =================================================================== --- stable/9/contrib/libpcap/CREDITS (revision 252280) +++ stable/9/contrib/libpcap/CREDITS (revision 252281) @@ -1,155 +1,157 @@ This file lists people who have contributed to libpcap: The current maintainers: Bill Fenner Fulvio Risso Guy Harris Hannes Gredler Michael Richardson Additional people who have contributed patches: Alan Bawden Albert Chin Alexander 'Leo' Bergolth Alexey Kuznetsov Alon Bar-Lev Andrew Brown Antti Kantee Arien Vijn Arkadiusz Miskiewicz Armando L. Caro Jr. Assar Westerlund Brian Ginsbach + Bill Parker Charles M. Hannum Chris G. Demetriou Chris Lightfoot Chris Maynard Chris Pepper Christian Bell Christian Peron Daniele Orlandi Darren Reed David Kaelbling David Young Dean Gaudet dhruv Don Ebright Dug Song Dustin Spicuzza Eric Anderson Erik de Castro Lopo Felix Obenhuber Florent Drouin Franz Schaefer frederich Fulko Hew Fumiyuki Shimizu Garrett Cooper Gianluca Varenni Gilbert Hoyek Gisle Vanem Graeme Hewson Greg Stark Greg Troxel Gregor Maier Guillaume Pelat Hagen Paul Pfeifer Henri Doreau Hyung Sik Yoon Igor Khristophorov + Jakub Zawadzki Jan-Philip Velders Jason R. Thorpe Javier Achirica Jean Tourrilhes Jean-Louis Charton Jefferson Ogata Jesper Dangaard Brouer Jesper Peterson Joerg Mayer John Bankier Jon Lindgren Jon Smirl Juergen Schoenwaelder Julien Moutinho Jung-uk Kim Kazushi Sugyo Klaus Klein Koryn Grant Kris Katterjohn Krzysztof Halasa Lorenzo Cavallaro Loris Degioanni Love Hörnquist-Åstrand Luis MartinGarcia Maciej W. Rozycki Marcus Felipe Pereira Mark C. Brown Mark Pizzolato Markus Mayer Martin Husemann Márton Németh Matthew Luckie Max Laier Mike Frysinger Mike Kershaw Mike Wiacek Miroslav Lichvar Monroe Williams N. Leiten Nicolas Dade Octavian Cerna Olaf Kirch Ollie Wild Onno van der Linden Paolo Abeni Patrick Marie Patrick McHardy Paul Mundt Pavel Kankovsky Pawel Pokrywka Peter Fales Peter Jeremy Peter Volkov Phil Wood Rafal Maszkowski Richard Stearn Rick Jones Robert Edmonds Roberto Mariani Romain Francoise Sagun Shakya Scott Barron Scott Gifford Scott Mcmillan Sebastian Krahmer Sebastien Roy Sepherosa Ziehau Shaun Clowes Solomon Peachy Stefan Hudson Stephen Donnelly Takashi Yamamoto Tanaka Shin-ya Tobias Poschwatta Tony Li Torsten Landschoff Uns Lider Uwe Girlich Wesley Shields Xianjie Zhang Xin Li Yen Yen Lim Yvan Vanhullebus Yoann Vandoorselaere The original LBL crew: Steve McCanne Craig Leres Van Jacobson Past maintainers: - Jun-ichiro itojun Hagino + Jun-ichiro itojun Hagino Also see: http://www.wide.ad.jp/itojun-award/ Index: stable/9/contrib/libpcap/README =================================================================== --- stable/9/contrib/libpcap/README (revision 252280) +++ stable/9/contrib/libpcap/README (revision 252281) @@ -1,105 +1,111 @@ @(#) $Header: /tcpdump/master/libpcap/README,v 1.34 2008-12-14 19:44:14 guy Exp $ (LBL) LIBPCAP 1.x.y www.tcpdump.org Please send inquiries/comments/reports to: tcpdump-workers@lists.tcpdump.org Anonymous Git is available via: git clone git://bpf.tcpdump.org/libpcap Version 1.x.y of LIBPCAP can be retrieved with the CVS tag "libpcap_1_{x}rel{y}": cvs -d :pserver:tcpdump@cvs.tcpdump.org:/tcpdump/master checkout -r libpcap_1_{x}rel{y} libpcap -Please submit patches against the master copy to the libpcap project on -sourceforge.net. +Please submit patches by forking the branch on GitHub at + http://github.com/mcr/libpcap/tree/master + +and issuing a pull request. + formerly from Lawrence Berkeley National Laboratory Network Research Group ftp://ftp.ee.lbl.gov/libpcap.tar.Z (0.4) This directory contains source code for libpcap, a system-independent interface for user-level packet capture. libpcap provides a portable framework for low-level network monitoring. Applications include network statistics collection, security monitoring, network debugging, etc. Since almost every system vendor provides a different interface for packet capture, and since we've developed several tools that require this functionality, we've created this system-independent API to ease in porting and to alleviate the need for several system-dependent packet capture modules in each application. For some platforms there are README.{system} files that discuss issues with the OS's interface for packet capture on those platforms, such as how to enable support for that interface in the OS, if it's not built in by default. The libpcap interface supports a filtering mechanism based on the architecture in the BSD packet filter. BPF is described in the 1993 Winter Usenix paper ``The BSD Packet Filter: A New Architecture for User-level Packet Capture''. A compressed PostScript version can be found at ftp://ftp.ee.lbl.gov/papers/bpf-usenix93.ps.Z or http://www.tcpdump.org/papers/bpf-usenix93.ps.Z and a gzipped version can be found at http://www.tcpdump.org/papers/bpf-usenix93.ps.gz A PDF version can be found at http://www.tcpdump.org/papers/bpf-usenix93.pdf Although most packet capture interfaces support in-kernel filtering, libpcap utilizes in-kernel filtering only for the BPF interface. On systems that don't have BPF, all packets are read into user-space and the BPF filters are evaluated in the libpcap library, incurring added overhead (especially, for selective filters). Ideally, libpcap would translate BPF filters into a filter program that is compatible with the underlying kernel subsystem, but this is not yet implemented. BPF is standard in 4.4BSD, BSD/OS, NetBSD, FreeBSD, OpenBSD, DragonFly BSD, and Mac OS X; an older, modified and undocumented version is standard in AIX. {DEC OSF/1, Digital UNIX, Tru64 UNIX} uses the packetfilter interface but has been extended to accept BPF filters (which libpcap utilizes). Also, you can add BPF filter support to Ultrix using the kernel source and/or object patches available in: http://www.tcpdump.org/other/bpfext42.tar.Z Linux, in the 2.2 kernel and later kernels, has a "Socket Filter" mechanism that accepts BPF filters; see the README.linux file for information on configuring that option. Note to Linux distributions and *BSD systems that include libpcap: There's now a rule to make a shared library, which should work on Linux and *BSD, among other platforms. It sets the soname of the library to "libpcap.so.1"; this is what it should be, *NOT* libpcap.so.1.x or libpcap.so.1.x.y or something such as that. We've been maintaining binary compatibility between libpcap releases for quite a while; there's no reason to tie a binary linked with libpcap to a particular release of libpcap. Problems, bugs, questions, desirable enhancements, etc. should be sent to the address "tcpdump-workers@lists.tcpdump.org". Bugs, support -requests, and feature requests may also be submitted on the SourceForge -site for libpcap at +requests, and feature requests may also be submitted on the GitHub issue +tracker for libpcap at - http://sourceforge.net/projects/libpcap/ + https://github.com/mcr/libpcap/issues Source code contributions, etc. should be sent to the email address -submitted as patches on the SourceForge site for libpcap. +above or submitted by forking the branch on GitHub at -Current versions can be found at www.tcpdump.org, or the SourceForge -site for libpcap. + http://github.com/mcr/libpcap/tree/master + +and issuing a pull request. + +Current versions can be found at www.tcpdump.org. - The TCPdump team Index: stable/9/contrib/libpcap/VERSION =================================================================== --- stable/9/contrib/libpcap/VERSION (revision 252280) +++ stable/9/contrib/libpcap/VERSION (revision 252281) @@ -1 +1 @@ -1.3.0 +1.4.0 Index: stable/9/contrib/libpcap/bpf_image.c =================================================================== --- stable/9/contrib/libpcap/bpf_image.c (revision 252280) +++ stable/9/contrib/libpcap/bpf_image.c (revision 252281) @@ -1,302 +1,305 @@ /* * Copyright (c) 1990, 1991, 1992, 1994, 1995, 1996 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/bpf_image.c,v 1.28 2008-01-02 04:16:46 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef WIN32 #include #else /* WIN32 */ #if HAVE_INTTYPES_H #include #elif HAVE_STDINT_H #include #endif #ifdef HAVE_SYS_BITYPES_H #include #endif #include #endif /* WIN32 */ #include #include #include "pcap-int.h" #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif char * bpf_image(p, n) struct bpf_insn *p; int n; { int v; const char *fmt, *op; static char image[256]; char operand[64]; v = p->k; switch (p->code) { default: op = "unimp"; fmt = "0x%x"; v = p->code; break; case BPF_RET|BPF_K: op = "ret"; fmt = "#%d"; break; case BPF_RET|BPF_A: op = "ret"; fmt = ""; break; case BPF_LD|BPF_W|BPF_ABS: op = "ld"; fmt = "[%d]"; break; case BPF_LD|BPF_H|BPF_ABS: op = "ldh"; fmt = "[%d]"; break; case BPF_LD|BPF_B|BPF_ABS: op = "ldb"; fmt = "[%d]"; break; case BPF_LD|BPF_W|BPF_LEN: op = "ld"; fmt = "#pktlen"; break; case BPF_LD|BPF_W|BPF_IND: op = "ld"; fmt = "[x + %d]"; break; case BPF_LD|BPF_H|BPF_IND: op = "ldh"; fmt = "[x + %d]"; break; case BPF_LD|BPF_B|BPF_IND: op = "ldb"; fmt = "[x + %d]"; break; case BPF_LD|BPF_IMM: op = "ld"; fmt = "#0x%x"; break; case BPF_LDX|BPF_IMM: op = "ldx"; fmt = "#0x%x"; break; case BPF_LDX|BPF_MSH|BPF_B: op = "ldxb"; fmt = "4*([%d]&0xf)"; break; case BPF_LD|BPF_MEM: op = "ld"; fmt = "M[%d]"; break; case BPF_LDX|BPF_MEM: op = "ldx"; fmt = "M[%d]"; break; case BPF_ST: op = "st"; fmt = "M[%d]"; break; case BPF_STX: op = "stx"; fmt = "M[%d]"; break; case BPF_JMP|BPF_JA: op = "ja"; fmt = "%d"; v = n + 1 + p->k; break; case BPF_JMP|BPF_JGT|BPF_K: op = "jgt"; fmt = "#0x%x"; break; case BPF_JMP|BPF_JGE|BPF_K: op = "jge"; fmt = "#0x%x"; break; case BPF_JMP|BPF_JEQ|BPF_K: op = "jeq"; fmt = "#0x%x"; break; case BPF_JMP|BPF_JSET|BPF_K: op = "jset"; fmt = "#0x%x"; break; case BPF_JMP|BPF_JGT|BPF_X: op = "jgt"; fmt = "x"; break; case BPF_JMP|BPF_JGE|BPF_X: op = "jge"; fmt = "x"; break; case BPF_JMP|BPF_JEQ|BPF_X: op = "jeq"; fmt = "x"; break; case BPF_JMP|BPF_JSET|BPF_X: op = "jset"; fmt = "x"; break; case BPF_ALU|BPF_ADD|BPF_X: op = "add"; fmt = "x"; break; case BPF_ALU|BPF_SUB|BPF_X: op = "sub"; fmt = "x"; break; case BPF_ALU|BPF_MUL|BPF_X: op = "mul"; fmt = "x"; break; case BPF_ALU|BPF_DIV|BPF_X: op = "div"; fmt = "x"; break; case BPF_ALU|BPF_AND|BPF_X: op = "and"; fmt = "x"; break; case BPF_ALU|BPF_OR|BPF_X: op = "or"; fmt = "x"; break; case BPF_ALU|BPF_LSH|BPF_X: op = "lsh"; fmt = "x"; break; case BPF_ALU|BPF_RSH|BPF_X: op = "rsh"; fmt = "x"; break; case BPF_ALU|BPF_ADD|BPF_K: op = "add"; fmt = "#%d"; break; case BPF_ALU|BPF_SUB|BPF_K: op = "sub"; fmt = "#%d"; break; case BPF_ALU|BPF_MUL|BPF_K: op = "mul"; fmt = "#%d"; break; case BPF_ALU|BPF_DIV|BPF_K: op = "div"; fmt = "#%d"; break; case BPF_ALU|BPF_AND|BPF_K: op = "and"; fmt = "#0x%x"; break; case BPF_ALU|BPF_OR|BPF_K: op = "or"; fmt = "#0x%x"; break; case BPF_ALU|BPF_LSH|BPF_K: op = "lsh"; fmt = "#%d"; break; case BPF_ALU|BPF_RSH|BPF_K: op = "rsh"; fmt = "#%d"; break; case BPF_ALU|BPF_NEG: op = "neg"; fmt = ""; break; case BPF_MISC|BPF_TAX: op = "tax"; fmt = ""; break; case BPF_MISC|BPF_TXA: op = "txa"; fmt = ""; break; } (void)snprintf(operand, sizeof operand, fmt, v); - (void)snprintf(image, sizeof image, - (BPF_CLASS(p->code) == BPF_JMP && - BPF_OP(p->code) != BPF_JA) ? - "(%03d) %-8s %-16s jt %d\tjf %d" - : "(%03d) %-8s %s", - n, op, operand, n + 1 + p->jt, n + 1 + p->jf); + if (BPF_CLASS(p->code) == BPF_JMP && BPF_OP(p->code) != BPF_JA) { + (void)snprintf(image, sizeof image, + "(%03d) %-8s %-16s jt %d\tjf %d", + n, op, operand, n + 1 + p->jt, n + 1 + p->jf); + } else { + (void)snprintf(image, sizeof image, + "(%03d) %-8s %s", + n, op, operand); + } return image; } Index: stable/9/contrib/libpcap/config.h.in =================================================================== --- stable/9/contrib/libpcap/config.h.in (revision 252280) +++ stable/9/contrib/libpcap/config.h.in (revision 252281) @@ -1,314 +1,326 @@ /* config.h.in. Generated from configure.in by autoheader. */ /* Enable optimizer debugging */ #undef BDEBUG /* define if you have a cloning BPF device */ #undef HAVE_CLONING_BPF /* define if you have the DAG API */ #undef HAVE_DAG_API /* define if you have dag_get_erf_types() */ #undef HAVE_DAG_GET_ERF_TYPES /* define if you have dag_get_stream_erf_types() */ #undef HAVE_DAG_GET_STREAM_ERF_TYPES /* define if you have streams capable DAG API */ #undef HAVE_DAG_STREAMS_API /* define if you have vdag_set_device_info() */ #undef HAVE_DAG_VDAG /* Define to 1 if you have the declaration of `ether_hostton', and to 0 if you don't. */ #undef HAVE_DECL_ETHER_HOSTTON /* define if you have a /dev/dlpi */ #undef HAVE_DEV_DLPI /* if passive_req_t primitive exists */ #undef HAVE_DLPI_PASSIVE /* Define to 1 if you have the `ether_hostton' function. */ #undef HAVE_ETHER_HOSTTON /* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ #undef HAVE_FSEEKO /* on HP-UX 10.20 or later */ #undef HAVE_HPUX10_20_OR_LATER /* on HP-UX 9.x */ #undef HAVE_HPUX9 /* if ppa_info_t_dl_module_id exists */ #undef HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1 /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* if libdlpi exists */ #undef HAVE_LIBDLPI /* if libnl exists */ #undef HAVE_LIBNL /* if libnl exists and is version 2.x */ #undef HAVE_LIBNL_2_x +/* if libnl exists and is version 3.x */ +#undef HAVE_LIBNL_3_x + +/* libnl has NLE_FAILURE */ +#undef HAVE_LIBNL_NLE + +/* libnl has new-style socket api */ +#undef HAVE_LIBNL_SOCKETS + /* Define to 1 if you have the header file. */ #undef HAVE_LIMITS_H /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_COMPILER_H /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_ETHTOOL_H /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_IF_PACKET_H /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_NET_TSTAMP_H /* if tp_vlan_tci exists */ #undef HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_USBDEVICE_FS_H /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_WIRELESS_H /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_ETHER_H /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_IF_ETHER_H /* Define to 1 if you have the header file. */ #undef HAVE_NETPACKET_IF_PACKET_H /* Define to 1 if you have the header file. */ #undef HAVE_NETPACKET_PACKET_H /* Define to 1 if you have the header file. */ #undef HAVE_NET_IF_MEDIA_H /* Define to 1 if you have the header file. */ #undef HAVE_NET_PFVAR_H /* if there's an os_proto.h for this platform, to use additional prototypes */ #undef HAVE_OS_PROTO_H /* Define to 1 if you have the header file. */ #undef HAVE_PATHS_H /* define if net/pfvar.h defines PF_NAT through PF_NORDR */ #undef HAVE_PF_NAT_THROUGH_PF_NORDR /* define if you have a Septel API */ #undef HAVE_SEPTEL_API /* define if you have Myricom SNF API */ #undef HAVE_SNF_API /* Define to 1 if you have the `snprintf' function. */ #undef HAVE_SNPRINTF /* if struct sockaddr has the sa_len member */ #undef HAVE_SOCKADDR_SA_LEN /* if struct sockaddr_storage exists */ #undef HAVE_SOCKADDR_STORAGE /* define if socklen_t is defined */ #undef HAVE_SOCKLEN_T /* On solaris */ #undef HAVE_SOLARIS /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strerror' function. */ #undef HAVE_STRERROR /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `strlcpy' function. */ #undef HAVE_STRLCPY /* Define to 1 if the system has the type `struct BPF_TIMEVAL'. */ #undef HAVE_STRUCT_BPF_TIMEVAL /* Define to 1 if the system has the type `struct ether_addr'. */ #undef HAVE_STRUCT_ETHER_ADDR /* Define to 1 if you have the header file. */ #undef HAVE_SYS_BITYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_BUFMOD_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_DLPI_EXT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_IOCCOM_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SOCKIO_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* if if_packet.h has tpacket_stats defined */ #undef HAVE_TPACKET_STATS /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* if struct usbdevfs_ctrltransfer has bRequestType */ #undef HAVE_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE /* define if version.h is generated in the build procedure */ #undef HAVE_VERSION_H /* Define to 1 if you have the `vsnprintf' function. */ #undef HAVE_VSNPRINTF /* define if the system supports zerocopy BPF */ #undef HAVE_ZEROCOPY_BPF /* define if your compiler has __attribute__ */ #undef HAVE___ATTRIBUTE__ /* IPv6 */ #undef INET6 /* if unaligned access fails */ #undef LBL_ALIGN /* path for device for USB sniffing */ #undef LINUX_USB_MON_DEV +/* if we need a pcap_parse wrapper around yyparse */ +#undef NEED_YYPARSE_WRAPPER + /* Define to 1 if netinet/ether.h declares `ether_hostton' */ #undef NETINET_ETHER_H_DECLARES_ETHER_HOSTTON /* Define to 1 if netinet/if_ether.h declares `ether_hostton' */ #undef NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON /* do not use protochain */ #undef NO_PROTOCHAIN /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME -/* Define to the home page for this package. */ -#undef PACKAGE_URL - /* Define to the version of this package. */ #undef PACKAGE_VERSION /* /dev/dlpi directory */ #undef PCAP_DEV_PREFIX /* target host supports Bluetooth sniffing */ #undef PCAP_SUPPORT_BT /* target host supports CAN sniffing */ #undef PCAP_SUPPORT_CAN /* target host supports canusb */ #undef PCAP_SUPPORT_CANUSB /* target host supports netfilter sniffing */ #undef PCAP_SUPPORT_NETFILTER /* target host supports USB sniffing */ #undef PCAP_SUPPORT_USB /* include ACN support */ #undef SITA + +/* if struct sockaddr_hci has hci_channel member */ +#undef SOCKADDR_HCI_HAS_HCI_CHANNEL /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Enable parser debugging */ #undef YYDEBUG /* Number of bits in a file offset, on hosts where this is settable. */ #undef _FILE_OFFSET_BITS /* needed on HP-UX */ #undef _HPUX_SOURCE /* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ #undef _LARGEFILE_SOURCE /* Define for large files, on AIX-style hosts. */ #undef _LARGE_FILES /* define on AIX to get certain functions */ #undef _SUN /* to handle Ultrix compilers that don't support const in prototypes */ #undef const /* Define as token for inline if inlining supported */ #undef inline /* Define to `short' if int16_t not defined. */ #undef int16_t /* Define to `int' if int32_t not defined. */ #undef int32_t /* Define to `long long' if int64_t not defined. */ #undef int64_t /* Define to `signed char' if int8_t not defined. */ #undef int8_t /* on sinix */ #undef sinix /* Define to `unsigned short' if u_int16_t not defined. */ #undef u_int16_t /* Define to `unsigned int' if u_int32_t not defined. */ #undef u_int32_t /* Define to `unsigned long long' if u_int64_t not defined. */ #undef u_int64_t /* Define to `unsigned char' if u_int8_t not defined. */ #undef u_int8_t Index: stable/9/contrib/libpcap/configure =================================================================== --- stable/9/contrib/libpcap/configure (revision 252280) +++ stable/9/contrib/libpcap/configure (revision 252281) @@ -1,9080 +1,13214 @@ #! /bin/sh # From configure.in Revision: 1.168 . # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.67. +# Generated by GNU Autoconf 2.61. # -# # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, -# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software -# Foundation, Inc. -# -# +# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. -## -------------------- ## -## M4sh Initialization. ## -## -------------------- ## +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else - case `(set -o) 2>/dev/null` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; esac + fi -as_nl=' -' -export as_nl -# Printing a long string crashes Solaris 7 /usr/bin/printf. -as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo -# Prefer a ksh shell builtin over an external printf program on Solaris, -# but without wasting forks for bash or zsh. -if test -z "$BASH_VERSION$ZSH_VERSION" \ - && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='print -r --' - as_echo_n='print -rn --' -elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='printf %s\n' - as_echo_n='printf %s' -else - if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then - as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' - as_echo_n='/usr/ucb/echo -n' + + +# PATH needs CR +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' else - as_echo_body='eval expr "X$1" : "X\\(.*\\)"' - as_echo_n_body='eval - arg=$1; - case $arg in #( - *"$as_nl"*) - expr "X$arg" : "X\\(.*\\)$as_nl"; - arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; - esac; - expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" - ' - export as_echo_n_body - as_echo_n='sh -c $as_echo_n_body as_echo' + PATH_SEPARATOR=: fi - export as_echo_body - as_echo='sh -c $as_echo_body as_echo' + rm -f conf$$.sh fi -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - PATH_SEPARATOR=: - (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { - (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || - PATH_SEPARATOR=';' - } +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) +as_nl=' +' IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. -case $0 in #(( +case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break - done + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then - $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - exit 1 + echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + { (exit 1); exit 1; } fi -# Unset variables that we do not need and which cause bugs (e.g. in -# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" -# suppresses any "Segmentation fault" message there. '((' could -# trigger a bug in pdksh 5.2.14. -for as_var in BASH_ENV ENV MAIL MAILPATH -do eval test x\${$as_var+set} = xset \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +# Work around bugs in pre-3.0 UWIN ksh. +for as_var in ENV MAIL MAILPATH +do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + fi +done +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + # CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH +$as_unset CDPATH + if test "x$CONFIG_SHELL" = x; then - as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which - # is contrary to our usage. Disable this feature. - alias -g '\${1+\"\$@\"}'='\"\$@\"' - setopt NO_GLOB_SUBST + if (eval ":") 2>/dev/null; then + as_have_required=yes else - case \`(set -o) 2>/dev/null\` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac + as_have_required=no fi -" - as_required="as_fn_return () { (exit \$1); } -as_fn_success () { as_fn_return 0; } -as_fn_failure () { as_fn_return 1; } -as_fn_ret_success () { return 0; } -as_fn_ret_failure () { return 1; } + if test $as_have_required = yes && (eval ": +(as_func_return () { + (exit \$1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + exitcode=0 -as_fn_success || { exitcode=1; echo as_fn_success failed.; } -as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } -as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } -as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } -if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : else - exitcode=1; echo positional parameters were not saved. + exitcode=1 + echo as_func_ret_success failed. fi -test x\$exitcode = x0 || exit 1" - as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO - as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO - eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && - test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 -test \$(( 1 + 1 )) = 2 || exit 1" - if (eval "$as_required") 2>/dev/null; then : - as_have_required=yes + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = \"\$1\" ); then + : else - as_have_required=no + exitcode=1 + echo positional parameters were not saved. fi - if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : +test \$exitcode = 0) || { (exit 1); exit 1; } + +( + as_lineno_1=\$LINENO + as_lineno_2=\$LINENO + test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" && + test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; } +") 2> /dev/null; then + : else - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -as_found=false + as_candidate_shells= + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - as_found=: - case $as_dir in #( + case $as_dir in /*) for as_base in sh bash ksh sh5; do - # Try only shells that exist, to save several forks. - as_shell=$as_dir/$as_base - if { test -f "$as_shell" || test -f "$as_shell.exe"; } && - { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : - CONFIG_SHELL=$as_shell as_have_required=yes - if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : - break 2 -fi -fi + as_candidate_shells="$as_candidate_shells $as_dir/$as_base" done;; esac - as_found=false done -$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && - { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : - CONFIG_SHELL=$SHELL as_have_required=yes -fi; } IFS=$as_save_IFS - if test "x$CONFIG_SHELL" != x; then : - # We cannot yet assume a decent shell, so we have to provide a - # neutralization value for shells without unset; and this also - # works around shells that cannot unset nonexistent variables. - BASH_ENV=/dev/null - ENV=/dev/null - (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV - export CONFIG_SHELL - exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} + for as_shell in $as_candidate_shells $SHELL; do + # Try only shells that exist, to save several forks. + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { ("$as_shell") 2> /dev/null <<\_ASEOF +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; +esac + fi - if test x$as_have_required = xno; then : - $as_echo "$0: This script requires a shell more modern than all" - $as_echo "$0: the shells that I found on your system." - if test x${ZSH_VERSION+set} = xset ; then - $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" - $as_echo "$0: be upgraded to zsh 4.3.4 or later." - else - $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, -$0: including any error possibly output before this -$0: message. Then install a modern shell, or manually run -$0: the script under such a shell if you do have one." - fi - exit 1 + +: +_ASEOF +}; then + CONFIG_SHELL=$as_shell + as_have_required=yes + if { "$as_shell" 2> /dev/null <<\_ASEOF +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; +esac + fi + + +: +(as_func_return () { + (exit $1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. fi -SHELL=${CONFIG_SHELL-/bin/sh} -export SHELL -# Unset more variables known to interfere with behavior of common tools. -CLICOLOR_FORCE= GREP_OPTIONS= -unset CLICOLOR_FORCE GREP_OPTIONS -## --------------------- ## -## M4sh Shell Functions. ## -## --------------------- ## -# as_fn_unset VAR -# --------------- -# Portably unset VAR. -as_fn_unset () -{ - { eval $1=; unset $1;} -} -as_unset=as_fn_unset +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi -# as_fn_set_status STATUS -# ----------------------- -# Set $? to STATUS, without forking. -as_fn_set_status () -{ - return $1 -} # as_fn_set_status +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi -# as_fn_exit STATUS -# ----------------- -# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. -as_fn_exit () -{ - set +e - as_fn_set_status $1 - exit $1 -} # as_fn_exit +if ( set x; as_func_ret_success y && test x = "$1" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi -# as_fn_mkdir_p -# ------------- -# Create "$as_dir" as a directory, including parents if necessary. -as_fn_mkdir_p () -{ +test $exitcode = 0) || { (exit 1); exit 1; } - case $as_dir in #( - -*) as_dir=./$as_dir;; - esac - test -d "$as_dir" || eval $as_mkdir_p || { - as_dirs= - while :; do - case $as_dir in #( - *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( - *) as_qdir=$as_dir;; - esac - as_dirs="'$as_qdir' $as_dirs" - as_dir=`$as_dirname -- "$as_dir" || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - test -d "$as_dir" && break - done - test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" +( + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; } +_ASEOF +}; then + break +fi -} # as_fn_mkdir_p -# as_fn_append VAR VALUE -# ---------------------- -# Append the text in VALUE to the end of the definition contained in VAR. Take -# advantage of any shell optimizations that allow amortized linear growth over -# repeated appends, instead of the typical quadratic growth present in naive -# implementations. -if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : - eval 'as_fn_append () - { - eval $1+=\$2 - }' -else - as_fn_append () - { - eval $1=\$$1\$2 - } -fi # as_fn_append +fi -# as_fn_arith ARG... -# ------------------ -# Perform arithmetic evaluation on the ARGs, and store the result in the -# global $as_val. Take advantage of shells that can avoid forks. The arguments -# must be portable across $(()) and expr. -if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : - eval 'as_fn_arith () - { - as_val=$(( $* )) - }' -else - as_fn_arith () - { - as_val=`expr "$@" || test $? -eq 1` - } -fi # as_fn_arith + done + if test "x$CONFIG_SHELL" != x; then + for as_var in BASH_ENV ENV + do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + done + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} +fi -# as_fn_error STATUS ERROR [LINENO LOG_FD] -# ---------------------------------------- -# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are -# provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with STATUS, using 1 if that was 0. -as_fn_error () -{ - as_status=$1; test $as_status -eq 0 && as_status=1 - if test "$4"; then - as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 - fi - $as_echo "$as_me: error: $2" >&2 - as_fn_exit $as_status -} # as_fn_error -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr + if test $as_have_required = no; then + echo This script requires a shell more modern than all the + echo shells that I found on your system. Please install a + echo modern shell, or manually run the script under such a + echo shell if you do have one. + { (exit 1); exit 1; } +fi + + +fi + +fi + + + +(eval "as_func_return () { + (exit \$1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : else - as_expr=false + exitcode=1 + echo as_func_success failed. fi -if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then - as_basename=basename +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : else - as_basename=false + exitcode=1 + echo as_func_ret_success failed. fi -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = \"\$1\" ); then + : else - as_dirname=false + exitcode=1 + echo positional parameters were not saved. fi -as_me=`$as_basename -- "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` +test \$exitcode = 0") || { + echo No shell found that supports shell functions. + echo Please tell autoconf@gnu.org about your system, + echo including any error possibly output before this + echo message +} -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - as_lineno_1=$LINENO as_lineno_1a=$LINENO - as_lineno_2=$LINENO as_lineno_2a=$LINENO - eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && - test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { - # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line after each line using $LINENO; the second 'sed' + # does the real work. The second script uses 'N' to pair each + # line-number line with the line containing $LINENO, and appends + # trailing '-' during substitution so that $LINENO is not a special + # case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # scripts with optimization help from Paolo Bonzini. Blame Lee + # E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || - { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in #((((( +case `echo -n x` in -n*) - case `echo 'xy\c'` in + case `echo 'x\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. - xy) ECHO_C='\c';; - *) echo `echo ksh88 bug on AIX 6.1` > /dev/null - ECHO_T=' ';; + *) ECHO_C='\c';; esac;; *) ECHO_N='-n';; esac +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir - mkdir conf$$.dir 2>/dev/null + mkdir conf$$.dir fi -if (echo >conf$$.file) 2>/dev/null; then - if ln -s conf$$.file conf$$ 2>/dev/null; then - as_ln_s='ln -s' - # ... but there are two gotchas: - # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. - # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -p'. - ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -p' - elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln - else +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' - fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then - as_mkdir_p='mkdir -p "$as_dir"' + as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then - test -d "$1/."; + test -d "$1/."; else - case $1 in #( - -*)set "./$1";; + case $1 in + -*)set "./$1";; esac; - case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" -test -n "$DJDIR" || exec 7<&0 &1 +exec 7<&0 &1 + # Name of the host. -# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME= PACKAGE_TARNAME= PACKAGE_VERSION= PACKAGE_STRING= PACKAGE_BUGREPORT= -PACKAGE_URL= ac_unique_file="pcap.c" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" -ac_subst_vars='LTLIBOBJS -INSTALL_DATA -INSTALL_SCRIPT -INSTALL_PROGRAM -CAN_SRC -PCAP_SUPPORT_CAN -CANUSB_SRC -PCAP_SUPPORT_CANUSB -BT_SRC -PCAP_SUPPORT_BT -NETFILTER_SRC -PCAP_SUPPORT_NETFILTER -USB_SRC -PCAP_SUPPORT_USB -MAN_MISC_INFO -MAN_FILE_FORMATS -DYEXT -SSRC -ADDLARCHIVEOBJS -ADDLOBJS -V_RPATH_OPT -V_SONAME_OPT -V_SHLIB_OPT -V_SHLIB_CMD -V_PCAP -V_INCLS -V_FINDALLDEVS -V_DEFS -V_CCOPT -AR -RANLIB -V_YACC -V_LEX -HAVE_LINUX_TPACKET_AUXDATA -LIBOBJS -EGREP -GREP -CPP -OBJEXT -EXEEXT -ac_ct_CC -CPPFLAGS -LDFLAGS -CFLAGS -CC -SHLICC2 -target_os -target_vendor -target_cpu -target -host_os -host_vendor -host_cpu -host -build_os -build_vendor -build_cpu -build -target_alias -host_alias -build_alias -LIBS -ECHO_T -ECHO_N -ECHO_C -DEFS -mandir -localedir -libdir -psdir -pdfdir -dvidir -htmldir -infodir -docdir -oldincludedir -includedir -localstatedir -sharedstatedir -sysconfdir -datadir -datarootdir -libexecdir -sbindir -bindir -program_transform_name -prefix -exec_prefix -PACKAGE_URL -PACKAGE_BUGREPORT -PACKAGE_STRING -PACKAGE_VERSION -PACKAGE_TARNAME -PACKAGE_NAME +ac_subst_vars='SHELL PATH_SEPARATOR -SHELL' +PACKAGE_NAME +PACKAGE_TARNAME +PACKAGE_VERSION +PACKAGE_STRING +PACKAGE_BUGREPORT +exec_prefix +prefix +program_transform_name +bindir +sbindir +libexecdir +datarootdir +datadir +sysconfdir +sharedstatedir +localstatedir +includedir +oldincludedir +docdir +infodir +htmldir +dvidir +pdfdir +psdir +libdir +localedir +mandir +DEFS +ECHO_C +ECHO_N +ECHO_T +LIBS +build_alias +host_alias +target_alias +build +build_cpu +build_vendor +build_os +host +host_cpu +host_vendor +host_os +target +target_cpu +target_vendor +target_os +SHLICC2 +CC +CFLAGS +LDFLAGS +CPPFLAGS +ac_ct_CC +EXEEXT +OBJEXT +CPP +GREP +EGREP +LIBOBJS +HAVE_LINUX_TPACKET_AUXDATA +V_LEX +V_YACC +RANLIB +AR +V_CCOPT +V_DEFS +V_FINDALLDEVS +V_INCLS +V_PCAP +V_SHLIB_CMD +V_SHLIB_OPT +V_SONAME_OPT +V_RPATH_OPT +ADDLOBJS +ADDLARCHIVEOBJS +SSRC +DYEXT +MAN_FILE_FORMATS +MAN_MISC_INFO +PCAP_SUPPORT_USB +USB_SRC +PCAP_SUPPORT_NETFILTER +NETFILTER_SRC +PCAP_SUPPORT_BT +BT_SRC +PCAP_SUPPORT_CANUSB +CANUSB_SRC +PCAP_SUPPORT_CAN +CAN_SRC +INSTALL_PROGRAM +INSTALL_SCRIPT +INSTALL_DATA +LTLIBOBJS' ac_subst_files='' -ac_user_opts=' -enable_option_checking -with_gcc -enable_largefile -enable_protochain -with_sita -with_pcap -with_libnl -enable_ipv6 -enable_optimizer_dbg -enable_yydebug -with_dag -with_dag_includes -with_dag_libraries -with_septel -with_snf -with_snf_includes -with_snf_libraries -with_flex -with_bison -enable_universal -enable_bluetooth -enable_canusb -enable_can -' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false -ac_unrecognized_opts= -ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in - *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; - *=) ac_optarg= ;; - *) ac_optarg=yes ;; + *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) - ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid feature name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"enable_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval enable_$ac_useropt=no ;; + expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` + eval enable_$ac_feature=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) - ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid feature name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"enable_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval enable_$ac_useropt=\$ac_optarg ;; + expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` + eval enable_$ac_feature=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) - ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid package name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"with_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval with_$ac_useropt=\$ac_optarg ;; + expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/[-.]/_/g'` + eval with_$ac_package=\$ac_optarg ;; -without-* | --without-*) - ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid package name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"with_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval with_$ac_useropt=no ;; + expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/[-.]/_/g'` + eval with_$ac_package=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; - -*) as_fn_error $? "unrecognized option: \`$ac_option' -Try \`$0 --help' for more information" + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. - case $ac_envvar in #( - '' | [0-9]* | *[!_$as_cr_alnum]* ) - as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; - esac + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. - $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && - $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` - as_fn_error $? "missing argument to $ac_option" + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } fi -if test -n "$ac_unrecognized_opts"; then - case $enable_option_checking in - no) ;; - fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; - *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; - esac -fi - -# Check all directory arguments for consistency. +# Be sure to have absolute directory names. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var - # Remove trailing slashes. case $ac_val in - */ ) - ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` - eval $ac_var=\$ac_val;; - esac - # Be sure to have absolute directory names. - case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac - as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" + { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; } done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe - $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host. - If a cross compiler is detected then cross compile mode will be used" >&2 + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || - as_fn_error $? "working directory cannot be determined" + { echo "$as_me: error: Working directory cannot be determined" >&2 + { (exit 1); exit 1; }; } test "X$ac_ls_di" = "X$ac_pwd_ls_di" || - as_fn_error $? "pwd does not report name of working directory" + { echo "$as_me: error: pwd does not report name of working directory" >&2 + { (exit 1); exit 1; }; } # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. - ac_confdir=`$as_dirname -- "$as_myself" || -$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_myself" : 'X\(//\)[^/]' \| \ - X"$as_myself" : 'X\(//\)$' \| \ - X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_myself" | + ac_confdir=`$as_dirname -- "$0" || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X"$0" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." - as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( - cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2 + { (exit 1); exit 1; }; } pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures this package to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit - -q, --quiet, --silent do not print \`checking ...' messages + -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX - [$ac_default_prefix] + [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX - [PREFIX] + [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: - --bindir=DIR user executables [EPREFIX/bin] - --sbindir=DIR system admin executables [EPREFIX/sbin] - --libexecdir=DIR program executables [EPREFIX/libexec] - --sysconfdir=DIR read-only single-machine data [PREFIX/etc] - --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] - --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --libdir=DIR object code libraries [EPREFIX/lib] - --includedir=DIR C header files [PREFIX/include] - --oldincludedir=DIR C header files for non-gcc [/usr/include] - --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] - --datadir=DIR read-only architecture-independent data [DATAROOTDIR] - --infodir=DIR info documentation [DATAROOTDIR/info] - --localedir=DIR locale-dependent data [DATAROOTDIR/locale] - --mandir=DIR man documentation [DATAROOTDIR/man] - --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] - --htmldir=DIR html documentation [DOCDIR] - --dvidir=DIR dvi documentation [DOCDIR] - --pdfdir=DIR pdf documentation [DOCDIR] - --psdir=DIR ps documentation [DOCDIR] + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] --target=TARGET configure for building compilers for TARGET [HOST] _ACEOF fi if test -n "$ac_init_help"; then cat <<\_ACEOF Optional Features: - --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --disable-largefile omit support for large files --disable-protochain disable \"protochain\" insn --enable-ipv6 build IPv6-capable version [default=yes, if getaddrinfo available] --enable-optimizer-dbg build optimizer debugging code --enable-yydebug build parser debugging code --disable-universal don't build universal on OS X + --enable-shared build shared libraries [default=yes, if support + available] --enable-bluetooth enable Bluetooth support [default=yes, if support available] --enable-canusb enable canusb support [default=yes, if support available] - --enable-can enable CAN support [default=yes, if support available] Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --without-gcc don't use gcc --with-sita include SITA support --with-pcap=TYPE use packet capture TYPE --without-libnl disable libnl support [default=yes, on Linux, if present] --with-dag[=DIR] include Endace DAG support ["yes", "no" or DIR; default="yes" on BSD and Linux if present] --with-dag-includes=DIR Endace DAG include directory --with-dag-libraries=DIR Endace DAG library directory --with-septel[=DIR] include Septel support (located in directory DIR, if supplied). [default=yes, on Linux, if present] --with-snf[=DIR] include Myricom SNF support ["yes", "no" or DIR; default="yes" on BSD and Linux if present] --with-snf-includes=DIR Myricom SNF include directory --with-snf-libraries=DIR Myricom SNF library directory --without-flex don't use flex --without-bison don't use bison Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l - CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. -Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue - test -d "$ac_dir" || - { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || - continue + test -d "$ac_dir" || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) - ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else - $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF configure -generated by GNU Autoconf 2.67 +generated by GNU Autoconf 2.61 -Copyright (C) 2010 Free Software Foundation, Inc. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi - -## ------------------------ ## -## Autoconf initialization. ## -## ------------------------ ## - -# ac_fn_c_try_compile LINENO -# -------------------------- -# Try to compile conftest.$ac_ext, and return whether this succeeded. -ac_fn_c_try_compile () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext - if { { ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compile") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} - as_fn_set_status $ac_retval - -} # ac_fn_c_try_compile - -# ac_fn_c_try_cpp LINENO -# ---------------------- -# Try to preprocess conftest.$ac_ext, and return whether this succeeded. -ac_fn_c_try_cpp () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if { { ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } > conftest.i && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} - as_fn_set_status $ac_retval - -} # ac_fn_c_try_cpp - -# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES -# ------------------------------------------------------- -# Tests whether HEADER exists, giving a warning if it cannot be compiled using -# the include files in INCLUDES and setting the cache variable VAR -# accordingly. -ac_fn_c_check_header_mongrel () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if eval "test \"\${$3+set}\"" = set; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval "test \"\${$3+set}\"" = set; then : - $as_echo_n "(cached) " >&6 -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -else - # Is the header compilable? -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 -$as_echo_n "checking $2 usability... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -#include <$2> -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_header_compiler=yes -else - ac_header_compiler=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 -$as_echo "$ac_header_compiler" >&6; } - -# Is the header present? -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 -$as_echo_n "checking $2 presence... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <$2> -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - ac_header_preproc=yes -else - ac_header_preproc=no -fi -rm -f conftest.err conftest.i conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 -$as_echo "$ac_header_preproc" >&6; } - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( - yes:no: ) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 -$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 -$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} - ;; - no:yes:* ) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 -$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 -$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 -$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 -$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 -$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} - ;; -esac - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval "test \"\${$3+set}\"" = set; then : - $as_echo_n "(cached) " >&6 -else - eval "$3=\$ac_header_compiler" -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -fi - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} - -} # ac_fn_c_check_header_mongrel - -# ac_fn_c_try_run LINENO -# ---------------------- -# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes -# that executables *can* be run. -ac_fn_c_try_run () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' - { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; }; then : - ac_retval=0 -else - $as_echo "$as_me: program exited with status $ac_status" >&5 - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=$ac_status -fi - rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} - as_fn_set_status $ac_retval - -} # ac_fn_c_try_run - -# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES -# ------------------------------------------------------- -# Tests whether HEADER exists and can be compiled using the include files in -# INCLUDES, setting the cache variable VAR accordingly. -ac_fn_c_check_header_compile () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval "test \"\${$3+set}\"" = set; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -#include <$2> -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - eval "$3=yes" -else - eval "$3=no" -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} - -} # ac_fn_c_check_header_compile - -# ac_fn_c_check_type LINENO TYPE VAR INCLUDES -# ------------------------------------------- -# Tests whether TYPE exists after having included INCLUDES, setting cache -# variable VAR accordingly. -ac_fn_c_check_type () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval "test \"\${$3+set}\"" = set; then : - $as_echo_n "(cached) " >&6 -else - eval "$3=no" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -int -main () -{ -if (sizeof ($2)) - return 0; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -int -main () -{ -if (sizeof (($2))) - return 0; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - -else - eval "$3=yes" -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} - -} # ac_fn_c_check_type - -# ac_fn_c_try_link LINENO -# ----------------------- -# Try to link conftest.$ac_ext, and return whether this succeeded. -ac_fn_c_try_link () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext conftest$ac_exeext - if { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - $as_test_x conftest$ac_exeext - }; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information - # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would - # interfere with the next link command; also delete a directory that is - # left behind by Apple's compiler. We do this before executing the actions. - rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} - as_fn_set_status $ac_retval - -} # ac_fn_c_try_link - -# ac_fn_c_check_func LINENO FUNC VAR -# ---------------------------------- -# Tests whether FUNC exists, setting the cache variable VAR accordingly -ac_fn_c_check_func () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval "test \"\${$3+set}\"" = set; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -/* Define $2 to an innocuous variant, in case declares $2. - For example, HP-UX 11i declares gettimeofday. */ -#define $2 innocuous_$2 - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $2 (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef $2 - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char $2 (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined __stub_$2 || defined __stub___$2 -choke me -#endif - -int -main () -{ -return $2 (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - eval "$3=yes" -else - eval "$3=no" -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} - -} # ac_fn_c_check_func - -# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES -# --------------------------------------------- -# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR -# accordingly. -ac_fn_c_check_decl () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - as_decl_name=`echo $2|sed 's/ *(.*//'` - as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 -$as_echo_n "checking whether $as_decl_name is declared... " >&6; } -if eval "test \"\${$3+set}\"" = set; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -int -main () -{ -#ifndef $as_decl_name -#ifdef __cplusplus - (void) $as_decl_use; -#else - (void) $as_decl_name; -#endif -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - eval "$3=yes" -else - eval "$3=no" -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} - -} # ac_fn_c_check_decl cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was -generated by GNU Autoconf 2.67. Invocation command line was +generated by GNU Autoconf 2.61. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - $as_echo "PATH: $as_dir" - done + echo "PATH: $as_dir" +done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) - ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in - 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; 2) - as_fn_append ac_configure_args1 " '$ac_arg'" + ac_configure_args1="$ac_configure_args1 '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi - as_fn_append ac_configure_args " '$ac_arg'" + ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac done done -{ ac_configure_args0=; unset ac_configure_args0;} -{ ac_configure_args1=; unset ac_configure_args1;} +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo - $as_echo "## ---------------- ## + cat <<\_ASBOX +## ---------------- ## ## Cache variables. ## -## ---------------- ##" +## ---------------- ## +_ASBOX echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( - *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 -$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 +echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( - BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( - *) { eval $ac_var=; unset $ac_var;} ;; + *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo - $as_echo "## ----------------- ## + cat <<\_ASBOX +## ----------------- ## ## Output variables. ## -## ----------------- ##" +## ----------------- ## +_ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in - *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac - $as_echo "$ac_var='\''$ac_val'\''" + echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then - $as_echo "## ------------------- ## + cat <<\_ASBOX +## ------------------- ## ## File substitutions. ## -## ------------------- ##" +## ------------------- ## +_ASBOX echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in - *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac - $as_echo "$ac_var='\''$ac_val'\''" + echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then - $as_echo "## ----------- ## + cat <<\_ASBOX +## ----------- ## ## confdefs.h. ## -## ----------- ##" +## ----------- ## +_ASBOX echo cat confdefs.h echo fi test "$ac_signal" != 0 && - $as_echo "$as_me: caught signal $ac_signal" - $as_echo "$as_me: exit $exit_status" + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do - trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h -$as_echo "/* confdefs.h */" > confdefs.h - # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF + cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF + cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF + cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF + cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF -cat >>confdefs.h <<_ACEOF -#define PACKAGE_URL "$PACKAGE_URL" -_ACEOF - # Let the site file select an alternate cache file if it wants to. -# Prefer an explicitly selected file to automatically selected ones. -ac_site_file1=NONE -ac_site_file2=NONE +# Prefer explicitly selected file to automatically selected ones. if test -n "$CONFIG_SITE"; then - # We do not want a PATH search for config.site. - case $CONFIG_SITE in #(( - -*) ac_site_file1=./$CONFIG_SITE;; - */*) ac_site_file1=$CONFIG_SITE;; - *) ac_site_file1=./$CONFIG_SITE;; - esac + set x "$CONFIG_SITE" elif test "x$prefix" != xNONE; then - ac_site_file1=$prefix/share/config.site - ac_site_file2=$prefix/etc/config.site + set x "$prefix/share/config.site" "$prefix/etc/config.site" else - ac_site_file1=$ac_default_prefix/share/config.site - ac_site_file2=$ac_default_prefix/etc/config.site + set x "$ac_default_prefix/share/config.site" \ + "$ac_default_prefix/etc/config.site" fi -for ac_site_file in "$ac_site_file1" "$ac_site_file2" +shift +for ac_site_file do - test "x$ac_site_file" = xNONE && continue - if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 -$as_echo "$as_me: loading site script $ac_site_file" >&6;} + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 - . "$ac_site_file" \ - || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "failed to load site script $ac_site_file -See \`config.log' for more details" "$LINENO" 5 ; } + . "$ac_site_file" fi done if test -r "$cache_file"; then - # Some versions of bash will fail to source /dev/null (special files - # actually), so we avoid doing that. DJGPP emulates it as a regular file. - if test /dev/null != "$cache_file" && test -f "$cache_file"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 -$as_echo "$as_me: loading cache $cache_file" >&6;} + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else - { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 -$as_echo "$as_me: creating cache $cache_file" >&6;} + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 -$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 -$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then - # differences in whitespace do not lead to failure. - ac_old_val_w=`echo x $ac_old_val` - ac_new_val_w=`echo x $ac_new_val` - if test "$ac_old_val_w" != "$ac_new_val_w"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 -$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} - ac_cache_corrupted=: - else - { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 -$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} - eval $ac_var=\$ac_old_val - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 -$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 -$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in - *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. - *) as_fn_append ac_configure_args " '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then - { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 -$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} - as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } fi -## -------------------- ## -## Main body of script. ## -## -------------------- ## + + + + + + + + + + + + + + + + ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then - as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5 +echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;} + { (exit 1); exit 1; }; } fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || - as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5 +echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;} + { (exit 1); exit 1; }; } -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 -$as_echo_n "checking build system type... " >&6; } -if test "${ac_cv_build+set}" = set; then : - $as_echo_n "(cached) " >&6 +{ echo "$as_me:$LINENO: checking build system type" >&5 +echo $ECHO_N "checking build system type... $ECHO_C" >&6; } +if test "${ac_cv_build+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && - as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 + { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 +echo "$as_me: error: cannot guess build type; you must specify one" >&2;} + { (exit 1); exit 1; }; } ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || - as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5 +echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;} + { (exit 1); exit 1; }; } fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 -$as_echo "$ac_cv_build" >&6; } +{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5 +echo "${ECHO_T}$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; -*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5 ;; +*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5 +echo "$as_me: error: invalid value of canonical build" >&2;} + { (exit 1); exit 1; }; };; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 -$as_echo_n "checking host system type... " >&6; } -if test "${ac_cv_host+set}" = set; then : - $as_echo_n "(cached) " >&6 +{ echo "$as_me:$LINENO: checking host system type" >&5 +echo $ECHO_N "checking host system type... $ECHO_C" >&6; } +if test "${ac_cv_host+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || - as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 + { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5 +echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;} + { (exit 1); exit 1; }; } fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 -$as_echo "$ac_cv_host" >&6; } +{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5 +echo "${ECHO_T}$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; -*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5 ;; +*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5 +echo "$as_me: error: invalid value of canonical host" >&2;} + { (exit 1); exit 1; }; };; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 -$as_echo_n "checking target system type... " >&6; } -if test "${ac_cv_target+set}" = set; then : - $as_echo_n "(cached) " >&6 +{ echo "$as_me:$LINENO: checking target system type" >&5 +echo $ECHO_N "checking target system type... $ECHO_C" >&6; } +if test "${ac_cv_target+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "x$target_alias" = x; then ac_cv_target=$ac_cv_host else ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || - as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5 + { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&5 +echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&2;} + { (exit 1); exit 1; }; } fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5 -$as_echo "$ac_cv_target" >&6; } +{ echo "$as_me:$LINENO: result: $ac_cv_target" >&5 +echo "${ECHO_T}$ac_cv_target" >&6; } case $ac_cv_target in *-*-*) ;; -*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5 ;; +*) { { echo "$as_me:$LINENO: error: invalid value of canonical target" >&5 +echo "$as_me: error: invalid value of canonical target" >&2;} + { (exit 1); exit 1; }; };; esac target=$ac_cv_target ac_save_IFS=$IFS; IFS='-' set x $ac_cv_target shift target_cpu=$1 target_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: target_os=$* IFS=$ac_save_IFS case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac # The aliases save the names the user supplied, while $host etc. # will get canonicalized. test -n "$target_alias" && test "$program_prefix$program_suffix$program_transform_name" = \ NONENONEs,x,x, && program_prefix=${target_alias}- - # Check whether --with-gcc was given. -if test "${with_gcc+set}" = set; then : +if test "${with_gcc+set}" = set; then withval=$with_gcc; fi V_CCOPT="-O" V_INCLS="" if test "${srcdir}" != "." ; then V_INCLS="-I\$(srcdir)" fi if test "${CFLAGS+set}" = set; then LBL_CFLAGS="$CFLAGS" fi if test -z "$CC" ; then case "$host_os" in bsdi*) # Extract the first word of "shlicc2", so it can be a program name with args. set dummy shlicc2; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_SHLICC2+set}" = set; then : - $as_echo_n "(cached) " >&6 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_SHLICC2+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$SHLICC2"; then ac_cv_prog_SHLICC2="$SHLICC2" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do + for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_SHLICC2="yes" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done - done +done IFS=$as_save_IFS test -z "$ac_cv_prog_SHLICC2" && ac_cv_prog_SHLICC2="no" fi fi SHLICC2=$ac_cv_prog_SHLICC2 if test -n "$SHLICC2"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SHLICC2" >&5 -$as_echo "$SHLICC2" >&6; } + { echo "$as_me:$LINENO: result: $SHLICC2" >&5 +echo "${ECHO_T}$SHLICC2" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } fi if test $SHLICC2 = yes ; then CC=shlicc2 export CC fi ;; esac fi if test -z "$CC" -a "$with_gcc" = no ; then CC=cc export CC fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : - $as_echo_n "(cached) " >&6 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do + for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done - done +done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : - $as_echo_n "(cached) " >&6 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do + for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done - done +done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } + { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : - $as_echo_n "(cached) " >&6 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do + for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done - done +done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : - $as_echo_n "(cached) " >&6 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do + for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done - done +done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : - $as_echo_n "(cached) " >&6 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do + for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done - done +done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : - $as_echo_n "(cached) " >&6 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do + for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done - done +done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } + { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi -test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "no acceptable C compiler found in \$PATH -See \`config.log' for more details" "$LINENO" 5 ; } +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } # Provide some information about the compiler. -$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 -set X $ac_compile -ac_compiler=$2 -for ac_option in --version -v -V -qversion; do - { { ac_try="$ac_compiler $ac_option >&5" +echo "$as_me:$LINENO: checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (ac_try="$ac_compiler --version >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compiler $ac_option >&5") 2>conftest.err +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler --version >&5") 2>&5 ac_status=$? - if test -s conftest.err; then - sed '10a\ -... rest of stderr output deleted ... - 10q' conftest.err >conftest.er1 - cat conftest.er1 >&5 - fi - rm -f conftest.er1 conftest.err - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } -done + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +ac_clean_files="$ac_clean_files a.out a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 -$as_echo_n "checking whether the C compiler works... " >&6; } -ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` - -# The possible output files: -ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" - +{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 +echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; } +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +# +# List of possible output files, starting from the most likely. +# The algorithm is not robust to junk in `.', hence go to wildcards (a.*) +# only as a last resort. b.out is created by i960 compilers. +ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out' +# +# The IRIX 6 linker writes into existing files which may not be +# executable, retaining their permissions. Remove them first so a +# subsequent execution test works. ac_rmfiles= for ac_file in $ac_files do case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles -if { { ac_try="$ac_link_default" +if { (ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link_default") 2>&5 ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then : + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) - if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi -if test -z "$ac_file"; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -$as_echo "$as_me: failed program was:" >&5 + +{ echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6; } +if test -z "$ac_file"; then + echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 -{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error 77 "C compiler cannot create executables -See \`config.log' for more details" "$LINENO" 5 ; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 -$as_echo_n "checking for C compiler default output file name... " >&6; } -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 -$as_echo "$ac_file" >&6; } + ac_exeext=$ac_cv_exeext -rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; } +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +{ echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + +rm -f a.out a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 -$as_echo_n "checking for suffix of executables... " >&6; } -if { { ac_try="$ac_link" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; } +{ echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6; } + +{ echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; } +if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then : + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details" "$LINENO" 5 ; } + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } fi -rm -f conftest conftest$ac_cv_exeext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 -$as_echo "$ac_cv_exeext" >&6; } +rm -f conftest$ac_cv_exeext +{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6; } + rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -int -main () -{ -FILE *f = fopen ("conftest.out", "w"); - return ferror (f) || fclose (f) != 0; - - ; - return 0; -} -_ACEOF -ac_clean_files="$ac_clean_files conftest.out" -# Check that the compiler produces executables we can run. If not, either -# the compiler is broken, or we cross compile. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 -$as_echo_n "checking whether we are cross compiling... " >&6; } -if test "$cross_compiling" != yes; then - { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - if { ac_try='./conftest$ac_cv_exeext' - { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; }; then - cross_compiling=no - else - if test "$cross_compiling" = maybe; then - cross_compiling=yes - else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot run C compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details" "$LINENO" 5 ; } - fi - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 -$as_echo "$cross_compiling" >&6; } - -rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out -ac_clean_files=$ac_clean_files_save -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 -$as_echo_n "checking for suffix of object files... " >&6; } -if test "${ac_cv_objext+set}" = set; then : - $as_echo_n "(cached) " >&6 +{ echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; } +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj -if { { ac_try="$ac_compile" +if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>&5 ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then : + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else - $as_echo "$as_me: failed program was:" >&5 + echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 -{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot compute suffix of object files: cannot compile -See \`config.log' for more details" "$LINENO" 5 ; } +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } fi + rm -f conftest.$ac_cv_objext conftest.$ac_ext fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 -$as_echo "$ac_cv_objext" >&6; } +{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 -$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } -if test "${ac_cv_c_compiler_gnu+set}" = set; then : - $as_echo_n "(cached) " >&6 +{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; } +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_compiler_gnu=yes else - ac_compiler_gnu=no + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_compiler_gnu=no fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 -$as_echo "$ac_cv_c_compiler_gnu" >&6; } -if test $ac_compiler_gnu = yes; then - GCC=yes -else - GCC= -fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; } +GCC=`test $ac_compiler_gnu = yes && echo yes` ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 -$as_echo_n "checking whether $CC accepts -g... " >&6; } -if test "${ac_cv_prog_cc_g+set}" = set; then : - $as_echo_n "(cached) " >&6 +{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_prog_cc_g=yes else - CFLAGS="" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + CFLAGS="" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + : else - ac_c_werror_flag=$ac_save_c_werror_flag + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 -$as_echo "$ac_cv_prog_cc_g" >&6; } +{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 -$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } -if test "${ac_cv_prog_cc_c89+set}" = set; then : - $as_echo_n "(cached) " >&6 +{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 +echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_c89+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" - if ac_fn_c_try_compile "$LINENO"; then : + rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_prog_cc_c89=$ac_arg +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + fi + rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 -$as_echo "none needed" >&6; } ;; + { echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6; } ;; xno) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 -$as_echo "unsupported" >&6; } ;; + { echo "$as_me:$LINENO: result: unsupported" >&5 +echo "${ECHO_T}unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 -$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; + { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;; esac -if test "x$ac_cv_prog_cc_c89" != xno; then : -fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test "$GCC" = yes ; then if test "$SHLICC2" = yes ; then ac_cv_lbl_gcc_vers=2 V_CCOPT="-O2" else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking gcc version" >&5 -$as_echo_n "checking gcc version... " >&6; } - if test "${ac_cv_lbl_gcc_vers+set}" = set; then : - $as_echo_n "(cached) " >&6 + { echo "$as_me:$LINENO: checking gcc version" >&5 +echo $ECHO_N "checking gcc version... $ECHO_C" >&6; } + if test "${ac_cv_lbl_gcc_vers+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_lbl_gcc_vers=`$CC -v 2>&1 | \ sed -e '/^gcc version /!d' \ -e 's/^gcc version //' \ -e 's/ .*//' -e 's/^[^0-9]*//' \ -e 's/\..*//'` fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_gcc_vers" >&5 -$as_echo "$ac_cv_lbl_gcc_vers" >&6; } + { echo "$as_me:$LINENO: result: $ac_cv_lbl_gcc_vers" >&5 +echo "${ECHO_T}$ac_cv_lbl_gcc_vers" >&6; } if test $ac_cv_lbl_gcc_vers -gt 1 ; then V_CCOPT="-O2" fi fi else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking that $CC handles ansi prototypes" >&5 -$as_echo_n "checking that $CC handles ansi prototypes... " >&6; } - if test "${ac_cv_lbl_cc_ansi_prototypes+set}" = set; then : - $as_echo_n "(cached) " >&6 + { echo "$as_me:$LINENO: checking that $CC handles ansi prototypes" >&5 +echo $ECHO_N "checking that $CC handles ansi prototypes... $ECHO_C" >&6; } + if test "${ac_cv_lbl_cc_ansi_prototypes+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { int frob(int, char *) ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_lbl_cc_ansi_prototypes=yes else - ac_cv_lbl_cc_ansi_prototypes=no + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lbl_cc_ansi_prototypes=no fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_cc_ansi_prototypes" >&5 -$as_echo "$ac_cv_lbl_cc_ansi_prototypes" >&6; } + { echo "$as_me:$LINENO: result: $ac_cv_lbl_cc_ansi_prototypes" >&5 +echo "${ECHO_T}$ac_cv_lbl_cc_ansi_prototypes" >&6; } if test $ac_cv_lbl_cc_ansi_prototypes = no ; then case "$host_os" in hpux*) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE)" >&5 -$as_echo_n "checking for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE)... " >&6; } + { echo "$as_me:$LINENO: checking for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE)" >&5 +echo $ECHO_N "checking for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE)... $ECHO_C" >&6; } savedcflags="$CFLAGS" CFLAGS="-Aa -D_HPUX_SOURCE $CFLAGS" - if test "${ac_cv_lbl_cc_hpux_cc_aa+set}" = set; then : - $as_echo_n "(cached) " >&6 + if test "${ac_cv_lbl_cc_hpux_cc_aa+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { int frob(int, char *) ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_lbl_cc_hpux_cc_aa=yes else - ac_cv_lbl_cc_hpux_cc_aa=no + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lbl_cc_hpux_cc_aa=no fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_cc_hpux_cc_aa" >&5 -$as_echo "$ac_cv_lbl_cc_hpux_cc_aa" >&6; } + { echo "$as_me:$LINENO: result: $ac_cv_lbl_cc_hpux_cc_aa" >&5 +echo "${ECHO_T}$ac_cv_lbl_cc_hpux_cc_aa" >&6; } if test $ac_cv_lbl_cc_hpux_cc_aa = no ; then - as_fn_error $? "see the INSTALL doc for more info" "$LINENO" 5 + { { echo "$as_me:$LINENO: error: see the INSTALL doc for more info" >&5 +echo "$as_me: error: see the INSTALL doc for more info" >&2;} + { (exit 1); exit 1; }; } fi CFLAGS="$savedcflags" V_CCOPT="-Aa $V_CCOPT" -$as_echo "#define _HPUX_SOURCE 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define _HPUX_SOURCE 1 +_ACEOF ;; osf*) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ansi mode in DEC compiler ($CC -std1)" >&5 -$as_echo_n "checking for ansi mode in DEC compiler ($CC -std1)... " >&6; } + { echo "$as_me:$LINENO: checking for ansi mode in DEC compiler ($CC -std1)" >&5 +echo $ECHO_N "checking for ansi mode in DEC compiler ($CC -std1)... $ECHO_C" >&6; } savedcflags="$CFLAGS" CFLAGS="-std1" - if test "${ac_cv_lbl_cc_osf1_cc_std1+set}" = set; then : - $as_echo_n "(cached) " >&6 + if test "${ac_cv_lbl_cc_osf1_cc_std1+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { int frob(int, char *) ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_lbl_cc_osf1_cc_std1=yes else - ac_cv_lbl_cc_osf1_cc_std1=no + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lbl_cc_osf1_cc_std1=no fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_cc_osf1_cc_std1" >&5 -$as_echo "$ac_cv_lbl_cc_osf1_cc_std1" >&6; } + { echo "$as_me:$LINENO: result: $ac_cv_lbl_cc_osf1_cc_std1" >&5 +echo "${ECHO_T}$ac_cv_lbl_cc_osf1_cc_std1" >&6; } if test $ac_cv_lbl_cc_osf1_cc_std1 = no ; then - as_fn_error $? "see the INSTALL doc for more info" "$LINENO" 5 + { { echo "$as_me:$LINENO: error: see the INSTALL doc for more info" >&5 +echo "$as_me: error: see the INSTALL doc for more info" >&2;} + { (exit 1); exit 1; }; } fi CFLAGS="$savedcflags" V_CCOPT="-std1 $V_CCOPT" ;; *) - as_fn_error $? "see the INSTALL doc for more info" "$LINENO" 5 + { { echo "$as_me:$LINENO: error: see the INSTALL doc for more info" >&5 +echo "$as_me: error: see the INSTALL doc for more info" >&2;} + { (exit 1); exit 1; }; } ;; esac fi V_INCLS="$V_INCLS -I/usr/local/include" LDFLAGS="$LDFLAGS -L/usr/local/lib" case "$host_os" in irix*) V_CCOPT="$V_CCOPT -xansi -signed -g3" ;; osf*) # # Presumed to be DEC OSF/1, Digital UNIX, or # Tru64 UNIX. # V_CCOPT="$V_CCOPT -g3" ;; ultrix*) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking that Ultrix $CC hacks const in prototypes" >&5 -$as_echo_n "checking that Ultrix $CC hacks const in prototypes... " >&6; } - if test "${ac_cv_lbl_cc_const_proto+set}" = set; then : - $as_echo_n "(cached) " >&6 + { echo "$as_me:$LINENO: checking that Ultrix $CC hacks const in prototypes" >&5 +echo $ECHO_N "checking that Ultrix $CC hacks const in prototypes... $ECHO_C" >&6; } + if test "${ac_cv_lbl_cc_const_proto+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { struct a { int b; }; void c(const struct a *) ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_lbl_cc_const_proto=yes else - ac_cv_lbl_cc_const_proto=no + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lbl_cc_const_proto=no fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_cc_const_proto" >&5 -$as_echo "$ac_cv_lbl_cc_const_proto" >&6; } + { echo "$as_me:$LINENO: result: $ac_cv_lbl_cc_const_proto" >&5 +echo "${ECHO_T}$ac_cv_lbl_cc_const_proto" >&6; } if test $ac_cv_lbl_cc_const_proto = no ; then -$as_echo "#define const /**/" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define const +_ACEOF fi ;; esac fi if test "$GCC" = yes ; then # # On platforms where we build a shared library: # # add options to generate position-independent code, # if necessary (it's the default in AIX and Darwin/OS X); # # define option to set the soname of the shared library, # if the OS supports that; # # add options to specify, at link time, a directory to # add to the run-time search path, if that's necessary. # V_SHLIB_CMD="\$(CC)" V_SHLIB_OPT="-shared" case "$host_os" in aix*) ;; freebsd*|netbsd*|openbsd*|dragonfly*|linux*|osf*) # # Platforms where the linker is the GNU linker # or accepts command-line arguments like # those the GNU linker accepts. # # Some instruction sets require -fPIC on some # operating systems. Check for them. If you # have a combination that requires it, add it # here. # PIC_OPT=-fpic case "$host_cpu" in sparc64*) case "$host_os" in - freebsd*) + freebsd*|openbsd*) PIC_OPT=-fPIC ;; esac ;; esac V_CCOPT="$V_CCOPT $PIC_OPT" V_SONAME_OPT="-Wl,-soname," V_RPATH_OPT="-Wl,-rpath," ;; hpux*) V_CCOPT="$V_CCOPT -fpic" # # XXX - this assumes GCC is using the HP linker, # rather than the GNU linker, and that the "+h" # option is used on all HP-UX platforms, both .sl # and .so. # V_SONAME_OPT="-Wl,+h," # # By default, directories specifed with -L # are added to the run-time search path, so # we don't add them in pcap-config. # ;; solaris*) V_CCOPT="$V_CCOPT -fpic" # # XXX - this assumes GCC is using the Sun linker, # rather than the GNU linker. # V_SONAME_OPT="-Wl,-h," V_RPATH_OPT="-Wl,-R," ;; esac else # # Set the appropriate compiler flags and, on platforms # where we build a shared library: # # add options to generate position-independent code, # if necessary (it's the default in Darwin/OS X); # # if we generate ".so" shared libraries, define the # appropriate options for building the shared library; # # add options to specify, at link time, a directory to # add to the run-time search path, if that's necessary. # # Note: spaces after V_SONAME_OPT are significant; on # some platforms the soname is passed with a GCC-like # "-Wl,-soname,{soname}" option, with the soname part # of the option, while on other platforms the C compiler # driver takes it as a regular option with the soname # following the option. The same applies to V_RPATH_OPT. # case "$host_os" in aix*) V_SHLIB_CMD="\$(CC)" V_SHLIB_OPT="-G -bnoentry -bexpall" ;; freebsd*|netbsd*|openbsd*|dragonfly*|linux*) # # "cc" is GCC. # V_CCOPT="$V_CCOPT -fpic" V_SHLIB_CMD="\$(CC)" V_SHLIB_OPT="-shared" V_SONAME_OPT="-Wl,-soname," V_RPATH_OPT="-Wl,-rpath," ;; hpux*) V_CCOPT="$V_CCOPT +z" V_SHLIB_CMD="\$(LD)" V_SHLIB_OPT="-b" V_SONAME_OPT="+h " # # By default, directories specifed with -L # are added to the run-time search path, so # we don't add them in pcap-config. # ;; osf*) # # Presumed to be DEC OSF/1, Digital UNIX, or # Tru64 UNIX. # V_SHLIB_CMD="\$(CC)" V_SHLIB_OPT="-shared" V_SONAME_OPT="-soname " V_RPATH_OPT="-rpath " ;; solaris*) V_CCOPT="$V_CCOPT -Kpic" V_SHLIB_CMD="\$(CC)" V_SHLIB_OPT="-G" V_SONAME_OPT="-h " V_RPATH_OPT="-R" ;; esac fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 -$as_echo_n "checking for inline... " >&6; } +{ echo "$as_me:$LINENO: checking for inline" >&5 +echo $ECHO_N "checking for inline... $ECHO_C" >&6; } save_CFLAGS="$CFLAGS" CFLAGS="$V_CCOPT" - if test "${ac_cv_lbl_inline+set}" = set; then : - $as_echo_n "(cached) " >&6 + if test "${ac_cv_lbl_inline+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_lbl_inline="" ac_lbl_cc_inline=no for ac_lbl_inline in inline __inline__ __inline do - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #define inline $ac_lbl_inline static inline struct iltest *foo(void); struct iltest { int iltest1; int iltest2; }; static inline struct iltest * foo() { static struct iltest xxx; return &xxx; } int main () { ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_lbl_cc_inline=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test "$ac_lbl_cc_inline" = yes ; then break; fi done if test "$ac_lbl_cc_inline" = yes ; then ac_cv_lbl_inline=$ac_lbl_inline fi fi CFLAGS="$save_CFLAGS" if test ! -z "$ac_cv_lbl_inline" ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_inline" >&5 -$as_echo "$ac_cv_lbl_inline" >&6; } + { echo "$as_me:$LINENO: result: $ac_cv_lbl_inline" >&5 +echo "${ECHO_T}$ac_cv_lbl_inline" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } fi cat >>confdefs.h <<_ACEOF #define inline $ac_cv_lbl_inline _ACEOF -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __attribute__" >&5 -$as_echo_n "checking for __attribute__... " >&6; } -if test "${ac_cv___attribute__+set}" = set; then : - $as_echo_n "(cached) " >&6 +{ echo "$as_me:$LINENO: checking for __attribute__" >&5 +echo $ECHO_N "checking for __attribute__... $ECHO_C" >&6; } +if test "${ac_cv___attribute__+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include static void foo(void) __attribute__ ((noreturn)); static void foo(void) { exit(1); } int main(int argc, char **argv) { foo(); } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv___attribute__=yes else - ac_cv___attribute__=no + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv___attribute__=no fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test "$ac_cv___attribute__" = "yes"; then -$as_echo "#define HAVE___ATTRIBUTE__ 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE___ATTRIBUTE__ 1 +_ACEOF V_DEFS="$V_DEFS -D_U_=\"__attribute__((unused))\"" else V_DEFS="$V_DEFS -D_U_=\"\"" fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv___attribute__" >&5 -$as_echo "$ac_cv___attribute__" >&6; } +{ echo "$as_me:$LINENO: result: $ac_cv___attribute__" >&5 +echo "${ECHO_T}$ac_cv___attribute__" >&6; } ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 -$as_echo_n "checking how to run the C preprocessor... " >&6; } +{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then - if test "${ac_cv_prog_CPP+set}" = set; then : - $as_echo_n "(cached) " >&6 + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + : else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + # Broken: fails on valid input. continue fi -rm -f conftest.err conftest.i conftest.$ac_ext +rm -f conftest.err conftest.$ac_ext + # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then # Broken: success on invalid input. continue else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + # Passes both tests. ac_preproc_ok=: break fi -rm -f conftest.err conftest.i conftest.$ac_ext +rm -f conftest.err conftest.$ac_ext + done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 -$as_echo "$CPP" >&6; } +{ echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + : else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + # Broken: fails on valid input. continue fi -rm -f conftest.err conftest.i conftest.$ac_ext +rm -f conftest.err conftest.$ac_ext + # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then # Broken: success on invalid input. continue else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + # Passes both tests. ac_preproc_ok=: break fi -rm -f conftest.err conftest.i conftest.$ac_ext +rm -f conftest.err conftest.$ac_ext + done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details" "$LINENO" 5 ; } + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 -$as_echo_n "checking for grep that handles long lines and -e... " >&6; } -if test "${ac_cv_path_GREP+set}" = set; then : - $as_echo_n "(cached) " >&6 +{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5 +echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; } +if test "${ac_cv_path_GREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - if test -z "$GREP"; then + # Extract the first word of "grep ggrep" to use in msg output +if test -z "$GREP"; then +set dummy grep ggrep; ac_prog_name=$2 +if test "${ac_cv_path_GREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else ac_path_GREP_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +# Loop through the user's path and test for each of PROGNAME-LIST +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_prog in grep ggrep; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue -# Check for GNU ac_path_GREP and select it if it is found. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue + # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 - $as_echo_n 0123456789 >"conftest.in" + echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" - $as_echo 'GREP' >> "conftest.nl" + echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - as_fn_arith $ac_count + 1 && ac_count=$as_val + ac_count=`expr $ac_count + 1` if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac - $ac_path_GREP_found && break 3 - done + + $ac_path_GREP_found && break 3 done - done +done + +done IFS=$as_save_IFS - if test -z "$ac_cv_path_GREP"; then - as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 - fi + + +fi + +GREP="$ac_cv_path_GREP" +if test -z "$GREP"; then + { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 +echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} + { (exit 1); exit 1; }; } +fi + else ac_cv_path_GREP=$GREP fi + fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 -$as_echo "$ac_cv_path_GREP" >&6; } +{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5 +echo "${ECHO_T}$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 -$as_echo_n "checking for egrep... " >&6; } -if test "${ac_cv_path_EGREP+set}" = set; then : - $as_echo_n "(cached) " >&6 +{ echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6; } +if test "${ac_cv_path_EGREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else - if test -z "$EGREP"; then + # Extract the first word of "egrep" to use in msg output +if test -z "$EGREP"; then +set dummy egrep; ac_prog_name=$2 +if test "${ac_cv_path_EGREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else ac_path_EGREP_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +# Loop through the user's path and test for each of PROGNAME-LIST +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_prog in egrep; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue -# Check for GNU ac_path_EGREP and select it if it is found. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue + # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 - $as_echo_n 0123456789 >"conftest.in" + echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" - $as_echo 'EGREP' >> "conftest.nl" + echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - as_fn_arith $ac_count + 1 && ac_count=$as_val + ac_count=`expr $ac_count + 1` if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac - $ac_path_EGREP_found && break 3 - done + + $ac_path_EGREP_found && break 3 done - done +done + +done IFS=$as_save_IFS - if test -z "$ac_cv_path_EGREP"; then - as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 - fi + + +fi + +EGREP="$ac_cv_path_EGREP" +if test -z "$EGREP"; then + { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 +echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} + { (exit 1); exit 1; }; } +fi + else ac_cv_path_EGREP=$EGREP fi + fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 -$as_echo "$ac_cv_path_EGREP" >&6; } +{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5 +echo "${ECHO_T}$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 -$as_echo_n "checking for ANSI C header files... " >&6; } -if test "${ac_cv_header_stdc+set}" = set; then : - $as_echo_n "(cached) " >&6 +{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; } +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_header_stdc=yes else - ac_cv_header_stdc=no + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_stdc=no fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then : - + $EGREP "memchr" >/dev/null 2>&1; then + : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then : - + $EGREP "free" >/dev/null 2>&1; then + : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then : + if test "$cross_compiling" = yes; then : else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO"; then : - +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : else - ac_cv_header_stdc=no + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi + fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 -$as_echo "$ac_cv_header_stdc" >&6; } +{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then -$as_echo "#define STDC_HEADERS 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h -do : - as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default -" -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done + for ac_header in sys/bitypes.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "sys/bitypes.h" "ac_cv_header_sys_bitypes_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_bitypes_h" = x""yes; then : +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF -#define HAVE_SYS_BITYPES_H 1 +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done -ac_fn_c_check_type "$LINENO" "int8_t" "ac_cv_type_int8_t" "$ac_includes_default +{ echo "$as_me:$LINENO: checking for int8_t" >&5 +echo $ECHO_N "checking for int8_t... $ECHO_C" >&6; } +if test "${ac_cv_type_int8_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default #ifdef HAVE_SYS_BITYPES_H #include #endif -" -if test "x$ac_cv_type_int8_t" = x""yes; then : +typedef int8_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_type_int8_t=yes else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 -$as_echo "#define int8_t signed char" >>confdefs.h + ac_cv_type_int8_t=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_int8_t" >&5 +echo "${ECHO_T}$ac_cv_type_int8_t" >&6; } +if test $ac_cv_type_int8_t = yes; then + : +else -ac_fn_c_check_type "$LINENO" "u_int8_t" "ac_cv_type_u_int8_t" "$ac_includes_default +cat >>confdefs.h <<\_ACEOF +#define int8_t signed char +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for u_int8_t" >&5 +echo $ECHO_N "checking for u_int8_t... $ECHO_C" >&6; } +if test "${ac_cv_type_u_int8_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default #ifdef HAVE_SYS_BITYPES_H #include #endif -" -if test "x$ac_cv_type_u_int8_t" = x""yes; then : +typedef u_int8_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_type_u_int8_t=yes else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 -$as_echo "#define u_int8_t unsigned char" >>confdefs.h + ac_cv_type_u_int8_t=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_u_int8_t" >&5 +echo "${ECHO_T}$ac_cv_type_u_int8_t" >&6; } +if test $ac_cv_type_u_int8_t = yes; then + : +else -ac_fn_c_check_type "$LINENO" "int16_t" "ac_cv_type_int16_t" "$ac_includes_default" -if test "x$ac_cv_type_int16_t" = x""yes; then : +cat >>confdefs.h <<\_ACEOF +#define u_int8_t unsigned char +_ACEOF +fi + +{ echo "$as_me:$LINENO: checking for int16_t" >&5 +echo $ECHO_N "checking for int16_t... $ECHO_C" >&6; } +if test "${ac_cv_type_int16_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +typedef int16_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_type_int16_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 -$as_echo "#define int16_t short" >>confdefs.h + ac_cv_type_int16_t=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_int16_t" >&5 +echo "${ECHO_T}$ac_cv_type_int16_t" >&6; } +if test $ac_cv_type_int16_t = yes; then + : +else + +cat >>confdefs.h <<\_ACEOF +#define int16_t short +_ACEOF + $ac_includes_default #ifdef HAVE_SYS_BITYPES_H #include #endif fi -ac_fn_c_check_type "$LINENO" "u_int16_t" "ac_cv_type_u_int16_t" "$ac_includes_default +{ echo "$as_me:$LINENO: checking for u_int16_t" >&5 +echo $ECHO_N "checking for u_int16_t... $ECHO_C" >&6; } +if test "${ac_cv_type_u_int16_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default #ifdef HAVE_SYS_BITYPES_H #include #endif -" -if test "x$ac_cv_type_u_int16_t" = x""yes; then : +typedef u_int16_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_type_u_int16_t=yes else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 -$as_echo "#define u_int16_t unsigned short" >>confdefs.h + ac_cv_type_u_int16_t=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_u_int16_t" >&5 +echo "${ECHO_T}$ac_cv_type_u_int16_t" >&6; } +if test $ac_cv_type_u_int16_t = yes; then + : +else -ac_fn_c_check_type "$LINENO" "int32_t" "ac_cv_type_int32_t" "$ac_includes_default +cat >>confdefs.h <<\_ACEOF +#define u_int16_t unsigned short +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for int32_t" >&5 +echo $ECHO_N "checking for int32_t... $ECHO_C" >&6; } +if test "${ac_cv_type_int32_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default #ifdef HAVE_SYS_BITYPES_H #include #endif -" -if test "x$ac_cv_type_int32_t" = x""yes; then : +typedef int32_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_type_int32_t=yes else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 -$as_echo "#define int32_t int" >>confdefs.h + ac_cv_type_int32_t=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_int32_t" >&5 +echo "${ECHO_T}$ac_cv_type_int32_t" >&6; } +if test $ac_cv_type_int32_t = yes; then + : +else -ac_fn_c_check_type "$LINENO" "u_int32_t" "ac_cv_type_u_int32_t" "$ac_includes_default +cat >>confdefs.h <<\_ACEOF +#define int32_t int +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for u_int32_t" >&5 +echo $ECHO_N "checking for u_int32_t... $ECHO_C" >&6; } +if test "${ac_cv_type_u_int32_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default #ifdef HAVE_SYS_BITYPES_H #include #endif -" -if test "x$ac_cv_type_u_int32_t" = x""yes; then : +typedef u_int32_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_type_u_int32_t=yes else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 -$as_echo "#define u_int32_t unsigned int" >>confdefs.h + ac_cv_type_u_int32_t=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_u_int32_t" >&5 +echo "${ECHO_T}$ac_cv_type_u_int32_t" >&6; } +if test $ac_cv_type_u_int32_t = yes; then + : +else -ac_fn_c_check_type "$LINENO" "int64_t" "ac_cv_type_int64_t" "$ac_includes_default +cat >>confdefs.h <<\_ACEOF +#define u_int32_t unsigned int +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for int64_t" >&5 +echo $ECHO_N "checking for int64_t... $ECHO_C" >&6; } +if test "${ac_cv_type_int64_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default #ifdef HAVE_SYS_BITYPES_H #include #endif -" -if test "x$ac_cv_type_int64_t" = x""yes; then : +typedef int64_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_type_int64_t=yes else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 -$as_echo "#define int64_t long long" >>confdefs.h + ac_cv_type_int64_t=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_int64_t" >&5 +echo "${ECHO_T}$ac_cv_type_int64_t" >&6; } +if test $ac_cv_type_int64_t = yes; then + : +else -ac_fn_c_check_type "$LINENO" "u_int64_t" "ac_cv_type_u_int64_t" "$ac_includes_default +cat >>confdefs.h <<\_ACEOF +#define int64_t long long +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for u_int64_t" >&5 +echo $ECHO_N "checking for u_int64_t... $ECHO_C" >&6; } +if test "${ac_cv_type_u_int64_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default #ifdef HAVE_SYS_BITYPES_H #include #endif -" -if test "x$ac_cv_type_u_int64_t" = x""yes; then : +typedef u_int64_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_type_u_int64_t=yes else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 -$as_echo "#define u_int64_t unsigned long long" >>confdefs.h + ac_cv_type_u_int64_t=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_u_int64_t" >&5 +echo "${ECHO_T}$ac_cv_type_u_int64_t" >&6; } +if test $ac_cv_type_u_int64_t = yes; then + : +else +cat >>confdefs.h <<\_ACEOF +#define u_int64_t unsigned long long +_ACEOF +fi + + # # Try to arrange for large file support. # # Check whether --enable-largefile was given. -if test "${enable_largefile+set}" = set; then : +if test "${enable_largefile+set}" = set; then enableval=$enable_largefile; fi if test "$enable_largefile" != no; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5 -$as_echo_n "checking for special C compiler options needed for large files... " >&6; } -if test "${ac_cv_sys_largefile_CC+set}" = set; then : - $as_echo_n "(cached) " >&6 + { echo "$as_me:$LINENO: checking for special C compiler options needed for large files" >&5 +echo $ECHO_N "checking for special C compiler options needed for large files... $ECHO_C" >&6; } +if test "${ac_cv_sys_largefile_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_sys_largefile_CC=no if test "$GCC" != yes; then ac_save_CC=$CC while :; do # IRIX 6.2 and later do not support large files by default, # so use the C compiler's -n32 option if that helps. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF - if ac_fn_c_try_compile "$LINENO"; then : + rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + fi + rm -f core conftest.err conftest.$ac_objext CC="$CC -n32" - if ac_fn_c_try_compile "$LINENO"; then : + rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_sys_largefile_CC=' -n32'; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + fi + rm -f core conftest.err conftest.$ac_objext break done CC=$ac_save_CC rm -f conftest.$ac_ext fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5 -$as_echo "$ac_cv_sys_largefile_CC" >&6; } +{ echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_CC" >&5 +echo "${ECHO_T}$ac_cv_sys_largefile_CC" >&6; } if test "$ac_cv_sys_largefile_CC" != no; then CC=$CC$ac_cv_sys_largefile_CC fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5 -$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; } -if test "${ac_cv_sys_file_offset_bits+set}" = set; then : - $as_echo_n "(cached) " >&6 + { echo "$as_me:$LINENO: checking for _FILE_OFFSET_BITS value needed for large files" >&5 +echo $ECHO_N "checking for _FILE_OFFSET_BITS value needed for large files... $ECHO_C" >&6; } +if test "${ac_cv_sys_file_offset_bits+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else while :; do - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_sys_file_offset_bits=no; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #define _FILE_OFFSET_BITS 64 #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_sys_file_offset_bits=64; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_sys_file_offset_bits=unknown break done fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5 -$as_echo "$ac_cv_sys_file_offset_bits" >&6; } +{ echo "$as_me:$LINENO: result: $ac_cv_sys_file_offset_bits" >&5 +echo "${ECHO_T}$ac_cv_sys_file_offset_bits" >&6; } case $ac_cv_sys_file_offset_bits in #( no | unknown) ;; *) cat >>confdefs.h <<_ACEOF #define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits _ACEOF ;; esac -rm -rf conftest* +rm -f conftest* if test $ac_cv_sys_file_offset_bits = unknown; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5 -$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; } -if test "${ac_cv_sys_large_files+set}" = set; then : - $as_echo_n "(cached) " >&6 + { echo "$as_me:$LINENO: checking for _LARGE_FILES value needed for large files" >&5 +echo $ECHO_N "checking for _LARGE_FILES value needed for large files... $ECHO_C" >&6; } +if test "${ac_cv_sys_large_files+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else while :; do - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_sys_large_files=no; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #define _LARGE_FILES 1 #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_sys_large_files=1; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_sys_large_files=unknown break done fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5 -$as_echo "$ac_cv_sys_large_files" >&6; } +{ echo "$as_me:$LINENO: result: $ac_cv_sys_large_files" >&5 +echo "${ECHO_T}$ac_cv_sys_large_files" >&6; } case $ac_cv_sys_large_files in #( no | unknown) ;; *) cat >>confdefs.h <<_ACEOF #define _LARGE_FILES $ac_cv_sys_large_files _ACEOF ;; esac -rm -rf conftest* +rm -f conftest* fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGEFILE_SOURCE value needed for large files" >&5 -$as_echo_n "checking for _LARGEFILE_SOURCE value needed for large files... " >&6; } -if test "${ac_cv_sys_largefile_source+set}" = set; then : - $as_echo_n "(cached) " >&6 +{ echo "$as_me:$LINENO: checking for _LARGEFILE_SOURCE value needed for large files" >&5 +echo $ECHO_N "checking for _LARGEFILE_SOURCE value needed for large files... $ECHO_C" >&6; } +if test "${ac_cv_sys_largefile_source+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else while :; do - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ -#include /* for off_t */ - #include +#include int main () { -int (*fp) (FILE *, off_t, int) = fseeko; - return fseeko (stdin, 0, 0) && fp (stdin, 0, 0); +return fseeko (stdin, 0, 0) && (fseeko) (stdin, 0, 0); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then ac_cv_sys_largefile_source=no; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #define _LARGEFILE_SOURCE 1 -#include /* for off_t */ - #include +#include int main () { -int (*fp) (FILE *, off_t, int) = fseeko; - return fseeko (stdin, 0, 0) && fp (stdin, 0, 0); +return fseeko (stdin, 0, 0) && (fseeko) (stdin, 0, 0); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then ac_cv_sys_largefile_source=1; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext ac_cv_sys_largefile_source=unknown break done fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_source" >&5 -$as_echo "$ac_cv_sys_largefile_source" >&6; } +{ echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_source" >&5 +echo "${ECHO_T}$ac_cv_sys_largefile_source" >&6; } case $ac_cv_sys_largefile_source in #( no | unknown) ;; *) cat >>confdefs.h <<_ACEOF #define _LARGEFILE_SOURCE $ac_cv_sys_largefile_source _ACEOF ;; esac -rm -rf conftest* +rm -f conftest* # We used to try defining _XOPEN_SOURCE=500 too, to work around a bug # in glibc 2.1.3, but that breaks too many other things. # If you want fseeko and ftello with glibc, upgrade to a fixed glibc. if test $ac_cv_sys_largefile_source != unknown; then -$as_echo "#define HAVE_FSEEKO 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_FSEEKO 1 +_ACEOF fi + + + + for ac_header in sys/ioccom.h sys/sockio.h limits.h paths.h -do : - as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done + for ac_header in linux/types.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "linux/types.h" "ac_cv_header_linux_types_h" "$ac_includes_default" -if test "x$ac_cv_header_linux_types_h" = x""yes; then : +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF -#define HAVE_LINUX_TYPES_H 1 +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done + + + for ac_header in linux/if_packet.h netpacket/packet.h netpacket/if_packet.h -do : - as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done + for ac_header in net/pfvar.h -do : - ac_fn_c_check_header_compile "$LINENO" "net/pfvar.h" "ac_cv_header_net_pfvar_h" "#include +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include #include #include -" -if test "x$ac_cv_header_net_pfvar_h" = x""yes; then : + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF -#define HAVE_NET_PFVAR_H 1 +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done if test "$ac_cv_header_net_pfvar_h" = yes; then # # Check for various PF actions. # - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether net/pfvar.h defines PF_NAT through PF_NORDR" >&5 -$as_echo_n "checking whether net/pfvar.h defines PF_NAT through PF_NORDR... " >&6; } - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + { echo "$as_me:$LINENO: checking whether net/pfvar.h defines PF_NAT through PF_NORDR" >&5 +echo $ECHO_N "checking whether net/pfvar.h defines PF_NAT through PF_NORDR... $ECHO_C" >&6; } + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include int main () { return PF_NAT+PF_NONAT+PF_BINAT+PF_NOBINAT+PF_RDR+PF_NORDR; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } -$as_echo "#define HAVE_PF_NAT_THROUGH_PF_NORDR 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_PF_NAT_THROUGH_PF_NORDR 1 +_ACEOF else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi + for ac_header in netinet/if_ether.h -do : - ac_fn_c_check_header_compile "$LINENO" "netinet/if_ether.h" "ac_cv_header_netinet_if_ether_h" "#include +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include #include -" -if test "x$ac_cv_header_netinet_if_ether_h" = x""yes; then : + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF -#define HAVE_NETINET_IF_ETHER_H 1 +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done if test "$ac_cv_header_netinet_if_ether_h" != yes; then # # The simple test didn't work. # Do we need to include first? # Unset ac_cv_header_netinet_if_ether_h so we don't # treat the previous failure as a cached value and # suppress the next test. # - { $as_echo "$as_me:${as_lineno-$LINENO}: Rechecking with some additional includes" >&5 -$as_echo "$as_me: Rechecking with some additional includes" >&6;} + { echo "$as_me:$LINENO: Rechecking with some additional includes" >&5 +echo "$as_me: Rechecking with some additional includes" >&6;} unset ac_cv_header_netinet_if_ether_h - for ac_header in netinet/if_ether.h -do : - ac_fn_c_check_header_compile "$LINENO" "netinet/if_ether.h" "ac_cv_header_netinet_if_ether_h" "#include + +for ac_header in netinet/if_ether.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include #include #include struct mbuf; struct rtentry; #include -" -if test "x$ac_cv_header_netinet_if_ether_h" = x""yes; then : + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF -#define HAVE_NETINET_IF_ETHER_H 1 +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done fi if test "$GCC" = yes ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI ioctl definitions" >&5 -$as_echo_n "checking for ANSI ioctl definitions... " >&6; } - if test "${ac_cv_lbl_gcc_fixincludes+set}" = set; then : - $as_echo_n "(cached) " >&6 + { echo "$as_me:$LINENO: checking for ANSI ioctl definitions" >&5 +echo $ECHO_N "checking for ANSI ioctl definitions... $ECHO_C" >&6; } + if test "${ac_cv_lbl_gcc_fixincludes+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* * This generates a "duplicate case value" when fixincludes * has not be run. */ # include # include # include # ifdef HAVE_SYS_IOCCOM_H # include # endif int main () { switch (0) { case _IO('A', 1):; case _IO('B', 1):; } ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_lbl_gcc_fixincludes=yes else - ac_cv_lbl_gcc_fixincludes=no + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lbl_gcc_fixincludes=no fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_gcc_fixincludes" >&5 -$as_echo "$ac_cv_lbl_gcc_fixincludes" >&6; } + { echo "$as_me:$LINENO: result: $ac_cv_lbl_gcc_fixincludes" >&5 +echo "${ECHO_T}$ac_cv_lbl_gcc_fixincludes" >&6; } if test $ac_cv_lbl_gcc_fixincludes = no ; then # Don't cache failure unset ac_cv_lbl_gcc_fixincludes - as_fn_error $? "see the INSTALL for more info" "$LINENO" 5 + { { echo "$as_me:$LINENO: error: see the INSTALL for more info" >&5 +echo "$as_me: error: see the INSTALL for more info" >&2;} + { (exit 1); exit 1; }; } fi fi + + for ac_func in strerror strlcpy -do : - as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` -ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" -if eval test \"x\$"$as_ac_var"\" = x"yes"; then : +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done needsnprintf=no + + for ac_func in vsnprintf snprintf -do : - as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` -ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" -if eval test \"x\$"$as_ac_var"\" = x"yes"; then : +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF else needsnprintf=yes fi done if test $needsnprintf = yes; then case " $LIBOBJS " in *" snprintf.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS snprintf.$ac_objext" ;; esac fi # # Do this before checking for ether_hostton(), as it's a # "gethostbyname() -ish function". # # Most operating systems have gethostbyname() in the default searched # libraries (i.e. libc): # Some OSes (eg. Solaris) place it in libnsl # Some strange OSes (SINIX) have it in libsocket: - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5 -$as_echo_n "checking for library containing gethostbyname... " >&6; } -if test "${ac_cv_search_gethostbyname+set}" = set; then : - $as_echo_n "(cached) " >&6 + { echo "$as_me:$LINENO: checking for library containing gethostbyname" >&5 +echo $ECHO_N "checking for library containing gethostbyname... $ECHO_C" >&6; } +if test "${ac_cv_search_gethostbyname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_LIBS=$LIBS -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gethostbyname (); int main () { return gethostbyname (); ; return 0; } _ACEOF for ac_lib in '' nsl socket resolv; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi - if ac_fn_c_try_link "$LINENO"; then : + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then ac_cv_search_gethostbyname=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if test "${ac_cv_search_gethostbyname+set}" = set; then : + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext + if test "${ac_cv_search_gethostbyname+set}" = set; then break fi done -if test "${ac_cv_search_gethostbyname+set}" = set; then : - +if test "${ac_cv_search_gethostbyname+set}" = set; then + : else ac_cv_search_gethostbyname=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname" >&5 -$as_echo "$ac_cv_search_gethostbyname" >&6; } +{ echo "$as_me:$LINENO: result: $ac_cv_search_gethostbyname" >&5 +echo "${ECHO_T}$ac_cv_search_gethostbyname" >&6; } ac_res=$ac_cv_search_gethostbyname -if test "$ac_res" != no; then : +if test "$ac_res" != no; then test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi # Unfortunately libsocket sometimes depends on libnsl and # AC_SEARCH_LIBS isn't up to the task of handling dependencies like this. if test "$ac_cv_search_gethostbyname" = "no" then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lsocket" >&5 -$as_echo_n "checking for gethostbyname in -lsocket... " >&6; } -if test "${ac_cv_lib_socket_gethostbyname+set}" = set; then : - $as_echo_n "(cached) " >&6 + { echo "$as_me:$LINENO: checking for gethostbyname in -lsocket" >&5 +echo $ECHO_N "checking for gethostbyname in -lsocket... $ECHO_C" >&6; } +if test "${ac_cv_lib_socket_gethostbyname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket -lnsl $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gethostbyname (); int main () { return gethostbyname (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then ac_cv_lib_socket_gethostbyname=yes else - ac_cv_lib_socket_gethostbyname=no + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_socket_gethostbyname=no fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_gethostbyname" >&5 -$as_echo "$ac_cv_lib_socket_gethostbyname" >&6; } -if test "x$ac_cv_lib_socket_gethostbyname" = x""yes; then : +{ echo "$as_me:$LINENO: result: $ac_cv_lib_socket_gethostbyname" >&5 +echo "${ECHO_T}$ac_cv_lib_socket_gethostbyname" >&6; } +if test $ac_cv_lib_socket_gethostbyname = yes; then LIBS="-lsocket -lnsl $LIBS" fi fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing socket" >&5 -$as_echo_n "checking for library containing socket... " >&6; } -if test "${ac_cv_search_socket+set}" = set; then : - $as_echo_n "(cached) " >&6 + { echo "$as_me:$LINENO: checking for library containing socket" >&5 +echo $ECHO_N "checking for library containing socket... $ECHO_C" >&6; } +if test "${ac_cv_search_socket+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_LIBS=$LIBS -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char socket (); int main () { return socket (); ; return 0; } _ACEOF for ac_lib in '' socket; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi - if ac_fn_c_try_link "$LINENO"; then : + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then ac_cv_search_socket=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if test "${ac_cv_search_socket+set}" = set; then : + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext + if test "${ac_cv_search_socket+set}" = set; then break fi done -if test "${ac_cv_search_socket+set}" = set; then : - +if test "${ac_cv_search_socket+set}" = set; then + : else ac_cv_search_socket=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_socket" >&5 -$as_echo "$ac_cv_search_socket" >&6; } +{ echo "$as_me:$LINENO: result: $ac_cv_search_socket" >&5 +echo "${ECHO_T}$ac_cv_search_socket" >&6; } ac_res=$ac_cv_search_socket -if test "$ac_res" != no; then : +if test "$ac_res" != no; then test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lsocket" >&5 -$as_echo_n "checking for socket in -lsocket... " >&6; } -if test "${ac_cv_lib_socket_socket+set}" = set; then : - $as_echo_n "(cached) " >&6 + { echo "$as_me:$LINENO: checking for socket in -lsocket" >&5 +echo $ECHO_N "checking for socket in -lsocket... $ECHO_C" >&6; } +if test "${ac_cv_lib_socket_socket+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket -lnsl $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char socket (); int main () { return socket (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then ac_cv_lib_socket_socket=yes else - ac_cv_lib_socket_socket=no + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_socket_socket=no fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_socket" >&5 -$as_echo "$ac_cv_lib_socket_socket" >&6; } -if test "x$ac_cv_lib_socket_socket" = x""yes; then : +{ echo "$as_me:$LINENO: result: $ac_cv_lib_socket_socket" >&5 +echo "${ECHO_T}$ac_cv_lib_socket_socket" >&6; } +if test $ac_cv_lib_socket_socket = yes; then LIBS="-lsocket -lnsl $LIBS" fi fi # DLPI needs putmsg under HPUX so test for -lstr while we're at it - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing putmsg" >&5 -$as_echo_n "checking for library containing putmsg... " >&6; } -if test "${ac_cv_search_putmsg+set}" = set; then : - $as_echo_n "(cached) " >&6 + { echo "$as_me:$LINENO: checking for library containing putmsg" >&5 +echo $ECHO_N "checking for library containing putmsg... $ECHO_C" >&6; } +if test "${ac_cv_search_putmsg+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_LIBS=$LIBS -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char putmsg (); int main () { return putmsg (); ; return 0; } _ACEOF for ac_lib in '' str; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi - if ac_fn_c_try_link "$LINENO"; then : + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then ac_cv_search_putmsg=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if test "${ac_cv_search_putmsg+set}" = set; then : + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext + if test "${ac_cv_search_putmsg+set}" = set; then break fi done -if test "${ac_cv_search_putmsg+set}" = set; then : - +if test "${ac_cv_search_putmsg+set}" = set; then + : else ac_cv_search_putmsg=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_putmsg" >&5 -$as_echo "$ac_cv_search_putmsg" >&6; } +{ echo "$as_me:$LINENO: result: $ac_cv_search_putmsg" >&5 +echo "${ECHO_T}$ac_cv_search_putmsg" >&6; } ac_res=$ac_cv_search_putmsg -if test "$ac_res" != no; then : +if test "$ac_res" != no; then test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi # # You are in a twisty little maze of UN*Xes, all different. # Some might not have ether_hostton(). # Some might have it, but not declare it in any header file. # Some might have it, but declare it in . # Some might have it, but declare it in # (And some might have it but document it as something declared in # , although appears to work.) # # Before you is a C compiler. # + for ac_func in ether_hostton -do : - ac_fn_c_check_func "$LINENO" "ether_hostton" "ac_cv_func_ether_hostton" -if test "x$ac_cv_func_ether_hostton" = x""yes; then : +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF -#define HAVE_ETHER_HOSTTON 1 +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done if test "$ac_cv_func_ether_hostton" = yes; then # # OK, we have ether_hostton(). Do we have ? # if test "$ac_cv_header_netinet_if_ether_h" = yes; then # # Yes. Does it declare ether_hostton()? # - ac_fn_c_check_decl "$LINENO" "ether_hostton" "ac_cv_have_decl_ether_hostton" " + { echo "$as_me:$LINENO: checking whether ether_hostton is declared" >&5 +echo $ECHO_N "checking whether ether_hostton is declared... $ECHO_C" >&6; } +if test "${ac_cv_have_decl_ether_hostton+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + #include #include #include #include struct mbuf; struct rtentry; #include #include -" -if test "x$ac_cv_have_decl_ether_hostton" = x""yes; then : +int +main () +{ +#ifndef ether_hostton + (void) ether_hostton; +#endif -$as_echo "#define NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON /**/" >>confdefs.h + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_have_decl_ether_hostton=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + ac_cv_have_decl_ether_hostton=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi +{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_ether_hostton" >&5 +echo "${ECHO_T}$ac_cv_have_decl_ether_hostton" >&6; } +if test $ac_cv_have_decl_ether_hostton = yes; then + +cat >>confdefs.h <<\_ACEOF +#define NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON +_ACEOF + + +fi + fi # # Did that succeed? # if test "$ac_cv_have_decl_ether_hostton" != yes; then # # No, how about , as on Linux? # - for ac_header in netinet/ether.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "netinet/ether.h" "ac_cv_header_netinet_ether_h" "$ac_includes_default" -if test "x$ac_cv_header_netinet_ether_h" = x""yes; then : + +for ac_header in netinet/ether.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF -#define HAVE_NETINET_ETHER_H 1 +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done if test "$ac_cv_header_netinet_ether_h" = yes; then # # We have it - does it declare ether_hostton()? # Unset ac_cv_have_decl_ether_hostton so we don't # treat the previous failure as a cached value and # suppress the next test. # unset ac_cv_have_decl_ether_hostton - ac_fn_c_check_decl "$LINENO" "ether_hostton" "ac_cv_have_decl_ether_hostton" " + { echo "$as_me:$LINENO: checking whether ether_hostton is declared" >&5 +echo $ECHO_N "checking whether ether_hostton is declared... $ECHO_C" >&6; } +if test "${ac_cv_have_decl_ether_hostton+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + #include -" -if test "x$ac_cv_have_decl_ether_hostton" = x""yes; then : +int +main () +{ +#ifndef ether_hostton + (void) ether_hostton; +#endif -$as_echo "#define NETINET_ETHER_H_DECLARES_ETHER_HOSTTON /**/" >>confdefs.h + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_have_decl_ether_hostton=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + ac_cv_have_decl_ether_hostton=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi +{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_ether_hostton" >&5 +echo "${ECHO_T}$ac_cv_have_decl_ether_hostton" >&6; } +if test $ac_cv_have_decl_ether_hostton = yes; then + +cat >>confdefs.h <<\_ACEOF +#define NETINET_ETHER_H_DECLARES_ETHER_HOSTTON +_ACEOF + + +fi + fi fi # # Is ether_hostton() declared? # if test "$ac_cv_have_decl_ether_hostton" != yes; then # # No, we'll have to declare it ourselves. # Do we have "struct ether_addr"? # - ac_fn_c_check_type "$LINENO" "struct ether_addr" "ac_cv_type_struct_ether_addr" " + { echo "$as_me:$LINENO: checking for struct ether_addr" >&5 +echo $ECHO_N "checking for struct ether_addr... $ECHO_C" >&6; } +if test "${ac_cv_type_struct_ether_addr+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + #include #include #include #include struct mbuf; struct rtentry; #include #include -" -if test "x$ac_cv_type_struct_ether_addr" = x""yes; then : +typedef struct ether_addr ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_type_struct_ether_addr=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_struct_ether_addr=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_struct_ether_addr" >&5 +echo "${ECHO_T}$ac_cv_type_struct_ether_addr" >&6; } +if test $ac_cv_type_struct_ether_addr = yes; then + cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_ETHER_ADDR 1 _ACEOF fi -$as_echo "#define HAVE_DECL_ETHER_HOSTTON 0" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_DECL_ETHER_HOSTTON 0 +_ACEOF else -$as_echo "#define HAVE_DECL_ETHER_HOSTTON 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_DECL_ETHER_HOSTTON 1 +_ACEOF fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --disable-protochain option is specified" >&5 -$as_echo_n "checking if --disable-protochain option is specified... " >&6; } +{ echo "$as_me:$LINENO: checking if --disable-protochain option is specified" >&5 +echo $ECHO_N "checking if --disable-protochain option is specified... $ECHO_C" >&6; } # Check whether --enable-protochain was given. -if test "${enable_protochain+set}" = set; then : +if test "${enable_protochain+set}" = set; then enableval=$enable_protochain; fi case "x$enable_protochain" in xyes) enable_protochain=enabled ;; xno) enable_protochain=disabled ;; x) enable_protochain=enabled ;; esac if test "$enable_protochain" = "disabled"; then -$as_echo "#define NO_PROTOCHAIN 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define NO_PROTOCHAIN 1 +_ACEOF fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${enable_protochain}" >&5 -$as_echo "${enable_protochain}" >&6; } +{ echo "$as_me:$LINENO: result: ${enable_protochain}" >&5 +echo "${ECHO_T}${enable_protochain}" >&6; } # # SITA support is mutually exclusive with native capture support; # "--with-sita" selects SITA support. # # Check whether --with-sita was given. -if test "${with_sita+set}" = set; then : +if test "${with_sita+set}" = set; then withval=$with_sita; if test ! "x$withval" = "xno" ; then -$as_echo "#define SITA 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define SITA 1 +_ACEOF - { $as_echo "$as_me:${as_lineno-$LINENO}: Enabling SITA ACN support" >&5 -$as_echo "$as_me: Enabling SITA ACN support" >&6;} + { echo "$as_me:$LINENO: Enabling SITA ACN support" >&5 +echo "$as_me: Enabling SITA ACN support" >&6;} V_PCAP=sita V_FINDALLDEVS=sita fi else if test -z "$with_pcap" && test "$cross_compiling" = yes; then - as_fn_error $? "pcap type not determined when cross-compiling; use --with-pcap=..." "$LINENO" 5 + { { echo "$as_me:$LINENO: error: pcap type not determined when cross-compiling; use --with-pcap=..." >&5 +echo "$as_me: error: pcap type not determined when cross-compiling; use --with-pcap=..." >&2;} + { (exit 1); exit 1; }; } fi # Check whether --with-pcap was given. -if test "${with_pcap+set}" = set; then : +if test "${with_pcap+set}" = set; then withval=$with_pcap; fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking packet capture type" >&5 -$as_echo_n "checking packet capture type... " >&6; } +{ echo "$as_me:$LINENO: checking packet capture type" >&5 +echo $ECHO_N "checking packet capture type... $ECHO_C" >&6; } if test ! -z "$with_pcap" ; then V_PCAP="$withval" elif test -r /dev/bpf -o -h /dev/bpf ; then # # Cloning BPF device. # V_PCAP=bpf -$as_echo "#define HAVE_CLONING_BPF 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_CLONING_BPF 1 +_ACEOF elif test -r /dev/bpf0 ; then V_PCAP=bpf elif test -r /usr/include/net/pfilt.h ; then V_PCAP=pf elif test -r /dev/enet ; then V_PCAP=enet elif test -r /dev/nit ; then V_PCAP=snit elif test -r /usr/include/sys/net/nit.h ; then V_PCAP=nit elif test -r /usr/include/linux/socket.h ; then V_PCAP=linux elif test -r /usr/include/net/raw.h ; then V_PCAP=snoop elif test -r /usr/include/odmi.h ; then # # On AIX, the BPF devices might not yet be present - they're # created the first time libpcap runs after booting. # We check for odmi.h instead. # V_PCAP=bpf elif test -c /dev/bpf0 ; then # check again in case not readable V_PCAP=bpf elif test -r /usr/include/sys/dlpi.h ; then V_PCAP=dlpi elif test -c /dev/enet ; then # check again in case not readable V_PCAP=enet elif test -c /dev/nit ; then # check again in case not readable V_PCAP=snit else V_PCAP=null fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $V_PCAP" >&5 -$as_echo "$V_PCAP" >&6; } +{ echo "$as_me:$LINENO: result: $V_PCAP" >&5 +echo "${ECHO_T}$V_PCAP" >&6; } # # Do capture-mechanism-dependent tests. # case "$V_PCAP" in dlpi) # # Checks to see if Solaris has the public libdlpi(3LIB) library. # Note: The existence of /usr/include/libdlpi.h does not mean it is the # public libdlpi(3LIB) version. Before libdlpi was made public, a # private version also existed, which did not have the same APIs. # Due to a gcc bug, the default search path for 32-bit libraries does # not include /lib, we add it explicitly here. # [http://bugs.opensolaris.org/view_bug.do?bug_id=6619485]. # Also, due to the bug above applications that link to libpcap with # libdlpi will have to add "-L/lib" option to "configure". # saved_ldflags=$LDFLAGS LDFLAGS="$LIBS -L/lib" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlpi_walk in -ldlpi" >&5 -$as_echo_n "checking for dlpi_walk in -ldlpi... " >&6; } -if test "${ac_cv_lib_dlpi_dlpi_walk+set}" = set; then : - $as_echo_n "(cached) " >&6 + { echo "$as_me:$LINENO: checking for dlpi_walk in -ldlpi" >&5 +echo $ECHO_N "checking for dlpi_walk in -ldlpi... $ECHO_C" >&6; } +if test "${ac_cv_lib_dlpi_dlpi_walk+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldlpi $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlpi_walk (); int main () { return dlpi_walk (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then ac_cv_lib_dlpi_dlpi_walk=yes else - ac_cv_lib_dlpi_dlpi_walk=no + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dlpi_dlpi_walk=no fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dlpi_dlpi_walk" >&5 -$as_echo "$ac_cv_lib_dlpi_dlpi_walk" >&6; } -if test "x$ac_cv_lib_dlpi_dlpi_walk" = x""yes; then : +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dlpi_dlpi_walk" >&5 +echo "${ECHO_T}$ac_cv_lib_dlpi_dlpi_walk" >&6; } +if test $ac_cv_lib_dlpi_dlpi_walk = yes; then LIBS="-ldlpi $LIBS" V_PCAP=libdlpi -$as_echo "#define HAVE_LIBDLPI 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBDLPI 1 +_ACEOF else V_PCAP=dlpi fi LDFLAGS=$saved_ldflags # # Checks whether is usable, to catch weird SCO # versions of DLPI. # - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether is usable" >&5 -$as_echo_n "checking whether is usable... " >&6; } - if test "${ac_cv_sys_dlpi_usable+set}" = set; then : - $as_echo_n "(cached) " >&6 + { echo "$as_me:$LINENO: checking whether is usable" >&5 +echo $ECHO_N "checking whether is usable... $ECHO_C" >&6; } + if test "${ac_cv_sys_dlpi_usable+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include int main () { int i = DL_PROMISC_PHYS; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_sys_dlpi_usable=yes else - ac_cv_sys_dlpi_usable=no + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_sys_dlpi_usable=no fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_dlpi_usable" >&5 -$as_echo "$ac_cv_sys_dlpi_usable" >&6; } + { echo "$as_me:$LINENO: result: $ac_cv_sys_dlpi_usable" >&5 +echo "${ECHO_T}$ac_cv_sys_dlpi_usable" >&6; } if test $ac_cv_sys_dlpi_usable = no ; then - as_fn_error $? " is not usable on this system; it probably has a non-standard DLPI" "$LINENO" 5 + { { echo "$as_me:$LINENO: error: is not usable on this system; it probably has a non-standard DLPI" >&5 +echo "$as_me: error: is not usable on this system; it probably has a non-standard DLPI" >&2;} + { (exit 1); exit 1; }; } fi # # Check whether we have a /dev/dlpi device or have multiple devices. # - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /dev/dlpi device" >&5 -$as_echo_n "checking for /dev/dlpi device... " >&6; } + { echo "$as_me:$LINENO: checking for /dev/dlpi device" >&5 +echo $ECHO_N "checking for /dev/dlpi device... $ECHO_C" >&6; } if test -c /dev/dlpi ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } -$as_echo "#define HAVE_DEV_DLPI 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_DEV_DLPI 1 +_ACEOF else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } dir="/dev/dlpi" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $dir directory" >&5 -$as_echo_n "checking for $dir directory... " >&6; } + { echo "$as_me:$LINENO: checking for $dir directory" >&5 +echo $ECHO_N "checking for $dir directory... $ECHO_C" >&6; } if test -d $dir ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } cat >>confdefs.h <<_ACEOF #define PCAP_DEV_PREFIX "$dir" _ACEOF else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } fi fi # # This check is for Solaris with DLPI support for passive modes. # See dlpi(7P) for more details. # - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if dl_passive_req_t struct exists" >&5 -$as_echo_n "checking if dl_passive_req_t struct exists... " >&6; } - if test "${ac_cv_lbl_has_dl_passive_req_t+set}" = set; then : - $as_echo_n "(cached) " >&6 + { echo "$as_me:$LINENO: checking if dl_passive_req_t struct exists" >&5 +echo $ECHO_N "checking if dl_passive_req_t struct exists... $ECHO_C" >&6; } + if test "${ac_cv_lbl_has_dl_passive_req_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ # include # include int main () { u_int i = sizeof(dl_passive_req_t) ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_lbl_has_dl_passive_req_t=yes else - ac_cv_lbl_has_dl_passive_req_t=no + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lbl_has_dl_passive_req_t=no fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_has_dl_passive_req_t" >&5 -$as_echo "$ac_cv_lbl_has_dl_passive_req_t" >&6; } + { echo "$as_me:$LINENO: result: $ac_cv_lbl_has_dl_passive_req_t" >&5 +echo "${ECHO_T}$ac_cv_lbl_has_dl_passive_req_t" >&6; } if test $ac_cv_lbl_has_dl_passive_req_t = yes ; then -$as_echo "#define HAVE_DLPI_PASSIVE 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_DLPI_PASSIVE 1 +_ACEOF fi ;; linux) # # Do we have the wireless extensions? # - for ac_header in linux/wireless.h -do : - ac_fn_c_check_header_compile "$LINENO" "linux/wireless.h" "ac_cv_header_linux_wireless_h" " + +for ac_header in linux/wireless.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + #include #include #include -" -if test "x$ac_cv_header_linux_wireless_h" = x""yes; then : + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF -#define HAVE_LINUX_WIRELESS_H 1 +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # # Do we have libnl? # # Check whether --with-libnl was given. -if test "${with_libnl+set}" = set; then : +if test "${with_libnl+set}" = set; then withval=$with_libnl; with_libnl=$withval fi if test x$with_libnl != xno ; then + have_any_nl="no" + # - # Try libnl 2.x first. + # Try libnl 3.x first. # - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for nl_socket_alloc in -lnl" >&5 -$as_echo_n "checking for nl_socket_alloc in -lnl... " >&6; } -if test "${ac_cv_lib_nl_nl_socket_alloc+set}" = set; then : - $as_echo_n "(cached) " >&6 + { echo "$as_me:$LINENO: checking for nl_socket_alloc in -lnl-3" >&5 +echo $ECHO_N "checking for nl_socket_alloc in -lnl-3... $ECHO_C" >&6; } +if test "${ac_cv_lib_nl_3_nl_socket_alloc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS -LIBS="-lnl $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +LIBS="-lnl-3 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char nl_socket_alloc (); int main () { return nl_socket_alloc (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_nl_nl_socket_alloc=yes +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_lib_nl_3_nl_socket_alloc=yes else - ac_cv_lib_nl_nl_socket_alloc=no + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_nl_3_nl_socket_alloc=no fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nl_nl_socket_alloc" >&5 -$as_echo "$ac_cv_lib_nl_nl_socket_alloc" >&6; } -if test "x$ac_cv_lib_nl_nl_socket_alloc" = x""yes; then : +{ echo "$as_me:$LINENO: result: $ac_cv_lib_nl_3_nl_socket_alloc" >&5 +echo "${ECHO_T}$ac_cv_lib_nl_3_nl_socket_alloc" >&6; } +if test $ac_cv_lib_nl_3_nl_socket_alloc = yes; then # - # Yes, we have libnl 2.x. + # Yes, we have libnl 3.x. # - LIBS="-lnl-genl -lnl $LIBS" + LIBS="-lnl-genl-3 -lnl-3 $LIBS" -$as_echo "#define HAVE_LIBNL 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBNL 1 +_ACEOF -$as_echo "#define HAVE_LIBNL_2_x 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBNL_3_x 1 +_ACEOF +cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBNL_NLE 1 +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBNL_SOCKETS 1 +_ACEOF + + V_INCLS="$V_INCLS -I/usr/include/libnl3" + have_any_nl="yes" + +fi + + + if test x$have_any_nl = xno ; then + # + # Try libnl 2.x + # + { echo "$as_me:$LINENO: checking for nl_socket_alloc in -lnl" >&5 +echo $ECHO_N "checking for nl_socket_alloc in -lnl... $ECHO_C" >&6; } +if test "${ac_cv_lib_nl_nl_socket_alloc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char nl_socket_alloc (); +int +main () +{ +return nl_socket_alloc (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_lib_nl_nl_socket_alloc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_nl_nl_socket_alloc=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_nl_nl_socket_alloc" >&5 +echo "${ECHO_T}$ac_cv_lib_nl_nl_socket_alloc" >&6; } +if test $ac_cv_lib_nl_nl_socket_alloc = yes; then + + # + # Yes, we have libnl 2.x. + # + LIBS="-lnl-genl -lnl $LIBS" + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBNL 1 +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBNL_2_x 1 +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBNL_NLE 1 +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBNL_SOCKETS 1 +_ACEOF + + have_any_nl="yes" + +fi + + fi + + if test x$have_any_nl = xno ; then # # No, we don't; do we have libnl 1.x? # - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for nl_handle_alloc in -lnl" >&5 -$as_echo_n "checking for nl_handle_alloc in -lnl... " >&6; } -if test "${ac_cv_lib_nl_nl_handle_alloc+set}" = set; then : - $as_echo_n "(cached) " >&6 + { echo "$as_me:$LINENO: checking for nl_handle_alloc in -lnl" >&5 +echo $ECHO_N "checking for nl_handle_alloc in -lnl... $ECHO_C" >&6; } +if test "${ac_cv_lib_nl_nl_handle_alloc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lnl $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char nl_handle_alloc (); int main () { return nl_handle_alloc (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then ac_cv_lib_nl_nl_handle_alloc=yes else - ac_cv_lib_nl_nl_handle_alloc=no + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_nl_nl_handle_alloc=no fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nl_nl_handle_alloc" >&5 -$as_echo "$ac_cv_lib_nl_nl_handle_alloc" >&6; } -if test "x$ac_cv_lib_nl_nl_handle_alloc" = x""yes; then : +{ echo "$as_me:$LINENO: result: $ac_cv_lib_nl_nl_handle_alloc" >&5 +echo "${ECHO_T}$ac_cv_lib_nl_nl_handle_alloc" >&6; } +if test $ac_cv_lib_nl_nl_handle_alloc = yes; then # # Yes. # LIBS="-lnl $LIBS" -$as_echo "#define HAVE_LIBNL 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBNL 1 +_ACEOF + have_any_nl="yes" -else - - # - # No, we don't have libnl at all. - # - if test x$with_libnl = xyes ; then - as_fn_error $? "libnl support requested but libnl not found" "$LINENO" 5 - fi - fi + fi -fi - + if test x$have_any_nl = xno ; then + # + # No, we don't have libnl at all. + # + if test x$with_libnl = xyes ; then + { { echo "$as_me:$LINENO: error: libnl support requested but libnl not found" >&5 +echo "$as_me: error: libnl support requested but libnl not found" >&2;} + { (exit 1); exit 1; }; } + fi + fi fi - for ac_header in linux/ethtool.h -do : - ac_fn_c_check_header_compile "$LINENO" "linux/ethtool.h" "ac_cv_header_linux_ethtool_h" " + +for ac_header in linux/ethtool.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + $ac_includes_default #include -" -if test "x$ac_cv_header_linux_ethtool_h" = x""yes; then : + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF -#define HAVE_LINUX_ETHTOOL_H 1 +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if if_packet.h has tpacket_stats defined" >&5 -$as_echo_n "checking if if_packet.h has tpacket_stats defined... " >&6; } - if test "${ac_cv_lbl_tpacket_stats+set}" = set; then : - $as_echo_n "(cached) " >&6 + { echo "$as_me:$LINENO: checking if if_packet.h has tpacket_stats defined" >&5 +echo $ECHO_N "checking if if_packet.h has tpacket_stats defined... $ECHO_C" >&6; } + if test "${ac_cv_lbl_tpacket_stats+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ # include int main () { struct tpacket_stats stats ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_lbl_tpacket_stats=yes else - ac_cv_lbl_tpacket_stats=no + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lbl_tpacket_stats=no fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_tpacket_stats" >&5 -$as_echo "$ac_cv_lbl_tpacket_stats" >&6; } + { echo "$as_me:$LINENO: result: $ac_cv_lbl_tpacket_stats" >&5 +echo "${ECHO_T}$ac_cv_lbl_tpacket_stats" >&6; } if test $ac_cv_lbl_tpacket_stats = yes; then -$as_echo "#define HAVE_TPACKET_STATS 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_TPACKET_STATS 1 +_ACEOF fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if tpacket_auxdata struct has tp_vlan_tci member" >&5 -$as_echo_n "checking if tpacket_auxdata struct has tp_vlan_tci member... " >&6; } - if test "${ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci+set}" = set; then : - $as_echo_n "(cached) " >&6 + { echo "$as_me:$LINENO: checking if tpacket_auxdata struct has tp_vlan_tci member" >&5 +echo $ECHO_N "checking if tpacket_auxdata struct has tp_vlan_tci member... $ECHO_C" >&6; } + if test "${ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ # include # include int main () { u_int i = sizeof(((struct tpacket_auxdata *)0)->tp_vlan_tci) ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci=yes else - ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci=no + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci=no fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci" >&5 -$as_echo "$ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci" >&6; } + { echo "$as_me:$LINENO: result: $ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci" >&5 +echo "${ECHO_T}$ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci" >&6; } if test $ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci = yes ; then HAVE_LINUX_TPACKET_AUXDATA=tp_vlan_tci -$as_echo "#define HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI 1 +_ACEOF fi ;; bpf) # # Check whether we have the *BSD-style ioctls. # - for ac_header in net/if_media.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "net/if_media.h" "ac_cv_header_net_if_media_h" "$ac_includes_default" -if test "x$ac_cv_header_net_if_media_h" = x""yes; then : + +for ac_header in net/if_media.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF -#define HAVE_NET_IF_MEDIA_H 1 +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the system supports zerocopy BPF" >&5 -$as_echo_n "checking whether the system supports zerocopy BPF... " >&6; } - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + { echo "$as_me:$LINENO: checking whether the system supports zerocopy BPF" >&5 +echo $ECHO_N "checking whether the system supports zerocopy BPF... $ECHO_C" >&6; } + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include int main () { return (BIOCROTZBUF + BPF_BUFMODE_ZBUF); ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } -$as_echo "#define HAVE_ZEROCOPY_BPF 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_ZEROCOPY_BPF 1 +_ACEOF else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # # Check whether we have struct BPF_TIMEVAL. # - ac_fn_c_check_type "$LINENO" "struct BPF_TIMEVAL" "ac_cv_type_struct_BPF_TIMEVAL" " + { echo "$as_me:$LINENO: checking for struct BPF_TIMEVAL" >&5 +echo $ECHO_N "checking for struct BPF_TIMEVAL... $ECHO_C" >&6; } +if test "${ac_cv_type_struct_BPF_TIMEVAL+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + #include #include #ifdef HAVE_SYS_IOCCOM_H #include #endif #include -" -if test "x$ac_cv_type_struct_BPF_TIMEVAL" = x""yes; then : +typedef struct BPF_TIMEVAL ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_type_struct_BPF_TIMEVAL=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_struct_BPF_TIMEVAL=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_struct_BPF_TIMEVAL" >&5 +echo "${ECHO_T}$ac_cv_type_struct_BPF_TIMEVAL" >&6; } +if test $ac_cv_type_struct_BPF_TIMEVAL = yes; then + cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_BPF_TIMEVAL 1 _ACEOF fi ;; dag) V_DEFS="$V_DEFS -DDAG_ONLY" ;; septel) V_DEFS="$V_DEFS -DSEPTEL_ONLY" ;; snf) V_DEFS="$V_DEFS -DSNF_ONLY" ;; null) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cannot determine packet capture interface" >&5 -$as_echo "$as_me: WARNING: cannot determine packet capture interface" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: (see the INSTALL doc for more info)" >&5 -$as_echo "$as_me: WARNING: (see the INSTALL doc for more info)" >&2;} + { echo "$as_me:$LINENO: WARNING: cannot determine packet capture interface" >&5 +echo "$as_me: WARNING: cannot determine packet capture interface" >&2;} + { echo "$as_me:$LINENO: WARNING: (see the INSTALL doc for more info)" >&5 +echo "$as_me: WARNING: (see the INSTALL doc for more info)" >&2;} ;; esac if test "$V_PCAP" = null then # # We can't capture, so we can't open any capture # devices, so we won't return any interfaces. # V_FINDALLDEVS=null else - ac_fn_c_check_func "$LINENO" "getifaddrs" "ac_cv_func_getifaddrs" -if test "x$ac_cv_func_getifaddrs" = x""yes; then : + { echo "$as_me:$LINENO: checking for getifaddrs" >&5 +echo $ECHO_N "checking for getifaddrs... $ECHO_C" >&6; } +if test "${ac_cv_func_getifaddrs+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define getifaddrs to an innocuous variant, in case declares getifaddrs. + For example, HP-UX 11i declares gettimeofday. */ +#define getifaddrs innocuous_getifaddrs +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char getifaddrs (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef getifaddrs + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char getifaddrs (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_getifaddrs || defined __stub___getifaddrs +choke me +#endif + +int +main () +{ +return getifaddrs (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_func_getifaddrs=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_getifaddrs=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_getifaddrs" >&5 +echo "${ECHO_T}$ac_cv_func_getifaddrs" >&6; } +if test $ac_cv_func_getifaddrs = yes; then + # # We have "getifaddrs()"; make sure we have # as well, just in case some platform is really weird. # - ac_fn_c_check_header_mongrel "$LINENO" "ifaddrs.h" "ac_cv_header_ifaddrs_h" "$ac_includes_default" -if test "x$ac_cv_header_ifaddrs_h" = x""yes; then : + if test "${ac_cv_header_ifaddrs_h+set}" = set; then + { echo "$as_me:$LINENO: checking for ifaddrs.h" >&5 +echo $ECHO_N "checking for ifaddrs.h... $ECHO_C" >&6; } +if test "${ac_cv_header_ifaddrs_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_ifaddrs_h" >&5 +echo "${ECHO_T}$ac_cv_header_ifaddrs_h" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking ifaddrs.h usability" >&5 +echo $ECHO_N "checking ifaddrs.h usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking ifaddrs.h presence" >&5 +echo $ECHO_N "checking ifaddrs.h presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: ifaddrs.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: ifaddrs.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: ifaddrs.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: ifaddrs.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: ifaddrs.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: ifaddrs.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: ifaddrs.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: ifaddrs.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: ifaddrs.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: ifaddrs.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: ifaddrs.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: ifaddrs.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: ifaddrs.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: ifaddrs.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: ifaddrs.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: ifaddrs.h: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for ifaddrs.h" >&5 +echo $ECHO_N "checking for ifaddrs.h... $ECHO_C" >&6; } +if test "${ac_cv_header_ifaddrs_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_ifaddrs_h=$ac_header_preproc +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_ifaddrs_h" >&5 +echo "${ECHO_T}$ac_cv_header_ifaddrs_h" >&6; } + +fi +if test $ac_cv_header_ifaddrs_h = yes; then + # # We have the header, so we use "getifaddrs()" to # get the list of interfaces. # V_FINDALLDEVS=getad else # # We don't have the header - give up. # XXX - we could also fall back on some other # mechanism, but, for now, this'll catch this # problem so that we can at least try to figure # out something to do on systems with "getifaddrs()" # but without "ifaddrs.h", if there is something # we can do on those systems. # - as_fn_error $? "Your system has getifaddrs() but doesn't have a usable ." "$LINENO" 5 + { { echo "$as_me:$LINENO: error: Your system has getifaddrs() but doesn't have a usable ." >&5 +echo "$as_me: error: Your system has getifaddrs() but doesn't have a usable ." >&2;} + { (exit 1); exit 1; }; } fi else # # Well, we don't have "getifaddrs()", so we have to use # some other mechanism; determine what that mechanism is. # # The first thing we use is the type of capture mechanism, # which is somewhat of a proxy for the OS we're using. # case "$V_PCAP" in dlpi|libdlpi) - for ac_header in sys/bufmod.h sys/dlpi_ext.h -do : - as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + + +for ac_header in sys/bufmod.h sys/dlpi_ext.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # # This might be Solaris 8 or later, with # SIOCGLIFCONF, or it might be some other OS # or some older version of Solaris, with # just SIOCGIFCONF. # - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have SIOCGLIFCONF" >&5 -$as_echo_n "checking whether we have SIOCGLIFCONF... " >&6; } - if test "${ac_cv_lbl_have_siocglifconf+set}" = set; then : - $as_echo_n "(cached) " >&6 + { echo "$as_me:$LINENO: checking whether we have SIOCGLIFCONF" >&5 +echo $ECHO_N "checking whether we have SIOCGLIFCONF... $ECHO_C" >&6; } + if test "${ac_cv_lbl_have_siocglifconf+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include #include int main () { ioctl(0, SIOCGLIFCONF, (char *)0); ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_lbl_have_siocglifconf=yes else - ac_cv_lbl_have_siocglifconf=no + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lbl_have_siocglifconf=no fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_have_siocglifconf" >&5 -$as_echo "$ac_cv_lbl_have_siocglifconf" >&6; } + { echo "$as_me:$LINENO: result: $ac_cv_lbl_have_siocglifconf" >&5 +echo "${ECHO_T}$ac_cv_lbl_have_siocglifconf" >&6; } if test $ac_cv_lbl_have_siocglifconf = yes ; then V_FINDALLDEVS=glifc else V_FINDALLDEVS=gifc fi # # Needed for common functions used by pcap-[dlpi,libdlpi].c # SSRC="dlpisubs.c" ;; *) # # Assume we just have SIOCGIFCONF. # (XXX - on at least later Linux kernels, there's # another mechanism, and we should be using that # instead.) # V_FINDALLDEVS=gifc ;; esac fi fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for socklen_t" >&5 -$as_echo_n "checking for socklen_t... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +{ echo "$as_me:$LINENO: checking for socklen_t" >&5 +echo $ECHO_N "checking for socklen_t... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include int main () { socklen_t x; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then have_socklen_t=yes else - have_socklen_t=no + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + have_socklen_t=no fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test "x$have_socklen_t" = "xyes"; then -$as_echo "#define HAVE_SOCKLEN_T 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_SOCKLEN_T 1 +_ACEOF fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_socklen_t" >&5 -$as_echo "$have_socklen_t" >&6; } +{ echo "$as_me:$LINENO: result: $have_socklen_t" >&5 +echo "${ECHO_T}$have_socklen_t" >&6; } # Check whether --enable-ipv6 was given. -if test "${enable_ipv6+set}" = set; then : +if test "${enable_ipv6+set}" = set; then enableval=$enable_ipv6; else enable_ipv6=ifavailable fi if test "$enable_ipv6" != "no"; then - ac_fn_c_check_func "$LINENO" "getaddrinfo" "ac_cv_func_getaddrinfo" -if test "x$ac_cv_func_getaddrinfo" = x""yes; then : + { echo "$as_me:$LINENO: checking for getaddrinfo" >&5 +echo $ECHO_N "checking for getaddrinfo... $ECHO_C" >&6; } +if test "${ac_cv_func_getaddrinfo+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define getaddrinfo to an innocuous variant, in case declares getaddrinfo. + For example, HP-UX 11i declares gettimeofday. */ +#define getaddrinfo innocuous_getaddrinfo +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char getaddrinfo (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ -$as_echo "#define INET6 1" >>confdefs.h +#ifdef __STDC__ +# include +#else +# include +#endif +#undef getaddrinfo +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char getaddrinfo (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_getaddrinfo || defined __stub___getaddrinfo +choke me +#endif + +int +main () +{ +return getaddrinfo (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_func_getaddrinfo=yes else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + ac_cv_func_getaddrinfo=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_getaddrinfo" >&5 +echo "${ECHO_T}$ac_cv_func_getaddrinfo" >&6; } +if test $ac_cv_func_getaddrinfo = yes; then + + +cat >>confdefs.h <<\_ACEOF +#define INET6 1 +_ACEOF + + +else + if test "$enable_ipv6" != "ifavailable"; then - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "--enable-ipv6 was given, but getaddrinfo isn't available -See \`config.log' for more details" "$LINENO" 5 ; } + { { echo "$as_me:$LINENO: error: --enable-ipv6 was given, but getaddrinfo isn't available +See \`config.log' for more details." >&5 +echo "$as_me: error: --enable-ipv6 was given, but getaddrinfo isn't available +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } fi fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build optimizer debugging code" >&5 -$as_echo_n "checking whether to build optimizer debugging code... " >&6; } +{ echo "$as_me:$LINENO: checking whether to build optimizer debugging code" >&5 +echo $ECHO_N "checking whether to build optimizer debugging code... $ECHO_C" >&6; } # Check whether --enable-optimizer-dbg was given. -if test "${enable_optimizer_dbg+set}" = set; then : +if test "${enable_optimizer_dbg+set}" = set; then enableval=$enable_optimizer_dbg; fi if test "$enable_optimizer_dbg" = "yes"; then -$as_echo "#define BDEBUG 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define BDEBUG 1 +_ACEOF fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${enable_optimizer_dbg-no}" >&5 -$as_echo "${enable_optimizer_dbg-no}" >&6; } +{ echo "$as_me:$LINENO: result: ${enable_optimizer_dbg-no}" >&5 +echo "${ECHO_T}${enable_optimizer_dbg-no}" >&6; } -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build parser debugging code" >&5 -$as_echo_n "checking whether to build parser debugging code... " >&6; } +{ echo "$as_me:$LINENO: checking whether to build parser debugging code" >&5 +echo $ECHO_N "checking whether to build parser debugging code... $ECHO_C" >&6; } # Check whether --enable-yydebug was given. -if test "${enable_yydebug+set}" = set; then : +if test "${enable_yydebug+set}" = set; then enableval=$enable_yydebug; fi if test "$enable_yydebug" = "yes"; then -$as_echo "#define YYDEBUG 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define YYDEBUG 1 +_ACEOF fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${enable_yydebug-no}" >&5 -$as_echo "${enable_yydebug-no}" >&6; } +{ echo "$as_me:$LINENO: result: ${enable_yydebug-no}" >&5 +echo "${ECHO_T}${enable_yydebug-no}" >&6; } # Check for Endace DAG card support. # Check whether --with-dag was given. -if test "${with_dag+set}" = set; then : +if test "${with_dag+set}" = set; then withval=$with_dag; if test "$withval" = no then # User doesn't want DAG support. want_dag=no elif test "$withval" = yes then # User wants DAG support but hasn't specified a directory. want_dag=yes else # User wants DAG support and has specified a directory, so use the provided value. want_dag=yes dag_root=$withval fi else # # Use DAG API if present, otherwise don't # want_dag=ifpresent fi # Check whether --with-dag-includes was given. -if test "${with_dag_includes+set}" = set; then : +if test "${with_dag_includes+set}" = set; then withval=$with_dag_includes; # User wants DAG support and has specified a header directory, so use the provided value. want_dag=yes dag_include_dir=$withval fi # Check whether --with-dag-libraries was given. -if test "${with_dag_libraries+set}" = set; then : +if test "${with_dag_libraries+set}" = set; then withval=$with_dag_libraries; # User wants DAG support and has specified a library directory, so use the provided value. want_dag=yes dag_lib_dir=$withval fi case "$V_PCAP" in linux|bpf|dag) # # We support the DAG API if we're on Linux or BSD, or if we're # building a DAG-only libpcap. # ;; *) # # If the user explicitly requested DAG, tell them it's not # supported. # # If they expressed no preference, don't include it. # if test $want_dag = yes; then - as_fn_error $? "DAG support is only available with 'linux' 'bpf' and 'dag' packet capture types" "$LINENO" 5 + { { echo "$as_me:$LINENO: error: DAG support is only available with 'linux' 'bpf' and 'dag' packet capture types" >&5 +echo "$as_me: error: DAG support is only available with 'linux' 'bpf' and 'dag' packet capture types" >&2;} + { (exit 1); exit 1; }; } elif test $want_dag = yes; then want_dag=no fi ;; esac ac_cv_lbl_dag_api=no if test "$want_dag" != no; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have DAG API headers" >&5 -$as_echo_n "checking whether we have DAG API headers... " >&6; } + { echo "$as_me:$LINENO: checking whether we have DAG API headers" >&5 +echo $ECHO_N "checking whether we have DAG API headers... $ECHO_C" >&6; } # If necessary, set default paths for DAG API headers and libraries. if test -z "$dag_root"; then dag_root=/usr/local fi if test -z "$dag_include_dir"; then dag_include_dir="$dag_root/include" fi if test -z "$dag_lib_dir"; then dag_lib_dir="$dag_root/lib" fi if test -z "$dag_tools_dir"; then dag_tools_dir="$dag_root/tools" fi if test -r $dag_include_dir/dagapi.h; then ac_cv_lbl_dag_api=yes fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_dag_api ($dag_include_dir)" >&5 -$as_echo "$ac_cv_lbl_dag_api ($dag_include_dir)" >&6; } + { echo "$as_me:$LINENO: result: $ac_cv_lbl_dag_api ($dag_include_dir)" >&5 +echo "${ECHO_T}$ac_cv_lbl_dag_api ($dag_include_dir)" >&6; } fi if test $ac_cv_lbl_dag_api = yes; then V_INCLS="$V_INCLS -I$dag_include_dir" if test $V_PCAP != dag ; then SSRC="pcap-dag.c" fi # See if we can find a general version string. # Don't need to save and restore LIBS to prevent -ldag being # included if there's a found-action (arg 3). saved_ldflags=$LDFLAGS LDFLAGS="-L$dag_lib_dir" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dag_attach_stream in -ldag" >&5 -$as_echo_n "checking for dag_attach_stream in -ldag... " >&6; } -if test "${ac_cv_lib_dag_dag_attach_stream+set}" = set; then : - $as_echo_n "(cached) " >&6 + { echo "$as_me:$LINENO: checking for dag_attach_stream in -ldag" >&5 +echo $ECHO_N "checking for dag_attach_stream in -ldag... $ECHO_C" >&6; } +if test "${ac_cv_lib_dag_dag_attach_stream+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldag $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dag_attach_stream (); int main () { return dag_attach_stream (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then ac_cv_lib_dag_dag_attach_stream=yes else - ac_cv_lib_dag_dag_attach_stream=no + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dag_dag_attach_stream=no fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dag_dag_attach_stream" >&5 -$as_echo "$ac_cv_lib_dag_dag_attach_stream" >&6; } -if test "x$ac_cv_lib_dag_dag_attach_stream" = x""yes; then : +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dag_dag_attach_stream" >&5 +echo "${ECHO_T}$ac_cv_lib_dag_dag_attach_stream" >&6; } +if test $ac_cv_lib_dag_dag_attach_stream = yes; then dag_streams="1" else dag_streams="0" fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dag_get_erf_types in -ldag" >&5 -$as_echo_n "checking for dag_get_erf_types in -ldag... " >&6; } -if test "${ac_cv_lib_dag_dag_get_erf_types+set}" = set; then : - $as_echo_n "(cached) " >&6 + { echo "$as_me:$LINENO: checking for dag_get_erf_types in -ldag" >&5 +echo $ECHO_N "checking for dag_get_erf_types in -ldag... $ECHO_C" >&6; } +if test "${ac_cv_lib_dag_dag_get_erf_types+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldag $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dag_get_erf_types (); int main () { return dag_get_erf_types (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then ac_cv_lib_dag_dag_get_erf_types=yes else - ac_cv_lib_dag_dag_get_erf_types=no + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dag_dag_get_erf_types=no fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dag_dag_get_erf_types" >&5 -$as_echo "$ac_cv_lib_dag_dag_get_erf_types" >&6; } -if test "x$ac_cv_lib_dag_dag_get_erf_types" = x""yes; then : +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dag_dag_get_erf_types" >&5 +echo "${ECHO_T}$ac_cv_lib_dag_dag_get_erf_types" >&6; } +if test $ac_cv_lib_dag_dag_get_erf_types = yes; then -$as_echo "#define HAVE_DAG_GET_ERF_TYPES 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_DAG_GET_ERF_TYPES 1 +_ACEOF fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dag_get_stream_erf_types in -ldag" >&5 -$as_echo_n "checking for dag_get_stream_erf_types in -ldag... " >&6; } -if test "${ac_cv_lib_dag_dag_get_stream_erf_types+set}" = set; then : - $as_echo_n "(cached) " >&6 + { echo "$as_me:$LINENO: checking for dag_get_stream_erf_types in -ldag" >&5 +echo $ECHO_N "checking for dag_get_stream_erf_types in -ldag... $ECHO_C" >&6; } +if test "${ac_cv_lib_dag_dag_get_stream_erf_types+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldag $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dag_get_stream_erf_types (); int main () { return dag_get_stream_erf_types (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then ac_cv_lib_dag_dag_get_stream_erf_types=yes else - ac_cv_lib_dag_dag_get_stream_erf_types=no + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dag_dag_get_stream_erf_types=no fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dag_dag_get_stream_erf_types" >&5 -$as_echo "$ac_cv_lib_dag_dag_get_stream_erf_types" >&6; } -if test "x$ac_cv_lib_dag_dag_get_stream_erf_types" = x""yes; then : +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dag_dag_get_stream_erf_types" >&5 +echo "${ECHO_T}$ac_cv_lib_dag_dag_get_stream_erf_types" >&6; } +if test $ac_cv_lib_dag_dag_get_stream_erf_types = yes; then -$as_echo "#define HAVE_DAG_GET_STREAM_ERF_TYPES 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_DAG_GET_STREAM_ERF_TYPES 1 +_ACEOF fi LDFLAGS=$saved_ldflags if test "$dag_streams" = 1; then -$as_echo "#define HAVE_DAG_STREAMS_API 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_DAG_STREAMS_API 1 +_ACEOF LIBS="$LIBS -ldag" LDFLAGS="$LDFLAGS -L$dag_lib_dir" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for vdag_set_device_info in -lvdag" >&5 -$as_echo_n "checking for vdag_set_device_info in -lvdag... " >&6; } -if test "${ac_cv_lib_vdag_vdag_set_device_info+set}" = set; then : - $as_echo_n "(cached) " >&6 + { echo "$as_me:$LINENO: checking for vdag_set_device_info in -lvdag" >&5 +echo $ECHO_N "checking for vdag_set_device_info in -lvdag... $ECHO_C" >&6; } +if test "${ac_cv_lib_vdag_vdag_set_device_info+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lvdag $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char vdag_set_device_info (); int main () { return vdag_set_device_info (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then ac_cv_lib_vdag_vdag_set_device_info=yes else - ac_cv_lib_vdag_vdag_set_device_info=no + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_vdag_vdag_set_device_info=no fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_vdag_vdag_set_device_info" >&5 -$as_echo "$ac_cv_lib_vdag_vdag_set_device_info" >&6; } -if test "x$ac_cv_lib_vdag_vdag_set_device_info" = x""yes; then : +{ echo "$as_me:$LINENO: result: $ac_cv_lib_vdag_vdag_set_device_info" >&5 +echo "${ECHO_T}$ac_cv_lib_vdag_vdag_set_device_info" >&6; } +if test $ac_cv_lib_vdag_vdag_set_device_info = yes; then ac_dag_have_vdag="1" else ac_dag_have_vdag="0" fi if test "$ac_dag_have_vdag" = 1; then -$as_echo "#define HAVE_DAG_VDAG 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_DAG_VDAG 1 +_ACEOF LIBS="$LIBS -lpthread" fi fi -$as_echo "#define HAVE_DAG_API 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_DAG_API 1 +_ACEOF fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have the DAG API" >&5 -$as_echo_n "checking whether we have the DAG API... " >&6; } +{ echo "$as_me:$LINENO: checking whether we have the DAG API" >&5 +echo $ECHO_N "checking whether we have the DAG API... $ECHO_C" >&6; } if test $ac_cv_lbl_dag_api = no; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } if test "$want_dag" = yes; then # User wanted DAG support but we couldn't find it. - as_fn_error $? "DAG API requested, but not found at $dag_root: use --without-dag" "$LINENO" 5 + { { echo "$as_me:$LINENO: error: DAG API requested, but not found at $dag_root: use --without-dag" >&5 +echo "$as_me: error: DAG API requested, but not found at $dag_root: use --without-dag" >&2;} + { (exit 1); exit 1; }; } fi if test "$V_PCAP" = dag; then # User requested "dag" capture type but the DAG API wasn't # found. - as_fn_error $? "Specifying the capture type as \"dag\" requires the DAG API to be present; use the --with-dag options to specify the location. (Try \"./configure --help\" for more information.)" "$LINENO" 5 + { { echo "$as_me:$LINENO: error: Specifying the capture type as \"dag\" requires the DAG API to be present; use the --with-dag options to specify the location. (Try \"./configure --help\" for more information.)" >&5 +echo "$as_me: error: Specifying the capture type as \"dag\" requires the DAG API to be present; use the --with-dag options to specify the location. (Try \"./configure --help\" for more information.)" >&2;} + { (exit 1); exit 1; }; } fi else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } fi # Check whether --with-septel was given. -if test "${with_septel+set}" = set; then : +if test "${with_septel+set}" = set; then withval=$with_septel; if test "$withval" = no then want_septel=no elif test "$withval" = yes then want_septel=yes septel_root= else want_septel=yes septel_root=$withval fi else # # Use Septel API if present, otherwise don't # want_septel=ifpresent septel_root=./../septel fi ac_cv_lbl_septel_api=no case "$V_PCAP" in linux|septel) # # We support the Septel API if we're on Linux, or if we're building # a Septel-only libpcap. # ;; *) # # If the user explicitly requested Septel, tell them it's not # supported. # # If they expressed no preference, don't include it. # if test $want_septel = yes; then - as_fn_error $? "Septel support only available with 'linux' and 'septel' packet capture types" "$LINENO" 5 + { { echo "$as_me:$LINENO: error: Septel support only available with 'linux' and 'septel' packet capture types" >&5 +echo "$as_me: error: Septel support only available with 'linux' and 'septel' packet capture types" >&2;} + { (exit 1); exit 1; }; } elif test $want_septel = yes; then want_septel=no fi ;; esac if test "$with_septel" != no; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have Septel API" >&5 -$as_echo_n "checking whether we have Septel API... " >&6; } + { echo "$as_me:$LINENO: checking whether we have Septel API" >&5 +echo $ECHO_N "checking whether we have Septel API... $ECHO_C" >&6; } if test -z "$septel_root"; then septel_root=$srcdir/../septel fi septel_tools_dir="$septel_root" septel_include_dir="$septel_root/INC" ac_cv_lbl_septel_api=no if test -r "$septel_include_dir/msg.h"; then V_INCLS="$V_INCLS -I$septel_include_dir" ADDLOBJS="$ADDLOBJS $septel_tools_dir/asciibin.o $septel_tools_dir/bit2byte.o $septel_tools_dir/confirm.o $septel_tools_dir/fmtmsg.o $septel_tools_dir/gct_unix.o $septel_tools_dir/hqueue.o $septel_tools_dir/ident.o $septel_tools_dir/mem.o $septel_tools_dir/pack.o $septel_tools_dir/parse.o $septel_tools_dir/pool.o $septel_tools_dir/sdlsig.o $septel_tools_dir/strtonum.o $septel_tools_dir/timer.o $septel_tools_dir/trace.o" ADDLARCHIVEOBJS="$ADDLARCHIVEOBJS $septel_tools_dir/asciibin.o $septel_tools_dir/bit2byte.o $septel_tools_dir/confirm.o $septel_tools_dir/fmtmsg.o $septel_tools_dir/gct_unix.o $septel_tools_dir/hqueue.o $septel_tools_dir/ident.o $septel_tools_dir/mem.o $septel_tools_dir/pack.o $septel_tools_dir/parse.o $septel_tools_dir/pool.o $septel_tools_dir/sdlsig.o $septel_tools_dir/strtonum.o $septel_tools_dir/timer.o $septel_tools_dir/trace.o" if test "$V_PCAP" != septel ; then SSRC="pcap-septel.c" fi ac_cv_lbl_septel_api=yes fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_septel_api" >&5 -$as_echo "$ac_cv_lbl_septel_api" >&6; } + { echo "$as_me:$LINENO: result: $ac_cv_lbl_septel_api" >&5 +echo "${ECHO_T}$ac_cv_lbl_septel_api" >&6; } if test $ac_cv_lbl_septel_api = no; then if test "$want_septel" = yes; then - as_fn_error $? "Septel API not found under directory $septel_root; use --without-septel" "$LINENO" 5 + { { echo "$as_me:$LINENO: error: Septel API not found under directory $septel_root; use --without-septel" >&5 +echo "$as_me: error: Septel API not found under directory $septel_root; use --without-septel" >&2;} + { (exit 1); exit 1; }; } fi else -$as_echo "#define HAVE_SEPTEL_API 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_SEPTEL_API 1 +_ACEOF fi fi if test "$V_PCAP" = septel -a "$ac_cv_lbl_septel_api" = no; then - as_fn_error $? "Specifying the capture type as 'septel' requires the Septel API to be present; use --with-septel=DIR" "$LINENO" 5 + { { echo "$as_me:$LINENO: error: Specifying the capture type as 'septel' requires the Septel API to be present; use --with-septel=DIR" >&5 +echo "$as_me: error: Specifying the capture type as 'septel' requires the Septel API to be present; use --with-septel=DIR" >&2;} + { (exit 1); exit 1; }; } fi # Check for Myricom SNF support. # Check whether --with-snf was given. -if test "${with_snf+set}" = set; then : +if test "${with_snf+set}" = set; then withval=$with_snf; if test "$withval" = no then # User explicitly doesn't want SNF want_snf=no elif test "$withval" = yes then # User wants SNF support but hasn't specific a directory. want_snf=yes else # User wants SNF support with a specified directory. want_snf=yes snf_root=$withval fi else # # Use Sniffer API if present, otherwise don't # want_snf=ifpresent fi # Check whether --with-snf-includes was given. -if test "${with_snf_includes+set}" = set; then : +if test "${with_snf_includes+set}" = set; then withval=$with_snf_includes; # User wants SNF with specific header directory want_snf=yes snf_include_dir=$withval fi # Check whether --with-snf-libraries was given. -if test "${with_snf_libraries+set}" = set; then : +if test "${with_snf_libraries+set}" = set; then withval=$with_snf_libraries; # User wants SNF with specific lib directory want_snf=yes snf_lib_dir=$withval fi case "$V_PCAP" in bpf|linux|snf) # # We support the Sniffer API if we're on BSD, Linux, or if we're # building a Sniffer-only libpcap. # ;; *) # # If the user explicitly requested Sniffer, tell them it's not # supported. # # If they expressed no preference, don't include it. # if test $want_snf = yes; then - as_fn_error $? "Myricom SNF support only available with 'bpf' 'linux' and 'snf' packet capture types" "$LINENO" 5 + { { echo "$as_me:$LINENO: error: Myricom SNF support only available with 'bpf' 'linux' and 'snf' packet capture types" >&5 +echo "$as_me: error: Myricom SNF support only available with 'bpf' 'linux' and 'snf' packet capture types" >&2;} + { (exit 1); exit 1; }; } elif test $want_snf = yes; then want_snf=no fi ;; esac ac_cv_lbl_snf_api=no if test "$with_snf" != no; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have Myricom Sniffer API" >&5 -$as_echo_n "checking whether we have Myricom Sniffer API... " >&6; } + { echo "$as_me:$LINENO: checking whether we have Myricom Sniffer API" >&5 +echo $ECHO_N "checking whether we have Myricom Sniffer API... $ECHO_C" >&6; } if test -z "$snf_root"; then snf_root=/opt/snf fi if test -z "$snf_include_dir"; then snf_include_dir="$snf_root/include" fi if test -z "$snf_lib_dir"; then snf_lib_dir="$snf_root/lib" fi if test -f "$snf_include_dir/snf.h"; then ac_cv_lbl_snf_api=yes fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_snf_api ($snf_root)" >&5 -$as_echo "$ac_cv_lbl_snf_api ($snf_root)" >&6; } + { echo "$as_me:$LINENO: result: $ac_cv_lbl_snf_api ($snf_root)" >&5 +echo "${ECHO_T}$ac_cv_lbl_snf_api ($snf_root)" >&6; } if test $ac_cv_lbl_snf_api = no; then if test "$want_snf" = yes; then - as_fn_error $? "SNF API headers not found under $snf_include_dir; use --without-snf" "$LINENO" 5 + { { echo "$as_me:$LINENO: error: SNF API headers not found under $snf_include_dir; use --without-snf" >&5 +echo "$as_me: error: SNF API headers not found under $snf_include_dir; use --without-snf" >&2;} + { (exit 1); exit 1; }; } fi else saved_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -L$snf_lib_dir" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for snf_init in -lsnf" >&5 -$as_echo_n "checking for snf_init in -lsnf... " >&6; } -if test "${ac_cv_lib_snf_snf_init+set}" = set; then : - $as_echo_n "(cached) " >&6 + { echo "$as_me:$LINENO: checking for snf_init in -lsnf" >&5 +echo $ECHO_N "checking for snf_init in -lsnf... $ECHO_C" >&6; } +if test "${ac_cv_lib_snf_snf_init+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsnf $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char snf_init (); int main () { return snf_init (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then ac_cv_lib_snf_snf_init=yes else - ac_cv_lib_snf_snf_init=no + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_snf_snf_init=no fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_snf_snf_init" >&5 -$as_echo "$ac_cv_lib_snf_snf_init" >&6; } -if test "x$ac_cv_lib_snf_snf_init" = x""yes; then : +{ echo "$as_me:$LINENO: result: $ac_cv_lib_snf_snf_init" >&5 +echo "${ECHO_T}$ac_cv_lib_snf_snf_init" >&6; } +if test $ac_cv_lib_snf_snf_init = yes; then ac_cv_lbl_snf_api="yes" else ac_cv_lbl_snf_api="no" fi LDFLAGS="$saved_ldflags" if test $ac_cv_lbl_snf_api = no; then if test "$want_snf" = yes; then - as_fn_error $? "SNF API cannot correctly be linked check config.log; use --without-snf" "$LINENO" 5 + { { echo "$as_me:$LINENO: error: SNF API cannot correctly be linked check config.log; use --without-snf" >&5 +echo "$as_me: error: SNF API cannot correctly be linked check config.log; use --without-snf" >&2;} + { (exit 1); exit 1; }; } fi else V_INCLS="$V_INCLS -I$snf_include_dir" LIBS="$LIBS -lsnf" LDFLAGS="$LDFLAGS -L$snf_lib_dir" if test "$V_PCAP" != snf ; then SSRC="pcap-snf.c" fi -$as_echo "#define HAVE_SNF_API 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_SNF_API 1 +_ACEOF fi fi fi if test "$V_PCAP" = snf -a "$ac_cv_lbl_snf_api" = no; then - as_fn_error $? "Specifying the capture type as 'snf' requires the Myricom Sniffer API to be present; use --with-snf=DIR" "$LINENO" 5 + { { echo "$as_me:$LINENO: error: Specifying the capture type as 'snf' requires the Myricom Sniffer API to be present; use --with-snf=DIR" >&5 +echo "$as_me: error: Specifying the capture type as 'snf' requires the Myricom Sniffer API to be present; use --with-snf=DIR" >&2;} + { (exit 1); exit 1; }; } fi # Check whether --with-flex was given. -if test "${with_flex+set}" = set; then : +if test "${with_flex+set}" = set; then withval=$with_flex; fi # Check whether --with-bison was given. -if test "${with_bison+set}" = set; then : +if test "${with_bison+set}" = set; then withval=$with_bison; fi if test "$with_flex" = no ; then V_LEX=lex else for ac_prog in flex do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_V_LEX+set}" = set; then : - $as_echo_n "(cached) " >&6 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_V_LEX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$V_LEX"; then ac_cv_prog_V_LEX="$V_LEX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do + for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_V_LEX="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done - done +done IFS=$as_save_IFS fi fi V_LEX=$ac_cv_prog_V_LEX if test -n "$V_LEX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $V_LEX" >&5 -$as_echo "$V_LEX" >&6; } + { echo "$as_me:$LINENO: result: $V_LEX" >&5 +echo "${ECHO_T}$V_LEX" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } fi test -n "$V_LEX" && break done test -n "$V_LEX" || V_LEX="lex" fi if test "$V_LEX" = flex ; then # The -V flag was added in 2.4 - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for flex 2.4 or higher" >&5 -$as_echo_n "checking for flex 2.4 or higher... " >&6; } - if test "${ac_cv_lbl_flex_v24+set}" = set; then : - $as_echo_n "(cached) " >&6 + { echo "$as_me:$LINENO: checking for flex 2.4 or higher" >&5 +echo $ECHO_N "checking for flex 2.4 or higher... $ECHO_C" >&6; } + if test "${ac_cv_lbl_flex_v24+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else if flex -V >/dev/null 2>&1; then ac_cv_lbl_flex_v24=yes else ac_cv_lbl_flex_v24=no fi fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_flex_v24" >&5 -$as_echo "$ac_cv_lbl_flex_v24" >&6; } + { echo "$as_me:$LINENO: result: $ac_cv_lbl_flex_v24" >&5 +echo "${ECHO_T}$ac_cv_lbl_flex_v24" >&6; } if test $ac_cv_lbl_flex_v24 = no ; then s="2.4 or higher required" - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ignoring obsolete flex executable ($s)" >&5 -$as_echo "$as_me: WARNING: ignoring obsolete flex executable ($s)" >&2;} + { echo "$as_me:$LINENO: WARNING: ignoring obsolete flex executable ($s)" >&5 +echo "$as_me: WARNING: ignoring obsolete flex executable ($s)" >&2;} V_LEX=lex fi fi if test "$with_bison" = no ; then V_YACC=yacc else for ac_prog in bison do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_V_YACC+set}" = set; then : - $as_echo_n "(cached) " >&6 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_V_YACC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$V_YACC"; then ac_cv_prog_V_YACC="$V_YACC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do + for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_V_YACC="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done - done +done IFS=$as_save_IFS fi fi V_YACC=$ac_cv_prog_V_YACC if test -n "$V_YACC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $V_YACC" >&5 -$as_echo "$V_YACC" >&6; } + { echo "$as_me:$LINENO: result: $V_YACC" >&5 +echo "${ECHO_T}$V_YACC" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } fi test -n "$V_YACC" && break done test -n "$V_YACC" || V_YACC="yacc" fi if test "$V_YACC" = bison ; then V_YACC="$V_YACC -y" fi if test "$V_LEX" != lex -a "$V_YACC" = yacc -o "$V_LEX" = lex -a "$V_YACC" != yacc ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: don't have both flex and bison; reverting to lex/yacc" >&5 -$as_echo "$as_me: WARNING: don't have both flex and bison; reverting to lex/yacc" >&2;} + { echo "$as_me:$LINENO: WARNING: don't have both flex and bison; reverting to lex/yacc" >&5 +echo "$as_me: WARNING: don't have both flex and bison; reverting to lex/yacc" >&2;} V_LEX=lex V_YACC=yacc fi if test "$V_LEX" = flex -a -n "pcap_" ; then V_LEX="$V_LEX -Ppcap_" V_YACC="$V_YACC -p pcap_" + else + +cat >>confdefs.h <<\_ACEOF +#define NEED_YYPARSE_WRAPPER 1 +_ACEOF + fi 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. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for capable lex" >&5 -$as_echo_n "checking for capable lex... " >&6; } -if test "${tcpdump_cv_capable_lex+set}" = set; then : - $as_echo_n "(cached) " >&6 + { echo "$as_me:$LINENO: checking for capable lex" >&5 +echo $ECHO_N "checking for capable lex... $ECHO_C" >&6; } +if test "${tcpdump_cv_capable_lex+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else if lex -t scanner.l > /dev/null 2>&1; then tcpdump_cv_capable_lex=yes else tcpdump_cv_capable_lex=insufficient fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcpdump_cv_capable_lex" >&5 -$as_echo "$tcpdump_cv_capable_lex" >&6; } +{ echo "$as_me:$LINENO: result: $tcpdump_cv_capable_lex" >&5 +echo "${ECHO_T}$tcpdump_cv_capable_lex" >&6; } if test $tcpdump_cv_capable_lex = insufficient ; then - as_fn_error $? "Your operating system's lex is insufficient to compile + { { echo "$as_me:$LINENO: error: Your operating system's lex is insufficient to compile libpcap. flex is a lex replacement that has many advantages, including being able to compile libpcap. For more information, see - http://www.gnu.org/software/flex/flex.html ." "$LINENO" 5 + http://www.gnu.org/software/flex/flex.html ." >&5 +echo "$as_me: error: Your operating system's lex is insufficient to compile + libpcap. flex is a lex replacement that has many advantages, including + being able to compile libpcap. For more information, see + http://www.gnu.org/software/flex/flex.html ." >&2;} + { (exit 1); exit 1; }; } fi fi # # Assume, by default, no support for shared libraries and V7/BSD convention # for man pages (file formats in section 5, miscellaneous info in section 7). # Individual cases can override this. # DYEXT="none" MAN_FILE_FORMATS=5 MAN_MISC_INFO=7 case "$host_os" in aix*) -$as_echo "#define _SUN 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define _SUN 1 +_ACEOF # # AIX makes it fun to build shared and static libraries, # because they're *both* ".a" archive libraries. We # build the static library for the benefit of the traditional # scheme of building libpcap and tcpdump in subdirectories of # the same directory, with tcpdump statically linked with the # libpcap in question, but we also build a shared library as # "libpcap.shareda" and install *it*, rather than the static # library, as "libpcap.a". # DYEXT="shareda" case "$V_PCAP" in dlpi) # # If we're using DLPI, applications will need to # use /lib/pse.exp if present, as we use the # STREAMS routines. # pseexe="/lib/pse.exp" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $pseexe" >&5 -$as_echo_n "checking for $pseexe... " >&6; } + { echo "$as_me:$LINENO: checking for $pseexe" >&5 +echo $ECHO_N "checking for $pseexe... $ECHO_C" >&6; } if test -f $pseexe ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } LIBS="-I:$pseexe" fi ;; bpf) # # If we're using BPF, we need "-lodm" and "-lcfg", as # we use them to load the BPF module. # LIBS="-lodm -lcfg" ;; esac ;; darwin*) DYEXT="dylib" V_CCOPT="$V_CCOPT -fno-common" # Check whether --enable-universal was given. -if test "${enable_universal+set}" = set; then : +if test "${enable_universal+set}" = set; then enableval=$enable_universal; fi if test "$enable_universal" != "no"; then case "$host_os" in darwin9.*) # # Leopard. Build for 32-bit PowerPC, 64-bit # PowerPC, x86, and x86-64, with 32-bit PowerPC # first. (That's what Apple does.) # V_CCOPT="$V_CCOPT -arch ppc -arch ppc64 -arch i386 -arch x86_64" LDFLAGS="$LDFLAGS -arch ppc -arch ppc64 -arch i386 -arch x86_64" ;; darwin10.*) # # Snow Leopard. Build for x86-64, x86, and # 32-bit PowerPC, with x86-64 first. (That's # what Apple does, even though Snow Leopard # doesn't run on PPC, so PPC libpcap runs under # Rosetta, and Rosetta doesn't support BPF # ioctls, so PPC programs can't do live # captures.) # V_CCOPT="$V_CCOPT -arch x86_64 -arch i386 -arch ppc" LDFLAGS="$LDFLAGS -arch x86_64 -arch i386 -arch ppc" ;; darwin11.*) # # Lion. Build for x86-64 and x86, with x86-64 # first. (That's probably what Apple does, # given that Rosetta is gone.) # V_CCOPT="$V_CCOPT -arch x86_64 -arch i386" LDFLAGS="$LDFLAGS -arch x86_64 -arch i386" ;; esac fi ;; hpux9*) -$as_echo "#define HAVE_HPUX9 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_HPUX9 1 +_ACEOF # # Use System V conventions for man pages. # MAN_FILE_FORMATS=4 MAN_MISC_INFO=5 ;; hpux10.0*) # # Use System V conventions for man pages. # MAN_FILE_FORMATS=4 MAN_MISC_INFO=5 ;; hpux10.1*) # # Use System V conventions for man pages. # MAN_FILE_FORMATS=4 MAN_MISC_INFO=5 ;; hpux*) -$as_echo "#define HAVE_HPUX10_20_OR_LATER 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_HPUX10_20_OR_LATER 1 +_ACEOF if test "`uname -m`" = "ia64"; then DYEXT="so" else DYEXT="sl" fi # # "-b" builds a shared library; "+h" sets the soname. # SHLIB_OPT="-b" SONAME_OPT="+h" # # Use System V conventions for man pages. # MAN_FILE_FORMATS=4 MAN_MISC_INFO=5 ;; irix*) # # Use System V conventions for man pages. # MAN_FILE_FORMATS=4 MAN_MISC_INFO=5 ;; linux*|freebsd*|netbsd*|openbsd*|dragonfly*|kfreebsd*|gnu*) DYEXT="so" # # Compiler assumed to be GCC; run-time linker may require a -R # flag. # if test "$libdir" != "/usr/lib"; then V_RFLAGS=-Wl,-R$libdir fi ;; osf*) DYEXT="so" # # Use System V conventions for man pages. # MAN_FILE_FORMATS=4 MAN_MISC_INFO=5 ;; sinix*) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if SINIX compiler defines sinix" >&5 -$as_echo_n "checking if SINIX compiler defines sinix... " >&6; } - if test "${ac_cv_cc_sinix_defined+set}" = set; then : - $as_echo_n "(cached) " >&6 + { echo "$as_me:$LINENO: checking if SINIX compiler defines sinix" >&5 +echo $ECHO_N "checking if SINIX compiler defines sinix... $ECHO_C" >&6; } + if test "${ac_cv_cc_sinix_defined+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { int i = sinix; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_cc_sinix_defined=yes else - ac_cv_cc_sinix_defined=no + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_cc_sinix_defined=no fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cc_sinix_defined" >&5 -$as_echo "$ac_cv_cc_sinix_defined" >&6; } + { echo "$as_me:$LINENO: result: $ac_cv_cc_sinix_defined" >&5 +echo "${ECHO_T}$ac_cv_cc_sinix_defined" >&6; } if test $ac_cv_cc_sinix_defined = no ; then -$as_echo "#define sinix 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define sinix 1 +_ACEOF fi ;; solaris*) -$as_echo "#define HAVE_SOLARIS 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_SOLARIS 1 +_ACEOF DYEXT="so" # # Use System V conventions for man pages. # MAN_FILE_FORMATS=4 MAN_MISC_INFO=5 ;; esac +# Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then + enableval=$enable_shared; +fi + +test "x$enable_shared" = "xno" && DYEXT="none" + if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_RANLIB+set}" = set; then : - $as_echo_n "(cached) " >&6 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do + for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done - done +done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 -$as_echo "$RANLIB" >&6; } + { echo "$as_me:$LINENO: result: $RANLIB" >&5 +echo "${ECHO_T}$RANLIB" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then : - $as_echo_n "(cached) " >&6 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do + for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_RANLIB="ranlib" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done - done +done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 -$as_echo "$ac_ct_RANLIB" >&6; } + { echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 +echo "${ECHO_T}$ac_ct_RANLIB" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. set dummy ${ac_tool_prefix}ar; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_AR+set}" = set; then : - $as_echo_n "(cached) " >&6 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_AR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do + for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_AR="${ac_tool_prefix}ar" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done - done +done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 -$as_echo "$AR" >&6; } + { echo "$as_me:$LINENO: result: $AR" >&5 +echo "${ECHO_T}$AR" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } fi fi if test -z "$ac_cv_prog_AR"; then ac_ct_AR=$AR # Extract the first word of "ar", so it can be a program name with args. set dummy ar; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_AR+set}" = set; then : - $as_echo_n "(cached) " >&6 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_AR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do + for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_AR="ar" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done - done +done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 -$as_echo "$ac_ct_AR" >&6; } + { echo "$as_me:$LINENO: result: $ac_ct_AR" >&5 +echo "${ECHO_T}$ac_ct_AR" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } fi if test "x$ac_ct_AR" = x; then AR="" else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi else AR="$ac_cv_prog_AR" fi rm -f os-proto.h if test "${LBL_CFLAGS+set}" = set; then V_CCOPT="$V_CCOPT ${LBL_CFLAGS}" fi if test -f .devel ; then if test "$GCC" = yes ; then if test "${LBL_CFLAGS+set}" != set; then if test "$ac_cv_prog_cc_g" = yes ; then V_CCOPT="-g $V_CCOPT" fi V_CCOPT="$V_CCOPT -Wall" if test $ac_cv_lbl_gcc_vers -gt 1 ; then V_CCOPT="$V_CCOPT -Wmissing-prototypes -Wstrict-prototypes" fi fi else case "$host_os" in irix6*) V_CCOPT="$V_CCOPT -n32" ;; *) ;; esac fi os=`echo $host_os | sed -e 's/\([0-9][0-9]*\)[^0-9].*$/\1/'` name="lbl/os-$os.h" if test -f $name ; then ln -s $name os-proto.h -$as_echo "#define HAVE_OS_PROTO_H 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_OS_PROTO_H 1 +_ACEOF else - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: can't find $name" >&5 -$as_echo "$as_me: WARNING: can't find $name" >&2;} + { echo "$as_me:$LINENO: WARNING: can't find $name" >&5 +echo "$as_me: WARNING: can't find $name" >&2;} fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if sockaddr struct has the sa_len member" >&5 -$as_echo_n "checking if sockaddr struct has the sa_len member... " >&6; } - if test "${ac_cv_lbl_sockaddr_has_sa_len+set}" = set; then : - $as_echo_n "(cached) " >&6 +{ echo "$as_me:$LINENO: checking if sockaddr struct has the sa_len member" >&5 +echo $ECHO_N "checking if sockaddr struct has the sa_len member... $ECHO_C" >&6; } + if test "${ac_cv_lbl_sockaddr_has_sa_len+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ # include # include int main () { u_int i = sizeof(((struct sockaddr *)0)->sa_len) ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_lbl_sockaddr_has_sa_len=yes else - ac_cv_lbl_sockaddr_has_sa_len=no + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lbl_sockaddr_has_sa_len=no fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_sockaddr_has_sa_len" >&5 -$as_echo "$ac_cv_lbl_sockaddr_has_sa_len" >&6; } + { echo "$as_me:$LINENO: result: $ac_cv_lbl_sockaddr_has_sa_len" >&5 +echo "${ECHO_T}$ac_cv_lbl_sockaddr_has_sa_len" >&6; } if test $ac_cv_lbl_sockaddr_has_sa_len = yes ; then -$as_echo "#define HAVE_SOCKADDR_SA_LEN 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_SOCKADDR_SA_LEN 1 +_ACEOF fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if sockaddr_storage struct exists" >&5 -$as_echo_n "checking if sockaddr_storage struct exists... " >&6; } - if test "${ac_cv_lbl_has_sockaddr_storage+set}" = set; then : - $as_echo_n "(cached) " >&6 +{ echo "$as_me:$LINENO: checking if sockaddr_storage struct exists" >&5 +echo $ECHO_N "checking if sockaddr_storage struct exists... $ECHO_C" >&6; } + if test "${ac_cv_lbl_has_sockaddr_storage+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ # include # include int main () { u_int i = sizeof (struct sockaddr_storage) ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_lbl_has_sockaddr_storage=yes else - ac_cv_lbl_has_sockaddr_storage=no + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lbl_has_sockaddr_storage=no fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_has_sockaddr_storage" >&5 -$as_echo "$ac_cv_lbl_has_sockaddr_storage" >&6; } + { echo "$as_me:$LINENO: result: $ac_cv_lbl_has_sockaddr_storage" >&5 +echo "${ECHO_T}$ac_cv_lbl_has_sockaddr_storage" >&6; } if test $ac_cv_lbl_has_sockaddr_storage = yes ; then -$as_echo "#define HAVE_SOCKADDR_STORAGE 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_SOCKADDR_STORAGE 1 +_ACEOF fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if dl_hp_ppa_info_t struct has dl_module_id_1 member" >&5 -$as_echo_n "checking if dl_hp_ppa_info_t struct has dl_module_id_1 member... " >&6; } - if test "${ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1+set}" = set; then : - $as_echo_n "(cached) " >&6 +{ echo "$as_me:$LINENO: checking if dl_hp_ppa_info_t struct has dl_module_id_1 member" >&5 +echo $ECHO_N "checking if dl_hp_ppa_info_t struct has dl_module_id_1 member... $ECHO_C" >&6; } + if test "${ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ # include # include # include int main () { u_int i = sizeof(((dl_hp_ppa_info_t *)0)->dl_module_id_1) ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1=yes else - ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1=no + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1=no fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1" >&5 -$as_echo "$ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1" >&6; } + { echo "$as_me:$LINENO: result: $ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1" >&5 +echo "${ECHO_T}$ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1" >&6; } if test $ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1 = yes ; then -$as_echo "#define HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1 1 +_ACEOF fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if unaligned accesses fail" >&5 -$as_echo_n "checking if unaligned accesses fail... " >&6; } - if test "${ac_cv_lbl_unaligned_fail+set}" = set; then : - $as_echo_n "(cached) " >&6 +{ echo "$as_me:$LINENO: checking if unaligned accesses fail" >&5 +echo $ECHO_N "checking if unaligned accesses fail... $ECHO_C" >&6; } + if test "${ac_cv_lbl_unaligned_fail+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else case "$host_cpu" in # # These are CPU types where: # # the CPU faults on an unaligned access, but at least some # OSes that support that CPU catch the fault and simulate # the unaligned access (e.g., Alpha/{Digital,Tru64} UNIX) - # the simulation is slow, so we don't want to use it; # # the CPU, I infer (from the old # # XXX: should also check that they don't do weird things (like on arm) # # comment) doesn't fault on unaligned accesses, but doesn't # do a normal unaligned fetch, either (e.g., presumably, ARM); # # for whatever reason, the test program doesn't work # (this has been claimed to be the case for several of those # CPUs - I don't know what the problem is; the problem # was reported as "the test program dumps core" for SuperH, # but that's what the test program is *supposed* to do - # it dumps core before it writes anything, so the test # for an empty output file should find an empty output # file and conclude that unaligned accesses don't work). # # This run-time test won't work if you're cross-compiling, so # in order to support cross-compiling for a particular CPU, # we have to wire in the list of CPU types anyway, as far as # I know, so perhaps we should just have a set of CPUs on # which we know it doesn't work, a set of CPUs on which we # know it does work, and have the script just fail on other # cpu types and update it when such a failure occurs. # alpha*|arm*|bfin*|hp*|mips*|sh*|sparc*|ia64|nv1) ac_cv_lbl_unaligned_fail=yes ;; *) cat >conftest.c < # include # include unsigned char a[5] = { 1, 2, 3, 4, 5 }; main() { unsigned int i; pid_t pid; int status; /* avoid "core dumped" message */ pid = fork(); if (pid < 0) exit(2); if (pid > 0) { /* parent */ pid = waitpid(pid, &status, 0); if (pid < 0) exit(3); exit(!WIFEXITED(status)); } /* child */ i = *(unsigned int *)&a[1]; printf("%d\n", i); exit(0); } EOF ${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS \ conftest.c $LIBS >/dev/null 2>&1 if test ! -x conftest ; then ac_cv_lbl_unaligned_fail=yes else ./conftest >conftest.out if test ! -s conftest.out ; then ac_cv_lbl_unaligned_fail=yes else ac_cv_lbl_unaligned_fail=no fi fi rm -f -r conftest* core core.conftest ;; esac fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_unaligned_fail" >&5 -$as_echo "$ac_cv_lbl_unaligned_fail" >&6; } + { echo "$as_me:$LINENO: result: $ac_cv_lbl_unaligned_fail" >&5 +echo "${ECHO_T}$ac_cv_lbl_unaligned_fail" >&6; } if test $ac_cv_lbl_unaligned_fail = yes ; then -$as_echo "#define LBL_ALIGN 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define LBL_ALIGN 1 +_ACEOF fi # # Makefile.in includes rules to generate version.h, so we assume # that it will be generated if autoconf is used. # -$as_echo "#define HAVE_VERSION_H 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_VERSION_H 1 +_ACEOF rm -f net ln -s ${srcdir}/bpf/net net -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for USB sniffing support" >&5 -$as_echo_n "checking for USB sniffing support... " >&6; } +{ echo "$as_me:$LINENO: checking for USB sniffing support" >&5 +echo $ECHO_N "checking for USB sniffing support... $ECHO_C" >&6; } case "$host_os" in linux*) -$as_echo "#define PCAP_SUPPORT_USB 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define PCAP_SUPPORT_USB 1 +_ACEOF USB_SRC=pcap-usb-linux.c - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } ac_usb_dev_name=`udevinfo -q name -p /sys/class/usb_device/usbmon 2>/dev/null` if test $? -ne 0 ; then ac_usb_dev_name="usbmon" fi cat >>confdefs.h <<_ACEOF #define LINUX_USB_MON_DEV "/dev/$ac_usb_dev_name" _ACEOF - { $as_echo "$as_me:${as_lineno-$LINENO}: Device for USB sniffing is /dev/$ac_usb_dev_name" >&5 -$as_echo "$as_me: Device for USB sniffing is /dev/$ac_usb_dev_name" >&6;} + { echo "$as_me:$LINENO: Device for USB sniffing is /dev/$ac_usb_dev_name" >&5 +echo "$as_me: Device for USB sniffing is /dev/$ac_usb_dev_name" >&6;} # # Do we have a version of available? # If so, we might need it for . # - for ac_header in linux/compiler.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "linux/compiler.h" "ac_cv_header_linux_compiler_h" "$ac_includes_default" -if test "x$ac_cv_header_linux_compiler_h" = x""yes; then : + +for ac_header in linux/compiler.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF -#define HAVE_LINUX_COMPILER_H 1 +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done if test "$ac_cv_header_linux_compiler_h" = yes; then # # Yes - include it when testing for . # - for ac_header in linux/usbdevice_fs.h -do : - ac_fn_c_check_header_compile "$LINENO" "linux/usbdevice_fs.h" "ac_cv_header_linux_usbdevice_fs_h" "#include -" -if test "x$ac_cv_header_linux_usbdevice_fs_h" = x""yes; then : + +for ac_header in linux/usbdevice_fs.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF -#define HAVE_LINUX_USBDEVICE_FS_H 1 +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done else - for ac_header in linux/usbdevice_fs.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "linux/usbdevice_fs.h" "ac_cv_header_linux_usbdevice_fs_h" "$ac_includes_default" -if test "x$ac_cv_header_linux_usbdevice_fs_h" = x""yes; then : + +for ac_header in linux/usbdevice_fs.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF -#define HAVE_LINUX_USBDEVICE_FS_H 1 +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done fi if test "$ac_cv_header_linux_usbdevice_fs_h" = yes; then # # OK, does it define bRequestType? Older versions of the kernel # define fields with names like "requesttype, "request", and # "value", rather than "bRequestType", "bRequest", and # "wValue". # - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if usbdevfs_ctrltransfer struct has bRequestType member" >&5 -$as_echo_n "checking if usbdevfs_ctrltransfer struct has bRequestType member... " >&6; } - if test "${ac_cv_usbdevfs_ctrltransfer_has_bRequestType+set}" = set; then : - $as_echo_n "(cached) " >&6 + { echo "$as_me:$LINENO: checking if usbdevfs_ctrltransfer struct has bRequestType member" >&5 +echo $ECHO_N "checking if usbdevfs_ctrltransfer struct has bRequestType member... $ECHO_C" >&6; } + if test "${ac_cv_usbdevfs_ctrltransfer_has_bRequestType+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #ifdef HAVE_SYS_BITYPES_H #include #endif #ifdef HAVE_LINUX_COMPILER_H #include #endif #include int main () { u_int i = sizeof(((struct usbdevfs_ctrltransfer *)0)->bRequestType) ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_usbdevfs_ctrltransfer_has_bRequestType=yes else - ac_cv_usbdevfs_ctrltransfer_has_bRequestType=no + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_usbdevfs_ctrltransfer_has_bRequestType=no fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_usbdevfs_ctrltransfer_has_bRequestType" >&5 -$as_echo "$ac_cv_usbdevfs_ctrltransfer_has_bRequestType" >&6; } + { echo "$as_me:$LINENO: result: $ac_cv_usbdevfs_ctrltransfer_has_bRequestType" >&5 +echo "${ECHO_T}$ac_cv_usbdevfs_ctrltransfer_has_bRequestType" >&6; } if test $ac_cv_usbdevfs_ctrltransfer_has_bRequestType = yes ; then -$as_echo "#define HAVE_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define HAVE_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE 1 +_ACEOF fi fi ;; *) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } ;; esac -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the platform could support netfilter sniffing" >&5 -$as_echo_n "checking whether the platform could support netfilter sniffing... " >&6; } +{ echo "$as_me:$LINENO: checking whether the platform could support netfilter sniffing" >&5 +echo $ECHO_N "checking whether the platform could support netfilter sniffing... $ECHO_C" >&6; } case "$host_os" in linux*) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } # # Life's too short to deal with trying to get this to compile # if you don't get the right types defined with # __KERNEL_STRICT_NAMES getting defined by some other include. # # Check whether the includes Just Work. If not, don't turn on # netfilter support. # - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we can compile the netfilter support" >&5 -$as_echo_n "checking whether we can compile the netfilter support... " >&6; } - if test "${ac_cv_netfilter_can_compile+set}" = set; then : - $as_echo_n "(cached) " >&6 + { echo "$as_me:$LINENO: checking whether we can compile the netfilter support" >&5 +echo $ECHO_N "checking whether we can compile the netfilter support... $ECHO_C" >&6; } + if test "${ac_cv_netfilter_can_compile+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include +#include #include #include +#include #include #include +#include int main () { ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_netfilter_can_compile=yes else - ac_cv_netfilter_can_compile=no + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_netfilter_can_compile=no fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_netfilter_can_compile" >&5 -$as_echo "$ac_cv_netfilter_can_compile" >&6; } + { echo "$as_me:$LINENO: result: $ac_cv_netfilter_can_compile" >&5 +echo "${ECHO_T}$ac_cv_netfilter_can_compile" >&6; } if test $ac_cv_netfilter_can_compile = yes ; then -$as_echo "#define PCAP_SUPPORT_NETFILTER 1" >>confdefs.h +cat >>confdefs.h <<\_ACEOF +#define PCAP_SUPPORT_NETFILTER 1 +_ACEOF NETFILTER_SRC=pcap-netfilter-linux.c fi ;; *) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } ;; esac # Check whether --enable-bluetooth was given. -if test "${enable_bluetooth+set}" = set; then : +if test "${enable_bluetooth+set}" = set; then enableval=$enable_bluetooth; else enable_bluetooth=yes fi if test "x$enable_bluetooth" != "xno" ; then case "$host_os" in linux*) - ac_fn_c_check_header_mongrel "$LINENO" "bluetooth/bluetooth.h" "ac_cv_header_bluetooth_bluetooth_h" "$ac_includes_default" -if test "x$ac_cv_header_bluetooth_bluetooth_h" = x""yes; then : + if test "${ac_cv_header_bluetooth_bluetooth_h+set}" = set; then + { echo "$as_me:$LINENO: checking for bluetooth/bluetooth.h" >&5 +echo $ECHO_N "checking for bluetooth/bluetooth.h... $ECHO_C" >&6; } +if test "${ac_cv_header_bluetooth_bluetooth_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_bluetooth_bluetooth_h" >&5 +echo "${ECHO_T}$ac_cv_header_bluetooth_bluetooth_h" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking bluetooth/bluetooth.h usability" >&5 +echo $ECHO_N "checking bluetooth/bluetooth.h usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + ac_header_compiler=no +fi -$as_echo "#define PCAP_SUPPORT_BT 1" >>confdefs.h +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } +# Is the header present? +{ echo "$as_me:$LINENO: checking bluetooth/bluetooth.h presence" >&5 +echo $ECHO_N "checking bluetooth/bluetooth.h presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: bluetooth/bluetooth.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: bluetooth/bluetooth.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: bluetooth/bluetooth.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: bluetooth/bluetooth.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: bluetooth/bluetooth.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: bluetooth/bluetooth.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: bluetooth/bluetooth.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: bluetooth/bluetooth.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: bluetooth/bluetooth.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: bluetooth/bluetooth.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: bluetooth/bluetooth.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: bluetooth/bluetooth.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: bluetooth/bluetooth.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: bluetooth/bluetooth.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: bluetooth/bluetooth.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: bluetooth/bluetooth.h: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for bluetooth/bluetooth.h" >&5 +echo $ECHO_N "checking for bluetooth/bluetooth.h... $ECHO_C" >&6; } +if test "${ac_cv_header_bluetooth_bluetooth_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_bluetooth_bluetooth_h=$ac_header_preproc +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_bluetooth_bluetooth_h" >&5 +echo "${ECHO_T}$ac_cv_header_bluetooth_bluetooth_h" >&6; } + +fi +if test $ac_cv_header_bluetooth_bluetooth_h = yes; then + + +cat >>confdefs.h <<\_ACEOF +#define PCAP_SUPPORT_BT 1 +_ACEOF + BT_SRC=pcap-bt-linux.c - { $as_echo "$as_me:${as_lineno-$LINENO}: Bluetooth sniffing is supported" >&5 -$as_echo "$as_me: Bluetooth sniffing is supported" >&6;} + { echo "$as_me:$LINENO: Bluetooth sniffing is supported" >&5 +echo "$as_me: Bluetooth sniffing is supported" >&6;} + # + # OK, does struct sockaddr_hci have an hci_channel + # member? + # + { echo "$as_me:$LINENO: checking if struct sockaddr_hci has hci_channel member" >&5 +echo $ECHO_N "checking if struct sockaddr_hci has hci_channel member... $ECHO_C" >&6; } + if test "${ac_cv_lbl_sockaddr_hci_has_hci_channel+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - { $as_echo "$as_me:${as_lineno-$LINENO}: Bluetooth sniffing is not supported; install bluez-lib devel to enable it" >&5 -$as_echo "$as_me: Bluetooth sniffing is not supported; install bluez-lib devel to enable it" >&6;} + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +int +main () +{ +u_int i = sizeof(((struct sockaddr_hci *)0)->hci_channel) + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_lbl_sockaddr_hci_has_hci_channel=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lbl_sockaddr_hci_has_hci_channel=no fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + { echo "$as_me:$LINENO: result: $ac_cv_lbl_sockaddr_hci_has_hci_channel" >&5 +echo "${ECHO_T}$ac_cv_lbl_sockaddr_hci_has_hci_channel" >&6; } + if test $ac_cv_lbl_sockaddr_hci_has_hci_channel = yes ; then + +cat >>confdefs.h <<\_ACEOF +#define SOCKADDR_HCI_HAS_HCI_CHANNEL +_ACEOF + + fi + +else + { echo "$as_me:$LINENO: Bluetooth sniffing is not supported; install bluez-lib devel to enable it" >&5 +echo "$as_me: Bluetooth sniffing is not supported; install bluez-lib devel to enable it" >&6;} + +fi + + ;; *) - { $as_echo "$as_me:${as_lineno-$LINENO}: no Bluetooth sniffing support implemented for $host_os" >&5 -$as_echo "$as_me: no Bluetooth sniffing support implemented for $host_os" >&6;} + { echo "$as_me:$LINENO: no Bluetooth sniffing support implemented for $host_os" >&5 +echo "$as_me: no Bluetooth sniffing support implemented for $host_os" >&6;} ;; esac fi # Check whether --enable-canusb was given. -if test "${enable_canusb+set}" = set; then : - enableval=$enable_canusb; enable_canusb=yes +if test "${enable_canusb+set}" = set; then + enableval=$enable_canusb; +else + enable_canusb=yes fi if test "x$enable_canusb" != "xno" ; then case "$host_os" in linux*) - ac_fn_c_check_header_mongrel "$LINENO" "libusb-1.0/libusb.h" "ac_cv_header_libusb_1_0_libusb_h" "$ac_includes_default" -if test "x$ac_cv_header_libusb_1_0_libusb_h" = x""yes; then : + if test "${ac_cv_header_libusb_1_0_libusb_h+set}" = set; then + { echo "$as_me:$LINENO: checking for libusb-1.0/libusb.h" >&5 +echo $ECHO_N "checking for libusb-1.0/libusb.h... $ECHO_C" >&6; } +if test "${ac_cv_header_libusb_1_0_libusb_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_libusb_1_0_libusb_h" >&5 +echo "${ECHO_T}$ac_cv_header_libusb_1_0_libusb_h" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking libusb-1.0/libusb.h usability" >&5 +echo $ECHO_N "checking libusb-1.0/libusb.h usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + ac_header_compiler=no +fi -$as_echo "#define PCAP_SUPPORT_CANUSB 1" >>confdefs.h +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } +# Is the header present? +{ echo "$as_me:$LINENO: checking libusb-1.0/libusb.h presence" >&5 +echo $ECHO_N "checking libusb-1.0/libusb.h presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: libusb-1.0/libusb.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: libusb-1.0/libusb.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: libusb-1.0/libusb.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: libusb-1.0/libusb.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: libusb-1.0/libusb.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: libusb-1.0/libusb.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: libusb-1.0/libusb.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: libusb-1.0/libusb.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: libusb-1.0/libusb.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: libusb-1.0/libusb.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: libusb-1.0/libusb.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: libusb-1.0/libusb.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: libusb-1.0/libusb.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: libusb-1.0/libusb.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: libusb-1.0/libusb.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: libusb-1.0/libusb.h: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for libusb-1.0/libusb.h" >&5 +echo $ECHO_N "checking for libusb-1.0/libusb.h... $ECHO_C" >&6; } +if test "${ac_cv_header_libusb_1_0_libusb_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_libusb_1_0_libusb_h=$ac_header_preproc +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_libusb_1_0_libusb_h" >&5 +echo "${ECHO_T}$ac_cv_header_libusb_1_0_libusb_h" >&6; } + +fi +if test $ac_cv_header_libusb_1_0_libusb_h = yes; then + + +cat >>confdefs.h <<\_ACEOF +#define PCAP_SUPPORT_CANUSB 1 +_ACEOF + CANUSB_SRC=pcap-canusb-linux.c - LIBS="-lusb-1.0 $LIBS" - { $as_echo "$as_me:${as_lineno-$LINENO}: canusb sniffing is supported" >&5 -$as_echo "$as_me: canusb sniffing is supported" >&6;} + LIBS="-lusb-1.0 -lpthread $LIBS" + { echo "$as_me:$LINENO: canusb sniffing is supported" >&5 +echo "$as_me: canusb sniffing is supported" >&6;} else - { $as_echo "$as_me:${as_lineno-$LINENO}: canusb sniffing is not supported; install libusb1.0 lib devel to enable it" >&5 -$as_echo "$as_me: canusb sniffing is not supported; install libusb1.0 lib devel to enable it" >&6;} + { echo "$as_me:$LINENO: canusb sniffing is not supported; install libusb1.0 lib devel to enable it" >&5 +echo "$as_me: canusb sniffing is not supported; install libusb1.0 lib devel to enable it" >&6;} fi ;; *) - { $as_echo "$as_me:${as_lineno-$LINENO}: no canusb support implemented for $host_os" >&5 -$as_echo "$as_me: no canusb support implemented for $host_os" >&6;} + { echo "$as_me:$LINENO: no canusb support implemented for $host_os" >&5 +echo "$as_me: no canusb support implemented for $host_os" >&6;} ;; esac fi # Check whether --enable-can was given. -if test "${enable_can+set}" = set; then : +if test "${enable_can+set}" = set; then enableval=$enable_can; else enable_can=yes fi if test "x$enable_can" != "xno" ; then case "$host_os" in linux*) - ac_fn_c_check_header_compile "$LINENO" "linux/can.h" "ac_cv_header_linux_can_h" "#include + { echo "$as_me:$LINENO: checking for linux/can.h" >&5 +echo $ECHO_N "checking for linux/can.h... $ECHO_C" >&6; } +if test "${ac_cv_header_linux_can_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include -" -if test "x$ac_cv_header_linux_can_h" = x""yes; then : -$as_echo "#define PCAP_SUPPORT_CAN 1" >>confdefs.h +#include +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_linux_can_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + ac_cv_header_linux_can_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_linux_can_h" >&5 +echo "${ECHO_T}$ac_cv_header_linux_can_h" >&6; } +if test $ac_cv_header_linux_can_h = yes; then + +cat >>confdefs.h <<\_ACEOF +#define PCAP_SUPPORT_CAN 1 +_ACEOF + CAN_SRC=pcap-can-linux.c - { $as_echo "$as_me:${as_lineno-$LINENO}: CAN sniffing is supported" >&5 -$as_echo "$as_me: CAN sniffing is supported" >&6;} + { echo "$as_me:$LINENO: CAN sniffing is supported" >&5 +echo "$as_me: CAN sniffing is supported" >&6;} else - { $as_echo "$as_me:${as_lineno-$LINENO}: CAN sniffing is not supported" >&5 -$as_echo "$as_me: CAN sniffing is not supported" >&6;} + { echo "$as_me:$LINENO: CAN sniffing is not supported" >&5 +echo "$as_me: CAN sniffing is not supported" >&6;} fi ;; *) - { $as_echo "$as_me:${as_lineno-$LINENO}: no CAN sniffing support implemented for $host_os" >&5 -$as_echo "$as_me: no CAN sniffing support implemented for $host_os" >&6;} + { echo "$as_me:$LINENO: no CAN sniffing support implemented for $host_os" >&5 +echo "$as_me: no CAN sniffing support implemented for $host_os" >&6;} ;; esac fi case "$host_os" in linux*) - for ac_header in linux/net_tstamp.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "linux/net_tstamp.h" "ac_cv_header_linux_net_tstamp_h" "$ac_includes_default" -if test "x$ac_cv_header_linux_net_tstamp_h" = x""yes; then : + +for ac_header in linux/net_tstamp.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF -#define HAVE_LINUX_NET_TSTAMP_H 1 +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done ;; *) - { $as_echo "$as_me:${as_lineno-$LINENO}: no hardware timestamp support implemented for $host_os" >&5 -$as_echo "$as_me: no hardware timestamp support implemented for $host_os" >&6;} + { echo "$as_me:$LINENO: no hardware timestamp support implemented for $host_os" >&5 +echo "$as_me: no hardware timestamp support implemented for $host_os" >&6;} ;; esac # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. -# Reject install programs that cannot install multiple files. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 -$as_echo_n "checking for a BSD-compatible install... " >&6; } +{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; } if test -z "$INSTALL"; then -if test "${ac_cv_path_install+set}" = set; then : - $as_echo_n "(cached) " >&6 +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - # Account for people who put trailing slashes in PATH elements. -case $as_dir/ in #(( - ./ | .// | /[cC]/* | \ + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ - ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else - rm -rf conftest.one conftest.two conftest.dir - echo one > conftest.one - echo two > conftest.two - mkdir conftest.dir - if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && - test -s conftest.one && test -s conftest.two && - test -s conftest.dir/conftest.one && - test -s conftest.dir/conftest.two - then - ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" - break 3 - fi + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 fi fi done done ;; esac - - done +done IFS=$as_save_IFS -rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 -$as_echo "$INSTALL" >&6; } +{ echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' ac_config_headers="$ac_config_headers config.h" ac_config_files="$ac_config_files Makefile pcap-filter.manmisc pcap-linktype.manmisc pcap-tstamp.manmisc pcap-savefile.manfile pcap.3pcap pcap_compile.3pcap pcap_datalink.3pcap pcap_dump_open.3pcap pcap_list_datalinks.3pcap pcap_list_tstamp_types.3pcap pcap_open_dead.3pcap pcap_open_offline.3pcap pcap_set_tstamp_type.3pcap" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( - *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 -$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 +echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( - BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( - *) { eval $ac_var=; unset $ac_var;} ;; + *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) - # `set' does not quote correctly, so add quotes: double-quote - # substitution turns \\\\ into \\, and sed turns \\ into \. + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && - { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 -$as_echo "$as_me: updating cache $cache_file" >&6;} + { echo "$as_me:$LINENO: updating cache $cache_file" >&5 +echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else - { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 -$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 +echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= -U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' - ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + ac_i=`echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. - as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" - as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' + ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : ${CONFIG_STATUS=./config.status} -ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" -{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 -$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} -as_write_fail=0 -cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false - SHELL=\${CONFIG_SHELL-$SHELL} -export SHELL -_ASEOF -cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 -## -------------------- ## -## M4sh Initialization. ## -## -------------------- ## +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else - case `(set -o) 2>/dev/null` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; esac + fi -as_nl=' -' -export as_nl -# Printing a long string crashes Solaris 7 /usr/bin/printf. -as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo -# Prefer a ksh shell builtin over an external printf program on Solaris, -# but without wasting forks for bash or zsh. -if test -z "$BASH_VERSION$ZSH_VERSION" \ - && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='print -r --' - as_echo_n='print -rn --' -elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='printf %s\n' - as_echo_n='printf %s' -else - if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then - as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' - as_echo_n='/usr/ucb/echo -n' + + +# PATH needs CR +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' else - as_echo_body='eval expr "X$1" : "X\\(.*\\)"' - as_echo_n_body='eval - arg=$1; - case $arg in #( - *"$as_nl"*) - expr "X$arg" : "X\\(.*\\)$as_nl"; - arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; - esac; - expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" - ' - export as_echo_n_body - as_echo_n='sh -c $as_echo_n_body as_echo' + PATH_SEPARATOR=: fi - export as_echo_body - as_echo='sh -c $as_echo_body as_echo' + rm -f conf$$.sh fi -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - PATH_SEPARATOR=: - (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { - (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || - PATH_SEPARATOR=';' - } +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) +as_nl=' +' IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. -case $0 in #(( +case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break - done + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then - $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - exit 1 + echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + { (exit 1); exit 1; } fi -# Unset variables that we do not need and which cause bugs (e.g. in -# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" -# suppresses any "Segmentation fault" message there. '((' could -# trigger a bug in pdksh 5.2.14. -for as_var in BASH_ENV ENV MAIL MAILPATH -do eval test x\${$as_var+set} = xset \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +# Work around bugs in pre-3.0 UWIN ksh. +for as_var in ENV MAIL MAILPATH +do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - - -# as_fn_error STATUS ERROR [LINENO LOG_FD] -# ---------------------------------------- -# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are -# provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with STATUS, using 1 if that was 0. -as_fn_error () -{ - as_status=$1; test $as_status -eq 0 && as_status=1 - if test "$4"; then - as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var fi - $as_echo "$as_me: error: $2" >&2 - as_fn_exit $as_status -} # as_fn_error +done - -# as_fn_set_status STATUS -# ----------------------- -# Set $? to STATUS, without forking. -as_fn_set_status () -{ - return $1 -} # as_fn_set_status - -# as_fn_exit STATUS -# ----------------- -# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. -as_fn_exit () -{ - set +e - as_fn_set_status $1 - exit $1 -} # as_fn_exit - -# as_fn_unset VAR -# --------------- -# Portably unset VAR. -as_fn_unset () -{ - { eval $1=; unset $1;} -} -as_unset=as_fn_unset -# as_fn_append VAR VALUE -# ---------------------- -# Append the text in VALUE to the end of the definition contained in VAR. Take -# advantage of any shell optimizations that allow amortized linear growth over -# repeated appends, instead of the typical quadratic growth present in naive -# implementations. -if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : - eval 'as_fn_append () - { - eval $1+=\$2 - }' -else - as_fn_append () - { - eval $1=\$$1\$2 - } -fi # as_fn_append - -# as_fn_arith ARG... -# ------------------ -# Perform arithmetic evaluation on the ARGs, and store the result in the -# global $as_val. Take advantage of shells that can avoid forks. The arguments -# must be portable across $(()) and expr. -if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : - eval 'as_fn_arith () - { - as_val=$(( $* )) - }' -else - as_fn_arith () - { - as_val=`expr "$@" || test $? -eq 1` - } -fi # as_fn_arith - - +# Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi +# Name of the executable. as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X/"$0" | +echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits +# CDPATH. +$as_unset CDPATH + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line after each line using $LINENO; the second 'sed' + # does the real work. The second script uses 'N' to pair each + # line-number line with the line containing $LINENO, and appends + # trailing '-' during substitution so that $LINENO is not a special + # case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # scripts with optimization help from Paolo Bonzini. Blame Lee + # E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in #((((( +case `echo -n x` in -n*) - case `echo 'xy\c'` in + case `echo 'x\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. - xy) ECHO_C='\c';; - *) echo `echo ksh88 bug on AIX 6.1` > /dev/null - ECHO_T=' ';; + *) ECHO_C='\c';; esac;; *) ECHO_N='-n';; esac +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir - mkdir conf$$.dir 2>/dev/null + mkdir conf$$.dir fi -if (echo >conf$$.file) 2>/dev/null; then - if ln -s conf$$.file conf$$ 2>/dev/null; then - as_ln_s='ln -s' - # ... but there are two gotchas: - # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. - # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -p'. - ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -p' - elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln - else +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' - fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null - -# as_fn_mkdir_p -# ------------- -# Create "$as_dir" as a directory, including parents if necessary. -as_fn_mkdir_p () -{ - - case $as_dir in #( - -*) as_dir=./$as_dir;; - esac - test -d "$as_dir" || eval $as_mkdir_p || { - as_dirs= - while :; do - case $as_dir in #( - *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( - *) as_qdir=$as_dir;; - esac - as_dirs="'$as_qdir' $as_dirs" - as_dir=`$as_dirname -- "$as_dir" || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - test -d "$as_dir" && break - done - test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" - - -} # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then - as_mkdir_p='mkdir -p "$as_dir"' + as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then - test -d "$1/."; + test -d "$1/."; else - case $1 in #( - -*)set "./$1";; + case $1 in + -*)set "./$1";; esac; - case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 -## ----------------------------------- ## -## Main body of $CONFIG_STATUS script. ## -## ----------------------------------- ## -_ASEOF -test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# Save the log message, to keep $0 and so on meaningful, and to +# Save the log message, to keep $[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by $as_me, which was -generated by GNU Autoconf 2.67. Invocation command line was +generated by GNU Autoconf 2.61. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF -case $ac_config_files in *" -"*) set x $ac_config_files; shift; ac_config_files=$*;; -esac - -case $ac_config_headers in *" -"*) set x $ac_config_headers; shift; ac_config_headers=$*;; -esac - - -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>$CONFIG_STATUS <<_ACEOF # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" _ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +cat >>$CONFIG_STATUS <<\_ACEOF ac_cs_usage="\ -\`$as_me' instantiates files and other configuration actions -from templates according to the current configuration. Unless the files -and actions are specified as TAGs, all are instantiated by default. +\`$as_me' instantiates files from templates according to the +current configuration. -Usage: $0 [OPTION]... [TAG]... +Usage: $0 [OPTIONS] [FILE]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit - --config print configuration, then exit - -q, --quiet, --silent - do not print progress messages + -q, --quiet do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions - --file=FILE[:TEMPLATE] - instantiate the configuration file FILE - --header=FILE[:TEMPLATE] - instantiate the configuration header FILE + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers -Report bugs to the package provider." +Report bugs to ." _ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ config.status -configured by $0, generated by GNU Autoconf 2.67, - with options \\"\$ac_cs_config\\" +configured by $0, generated by GNU Autoconf 2.61, + with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" -Copyright (C) 2010 Free Software Foundation, Inc. +Copyright (C) 2006 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' -test -n "\$AWK" || AWK=awk _ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# The default lists apply if the user does not specify any file. +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. ac_need_defaults=: while test $# != 0 do case $1 in - --*=?*) + --*=*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; - --*=) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg= - ac_shift=: - ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) - $as_echo "$ac_cs_version"; exit ;; - --config | --confi | --conf | --con | --co | --c ) - $as_echo "$ac_cs_config"; exit ;; + echo "$ac_cs_version"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift - case $ac_optarg in - *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; - '') as_fn_error $? "missing file argument" ;; - esac - as_fn_append CONFIG_FILES " '$ac_optarg'" + CONFIG_FILES="$CONFIG_FILES $ac_optarg" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift - case $ac_optarg in - *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; - esac - as_fn_append CONFIG_HEADERS " '$ac_optarg'" + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header - as_fn_error $? "ambiguous option: \`$1' -Try \`$0 --help' for more information.";; + { echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; };; --help | --hel | -h ) - $as_echo "$ac_cs_usage"; exit ;; + echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. - -*) as_fn_error $? "unrecognized option: \`$1' -Try \`$0 --help' for more information." ;; + -*) { echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } ;; - *) as_fn_append ac_config_targets " $1" + *) ac_config_targets="$ac_config_targets $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>$CONFIG_STATUS <<_ACEOF if \$ac_cs_recheck; then - set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion - shift - \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 - CONFIG_SHELL='$SHELL' + echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + CONFIG_SHELL=$SHELL export CONFIG_SHELL - exec "\$@" + exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion fi _ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +cat >>$CONFIG_STATUS <<\_ACEOF exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX - $as_echo "$ac_log" + echo "$ac_log" } >&5 _ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>$CONFIG_STATUS <<_ACEOF _ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +cat >>$CONFIG_STATUS <<\_ACEOF # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "pcap-filter.manmisc") CONFIG_FILES="$CONFIG_FILES pcap-filter.manmisc" ;; "pcap-linktype.manmisc") CONFIG_FILES="$CONFIG_FILES pcap-linktype.manmisc" ;; "pcap-tstamp.manmisc") CONFIG_FILES="$CONFIG_FILES pcap-tstamp.manmisc" ;; "pcap-savefile.manfile") CONFIG_FILES="$CONFIG_FILES pcap-savefile.manfile" ;; "pcap.3pcap") CONFIG_FILES="$CONFIG_FILES pcap.3pcap" ;; "pcap_compile.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_compile.3pcap" ;; "pcap_datalink.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_datalink.3pcap" ;; "pcap_dump_open.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_dump_open.3pcap" ;; "pcap_list_datalinks.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_list_datalinks.3pcap" ;; "pcap_list_tstamp_types.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_list_tstamp_types.3pcap" ;; "pcap_open_dead.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_open_dead.3pcap" ;; "pcap_open_offline.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_open_offline.3pcap" ;; "pcap_set_tstamp_type.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_set_tstamp_type.3pcap" ;; - *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;; + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= trap 'exit_status=$? { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status ' 0 - trap 'as_fn_exit 1' 1 2 13 15 + trap '{ (exit 1); exit 1; }' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") -} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} -# Set up the scripts for CONFIG_FILES section. -# No need to generate them if there are no CONFIG_FILES. -# This happens for instance with `./config.status config.h'. +# +# Set up the sed scripts for CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h if test -n "$CONFIG_FILES"; then - -ac_cr=`echo X | tr X '\015'` -# On cygwin, bash can eat \r inside `` if the user requested igncr. -# But we know of no other shell where ac_cr would be empty at this -# point, so we can use a bashism as a fallback. -if test "x$ac_cr" = x; then - eval ac_cr=\$\'\\r\' -fi -ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` -if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then - ac_cs_awk_cr='\\r' -else - ac_cs_awk_cr=$ac_cr -fi - -echo 'BEGIN {' >"$tmp/subs1.awk" && _ACEOF -{ - echo "cat >conf$$subs.awk <<_ACEOF" && - echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && - echo "_ACEOF" -} >conf$$subs.sh || - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 -ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` + ac_delim='%!_!# ' for ac_last_try in false false false false false :; do - . ./conf$$subs.sh || - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + cat >conf$$subs.sed <<_ACEOF +SHELL!$SHELL$ac_delim +PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim +PACKAGE_NAME!$PACKAGE_NAME$ac_delim +PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim +PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim +PACKAGE_STRING!$PACKAGE_STRING$ac_delim +PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim +exec_prefix!$exec_prefix$ac_delim +prefix!$prefix$ac_delim +program_transform_name!$program_transform_name$ac_delim +bindir!$bindir$ac_delim +sbindir!$sbindir$ac_delim +libexecdir!$libexecdir$ac_delim +datarootdir!$datarootdir$ac_delim +datadir!$datadir$ac_delim +sysconfdir!$sysconfdir$ac_delim +sharedstatedir!$sharedstatedir$ac_delim +localstatedir!$localstatedir$ac_delim +includedir!$includedir$ac_delim +oldincludedir!$oldincludedir$ac_delim +docdir!$docdir$ac_delim +infodir!$infodir$ac_delim +htmldir!$htmldir$ac_delim +dvidir!$dvidir$ac_delim +pdfdir!$pdfdir$ac_delim +psdir!$psdir$ac_delim +libdir!$libdir$ac_delim +localedir!$localedir$ac_delim +mandir!$mandir$ac_delim +DEFS!$DEFS$ac_delim +ECHO_C!$ECHO_C$ac_delim +ECHO_N!$ECHO_N$ac_delim +ECHO_T!$ECHO_T$ac_delim +LIBS!$LIBS$ac_delim +build_alias!$build_alias$ac_delim +host_alias!$host_alias$ac_delim +target_alias!$target_alias$ac_delim +build!$build$ac_delim +build_cpu!$build_cpu$ac_delim +build_vendor!$build_vendor$ac_delim +build_os!$build_os$ac_delim +host!$host$ac_delim +host_cpu!$host_cpu$ac_delim +host_vendor!$host_vendor$ac_delim +host_os!$host_os$ac_delim +target!$target$ac_delim +target_cpu!$target_cpu$ac_delim +target_vendor!$target_vendor$ac_delim +target_os!$target_os$ac_delim +SHLICC2!$SHLICC2$ac_delim +CC!$CC$ac_delim +CFLAGS!$CFLAGS$ac_delim +LDFLAGS!$LDFLAGS$ac_delim +CPPFLAGS!$CPPFLAGS$ac_delim +ac_ct_CC!$ac_ct_CC$ac_delim +EXEEXT!$EXEEXT$ac_delim +OBJEXT!$OBJEXT$ac_delim +CPP!$CPP$ac_delim +GREP!$GREP$ac_delim +EGREP!$EGREP$ac_delim +LIBOBJS!$LIBOBJS$ac_delim +HAVE_LINUX_TPACKET_AUXDATA!$HAVE_LINUX_TPACKET_AUXDATA$ac_delim +V_LEX!$V_LEX$ac_delim +V_YACC!$V_YACC$ac_delim +RANLIB!$RANLIB$ac_delim +AR!$AR$ac_delim +V_CCOPT!$V_CCOPT$ac_delim +V_DEFS!$V_DEFS$ac_delim +V_FINDALLDEVS!$V_FINDALLDEVS$ac_delim +V_INCLS!$V_INCLS$ac_delim +V_PCAP!$V_PCAP$ac_delim +V_SHLIB_CMD!$V_SHLIB_CMD$ac_delim +V_SHLIB_OPT!$V_SHLIB_OPT$ac_delim +V_SONAME_OPT!$V_SONAME_OPT$ac_delim +V_RPATH_OPT!$V_RPATH_OPT$ac_delim +ADDLOBJS!$ADDLOBJS$ac_delim +ADDLARCHIVEOBJS!$ADDLARCHIVEOBJS$ac_delim +SSRC!$SSRC$ac_delim +DYEXT!$DYEXT$ac_delim +MAN_FILE_FORMATS!$MAN_FILE_FORMATS$ac_delim +MAN_MISC_INFO!$MAN_MISC_INFO$ac_delim +PCAP_SUPPORT_USB!$PCAP_SUPPORT_USB$ac_delim +USB_SRC!$USB_SRC$ac_delim +PCAP_SUPPORT_NETFILTER!$PCAP_SUPPORT_NETFILTER$ac_delim +NETFILTER_SRC!$NETFILTER_SRC$ac_delim +PCAP_SUPPORT_BT!$PCAP_SUPPORT_BT$ac_delim +BT_SRC!$BT_SRC$ac_delim +PCAP_SUPPORT_CANUSB!$PCAP_SUPPORT_CANUSB$ac_delim +CANUSB_SRC!$CANUSB_SRC$ac_delim +PCAP_SUPPORT_CAN!$PCAP_SUPPORT_CAN$ac_delim +CAN_SRC!$CAN_SRC$ac_delim +INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim +INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim +INSTALL_DATA!$INSTALL_DATA$ac_delim +LTLIBOBJS!$LTLIBOBJS$ac_delim +_ACEOF - ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` - if test $ac_delim_n = $ac_delim_num; then + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 95; then break elif $ac_last_try; then - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 +echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done -rm -f conf$$subs.sh -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -cat >>"\$tmp/subs1.awk" <<\\_ACAWK && -_ACEOF -sed -n ' -h -s/^/S["/; s/!.*/"]=/ -p -g -s/^[^!]*!// -:repl -t repl -s/'"$ac_delim"'$// -t delim -:nl -h -s/\(.\{148\}\)..*/\1/ -t more1 -s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ -p -n -b repl -:more1 -s/["\\]/\\&/g; s/^/"/; s/$/"\\/ -p -g -s/.\{148\}// -t nl -:delim -h -s/\(.\{148\}\)..*/\1/ -t more2 -s/["\\]/\\&/g; s/^/"/; s/$/"/ -p -b -:more2 -s/["\\]/\\&/g; s/^/"/; s/$/"\\/ -p -g -s/.\{148\}// -t delim -' >$CONFIG_STATUS || ac_write_fail=1 -rm -f conf$$subs.awk -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -_ACAWK -cat >>"\$tmp/subs1.awk" <<_ACAWK && - for (key in S) S_is_set[key] = 1 - FS = "" +ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` +if test -n "$ac_eof"; then + ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` + ac_eof=`expr $ac_eof + 1` +fi -} -{ - line = $ 0 - nfields = split(line, field, "@") - substed = 0 - len = length(field[1]) - for (i = 2; i < nfields; i++) { - key = field[i] - keylen = length(key) - if (S_is_set[key]) { - value = S[key] - line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) - len += length(value) + length(field[++i]) - substed = 1 - } else - len += 1 + keylen - } - - print line -} - -_ACAWK +cat >>$CONFIG_STATUS <<_ACEOF +cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end _ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then - sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" -else - cat -fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ - || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +sed ' +s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g +s/^/s,@/; s/!/@,|#_!!_#|/ +:n +t n +s/'"$ac_delim"'$/,g/; t +s/$/\\/; p +N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n +' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF +:end +s/|#_!!_#|//g +CEOF$ac_eof _ACEOF -# VPATH may cause trouble with some makes, so we remove sole $(srcdir), -# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ -h -s/// -s/^/:/ -s/[ ]*$/:/ -s/:\$(srcdir):/:/g -s/:\${srcdir}:/:/g -s/:@srcdir@:/:/g -s/^:*// + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/ +s/:*\${srcdir}:*/:/ +s/:*@srcdir@:*/:/ +s/^\([^=]*=[ ]*\):*/\1/ s/:*$// -x -s/\(=[ ]*\).*/\1/ -G -s/\n// s/^[^=]*=[ ]*$// }' fi -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +cat >>$CONFIG_STATUS <<\_ACEOF fi # test -n "$CONFIG_FILES" -# Set up the scripts for CONFIG_HEADERS section. -# No need to generate them if there are no CONFIG_HEADERS. -# This happens for instance with `./config.status Makefile'. -if test -n "$CONFIG_HEADERS"; then -cat >"$tmp/defines.awk" <<\_ACAWK || -BEGIN { -_ACEOF -# Transform confdefs.h into an awk script `defines.awk', embedded as -# here-document in config.status, that substitutes the proper values into -# config.h.in to produce config.h. - -# Create a delimiter string that does not exist in confdefs.h, to ease -# handling of long lines. -ac_delim='%!_!# ' -for ac_last_try in false false :; do - ac_t=`sed -n "/$ac_delim/p" confdefs.h` - if test -z "$ac_t"; then - break - elif $ac_last_try; then - as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 - else - ac_delim="$ac_delim!$ac_delim _$ac_delim!! " - fi -done - -# For the awk script, D is an array of macro values keyed by name, -# likewise P contains macro parameters if any. Preserve backslash -# newline sequences. - -ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* -sed -n ' -s/.\{148\}/&'"$ac_delim"'/g -t rset -:rset -s/^[ ]*#[ ]*define[ ][ ]*/ / -t def -d -:def -s/\\$// -t bsnl -s/["\\]/\\&/g -s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ -D["\1"]=" \3"/p -s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p -d -:bsnl -s/["\\]/\\&/g -s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ -D["\1"]=" \3\\\\\\n"\\/p -t cont -s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p -t cont -d -:cont -n -s/.\{148\}/&'"$ac_delim"'/g -t clear -:clear -s/\\$// -t bsnlc -s/["\\]/\\&/g; s/^/"/; s/$/"/p -d -:bsnlc -s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p -b cont -' >$CONFIG_STATUS || ac_write_fail=1 - -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 - for (key in D) D_is_set[key] = 1 - FS = "" -} -/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { - line = \$ 0 - split(line, arg, " ") - if (arg[1] == "#") { - defundef = arg[2] - mac1 = arg[3] - } else { - defundef = substr(arg[1], 2) - mac1 = arg[2] - } - split(mac1, mac2, "(") #) - macro = mac2[1] - prefix = substr(line, 1, index(line, defundef) - 1) - if (D_is_set[macro]) { - # Preserve the white space surrounding the "#". - print prefix "define", macro P[macro] D[macro] - next - } else { - # Replace #undef with comments. This is necessary, for example, - # in the case of _POSIX_SOURCE, which is predefined and required - # on some systems where configure will not decide to define it. - if (defundef == "undef") { - print "/*", prefix defundef, macro, "*/" - next - } - } -} -{ print } -_ACAWK -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 - as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 -fi # test -n "$CONFIG_HEADERS" - - -eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " -shift -for ac_tag +for ac_tag in :F $CONFIG_FILES :H $CONFIG_HEADERS do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; - :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5 ;; + :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5 +echo "$as_me: error: Invalid tag $ac_tag." >&2;} + { (exit 1); exit 1; }; };; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || - as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5 ;; + { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5 +echo "$as_me: error: cannot find input file: $ac_f" >&2;} + { (exit 1); exit 1; }; };; esac - case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac - as_fn_append ac_file_inputs " '$ac_f'" + ac_file_inputs="$ac_file_inputs $ac_f" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ - configure_input='Generated from '` - $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' - `' by configure.' + configure_input="Generated from "`IFS=: + echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure." if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" - { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 -$as_echo "$as_me: creating $ac_file" >&6;} + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} fi - # Neutralize special characters interpreted by sed in replacement strings. - case $configure_input in #( - *\&* | *\|* | *\\* ) - ac_sed_conf_input=`$as_echo "$configure_input" | - sed 's/[\\\\&|]/\\\\&/g'`;; #( - *) ac_sed_conf_input=$configure_input;; - esac case $ac_tag in - *:-:* | *:-) cat >"$tmp/stdin" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + *:-:* | *:-) cat >"$tmp/stdin";; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$ac_file" | +echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` - as_dir="$ac_dir"; as_fn_mkdir_p + { as_dir="$ac_dir" + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 +echo "$as_me: error: cannot create directory $as_dir" >&2;} + { (exit 1); exit 1; }; }; } ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) - ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac _ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +cat >>$CONFIG_STATUS <<\_ACEOF # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= -ac_sed_dataroot=' -/datarootdir/ { + +case `sed -n '/datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p -/@mandir@/p' -case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +/@mandir@/p +' $ac_file_inputs` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 -$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>$CONFIG_STATUS <<_ACEOF ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g - s&\\\${datarootdir}&$datarootdir&g' ;; + s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -ac_sed_extra="$ac_vpsub +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub $extrasub _ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +cat >>$CONFIG_STATUS <<\_ACEOF :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b -s|@configure_input@|$ac_sed_conf_input|;t t +s&@configure_input@&$configure_input&;t t s&@top_builddir@&$ac_top_builddir_sub&;t t -s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t $ac_datarootdir_hack -" -eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 +" $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined" >&5 -$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&5 +echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&2;} rm -f "$tmp/stdin" case $ac_file in - -) cat "$tmp/out" && rm -f "$tmp/out";; - *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; - esac \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + -) cat "$tmp/out"; rm -f "$tmp/out";; + *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;; + esac ;; :H) # # CONFIG_HEADER # +_ACEOF + +# Transform confdefs.h into a sed script `conftest.defines', that +# substitutes the proper values into config.h.in to produce config.h. +rm -f conftest.defines conftest.tail +# First, append a space to every undef/define line, to ease matching. +echo 's/$/ /' >conftest.defines +# Then, protect against being on the right side of a sed subst, or in +# an unquoted here document, in config.status. If some macros were +# called several times there might be several #defines for the same +# symbol, which is useless. But do not sort them, since the last +# AC_DEFINE must be honored. +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where +# NAME is the cpp macro being defined, VALUE is the value it is being given. +# PARAMS is the parameter list in the macro definition--in most cases, it's +# just an empty string. +ac_dA='s,^\\([ #]*\\)[^ ]*\\([ ]*' +ac_dB='\\)[ (].*,\\1define\\2' +ac_dC=' ' +ac_dD=' ,' + +uniq confdefs.h | + sed -n ' + t rset + :rset + s/^[ ]*#[ ]*define[ ][ ]*// + t ok + d + :ok + s/[\\&,]/\\&/g + s/^\('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p + s/^\('"$ac_word_re"'\)[ ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p + ' >>conftest.defines + +# Remove the space that was appended to ease matching. +# Then replace #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +# (The regexp can be short, since the line contains either #define or #undef.) +echo 's/ $// +s,^[ #]*u.*,/* & */,' >>conftest.defines + +# Break up conftest.defines: +ac_max_sed_lines=50 + +# First sed command is: sed -f defines.sed $ac_file_inputs >"$tmp/out1" +# Second one is: sed -f defines.sed "$tmp/out1" >"$tmp/out2" +# Third one will be: sed -f defines.sed "$tmp/out2" >"$tmp/out1" +# et cetera. +ac_in='$ac_file_inputs' +ac_out='"$tmp/out1"' +ac_nxt='"$tmp/out2"' + +while : +do + # Write a here document: + cat >>$CONFIG_STATUS <<_ACEOF + # First, check the format of the line: + cat >"\$tmp/defines.sed" <<\\CEOF +/^[ ]*#[ ]*undef[ ][ ]*$ac_word_re[ ]*\$/b def +/^[ ]*#[ ]*define[ ][ ]*$ac_word_re[( ]/b def +b +:def +_ACEOF + sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS + echo 'CEOF + sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS + ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in + sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail + grep . conftest.tail >/dev/null || break + rm -f conftest.defines + mv conftest.tail conftest.defines +done +rm -f conftest.defines conftest.tail + +echo "ac_result=$ac_in" >>$CONFIG_STATUS +cat >>$CONFIG_STATUS <<\_ACEOF if test x"$ac_file" != x-; then - { - $as_echo "/* $configure_input */" \ - && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" - } >"$tmp/config.h" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 - if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then - { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 -$as_echo "$as_me: $ac_file is unchanged" >&6;} + echo "/* $configure_input */" >"$tmp/config.h" + cat "$ac_result" >>"$tmp/config.h" + if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then + { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 +echo "$as_me: $ac_file is unchanged" >&6;} else - rm -f "$ac_file" - mv "$tmp/config.h" "$ac_file" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + rm -f $ac_file + mv "$tmp/config.h" $ac_file fi else - $as_echo "/* $configure_input */" \ - && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \ - || as_fn_error $? "could not create -" "$LINENO" 5 + echo "/* $configure_input */" + cat "$ac_result" fi + rm -f "$tmp/out12" ;; esac done # for ac_tag -as_fn_exit 0 +{ (exit 0); exit 0; } _ACEOF +chmod +x $CONFIG_STATUS ac_clean_files=$ac_clean_files_save -test $ac_write_fail = 0 || - as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 - # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. - $ac_cs_success || as_fn_exit 1 -fi -if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 -$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} + $ac_cs_success || { (exit 1); exit 1; } fi if test -f .devel ; then make depend fi exit 0 Index: stable/9/contrib/libpcap/configure.in =================================================================== --- stable/9/contrib/libpcap/configure.in (revision 252280) +++ stable/9/contrib/libpcap/configure.in (revision 252281) @@ -1,1471 +1,1524 @@ dnl @(#) $Header: /tcpdump/master/libpcap/configure.in,v 1.168 2008-12-23 20:49:26 guy Exp $ (LBL) dnl dnl Copyright (c) 1994, 1995, 1996, 1997 dnl The Regents of the University of California. All rights reserved. dnl dnl Process this file with autoconf to produce a configure script. dnl # # See # # http://ftp.gnu.org/gnu/config/README # # for the URLs to use to fetch new versions of config.guess and # config.sub. # AC_REVISION($Revision: 1.168 $) AC_PREREQ(2.50) AC_INIT(pcap.c) AC_CANONICAL_SYSTEM AC_LBL_C_INIT_BEFORE_CC(V_CCOPT, V_INCLS) AC_PROG_CC AC_LBL_C_INIT(V_CCOPT, V_INCLS) AC_LBL_SHLIBS_INIT AC_LBL_C_INLINE AC_C___ATTRIBUTE__ AC_CHECK_HEADERS(sys/bitypes.h) AC_CHECK_TYPE([int8_t], , [AC_DEFINE([int8_t], [signed char], [Define to `signed char' if int8_t not defined.])], [AC_INCLUDES_DEFAULT #ifdef HAVE_SYS_BITYPES_H #include #endif]) AC_CHECK_TYPE([u_int8_t], , [AC_DEFINE([u_int8_t], [unsigned char], [Define to `unsigned char' if u_int8_t not defined.])], [AC_INCLUDES_DEFAULT #ifdef HAVE_SYS_BITYPES_H #include #endif]) AC_CHECK_TYPE([int16_t], , [AC_DEFINE([int16_t], [short], [Define to `short' if int16_t not defined.])] [AC_INCLUDES_DEFAULT #ifdef HAVE_SYS_BITYPES_H #include #endif]) AC_CHECK_TYPE([u_int16_t], , [AC_DEFINE([u_int16_t], [unsigned short], [Define to `unsigned short' if u_int16_t not defined.])], [AC_INCLUDES_DEFAULT #ifdef HAVE_SYS_BITYPES_H #include #endif]) AC_CHECK_TYPE([int32_t], , [AC_DEFINE([int32_t], [int], [Define to `int' if int32_t not defined.])], [AC_INCLUDES_DEFAULT #ifdef HAVE_SYS_BITYPES_H #include #endif]) AC_CHECK_TYPE([u_int32_t], , [AC_DEFINE([u_int32_t], [unsigned int], [Define to `unsigned int' if u_int32_t not defined.])], [AC_INCLUDES_DEFAULT #ifdef HAVE_SYS_BITYPES_H #include #endif]) AC_CHECK_TYPE([int64_t], , [AC_DEFINE([int64_t], [long long], [Define to `long long' if int64_t not defined.])], [AC_INCLUDES_DEFAULT #ifdef HAVE_SYS_BITYPES_H #include #endif]) AC_CHECK_TYPE([u_int64_t], , [AC_DEFINE([u_int64_t], [unsigned long long], [Define to `unsigned long long' if u_int64_t not defined.])], [AC_INCLUDES_DEFAULT #ifdef HAVE_SYS_BITYPES_H #include #endif]) # # Try to arrange for large file support. # AC_SYS_LARGEFILE AC_FUNC_FSEEKO dnl dnl Even if were, on all OSes that support BPF, fixed to dnl include , and we were to drop support for older dnl releases without that fix, so that pcap-bpf.c doesn't need to dnl include , the test program in "AC_LBL_FIXINCLUDES" dnl in "aclocal.m4" uses it, so we would still have to test for it dnl and set "HAVE_SYS_IOCCOM_H" if we have it, otherwise dnl "AC_LBL_FIXINCLUDES" wouldn't work on some platforms such as Solaris. dnl AC_CHECK_HEADERS(sys/ioccom.h sys/sockio.h limits.h paths.h) AC_CHECK_HEADERS(linux/types.h) AC_CHECK_HEADERS(linux/if_packet.h netpacket/packet.h netpacket/if_packet.h) AC_CHECK_HEADERS(net/pfvar.h, , , [#include #include #include ]) if test "$ac_cv_header_net_pfvar_h" = yes; then # # Check for various PF actions. # AC_MSG_CHECKING(whether net/pfvar.h defines PF_NAT through PF_NORDR) AC_TRY_COMPILE( [#include #include #include #include ], [return PF_NAT+PF_NONAT+PF_BINAT+PF_NOBINAT+PF_RDR+PF_NORDR;], [ AC_MSG_RESULT(yes) AC_DEFINE(HAVE_PF_NAT_THROUGH_PF_NORDR, 1, [define if net/pfvar.h defines PF_NAT through PF_NORDR]) ], AC_MSG_RESULT(no)) fi AC_CHECK_HEADERS(netinet/if_ether.h, , , [#include #include ]) if test "$ac_cv_header_netinet_if_ether_h" != yes; then # # The simple test didn't work. # Do we need to include first? # Unset ac_cv_header_netinet_if_ether_h so we don't # treat the previous failure as a cached value and # suppress the next test. # AC_MSG_NOTICE([Rechecking with some additional includes]) unset ac_cv_header_netinet_if_ether_h AC_CHECK_HEADERS(netinet/if_ether.h, , , [#include #include #include struct mbuf; struct rtentry; #include ]) fi AC_LBL_FIXINCLUDES AC_CHECK_FUNCS(strerror strlcpy) needsnprintf=no AC_CHECK_FUNCS(vsnprintf snprintf,, [needsnprintf=yes]) if test $needsnprintf = yes; then AC_LIBOBJ([snprintf]) fi # # Do this before checking for ether_hostton(), as it's a # "gethostbyname() -ish function". # AC_LBL_LIBRARY_NET # # You are in a twisty little maze of UN*Xes, all different. # Some might not have ether_hostton(). # Some might have it, but not declare it in any header file. # Some might have it, but declare it in . # Some might have it, but declare it in # (And some might have it but document it as something declared in # , although appears to work.) # # Before you is a C compiler. # AC_CHECK_FUNCS(ether_hostton) if test "$ac_cv_func_ether_hostton" = yes; then # # OK, we have ether_hostton(). Do we have ? # if test "$ac_cv_header_netinet_if_ether_h" = yes; then # # Yes. Does it declare ether_hostton()? # AC_CHECK_DECL(ether_hostton, [ AC_DEFINE(NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON,, [Define to 1 if netinet/if_ether.h declares `ether_hostton']) ],, [ #include #include #include #include struct mbuf; struct rtentry; #include #include ]) fi # # Did that succeed? # if test "$ac_cv_have_decl_ether_hostton" != yes; then # # No, how about , as on Linux? # AC_CHECK_HEADERS(netinet/ether.h) if test "$ac_cv_header_netinet_ether_h" = yes; then # # We have it - does it declare ether_hostton()? # Unset ac_cv_have_decl_ether_hostton so we don't # treat the previous failure as a cached value and # suppress the next test. # unset ac_cv_have_decl_ether_hostton AC_CHECK_DECL(ether_hostton, [ AC_DEFINE(NETINET_ETHER_H_DECLARES_ETHER_HOSTTON,, [Define to 1 if netinet/ether.h declares `ether_hostton']) ],, [ #include ]) fi fi # # Is ether_hostton() declared? # if test "$ac_cv_have_decl_ether_hostton" != yes; then # # No, we'll have to declare it ourselves. # Do we have "struct ether_addr"? # AC_CHECK_TYPES(struct ether_addr,,, [ #include #include #include #include struct mbuf; struct rtentry; #include #include ]) AC_DEFINE(HAVE_DECL_ETHER_HOSTTON, 0, [Define to 1 if you have the declaration of `ether_hostton', and to 0 if you don't.]) else AC_DEFINE(HAVE_DECL_ETHER_HOSTTON, 1, [Define to 1 if you have the declaration of `ether_hostton', and to 0 if you don't.]) fi fi dnl to pacify those who hate protochain insn AC_MSG_CHECKING(if --disable-protochain option is specified) AC_ARG_ENABLE(protochain, AC_HELP_STRING([--disable-protochain],[disable \"protochain\" insn])) case "x$enable_protochain" in xyes) enable_protochain=enabled ;; xno) enable_protochain=disabled ;; x) enable_protochain=enabled ;; esac if test "$enable_protochain" = "disabled"; then AC_DEFINE(NO_PROTOCHAIN,1,[do not use protochain]) fi AC_MSG_RESULT(${enable_protochain}) # # SITA support is mutually exclusive with native capture support; # "--with-sita" selects SITA support. # AC_ARG_WITH(sita, AC_HELP_STRING([--with-sita],[include SITA support]), [ if test ! "x$withval" = "xno" ; then AC_DEFINE(SITA,1,[include ACN support]) AC_MSG_NOTICE(Enabling SITA ACN support) V_PCAP=sita V_FINDALLDEVS=sita fi ], [ dnl dnl Not all versions of test support -c (character special) but it's a dnl better way of testing since the device might be protected. So we dnl check in our normal order using -r and then check the for the /dev dnl guys again using -c. dnl dnl XXX This could be done for cross-compiling, but for now it's not. dnl if test -z "$with_pcap" && test "$cross_compiling" = yes; then AC_MSG_ERROR(pcap type not determined when cross-compiling; use --with-pcap=...) fi AC_ARG_WITH(pcap, AC_HELP_STRING([--with-pcap=TYPE],[use packet capture TYPE])) AC_MSG_CHECKING(packet capture type) if test ! -z "$with_pcap" ; then V_PCAP="$withval" elif test -r /dev/bpf -o -h /dev/bpf ; then # # Cloning BPF device. # V_PCAP=bpf AC_DEFINE(HAVE_CLONING_BPF,1,[define if you have a cloning BPF device]) elif test -r /dev/bpf0 ; then V_PCAP=bpf elif test -r /usr/include/net/pfilt.h ; then V_PCAP=pf elif test -r /dev/enet ; then V_PCAP=enet elif test -r /dev/nit ; then V_PCAP=snit elif test -r /usr/include/sys/net/nit.h ; then V_PCAP=nit elif test -r /usr/include/linux/socket.h ; then V_PCAP=linux elif test -r /usr/include/net/raw.h ; then V_PCAP=snoop elif test -r /usr/include/odmi.h ; then # # On AIX, the BPF devices might not yet be present - they're # created the first time libpcap runs after booting. # We check for odmi.h instead. # V_PCAP=bpf elif test -c /dev/bpf0 ; then # check again in case not readable V_PCAP=bpf elif test -r /usr/include/sys/dlpi.h ; then V_PCAP=dlpi elif test -c /dev/enet ; then # check again in case not readable V_PCAP=enet elif test -c /dev/nit ; then # check again in case not readable V_PCAP=snit else V_PCAP=null fi AC_MSG_RESULT($V_PCAP) # # Do capture-mechanism-dependent tests. # case "$V_PCAP" in dlpi) # # Checks to see if Solaris has the public libdlpi(3LIB) library. # Note: The existence of /usr/include/libdlpi.h does not mean it is the # public libdlpi(3LIB) version. Before libdlpi was made public, a # private version also existed, which did not have the same APIs. # Due to a gcc bug, the default search path for 32-bit libraries does # not include /lib, we add it explicitly here. # [http://bugs.opensolaris.org/view_bug.do?bug_id=6619485]. # Also, due to the bug above applications that link to libpcap with # libdlpi will have to add "-L/lib" option to "configure". # saved_ldflags=$LDFLAGS LDFLAGS="$LIBS -L/lib" AC_CHECK_LIB(dlpi, dlpi_walk, LIBS="-ldlpi $LIBS" V_PCAP=libdlpi AC_DEFINE(HAVE_LIBDLPI,1,[if libdlpi exists]), V_PCAP=dlpi) LDFLAGS=$saved_ldflags # # Checks whether is usable, to catch weird SCO # versions of DLPI. # AC_MSG_CHECKING(whether is usable) AC_CACHE_VAL(ac_cv_sys_dlpi_usable, AC_TRY_COMPILE( [ #include #include #include ], [int i = DL_PROMISC_PHYS;], ac_cv_sys_dlpi_usable=yes, ac_cv_sys_dlpi_usable=no)) AC_MSG_RESULT($ac_cv_sys_dlpi_usable) if test $ac_cv_sys_dlpi_usable = no ; then AC_MSG_ERROR( is not usable on this system; it probably has a non-standard DLPI) fi # # Check whether we have a /dev/dlpi device or have multiple devices. # AC_MSG_CHECKING(for /dev/dlpi device) if test -c /dev/dlpi ; then AC_MSG_RESULT(yes) AC_DEFINE(HAVE_DEV_DLPI, 1, [define if you have a /dev/dlpi]) else AC_MSG_RESULT(no) dir="/dev/dlpi" AC_MSG_CHECKING(for $dir directory) if test -d $dir ; then AC_MSG_RESULT(yes) AC_DEFINE_UNQUOTED(PCAP_DEV_PREFIX, "$dir", [/dev/dlpi directory]) else AC_MSG_RESULT(no) fi fi # # This check is for Solaris with DLPI support for passive modes. # See dlpi(7P) for more details. # AC_LBL_DL_PASSIVE_REQ_T ;; linux) # # Do we have the wireless extensions? # AC_CHECK_HEADERS(linux/wireless.h, [], [], [ #include #include #include ]) # # Do we have libnl? # AC_ARG_WITH(libnl, AC_HELP_STRING([--without-libnl],[disable libnl support @<:@default=yes, on Linux, if present@:>@]), with_libnl=$withval,,) if test x$with_libnl != xno ; then + have_any_nl="no" + # - # Try libnl 2.x first. + # Try libnl 3.x first. # - AC_CHECK_LIB(nl, nl_socket_alloc, + AC_CHECK_LIB(nl-3, nl_socket_alloc, [ # - # Yes, we have libnl 2.x. + # Yes, we have libnl 3.x. # - LIBS="-lnl-genl -lnl $LIBS" + LIBS="-lnl-genl-3 -lnl-3 $LIBS" AC_DEFINE(HAVE_LIBNL,1,[if libnl exists]) - AC_DEFINE(HAVE_LIBNL_2_x,1,[if libnl exists and is version 2.x]) - ], - [ + AC_DEFINE(HAVE_LIBNL_3_x,1,[if libnl exists and is version 3.x]) + AC_DEFINE(HAVE_LIBNL_NLE,1,[libnl has NLE_FAILURE]) + AC_DEFINE(HAVE_LIBNL_SOCKETS,1,[libnl has new-style socket api]) + V_INCLS="$V_INCLS -I/usr/include/libnl3" + have_any_nl="yes" + ]) + + if test x$have_any_nl = xno ; then # + # Try libnl 2.x + # + AC_CHECK_LIB(nl, nl_socket_alloc, + [ + # + # Yes, we have libnl 2.x. + # + LIBS="-lnl-genl -lnl $LIBS" + AC_DEFINE(HAVE_LIBNL,1,[if libnl exists]) + AC_DEFINE(HAVE_LIBNL_2_x,1,[if libnl exists and is version 2.x]) + AC_DEFINE(HAVE_LIBNL_NLE,1,[libnl has NLE_FAILURE]) + AC_DEFINE(HAVE_LIBNL_SOCKETS,1,[libnl has new-style socket api]) + have_any_nl="yes" + ]) + fi + + if test x$have_any_nl = xno ; then + # # No, we don't; do we have libnl 1.x? # AC_CHECK_LIB(nl, nl_handle_alloc, [ # # Yes. # LIBS="-lnl $LIBS" AC_DEFINE(HAVE_LIBNL,1,[if libnl exists]) - ], - [ - # - # No, we don't have libnl at all. - # - if test x$with_libnl = xyes ; then - AC_MSG_ERROR([libnl support requested but libnl not found]) - fi + have_any_nl="yes" ]) - ]) + fi + + if test x$have_any_nl = xno ; then + # + # No, we don't have libnl at all. + # + if test x$with_libnl = xyes ; then + AC_MSG_ERROR([libnl support requested but libnl not found]) + fi + fi fi AC_CHECK_HEADERS(linux/ethtool.h,,, [ AC_INCLUDES_DEFAULT #include ]) AC_LBL_TPACKET_STATS AC_LBL_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI ;; bpf) # # Check whether we have the *BSD-style ioctls. # AC_CHECK_HEADERS(net/if_media.h) AC_MSG_CHECKING(whether the system supports zerocopy BPF) AC_TRY_COMPILE( [#include #include #include #include ], [return (BIOCROTZBUF + BPF_BUFMODE_ZBUF);], [ AC_MSG_RESULT(yes) AC_DEFINE(HAVE_ZEROCOPY_BPF, 1, [define if the system supports zerocopy BPF]) ], AC_MSG_RESULT(no)) # # Check whether we have struct BPF_TIMEVAL. # AC_CHECK_TYPES(struct BPF_TIMEVAL,,, [ #include #include #ifdef HAVE_SYS_IOCCOM_H #include #endif #include ]) ;; dag) V_DEFS="$V_DEFS -DDAG_ONLY" ;; septel) V_DEFS="$V_DEFS -DSEPTEL_ONLY" ;; snf) V_DEFS="$V_DEFS -DSNF_ONLY" ;; null) AC_MSG_WARN(cannot determine packet capture interface) AC_MSG_WARN((see the INSTALL doc for more info)) ;; esac dnl dnl Now figure out how we get a list of interfaces and addresses, dnl if we support capturing. Don't bother if we don't support dnl capturing. dnl if test "$V_PCAP" = null then # # We can't capture, so we can't open any capture # devices, so we won't return any interfaces. # V_FINDALLDEVS=null else AC_CHECK_FUNC(getifaddrs,[ # # We have "getifaddrs()"; make sure we have # as well, just in case some platform is really weird. # AC_CHECK_HEADER(ifaddrs.h,[ # # We have the header, so we use "getifaddrs()" to # get the list of interfaces. # V_FINDALLDEVS=getad ],[ # # We don't have the header - give up. # XXX - we could also fall back on some other # mechanism, but, for now, this'll catch this # problem so that we can at least try to figure # out something to do on systems with "getifaddrs()" # but without "ifaddrs.h", if there is something # we can do on those systems. # AC_MSG_ERROR([Your system has getifaddrs() but doesn't have a usable .]) ]) ],[ # # Well, we don't have "getifaddrs()", so we have to use # some other mechanism; determine what that mechanism is. # # The first thing we use is the type of capture mechanism, # which is somewhat of a proxy for the OS we're using. # case "$V_PCAP" in dlpi|libdlpi) AC_CHECK_HEADERS(sys/bufmod.h sys/dlpi_ext.h) # # This might be Solaris 8 or later, with # SIOCGLIFCONF, or it might be some other OS # or some older version of Solaris, with # just SIOCGIFCONF. # AC_MSG_CHECKING(whether we have SIOCGLIFCONF) AC_CACHE_VAL(ac_cv_lbl_have_siocglifconf, AC_TRY_COMPILE( [#include #include #include #include #include ], [ioctl(0, SIOCGLIFCONF, (char *)0);], ac_cv_lbl_have_siocglifconf=yes, ac_cv_lbl_have_siocglifconf=no)) AC_MSG_RESULT($ac_cv_lbl_have_siocglifconf) if test $ac_cv_lbl_have_siocglifconf = yes ; then V_FINDALLDEVS=glifc else V_FINDALLDEVS=gifc fi # # Needed for common functions used by pcap-[dlpi,libdlpi].c # SSRC="dlpisubs.c" ;; *) # # Assume we just have SIOCGIFCONF. # (XXX - on at least later Linux kernels, there's # another mechanism, and we should be using that # instead.) # V_FINDALLDEVS=gifc ;; esac]) fi ]) AC_MSG_CHECKING(for socklen_t) AC_TRY_COMPILE([ #include #include ], [ socklen_t x; ], have_socklen_t=yes, have_socklen_t=no) if test "x$have_socklen_t" = "xyes"; then AC_DEFINE(HAVE_SOCKLEN_T, 1, [define if socklen_t is defined]) fi AC_MSG_RESULT($have_socklen_t) AC_ARG_ENABLE(ipv6, AC_HELP_STRING([--enable-ipv6],[build IPv6-capable version @<:@default=yes, if getaddrinfo available@:>@]), [], [enable_ipv6=ifavailable]) if test "$enable_ipv6" != "no"; then AC_CHECK_FUNC(getaddrinfo, [ AC_DEFINE(INET6,1,[IPv6]) ], [ if test "$enable_ipv6" != "ifavailable"; then AC_MSG_FAILURE([--enable-ipv6 was given, but getaddrinfo isn't available]) fi ]) fi AC_MSG_CHECKING(whether to build optimizer debugging code) AC_ARG_ENABLE(optimizer-dbg, AC_HELP_STRING([--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, AC_HELP_STRING([--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}) # Check for Endace DAG card support. AC_ARG_WITH([dag], AC_HELP_STRING([--with-dag@<:@=DIR@:>@],[include Endace DAG support @<:@"yes", "no" or DIR; default="yes" on BSD and Linux if present@:>@]), [ if test "$withval" = no then # User doesn't want DAG support. want_dag=no elif test "$withval" = yes then # User wants DAG support but hasn't specified a directory. want_dag=yes else # User wants DAG support and has specified a directory, so use the provided value. want_dag=yes dag_root=$withval fi ],[ # # Use DAG API if present, otherwise don't # want_dag=ifpresent ]) AC_ARG_WITH([dag-includes], AC_HELP_STRING([--with-dag-includes=DIR],[Endace DAG include directory]), [ # User wants DAG support and has specified a header directory, so use the provided value. want_dag=yes dag_include_dir=$withval ],[]) AC_ARG_WITH([dag-libraries], AC_HELP_STRING([--with-dag-libraries=DIR],[Endace DAG library directory]), [ # User wants DAG support and has specified a library directory, so use the provided value. want_dag=yes dag_lib_dir=$withval ],[]) case "$V_PCAP" in linux|bpf|dag) # # We support the DAG API if we're on Linux or BSD, or if we're # building a DAG-only libpcap. # ;; *) # # If the user explicitly requested DAG, tell them it's not # supported. # # If they expressed no preference, don't include it. # if test $want_dag = yes; then AC_MSG_ERROR([DAG support is only available with 'linux' 'bpf' and 'dag' packet capture types]) elif test $want_dag = yes; then want_dag=no fi ;; esac ac_cv_lbl_dag_api=no if test "$want_dag" != no; then AC_MSG_CHECKING([whether we have DAG API headers]) # If necessary, set default paths for DAG API headers and libraries. if test -z "$dag_root"; then dag_root=/usr/local fi if test -z "$dag_include_dir"; then dag_include_dir="$dag_root/include" fi if test -z "$dag_lib_dir"; then dag_lib_dir="$dag_root/lib" fi if test -z "$dag_tools_dir"; then dag_tools_dir="$dag_root/tools" fi if test -r $dag_include_dir/dagapi.h; then ac_cv_lbl_dag_api=yes fi AC_MSG_RESULT([$ac_cv_lbl_dag_api ($dag_include_dir)]) fi if test $ac_cv_lbl_dag_api = yes; then V_INCLS="$V_INCLS -I$dag_include_dir" if test $V_PCAP != dag ; then SSRC="pcap-dag.c" fi # See if we can find a general version string. # Don't need to save and restore LIBS to prevent -ldag being # included if there's a found-action (arg 3). saved_ldflags=$LDFLAGS LDFLAGS="-L$dag_lib_dir" AC_CHECK_LIB([dag], [dag_attach_stream], [dag_streams="1"], [dag_streams="0"]) AC_CHECK_LIB([dag],[dag_get_erf_types], [ AC_DEFINE(HAVE_DAG_GET_ERF_TYPES, 1, [define if you have dag_get_erf_types()])]) AC_CHECK_LIB([dag],[dag_get_stream_erf_types], [ AC_DEFINE(HAVE_DAG_GET_STREAM_ERF_TYPES, 1, [define if you have dag_get_stream_erf_types()])]) LDFLAGS=$saved_ldflags if test "$dag_streams" = 1; then AC_DEFINE(HAVE_DAG_STREAMS_API, 1, [define if you have streams capable DAG API]) LIBS="$LIBS -ldag" LDFLAGS="$LDFLAGS -L$dag_lib_dir" AC_CHECK_LIB([vdag],[vdag_set_device_info], [ac_dag_have_vdag="1"], [ac_dag_have_vdag="0"]) if test "$ac_dag_have_vdag" = 1; then AC_DEFINE(HAVE_DAG_VDAG, 1, [define if you have vdag_set_device_info()]) LIBS="$LIBS -lpthread" fi fi AC_DEFINE(HAVE_DAG_API, 1, [define if you have the DAG API]) fi AC_MSG_CHECKING(whether we have the DAG API) if test $ac_cv_lbl_dag_api = no; then AC_MSG_RESULT(no) if test "$want_dag" = yes; then # User wanted DAG support but we couldn't find it. AC_MSG_ERROR([DAG API requested, but not found at $dag_root: use --without-dag]) fi if test "$V_PCAP" = dag; then # User requested "dag" capture type but the DAG API wasn't # found. AC_MSG_ERROR([Specifying the capture type as "dag" requires the DAG API to be present; use the --with-dag options to specify the location. (Try "./configure --help" for more information.)]) fi else AC_MSG_RESULT(yes) fi AC_ARG_WITH(septel, AC_HELP_STRING([--with-septel@<:@=DIR@:>@],[include Septel support (located in directory DIR, if supplied). @<:@default=yes, on Linux, if present@:>@]), [ if test "$withval" = no then want_septel=no elif test "$withval" = yes then want_septel=yes septel_root= else want_septel=yes septel_root=$withval fi ],[ # # Use Septel API if present, otherwise don't # want_septel=ifpresent septel_root=./../septel ]) ac_cv_lbl_septel_api=no case "$V_PCAP" in linux|septel) # # We support the Septel API if we're on Linux, or if we're building # a Septel-only libpcap. # ;; *) # # If the user explicitly requested Septel, tell them it's not # supported. # # If they expressed no preference, don't include it. # if test $want_septel = yes; then AC_MSG_ERROR(Septel support only available with 'linux' and 'septel' packet capture types) elif test $want_septel = yes; then want_septel=no fi ;; esac if test "$with_septel" != no; then AC_MSG_CHECKING(whether we have Septel API) if test -z "$septel_root"; then septel_root=$srcdir/../septel fi septel_tools_dir="$septel_root" septel_include_dir="$septel_root/INC" ac_cv_lbl_septel_api=no if test -r "$septel_include_dir/msg.h"; then V_INCLS="$V_INCLS -I$septel_include_dir" ADDLOBJS="$ADDLOBJS $septel_tools_dir/asciibin.o $septel_tools_dir/bit2byte.o $septel_tools_dir/confirm.o $septel_tools_dir/fmtmsg.o $septel_tools_dir/gct_unix.o $septel_tools_dir/hqueue.o $septel_tools_dir/ident.o $septel_tools_dir/mem.o $septel_tools_dir/pack.o $septel_tools_dir/parse.o $septel_tools_dir/pool.o $septel_tools_dir/sdlsig.o $septel_tools_dir/strtonum.o $septel_tools_dir/timer.o $septel_tools_dir/trace.o" ADDLARCHIVEOBJS="$ADDLARCHIVEOBJS $septel_tools_dir/asciibin.o $septel_tools_dir/bit2byte.o $septel_tools_dir/confirm.o $septel_tools_dir/fmtmsg.o $septel_tools_dir/gct_unix.o $septel_tools_dir/hqueue.o $septel_tools_dir/ident.o $septel_tools_dir/mem.o $septel_tools_dir/pack.o $septel_tools_dir/parse.o $septel_tools_dir/pool.o $septel_tools_dir/sdlsig.o $septel_tools_dir/strtonum.o $septel_tools_dir/timer.o $septel_tools_dir/trace.o" if test "$V_PCAP" != septel ; then SSRC="pcap-septel.c" fi ac_cv_lbl_septel_api=yes fi AC_MSG_RESULT($ac_cv_lbl_septel_api) if test $ac_cv_lbl_septel_api = no; then if test "$want_septel" = yes; then AC_MSG_ERROR(Septel API not found under directory $septel_root; use --without-septel) fi else AC_DEFINE(HAVE_SEPTEL_API, 1, [define if you have a Septel API]) fi fi if test "$V_PCAP" = septel -a "$ac_cv_lbl_septel_api" = no; then AC_MSG_ERROR(Specifying the capture type as 'septel' requires the Septel API to be present; use --with-septel=DIR) fi # Check for Myricom SNF support. AC_ARG_WITH([snf], AC_HELP_STRING([--with-snf@<:@=DIR@:>@],[include Myricom SNF support @<:@"yes", "no" or DIR; default="yes" on BSD and Linux if present@:>@]), [ if test "$withval" = no then # User explicitly doesn't want SNF want_snf=no elif test "$withval" = yes then # User wants SNF support but hasn't specific a directory. want_snf=yes else # User wants SNF support with a specified directory. want_snf=yes snf_root=$withval fi ],[ # # Use Sniffer API if present, otherwise don't # want_snf=ifpresent ]) AC_ARG_WITH([snf-includes], AC_HELP_STRING([--with-snf-includes=DIR],[Myricom SNF include directory]), [ # User wants SNF with specific header directory want_snf=yes snf_include_dir=$withval ],[]) AC_ARG_WITH([snf-libraries], AC_HELP_STRING([--with-snf-libraries=DIR],[Myricom SNF library directory]), [ # User wants SNF with specific lib directory want_snf=yes snf_lib_dir=$withval ],[]) case "$V_PCAP" in bpf|linux|snf) # # We support the Sniffer API if we're on BSD, Linux, or if we're # building a Sniffer-only libpcap. # ;; *) # # If the user explicitly requested Sniffer, tell them it's not # supported. # # If they expressed no preference, don't include it. # if test $want_snf = yes; then AC_MSG_ERROR(Myricom SNF support only available with 'bpf' 'linux' and 'snf' packet capture types) elif test $want_snf = yes; then want_snf=no fi ;; esac ac_cv_lbl_snf_api=no if test "$with_snf" != no; then AC_MSG_CHECKING(whether we have Myricom Sniffer API) if test -z "$snf_root"; then snf_root=/opt/snf fi if test -z "$snf_include_dir"; then snf_include_dir="$snf_root/include" fi if test -z "$snf_lib_dir"; then snf_lib_dir="$snf_root/lib" fi if test -f "$snf_include_dir/snf.h"; then ac_cv_lbl_snf_api=yes fi AC_MSG_RESULT([$ac_cv_lbl_snf_api ($snf_root)]) if test $ac_cv_lbl_snf_api = no; then if test "$want_snf" = yes; then AC_MSG_ERROR(SNF API headers not found under $snf_include_dir; use --without-snf) fi else saved_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -L$snf_lib_dir" AC_CHECK_LIB([snf], [snf_init], [ac_cv_lbl_snf_api="yes"], [ac_cv_lbl_snf_api="no"]) LDFLAGS="$saved_ldflags" if test $ac_cv_lbl_snf_api = no; then if test "$want_snf" = yes; then AC_MSG_ERROR(SNF API cannot correctly be linked check config.log; use --without-snf) fi else V_INCLS="$V_INCLS -I$snf_include_dir" LIBS="$LIBS -lsnf" LDFLAGS="$LDFLAGS -L$snf_lib_dir" if test "$V_PCAP" != snf ; then SSRC="pcap-snf.c" fi AC_DEFINE(HAVE_SNF_API, 1, [define if you have Myricom SNF API]) fi fi fi if test "$V_PCAP" = snf -a "$ac_cv_lbl_snf_api" = no; then AC_MSG_ERROR(Specifying the capture type as 'snf' requires the Myricom Sniffer API to be present; use --with-snf=DIR) fi 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 . # Try lexing it and complain if it can't deal. AC_CACHE_CHECK([for capable lex], tcpdump_cv_capable_lex, if lex -t scanner.l > /dev/null 2>&1; then tcpdump_cv_capable_lex=yes else tcpdump_cv_capable_lex=insufficient fi) if test $tcpdump_cv_capable_lex = insufficient ; then AC_MSG_ERROR([Your operating system's lex is insufficient to compile libpcap. flex is a lex replacement that has many advantages, including being able to compile libpcap. For more information, see http://www.gnu.org/software/flex/flex.html .]) fi fi # # Assume, by default, no support for shared libraries and V7/BSD convention # for man pages (file formats in section 5, miscellaneous info in section 7). # Individual cases can override this. # DYEXT="none" MAN_FILE_FORMATS=5 MAN_MISC_INFO=7 case "$host_os" in aix*) dnl Workaround to enable certain features AC_DEFINE(_SUN,1,[define on AIX to get certain functions]) # # AIX makes it fun to build shared and static libraries, # because they're *both* ".a" archive libraries. We # build the static library for the benefit of the traditional # scheme of building libpcap and tcpdump in subdirectories of # the same directory, with tcpdump statically linked with the # libpcap in question, but we also build a shared library as # "libpcap.shareda" and install *it*, rather than the static # library, as "libpcap.a". # DYEXT="shareda" case "$V_PCAP" in dlpi) # # If we're using DLPI, applications will need to # use /lib/pse.exp if present, as we use the # STREAMS routines. # pseexe="/lib/pse.exp" AC_MSG_CHECKING(for $pseexe) if test -f $pseexe ; then AC_MSG_RESULT(yes) LIBS="-I:$pseexe" fi ;; bpf) # # If we're using BPF, we need "-lodm" and "-lcfg", as # we use them to load the BPF module. # LIBS="-lodm -lcfg" ;; esac ;; darwin*) DYEXT="dylib" V_CCOPT="$V_CCOPT -fno-common" AC_ARG_ENABLE(universal, AC_HELP_STRING([--disable-universal],[don't build universal on OS X])) if test "$enable_universal" != "no"; then case "$host_os" in darwin9.*) # # Leopard. Build for 32-bit PowerPC, 64-bit # PowerPC, x86, and x86-64, with 32-bit PowerPC # first. (That's what Apple does.) # V_CCOPT="$V_CCOPT -arch ppc -arch ppc64 -arch i386 -arch x86_64" LDFLAGS="$LDFLAGS -arch ppc -arch ppc64 -arch i386 -arch x86_64" ;; darwin10.*) # # Snow Leopard. Build for x86-64, x86, and # 32-bit PowerPC, with x86-64 first. (That's # what Apple does, even though Snow Leopard # doesn't run on PPC, so PPC libpcap runs under # Rosetta, and Rosetta doesn't support BPF # ioctls, so PPC programs can't do live # captures.) # V_CCOPT="$V_CCOPT -arch x86_64 -arch i386 -arch ppc" LDFLAGS="$LDFLAGS -arch x86_64 -arch i386 -arch ppc" ;; darwin11.*) # # Lion. Build for x86-64 and x86, with x86-64 # first. (That's probably what Apple does, # given that Rosetta is gone.) # V_CCOPT="$V_CCOPT -arch x86_64 -arch i386" LDFLAGS="$LDFLAGS -arch x86_64 -arch i386" ;; esac fi ;; hpux9*) AC_DEFINE(HAVE_HPUX9,1,[on HP-UX 9.x]) # # Use System V conventions for man pages. # MAN_FILE_FORMATS=4 MAN_MISC_INFO=5 ;; hpux10.0*) # # Use System V conventions for man pages. # MAN_FILE_FORMATS=4 MAN_MISC_INFO=5 ;; hpux10.1*) # # Use System V conventions for man pages. # MAN_FILE_FORMATS=4 MAN_MISC_INFO=5 ;; hpux*) dnl HPUX 10.20 and above is similar to HPUX 9, but dnl not the same.... dnl dnl XXX - DYEXT should be set to "sl" if this is building dnl for 32-bit PA-RISC, but should be left as "so" for dnl 64-bit PA-RISC or, I suspect, IA-64. AC_DEFINE(HAVE_HPUX10_20_OR_LATER,1,[on HP-UX 10.20 or later]) if test "`uname -m`" = "ia64"; then DYEXT="so" else DYEXT="sl" fi # # "-b" builds a shared library; "+h" sets the soname. # SHLIB_OPT="-b" SONAME_OPT="+h" # # Use System V conventions for man pages. # MAN_FILE_FORMATS=4 MAN_MISC_INFO=5 ;; irix*) # # Use System V conventions for man pages. # MAN_FILE_FORMATS=4 MAN_MISC_INFO=5 ;; linux*|freebsd*|netbsd*|openbsd*|dragonfly*|kfreebsd*|gnu*) DYEXT="so" # # Compiler assumed to be GCC; run-time linker may require a -R # flag. # if test "$libdir" != "/usr/lib"; then V_RFLAGS=-Wl,-R$libdir fi ;; osf*) DYEXT="so" # # Use System V conventions for man pages. # MAN_FILE_FORMATS=4 MAN_MISC_INFO=5 ;; sinix*) AC_MSG_CHECKING(if SINIX compiler defines sinix) AC_CACHE_VAL(ac_cv_cc_sinix_defined, AC_TRY_COMPILE( [], [int i = sinix;], ac_cv_cc_sinix_defined=yes, ac_cv_cc_sinix_defined=no)) AC_MSG_RESULT($ac_cv_cc_sinix_defined) if test $ac_cv_cc_sinix_defined = no ; then AC_DEFINE(sinix,1,[on sinix]) fi ;; solaris*) AC_DEFINE(HAVE_SOLARIS,1,[On solaris]) DYEXT="so" # # Use System V conventions for man pages. # MAN_FILE_FORMATS=4 MAN_MISC_INFO=5 ;; esac AC_ARG_ENABLE(shared, AC_HELP_STRING([--enable-shared],[build shared libraries @<:@default=yes, if support available@:>@])) test "x$enable_shared" = "xno" && DYEXT="none" AC_PROG_RANLIB AC_CHECK_TOOL([AR], [ar]) AC_LBL_DEVEL(V_CCOPT) AC_LBL_SOCKADDR_SA_LEN AC_LBL_SOCKADDR_STORAGE AC_LBL_HP_PPA_INFO_T_DL_MODULE_ID_1 AC_LBL_UNALIGNED_ACCESS # # Makefile.in includes rules to generate version.h, so we assume # that it will be generated if autoconf is used. # AC_DEFINE(HAVE_VERSION_H, 1, [define if version.h is generated in the build procedure]) rm -f net ln -s ${srcdir}/bpf/net net AC_SUBST(V_CCOPT) AC_SUBST(V_DEFS) AC_SUBST(V_FINDALLDEVS) AC_SUBST(V_INCLS) AC_SUBST(V_LEX) AC_SUBST(V_PCAP) AC_SUBST(V_SHLIB_CMD) AC_SUBST(V_SHLIB_OPT) AC_SUBST(V_SONAME_OPT) AC_SUBST(V_RPATH_OPT) AC_SUBST(V_YACC) AC_SUBST(ADDLOBJS) AC_SUBST(ADDLARCHIVEOBJS) AC_SUBST(SSRC) AC_SUBST(DYEXT) AC_SUBST(MAN_FILE_FORMATS) AC_SUBST(MAN_MISC_INFO) dnl check for USB sniffing support AC_MSG_CHECKING(for USB sniffing support) case "$host_os" in linux*) AC_DEFINE(PCAP_SUPPORT_USB, 1, [target host supports USB sniffing]) USB_SRC=pcap-usb-linux.c AC_MSG_RESULT(yes) ac_usb_dev_name=`udevinfo -q name -p /sys/class/usb_device/usbmon 2>/dev/null` if test $? -ne 0 ; then ac_usb_dev_name="usbmon" fi AC_DEFINE_UNQUOTED(LINUX_USB_MON_DEV, "/dev/$ac_usb_dev_name", [path for device for USB sniffing]) AC_MSG_NOTICE(Device for USB sniffing is /dev/$ac_usb_dev_name) # # Do we have a version of available? # If so, we might need it for . # AC_CHECK_HEADERS(linux/compiler.h) if test "$ac_cv_header_linux_compiler_h" = yes; then # # Yes - include it when testing for . # AC_CHECK_HEADERS(linux/usbdevice_fs.h,,,[#include ]) else AC_CHECK_HEADERS(linux/usbdevice_fs.h) fi if test "$ac_cv_header_linux_usbdevice_fs_h" = yes; then # # OK, does it define bRequestType? Older versions of the kernel # define fields with names like "requesttype, "request", and # "value", rather than "bRequestType", "bRequest", and # "wValue". # AC_MSG_CHECKING(if usbdevfs_ctrltransfer struct has bRequestType member) AC_CACHE_VAL(ac_cv_usbdevfs_ctrltransfer_has_bRequestType, AC_TRY_COMPILE([ AC_INCLUDES_DEFAULT #ifdef HAVE_SYS_BITYPES_H #include #endif #ifdef HAVE_LINUX_COMPILER_H #include #endif #include ], [u_int i = sizeof(((struct usbdevfs_ctrltransfer *)0)->bRequestType)], ac_cv_usbdevfs_ctrltransfer_has_bRequestType=yes, ac_cv_usbdevfs_ctrltransfer_has_bRequestType=no)) AC_MSG_RESULT($ac_cv_usbdevfs_ctrltransfer_has_bRequestType) if test $ac_cv_usbdevfs_ctrltransfer_has_bRequestType = yes ; then AC_DEFINE(HAVE_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE,1, [if struct usbdevfs_ctrltransfer has bRequestType]) fi fi ;; *) AC_MSG_RESULT(no) ;; esac AC_SUBST(PCAP_SUPPORT_USB) AC_SUBST(USB_SRC) dnl check for netfilter sniffing support AC_MSG_CHECKING(whether the platform could support netfilter sniffing) case "$host_os" in linux*) AC_MSG_RESULT(yes) # # Life's too short to deal with trying to get this to compile # if you don't get the right types defined with # __KERNEL_STRICT_NAMES getting defined by some other include. # # Check whether the includes Just Work. If not, don't turn on # netfilter support. # AC_MSG_CHECKING(whether we can compile the netfilter support) AC_CACHE_VAL(ac_cv_netfilter_can_compile, AC_TRY_COMPILE([ AC_INCLUDES_DEFAULT #include +#include #include #include +#include #include -#include ], +#include +#include ], [], ac_cv_netfilter_can_compile=yes, ac_cv_netfilter_can_compile=no)) AC_MSG_RESULT($ac_cv_netfilter_can_compile) if test $ac_cv_netfilter_can_compile = yes ; then AC_DEFINE(PCAP_SUPPORT_NETFILTER, 1, [target host supports netfilter sniffing]) NETFILTER_SRC=pcap-netfilter-linux.c fi ;; *) AC_MSG_RESULT(no) ;; esac AC_SUBST(PCAP_SUPPORT_NETFILTER) AC_SUBST(NETFILTER_SRC) AC_ARG_ENABLE([bluetooth], [AC_HELP_STRING([--enable-bluetooth],[enable Bluetooth support @<:@default=yes, if support available@:>@])], -,enable_bluetooth=yes) + [], + [enable_bluetooth=yes]) if test "x$enable_bluetooth" != "xno" ; then dnl check for Bluetooth sniffing support case "$host_os" in linux*) AC_CHECK_HEADER(bluetooth/bluetooth.h, [ AC_DEFINE(PCAP_SUPPORT_BT, 1, [target host supports Bluetooth sniffing]) BT_SRC=pcap-bt-linux.c AC_MSG_NOTICE(Bluetooth sniffing is supported) + + # + # OK, does struct sockaddr_hci have an hci_channel + # member? + # + AC_MSG_CHECKING(if struct sockaddr_hci has hci_channel member) + AC_CACHE_VAL(ac_cv_lbl_sockaddr_hci_has_hci_channel, + AC_TRY_COMPILE( +[ +#include +#include +], + [u_int i = sizeof(((struct sockaddr_hci *)0)->hci_channel)], + ac_cv_lbl_sockaddr_hci_has_hci_channel=yes, + ac_cv_lbl_sockaddr_hci_has_hci_channel=no)) + AC_MSG_RESULT($ac_cv_lbl_sockaddr_hci_has_hci_channel) + if test $ac_cv_lbl_sockaddr_hci_has_hci_channel = yes ; then + AC_DEFINE(SOCKADDR_HCI_HAS_HCI_CHANNEL,, + [if struct sockaddr_hci has hci_channel member]) + fi ], AC_MSG_NOTICE(Bluetooth sniffing is not supported; install bluez-lib devel to enable it) ) ;; *) AC_MSG_NOTICE(no Bluetooth sniffing support implemented for $host_os) ;; esac AC_SUBST(PCAP_SUPPORT_BT) AC_SUBST(BT_SRC) fi AC_ARG_ENABLE([canusb], -[AC_HELP_STRING([--enable-canusb],[enable canusb support @<:@default=yes, if support available@:>@])] -,enable_canusb=yes) +[AC_HELP_STRING([--enable-canusb],[enable canusb support @<:@default=yes, if support available@:>@])], + [], + [enable_canusb=yes]) if test "x$enable_canusb" != "xno" ; then dnl check for canusb support case "$host_os" in linux*) AC_CHECK_HEADER(libusb-1.0/libusb.h, [ AC_DEFINE(PCAP_SUPPORT_CANUSB, 1, [target host supports canusb]) CANUSB_SRC=pcap-canusb-linux.c - LIBS="-lusb-1.0 $LIBS" + LIBS="-lusb-1.0 -lpthread $LIBS" AC_MSG_NOTICE(canusb sniffing is supported) ], AC_MSG_NOTICE(canusb sniffing is not supported; install libusb1.0 lib devel to enable it) ) ;; *) AC_MSG_NOTICE(no canusb support implemented for $host_os) ;; esac AC_SUBST(PCAP_SUPPORT_CANUSB) AC_SUBST(CANUSB_SRC) fi AC_ARG_ENABLE([can], [AC_HELP_STRING([--enable-can],[enable CAN support @<:@default=yes, if support available@:>@])], -,enable_can=yes) + [], + [enable_can=yes]) if test "x$enable_can" != "xno" ; then dnl check for CAN sniffing support case "$host_os" in linux*) AC_CHECK_HEADER(linux/can.h, [ AC_DEFINE(PCAP_SUPPORT_CAN, 1, [target host supports CAN sniffing]) CAN_SRC=pcap-can-linux.c AC_MSG_NOTICE(CAN sniffing is supported)], AC_MSG_NOTICE(CAN sniffing is not supported), [#include ] ) ;; *) AC_MSG_NOTICE(no CAN sniffing support implemented for $host_os) ;; esac AC_SUBST(PCAP_SUPPORT_CAN) AC_SUBST(CAN_SRC) fi dnl check for hardware timestamp support case "$host_os" in linux*) AC_CHECK_HEADERS([linux/net_tstamp.h]) ;; *) AC_MSG_NOTICE(no hardware timestamp support implemented for $host_os) ;; esac AC_PROG_INSTALL AC_CONFIG_HEADER(config.h) AC_OUTPUT(Makefile pcap-filter.manmisc pcap-linktype.manmisc pcap-tstamp.manmisc pcap-savefile.manfile pcap.3pcap pcap_compile.3pcap pcap_datalink.3pcap pcap_dump_open.3pcap pcap_list_datalinks.3pcap pcap_list_tstamp_types.3pcap pcap_open_dead.3pcap pcap_open_offline.3pcap pcap_set_tstamp_type.3pcap) if test -f .devel ; then make depend fi exit 0 Index: stable/9/contrib/libpcap/fad-getad.c =================================================================== --- stable/9/contrib/libpcap/fad-getad.c (revision 252280) +++ stable/9/contrib/libpcap/fad-getad.c (revision 252281) @@ -1,297 +1,286 @@ /* -*- 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. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Computer Systems * Engineering Group at Lawrence Berkeley Laboratory. * 4. Neither the name of the University nor of the Laboratory may be used * to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/fad-getad.c,v 1.12 2007-09-14 00:44:55 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include "pcap-int.h" #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif #ifdef AF_PACKET # ifdef HAVE_NETPACKET_PACKET_H /* Solaris 11 and later, Linux distributions with newer glibc */ # include # else /* HAVE_NETPACKET_PACKET_H */ /* LynxOS, Linux distributions with older glibc */ # ifdef __Lynx__ /* LynxOS */ # include # else /* __Lynx__ */ /* Linux */ # include # include # endif /* __Lynx__ */ # endif /* HAVE_NETPACKET_PACKET_H */ #endif /* AF_PACKET */ /* * 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, some use the RFC 2553 * variant of the old BSD scheme (with "struct sockaddr_storage" rather * than "struct sockaddr"), and some use the new BSD scheme. * * Some versions of GNU libc use neither scheme, but has an "SA_LEN()" * macro that determines the size based on the address family. Other * versions don't have "SA_LEN()" (as it was in drafts of RFC 2553 * but not in the final version). On the latter systems, we explicitly * check the AF_ type to determine the length; we assume that on * all those systems we have "struct sockaddr_storage". */ #ifndef SA_LEN #ifdef HAVE_SOCKADDR_SA_LEN #define SA_LEN(addr) ((addr)->sa_len) #else /* HAVE_SOCKADDR_SA_LEN */ #ifdef HAVE_SOCKADDR_STORAGE static size_t get_sa_len(struct sockaddr *addr) { switch (addr->sa_family) { #ifdef AF_INET case AF_INET: return (sizeof (struct sockaddr_in)); #endif #ifdef AF_INET6 case AF_INET6: return (sizeof (struct sockaddr_in6)); #endif #ifdef AF_PACKET case AF_PACKET: return (sizeof (struct sockaddr_ll)); #endif default: return (sizeof (struct sockaddr)); } } #define SA_LEN(addr) (get_sa_len(addr)) #else /* HAVE_SOCKADDR_STORAGE */ #define SA_LEN(addr) (sizeof (struct sockaddr)) #endif /* HAVE_SOCKADDR_STORAGE */ #endif /* HAVE_SOCKADDR_SA_LEN */ #endif /* SA_LEN */ /* * 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. - * - * This is the implementation used on platforms that have "getifaddrs()". */ int -pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) +pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf) { pcap_if_t *devlist = NULL; struct ifaddrs *ifap, *ifa; struct sockaddr *addr, *netmask, *broadaddr, *dstaddr; size_t addr_size, broadaddr_size, dstaddr_size; int ret = 0; char *p, *q; /* * 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_addr" was apparently null on at least one * interface on some system. * * "ifa_broadaddr" may be non-null even on * non-broadcast interfaces, and was null on * at least one OpenBSD 3.4 system on at least * one interface with IFF_BROADCAST set. * * "ifa_dstaddr" was, on at least one FreeBSD 4.1 * system, non-null on a non-point-to-point * interface. * * Therefore, we supply the address and netmask only * if "ifa_addr" is non-null (if there's no address, * there's obviously no netmask), and supply the * broadcast and destination addresses if the appropriate * flag is set *and* the appropriate "ifa_" entry doesn't * evaluate to a null pointer. */ if (ifa->ifa_addr != NULL) { addr = ifa->ifa_addr; addr_size = SA_LEN(addr); netmask = ifa->ifa_netmask; } else { addr = NULL; addr_size = 0; netmask = NULL; } if (ifa->ifa_flags & IFF_BROADCAST && ifa->ifa_broadaddr != NULL) { broadaddr = ifa->ifa_broadaddr; broadaddr_size = SA_LEN(broadaddr); } else { broadaddr = NULL; broadaddr_size = 0; } if (ifa->ifa_flags & IFF_POINTOPOINT && ifa->ifa_dstaddr != NULL) { dstaddr = ifa->ifa_dstaddr; dstaddr_size = SA_LEN(ifa->ifa_dstaddr); } else { dstaddr = NULL; dstaddr_size = 0; } /* * If this entry has a colon followed by a number at * the end, we assume it's a logical interface. Those * are just the way you assign multiple IP addresses to * a real interface on Linux, so an entry for a logical * interface should be treated like the entry for the * real interface; we do that by stripping off the ":" * and the number. * * XXX - should we do this only on Linux? */ p = strchr(ifa->ifa_name, ':'); if (p != NULL) { /* * We have a ":"; is it followed by a number? */ q = p + 1; while (isdigit((unsigned char)*q)) q++; if (*q == '\0') { /* * All digits after the ":" until the end. * Strip off the ":" and everything after * it. */ *p = '\0'; } } /* * Add information for this address to the list. */ if (add_addr_to_iflist(&devlist, ifa->ifa_name, ifa->ifa_flags, addr, addr_size, netmask, addr_size, broadaddr, broadaddr_size, dstaddr, dstaddr_size, errbuf) < 0) { ret = -1; break; } } freeifaddrs(ifap); - - if (ret != -1) { - /* - * We haven't had any errors yet; do any platform-specific - * operations to add devices. - */ - if (pcap_platform_finddevs(&devlist, 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); } Index: stable/9/contrib/libpcap/fad-gifc.c =================================================================== --- stable/9/contrib/libpcap/fad-gifc.c (revision 252280) +++ stable/9/contrib/libpcap/fad-gifc.c (revision 252281) @@ -1,433 +1,425 @@ /* -*- 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. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Computer Systems * Engineering Group at Lawrence Berkeley Laboratory. * 4. Neither the name of the University nor of the Laboratory may be used * to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/fad-gifc.c,v 1.12 2008-08-06 07:34:09 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #ifdef HAVE_SYS_SOCKIO_H #include #endif #include /* concession to AIX */ struct mbuf; /* Squelch compiler warnings on some platforms for */ struct rtentry; /* declarations in */ #include #include #include #include #include #include #include #include #include #include "pcap-int.h" #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #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, some use the RFC 2553 * variant of the old BSD scheme (with "struct sockaddr_storage" rather * than "struct sockaddr"), and some use the new BSD scheme. * * Some versions of GNU libc use neither scheme, but has an "SA_LEN()" * macro that determines the size based on the address family. Other * versions don't have "SA_LEN()" (as it was in drafts of RFC 2553 * but not in the final version). * * We assume that a UNIX that doesn't have "getifaddrs()" and doesn't have * SIOCGLIFCONF, but has SIOCGIFCONF, uses "struct sockaddr" for the * address in an entry returned by SIOCGIFCONF. */ #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 */ /* * This is also fun. * * There is no ioctl that returns the amount of space required for all * the data that SIOCGIFCONF could return, and if a buffer is supplied * that's not large enough for all the data SIOCGIFCONF could return, * on at least some platforms it just returns the data that'd fit with * no indication that there wasn't enough room for all the data, much * less an indication of how much more room is required. * * The only way to ensure that we got all the data is to pass a buffer * large enough that the amount of space in the buffer *not* filled in * is greater than the largest possible entry. * * We assume that's "sizeof(ifreq.ifr_name)" plus 255, under the assumption * that no address is more than 255 bytes (on systems where the "sa_len" * field in a "struct sockaddr" is 1 byte, e.g. newer BSDs, that's the * case, and addresses are unlikely to be bigger than that in any case). */ #define MAX_SA_LEN 255 /* * 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. * * This is the implementation used on platforms that have SIOCGIFCONF but * don't have any other mechanism for getting a list of interfaces. * * XXX - or platforms that have other, better mechanisms but for which * we don't yet have code to use that mechanism; I think there's a better - * way on Linux, for example. + * way on Linux, for example, but if that better way is "getifaddrs()", + * we already have that. */ int -pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) +pcap_findalldevs_interfaces(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; #if defined (HAVE_SOLARIS) || defined (HAVE_HPUX10_20_OR_LATER) char *p, *q; #endif struct ifreq ifrflags, ifrnetmask, ifrbroadaddr, ifrdstaddr; struct sockaddr *netmask, *broadaddr, *dstaddr; size_t netmask_size, broadaddr_size, dstaddr_size; 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 have more than "sizeof(ifrp->ifr_name) + MAX_SA_LEN" * bytes left over in the buffer or we fail to get the * interface list 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 && (buf_size - ifc.ifc_len) > sizeof(ifrp->ifr_name) + MAX_SA_LEN) break; free(buf); buf_size *= 2; } ifrp = (struct ifreq *)buf; ifend = (struct ifreq *)(buf + ifc.ifc_len); for (; ifrp < ifend; ifrp = ifnext) { /* * XXX - what if this isn't an IPv4 address? Can * we still get the netmask, etc. with ioctls on * an IPv4 socket? * * The answer is probably platform-dependent, and * if the answer is "no" on more than one platform, * the way you work around it is probably platform- * dependent as well. */ n = SA_LEN(&ifrp->ifr_addr) + sizeof(ifrp->ifr_name); if (n < sizeof(*ifrp)) ifnext = ifrp + 1; else ifnext = (struct ifreq *)((char *)ifrp + n); /* * XXX - The 32-bit compatibility layer for Linux on IA-64 * is slightly broken. It correctly converts the structures * to and from kernel land from 64 bit to 32 bit but * doesn't update ifc.ifc_len, leaving it larger than the * amount really used. This means we read off the end * of the buffer and encounter an interface with an * "empty" name. Since this is highly unlikely to ever * occur in a valid case we can just finish looking for * interfaces if we see an empty name. */ if (!(*ifrp->ifr_name)) break; /* * Skip entries that begin with "dummy". * XXX - what are these? Is this Linux-specific? * Are there platforms on which we shouldn't do this? */ if (strncmp(ifrp->ifr_name, "dummy", 5) == 0) continue; /* * Get the flags for this interface, and skip it if it's * not up. */ 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; netmask_size = 0; } 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; netmask_size = SA_LEN(netmask); } /* * 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; broadaddr_size = 0; } 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; broadaddr_size = SA_LEN(broadaddr); } } else { /* * Not a broadcast interface, so no broadcast * address. */ broadaddr = NULL; broadaddr_size = 0; } /* * 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; dstaddr_size = 0; } 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; dstaddr_size = SA_LEN(dstaddr); } } else { /* * Not a point-to-point interface, so no destination * address. */ dstaddr = NULL; dstaddr_size = 0; } #if defined (HAVE_SOLARIS) || defined (HAVE_HPUX10_20_OR_LATER) /* * If this entry has a colon followed by a number at * the end, it's a logical interface. Those are just * the way you assign multiple IP addresses to a real * interface, so an entry for a logical interface should * be treated like the entry for the real interface; * we do that by stripping off the ":" and the number. */ p = strchr(ifrp->ifr_name, ':'); if (p != NULL) { /* * We have a ":"; is it followed by a number? */ q = p + 1; while (isdigit((unsigned char)*q)) q++; if (*q == '\0') { /* * All digits after the ":" until the end. * Strip off the ":" and everything after * it. */ *p = '\0'; } } #endif /* * Add information for this address to the list. */ if (add_addr_to_iflist(&devlist, ifrp->ifr_name, ifrflags.ifr_flags, &ifrp->ifr_addr, SA_LEN(&ifrp->ifr_addr), netmask, netmask_size, broadaddr, broadaddr_size, dstaddr, dstaddr_size, errbuf) < 0) { ret = -1; break; } } free(buf); (void)close(fd); - - if (ret != -1) { - /* - * We haven't had any errors yet; do any platform-specific - * operations to add devices. - */ - if (pcap_platform_finddevs(&devlist, 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); } Index: stable/9/contrib/libpcap/fad-glifc.c =================================================================== --- stable/9/contrib/libpcap/fad-glifc.c (revision 252280) +++ stable/9/contrib/libpcap/fad-glifc.c (revision 252281) @@ -1,386 +1,377 @@ /* -*- 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. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Computer Systems * Engineering Group at Lawrence Berkeley Laboratory. * 4. Neither the name of the University nor of the Laboratory may be used * to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/fad-glifc.c,v 1.7 2008-01-30 09:35:48 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #ifdef HAVE_SYS_SOCKIO_H #include #endif #include /* concession to AIX */ struct mbuf; /* Squelch compiler warnings on some platforms for */ struct rtentry; /* declarations in */ #include #include #include #include #include #include #include #include #include #include "pcap-int.h" #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif /* * 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. * * This is the implementation used on platforms that have SIOCGLIFCONF * but don't have "getifaddrs()". (Solaris 8 and later; we use * SIOCGLIFCONF rather than SIOCGIFCONF in order to get IPv6 addresses.) */ int -pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) +pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf) { pcap_if_t *devlist = NULL; register int fd4, fd6, fd; register struct lifreq *ifrp, *ifend; struct lifnum ifn; struct lifconf ifc; char *buf = NULL; unsigned buf_size; #ifdef HAVE_SOLARIS char *p, *q; #endif struct lifreq ifrflags, ifrnetmask, ifrbroadaddr, ifrdstaddr; struct sockaddr *netmask, *broadaddr, *dstaddr; int ret = 0; /* * Create a socket from which to fetch the list of interfaces, * and from which to fetch IPv4 information. */ fd4 = socket(AF_INET, SOCK_DGRAM, 0); if (fd4 < 0) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s", pcap_strerror(errno)); return (-1); } /* * Create a socket from which to fetch IPv6 information. */ fd6 = socket(AF_INET6, SOCK_DGRAM, 0); if (fd6 < 0) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s", pcap_strerror(errno)); (void)close(fd4); return (-1); } /* * How many entries will SIOCGLIFCONF return? */ ifn.lifn_family = AF_UNSPEC; ifn.lifn_flags = 0; ifn.lifn_count = 0; if (ioctl(fd4, SIOCGLIFNUM, (char *)&ifn) < 0) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGLIFNUM: %s", pcap_strerror(errno)); (void)close(fd6); (void)close(fd4); return (-1); } /* * Allocate a buffer for those entries. */ buf_size = ifn.lifn_count * sizeof (struct lifreq); buf = malloc(buf_size); if (buf == NULL) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); (void)close(fd6); (void)close(fd4); return (-1); } /* * Get the entries. */ ifc.lifc_len = buf_size; ifc.lifc_buf = buf; ifc.lifc_family = AF_UNSPEC; ifc.lifc_flags = 0; memset(buf, 0, buf_size); if (ioctl(fd4, SIOCGLIFCONF, (char *)&ifc) < 0) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGLIFCONF: %s", pcap_strerror(errno)); (void)close(fd6); (void)close(fd4); free(buf); return (-1); } /* * Loop over the entries. */ ifrp = (struct lifreq *)buf; ifend = (struct lifreq *)(buf + ifc.lifc_len); for (; ifrp < ifend; ifrp++) { /* * IPv6 or not? */ if (((struct sockaddr *)&ifrp->lifr_addr)->sa_family == AF_INET6) fd = fd6; else fd = fd4; /* * Skip entries that begin with "dummy". * XXX - what are these? Is this Linux-specific? * Are there platforms on which we shouldn't do this? */ if (strncmp(ifrp->lifr_name, "dummy", 5) == 0) continue; #ifdef HAVE_SOLARIS /* * Skip entries that have a ":" followed by a number * at the end - those are Solaris virtual interfaces * on which you can't capture. */ p = strchr(ifrp->lifr_name, ':'); if (p != NULL) { /* * We have a ":"; is it followed by a number? */ while (isdigit((unsigned char)*p)) p++; if (*p == '\0') { /* * All digits after the ":" until the end. */ continue; } } #endif /* * Get the flags for this interface, and skip it if it's * not up. */ strncpy(ifrflags.lifr_name, ifrp->lifr_name, sizeof(ifrflags.lifr_name)); if (ioctl(fd, SIOCGLIFFLAGS, (char *)&ifrflags) < 0) { if (errno == ENXIO) continue; (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGLIFFLAGS: %.*s: %s", (int)sizeof(ifrflags.lifr_name), ifrflags.lifr_name, pcap_strerror(errno)); ret = -1; break; } if (!(ifrflags.lifr_flags & IFF_UP)) continue; /* * Get the netmask for this address on this interface. */ strncpy(ifrnetmask.lifr_name, ifrp->lifr_name, sizeof(ifrnetmask.lifr_name)); memcpy(&ifrnetmask.lifr_addr, &ifrp->lifr_addr, sizeof(ifrnetmask.lifr_addr)); if (ioctl(fd, SIOCGLIFNETMASK, (char *)&ifrnetmask) < 0) { if (errno == EADDRNOTAVAIL) { /* * Not available. */ netmask = NULL; } else { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGLIFNETMASK: %.*s: %s", (int)sizeof(ifrnetmask.lifr_name), ifrnetmask.lifr_name, pcap_strerror(errno)); ret = -1; break; } } else netmask = (struct sockaddr *)&ifrnetmask.lifr_addr; /* * Get the broadcast address for this address on this * interface (if any). */ if (ifrflags.lifr_flags & IFF_BROADCAST) { strncpy(ifrbroadaddr.lifr_name, ifrp->lifr_name, sizeof(ifrbroadaddr.lifr_name)); memcpy(&ifrbroadaddr.lifr_addr, &ifrp->lifr_addr, sizeof(ifrbroadaddr.lifr_addr)); if (ioctl(fd, SIOCGLIFBRDADDR, (char *)&ifrbroadaddr) < 0) { if (errno == EADDRNOTAVAIL) { /* * Not available. */ broadaddr = NULL; } else { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGLIFBRDADDR: %.*s: %s", (int)sizeof(ifrbroadaddr.lifr_name), ifrbroadaddr.lifr_name, pcap_strerror(errno)); ret = -1; break; } } else broadaddr = (struct sockaddr *)&ifrbroadaddr.lifr_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.lifr_flags & IFF_POINTOPOINT) { strncpy(ifrdstaddr.lifr_name, ifrp->lifr_name, sizeof(ifrdstaddr.lifr_name)); memcpy(&ifrdstaddr.lifr_addr, &ifrp->lifr_addr, sizeof(ifrdstaddr.lifr_addr)); if (ioctl(fd, SIOCGLIFDSTADDR, (char *)&ifrdstaddr) < 0) { if (errno == EADDRNOTAVAIL) { /* * Not available. */ dstaddr = NULL; } else { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGLIFDSTADDR: %.*s: %s", (int)sizeof(ifrdstaddr.lifr_name), ifrdstaddr.lifr_name, pcap_strerror(errno)); ret = -1; break; } } else dstaddr = (struct sockaddr *)&ifrdstaddr.lifr_dstaddr; } else dstaddr = NULL; #ifdef HAVE_SOLARIS /* * If this entry has a colon followed by a number at * the end, it's a logical interface. Those are just * the way you assign multiple IP addresses to a real * interface, so an entry for a logical interface should * be treated like the entry for the real interface; * we do that by stripping off the ":" and the number. */ p = strchr(ifrp->lifr_name, ':'); if (p != NULL) { /* * We have a ":"; is it followed by a number? */ q = p + 1; while (isdigit((unsigned char)*q)) q++; if (*q == '\0') { /* * All digits after the ":" until the end. * Strip off the ":" and everything after * it. */ *p = '\0'; } } #endif /* * Add information for this address to the list. */ if (add_addr_to_iflist(&devlist, ifrp->lifr_name, ifrflags.lifr_flags, (struct sockaddr *)&ifrp->lifr_addr, sizeof (struct sockaddr_storage), netmask, sizeof (struct sockaddr_storage), broadaddr, sizeof (struct sockaddr_storage), dstaddr, sizeof (struct sockaddr_storage), errbuf) < 0) { ret = -1; break; } } free(buf); (void)close(fd6); (void)close(fd4); - - if (ret != -1) { - /* - * We haven't had any errors yet; do any platform-specific - * operations to add devices. - */ - if (pcap_platform_finddevs(&devlist, 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); } Index: stable/9/contrib/libpcap/fad-sita.c =================================================================== --- stable/9/contrib/libpcap/fad-sita.c (revision 252280) +++ stable/9/contrib/libpcap/fad-sita.c (revision 252281) @@ -1,61 +1,61 @@ /* * fad-sita.c: Packet capture interface additions for SITA ACN devices * * Copyright (c) 2007 Fulko Hew, SITA INC Canada, Inc * * License: BSD * * 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. The names of the authors may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ /* $Id: fad-sita.c */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "pcap-int.h" #include "pcap-sita.h" extern pcap_if_t *acn_if_list; /* pcap's list of available interfaces */ -int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) { +int pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf) { //printf("pcap_findalldevs()\n"); // fulko *alldevsp = 0; /* initialize the returned variables before we do anything */ strcpy(errbuf, ""); if (acn_parse_hosts_file(errbuf)) /* scan the hosts file for potential IOPs */ { //printf("pcap_findalldevs() returning BAD after parsehosts\n"); // fulko return -1; } //printf("pcap_findalldevs() got hostlist now finding devs\n"); // fulko if (acn_findalldevs(errbuf)) /* then ask the IOPs for their monitorable devices */ { //printf("pcap_findalldevs() returning BAD after findalldevs\n"); // fulko return -1; } *alldevsp = acn_if_list; acn_if_list = 0; /* then forget our list head, because someone will call pcap_freealldevs() to empty the malloc'ed stuff */ //printf("pcap_findalldevs() returning ZERO OK\n"); // fulko return 0; } Index: stable/9/contrib/libpcap/gencode.c =================================================================== --- stable/9/contrib/libpcap/gencode.c (revision 252280) +++ stable/9/contrib/libpcap/gencode.c (revision 252281) @@ -1,8537 +1,8487 @@ /*#define CHASE_CHAIN*/ /* * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * $FreeBSD$ */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.309 2008-12-23 20:13:29 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef WIN32 #include #else /* WIN32 */ #if HAVE_INTTYPES_H #include #elif HAVE_STDINT_H #include #endif #ifdef HAVE_SYS_BITYPES_H #include #endif #include #include #endif /* WIN32 */ /* * XXX - why was this included even on UNIX? */ #ifdef __MINGW32__ #include "ip6_misc.h" #endif #ifndef WIN32 #ifdef __NetBSD__ #include #endif #include #include #endif /* WIN32 */ #include #include #include #include #include #ifdef MSDOS #include "pcap-dos.h" #endif #include "pcap-int.h" #include "ethertype.h" #include "nlpid.h" #include "llc.h" #include "gencode.h" #include "ieee80211.h" #include "atmuni31.h" #include "sunatmpos.h" #include "ppp.h" #include "pcap/sll.h" #include "pcap/ipnet.h" #include "arcnet.h" #if defined(PF_PACKET) && defined(SO_ATTACH_FILTER) #include #include #include #endif #ifdef HAVE_NET_PFVAR_H #include #include #include #include #endif #ifndef offsetof #define offsetof(s, e) ((size_t)&((s *)0)->e) #endif #ifdef INET6 #ifndef WIN32 #include /* for "struct addrinfo" */ #endif /* WIN32 */ #endif /*INET6*/ #include #define ETHERMTU 1500 +#ifndef IPPROTO_HOPOPTS +#define IPPROTO_HOPOPTS 0 +#endif +#ifndef IPPROTO_ROUTING +#define IPPROTO_ROUTING 43 +#endif +#ifndef IPPROTO_FRAGMENT +#define IPPROTO_FRAGMENT 44 +#endif +#ifndef IPPROTO_DSTOPTS +#define IPPROTO_DSTOPTS 60 +#endif #ifndef IPPROTO_SCTP #define IPPROTO_SCTP 132 #endif #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif #define JMP(c) ((c)|BPF_JMP|BPF_K) /* Locals */ static jmp_buf top_ctx; static pcap_t *bpf_pcap; /* Hack for updating VLAN, MPLS, and PPPoE offsets. */ #ifdef WIN32 static u_int orig_linktype = (u_int)-1, orig_nl = (u_int)-1, label_stack_depth = (u_int)-1; #else static u_int orig_linktype = -1U, orig_nl = -1U, label_stack_depth = -1U; #endif /* XXX */ #ifdef PCAP_FDDIPAD static int pcap_fddipad; #endif /* VARARGS */ void bpf_error(const char *fmt, ...) { va_list ap; va_start(ap, fmt); if (bpf_pcap != NULL) (void)vsnprintf(pcap_geterr(bpf_pcap), PCAP_ERRBUF_SIZE, fmt, ap); va_end(ap); longjmp(top_ctx, 1); /* NOTREACHED */ } static void init_linktype(pcap_t *); static void init_regs(void); static int alloc_reg(void); static void free_reg(int); static struct block *root; /* * Value passed to gen_load_a() to indicate what the offset argument * is relative to. */ enum e_offrel { OR_PACKET, /* relative to the beginning of the packet */ OR_LINK, /* relative to the beginning of the link-layer header */ OR_MACPL, /* relative to the end of the MAC-layer header */ OR_NET, /* relative to the network-layer header */ OR_NET_NOSNAP, /* relative to the network-layer header, with no SNAP header at the link layer */ OR_TRAN_IPV4, /* relative to the transport-layer header, with IPv4 network layer */ OR_TRAN_IPV6 /* relative to the transport-layer header, with IPv6 network layer */ }; #ifdef INET6 /* * As errors are handled by a longjmp, anything allocated must be freed * in the longjmp handler, so it must be reachable from that handler. * One thing that's allocated is the result of pcap_nametoaddrinfo(); * it must be freed with freeaddrinfo(). This variable points to any * addrinfo structure that would need to be freed. */ static struct addrinfo *ai; #endif /* * We divy out chunks of memory rather than call malloc each time so * we don't have to worry about leaking memory. It's probably * not a big deal if all this memory was wasted but if this ever * goes into a library that would probably not be a good idea. * * XXX - this *is* in a library.... */ #define NCHUNKS 16 #define CHUNK0SIZE 1024 struct chunk { u_int n_left; void *m; }; static struct chunk chunks[NCHUNKS]; static int cur_chunk; static void *newchunk(u_int); static void freechunks(void); static inline struct block *new_block(int); static inline struct slist *new_stmt(int); static struct block *gen_retblk(int); static inline void syntax(void); static void backpatch(struct block *, struct block *); static void merge(struct block *, struct block *); static struct block *gen_cmp(enum e_offrel, u_int, u_int, bpf_int32); static struct block *gen_cmp_gt(enum e_offrel, u_int, u_int, bpf_int32); static struct block *gen_cmp_ge(enum e_offrel, u_int, u_int, bpf_int32); static struct block *gen_cmp_lt(enum e_offrel, u_int, u_int, bpf_int32); static struct block *gen_cmp_le(enum e_offrel, u_int, u_int, bpf_int32); static struct block *gen_mcmp(enum e_offrel, u_int, u_int, bpf_int32, bpf_u_int32); static struct block *gen_bcmp(enum e_offrel, u_int, u_int, const u_char *); static struct block *gen_ncmp(enum e_offrel, bpf_u_int32, bpf_u_int32, bpf_u_int32, bpf_u_int32, int, bpf_int32); static struct slist *gen_load_llrel(u_int, u_int); static struct slist *gen_load_macplrel(u_int, u_int); static struct slist *gen_load_a(enum e_offrel, u_int, u_int); static struct slist *gen_loadx_iphdrlen(void); static struct block *gen_uncond(int); static inline struct block *gen_true(void); static inline struct block *gen_false(void); static struct block *gen_ether_linktype(int); static struct block *gen_ipnet_linktype(int); static struct block *gen_linux_sll_linktype(int); static struct slist *gen_load_prism_llprefixlen(void); static struct slist *gen_load_avs_llprefixlen(void); static struct slist *gen_load_radiotap_llprefixlen(void); static struct slist *gen_load_ppi_llprefixlen(void); static void insert_compute_vloffsets(struct block *); static struct slist *gen_llprefixlen(void); static struct slist *gen_off_macpl(void); static int ethertype_to_ppptype(int); static struct block *gen_linktype(int); static struct block *gen_snap(bpf_u_int32, bpf_u_int32); static struct block *gen_llc_linktype(int); 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); static struct block *gen_wlanhostop(const u_char *, int); static struct block *gen_ipfchostop(const u_char *, int); static struct block *gen_dnhostop(bpf_u_int32, int); static struct block *gen_mpls_linktype(int); static struct block *gen_host(bpf_u_int32, bpf_u_int32, int, int, int); #ifdef INET6 static struct block *gen_host6(struct in6_addr *, struct in6_addr *, int, int, int); #endif #ifndef INET6 static struct block *gen_gateway(const u_char *, bpf_u_int32 **, int, int); #endif static struct block *gen_ipfrag(void); static struct block *gen_portatom(int, bpf_int32); static struct block *gen_portrangeatom(int, bpf_int32, bpf_int32); -#ifdef INET6 static struct block *gen_portatom6(int, bpf_int32); static struct block *gen_portrangeatom6(int, bpf_int32, bpf_int32); -#endif struct block *gen_portop(int, int, int); static struct block *gen_port(int, int, int); struct block *gen_portrangeop(int, int, int, int); static struct block *gen_portrange(int, int, int, int); -#ifdef INET6 struct block *gen_portop6(int, int, int); static struct block *gen_port6(int, int, int); struct block *gen_portrangeop6(int, int, int, int); static struct block *gen_portrange6(int, int, int, int); -#endif static int lookup_proto(const char *, int); static struct block *gen_protochain(int, int, int); static struct block *gen_proto(int, int, int); static struct slist *xfer_to_x(struct arth *); static struct slist *xfer_to_a(struct arth *); static struct block *gen_mac_multicast(int); static struct block *gen_len(int, int); static struct block *gen_check_802_11_data_frame(void); static struct block *gen_ppi_dlt_check(void); static struct block *gen_msg_abbrev(int type); static void * newchunk(n) u_int n; { struct chunk *cp; int k; size_t size; #ifndef __NetBSD__ /* XXX Round up to nearest long. */ n = (n + sizeof(long) - 1) & ~(sizeof(long) - 1); #else /* XXX Round up to structure boundary. */ n = ALIGN(n); #endif cp = &chunks[cur_chunk]; if (n > cp->n_left) { ++cp, k = ++cur_chunk; if (k >= NCHUNKS) bpf_error("out of memory"); size = CHUNK0SIZE << k; cp->m = (void *)malloc(size); if (cp->m == NULL) bpf_error("out of memory"); memset((char *)cp->m, 0, size); cp->n_left = size; if (n > size) bpf_error("out of memory"); } cp->n_left -= n; return (void *)((char *)cp->m + cp->n_left); } static void freechunks() { int i; cur_chunk = 0; for (i = 0; i < NCHUNKS; ++i) if (chunks[i].m != NULL) { free(chunks[i].m); chunks[i].m = NULL; } } /* * A strdup whose allocations are freed after code generation is over. */ char * sdup(s) register const char *s; { int n = strlen(s) + 1; char *cp = newchunk(n); strlcpy(cp, s, n); return (cp); } static inline struct block * new_block(code) int code; { struct block *p; p = (struct block *)newchunk(sizeof(*p)); p->s.code = code; p->head = p; return p; } static inline struct slist * new_stmt(code) int code; { struct slist *p; p = (struct slist *)newchunk(sizeof(*p)); p->s.code = code; return p; } static struct block * gen_retblk(v) int v; { struct block *b = new_block(BPF_RET|BPF_K); b->s.k = v; return b; } static inline void syntax() { bpf_error("syntax error in filter expression"); } static bpf_u_int32 netmask; static int snaplen; int no_optimize; #ifdef WIN32 static int pcap_compile_unsafe(pcap_t *p, struct bpf_program *program, const char *buf, int optimize, bpf_u_int32 mask); int pcap_compile(pcap_t *p, struct bpf_program *program, const char *buf, int optimize, bpf_u_int32 mask) { int result; EnterCriticalSection(&g_PcapCompileCriticalSection); result = pcap_compile_unsafe(p, program, buf, optimize, mask); LeaveCriticalSection(&g_PcapCompileCriticalSection); return result; } static int pcap_compile_unsafe(pcap_t *p, struct bpf_program *program, const char *buf, int optimize, bpf_u_int32 mask) #else /* WIN32 */ int pcap_compile(pcap_t *p, struct bpf_program *program, const char *buf, int optimize, bpf_u_int32 mask) #endif /* WIN32 */ { extern int n_errors; const char * volatile xbuf = buf; u_int len; + /* + * If this pcap_t hasn't been activated, it doesn't have a + * link-layer type, so we can't use it. + */ + if (!p->activated) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "not-yet-activated pcap_t passed to pcap_compile"); + return (-1); + } no_optimize = 0; n_errors = 0; root = NULL; bpf_pcap = p; init_regs(); if (setjmp(top_ctx)) { #ifdef INET6 if (ai != NULL) { freeaddrinfo(ai); ai = NULL; } #endif lex_cleanup(); freechunks(); return (-1); } netmask = mask; snaplen = pcap_snapshot(p); if (snaplen == 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snaplen of 0 rejects all packets"); return -1; } lex_init(xbuf ? xbuf : ""); init_linktype(p); (void)pcap_parse(); if (n_errors) syntax(); if (root == NULL) root = gen_retblk(snaplen); if (optimize && !no_optimize) { bpf_optimize(&root); if (root == NULL || (root->s.code == (BPF_RET|BPF_K) && root->s.k == 0)) bpf_error("expression rejects all packets"); } program->bf_insns = icode_to_fcode(root, &len); program->bf_len = len; lex_cleanup(); freechunks(); return (0); } /* * entry point for using the compiler with no pcap open * pass in all the stuff that is needed explicitly instead. */ int pcap_compile_nopcap(int snaplen_arg, int linktype_arg, struct bpf_program *program, const char *buf, int optimize, bpf_u_int32 mask) { pcap_t *p; int ret; p = pcap_open_dead(linktype_arg, snaplen_arg); if (p == NULL) return (-1); ret = pcap_compile(p, program, buf, optimize, mask); pcap_close(p); return (ret); } /* * Clean up a "struct bpf_program" by freeing all the memory allocated * in it. */ void pcap_freecode(struct bpf_program *program) { program->bf_len = 0; if (program->bf_insns != NULL) { free((char *)program->bf_insns); program->bf_insns = NULL; } } /* * Backpatch the blocks in 'list' to 'target'. The 'sense' field indicates * which of the jt and jf fields has been resolved and which is a pointer * back to another unresolved block (or nil). At least one of the fields * in each block is already resolved. */ static void backpatch(list, target) struct block *list, *target; { struct block *next; while (list) { if (!list->sense) { next = JT(list); JT(list) = target; } else { next = JF(list); JF(list) = target; } list = next; } } /* * Merge the lists in b0 and b1, using the 'sense' field to indicate * which of jt and jf is the link. */ static void merge(b0, b1) struct block *b0, *b1; { register struct block **p = &b0; /* Find end of list. */ while (*p) p = !((*p)->sense) ? &JT(*p) : &JF(*p); /* Concatenate the lists. */ *p = b1; } void finish_parse(p) struct block *p; { struct block *ppi_dlt_check; /* * Insert before the statements of the first (root) block any * statements needed to load the lengths of any variable-length * headers into registers. * * XXX - a fancier strategy would be to insert those before the * statements of all blocks that use those lengths and that * have no predecessors that use them, so that we only compute * the lengths if we need them. There might be even better * approaches than that. * * However, those strategies would be more complicated, and * as we don't generate code to compute a length if the * program has no tests that use the length, and as most * tests will probably use those lengths, we would just * postpone computing the lengths so that it's not done * for tests that fail early, and it's not clear that's * worth the effort. */ insert_compute_vloffsets(p->head); /* * For DLT_PPI captures, generate a check of the per-packet * DLT value to make sure it's DLT_IEEE802_11. */ ppi_dlt_check = gen_ppi_dlt_check(); if (ppi_dlt_check != NULL) gen_and(ppi_dlt_check, p); backpatch(p, gen_retblk(snaplen)); p->sense = !p->sense; backpatch(p, gen_retblk(0)); root = p->head; } void gen_and(b0, b1) struct block *b0, *b1; { backpatch(b0, b1->head); b0->sense = !b0->sense; b1->sense = !b1->sense; merge(b1, b0); b1->sense = !b1->sense; b1->head = b0->head; } void gen_or(b0, b1) struct block *b0, *b1; { b0->sense = !b0->sense; backpatch(b0, b1->head); b0->sense = !b0->sense; merge(b1, b0); b1->head = b0->head; } void gen_not(b) struct block *b; { b->sense = !b->sense; } static struct block * gen_cmp(offrel, offset, size, v) enum e_offrel offrel; u_int offset, size; bpf_int32 v; { return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JEQ, 0, v); } static struct block * gen_cmp_gt(offrel, offset, size, v) enum e_offrel offrel; u_int offset, size; bpf_int32 v; { return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGT, 0, v); } static struct block * gen_cmp_ge(offrel, offset, size, v) enum e_offrel offrel; u_int offset, size; bpf_int32 v; { return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGE, 0, v); } static struct block * gen_cmp_lt(offrel, offset, size, v) enum e_offrel offrel; u_int offset, size; bpf_int32 v; { return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGE, 1, v); } static struct block * gen_cmp_le(offrel, offset, size, v) enum e_offrel offrel; u_int offset, size; bpf_int32 v; { return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGT, 1, v); } static struct block * gen_mcmp(offrel, offset, size, v, mask) enum e_offrel offrel; u_int offset, size; bpf_int32 v; bpf_u_int32 mask; { return gen_ncmp(offrel, offset, size, mask, BPF_JEQ, 0, v); } static struct block * gen_bcmp(offrel, offset, size, v) enum e_offrel offrel; register u_int offset, size; register const u_char *v; { register struct block *b, *tmp; b = NULL; while (size >= 4) { register const u_char *p = &v[size - 4]; bpf_int32 w = ((bpf_int32)p[0] << 24) | ((bpf_int32)p[1] << 16) | ((bpf_int32)p[2] << 8) | p[3]; tmp = gen_cmp(offrel, offset + size - 4, BPF_W, w); if (b != NULL) gen_and(b, tmp); b = tmp; size -= 4; } while (size >= 2) { register const u_char *p = &v[size - 2]; bpf_int32 w = ((bpf_int32)p[0] << 8) | p[1]; tmp = gen_cmp(offrel, offset + size - 2, BPF_H, w); if (b != NULL) gen_and(b, tmp); b = tmp; size -= 2; } if (size > 0) { tmp = gen_cmp(offrel, offset, BPF_B, (bpf_int32)v[0]); if (b != NULL) gen_and(b, tmp); b = tmp; } return b; } /* * AND the field of size "size" at offset "offset" relative to the header * specified by "offrel" with "mask", and compare it with the value "v" * with the test specified by "jtype"; if "reverse" is true, the test * should test the opposite of "jtype". */ static struct block * gen_ncmp(offrel, offset, size, mask, jtype, reverse, v) enum e_offrel offrel; bpf_int32 v; bpf_u_int32 offset, size, mask, jtype; int reverse; { struct slist *s, *s2; struct block *b; s = gen_load_a(offrel, offset, size); if (mask != 0xffffffff) { s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K); s2->s.k = mask; sappend(s, s2); } b = new_block(JMP(jtype)); b->stmts = s; b->s.k = v; if (reverse && (jtype == BPF_JGT || jtype == BPF_JGE)) gen_not(b); return b; } /* * Various code constructs need to know the layout of the data link * layer. These variables give the necessary offsets from the beginning * of the packet data. */ /* * This is the offset of the beginning of the link-layer header from * the beginning of the raw packet data. * * It's usually 0, except for 802.11 with a fixed-length radio header. * (For 802.11 with a variable-length radio header, we have to generate * code to compute that offset; off_ll is 0 in that case.) */ static u_int off_ll; /* * If there's a variable-length header preceding the link-layer header, * "reg_off_ll" is the register number for a register containing the * length of that header, and therefore the offset of the link-layer * header from the beginning of the raw packet data. Otherwise, * "reg_off_ll" is -1. */ static int reg_off_ll; /* * This is the offset of the beginning of the MAC-layer header from * the beginning of the link-layer header. * It's usually 0, except for ATM LANE, where it's the offset, relative * to the beginning of the raw packet data, of the Ethernet header, and * for Ethernet with various additional information. */ static u_int off_mac; /* * This is the offset of the beginning of the MAC-layer payload, * from the beginning of the raw packet data. * * I.e., it's the sum of the length of the link-layer header (without, * for example, any 802.2 LLC header, so it's the MAC-layer * portion of that header), plus any prefix preceding the * link-layer header. */ static u_int off_macpl; /* * This is 1 if the offset of the beginning of the MAC-layer payload * from the beginning of the link-layer header is variable-length. */ static int off_macpl_is_variable; /* * If the link layer has variable_length headers, "reg_off_macpl" * is the register number for a register containing the length of the * link-layer header plus the length of any variable-length header * preceding the link-layer header. Otherwise, "reg_off_macpl" * is -1. */ static int reg_off_macpl; /* * "off_linktype" is the offset to information in the link-layer header * giving the packet type. This offset is relative to the beginning * of the link-layer header (i.e., it doesn't include off_ll). * * For Ethernet, it's the offset of the Ethernet type field. * * For link-layer types that always use 802.2 headers, it's the * offset of the LLC header. * * For PPP, it's the offset of the PPP type field. * * For Cisco HDLC, it's the offset of the CHDLC type field. * * For BSD loopback, it's the offset of the AF_ value. * * For Linux cooked sockets, it's the offset of the type field. * * It's set to -1 for no encapsulation, in which case, IP is assumed. */ static u_int off_linktype; /* * TRUE if "pppoes" appeared in the filter; it causes link-layer type * checks to check the PPP header, assumed to follow a LAN-style link- * layer header and a PPPoE session header. */ static int is_pppoes = 0; /* * TRUE if the link layer includes an ATM pseudo-header. */ static int is_atm = 0; /* * TRUE if "lane" appeared in the filter; it causes us to generate * code that assumes LANE rather than LLC-encapsulated traffic in SunATM. */ static int is_lane = 0; /* * These are offsets for the ATM pseudo-header. */ static u_int off_vpi; static u_int off_vci; static u_int off_proto; /* * These are offsets for the MTP2 fields. */ static u_int off_li; /* * These are offsets for the MTP3 fields. */ static u_int off_sio; static u_int off_opc; static u_int off_dpc; static u_int off_sls; /* * This is the offset of the first byte after the ATM pseudo_header, * or -1 if there is no ATM pseudo-header. */ static u_int off_payload; /* * These are offsets to the beginning of the network-layer header. * They are relative to the beginning of the MAC-layer payload (i.e., * they don't include off_ll or off_macpl). * * If the link layer never uses 802.2 LLC: * * "off_nl" and "off_nl_nosnap" are the same. * * If the link layer always uses 802.2 LLC: * * "off_nl" is the offset if there's a SNAP header following * the 802.2 header; * * "off_nl_nosnap" is the offset if there's no SNAP header. * * If the link layer is Ethernet: * * "off_nl" is the offset if the packet is an Ethernet II packet * (we assume no 802.3+802.2+SNAP); * * "off_nl_nosnap" is the offset if the packet is an 802.3 packet * with an 802.2 header following it. */ static u_int off_nl; static u_int off_nl_nosnap; static int linktype; static void init_linktype(p) pcap_t *p; { linktype = pcap_datalink(p); #ifdef PCAP_FDDIPAD pcap_fddipad = p->fddipad; #endif /* * Assume it's not raw ATM with a pseudo-header, for now. */ off_mac = 0; is_atm = 0; is_lane = 0; off_vpi = -1; off_vci = -1; off_proto = -1; off_payload = -1; /* * And that we're not doing PPPoE. */ is_pppoes = 0; /* * And assume we're not doing SS7. */ off_li = -1; off_sio = -1; off_opc = -1; off_dpc = -1; off_sls = -1; /* * Also assume it's not 802.11. */ off_ll = 0; off_macpl = 0; off_macpl_is_variable = 0; orig_linktype = -1; orig_nl = -1; label_stack_depth = 0; reg_off_ll = -1; reg_off_macpl = -1; switch (linktype) { case DLT_ARCNET: off_linktype = 2; off_macpl = 6; off_nl = 0; /* XXX in reality, variable! */ off_nl_nosnap = 0; /* no 802.2 LLC */ return; case DLT_ARCNET_LINUX: off_linktype = 4; off_macpl = 8; off_nl = 0; /* XXX in reality, variable! */ off_nl_nosnap = 0; /* no 802.2 LLC */ return; case DLT_EN10MB: off_linktype = 12; off_macpl = 14; /* Ethernet header length */ off_nl = 0; /* Ethernet II */ off_nl_nosnap = 3; /* 802.3+802.2 */ return; case DLT_SLIP: /* * SLIP doesn't have a link level type. The 16 byte * header is hacked into our SLIP driver. */ off_linktype = -1; off_macpl = 16; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ return; case DLT_SLIP_BSDOS: /* XXX this may be the same as the DLT_PPP_BSDOS case */ off_linktype = -1; /* XXX end */ off_macpl = 24; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ return; case DLT_NULL: case DLT_LOOP: off_linktype = 0; off_macpl = 4; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ return; case DLT_ENC: off_linktype = 0; off_macpl = 12; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ return; case DLT_PPP: case DLT_PPP_PPPD: case DLT_C_HDLC: /* BSD/OS Cisco HDLC */ case DLT_PPP_SERIAL: /* NetBSD sync/async serial PPP */ off_linktype = 2; off_macpl = 4; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ return; case DLT_PPP_ETHER: /* * This does no include the Ethernet header, and * only covers session state. */ off_linktype = 6; off_macpl = 8; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ return; case DLT_PPP_BSDOS: off_linktype = 5; off_macpl = 24; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ return; case DLT_FDDI: /* * FDDI 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? */ off_linktype = 13; #ifdef PCAP_FDDIPAD off_linktype += pcap_fddipad; #endif off_macpl = 13; /* FDDI MAC header length */ #ifdef PCAP_FDDIPAD off_macpl += pcap_fddipad; #endif off_nl = 8; /* 802.2+SNAP */ off_nl_nosnap = 3; /* 802.2 */ return; case DLT_IEEE802: /* * Token Ring 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. * Some various Linux patched versions gave 38 * as "off_linktype" and 40 as "off_nl"; however, * if a token ring packet has *no* routing * information, i.e. is not source-routed, the correct * values are 20 and 22, as they are in the vanilla code. * * A packet is source-routed iff the uppermost bit * of the first byte of the source address, at an * offset of 8, has the uppermost bit set. If the * packet is source-routed, the total number of bytes * of routing information is 2 plus bits 0x1F00 of * the 16-bit value at an offset of 14 (shifted right * 8 - figure out which byte that is). */ off_linktype = 14; off_macpl = 14; /* Token Ring MAC header length */ off_nl = 8; /* 802.2+SNAP */ off_nl_nosnap = 3; /* 802.2 */ return; case DLT_IEEE802_11: case DLT_PRISM_HEADER: case DLT_IEEE802_11_RADIO_AVS: case DLT_IEEE802_11_RADIO: /* * 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? * * We also handle variable-length radio headers here. * The Prism header is in theory variable-length, but in * practice it's always 144 bytes long. However, some * drivers on Linux use ARPHRD_IEEE80211_PRISM, but * sometimes or always supply an AVS header, so we * have to check whether the radio header is a Prism * header or an AVS header, so, in practice, it's * variable-length. */ off_linktype = 24; off_macpl = 0; /* link-layer header is variable-length */ off_macpl_is_variable = 1; off_nl = 8; /* 802.2+SNAP */ off_nl_nosnap = 3; /* 802.2 */ return; case DLT_PPI: /* * At the moment we treat PPI the same way that we treat * normal Radiotap encoded packets. The difference is in * the function that generates the code at the beginning * to compute the header length. Since this code generator * of PPI supports bare 802.11 encapsulation only (i.e. * the encapsulated DLT should be DLT_IEEE802_11) we * generate code to check for this too. */ off_linktype = 24; off_macpl = 0; /* link-layer header is variable-length */ off_macpl_is_variable = 1; off_nl = 8; /* 802.2+SNAP */ off_nl_nosnap = 3; /* 802.2 */ return; case DLT_ATM_RFC1483: case DLT_ATM_CLIP: /* Linux ATM defines this */ /* * assume routed, non-ISO PDUs * (i.e., LLC = 0xAA-AA-03, OUT = 0x00-00-00) * * XXX - what about ISO PDUs, e.g. CLNP, ISIS, ESIS, * or PPP with the PPP NLPID (e.g., PPPoA)? The * latter would presumably be treated the way PPPoE * should be, so you can do "pppoe and udp port 2049" * or "pppoa and tcp port 80" and have it check for * PPPo{A,E} and a PPP protocol of IP and.... */ off_linktype = 0; off_macpl = 0; /* packet begins with LLC header */ off_nl = 8; /* 802.2+SNAP */ off_nl_nosnap = 3; /* 802.2 */ return; case DLT_SUNATM: /* * Full Frontal ATM; you get AALn PDUs with an ATM * pseudo-header. */ is_atm = 1; off_vpi = SUNATM_VPI_POS; off_vci = SUNATM_VCI_POS; off_proto = PROTO_POS; off_mac = -1; /* assume LLC-encapsulated, so no MAC-layer header */ off_payload = SUNATM_PKT_BEGIN_POS; off_linktype = off_payload; off_macpl = off_payload; /* if LLC-encapsulated */ off_nl = 8; /* 802.2+SNAP */ off_nl_nosnap = 3; /* 802.2 */ return; case DLT_RAW: case DLT_IPV4: case DLT_IPV6: off_linktype = -1; off_macpl = 0; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ return; case DLT_LINUX_SLL: /* fake header for Linux cooked socket */ off_linktype = 14; off_macpl = 16; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ 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_macpl = 0; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ return; case DLT_IP_OVER_FC: /* * RFC 2625 IP-over-Fibre-Channel 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? RFC * 2625 says SNAP should be used. */ off_linktype = 16; off_macpl = 16; off_nl = 8; /* 802.2+SNAP */ off_nl_nosnap = 3; /* 802.2 */ return; case DLT_FRELAY: /* * XXX - we should set this to handle SNAP-encapsulated * frames (NLPID of 0x80). */ off_linktype = -1; off_macpl = 0; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ return; /* * the only BPF-interesting FRF.16 frames are non-control frames; * Frame Relay has a variable length link-layer * so lets start with offset 4 for now and increments later on (FIXME); */ case DLT_MFR: off_linktype = -1; off_macpl = 0; off_nl = 4; off_nl_nosnap = 0; /* XXX - for now -> no 802.2 LLC */ return; case DLT_APPLE_IP_OVER_IEEE1394: off_linktype = 16; off_macpl = 18; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ return; case DLT_SYMANTEC_FIREWALL: off_linktype = 6; off_macpl = 44; off_nl = 0; /* Ethernet II */ off_nl_nosnap = 0; /* XXX - what does it do with 802.3 packets? */ return; #ifdef HAVE_NET_PFVAR_H case DLT_PFLOG: off_linktype = 0; off_macpl = PFLOG_HDRLEN; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ return; #endif case DLT_JUNIPER_MFR: case DLT_JUNIPER_MLFR: case DLT_JUNIPER_MLPPP: case DLT_JUNIPER_PPP: case DLT_JUNIPER_CHDLC: case DLT_JUNIPER_FRELAY: off_linktype = 4; off_macpl = 4; off_nl = 0; off_nl_nosnap = -1; /* no 802.2 LLC */ return; case DLT_JUNIPER_ATM1: off_linktype = 4; /* in reality variable between 4-8 */ off_macpl = 4; /* in reality variable between 4-8 */ off_nl = 0; off_nl_nosnap = 10; return; case DLT_JUNIPER_ATM2: off_linktype = 8; /* in reality variable between 8-12 */ off_macpl = 8; /* in reality variable between 8-12 */ off_nl = 0; off_nl_nosnap = 10; return; /* frames captured on a Juniper PPPoE service PIC * contain raw ethernet frames */ case DLT_JUNIPER_PPPOE: case DLT_JUNIPER_ETHER: off_macpl = 14; off_linktype = 16; off_nl = 18; /* Ethernet II */ off_nl_nosnap = 21; /* 802.3+802.2 */ return; case DLT_JUNIPER_PPPOE_ATM: off_linktype = 4; off_macpl = 6; off_nl = 0; off_nl_nosnap = -1; /* no 802.2 LLC */ return; case DLT_JUNIPER_GGSN: off_linktype = 6; off_macpl = 12; off_nl = 0; off_nl_nosnap = -1; /* no 802.2 LLC */ return; case DLT_JUNIPER_ES: off_linktype = 6; off_macpl = -1; /* not really a network layer but raw IP addresses */ off_nl = -1; /* not really a network layer but raw IP addresses */ off_nl_nosnap = -1; /* no 802.2 LLC */ return; case DLT_JUNIPER_MONITOR: off_linktype = 12; off_macpl = 12; off_nl = 0; /* raw IP/IP6 header */ off_nl_nosnap = -1; /* no 802.2 LLC */ return; case DLT_JUNIPER_SERVICES: off_linktype = 12; off_macpl = -1; /* L3 proto location dep. on cookie type */ off_nl = -1; /* L3 proto location dep. on cookie type */ off_nl_nosnap = -1; /* no 802.2 LLC */ return; case DLT_JUNIPER_VP: off_linktype = 18; off_macpl = -1; off_nl = -1; off_nl_nosnap = -1; return; case DLT_JUNIPER_ST: off_linktype = 18; off_macpl = -1; off_nl = -1; off_nl_nosnap = -1; return; case DLT_JUNIPER_ISM: off_linktype = 8; off_macpl = -1; off_nl = -1; off_nl_nosnap = -1; return; case DLT_JUNIPER_VS: case DLT_JUNIPER_SRX_E2E: case DLT_JUNIPER_FIBRECHANNEL: case DLT_JUNIPER_ATM_CEMIC: off_linktype = 8; off_macpl = -1; off_nl = -1; off_nl_nosnap = -1; return; case DLT_MTP2: off_li = 2; off_sio = 3; off_opc = 4; off_dpc = 4; off_sls = 7; off_linktype = -1; off_macpl = -1; off_nl = -1; off_nl_nosnap = -1; return; case DLT_MTP2_WITH_PHDR: off_li = 6; off_sio = 7; off_opc = 8; off_dpc = 8; off_sls = 11; off_linktype = -1; off_macpl = -1; off_nl = -1; off_nl_nosnap = -1; return; case DLT_ERF: off_li = 22; off_sio = 23; off_opc = 24; off_dpc = 24; off_sls = 27; off_linktype = -1; off_macpl = -1; off_nl = -1; off_nl_nosnap = -1; return; case DLT_PFSYNC: off_linktype = -1; off_macpl = 4; off_nl = 0; off_nl_nosnap = 0; return; case DLT_AX25_KISS: /* * Currently, only raw "link[N:M]" filtering is supported. */ off_linktype = -1; /* variable, min 15, max 71 steps of 7 */ off_macpl = -1; off_nl = -1; /* variable, min 16, max 71 steps of 7 */ off_nl_nosnap = -1; /* no 802.2 LLC */ off_mac = 1; /* step over the kiss length byte */ return; case DLT_IPNET: off_linktype = 1; off_macpl = 24; /* ipnet header length */ off_nl = 0; off_nl_nosnap = -1; return; case DLT_NETANALYZER: off_mac = 4; /* MAC header is past 4-byte pseudo-header */ off_linktype = 16; /* includes 4-byte pseudo-header */ off_macpl = 18; /* pseudo-header+Ethernet header length */ off_nl = 0; /* Ethernet II */ off_nl_nosnap = 3; /* 802.3+802.2 */ return; case DLT_NETANALYZER_TRANSPARENT: off_mac = 12; /* MAC header is past 4-byte pseudo-header, preamble, and SFD */ off_linktype = 24; /* includes 4-byte pseudo-header+preamble+SFD */ off_macpl = 26; /* pseudo-header+preamble+SFD+Ethernet header length */ off_nl = 0; /* Ethernet II */ off_nl_nosnap = 3; /* 802.3+802.2 */ return; default: /* * For values in the range in which we've assigned new * DLT_ values, only raw "link[N:M]" filtering is supported. */ if (linktype >= DLT_MATCHING_MIN && linktype <= DLT_MATCHING_MAX) { off_linktype = -1; off_macpl = -1; off_nl = -1; off_nl_nosnap = -1; return; } } bpf_error("unknown data link type %d", linktype); /* NOTREACHED */ } /* * Load a value relative to the beginning of the link-layer header. * The link-layer header doesn't necessarily begin at the beginning * of the packet data; there might be a variable-length prefix containing * radio information. */ static struct slist * gen_load_llrel(offset, size) u_int offset, size; { struct slist *s, *s2; s = gen_llprefixlen(); /* * If "s" is non-null, it has code to arrange that the X register * contains the length of the prefix preceding the link-layer * header. * * Otherwise, the length of the prefix preceding the link-layer * header is "off_ll". */ if (s != NULL) { /* * There's a variable-length prefix preceding the * link-layer header. "s" points to a list of statements * that put the length of that prefix into the X register. * do an indirect load, to use the X register as an offset. */ s2 = new_stmt(BPF_LD|BPF_IND|size); s2->s.k = offset; sappend(s, s2); } else { /* * There is no variable-length header preceding the * link-layer header; add in off_ll, which, if there's * a fixed-length header preceding the link-layer header, * is the length of that header. */ s = new_stmt(BPF_LD|BPF_ABS|size); s->s.k = offset + off_ll; } return s; } /* * Load a value relative to the beginning of the MAC-layer payload. */ static struct slist * gen_load_macplrel(offset, size) u_int offset, size; { struct slist *s, *s2; s = gen_off_macpl(); /* * If s is non-null, the offset of the MAC-layer payload is * variable, and s points to a list of instructions that * arrange that the X register contains that offset. * * Otherwise, the offset of the MAC-layer payload is constant, * and is in off_macpl. */ if (s != NULL) { /* * The offset of the MAC-layer payload is in the X * register. Do an indirect load, to use the X register * as an offset. */ s2 = new_stmt(BPF_LD|BPF_IND|size); s2->s.k = offset; sappend(s, s2); } else { /* * The offset of the MAC-layer payload is constant, * and is in off_macpl; load the value at that offset * plus the specified offset. */ s = new_stmt(BPF_LD|BPF_ABS|size); s->s.k = off_macpl + offset; } return s; } /* * Load a value relative to the beginning of the specified header. */ static struct slist * gen_load_a(offrel, offset, size) enum e_offrel offrel; u_int offset, size; { struct slist *s, *s2; switch (offrel) { case OR_PACKET: s = new_stmt(BPF_LD|BPF_ABS|size); s->s.k = offset; break; case OR_LINK: s = gen_load_llrel(offset, size); break; case OR_MACPL: s = gen_load_macplrel(offset, size); break; case OR_NET: s = gen_load_macplrel(off_nl + offset, size); break; case OR_NET_NOSNAP: s = gen_load_macplrel(off_nl_nosnap + offset, size); break; case OR_TRAN_IPV4: /* * Load the X register with the length of the IPv4 header * (plus the offset of the link-layer header, if it's * preceded by a variable-length header such as a radio * header), in bytes. */ s = gen_loadx_iphdrlen(); /* * Load the item at {offset of the MAC-layer payload} + * {offset, relative to the start of the MAC-layer * paylod, of the IPv4 header} + {length of the IPv4 header} + * {specified offset}. * * (If the offset of the MAC-layer payload is variable, * it's included in the value in the X register, and * off_macpl is 0.) */ s2 = new_stmt(BPF_LD|BPF_IND|size); s2->s.k = off_macpl + off_nl + offset; sappend(s, s2); break; case OR_TRAN_IPV6: s = gen_load_macplrel(off_nl + 40 + offset, size); break; default: abort(); return NULL; } return s; } /* * Generate code to load into the X register the sum of the length of * the IPv4 header and any variable-length header preceding the link-layer * header. */ static struct slist * gen_loadx_iphdrlen() { struct slist *s, *s2; s = gen_off_macpl(); if (s != NULL) { /* * There's a variable-length prefix preceding the * link-layer header, or the link-layer header is itself * variable-length. "s" points to a list of statements * that put the offset of the MAC-layer payload into * the X register. * * The 4*([k]&0xf) addressing mode can't be used, as we * don't have a constant offset, so we have to load the * value in question into the A register and add to it * the value from the X register. */ s2 = new_stmt(BPF_LD|BPF_IND|BPF_B); s2->s.k = off_nl; sappend(s, s2); s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K); s2->s.k = 0xf; sappend(s, s2); s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K); s2->s.k = 2; sappend(s, s2); /* * The A register now contains the length of the * IP header. We need to add to it the offset of * the MAC-layer payload, which is still in the X * register, and move the result into the X register. */ sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X)); sappend(s, new_stmt(BPF_MISC|BPF_TAX)); } else { /* * There is no variable-length header preceding the * link-layer header, and the link-layer header is * fixed-length; load the length of the IPv4 header, * which is at an offset of off_nl from the beginning * of the MAC-layer payload, and thus at an offset * of off_mac_pl + off_nl from the beginning of the * raw packet data. */ s = new_stmt(BPF_LDX|BPF_MSH|BPF_B); s->s.k = off_macpl + off_nl; } return s; } static struct block * gen_uncond(rsense) int rsense; { struct block *b; struct slist *s; s = new_stmt(BPF_LD|BPF_IMM); s->s.k = !rsense; b = new_block(JMP(BPF_JEQ)); b->stmts = s; return b; } static inline struct block * gen_true() { return gen_uncond(1); } static inline struct block * gen_false() { return gen_uncond(0); } /* * Byte-swap a 32-bit number. * ("htonl()" or "ntohl()" won't work - we want to byte-swap even on * big-endian platforms.) */ #define SWAPLONG(y) \ ((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff)) /* * Generate code to match a particular packet type. * * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP * value, if <= ETHERMTU. We use that to determine whether to * match the type/length field or to check the type/length field for * a value <= ETHERMTU to see whether it's a type field and then do * the appropriate test. */ static struct block * gen_ether_linktype(proto) register int proto; { struct block *b0, *b1; switch (proto) { case LLCSAP_ISONS: case LLCSAP_IP: case LLCSAP_NETBEUI: /* * OSI protocols and NetBEUI always use 802.2 encapsulation, * so we check the DSAP and SSAP. * * LLCSAP_IP checks for IP-over-802.2, rather * than IP-over-Ethernet or IP-over-SNAP. * * XXX - should we check both the DSAP and the * SSAP, like this, or should we check just the * DSAP, as we do for other types <= ETHERMTU * (i.e., other SAP values)? */ b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU); gen_not(b0); b1 = gen_cmp(OR_MACPL, 0, BPF_H, (bpf_int32) ((proto << 8) | proto)); 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(OR_MACPL, 0, BPF_B, (bpf_int32)LLCSAP_IPX); b1 = gen_cmp(OR_MACPL, 0, 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); gen_or(b0, b1); /* * Now we generate code to check for 802.3 * frames in general. */ b0 = gen_cmp_gt(OR_LINK, 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(OR_LINK, 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 an Ethernet type field less than * 1500, which means it's an 802.3 length field. */ b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU); gen_not(b0); /* * 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); else /* proto == ETHERTYPE_AARP */ b1 = gen_snap(0x000000, ETHERTYPE_AARP); gen_and(b0, b1); /* * Check for Ethernet encapsulation (Ethertalk * phase 1?); we just check for the Ethernet * protocol type. */ b0 = gen_cmp(OR_LINK, 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 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(OR_LINK, off_linktype, BPF_H, ETHERMTU); gen_not(b0); b1 = gen_cmp(OR_LINK, 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(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); } } } /* * "proto" is an Ethernet type value and for IPNET, if it is not IPv4 * or IPv6 then we have an error. */ static struct block * gen_ipnet_linktype(proto) register int proto; { switch (proto) { case ETHERTYPE_IP: return gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)IPH_AF_INET); /* NOTREACHED */ case ETHERTYPE_IPV6: return gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)IPH_AF_INET6); /* NOTREACHED */ default: break; } return gen_false(); } /* * Generate code to match a particular packet type. * * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP * value, if <= ETHERMTU. We use that to determine whether to * match the type field or to check the type field for the special * LINUX_SLL_P_802_2 value and then do the appropriate test. */ static struct block * gen_linux_sll_linktype(proto) register int proto; { struct block *b0, *b1; switch (proto) { case LLCSAP_ISONS: case LLCSAP_IP: case LLCSAP_NETBEUI: /* * OSI protocols and NetBEUI always use 802.2 encapsulation, * so we check the DSAP and SSAP. * * LLCSAP_IP checks for IP-over-802.2, rather * than IP-over-Ethernet or IP-over-SNAP. * * XXX - should we check both the DSAP and the * SSAP, like this, or should we check just the * DSAP, as we do for other types <= ETHERMTU * (i.e., other SAP values)? */ b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2); b1 = gen_cmp(OR_MACPL, 0, BPF_H, (bpf_int32) ((proto << 8) | proto)); 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(OR_MACPL, 0, BPF_B, (bpf_int32)LLCSAP_IPX); b1 = gen_snap(0x000000, ETHERTYPE_IPX); gen_or(b0, b1); b0 = gen_cmp(OR_LINK, 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(OR_LINK, 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(OR_LINK, 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(OR_LINK, 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); else /* proto == ETHERTYPE_AARP */ b1 = gen_snap(0x000000, ETHERTYPE_AARP); gen_and(b0, b1); /* * Check for Ethernet encapsulation (Ethertalk * phase 1?); we just check for the Ethernet * protocol type. */ b0 = gen_cmp(OR_LINK, 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(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2); b1 = gen_cmp(OR_LINK, off_macpl, 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(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); } } } static struct slist * gen_load_prism_llprefixlen() { struct slist *s1, *s2; struct slist *sjeq_avs_cookie; struct slist *sjcommon; /* * This code is not compatible with the optimizer, as * we are generating jmp instructions within a normal * slist of instructions */ no_optimize = 1; /* * Generate code to load the length of the radio header into * the register assigned to hold that length, if one has been * assigned. (If one hasn't been assigned, no code we've * generated uses that prefix, so we don't need to generate any * code to load it.) * * Some Linux drivers use ARPHRD_IEEE80211_PRISM but sometimes * or always use the AVS header rather than the Prism header. * We load a 4-byte big-endian value at the beginning of the * raw packet data, and see whether, when masked with 0xFFFFF000, * it's equal to 0x80211000. If so, that indicates that it's * an AVS header (the masked-out bits are the version number). * Otherwise, it's a Prism header. * * XXX - the Prism header is also, in theory, variable-length, * but no known software generates headers that aren't 144 * bytes long. */ if (reg_off_ll != -1) { /* * Load the cookie. */ s1 = new_stmt(BPF_LD|BPF_W|BPF_ABS); s1->s.k = 0; /* * AND it with 0xFFFFF000. */ s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K); s2->s.k = 0xFFFFF000; sappend(s1, s2); /* * Compare with 0x80211000. */ sjeq_avs_cookie = new_stmt(JMP(BPF_JEQ)); sjeq_avs_cookie->s.k = 0x80211000; sappend(s1, sjeq_avs_cookie); /* * If it's AVS: * * The 4 bytes at an offset of 4 from the beginning of * the AVS header are the length of the AVS header. * That field is big-endian. */ s2 = new_stmt(BPF_LD|BPF_W|BPF_ABS); s2->s.k = 4; sappend(s1, s2); sjeq_avs_cookie->s.jt = s2; /* * Now jump to the code to allocate a register * into which to save the header length and * store the length there. (The "jump always" * instruction needs to have the k field set; * it's added to the PC, so, as we're jumping * over a single instruction, it should be 1.) */ sjcommon = new_stmt(JMP(BPF_JA)); sjcommon->s.k = 1; sappend(s1, sjcommon); /* * Now for the code that handles the Prism header. * Just load the length of the Prism header (144) * into the A register. Have the test for an AVS * header branch here if we don't have an AVS header. */ s2 = new_stmt(BPF_LD|BPF_W|BPF_IMM); s2->s.k = 144; sappend(s1, s2); sjeq_avs_cookie->s.jf = s2; /* * Now allocate a register to hold that value and store * it. The code for the AVS header will jump here after * loading the length of the AVS header. */ s2 = new_stmt(BPF_ST); s2->s.k = reg_off_ll; sappend(s1, s2); sjcommon->s.jf = s2; /* * Now move it into the X register. */ s2 = new_stmt(BPF_MISC|BPF_TAX); sappend(s1, s2); return (s1); } else return (NULL); } static struct slist * gen_load_avs_llprefixlen() { struct slist *s1, *s2; /* * Generate code to load the length of the AVS header into * the register assigned to hold that length, if one has been * assigned. (If one hasn't been assigned, no code we've * generated uses that prefix, so we don't need to generate any * code to load it.) */ if (reg_off_ll != -1) { /* * The 4 bytes at an offset of 4 from the beginning of * the AVS header are the length of the AVS header. * That field is big-endian. */ s1 = new_stmt(BPF_LD|BPF_W|BPF_ABS); s1->s.k = 4; /* * Now allocate a register to hold that value and store * it. */ s2 = new_stmt(BPF_ST); s2->s.k = reg_off_ll; sappend(s1, s2); /* * Now move it into the X register. */ s2 = new_stmt(BPF_MISC|BPF_TAX); sappend(s1, s2); return (s1); } else return (NULL); } static struct slist * gen_load_radiotap_llprefixlen() { struct slist *s1, *s2; /* * Generate code to load the length of the radiotap header into * the register assigned to hold that length, if one has been * assigned. (If one hasn't been assigned, no code we've * generated uses that prefix, so we don't need to generate any * code to load it.) */ if (reg_off_ll != -1) { /* * The 2 bytes at offsets of 2 and 3 from the beginning * of the radiotap header are the length of the radiotap * header; unfortunately, it's little-endian, so we have * to load it a byte at a time and construct the value. */ /* * Load the high-order byte, at an offset of 3, shift it * left a byte, and put the result in the X register. */ s1 = new_stmt(BPF_LD|BPF_B|BPF_ABS); s1->s.k = 3; s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K); sappend(s1, s2); s2->s.k = 8; s2 = new_stmt(BPF_MISC|BPF_TAX); sappend(s1, s2); /* * Load the next byte, at an offset of 2, and OR the * value from the X register into it. */ s2 = new_stmt(BPF_LD|BPF_B|BPF_ABS); sappend(s1, s2); s2->s.k = 2; s2 = new_stmt(BPF_ALU|BPF_OR|BPF_X); sappend(s1, s2); /* * Now allocate a register to hold that value and store * it. */ s2 = new_stmt(BPF_ST); s2->s.k = reg_off_ll; sappend(s1, s2); /* * Now move it into the X register. */ s2 = new_stmt(BPF_MISC|BPF_TAX); sappend(s1, s2); return (s1); } else return (NULL); } /* * At the moment we treat PPI as normal Radiotap encoded * packets. The difference is in the function that generates * the code at the beginning to compute the header length. * Since this code generator of PPI supports bare 802.11 * encapsulation only (i.e. the encapsulated DLT should be * DLT_IEEE802_11) we generate code to check for this too; * that's done in finish_parse(). */ static struct slist * gen_load_ppi_llprefixlen() { struct slist *s1, *s2; /* * Generate code to load the length of the radiotap header * into the register assigned to hold that length, if one has * been assigned. */ if (reg_off_ll != -1) { /* * The 2 bytes at offsets of 2 and 3 from the beginning * of the radiotap header are the length of the radiotap * header; unfortunately, it's little-endian, so we have * to load it a byte at a time and construct the value. */ /* * Load the high-order byte, at an offset of 3, shift it * left a byte, and put the result in the X register. */ s1 = new_stmt(BPF_LD|BPF_B|BPF_ABS); s1->s.k = 3; s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K); sappend(s1, s2); s2->s.k = 8; s2 = new_stmt(BPF_MISC|BPF_TAX); sappend(s1, s2); /* * Load the next byte, at an offset of 2, and OR the * value from the X register into it. */ s2 = new_stmt(BPF_LD|BPF_B|BPF_ABS); sappend(s1, s2); s2->s.k = 2; s2 = new_stmt(BPF_ALU|BPF_OR|BPF_X); sappend(s1, s2); /* * Now allocate a register to hold that value and store * it. */ s2 = new_stmt(BPF_ST); s2->s.k = reg_off_ll; sappend(s1, s2); /* * Now move it into the X register. */ s2 = new_stmt(BPF_MISC|BPF_TAX); sappend(s1, s2); return (s1); } else return (NULL); } /* * Load a value relative to the beginning of the link-layer header after the 802.11 * header, i.e. LLC_SNAP. * The link-layer header doesn't necessarily begin at the beginning * of the packet data; there might be a variable-length prefix containing * radio information. */ static struct slist * gen_load_802_11_header_len(struct slist *s, struct slist *snext) { struct slist *s2; struct slist *sjset_data_frame_1; struct slist *sjset_data_frame_2; struct slist *sjset_qos; struct slist *sjset_radiotap_flags; struct slist *sjset_radiotap_tsft; struct slist *sjset_tsft_datapad, *sjset_notsft_datapad; struct slist *s_roundup; if (reg_off_macpl == -1) { /* * No register has been assigned to the offset of * the MAC-layer payload, which means nobody needs * it; don't bother computing it - just return * what we already have. */ return (s); } /* * This code is not compatible with the optimizer, as * we are generating jmp instructions within a normal * slist of instructions */ no_optimize = 1; /* * If "s" is non-null, it has code to arrange that the X register * contains the length of the prefix preceding the link-layer * header. * * Otherwise, the length of the prefix preceding the link-layer * header is "off_ll". */ if (s == NULL) { /* * There is no variable-length header preceding the * link-layer header. * * Load the length of the fixed-length prefix preceding * the link-layer header (if any) into the X register, * and store it in the reg_off_macpl register. * That length is off_ll. */ s = new_stmt(BPF_LDX|BPF_IMM); s->s.k = off_ll; } /* * The X register contains the offset of the beginning of the * link-layer header; add 24, which is the minimum length * of the MAC header for a data frame, to that, and store it * in reg_off_macpl, and then load the Frame Control field, * which is at the offset in the X register, with an indexed load. */ s2 = new_stmt(BPF_MISC|BPF_TXA); sappend(s, s2); s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_K); s2->s.k = 24; sappend(s, s2); s2 = new_stmt(BPF_ST); s2->s.k = reg_off_macpl; sappend(s, s2); s2 = new_stmt(BPF_LD|BPF_IND|BPF_B); s2->s.k = 0; sappend(s, s2); /* * Check the Frame Control field to see if this is a data frame; * a data frame has the 0x08 bit (b3) in that field set and the * 0x04 bit (b2) clear. */ sjset_data_frame_1 = new_stmt(JMP(BPF_JSET)); sjset_data_frame_1->s.k = 0x08; sappend(s, sjset_data_frame_1); /* * If b3 is set, test b2, otherwise go to the first statement of * the rest of the program. */ sjset_data_frame_1->s.jt = sjset_data_frame_2 = new_stmt(JMP(BPF_JSET)); sjset_data_frame_2->s.k = 0x04; sappend(s, sjset_data_frame_2); sjset_data_frame_1->s.jf = snext; /* * If b2 is not set, this is a data frame; test the QoS bit. * Otherwise, go to the first statement of the rest of the * program. */ sjset_data_frame_2->s.jt = snext; sjset_data_frame_2->s.jf = sjset_qos = new_stmt(JMP(BPF_JSET)); sjset_qos->s.k = 0x80; /* QoS bit */ sappend(s, sjset_qos); /* * If it's set, add 2 to reg_off_macpl, to skip the QoS * field. * Otherwise, go to the first statement of the rest of the * program. */ sjset_qos->s.jt = s2 = new_stmt(BPF_LD|BPF_MEM); s2->s.k = reg_off_macpl; sappend(s, s2); s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_IMM); s2->s.k = 2; sappend(s, s2); s2 = new_stmt(BPF_ST); s2->s.k = reg_off_macpl; sappend(s, s2); /* * If we have a radiotap header, look at it to see whether * there's Atheros padding between the MAC-layer header * and the payload. * * Note: all of the fields in the radiotap header are * little-endian, so we byte-swap all of the values * we test against, as they will be loaded as big-endian * values. */ if (linktype == DLT_IEEE802_11_RADIO) { /* * Is the IEEE80211_RADIOTAP_FLAGS bit (0x0000002) set * in the presence flag? */ sjset_qos->s.jf = s2 = new_stmt(BPF_LD|BPF_ABS|BPF_W); s2->s.k = 4; sappend(s, s2); sjset_radiotap_flags = new_stmt(JMP(BPF_JSET)); sjset_radiotap_flags->s.k = SWAPLONG(0x00000002); sappend(s, sjset_radiotap_flags); /* * If not, skip all of this. */ sjset_radiotap_flags->s.jf = snext; /* * Otherwise, is the IEEE80211_RADIOTAP_TSFT bit set? */ sjset_radiotap_tsft = sjset_radiotap_flags->s.jt = new_stmt(JMP(BPF_JSET)); sjset_radiotap_tsft->s.k = SWAPLONG(0x00000001); sappend(s, sjset_radiotap_tsft); /* * If IEEE80211_RADIOTAP_TSFT is set, the flags field is * at an offset of 16 from the beginning of the raw packet * data (8 bytes for the radiotap header and 8 bytes for * the TSFT field). * * Test whether the IEEE80211_RADIOTAP_F_DATAPAD bit (0x20) * is set. */ sjset_radiotap_tsft->s.jt = s2 = new_stmt(BPF_LD|BPF_ABS|BPF_B); s2->s.k = 16; sappend(s, s2); sjset_tsft_datapad = new_stmt(JMP(BPF_JSET)); sjset_tsft_datapad->s.k = 0x20; sappend(s, sjset_tsft_datapad); /* * If IEEE80211_RADIOTAP_TSFT is not set, the flags field is * at an offset of 8 from the beginning of the raw packet * data (8 bytes for the radiotap header). * * Test whether the IEEE80211_RADIOTAP_F_DATAPAD bit (0x20) * is set. */ sjset_radiotap_tsft->s.jf = s2 = new_stmt(BPF_LD|BPF_ABS|BPF_B); s2->s.k = 8; sappend(s, s2); sjset_notsft_datapad = new_stmt(JMP(BPF_JSET)); sjset_notsft_datapad->s.k = 0x20; sappend(s, sjset_notsft_datapad); /* * In either case, if IEEE80211_RADIOTAP_F_DATAPAD is * set, round the length of the 802.11 header to * a multiple of 4. Do that by adding 3 and then * dividing by and multiplying by 4, which we do by * ANDing with ~3. */ s_roundup = new_stmt(BPF_LD|BPF_MEM); s_roundup->s.k = reg_off_macpl; sappend(s, s_roundup); s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_IMM); s2->s.k = 3; sappend(s, s2); s2 = new_stmt(BPF_ALU|BPF_AND|BPF_IMM); s2->s.k = ~3; sappend(s, s2); s2 = new_stmt(BPF_ST); s2->s.k = reg_off_macpl; sappend(s, s2); sjset_tsft_datapad->s.jt = s_roundup; sjset_tsft_datapad->s.jf = snext; sjset_notsft_datapad->s.jt = s_roundup; sjset_notsft_datapad->s.jf = snext; } else sjset_qos->s.jf = snext; return s; } static void insert_compute_vloffsets(b) struct block *b; { struct slist *s; /* * For link-layer types that have a variable-length header * preceding the link-layer header, generate code to load * the offset of the link-layer header into the register * assigned to that offset, if any. */ switch (linktype) { case DLT_PRISM_HEADER: s = gen_load_prism_llprefixlen(); break; case DLT_IEEE802_11_RADIO_AVS: s = gen_load_avs_llprefixlen(); break; case DLT_IEEE802_11_RADIO: s = gen_load_radiotap_llprefixlen(); break; case DLT_PPI: s = gen_load_ppi_llprefixlen(); break; default: s = NULL; break; } /* * For link-layer types that have a variable-length link-layer * header, generate code to load the offset of the MAC-layer * payload into the register assigned to that offset, if any. */ switch (linktype) { case DLT_IEEE802_11: case DLT_PRISM_HEADER: case DLT_IEEE802_11_RADIO_AVS: case DLT_IEEE802_11_RADIO: case DLT_PPI: s = gen_load_802_11_header_len(s, b->stmts); break; } /* * If we have any offset-loading code, append all the * existing statements in the block to those statements, * and make the resulting list the list of statements * for the block. */ if (s != NULL) { sappend(s, b->stmts); b->stmts = s; } } static struct block * gen_ppi_dlt_check(void) { struct slist *s_load_dlt; struct block *b; if (linktype == DLT_PPI) { /* Create the statements that check for the DLT */ s_load_dlt = new_stmt(BPF_LD|BPF_W|BPF_ABS); s_load_dlt->s.k = 4; b = new_block(JMP(BPF_JEQ)); b->stmts = s_load_dlt; b->s.k = SWAPLONG(DLT_IEEE802_11); } else { b = NULL; } return b; } static struct slist * gen_prism_llprefixlen(void) { struct slist *s; if (reg_off_ll == -1) { /* * We haven't yet assigned a register for the length * of the radio header; allocate one. */ reg_off_ll = alloc_reg(); } /* * Load the register containing the radio length * into the X register. */ s = new_stmt(BPF_LDX|BPF_MEM); s->s.k = reg_off_ll; return s; } static struct slist * gen_avs_llprefixlen(void) { struct slist *s; if (reg_off_ll == -1) { /* * We haven't yet assigned a register for the length * of the AVS header; allocate one. */ reg_off_ll = alloc_reg(); } /* * Load the register containing the AVS length * into the X register. */ s = new_stmt(BPF_LDX|BPF_MEM); s->s.k = reg_off_ll; return s; } static struct slist * gen_radiotap_llprefixlen(void) { struct slist *s; if (reg_off_ll == -1) { /* * We haven't yet assigned a register for the length * of the radiotap header; allocate one. */ reg_off_ll = alloc_reg(); } /* * Load the register containing the radiotap length * into the X register. */ s = new_stmt(BPF_LDX|BPF_MEM); s->s.k = reg_off_ll; return s; } /* * At the moment we treat PPI as normal Radiotap encoded * packets. The difference is in the function that generates * the code at the beginning to compute the header length. * Since this code generator of PPI supports bare 802.11 * encapsulation only (i.e. the encapsulated DLT should be * DLT_IEEE802_11) we generate code to check for this too. */ static struct slist * gen_ppi_llprefixlen(void) { struct slist *s; if (reg_off_ll == -1) { /* * We haven't yet assigned a register for the length * of the radiotap header; allocate one. */ reg_off_ll = alloc_reg(); } /* * Load the register containing the PPI length * into the X register. */ s = new_stmt(BPF_LDX|BPF_MEM); s->s.k = reg_off_ll; return s; } /* * Generate code to compute the link-layer header length, if necessary, * putting it into the X register, and to return either a pointer to a * "struct slist" for the list of statements in that code, or NULL if * no code is necessary. */ static struct slist * gen_llprefixlen(void) { switch (linktype) { case DLT_PRISM_HEADER: return gen_prism_llprefixlen(); case DLT_IEEE802_11_RADIO_AVS: return gen_avs_llprefixlen(); case DLT_IEEE802_11_RADIO: return gen_radiotap_llprefixlen(); case DLT_PPI: return gen_ppi_llprefixlen(); default: return NULL; } } /* * Generate code to load the register containing the offset of the * MAC-layer payload into the X register; if no register for that offset * has been allocated, allocate it first. */ static struct slist * gen_off_macpl(void) { struct slist *s; if (off_macpl_is_variable) { if (reg_off_macpl == -1) { /* * We haven't yet assigned a register for the offset * of the MAC-layer payload; allocate one. */ reg_off_macpl = alloc_reg(); } /* * Load the register containing the offset of the MAC-layer * payload into the X register. */ s = new_stmt(BPF_LDX|BPF_MEM); s->s.k = reg_off_macpl; return s; } else { /* * That offset isn't variable, so we don't need to * generate any code. */ return NULL; } } /* * Map an Ethernet type to the equivalent PPP type. */ static int ethertype_to_ppptype(proto) int proto; { switch (proto) { case ETHERTYPE_IP: proto = PPP_IP; break; -#ifdef INET6 case ETHERTYPE_IPV6: proto = PPP_IPV6; break; -#endif case ETHERTYPE_DN: proto = PPP_DECNET; break; case ETHERTYPE_ATALK: proto = PPP_APPLE; break; case ETHERTYPE_NS: proto = PPP_NS; break; 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; } return (proto); } /* * Generate code to match a particular packet type by matching the * link-layer type field or fields in the 802.2 LLC header. * * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP * value, if <= ETHERMTU. */ static struct block * gen_linktype(proto) register int proto; { struct block *b0, *b1, *b2; /* are we checking MPLS-encapsulated packets? */ if (label_stack_depth > 0) { switch (proto) { case ETHERTYPE_IP: case PPP_IP: /* FIXME add other L3 proto IDs */ return gen_mpls_linktype(Q_IP); case ETHERTYPE_IPV6: case PPP_IPV6: /* FIXME add other L3 proto IDs */ return gen_mpls_linktype(Q_IPV6); default: bpf_error("unsupported protocol over mpls"); /* NOTREACHED */ } } /* * Are we testing PPPoE packets? */ if (is_pppoes) { /* * The PPPoE session header is part of the * MAC-layer payload, so all references * should be relative to the beginning of * that payload. */ /* * We use Ethernet protocol types inside libpcap; * map them to the corresponding PPP protocol types. */ proto = ethertype_to_ppptype(proto); return gen_cmp(OR_MACPL, off_linktype, BPF_H, (bpf_int32)proto); } switch (linktype) { case DLT_EN10MB: case DLT_NETANALYZER: case DLT_NETANALYZER_TRANSPARENT: return gen_ether_linktype(proto); /*NOTREACHED*/ break; case DLT_C_HDLC: switch (proto) { case LLCSAP_ISONS: proto = (proto << 8 | LLCSAP_ISONS); /* fall through */ default: return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); /*NOTREACHED*/ break; } break; case DLT_IEEE802_11: case DLT_PRISM_HEADER: case DLT_IEEE802_11_RADIO_AVS: case DLT_IEEE802_11_RADIO: case DLT_PPI: /* * Check that we have a data frame. */ b0 = gen_check_802_11_data_frame(); /* * Now check for the specified link-layer type. */ b1 = gen_llc_linktype(proto); gen_and(b0, b1); return b1; /*NOTREACHED*/ break; case DLT_FDDI: /* * XXX - check for asynchronous frames, as per RFC 1103. */ return gen_llc_linktype(proto); /*NOTREACHED*/ break; case DLT_IEEE802: /* * XXX - check for LLC PDUs, as per IEEE 802.5. */ return gen_llc_linktype(proto); /*NOTREACHED*/ break; case DLT_ATM_RFC1483: case DLT_ATM_CLIP: case DLT_IP_OVER_FC: return gen_llc_linktype(proto); /*NOTREACHED*/ break; case DLT_SUNATM: /* * If "is_lane" is set, check for a LANE-encapsulated * version of this protocol, otherwise check for an * LLC-encapsulated version of this protocol. * * We assume LANE means Ethernet, not Token Ring. */ if (is_lane) { /* * Check that the packet doesn't begin with an * LE Control marker. (We've already generated * a test for LANE.) */ b0 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00); gen_not(b0); /* * Now generate an Ethernet test. */ b1 = gen_ether_linktype(proto); gen_and(b0, b1); return b1; } else { /* * Check for LLC encapsulation and then check the * protocol. */ b0 = gen_atmfield_code(A_PROTOTYPE, PT_LLC, BPF_JEQ, 0); b1 = gen_llc_linktype(proto); gen_and(b0, b1); return b1; } /*NOTREACHED*/ break; case DLT_LINUX_SLL: return gen_linux_sll_linktype(proto); /*NOTREACHED*/ break; case DLT_SLIP: case DLT_SLIP_BSDOS: case DLT_RAW: /* * These types don't provide any type field; packets * are always IPv4 or IPv6. * * 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: /* Check for a version number of 4. */ return gen_mcmp(OR_LINK, 0, BPF_B, 0x40, 0xF0); -#ifdef INET6 + case ETHERTYPE_IPV6: /* Check for a version number of 6. */ return gen_mcmp(OR_LINK, 0, BPF_B, 0x60, 0xF0); -#endif default: return gen_false(); /* always false */ } /*NOTREACHED*/ break; case DLT_IPV4: /* * Raw IPv4, so no type field. */ if (proto == ETHERTYPE_IP) return gen_true(); /* always true */ /* Checking for something other than IPv4; always false */ return gen_false(); /*NOTREACHED*/ break; case DLT_IPV6: /* * Raw IPv6, so no type field. */ -#ifdef INET6 if (proto == ETHERTYPE_IPV6) return gen_true(); /* always true */ -#endif /* Checking for something other than IPv6; always false */ return gen_false(); /*NOTREACHED*/ break; case DLT_PPP: case DLT_PPP_PPPD: case DLT_PPP_SERIAL: case DLT_PPP_ETHER: /* * We use Ethernet protocol types inside libpcap; * map them to the corresponding PPP protocol types. */ proto = ethertype_to_ppptype(proto); return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); /*NOTREACHED*/ break; case DLT_PPP_BSDOS: /* * We use Ethernet protocol types inside libpcap; * map them to the corresponding PPP protocol types. */ switch (proto) { case ETHERTYPE_IP: /* * Also check for Van Jacobson-compressed IP. * XXX - do this for other forms of PPP? */ b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_IP); b1 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_VJC); gen_or(b0, b1); b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_VJNC); gen_or(b1, b0); return b0; default: proto = ethertype_to_ppptype(proto); return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); } /*NOTREACHED*/ break; case DLT_NULL: case DLT_LOOP: case DLT_ENC: /* * For DLT_NULL, the link-layer header is a 32-bit * word containing an AF_ value in *host* byte order, * and for DLT_ENC, the link-layer header begins * with a 32-bit work containing an AF_ value in * host byte order. * * In addition, if we're reading a saved capture file, * the host byte order in the capture may not be the * same as the host byte order on this machine. * * For DLT_LOOP, the link-layer header is a 32-bit * word containing an AF_ value in *network* byte order. * * XXX - AF_ values may, unfortunately, be platform- * dependent; for example, FreeBSD's AF_INET6 is 24 * whilst NetBSD's and OpenBSD's is 26. * * This means that, when reading a capture file, just * checking for our AF_INET6 value won't work if the * capture file came from another OS. */ switch (proto) { case ETHERTYPE_IP: proto = AF_INET; break; #ifdef INET6 case ETHERTYPE_IPV6: proto = AF_INET6; break; #endif default: /* * Not a type on which we support filtering. * XXX - support those that have AF_ values * #defined on this platform, at least? */ return gen_false(); } if (linktype == DLT_NULL || linktype == DLT_ENC) { /* * The AF_ value is in host byte order, but * the BPF interpreter will convert it to * network byte order. * * If this is a save file, and it's from a * machine with the opposite byte order to * ours, we byte-swap the AF_ value. * * Then we run it through "htonl()", and * generate code to compare against the result. */ if (bpf_pcap->sf.rfile != NULL && bpf_pcap->sf.swapped) proto = SWAPLONG(proto); proto = htonl(proto); } return (gen_cmp(OR_LINK, 0, BPF_W, (bpf_int32)proto)); #ifdef HAVE_NET_PFVAR_H case DLT_PFLOG: /* * af field is host byte order in contrast to the rest of * the packet. */ if (proto == ETHERTYPE_IP) return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af), BPF_B, (bpf_int32)AF_INET)); -#ifdef INET6 else if (proto == ETHERTYPE_IPV6) return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af), BPF_B, (bpf_int32)AF_INET6)); -#endif /* INET6 */ else return gen_false(); /*NOTREACHED*/ break; #endif /* HAVE_NET_PFVAR_H */ case DLT_ARCNET: case DLT_ARCNET_LINUX: /* * 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(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_INET6)); -#endif /* INET6 */ case ETHERTYPE_IP: b0 = gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_IP); b1 = gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_IP_OLD); gen_or(b0, b1); return (b1); case ETHERTYPE_ARP: b0 = gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_ARP); b1 = gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_ARP_OLD); gen_or(b0, b1); return (b1); case ETHERTYPE_REVARP: return (gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_REVARP)); case ETHERTYPE_ATALK: return (gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_ATALK)); } /*NOTREACHED*/ break; case DLT_LTALK: switch (proto) { case ETHERTYPE_ATALK: return gen_true(); default: return gen_false(); } /*NOTREACHED*/ break; case DLT_FRELAY: /* * XXX - assumes a 2-byte Frame Relay header with * DLCI and flags. What if the address is longer? */ switch (proto) { case ETHERTYPE_IP: /* * Check for the special NLPID for IP. */ return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0xcc); -#ifdef INET6 case ETHERTYPE_IPV6: /* * Check for the special NLPID for IPv6. */ return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0x8e); -#endif case LLCSAP_ISONS: /* * Check for several OSI protocols. * * Frame Relay packets typically have an OSI * NLPID at the beginning; we check for each * of them. * * What we check for is the NLPID and a frame * control field of UI, i.e. 0x03 followed * by the NLPID. */ b0 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO8473_CLNP); b1 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO9542_ESIS); b2 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO10589_ISIS); gen_or(b1, b2); gen_or(b0, b2); return b2; default: return gen_false(); } /*NOTREACHED*/ break; case DLT_MFR: bpf_error("Multi-link Frame Relay link-layer type filtering not implemented"); case DLT_JUNIPER_MFR: case DLT_JUNIPER_MLFR: case DLT_JUNIPER_MLPPP: case DLT_JUNIPER_ATM1: case DLT_JUNIPER_ATM2: case DLT_JUNIPER_PPPOE: case DLT_JUNIPER_PPPOE_ATM: case DLT_JUNIPER_GGSN: case DLT_JUNIPER_ES: case DLT_JUNIPER_MONITOR: case DLT_JUNIPER_SERVICES: case DLT_JUNIPER_ETHER: case DLT_JUNIPER_PPP: case DLT_JUNIPER_FRELAY: case DLT_JUNIPER_CHDLC: case DLT_JUNIPER_VP: case DLT_JUNIPER_ST: case DLT_JUNIPER_ISM: case DLT_JUNIPER_VS: case DLT_JUNIPER_SRX_E2E: case DLT_JUNIPER_FIBRECHANNEL: case DLT_JUNIPER_ATM_CEMIC: /* just lets verify the magic number for now - * on ATM we may have up to 6 different encapsulations on the wire * and need a lot of heuristics to figure out that the payload * might be; * * FIXME encapsulation specific BPF_ filters */ return gen_mcmp(OR_LINK, 0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */ case DLT_IPNET: return gen_ipnet_linktype(proto); case DLT_LINUX_IRDA: bpf_error("IrDA link-layer type filtering not implemented"); case DLT_DOCSIS: bpf_error("DOCSIS link-layer type filtering not implemented"); case DLT_MTP2: case DLT_MTP2_WITH_PHDR: bpf_error("MTP2 link-layer type filtering not implemented"); case DLT_ERF: bpf_error("ERF link-layer type filtering not implemented"); case DLT_PFSYNC: bpf_error("PFSYNC link-layer type filtering not implemented"); case DLT_LINUX_LAPD: bpf_error("LAPD link-layer type filtering not implemented"); case DLT_USB: case DLT_USB_LINUX: case DLT_USB_LINUX_MMAPPED: bpf_error("USB link-layer type filtering not implemented"); case DLT_BLUETOOTH_HCI_H4: case DLT_BLUETOOTH_HCI_H4_WITH_PHDR: bpf_error("Bluetooth link-layer type filtering not implemented"); case DLT_CAN20B: case DLT_CAN_SOCKETCAN: bpf_error("CAN link-layer type filtering not implemented"); case DLT_IEEE802_15_4: case DLT_IEEE802_15_4_LINUX: case DLT_IEEE802_15_4_NONASK_PHY: case DLT_IEEE802_15_4_NOFCS: bpf_error("IEEE 802.15.4 link-layer type filtering not implemented"); case DLT_IEEE802_16_MAC_CPS_RADIO: bpf_error("IEEE 802.16 link-layer type filtering not implemented"); case DLT_SITA: bpf_error("SITA link-layer type filtering not implemented"); case DLT_RAIF1: bpf_error("RAIF1 link-layer type filtering not implemented"); case DLT_IPMB: bpf_error("IPMB link-layer type filtering not implemented"); case DLT_AX25_KISS: bpf_error("AX.25 link-layer type filtering not implemented"); } /* * 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 == (u_int)-1) abort(); /* * Any type not handled above should always have an Ethernet * type at an offset of "off_linktype". */ return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); } /* * Check for an LLC SNAP packet with a given organization code and * protocol type; we check the entire contents of the 802.2 LLC and * snap headers, checking for DSAP and SSAP of SNAP and a control * field of 0x03 in the LLC header, and for the specified organization * code and protocol type in the SNAP header. */ static struct block * gen_snap(orgcode, ptype) bpf_u_int32 orgcode; bpf_u_int32 ptype; { u_char snapblock[8]; 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 */ snapblock[5] = (orgcode >> 0); /* lower 8 bits of organization code */ snapblock[6] = (ptype >> 8); /* upper 8 bits of protocol type */ snapblock[7] = (ptype >> 0); /* lower 8 bits of protocol type */ return gen_bcmp(OR_MACPL, 0, 8, snapblock); } /* * Generate code to match a particular packet type, for link-layer types * using 802.2 LLC headers. * * This is *NOT* used for Ethernet; "gen_ether_linktype()" is used * for that - it handles the D/I/X Ethernet vs. 802.3+802.2 issues. * * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP * value, if <= ETHERMTU. We use that to determine whether to * match the DSAP or both DSAP and LSAP or to check the OUI and * protocol ID in a SNAP header. */ static struct block * gen_llc_linktype(proto) int proto; { /* * XXX - handle token-ring variable-length header. */ switch (proto) { case LLCSAP_IP: case LLCSAP_ISONS: case LLCSAP_NETBEUI: /* * XXX - should we check both the DSAP and the * SSAP, like this, or should we check just the * DSAP, as we do for other types <= ETHERMTU * (i.e., other SAP values)? */ return gen_cmp(OR_MACPL, 0, BPF_H, (bpf_u_int32) ((proto << 8) | proto)); case LLCSAP_IPX: /* * XXX - are there ever SNAP frames for IPX on * non-Ethernet 802.x networks? */ return gen_cmp(OR_MACPL, 0, 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); 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(OR_MACPL, 0, 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); * * 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(OR_MACPL, 6, BPF_H, (bpf_int32)proto); } } } static struct block * gen_hostop(addr, mask, dir, proto, src_off, dst_off) bpf_u_int32 addr; bpf_u_int32 mask; int dir, proto; u_int src_off, dst_off; { struct block *b0, *b1; u_int offset; switch (dir) { case Q_SRC: offset = src_off; break; case Q_DST: offset = dst_off; break; case Q_AND: b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off); b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off); gen_and(b0, b1); return b1; case Q_OR: case Q_DEFAULT: b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off); b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off); gen_or(b0, b1); return b1; default: abort(); } b0 = gen_linktype(proto); b1 = gen_mcmp(OR_NET, offset, BPF_W, (bpf_int32)addr, mask); gen_and(b0, b1); return b1; } #ifdef INET6 static struct block * gen_hostop6(addr, mask, dir, proto, src_off, dst_off) struct in6_addr *addr; struct in6_addr *mask; int dir, proto; u_int src_off, dst_off; { struct block *b0, *b1; u_int offset; u_int32_t *a, *m; switch (dir) { case Q_SRC: offset = src_off; break; case Q_DST: offset = dst_off; break; case Q_AND: b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off); b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off); gen_and(b0, b1); return b1; case Q_OR: case Q_DEFAULT: b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off); b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off); gen_or(b0, b1); return b1; default: abort(); } /* this order is important */ a = (u_int32_t *)addr; m = (u_int32_t *)mask; b1 = gen_mcmp(OR_NET, offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3])); b0 = gen_mcmp(OR_NET, offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2])); gen_and(b0, b1); b0 = gen_mcmp(OR_NET, offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1])); gen_and(b0, b1); b0 = gen_mcmp(OR_NET, offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0])); gen_and(b0, b1); b0 = gen_linktype(proto); gen_and(b0, b1); return b1; } -#endif /*INET6*/ +#endif static struct block * gen_ehostop(eaddr, dir) register const u_char *eaddr; register int dir; { register struct block *b0, *b1; switch (dir) { case Q_SRC: return gen_bcmp(OR_LINK, off_mac + 6, 6, eaddr); case Q_DST: return gen_bcmp(OR_LINK, off_mac + 0, 6, eaddr); case Q_AND: b0 = gen_ehostop(eaddr, Q_SRC); b1 = gen_ehostop(eaddr, Q_DST); gen_and(b0, b1); return b1; case Q_DEFAULT: case Q_OR: b0 = gen_ehostop(eaddr, Q_SRC); b1 = gen_ehostop(eaddr, Q_DST); gen_or(b0, b1); return b1; case Q_ADDR1: bpf_error("'addr1' is only supported on 802.11 with 802.11 headers"); break; case Q_ADDR2: bpf_error("'addr2' is only supported on 802.11 with 802.11 headers"); break; case Q_ADDR3: bpf_error("'addr3' is only supported on 802.11 with 802.11 headers"); break; case Q_ADDR4: bpf_error("'addr4' is only supported on 802.11 with 802.11 headers"); break; case Q_RA: bpf_error("'ra' is only supported on 802.11 with 802.11 headers"); break; case Q_TA: bpf_error("'ta' is only supported on 802.11 with 802.11 headers"); break; } abort(); /* NOTREACHED */ } /* * Like gen_ehostop, but for DLT_FDDI */ static struct block * gen_fhostop(eaddr, dir) register const u_char *eaddr; register int dir; { struct block *b0, *b1; switch (dir) { case Q_SRC: #ifdef PCAP_FDDIPAD return gen_bcmp(OR_LINK, 6 + 1 + pcap_fddipad, 6, eaddr); #else return gen_bcmp(OR_LINK, 6 + 1, 6, eaddr); #endif case Q_DST: #ifdef PCAP_FDDIPAD return gen_bcmp(OR_LINK, 0 + 1 + pcap_fddipad, 6, eaddr); #else return gen_bcmp(OR_LINK, 0 + 1, 6, eaddr); #endif case Q_AND: b0 = gen_fhostop(eaddr, Q_SRC); b1 = gen_fhostop(eaddr, Q_DST); gen_and(b0, b1); return b1; case Q_DEFAULT: case Q_OR: b0 = gen_fhostop(eaddr, Q_SRC); b1 = gen_fhostop(eaddr, Q_DST); gen_or(b0, b1); return b1; case Q_ADDR1: bpf_error("'addr1' is only supported on 802.11"); break; case Q_ADDR2: bpf_error("'addr2' is only supported on 802.11"); break; case Q_ADDR3: bpf_error("'addr3' is only supported on 802.11"); break; case Q_ADDR4: bpf_error("'addr4' is only supported on 802.11"); break; case Q_RA: bpf_error("'ra' is only supported on 802.11"); break; case Q_TA: bpf_error("'ta' is only supported on 802.11"); break; } abort(); /* NOTREACHED */ } /* * Like gen_ehostop, but for DLT_IEEE802 (Token Ring) */ static struct block * gen_thostop(eaddr, dir) register const u_char *eaddr; register int dir; { register struct block *b0, *b1; switch (dir) { case Q_SRC: return gen_bcmp(OR_LINK, 8, 6, eaddr); case Q_DST: return gen_bcmp(OR_LINK, 2, 6, eaddr); case Q_AND: b0 = gen_thostop(eaddr, Q_SRC); b1 = gen_thostop(eaddr, Q_DST); gen_and(b0, b1); return b1; case Q_DEFAULT: case Q_OR: b0 = gen_thostop(eaddr, Q_SRC); b1 = gen_thostop(eaddr, Q_DST); gen_or(b0, b1); return b1; case Q_ADDR1: bpf_error("'addr1' is only supported on 802.11"); break; case Q_ADDR2: bpf_error("'addr2' is only supported on 802.11"); break; case Q_ADDR3: bpf_error("'addr3' is only supported on 802.11"); break; case Q_ADDR4: bpf_error("'addr4' is only supported on 802.11"); break; case Q_RA: bpf_error("'ra' is only supported on 802.11"); break; case Q_TA: bpf_error("'ta' is only supported on 802.11"); break; } abort(); /* NOTREACHED */ } /* * Like gen_ehostop, but for DLT_IEEE802_11 (802.11 wireless LAN) and * various 802.11 + radio headers. */ static struct block * gen_wlanhostop(eaddr, dir) register const u_char *eaddr; register int dir; { register struct block *b0, *b1, *b2; register struct slist *s; #ifdef ENABLE_WLAN_FILTERING_PATCH /* * TODO GV 20070613 * We need to disable the optimizer because the optimizer is buggy * and wipes out some LD instructions generated by the below * code to validate the Frame Control bits */ no_optimize = 1; #endif /* ENABLE_WLAN_FILTERING_PATCH */ switch (dir) { case Q_SRC: /* * Oh, yuk. * * For control frames, there is no SA. * * For management frames, SA is at an * offset of 10 from the beginning of * the packet. * * For data frames, SA is at an offset * of 10 from the beginning of the packet * if From DS is clear, at an offset of * 16 from the beginning of the packet * if From DS is set and To DS is clear, * and an offset of 24 from the beginning * of the packet if From DS is set and To DS * is set. */ /* * Generate the tests to be done for data frames * with From DS set. * * First, check for To DS set, i.e. check "link[1] & 0x01". */ s = gen_load_a(OR_LINK, 1, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x01; /* To DS */ b1->stmts = s; /* * If To DS is set, the SA is at 24. */ b0 = gen_bcmp(OR_LINK, 24, 6, eaddr); gen_and(b1, b0); /* * Now, check for To DS not set, i.e. check * "!(link[1] & 0x01)". */ s = gen_load_a(OR_LINK, 1, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x01; /* To DS */ b2->stmts = s; gen_not(b2); /* * If To DS is not set, the SA is at 16. */ b1 = gen_bcmp(OR_LINK, 16, 6, eaddr); gen_and(b2, b1); /* * Now OR together the last two checks. That gives * the complete set of checks for data frames with * From DS set. */ gen_or(b1, b0); /* * Now check for From DS being set, and AND that with * the ORed-together checks. */ s = gen_load_a(OR_LINK, 1, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x02; /* From DS */ b1->stmts = s; gen_and(b1, b0); /* * Now check for data frames with From DS not set. */ s = gen_load_a(OR_LINK, 1, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x02; /* From DS */ b2->stmts = s; gen_not(b2); /* * If From DS isn't set, the SA is at 10. */ b1 = gen_bcmp(OR_LINK, 10, 6, eaddr); gen_and(b2, b1); /* * Now OR together the checks for data frames with * From DS not set and for data frames with From DS * set; that gives the checks done for data frames. */ gen_or(b1, b0); /* * Now check for a data frame. * I.e, check "link[0] & 0x08". */ s = gen_load_a(OR_LINK, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x08; b1->stmts = s; /* * AND that with the checks done for data frames. */ gen_and(b1, b0); /* * If the high-order bit of the type value is 0, this * is a management frame. * I.e, check "!(link[0] & 0x08)". */ s = gen_load_a(OR_LINK, 0, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x08; b2->stmts = s; gen_not(b2); /* * For management frames, the SA is at 10. */ b1 = gen_bcmp(OR_LINK, 10, 6, eaddr); gen_and(b2, b1); /* * OR that with the checks done for data frames. * That gives the checks done for management and * data frames. */ gen_or(b1, b0); /* * If the low-order bit of the type value is 1, * this is either a control frame or a frame * with a reserved type, and thus not a * frame with an SA. * * I.e., check "!(link[0] & 0x04)". */ s = gen_load_a(OR_LINK, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x04; b1->stmts = s; gen_not(b1); /* * AND that with the checks for data and management * frames. */ gen_and(b1, b0); return b0; case Q_DST: /* * Oh, yuk. * * For control frames, there is no DA. * * For management frames, DA is at an * offset of 4 from the beginning of * the packet. * * For data frames, DA is at an offset * of 4 from the beginning of the packet * if To DS is clear and at an offset of * 16 from the beginning of the packet * if To DS is set. */ /* * Generate the tests to be done for data frames. * * First, check for To DS set, i.e. "link[1] & 0x01". */ s = gen_load_a(OR_LINK, 1, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x01; /* To DS */ b1->stmts = s; /* * If To DS is set, the DA is at 16. */ b0 = gen_bcmp(OR_LINK, 16, 6, eaddr); gen_and(b1, b0); /* * Now, check for To DS not set, i.e. check * "!(link[1] & 0x01)". */ s = gen_load_a(OR_LINK, 1, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x01; /* To DS */ b2->stmts = s; gen_not(b2); /* * If To DS is not set, the DA is at 4. */ b1 = gen_bcmp(OR_LINK, 4, 6, eaddr); gen_and(b2, b1); /* * Now OR together the last two checks. That gives * the complete set of checks for data frames. */ gen_or(b1, b0); /* * Now check for a data frame. * I.e, check "link[0] & 0x08". */ s = gen_load_a(OR_LINK, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x08; b1->stmts = s; /* * AND that with the checks done for data frames. */ gen_and(b1, b0); /* * If the high-order bit of the type value is 0, this * is a management frame. * I.e, check "!(link[0] & 0x08)". */ s = gen_load_a(OR_LINK, 0, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x08; b2->stmts = s; gen_not(b2); /* * For management frames, the DA is at 4. */ b1 = gen_bcmp(OR_LINK, 4, 6, eaddr); gen_and(b2, b1); /* * OR that with the checks done for data frames. * That gives the checks done for management and * data frames. */ gen_or(b1, b0); /* * If the low-order bit of the type value is 1, * this is either a control frame or a frame * with a reserved type, and thus not a * frame with an SA. * * I.e., check "!(link[0] & 0x04)". */ s = gen_load_a(OR_LINK, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x04; b1->stmts = s; gen_not(b1); /* * AND that with the checks for data and management * frames. */ gen_and(b1, b0); return b0; case Q_RA: /* * Not present in management frames; addr1 in other * frames. */ /* * If the high-order bit of the type value is 0, this * is a management frame. * I.e, check "(link[0] & 0x08)". */ s = gen_load_a(OR_LINK, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x08; b1->stmts = s; /* * Check addr1. */ b0 = gen_bcmp(OR_LINK, 4, 6, eaddr); /* * AND that with the check of addr1. */ gen_and(b1, b0); return (b0); case Q_TA: /* * Not present in management frames; addr2, if present, * in other frames. */ /* * Not present in CTS or ACK control frames. */ b0 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_TYPE_CTL, IEEE80211_FC0_TYPE_MASK); gen_not(b0); b1 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS, IEEE80211_FC0_SUBTYPE_MASK); gen_not(b1); b2 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK, IEEE80211_FC0_SUBTYPE_MASK); gen_not(b2); gen_and(b1, b2); gen_or(b0, b2); /* * If the high-order bit of the type value is 0, this * is a management frame. * I.e, check "(link[0] & 0x08)". */ s = gen_load_a(OR_LINK, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x08; b1->stmts = s; /* * AND that with the check for frames other than * CTS and ACK frames. */ gen_and(b1, b2); /* * Check addr2. */ b1 = gen_bcmp(OR_LINK, 10, 6, eaddr); gen_and(b2, b1); return b1; /* * XXX - add BSSID keyword? */ case Q_ADDR1: return (gen_bcmp(OR_LINK, 4, 6, eaddr)); case Q_ADDR2: /* * Not present in CTS or ACK control frames. */ b0 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_TYPE_CTL, IEEE80211_FC0_TYPE_MASK); gen_not(b0); b1 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS, IEEE80211_FC0_SUBTYPE_MASK); gen_not(b1); b2 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK, IEEE80211_FC0_SUBTYPE_MASK); gen_not(b2); gen_and(b1, b2); gen_or(b0, b2); b1 = gen_bcmp(OR_LINK, 10, 6, eaddr); gen_and(b2, b1); return b1; case Q_ADDR3: /* * Not present in control frames. */ b0 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_TYPE_CTL, IEEE80211_FC0_TYPE_MASK); gen_not(b0); b1 = gen_bcmp(OR_LINK, 16, 6, eaddr); gen_and(b0, b1); return b1; case Q_ADDR4: /* * Present only if the direction mask has both "From DS" * and "To DS" set. Neither control frames nor management * frames should have both of those set, so we don't * check the frame type. */ b0 = gen_mcmp(OR_LINK, 1, BPF_B, IEEE80211_FC1_DIR_DSTODS, IEEE80211_FC1_DIR_MASK); b1 = gen_bcmp(OR_LINK, 24, 6, eaddr); gen_and(b0, b1); return b1; case Q_AND: b0 = gen_wlanhostop(eaddr, Q_SRC); b1 = gen_wlanhostop(eaddr, Q_DST); gen_and(b0, b1); return b1; case Q_DEFAULT: case Q_OR: b0 = gen_wlanhostop(eaddr, Q_SRC); b1 = gen_wlanhostop(eaddr, Q_DST); gen_or(b0, b1); return b1; } abort(); /* NOTREACHED */ } /* * Like gen_ehostop, but for RFC 2625 IP-over-Fibre-Channel. * (We assume that the addresses are IEEE 48-bit MAC addresses, * as the RFC states.) */ static struct block * gen_ipfchostop(eaddr, dir) register const u_char *eaddr; register int dir; { register struct block *b0, *b1; switch (dir) { case Q_SRC: return gen_bcmp(OR_LINK, 10, 6, eaddr); case Q_DST: return gen_bcmp(OR_LINK, 2, 6, eaddr); case Q_AND: b0 = gen_ipfchostop(eaddr, Q_SRC); b1 = gen_ipfchostop(eaddr, Q_DST); gen_and(b0, b1); return b1; case Q_DEFAULT: case Q_OR: b0 = gen_ipfchostop(eaddr, Q_SRC); b1 = gen_ipfchostop(eaddr, Q_DST); gen_or(b0, b1); return b1; case Q_ADDR1: bpf_error("'addr1' is only supported on 802.11"); break; case Q_ADDR2: bpf_error("'addr2' is only supported on 802.11"); break; case Q_ADDR3: bpf_error("'addr3' is only supported on 802.11"); break; case Q_ADDR4: bpf_error("'addr4' is only supported on 802.11"); break; case Q_RA: bpf_error("'ra' is only supported on 802.11"); break; case Q_TA: bpf_error("'ta' is only supported on 802.11"); break; } abort(); /* NOTREACHED */ } /* * This is quite tricky because there may be pad bytes in front of the * DECNET header, and then there are two possible data packet formats that * carry both src and dst addresses, plus 5 packet types in a format that * carries only the src node, plus 2 types that use a different format and * also carry just the src node. * * Yuck. * * Instead of doing those all right, we just look for data packets with * 0 or 1 bytes of padding. If you want to look at other packets, that * will require a lot more hacking. * * To add support for filtering on DECNET "areas" (network numbers) * one would want to add a "mask" argument to this routine. That would * make the filter even more inefficient, although one could be clever * and not generate masking instructions if the mask is 0xFFFF. */ static struct block * gen_dnhostop(addr, dir) bpf_u_int32 addr; int dir; { struct block *b0, *b1, *b2, *tmp; u_int offset_lh; /* offset if long header is received */ u_int offset_sh; /* offset if short header is received */ switch (dir) { case Q_DST: offset_sh = 1; /* follows flags */ offset_lh = 7; /* flgs,darea,dsubarea,HIORD */ break; case Q_SRC: offset_sh = 3; /* follows flags, dstnode */ offset_lh = 15; /* flgs,darea,dsubarea,did,sarea,ssub,HIORD */ break; case Q_AND: /* Inefficient because we do our Calvinball dance twice */ b0 = gen_dnhostop(addr, Q_SRC); b1 = gen_dnhostop(addr, Q_DST); gen_and(b0, b1); return b1; case Q_OR: case Q_DEFAULT: /* Inefficient because we do our Calvinball dance twice */ b0 = gen_dnhostop(addr, Q_SRC); b1 = gen_dnhostop(addr, Q_DST); gen_or(b0, b1); return b1; case Q_ISO: bpf_error("ISO host filtering not implemented"); default: abort(); } b0 = gen_linktype(ETHERTYPE_DN); /* Check for pad = 1, long header case */ tmp = gen_mcmp(OR_NET, 2, BPF_H, (bpf_int32)ntohs(0x0681), (bpf_int32)ntohs(0x07FF)); b1 = gen_cmp(OR_NET, 2 + 1 + offset_lh, BPF_H, (bpf_int32)ntohs((u_short)addr)); gen_and(tmp, b1); /* Check for pad = 0, long header case */ tmp = gen_mcmp(OR_NET, 2, BPF_B, (bpf_int32)0x06, (bpf_int32)0x7); b2 = gen_cmp(OR_NET, 2 + offset_lh, BPF_H, (bpf_int32)ntohs((u_short)addr)); gen_and(tmp, b2); gen_or(b2, b1); /* Check for pad = 1, short header case */ tmp = gen_mcmp(OR_NET, 2, BPF_H, (bpf_int32)ntohs(0x0281), (bpf_int32)ntohs(0x07FF)); b2 = gen_cmp(OR_NET, 2 + 1 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr)); gen_and(tmp, b2); gen_or(b2, b1); /* Check for pad = 0, short header case */ tmp = gen_mcmp(OR_NET, 2, BPF_B, (bpf_int32)0x02, (bpf_int32)0x7); b2 = gen_cmp(OR_NET, 2 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr)); gen_and(tmp, b2); gen_or(b2, b1); /* Combine with test for linktype */ gen_and(b0, b1); return b1; } /* * Generate a check for IPv4 or IPv6 for MPLS-encapsulated packets; * test the bottom-of-stack bit, and then check the version number * field in the IP header. */ static struct block * gen_mpls_linktype(proto) int proto; { struct block *b0, *b1; switch (proto) { case Q_IP: /* match the bottom-of-stack bit */ b0 = gen_mcmp(OR_NET, -2, BPF_B, 0x01, 0x01); /* match the IPv4 version number */ b1 = gen_mcmp(OR_NET, 0, BPF_B, 0x40, 0xf0); gen_and(b0, b1); return b1; case Q_IPV6: /* match the bottom-of-stack bit */ b0 = gen_mcmp(OR_NET, -2, BPF_B, 0x01, 0x01); /* match the IPv4 version number */ b1 = gen_mcmp(OR_NET, 0, BPF_B, 0x60, 0xf0); gen_and(b0, b1); return b1; default: abort(); } } static struct block * gen_host(addr, mask, proto, dir, type) bpf_u_int32 addr; bpf_u_int32 mask; int proto; int dir; int type; { struct block *b0, *b1; const char *typestr; if (type == Q_NET) typestr = "net"; else typestr = "host"; switch (proto) { case Q_DEFAULT: b0 = gen_host(addr, mask, Q_IP, dir, type); /* * Only check for non-IPv4 addresses if we're not * checking MPLS-encapsulated packets. */ if (label_stack_depth == 0) { b1 = gen_host(addr, mask, Q_ARP, dir, type); gen_or(b0, b1); b0 = gen_host(addr, mask, Q_RARP, dir, type); gen_or(b1, b0); } return b0; case Q_IP: return gen_hostop(addr, mask, dir, ETHERTYPE_IP, 12, 16); case Q_RARP: return gen_hostop(addr, mask, dir, ETHERTYPE_REVARP, 14, 24); case Q_ARP: return gen_hostop(addr, mask, dir, ETHERTYPE_ARP, 14, 24); case Q_TCP: bpf_error("'tcp' modifier applied to %s", typestr); case Q_SCTP: bpf_error("'sctp' modifier applied to %s", typestr); case Q_UDP: bpf_error("'udp' modifier applied to %s", typestr); case Q_ICMP: bpf_error("'icmp' modifier applied to %s", typestr); case Q_IGMP: bpf_error("'igmp' modifier applied to %s", typestr); case Q_IGRP: bpf_error("'igrp' modifier applied to %s", typestr); case Q_PIM: bpf_error("'pim' modifier applied to %s", typestr); case Q_VRRP: bpf_error("'vrrp' modifier applied to %s", typestr); case Q_CARP: bpf_error("'carp' modifier applied to %s", typestr); case Q_ATALK: bpf_error("ATALK host filtering not implemented"); case Q_AARP: bpf_error("AARP host filtering not implemented"); case Q_DECNET: return gen_dnhostop(addr, dir); case Q_SCA: bpf_error("SCA host filtering not implemented"); case Q_LAT: bpf_error("LAT host filtering not implemented"); case Q_MOPDL: bpf_error("MOPDL host filtering not implemented"); case Q_MOPRC: bpf_error("MOPRC host filtering not implemented"); -#ifdef INET6 case Q_IPV6: bpf_error("'ip6' modifier applied to ip host"); case Q_ICMPV6: bpf_error("'icmp6' modifier applied to %s", typestr); -#endif /* INET6 */ case Q_AH: bpf_error("'ah' modifier applied to %s", typestr); case Q_ESP: bpf_error("'esp' modifier applied to %s", typestr); case Q_ISO: bpf_error("ISO host filtering not implemented"); case Q_ESIS: bpf_error("'esis' modifier applied to %s", typestr); case Q_ISIS: bpf_error("'isis' modifier applied to %s", typestr); case Q_CLNP: bpf_error("'clnp' modifier applied to %s", typestr); case Q_STP: bpf_error("'stp' modifier applied to %s", typestr); case Q_IPX: bpf_error("IPX host filtering not implemented"); case Q_NETBEUI: bpf_error("'netbeui' modifier applied to %s", typestr); case Q_RADIO: bpf_error("'radio' modifier applied to %s", typestr); default: abort(); } /* NOTREACHED */ } #ifdef INET6 static struct block * gen_host6(addr, mask, proto, dir, type) struct in6_addr *addr; struct in6_addr *mask; int proto; int dir; int type; { const char *typestr; if (type == Q_NET) typestr = "net"; else typestr = "host"; switch (proto) { case Q_DEFAULT: return gen_host6(addr, mask, Q_IPV6, dir, type); case Q_IP: bpf_error("'ip' modifier applied to ip6 %s", typestr); case Q_RARP: bpf_error("'rarp' modifier applied to ip6 %s", typestr); case Q_ARP: bpf_error("'arp' modifier applied to ip6 %s", typestr); case Q_SCTP: bpf_error("'sctp' modifier applied to %s", typestr); case Q_TCP: bpf_error("'tcp' modifier applied to %s", typestr); case Q_UDP: bpf_error("'udp' modifier applied to %s", typestr); case Q_ICMP: bpf_error("'icmp' modifier applied to %s", typestr); case Q_IGMP: bpf_error("'igmp' modifier applied to %s", typestr); case Q_IGRP: bpf_error("'igrp' modifier applied to %s", typestr); case Q_PIM: bpf_error("'pim' modifier applied to %s", typestr); case Q_VRRP: bpf_error("'vrrp' modifier applied to %s", typestr); case Q_CARP: bpf_error("'carp' modifier applied to %s", typestr); case Q_ATALK: bpf_error("ATALK host filtering not implemented"); case Q_AARP: bpf_error("AARP host filtering not implemented"); case Q_DECNET: bpf_error("'decnet' modifier applied to ip6 %s", typestr); case Q_SCA: bpf_error("SCA host filtering not implemented"); case Q_LAT: bpf_error("LAT host filtering not implemented"); case Q_MOPDL: bpf_error("MOPDL host filtering not implemented"); case Q_MOPRC: bpf_error("MOPRC host filtering not implemented"); case Q_IPV6: return gen_hostop6(addr, mask, dir, ETHERTYPE_IPV6, 8, 24); case Q_ICMPV6: bpf_error("'icmp6' modifier applied to %s", typestr); case Q_AH: bpf_error("'ah' modifier applied to %s", typestr); case Q_ESP: bpf_error("'esp' modifier applied to %s", typestr); case Q_ISO: bpf_error("ISO host filtering not implemented"); case Q_ESIS: bpf_error("'esis' modifier applied to %s", typestr); case Q_ISIS: bpf_error("'isis' modifier applied to %s", typestr); case Q_CLNP: bpf_error("'clnp' modifier applied to %s", typestr); case Q_STP: bpf_error("'stp' modifier applied to %s", typestr); case Q_IPX: bpf_error("IPX host filtering not implemented"); case Q_NETBEUI: bpf_error("'netbeui' modifier applied to %s", typestr); case Q_RADIO: bpf_error("'radio' modifier applied to %s", typestr); default: abort(); } /* NOTREACHED */ } -#endif /*INET6*/ +#endif #ifndef INET6 static struct block * gen_gateway(eaddr, alist, proto, dir) const u_char *eaddr; bpf_u_int32 **alist; int proto; int dir; { struct block *b0, *b1, *tmp; if (dir != 0) bpf_error("direction applied to 'gateway'"); switch (proto) { case Q_DEFAULT: case Q_IP: case Q_ARP: case Q_RARP: switch (linktype) { case DLT_EN10MB: case DLT_NETANALYZER: case DLT_NETANALYZER_TRANSPARENT: b0 = gen_ehostop(eaddr, Q_OR); break; case DLT_FDDI: b0 = gen_fhostop(eaddr, Q_OR); break; case DLT_IEEE802: b0 = gen_thostop(eaddr, Q_OR); break; case DLT_IEEE802_11: case DLT_PRISM_HEADER: case DLT_IEEE802_11_RADIO_AVS: case DLT_IEEE802_11_RADIO: case DLT_PPI: b0 = gen_wlanhostop(eaddr, Q_OR); break; case DLT_SUNATM: if (!is_lane) bpf_error( "'gateway' supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel"); /* * Check that the packet doesn't begin with an * LE Control marker. (We've already generated * a test for LANE.) */ b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00); gen_not(b1); /* * Now check the MAC address. */ b0 = gen_ehostop(eaddr, Q_OR); gen_and(b1, b0); break; case DLT_IP_OVER_FC: b0 = gen_ipfchostop(eaddr, Q_OR); break; default: bpf_error( "'gateway' supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel"); } b1 = gen_host(**alist++, 0xffffffff, proto, Q_OR, Q_HOST); while (*alist) { tmp = gen_host(**alist++, 0xffffffff, proto, Q_OR, Q_HOST); gen_or(b1, tmp); b1 = tmp; } gen_not(b1); gen_and(b0, b1); return b1; } bpf_error("illegal modifier of 'gateway'"); /* NOTREACHED */ } #endif struct block * gen_proto_abbrev(proto) int proto; { struct block *b0; struct block *b1; 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 b0 = gen_proto(IPPROTO_TCP, Q_IPV6, Q_DEFAULT); gen_or(b0, b1); -#endif break; case Q_UDP: b1 = gen_proto(IPPROTO_UDP, Q_IP, Q_DEFAULT); -#ifdef INET6 b0 = gen_proto(IPPROTO_UDP, Q_IPV6, Q_DEFAULT); gen_or(b0, b1); -#endif break; case Q_ICMP: b1 = gen_proto(IPPROTO_ICMP, Q_IP, Q_DEFAULT); break; #ifndef IPPROTO_IGMP #define IPPROTO_IGMP 2 #endif case Q_IGMP: b1 = gen_proto(IPPROTO_IGMP, Q_IP, Q_DEFAULT); break; #ifndef IPPROTO_IGRP #define IPPROTO_IGRP 9 #endif case Q_IGRP: b1 = gen_proto(IPPROTO_IGRP, Q_IP, Q_DEFAULT); break; #ifndef IPPROTO_PIM #define IPPROTO_PIM 103 #endif case Q_PIM: b1 = gen_proto(IPPROTO_PIM, Q_IP, Q_DEFAULT); -#ifdef INET6 b0 = gen_proto(IPPROTO_PIM, Q_IPV6, Q_DEFAULT); gen_or(b0, b1); -#endif break; #ifndef IPPROTO_VRRP #define IPPROTO_VRRP 112 #endif case Q_VRRP: b1 = gen_proto(IPPROTO_VRRP, Q_IP, Q_DEFAULT); break; #ifndef IPPROTO_CARP #define IPPROTO_CARP 112 #endif case Q_CARP: b1 = gen_proto(IPPROTO_CARP, Q_IP, Q_DEFAULT); break; case Q_IP: b1 = gen_linktype(ETHERTYPE_IP); break; case Q_ARP: b1 = gen_linktype(ETHERTYPE_ARP); break; case Q_RARP: b1 = gen_linktype(ETHERTYPE_REVARP); break; case Q_LINK: bpf_error("link layer applied in wrong context"); case Q_ATALK: b1 = gen_linktype(ETHERTYPE_ATALK); break; case Q_AARP: b1 = gen_linktype(ETHERTYPE_AARP); break; case Q_DECNET: b1 = gen_linktype(ETHERTYPE_DN); break; case Q_SCA: b1 = gen_linktype(ETHERTYPE_SCA); break; case Q_LAT: b1 = gen_linktype(ETHERTYPE_LAT); break; case Q_MOPDL: b1 = gen_linktype(ETHERTYPE_MOPDL); break; case Q_MOPRC: b1 = gen_linktype(ETHERTYPE_MOPRC); break; -#ifdef INET6 case Q_IPV6: b1 = gen_linktype(ETHERTYPE_IPV6); break; #ifndef IPPROTO_ICMPV6 #define IPPROTO_ICMPV6 58 #endif case Q_ICMPV6: b1 = gen_proto(IPPROTO_ICMPV6, Q_IPV6, Q_DEFAULT); break; -#endif /* INET6 */ #ifndef IPPROTO_AH #define IPPROTO_AH 51 #endif case Q_AH: b1 = gen_proto(IPPROTO_AH, Q_IP, Q_DEFAULT); -#ifdef INET6 b0 = gen_proto(IPPROTO_AH, Q_IPV6, Q_DEFAULT); gen_or(b0, b1); -#endif break; #ifndef IPPROTO_ESP #define IPPROTO_ESP 50 #endif case Q_ESP: b1 = gen_proto(IPPROTO_ESP, Q_IP, Q_DEFAULT); -#ifdef INET6 b0 = gen_proto(IPPROTO_ESP, Q_IPV6, Q_DEFAULT); gen_or(b0, b1); -#endif break; case Q_ISO: b1 = gen_linktype(LLCSAP_ISONS); break; case Q_ESIS: b1 = gen_proto(ISO9542_ESIS, Q_ISO, Q_DEFAULT); break; case Q_ISIS: b1 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT); break; case Q_ISIS_L1: /* all IS-IS Level1 PDU-Types */ b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT); b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */ gen_or(b0, b1); b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_ISIS_L2: /* all IS-IS Level2 PDU-Types */ b0 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT); b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */ gen_or(b0, b1); b0 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); b0 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_ISIS_IIH: /* all IS-IS Hello PDU-Types */ b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT); b1 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); b0 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_ISIS_LSP: b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT); b1 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_ISIS_SNP: b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT); b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_ISIS_CSNP: b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT); b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_ISIS_PSNP: b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT); b1 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_CLNP: 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; case Q_RADIO: bpf_error("'radio' is not a valid protocol type"); default: abort(); } return b1; } static struct block * gen_ipfrag() { struct slist *s; struct block *b; /* not IPv4 frag other than the first frag */ s = gen_load_a(OR_NET, 6, BPF_H); b = new_block(JMP(BPF_JSET)); b->s.k = 0x1fff; b->stmts = s; gen_not(b); return b; } /* * Generate a comparison to a port value in the transport-layer header * at the specified offset from the beginning of that header. * * XXX - this handles a variable-length prefix preceding the link-layer * header, such as the radiotap or AVS radio prefix, but doesn't handle * variable-length link-layer headers (such as Token Ring or 802.11 * headers). */ static struct block * gen_portatom(off, v) int off; bpf_int32 v; { return gen_cmp(OR_TRAN_IPV4, off, BPF_H, v); } -#ifdef INET6 static struct block * gen_portatom6(off, v) int off; bpf_int32 v; { return gen_cmp(OR_TRAN_IPV6, off, BPF_H, v); } -#endif/*INET6*/ struct block * gen_portop(port, proto, dir) int port, proto, dir; { struct block *b0, *b1, *tmp; /* ip proto 'proto' and not a fragment other than the first fragment */ tmp = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)proto); b0 = gen_ipfrag(); gen_and(tmp, b0); switch (dir) { case Q_SRC: b1 = gen_portatom(0, (bpf_int32)port); break; case Q_DST: b1 = gen_portatom(2, (bpf_int32)port); break; case Q_OR: case Q_DEFAULT: tmp = gen_portatom(0, (bpf_int32)port); b1 = gen_portatom(2, (bpf_int32)port); gen_or(tmp, b1); break; case Q_AND: tmp = gen_portatom(0, (bpf_int32)port); b1 = gen_portatom(2, (bpf_int32)port); gen_and(tmp, b1); break; default: abort(); } gen_and(b0, b1); return b1; } static struct block * gen_port(port, ip_proto, dir) int port; int ip_proto; int dir; { struct block *b0, *b1, *tmp; /* * ether proto ip * * For FDDI, RFC 1188 says that SNAP encapsulation is used, * not LLC encapsulation with LLCSAP_IP. * * For IEEE 802 networks - which includes 802.5 token ring * (which is what DLT_IEEE802 means) and 802.11 - RFC 1042 * says that SNAP encapsulation is used, not LLC encapsulation * with LLCSAP_IP. * * For LLC-encapsulated ATM/"Classical IP", RFC 1483 and * RFC 2225 say that SNAP encapsulation is used, not LLC * encapsulation with LLCSAP_IP. * * So we always check for ETHERTYPE_IP. */ b0 = gen_linktype(ETHERTYPE_IP); switch (ip_proto) { case IPPROTO_UDP: case IPPROTO_TCP: case IPPROTO_SCTP: b1 = gen_portop(port, ip_proto, dir); break; case PROTO_UNDEF: tmp = gen_portop(port, IPPROTO_TCP, dir); b1 = gen_portop(port, IPPROTO_UDP, dir); gen_or(tmp, b1); tmp = gen_portop(port, IPPROTO_SCTP, dir); gen_or(tmp, b1); break; default: abort(); } gen_and(b0, b1); return b1; } -#ifdef INET6 struct block * gen_portop6(port, proto, dir) int port, proto, dir; { struct block *b0, *b1, *tmp; /* ip6 proto 'proto' */ /* XXX - catch the first fragment of a fragmented packet? */ b0 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)proto); switch (dir) { case Q_SRC: b1 = gen_portatom6(0, (bpf_int32)port); break; case Q_DST: b1 = gen_portatom6(2, (bpf_int32)port); break; case Q_OR: case Q_DEFAULT: tmp = gen_portatom6(0, (bpf_int32)port); b1 = gen_portatom6(2, (bpf_int32)port); gen_or(tmp, b1); break; case Q_AND: tmp = gen_portatom6(0, (bpf_int32)port); b1 = gen_portatom6(2, (bpf_int32)port); gen_and(tmp, b1); break; default: abort(); } gen_and(b0, b1); return b1; } static struct block * gen_port6(port, ip_proto, dir) int port; int ip_proto; int dir; { struct block *b0, *b1, *tmp; /* link proto ip6 */ b0 = gen_linktype(ETHERTYPE_IPV6); switch (ip_proto) { case IPPROTO_UDP: case IPPROTO_TCP: case IPPROTO_SCTP: b1 = gen_portop6(port, ip_proto, dir); break; case PROTO_UNDEF: 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: abort(); } gen_and(b0, b1); return b1; } -#endif /* INET6 */ /* gen_portrange code */ static struct block * gen_portrangeatom(off, v1, v2) int off; bpf_int32 v1, v2; { struct block *b1, *b2; if (v1 > v2) { /* * Reverse the order of the ports, so v1 is the lower one. */ bpf_int32 vtemp; vtemp = v1; v1 = v2; v2 = vtemp; } b1 = gen_cmp_ge(OR_TRAN_IPV4, off, BPF_H, v1); b2 = gen_cmp_le(OR_TRAN_IPV4, off, BPF_H, v2); gen_and(b1, b2); return b2; } struct block * gen_portrangeop(port1, port2, proto, dir) int port1, port2; int proto; int dir; { struct block *b0, *b1, *tmp; /* ip proto 'proto' and not a fragment other than the first fragment */ tmp = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)proto); b0 = gen_ipfrag(); gen_and(tmp, b0); switch (dir) { case Q_SRC: b1 = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2); break; case Q_DST: b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2); break; case Q_OR: case Q_DEFAULT: tmp = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2); b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2); gen_or(tmp, b1); break; case Q_AND: tmp = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2); b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2); gen_and(tmp, b1); break; default: abort(); } gen_and(b0, b1); return b1; } static struct block * gen_portrange(port1, port2, ip_proto, dir) int port1, port2; int ip_proto; int dir; { struct block *b0, *b1, *tmp; /* link proto ip */ b0 = gen_linktype(ETHERTYPE_IP); switch (ip_proto) { case IPPROTO_UDP: case IPPROTO_TCP: case IPPROTO_SCTP: b1 = gen_portrangeop(port1, port2, ip_proto, dir); break; case PROTO_UNDEF: tmp = gen_portrangeop(port1, port2, IPPROTO_TCP, dir); b1 = gen_portrangeop(port1, port2, IPPROTO_UDP, dir); gen_or(tmp, b1); tmp = gen_portrangeop(port1, port2, IPPROTO_SCTP, dir); gen_or(tmp, b1); break; default: abort(); } gen_and(b0, b1); return b1; } -#ifdef INET6 static struct block * gen_portrangeatom6(off, v1, v2) int off; bpf_int32 v1, v2; { struct block *b1, *b2; if (v1 > v2) { /* * Reverse the order of the ports, so v1 is the lower one. */ bpf_int32 vtemp; vtemp = v1; v1 = v2; v2 = vtemp; } b1 = gen_cmp_ge(OR_TRAN_IPV6, off, BPF_H, v1); b2 = gen_cmp_le(OR_TRAN_IPV6, off, BPF_H, v2); gen_and(b1, b2); return b2; } struct block * gen_portrangeop6(port1, port2, proto, dir) int port1, port2; int proto; int dir; { struct block *b0, *b1, *tmp; /* ip6 proto 'proto' */ /* XXX - catch the first fragment of a fragmented packet? */ b0 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)proto); switch (dir) { case Q_SRC: b1 = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2); break; case Q_DST: b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2); break; case Q_OR: case Q_DEFAULT: tmp = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2); b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2); gen_or(tmp, b1); break; case Q_AND: tmp = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2); b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2); gen_and(tmp, b1); break; default: abort(); } gen_and(b0, b1); return b1; } static struct block * gen_portrange6(port1, port2, ip_proto, dir) int port1, port2; int ip_proto; int dir; { struct block *b0, *b1, *tmp; /* link proto ip6 */ b0 = gen_linktype(ETHERTYPE_IPV6); switch (ip_proto) { case IPPROTO_UDP: case IPPROTO_TCP: case IPPROTO_SCTP: b1 = gen_portrangeop6(port1, port2, ip_proto, dir); break; case PROTO_UNDEF: tmp = gen_portrangeop6(port1, port2, IPPROTO_TCP, dir); b1 = gen_portrangeop6(port1, port2, IPPROTO_UDP, dir); gen_or(tmp, b1); tmp = gen_portrangeop6(port1, port2, IPPROTO_SCTP, dir); gen_or(tmp, b1); break; default: abort(); } gen_and(b0, b1); return b1; } -#endif /* INET6 */ static int lookup_proto(name, proto) register const char *name; register int proto; { register int v; switch (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); break; case Q_LINK: /* XXX should look up h/w protocol type based on linktype */ v = pcap_nametoeproto(name); if (v == PROTO_UNDEF) { v = pcap_nametollc(name); if (v == PROTO_UNDEF) bpf_error("unknown ether proto '%s'", name); } break; case Q_ISO: if (strcmp(name, "esis") == 0) v = ISO9542_ESIS; else if (strcmp(name, "isis") == 0) v = ISO10589_ISIS; else if (strcmp(name, "clnp") == 0) v = ISO8473_CLNP; else bpf_error("unknown osi proto '%s'", name); break; default: v = PROTO_UNDEF; break; } return v; } #if 0 struct stmt * gen_joinsp(s, n) struct stmt **s; int n; { return NULL; } #endif static struct block * gen_protochain(v, proto, dir) int v; int proto; int dir; { #ifdef NO_PROTOCHAIN return gen_proto(v, proto, dir); #else struct block *b0, *b; struct slist *s[100]; int fix2, fix3, fix4, fix5; int ahcheck, again, end; int i, max; int reg2 = alloc_reg(); memset(s, 0, sizeof(s)); fix2 = fix3 = fix4 = fix5 = 0; switch (proto) { case Q_IP: case Q_IPV6: break; case Q_DEFAULT: b0 = gen_protochain(v, Q_IP, dir); b = gen_protochain(v, Q_IPV6, dir); gen_or(b0, b); return b; default: bpf_error("bad protocol applied for 'protochain'"); /*NOTREACHED*/ } /* * We don't handle variable-length prefixes before the link-layer * header, or variable-length link-layer headers, here yet. * We might want to add BPF instructions to do the protochain * work, to simplify that and, on platforms that have a BPF * interpreter with the new instructions, let the filtering * be done in the kernel. (We already require a modified BPF * engine to do the protochain stuff, to support backward * branches, and backward branch support is unlikely to appear * in kernel BPF engines.) */ switch (linktype) { case DLT_IEEE802_11: case DLT_PRISM_HEADER: case DLT_IEEE802_11_RADIO_AVS: case DLT_IEEE802_11_RADIO: case DLT_PPI: bpf_error("'protochain' not supported with 802.11"); } no_optimize = 1; /*this code is not compatible with optimzer yet */ /* * s[0] is a dummy entry to protect other BPF insn from damage * by s[fix] = foo with uninitialized variable "fix". It is somewhat * hard to find interdependency made by jump table fixup. */ i = 0; s[i] = new_stmt(0); /*dummy*/ i++; switch (proto) { case Q_IP: b0 = gen_linktype(ETHERTYPE_IP); /* A = ip->ip_p */ s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B); s[i]->s.k = off_macpl + off_nl + 9; i++; /* X = ip->ip_hl << 2 */ s[i] = new_stmt(BPF_LDX|BPF_MSH|BPF_B); s[i]->s.k = off_macpl + off_nl; i++; break; -#ifdef INET6 + case Q_IPV6: b0 = gen_linktype(ETHERTYPE_IPV6); /* A = ip6->ip_nxt */ s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B); s[i]->s.k = off_macpl + off_nl + 6; i++; /* X = sizeof(struct ip6_hdr) */ s[i] = new_stmt(BPF_LDX|BPF_IMM); s[i]->s.k = 40; i++; break; -#endif + default: bpf_error("unsupported proto to gen_protochain"); /*NOTREACHED*/ } /* again: if (A == v) goto end; else fall through; */ again = i; s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K); s[i]->s.k = v; s[i]->s.jt = NULL; /*later*/ s[i]->s.jf = NULL; /*update in next stmt*/ fix5 = i; i++; #ifndef IPPROTO_NONE #define IPPROTO_NONE 59 #endif /* if (A == IPPROTO_NONE) goto end */ s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K); s[i]->s.jt = NULL; /*later*/ s[i]->s.jf = NULL; /*update in next stmt*/ s[i]->s.k = IPPROTO_NONE; s[fix5]->s.jf = s[i]; fix2 = i; i++; -#ifdef INET6 if (proto == Q_IPV6) { int v6start, v6end, v6advance, j; v6start = i; /* if (A == IPPROTO_HOPOPTS) goto v6advance */ s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K); s[i]->s.jt = NULL; /*later*/ s[i]->s.jf = NULL; /*update in next stmt*/ s[i]->s.k = IPPROTO_HOPOPTS; s[fix2]->s.jf = s[i]; i++; /* if (A == IPPROTO_DSTOPTS) goto v6advance */ s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K); s[i]->s.jt = NULL; /*later*/ s[i]->s.jf = NULL; /*update in next stmt*/ s[i]->s.k = IPPROTO_DSTOPTS; i++; /* if (A == IPPROTO_ROUTING) goto v6advance */ s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K); s[i]->s.jt = NULL; /*later*/ s[i]->s.jf = NULL; /*update in next stmt*/ s[i]->s.k = IPPROTO_ROUTING; i++; /* if (A == IPPROTO_FRAGMENT) goto v6advance; else goto ahcheck; */ s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K); s[i]->s.jt = NULL; /*later*/ s[i]->s.jf = NULL; /*later*/ s[i]->s.k = IPPROTO_FRAGMENT; fix3 = i; v6end = i; i++; /* v6advance: */ v6advance = i; /* * in short, * A = P[X + packet head]; * X = X + (P[X + packet head + 1] + 1) * 8; */ /* A = P[X + packet head] */ s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B); s[i]->s.k = off_macpl + off_nl; i++; /* MEM[reg2] = A */ s[i] = new_stmt(BPF_ST); s[i]->s.k = reg2; i++; /* A = P[X + packet head + 1]; */ s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B); s[i]->s.k = off_macpl + off_nl + 1; i++; /* A += 1 */ s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); s[i]->s.k = 1; i++; /* A *= 8 */ s[i] = new_stmt(BPF_ALU|BPF_MUL|BPF_K); s[i]->s.k = 8; i++; /* A += X */ s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_X); s[i]->s.k = 0; i++; /* X = A; */ s[i] = new_stmt(BPF_MISC|BPF_TAX); i++; /* A = MEM[reg2] */ s[i] = new_stmt(BPF_LD|BPF_MEM); s[i]->s.k = reg2; i++; /* goto again; (must use BPF_JA for backward jump) */ s[i] = new_stmt(BPF_JMP|BPF_JA); s[i]->s.k = again - i - 1; s[i - 1]->s.jf = s[i]; i++; /* fixup */ for (j = v6start; j <= v6end; j++) s[j]->s.jt = s[v6advance]; - } else -#endif - { + } else { /* nop */ s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); s[i]->s.k = 0; s[fix2]->s.jf = s[i]; i++; } /* ahcheck: */ ahcheck = i; /* if (A == IPPROTO_AH) then fall through; else goto end; */ s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K); s[i]->s.jt = NULL; /*later*/ s[i]->s.jf = NULL; /*later*/ s[i]->s.k = IPPROTO_AH; if (fix3) s[fix3]->s.jf = s[ahcheck]; fix4 = i; i++; /* * in short, * A = P[X]; * X = X + (P[X + 1] + 2) * 4; */ /* A = X */ s[i - 1]->s.jt = s[i] = new_stmt(BPF_MISC|BPF_TXA); i++; /* A = P[X + packet head]; */ s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B); s[i]->s.k = off_macpl + off_nl; i++; /* MEM[reg2] = A */ s[i] = new_stmt(BPF_ST); s[i]->s.k = reg2; i++; /* A = X */ s[i - 1]->s.jt = s[i] = new_stmt(BPF_MISC|BPF_TXA); i++; /* A += 1 */ s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); s[i]->s.k = 1; i++; /* X = A */ s[i] = new_stmt(BPF_MISC|BPF_TAX); i++; /* A = P[X + packet head] */ s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B); s[i]->s.k = off_macpl + off_nl; i++; /* A += 2 */ s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); s[i]->s.k = 2; i++; /* A *= 4 */ s[i] = new_stmt(BPF_ALU|BPF_MUL|BPF_K); s[i]->s.k = 4; i++; /* X = A; */ s[i] = new_stmt(BPF_MISC|BPF_TAX); i++; /* A = MEM[reg2] */ s[i] = new_stmt(BPF_LD|BPF_MEM); s[i]->s.k = reg2; i++; /* goto again; (must use BPF_JA for backward jump) */ s[i] = new_stmt(BPF_JMP|BPF_JA); s[i]->s.k = again - i - 1; i++; /* end: nop */ end = i; s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); s[i]->s.k = 0; s[fix2]->s.jt = s[end]; s[fix4]->s.jf = s[end]; s[fix5]->s.jt = s[end]; i++; /* * make slist chain */ max = i; for (i = 0; i < max - 1; i++) s[i]->next = s[i + 1]; s[max - 1]->next = NULL; /* * emit final check */ b = new_block(JMP(BPF_JEQ)); b->stmts = s[1]; /*remember, s[0] is dummy*/ b->s.k = v; free_reg(reg2); gen_and(b0, b); return b; #endif } static struct block * gen_check_802_11_data_frame() { struct slist *s; struct block *b0, *b1; /* * A data frame has the 0x08 bit (b3) in the frame control field set * and the 0x04 bit (b2) clear. */ s = gen_load_a(OR_LINK, 0, BPF_B); b0 = new_block(JMP(BPF_JSET)); b0->s.k = 0x08; b0->stmts = s; s = gen_load_a(OR_LINK, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x04; b1->stmts = s; gen_not(b1); gen_and(b1, b0); return b0; } /* * Generate code that checks whether the packet is a packet for protocol * and whether the type field in that protocol's header has * the value , e.g. if is Q_IP, it checks whether it's an * IP packet and checks the protocol number in the IP header against . * * If is Q_DEFAULT, i.e. just "proto" was specified, it checks * against Q_IP and Q_IPV6. */ static struct block * gen_proto(v, proto, dir) int v; int proto; int dir; { struct block *b0, *b1; -#ifdef INET6 #ifndef CHASE_CHAIN struct block *b2; #endif -#endif if (dir != Q_DEFAULT) bpf_error("direction applied to 'proto'"); switch (proto) { case Q_DEFAULT: -#ifdef INET6 b0 = gen_proto(v, Q_IP, dir); b1 = gen_proto(v, Q_IPV6, dir); gen_or(b0, b1); return b1; -#else - /*FALLTHROUGH*/ -#endif + case Q_IP: /* * For FDDI, RFC 1188 says that SNAP encapsulation is used, * not LLC encapsulation with LLCSAP_IP. * * For IEEE 802 networks - which includes 802.5 token ring * (which is what DLT_IEEE802 means) and 802.11 - RFC 1042 * says that SNAP encapsulation is used, not LLC encapsulation * with LLCSAP_IP. * * For LLC-encapsulated ATM/"Classical IP", RFC 1483 and * RFC 2225 say that SNAP encapsulation is used, not LLC * encapsulation with LLCSAP_IP. * * So we always check for ETHERTYPE_IP. */ b0 = gen_linktype(ETHERTYPE_IP); #ifndef CHASE_CHAIN b1 = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)v); #else b1 = gen_protochain(v, Q_IP); #endif gen_and(b0, b1); return b1; case Q_ISO: switch (linktype) { case DLT_FRELAY: /* * Frame Relay packets typically have an OSI * NLPID at the beginning; "gen_linktype(LLCSAP_ISONS)" * generates code to check for all the OSI * NLPIDs, so calling it and then adding a check * for the particular NLPID for which we're * looking is bogus, as we can just check for * the NLPID. * * What we check for is the NLPID and a frame * control field value of UI, i.e. 0x03 followed * by the NLPID. * * XXX - assumes a 2-byte Frame Relay header with * DLCI and flags. What if the address is longer? * * XXX - what about SNAP-encapsulated frames? */ return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | v); /*NOTREACHED*/ break; case DLT_C_HDLC: /* * Cisco uses an Ethertype lookalike - for OSI, * it's 0xfefe. */ b0 = gen_linktype(LLCSAP_ISONS<<8 | LLCSAP_ISONS); /* OSI in C-HDLC is stuffed with a fudge byte */ b1 = gen_cmp(OR_NET_NOSNAP, 1, BPF_B, (long)v); gen_and(b0, b1); return b1; default: b0 = gen_linktype(LLCSAP_ISONS); b1 = gen_cmp(OR_NET_NOSNAP, 0, BPF_B, (long)v); gen_and(b0, b1); return b1; } case Q_ISIS: b0 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT); /* * 4 is the offset of the PDU type relative to the IS-IS * header. */ b1 = gen_cmp(OR_NET_NOSNAP, 4, BPF_B, (long)v); gen_and(b0, b1); return b1; case Q_ARP: bpf_error("arp does not encapsulate another protocol"); /* NOTREACHED */ case Q_RARP: bpf_error("rarp does not encapsulate another protocol"); /* NOTREACHED */ case Q_ATALK: bpf_error("atalk encapsulation is not specifiable"); /* NOTREACHED */ case Q_DECNET: bpf_error("decnet encapsulation is not specifiable"); /* NOTREACHED */ case Q_SCA: bpf_error("sca does not encapsulate another protocol"); /* NOTREACHED */ case Q_LAT: bpf_error("lat does not encapsulate another protocol"); /* NOTREACHED */ case Q_MOPRC: bpf_error("moprc does not encapsulate another protocol"); /* NOTREACHED */ case Q_MOPDL: bpf_error("mopdl does not encapsulate another protocol"); /* NOTREACHED */ case Q_LINK: return gen_linktype(v); case Q_UDP: bpf_error("'udp proto' is bogus"); /* NOTREACHED */ case Q_TCP: bpf_error("'tcp proto' is bogus"); /* NOTREACHED */ case Q_SCTP: bpf_error("'sctp proto' is bogus"); /* NOTREACHED */ case Q_ICMP: bpf_error("'icmp proto' is bogus"); /* NOTREACHED */ case Q_IGMP: bpf_error("'igmp proto' is bogus"); /* NOTREACHED */ case Q_IGRP: bpf_error("'igrp proto' is bogus"); /* NOTREACHED */ case Q_PIM: bpf_error("'pim proto' is bogus"); /* NOTREACHED */ case Q_VRRP: bpf_error("'vrrp proto' is bogus"); /* NOTREACHED */ case Q_CARP: bpf_error("'carp proto' is bogus"); /* NOTREACHED */ -#ifdef INET6 case Q_IPV6: b0 = gen_linktype(ETHERTYPE_IPV6); #ifndef CHASE_CHAIN /* * Also check for a fragment header before the final * header. */ b2 = gen_cmp(OR_NET, 6, BPF_B, IPPROTO_FRAGMENT); b1 = gen_cmp(OR_NET, 40, BPF_B, (bpf_int32)v); gen_and(b2, b1); b2 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)v); gen_or(b2, b1); #else b1 = gen_protochain(v, Q_IPV6); #endif gen_and(b0, b1); return b1; case Q_ICMPV6: bpf_error("'icmp6 proto' is bogus"); -#endif /* INET6 */ case Q_AH: bpf_error("'ah proto' is bogus"); 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"); case Q_RADIO: bpf_error("'radio proto' is bogus"); default: abort(); /* NOTREACHED */ } /* NOTREACHED */ } struct block * gen_scode(name, q) register const char *name; struct qual q; { int proto = q.proto; int dir = q.dir; int tproto; u_char *eaddr; bpf_u_int32 mask, addr; #ifndef INET6 bpf_u_int32 **alist; #else int tproto6; struct sockaddr_in *sin4; struct sockaddr_in6 *sin6; struct addrinfo *res, *res0; struct in6_addr mask128; #endif /*INET6*/ struct block *b, *tmp; int port, real_proto; int port1, port2; switch (q.addr) { case Q_NET: addr = pcap_nametonetaddr(name); if (addr == 0) bpf_error("unknown network '%s'", name); /* Left justify network addr and calculate its network mask */ mask = 0xffffffff; while (addr && (addr & 0xff000000) == 0) { addr <<= 8; mask <<= 8; } return gen_host(addr, mask, proto, dir, q.addr); case Q_DEFAULT: case Q_HOST: if (proto == Q_LINK) { switch (linktype) { case DLT_EN10MB: case DLT_NETANALYZER: case DLT_NETANALYZER_TRANSPARENT: eaddr = pcap_ether_hostton(name); if (eaddr == NULL) bpf_error( "unknown ether host '%s'", name); 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); 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); b = gen_thostop(eaddr, dir); free(eaddr); return b; case DLT_IEEE802_11: case DLT_PRISM_HEADER: case DLT_IEEE802_11_RADIO_AVS: case DLT_IEEE802_11_RADIO: case DLT_PPI: eaddr = pcap_ether_hostton(name); if (eaddr == NULL) bpf_error( "unknown 802.11 host '%s'", name); b = gen_wlanhostop(eaddr, dir); free(eaddr); return b; case DLT_IP_OVER_FC: eaddr = pcap_ether_hostton(name); if (eaddr == NULL) bpf_error( "unknown Fibre Channel host '%s'", name); b = gen_ipfchostop(eaddr, dir); free(eaddr); return b; case DLT_SUNATM: if (!is_lane) break; /* * Check that the packet doesn't begin * with an LE Control marker. (We've * already generated a test for LANE.) */ tmp = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00); gen_not(tmp); eaddr = pcap_ether_hostton(name); if (eaddr == NULL) bpf_error( "unknown ether host '%s'", name); b = gen_ehostop(eaddr, dir); gen_and(tmp, b); free(eaddr); return b; } bpf_error("only ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel supports link-level host name"); } else if (proto == Q_DECNET) { unsigned short dn_addr = __pcap_nametodnaddr(name); /* * I don't think DECNET hosts can be multihomed, so * there is no need to build up a list of addresses */ return (gen_host(dn_addr, 0, proto, dir, q.addr)); } else { #ifndef INET6 alist = pcap_nametoaddr(name); if (alist == NULL || *alist == NULL) bpf_error("unknown host '%s'", name); tproto = proto; if (off_linktype == (u_int)-1 && tproto == Q_DEFAULT) tproto = Q_IP; b = gen_host(**alist++, 0xffffffff, tproto, dir, q.addr); while (*alist) { tmp = gen_host(**alist++, 0xffffffff, tproto, dir, q.addr); gen_or(b, tmp); b = tmp; } return b; #else memset(&mask128, 0xff, sizeof(mask128)); res0 = res = pcap_nametoaddrinfo(name); if (res == NULL) bpf_error("unknown host '%s'", name); ai = res; b = tmp = NULL; tproto = tproto6 = proto; if (off_linktype == -1 && tproto == Q_DEFAULT) { tproto = Q_IP; tproto6 = Q_IPV6; } for (res = res0; res; res = res->ai_next) { switch (res->ai_family) { case AF_INET: if (tproto == Q_IPV6) continue; sin4 = (struct sockaddr_in *) res->ai_addr; tmp = gen_host(ntohl(sin4->sin_addr.s_addr), 0xffffffff, tproto, dir, q.addr); break; case AF_INET6: if (tproto6 == Q_IP) continue; sin6 = (struct sockaddr_in6 *) res->ai_addr; tmp = gen_host6(&sin6->sin6_addr, &mask128, tproto6, dir, q.addr); break; default: continue; } if (b) gen_or(b, tmp); b = tmp; } ai = NULL; freeaddrinfo(res0); if (b == NULL) { bpf_error("unknown host '%s'%s", name, (proto == Q_DEFAULT) ? "" : " for specified address family"); } return b; #endif /*INET6*/ } case Q_PORT: 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; } 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; } if (port < 0) bpf_error("illegal port number %d < 0", port); if (port > 65535) bpf_error("illegal port number %d > 65535", port); -#ifndef INET6 - return gen_port(port, real_proto, dir); -#else b = gen_port(port, real_proto, dir); gen_or(gen_port6(port, real_proto, dir), b); return b; -#endif /* INET6 */ case Q_PORTRANGE: if (proto != Q_DEFAULT && proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP) bpf_error("illegal qualifier of 'portrange'"); if (pcap_nametoportrange(name, &port1, &port2, &real_proto) == 0) bpf_error("unknown port in range '%s'", name); if (proto == Q_UDP) { if (real_proto == IPPROTO_TCP) bpf_error("port in range '%s' is tcp", name); else if (real_proto == IPPROTO_SCTP) bpf_error("port in range '%s' is sctp", name); else /* override PROTO_UNDEF */ real_proto = IPPROTO_UDP; } if (proto == Q_TCP) { if (real_proto == IPPROTO_UDP) bpf_error("port in range '%s' is udp", name); else if (real_proto == IPPROTO_SCTP) bpf_error("port in range '%s' is sctp", name); else /* override PROTO_UNDEF */ real_proto = IPPROTO_TCP; } if (proto == Q_SCTP) { if (real_proto == IPPROTO_UDP) bpf_error("port in range '%s' is udp", name); else if (real_proto == IPPROTO_TCP) bpf_error("port in range '%s' is tcp", name); else /* override PROTO_UNDEF */ real_proto = IPPROTO_SCTP; } if (port1 < 0) bpf_error("illegal port number %d < 0", port1); if (port1 > 65535) bpf_error("illegal port number %d > 65535", port1); if (port2 < 0) bpf_error("illegal port number %d < 0", port2); if (port2 > 65535) bpf_error("illegal port number %d > 65535", port2); -#ifndef INET6 - return gen_portrange(port1, port2, real_proto, dir); -#else b = gen_portrange(port1, port2, real_proto, dir); gen_or(gen_portrange6(port1, port2, real_proto, dir), b); return b; -#endif /* INET6 */ case Q_GATEWAY: #ifndef INET6 eaddr = pcap_ether_hostton(name); if (eaddr == NULL) bpf_error("unknown ether host: %s", name); alist = pcap_nametoaddr(name); if (alist == NULL || *alist == NULL) bpf_error("unknown host '%s'", name); b = gen_gateway(eaddr, alist, proto, dir); free(eaddr); return b; #else bpf_error("'gateway' not supported in this configuration"); #endif /*INET6*/ case Q_PROTO: real_proto = lookup_proto(name, proto); if (real_proto >= 0) return gen_proto(real_proto, proto, dir); else bpf_error("unknown protocol: %s", name); case Q_PROTOCHAIN: real_proto = lookup_proto(name, proto); if (real_proto >= 0) return gen_protochain(real_proto, proto, dir); else bpf_error("unknown protocol: %s", name); case Q_UNDEF: syntax(); /* NOTREACHED */ } abort(); /* NOTREACHED */ } struct block * gen_mcode(s1, s2, masklen, q) register const char *s1, *s2; register int masklen; struct qual q; { register int nlen, mlen; bpf_u_int32 n, m; nlen = __pcap_atoin(s1, &n); /* Promote short ipaddr */ n <<= 32 - nlen; if (s2 != NULL) { mlen = __pcap_atoin(s2, &m); /* Promote short ipaddr */ m <<= 32 - mlen; if ((n & ~m) != 0) bpf_error("non-network bits set in \"%s mask %s\"", s1, s2); } else { /* Convert mask len to mask */ if (masklen > 32) bpf_error("mask length must be <= 32"); if (masklen == 0) { /* * X << 32 is not guaranteed by C to be 0; it's * undefined. */ m = 0; } else m = 0xffffffff << (32 - masklen); if ((n & ~m) != 0) bpf_error("non-network bits set in \"%s/%d\"", s1, masklen); } switch (q.addr) { case Q_NET: return gen_host(n, m, q.proto, q.dir, q.addr); default: bpf_error("Mask syntax for networks only"); /* NOTREACHED */ } /* NOTREACHED */ return NULL; } struct block * gen_ncode(s, v, q) register const char *s; bpf_u_int32 v; struct qual q; { bpf_u_int32 mask; int proto = q.proto; int dir = q.dir; register int vlen; if (s == NULL) vlen = 32; else if (q.proto == Q_DECNET) vlen = __pcap_atodn(s, &v); else vlen = __pcap_atoin(s, &v); switch (q.addr) { case Q_DEFAULT: case Q_HOST: case Q_NET: if (proto == Q_DECNET) return gen_host(v, 0, proto, dir, q.addr); else if (proto == Q_LINK) { bpf_error("illegal link layer address"); } else { mask = 0xffffffff; if (s == NULL && q.addr == Q_NET) { /* Promote short net number */ while (v && (v & 0xff000000) == 0) { v <<= 8; mask <<= 8; } } else { /* Promote short ipaddr */ v <<= 32 - vlen; mask <<= 32 - vlen; } return gen_host(v, mask, proto, dir, q.addr); } case Q_PORT: if (proto == Q_UDP) 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 bpf_error("illegal qualifier of 'port'"); if (v > 65535) bpf_error("illegal port number %u > 65535", v); -#ifndef INET6 - return gen_port((int)v, proto, dir); -#else { struct block *b; b = gen_port((int)v, proto, dir); gen_or(gen_port6((int)v, proto, dir), b); return b; } -#endif /* INET6 */ case Q_PORTRANGE: if (proto == Q_UDP) 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 bpf_error("illegal qualifier of 'portrange'"); if (v > 65535) bpf_error("illegal port number %u > 65535", v); -#ifndef INET6 - return gen_portrange((int)v, (int)v, proto, dir); -#else { struct block *b; b = gen_portrange((int)v, (int)v, proto, dir); gen_or(gen_portrange6((int)v, (int)v, proto, dir), b); return b; } -#endif /* INET6 */ case Q_GATEWAY: bpf_error("'gateway' requires a name"); /* NOTREACHED */ case Q_PROTO: return gen_proto((int)v, proto, dir); case Q_PROTOCHAIN: return gen_protochain((int)v, proto, dir); case Q_UNDEF: syntax(); /* NOTREACHED */ default: abort(); /* NOTREACHED */ } /* NOTREACHED */ } #ifdef INET6 struct block * gen_mcode6(s1, s2, masklen, q) register const char *s1, *s2; register int masklen; struct qual q; { struct addrinfo *res; struct in6_addr *addr; struct in6_addr mask; struct block *b; u_int32_t *a, *m; if (s2) bpf_error("no mask %s supported", s2); res = pcap_nametoaddrinfo(s1); if (!res) bpf_error("invalid ip6 address %s", s1); ai = res; if (res->ai_next) bpf_error("%s resolved to multiple address", s1); addr = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr; 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] = (0xff << (8 - masklen % 8)) & 0xff; } a = (u_int32_t *)addr; m = (u_int32_t *)&mask; if ((a[0] & ~m[0]) || (a[1] & ~m[1]) || (a[2] & ~m[2]) || (a[3] & ~m[3])) { bpf_error("non-network bits set in \"%s/%d\"", s1, masklen); } switch (q.addr) { case Q_DEFAULT: case Q_HOST: if (masklen != 128) bpf_error("Mask syntax for networks only"); /* FALLTHROUGH */ case Q_NET: b = gen_host6(addr, &mask, q.proto, q.dir, q.addr); ai = NULL; freeaddrinfo(res); return b; default: bpf_error("invalid qualifier against IPv6 address"); /* NOTREACHED */ } return NULL; } #endif /*INET6*/ struct block * gen_ecode(eaddr, q) register const u_char *eaddr; struct qual q; { struct block *b, *tmp; if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) { switch (linktype) { case DLT_EN10MB: case DLT_NETANALYZER: case DLT_NETANALYZER_TRANSPARENT: return gen_ehostop(eaddr, (int)q.dir); case DLT_FDDI: return gen_fhostop(eaddr, (int)q.dir); case DLT_IEEE802: return gen_thostop(eaddr, (int)q.dir); case DLT_IEEE802_11: case DLT_PRISM_HEADER: case DLT_IEEE802_11_RADIO_AVS: case DLT_IEEE802_11_RADIO: case DLT_PPI: return gen_wlanhostop(eaddr, (int)q.dir); case DLT_SUNATM: if (is_lane) { /* * Check that the packet doesn't begin with an * LE Control marker. (We've already generated * a test for LANE.) */ tmp = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00); gen_not(tmp); /* * Now check the MAC address. */ b = gen_ehostop(eaddr, (int)q.dir); gen_and(tmp, b); return b; } break; case DLT_IP_OVER_FC: return gen_ipfchostop(eaddr, (int)q.dir); default: bpf_error("ethernet addresses supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel"); break; } } bpf_error("ethernet address used in non-ether expression"); /* NOTREACHED */ return NULL; } void sappend(s0, s1) struct slist *s0, *s1; { /* * This is definitely not the best way to do this, but the * lists will rarely get long. */ while (s0->next) s0 = s0->next; s0->next = s1; } static struct slist * xfer_to_x(a) struct arth *a; { struct slist *s; s = new_stmt(BPF_LDX|BPF_MEM); s->s.k = a->regno; return s; } static struct slist * xfer_to_a(a) struct arth *a; { struct slist *s; s = new_stmt(BPF_LD|BPF_MEM); s->s.k = a->regno; return s; } /* * Modify "index" to use the value stored into its register as an * offset relative to the beginning of the header for the protocol * "proto", and allocate a register and put an item "size" bytes long * (1, 2, or 4) at that offset into that register, making it the register * for "index". */ struct arth * gen_load(proto, inst, size) int proto; struct arth *inst; int size; { struct slist *s, *tmp; struct block *b; int regno = alloc_reg(); free_reg(inst->regno); switch (size) { default: bpf_error("data size must be 1, 2, or 4"); case 1: size = BPF_B; break; case 2: size = BPF_H; break; case 4: size = BPF_W; break; } switch (proto) { default: bpf_error("unsupported index operation"); case Q_RADIO: /* * The offset is relative to the beginning of the packet * data, if we have a radio header. (If we don't, this * is an error.) */ if (linktype != DLT_IEEE802_11_RADIO_AVS && linktype != DLT_IEEE802_11_RADIO && linktype != DLT_PRISM_HEADER) bpf_error("radio information not present in capture"); /* * Load into the X register the offset computed into the * register specified by "index". */ s = xfer_to_x(inst); /* * Load the item at that offset. */ tmp = new_stmt(BPF_LD|BPF_IND|size); sappend(s, tmp); sappend(inst->s, s); break; case Q_LINK: /* * The offset is relative to the beginning of * the link-layer header. * * XXX - what about ATM LANE? Should the index be * relative to the beginning of the AAL5 frame, so * that 0 refers to the beginning of the LE Control * field, or relative to the beginning of the LAN * frame, so that 0 refers, for Ethernet LANE, to * the beginning of the destination address? */ s = gen_llprefixlen(); /* * If "s" is non-null, it has code to arrange that the * X register contains the length of the prefix preceding * the link-layer header. Add to it the offset computed * into the register specified by "index", and move that * into the X register. Otherwise, just load into the X * register the offset computed into the register specified * by "index". */ if (s != NULL) { sappend(s, xfer_to_a(inst)); sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X)); sappend(s, new_stmt(BPF_MISC|BPF_TAX)); } else s = xfer_to_x(inst); /* * Load the item at the sum of the offset we've put in the * X register and the offset of the start of the link * layer header (which is 0 if the radio header is * variable-length; that header length is what we put * into the X register and then added to the index). */ tmp = new_stmt(BPF_LD|BPF_IND|size); tmp->s.k = off_ll; sappend(s, tmp); sappend(inst->s, s); break; case Q_IP: case Q_ARP: case Q_RARP: case Q_ATALK: case Q_DECNET: case Q_SCA: case Q_LAT: case Q_MOPRC: case Q_MOPDL: -#ifdef INET6 case Q_IPV6: -#endif /* * The offset is relative to the beginning of * the network-layer header. * XXX - are there any cases where we want * off_nl_nosnap? */ s = gen_off_macpl(); /* * If "s" is non-null, it has code to arrange that the * X register contains the offset of the MAC-layer * payload. Add to it the offset computed into the * register specified by "index", and move that into * the X register. Otherwise, just load into the X * register the offset computed into the register specified * by "index". */ if (s != NULL) { sappend(s, xfer_to_a(inst)); sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X)); sappend(s, new_stmt(BPF_MISC|BPF_TAX)); } else s = xfer_to_x(inst); /* * Load the item at the sum of the offset we've put in the * X register, the offset of the start of the network * layer header from the beginning of the MAC-layer * payload, and the purported offset of the start of the * MAC-layer payload (which might be 0 if there's a * variable-length prefix before the link-layer header * or the link-layer header itself is variable-length; * the variable-length offset of the start of the * MAC-layer payload is what we put into the X register * and then added to the index). */ tmp = new_stmt(BPF_LD|BPF_IND|size); tmp->s.k = off_macpl + off_nl; sappend(s, tmp); sappend(inst->s, s); /* * Do the computation only if the packet contains * the protocol in question. */ b = gen_proto_abbrev(proto); if (inst->b) gen_and(inst->b, b); inst->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: case Q_CARP: /* * The offset is relative to the beginning of * the transport-layer header. * * Load the X register with the length of the IPv4 header * (plus the offset of the link-layer header, if it's * a variable-length header), in bytes. * * XXX - are there any cases where we want * off_nl_nosnap? * XXX - we should, if we're built with * IPv6 support, generate code to load either * IPv4, IPv6, or both, as appropriate. */ s = gen_loadx_iphdrlen(); /* * The X register now contains the sum of the length * of any variable-length header preceding the link-layer * header, any variable-length link-layer header, and the * length of the network-layer header. * * Load into the A register the offset relative to * the beginning of the transport layer header, * add the X register to that, move that to the * X register, and load with an offset from the * X register equal to the offset of the network * layer header relative to the beginning of * the MAC-layer payload plus the fixed-length * portion of the offset of the MAC-layer payload * from the beginning of the raw packet data. */ sappend(s, xfer_to_a(inst)); sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X)); sappend(s, new_stmt(BPF_MISC|BPF_TAX)); sappend(s, tmp = new_stmt(BPF_LD|BPF_IND|size)); tmp->s.k = off_macpl + off_nl; sappend(inst->s, s); /* * Do the computation only if the packet contains * the protocol in question - which is true only * if this is an IP datagram and is the first or * only fragment of that datagram. */ gen_and(gen_proto_abbrev(proto), b = gen_ipfrag()); if (inst->b) gen_and(inst->b, b); -#ifdef INET6 gen_and(gen_proto_abbrev(Q_IP), b); -#endif inst->b = b; break; -#ifdef INET6 case Q_ICMPV6: bpf_error("IPv6 upper-layer protocol is not supported by proto[x]"); /*NOTREACHED*/ -#endif } inst->regno = regno; s = new_stmt(BPF_ST); s->s.k = regno; sappend(inst->s, s); return inst; } struct block * gen_relation(code, a0, a1, reversed) int code; struct arth *a0, *a1; int reversed; { struct slist *s0, *s1, *s2; struct block *b, *tmp; s0 = xfer_to_x(a1); s1 = xfer_to_a(a0); if (code == BPF_JEQ) { s2 = new_stmt(BPF_ALU|BPF_SUB|BPF_X); b = new_block(JMP(code)); sappend(s1, s2); } else b = new_block(BPF_JMP|code|BPF_X); if (reversed) gen_not(b); sappend(s0, s1); sappend(a1->s, s0); sappend(a0->s, a1->s); b->stmts = a0->s; free_reg(a0->regno); free_reg(a1->regno); /* 'and' together protocol checks */ if (a0->b) { if (a1->b) { gen_and(a0->b, tmp = a1->b); } else tmp = a0->b; } else tmp = a1->b; if (tmp) gen_and(tmp, b); return b; } struct arth * gen_loadlen() { int regno = alloc_reg(); struct arth *a = (struct arth *)newchunk(sizeof(*a)); struct slist *s; s = new_stmt(BPF_LD|BPF_LEN); s->next = new_stmt(BPF_ST); s->next->s.k = regno; a->s = s; a->regno = regno; return a; } struct arth * gen_loadi(val) int val; { struct arth *a; struct slist *s; int reg; a = (struct arth *)newchunk(sizeof(*a)); reg = alloc_reg(); s = new_stmt(BPF_LD|BPF_IMM); s->s.k = val; s->next = new_stmt(BPF_ST); s->next->s.k = reg; a->s = s; a->regno = reg; return a; } struct arth * gen_neg(a) struct arth *a; { struct slist *s; s = xfer_to_a(a); sappend(a->s, s); s = new_stmt(BPF_ALU|BPF_NEG); s->s.k = 0; sappend(a->s, s); s = new_stmt(BPF_ST); s->s.k = a->regno; sappend(a->s, s); return a; } struct arth * gen_arth(code, a0, a1) int code; struct arth *a0, *a1; { struct slist *s0, *s1, *s2; s0 = xfer_to_x(a1); s1 = xfer_to_a(a0); s2 = new_stmt(BPF_ALU|BPF_X|code); sappend(s1, s2); sappend(s0, s1); sappend(a1->s, s0); sappend(a0->s, a1->s); free_reg(a0->regno); free_reg(a1->regno); s0 = new_stmt(BPF_ST); a0->regno = s0->s.k = alloc_reg(); sappend(a0->s, s0); return a0; } /* * Here we handle simple allocation of the scratch registers. * If too many registers are alloc'd, the allocator punts. */ static int regused[BPF_MEMWORDS]; static int curreg; /* * Initialize the table of used registers and the current register. */ static void init_regs() { curreg = 0; memset(regused, 0, sizeof regused); } /* * Return the next free register. */ static int alloc_reg() { int n = BPF_MEMWORDS; while (--n >= 0) { if (regused[curreg]) curreg = (curreg + 1) % BPF_MEMWORDS; else { regused[curreg] = 1; return curreg; } } bpf_error("too many registers needed to evaluate expression"); /* NOTREACHED */ return 0; } /* * Return a register to the table so it can * be used later. */ static void free_reg(n) int n; { regused[n] = 0; } static struct block * gen_len(jmp, n) int jmp, n; { struct slist *s; struct block *b; s = new_stmt(BPF_LD|BPF_LEN); b = new_block(JMP(jmp)); b->stmts = s; b->s.k = n; return b; } struct block * gen_greater(n) int n; { return gen_len(BPF_JGE, n); } /* * Actually, this is less than or equal. */ struct block * gen_less(n) int n; { struct block *b; b = gen_len(BPF_JGT, n); gen_not(b); return b; } /* * This is for "byte {idx} {op} {val}"; "idx" is treated as relative to * the beginning of the link-layer header. * XXX - that means you can't test values in the radiotap header, but * as that header is difficult if not impossible to parse generally * without a loop, that might not be a severe problem. A new keyword * "radio" could be added for that, although what you'd really want * would be a way of testing particular radio header values, which * would generate code appropriate to the radio header in question. */ struct block * gen_byteop(op, idx, val) int op, idx, val; { struct block *b; struct slist *s; switch (op) { default: abort(); case '=': return gen_cmp(OR_LINK, (u_int)idx, BPF_B, (bpf_int32)val); case '<': b = gen_cmp_lt(OR_LINK, (u_int)idx, BPF_B, (bpf_int32)val); return b; case '>': b = gen_cmp_gt(OR_LINK, (u_int)idx, BPF_B, (bpf_int32)val); return b; case '|': s = new_stmt(BPF_ALU|BPF_OR|BPF_K); break; case '&': s = new_stmt(BPF_ALU|BPF_AND|BPF_K); break; } s->s.k = val; b = new_block(JMP(BPF_JEQ)); b->stmts = s; gen_not(b); return b; } static u_char abroadcast[] = { 0x0 }; struct block * gen_broadcast(proto) int proto; { bpf_u_int32 hostmask; struct block *b0, *b1, *b2; static u_char ebroadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; switch (proto) { case Q_DEFAULT: case Q_LINK: switch (linktype) { case DLT_ARCNET: case DLT_ARCNET_LINUX: return gen_ahostop(abroadcast, Q_DST); case DLT_EN10MB: case DLT_NETANALYZER: case DLT_NETANALYZER_TRANSPARENT: return gen_ehostop(ebroadcast, Q_DST); case DLT_FDDI: return gen_fhostop(ebroadcast, Q_DST); case DLT_IEEE802: return gen_thostop(ebroadcast, Q_DST); case DLT_IEEE802_11: case DLT_PRISM_HEADER: case DLT_IEEE802_11_RADIO_AVS: case DLT_IEEE802_11_RADIO: case DLT_PPI: return gen_wlanhostop(ebroadcast, Q_DST); case DLT_IP_OVER_FC: return gen_ipfchostop(ebroadcast, Q_DST); case DLT_SUNATM: if (is_lane) { /* * Check that the packet doesn't begin with an * LE Control marker. (We've already generated * a test for LANE.) */ b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00); gen_not(b1); /* * Now check the MAC address. */ b0 = gen_ehostop(ebroadcast, Q_DST); gen_and(b1, b0); return b0; } break; default: bpf_error("not a broadcast link"); } break; case Q_IP: /* * We treat a netmask of PCAP_NETMASK_UNKNOWN (0xffffffff) * as an indication that we don't know the netmask, and fail * in that case. */ if (netmask == PCAP_NETMASK_UNKNOWN) bpf_error("netmask not known, so 'ip broadcast' not supported"); b0 = gen_linktype(ETHERTYPE_IP); hostmask = ~netmask; b1 = gen_mcmp(OR_NET, 16, BPF_W, (bpf_int32)0, hostmask); b2 = gen_mcmp(OR_NET, 16, BPF_W, (bpf_int32)(~0 & hostmask), hostmask); gen_or(b1, b2); gen_and(b0, b2); return b2; } bpf_error("only link-layer/IP broadcast filters supported"); /* NOTREACHED */ return NULL; } /* * Generate code to test the low-order bit of a MAC address (that's * the bottom bit of the *first* byte). */ static struct block * gen_mac_multicast(offset) int offset; { register struct block *b0; register struct slist *s; /* link[offset] & 1 != 0 */ s = gen_load_a(OR_LINK, offset, BPF_B); b0 = new_block(JMP(BPF_JSET)); b0->s.k = 1; b0->stmts = s; return b0; } struct block * gen_multicast(proto) int proto; { register struct block *b0, *b1, *b2; register struct slist *s; switch (proto) { case Q_DEFAULT: case Q_LINK: switch (linktype) { case DLT_ARCNET: case DLT_ARCNET_LINUX: /* all ARCnet multicasts use the same address */ return gen_ahostop(abroadcast, Q_DST); case DLT_EN10MB: case DLT_NETANALYZER: case DLT_NETANALYZER_TRANSPARENT: /* ether[0] & 1 != 0 */ return gen_mac_multicast(0); case DLT_FDDI: /* * XXX TEST THIS: MIGHT NOT PORT PROPERLY XXX * * XXX - was that referring to bit-order issues? */ /* fddi[1] & 1 != 0 */ return gen_mac_multicast(1); case DLT_IEEE802: /* tr[2] & 1 != 0 */ return gen_mac_multicast(2); case DLT_IEEE802_11: case DLT_PRISM_HEADER: case DLT_IEEE802_11_RADIO_AVS: case DLT_IEEE802_11_RADIO: case DLT_PPI: /* * Oh, yuk. * * For control frames, there is no DA. * * For management frames, DA is at an * offset of 4 from the beginning of * the packet. * * For data frames, DA is at an offset * of 4 from the beginning of the packet * if To DS is clear and at an offset of * 16 from the beginning of the packet * if To DS is set. */ /* * Generate the tests to be done for data frames. * * First, check for To DS set, i.e. "link[1] & 0x01". */ s = gen_load_a(OR_LINK, 1, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x01; /* To DS */ b1->stmts = s; /* * If To DS is set, the DA is at 16. */ b0 = gen_mac_multicast(16); gen_and(b1, b0); /* * Now, check for To DS not set, i.e. check * "!(link[1] & 0x01)". */ s = gen_load_a(OR_LINK, 1, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x01; /* To DS */ b2->stmts = s; gen_not(b2); /* * If To DS is not set, the DA is at 4. */ b1 = gen_mac_multicast(4); gen_and(b2, b1); /* * Now OR together the last two checks. That gives * the complete set of checks for data frames. */ gen_or(b1, b0); /* * Now check for a data frame. * I.e, check "link[0] & 0x08". */ s = gen_load_a(OR_LINK, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x08; b1->stmts = s; /* * AND that with the checks done for data frames. */ gen_and(b1, b0); /* * If the high-order bit of the type value is 0, this * is a management frame. * I.e, check "!(link[0] & 0x08)". */ s = gen_load_a(OR_LINK, 0, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x08; b2->stmts = s; gen_not(b2); /* * For management frames, the DA is at 4. */ b1 = gen_mac_multicast(4); gen_and(b2, b1); /* * OR that with the checks done for data frames. * That gives the checks done for management and * data frames. */ gen_or(b1, b0); /* * If the low-order bit of the type value is 1, * this is either a control frame or a frame * with a reserved type, and thus not a * frame with an SA. * * I.e., check "!(link[0] & 0x04)". */ s = gen_load_a(OR_LINK, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x04; b1->stmts = s; gen_not(b1); /* * AND that with the checks for data and management * frames. */ gen_and(b1, b0); return b0; case DLT_IP_OVER_FC: b0 = gen_mac_multicast(2); return b0; case DLT_SUNATM: if (is_lane) { /* * Check that the packet doesn't begin with an * LE Control marker. (We've already generated * a test for LANE.) */ b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00); gen_not(b1); /* ether[off_mac] & 1 != 0 */ b0 = gen_mac_multicast(off_mac); gen_and(b1, b0); return b0; } break; default: break; } /* Link not known to support multicasts */ break; case Q_IP: b0 = gen_linktype(ETHERTYPE_IP); b1 = gen_cmp_ge(OR_NET, 16, BPF_B, (bpf_int32)224); gen_and(b0, b1); return b1; -#ifdef INET6 case Q_IPV6: b0 = gen_linktype(ETHERTYPE_IPV6); b1 = gen_cmp(OR_NET, 24, BPF_B, (bpf_int32)255); gen_and(b0, b1); return b1; -#endif /* INET6 */ } bpf_error("link-layer multicast filters supported only on ethernet/FDDI/token ring/ARCNET/802.11/ATM LANE/Fibre Channel"); /* NOTREACHED */ return NULL; } /* * Filter on inbound (dir == 0) or outbound (dir == 1) traffic. * Outbound traffic is sent by this machine, while inbound traffic is * sent by a remote machine (and may include packets destined for a * unicast or multicast link-layer address we are not subscribing to). * These are the same definitions implemented by pcap_setdirection(). * Capturing only unicast traffic destined for this host is probably * better accomplished using a higher-layer filter. */ struct block * gen_inbound(dir) int dir; { register struct block *b0; /* * Only some data link types support inbound/outbound qualifiers. */ switch (linktype) { case DLT_SLIP: b0 = gen_relation(BPF_JEQ, gen_load(Q_LINK, gen_loadi(0), 1), gen_loadi(0), dir); break; case DLT_IPNET: if (dir) { /* match outgoing packets */ b0 = gen_cmp(OR_LINK, 2, BPF_H, IPNET_OUTBOUND); } else { /* match incoming packets */ b0 = gen_cmp(OR_LINK, 2, BPF_H, IPNET_INBOUND); } break; case DLT_LINUX_SLL: /* match outgoing packets */ b0 = gen_cmp(OR_LINK, 0, BPF_H, LINUX_SLL_OUTGOING); if (!dir) { /* to filter on inbound traffic, invert the match */ gen_not(b0); } break; #ifdef HAVE_NET_PFVAR_H case DLT_PFLOG: b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, dir), BPF_B, (bpf_int32)((dir == 0) ? PF_IN : PF_OUT)); break; #endif case DLT_PPP_PPPD: if (dir) { /* match outgoing packets */ b0 = gen_cmp(OR_LINK, 0, BPF_B, PPP_PPPD_OUT); } else { /* match incoming packets */ b0 = gen_cmp(OR_LINK, 0, BPF_B, PPP_PPPD_IN); } break; case DLT_JUNIPER_MFR: case DLT_JUNIPER_MLFR: case DLT_JUNIPER_MLPPP: case DLT_JUNIPER_ATM1: case DLT_JUNIPER_ATM2: case DLT_JUNIPER_PPPOE: case DLT_JUNIPER_PPPOE_ATM: case DLT_JUNIPER_GGSN: case DLT_JUNIPER_ES: case DLT_JUNIPER_MONITOR: case DLT_JUNIPER_SERVICES: case DLT_JUNIPER_ETHER: case DLT_JUNIPER_PPP: case DLT_JUNIPER_FRELAY: case DLT_JUNIPER_CHDLC: case DLT_JUNIPER_VP: case DLT_JUNIPER_ST: case DLT_JUNIPER_ISM: case DLT_JUNIPER_VS: case DLT_JUNIPER_SRX_E2E: case DLT_JUNIPER_FIBRECHANNEL: case DLT_JUNIPER_ATM_CEMIC: /* juniper flags (including direction) are stored * the byte after the 3-byte magic number */ if (dir) { /* match outgoing packets */ b0 = gen_mcmp(OR_LINK, 3, BPF_B, 0, 0x01); } else { /* match incoming packets */ b0 = gen_mcmp(OR_LINK, 3, BPF_B, 1, 0x01); } break; default: /* * If we have packet meta-data indicating a direction, * check it, otherwise give up as this link-layer type * has nothing in the packet data. */ #if defined(PF_PACKET) && defined(SO_ATTACH_FILTER) /* * We infer that this is Linux with PF_PACKET support. * If this is a *live* capture, we can look at * special meta-data in the filter expression; * if it's a savefile, we can't. */ if (bpf_pcap->sf.rfile != NULL) { /* We have a FILE *, so this is a savefile */ bpf_error("inbound/outbound not supported on linktype %d when reading savefiles", linktype); b0 = NULL; /* NOTREACHED */ } /* match outgoing packets */ b0 = gen_cmp(OR_LINK, SKF_AD_OFF + SKF_AD_PKTTYPE, BPF_H, PACKET_OUTGOING); if (!dir) { /* to filter on inbound traffic, invert the match */ gen_not(b0); } #else /* defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */ bpf_error("inbound/outbound not supported on linktype %d", linktype); b0 = NULL; /* NOTREACHED */ #endif /* defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */ } return (b0); } #ifdef HAVE_NET_PFVAR_H /* PF firewall log matched interface */ struct block * gen_pf_ifname(const char *ifname) { struct block *b0; u_int len, off; if (linktype != DLT_PFLOG) { bpf_error("ifname supported only on PF linktype"); /* NOTREACHED */ } len = sizeof(((struct pfloghdr *)0)->ifname); off = offsetof(struct pfloghdr, ifname); if (strlen(ifname) >= len) { bpf_error("ifname interface names can only be %d characters", len-1); /* NOTREACHED */ } b0 = gen_bcmp(OR_LINK, off, strlen(ifname), (const u_char *)ifname); return (b0); } /* PF firewall log ruleset name */ struct block * gen_pf_ruleset(char *ruleset) { struct block *b0; if (linktype != DLT_PFLOG) { bpf_error("ruleset supported only on PF linktype"); /* NOTREACHED */ } if (strlen(ruleset) >= sizeof(((struct pfloghdr *)0)->ruleset)) { bpf_error("ruleset names can only be %ld characters", (long)(sizeof(((struct pfloghdr *)0)->ruleset) - 1)); /* NOTREACHED */ } b0 = gen_bcmp(OR_LINK, offsetof(struct pfloghdr, ruleset), strlen(ruleset), (const u_char *)ruleset); return (b0); } /* PF firewall log rule number */ struct block * gen_pf_rnr(int rnr) { struct block *b0; if (linktype != DLT_PFLOG) { bpf_error("rnr supported only on PF linktype"); /* NOTREACHED */ } b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, rulenr), BPF_W, (bpf_int32)rnr); return (b0); } /* PF firewall log sub-rule number */ struct block * gen_pf_srnr(int srnr) { struct block *b0; if (linktype != DLT_PFLOG) { bpf_error("srnr supported only on PF linktype"); /* NOTREACHED */ } b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, subrulenr), BPF_W, (bpf_int32)srnr); return (b0); } /* PF firewall log reason code */ struct block * gen_pf_reason(int reason) { struct block *b0; if (linktype != DLT_PFLOG) { bpf_error("reason supported only on PF linktype"); /* NOTREACHED */ } b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, reason), BPF_B, (bpf_int32)reason); return (b0); } /* PF firewall log action */ struct block * gen_pf_action(int action) { struct block *b0; if (linktype != DLT_PFLOG) { bpf_error("action supported only on PF linktype"); /* NOTREACHED */ } b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, action), BPF_B, (bpf_int32)action); return (b0); } #else /* !HAVE_NET_PFVAR_H */ struct block * gen_pf_ifname(const char *ifname) { bpf_error("libpcap was compiled without pf support"); /* NOTREACHED */ return (NULL); } struct block * gen_pf_ruleset(char *ruleset) { bpf_error("libpcap was compiled on a machine without pf support"); /* NOTREACHED */ return (NULL); } struct block * gen_pf_rnr(int rnr) { bpf_error("libpcap was compiled on a machine without pf support"); /* NOTREACHED */ return (NULL); } struct block * gen_pf_srnr(int srnr) { bpf_error("libpcap was compiled on a machine without pf support"); /* NOTREACHED */ return (NULL); } struct block * gen_pf_reason(int reason) { bpf_error("libpcap was compiled on a machine without pf support"); /* NOTREACHED */ return (NULL); } struct block * gen_pf_action(int action) { bpf_error("libpcap was compiled on a machine without pf support"); /* NOTREACHED */ return (NULL); } #endif /* HAVE_NET_PFVAR_H */ /* IEEE 802.11 wireless header */ struct block * gen_p80211_type(int type, int mask) { struct block *b0; switch (linktype) { case DLT_IEEE802_11: case DLT_PRISM_HEADER: case DLT_IEEE802_11_RADIO_AVS: case DLT_IEEE802_11_RADIO: b0 = gen_mcmp(OR_LINK, 0, BPF_B, (bpf_int32)type, (bpf_int32)mask); break; default: bpf_error("802.11 link-layer types supported only on 802.11"); /* NOTREACHED */ } return (b0); } struct block * gen_p80211_fcdir(int fcdir) { struct block *b0; switch (linktype) { case DLT_IEEE802_11: case DLT_PRISM_HEADER: case DLT_IEEE802_11_RADIO_AVS: case DLT_IEEE802_11_RADIO: break; default: bpf_error("frame direction supported only with 802.11 headers"); /* NOTREACHED */ } b0 = gen_mcmp(OR_LINK, 1, BPF_B, (bpf_int32)fcdir, (bpf_u_int32)IEEE80211_FC1_DIR_MASK); return (b0); } struct block * gen_acode(eaddr, q) register const u_char *eaddr; struct qual q; { switch (linktype) { case DLT_ARCNET: case DLT_ARCNET_LINUX: if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) return (gen_ahostop(eaddr, (int)q.dir)); else { bpf_error("ARCnet address used in non-arc expression"); /* NOTREACHED */ } break; default: bpf_error("aid supported only on ARCnet"); /* NOTREACHED */ } bpf_error("ARCnet address used in non-arc expression"); /* NOTREACHED */ return NULL; } 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(OR_LINK, 0, 1, eaddr); case Q_DST: return gen_bcmp(OR_LINK, 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; case Q_ADDR1: bpf_error("'addr1' is only supported on 802.11"); break; case Q_ADDR2: bpf_error("'addr2' is only supported on 802.11"); break; case Q_ADDR3: bpf_error("'addr3' is only supported on 802.11"); break; case Q_ADDR4: bpf_error("'addr4' is only supported on 802.11"); break; case Q_RA: bpf_error("'ra' is only supported on 802.11"); break; case Q_TA: bpf_error("'ta' is only supported on 802.11"); break; } abort(); /* NOTREACHED */ } /* * support IEEE 802.1Q VLAN trunk over ethernet */ struct block * gen_vlan(vlan_num) int vlan_num; { struct block *b0, *b1; /* can't check for VLAN-encapsulated packets inside MPLS */ if (label_stack_depth > 0) bpf_error("no VLAN match after MPLS"); /* * Check for a VLAN packet, and then change the offsets to point * to the type and data fields within the VLAN packet. Just * increment the offsets, so that we can support a hierarchy, e.g. * "vlan 300 && vlan 200" to capture VLAN 200 encapsulated within * VLAN 100. * * XXX - this is a bit of a kludge. If we were to split the * compiler into a parser that parses an expression and * generates an expression tree, and a code generator that * takes an expression tree (which could come from our * parser or from some other parser) and generates BPF code, * we could perhaps make the offsets parameters of routines * and, in the handler for an "AND" node, pass to subnodes * other than the VLAN node the adjusted offsets. * * This would mean that "vlan" would, instead of changing the * behavior of *all* tests after it, change only the behavior * of tests ANDed with it. That would change the documented * semantics of "vlan", which might break some expressions. * However, it would mean that "(vlan and ip) or ip" would check * both for VLAN-encapsulated IP and IP-over-Ethernet, rather than * checking only for VLAN-encapsulated IP, so that could still * be considered worth doing; it wouldn't break expressions * that are of the form "vlan and ..." or "vlan N and ...", * which I suspect are the most common expressions involving * "vlan". "vlan or ..." doesn't necessarily do what the user * would really want, now, as all the "or ..." tests would * be done assuming a VLAN, even though the "or" could be viewed * as meaning "or, if this isn't a VLAN packet...". */ orig_nl = off_nl; switch (linktype) { case DLT_EN10MB: case DLT_NETANALYZER: case DLT_NETANALYZER_TRANSPARENT: /* check for VLAN, including QinQ */ b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)ETHERTYPE_8021Q); b1 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)ETHERTYPE_8021QINQ); gen_or(b0,b1); b0 = b1; /* If a specific VLAN is requested, check VLAN id */ if (vlan_num >= 0) { b1 = gen_mcmp(OR_MACPL, 0, BPF_H, (bpf_int32)vlan_num, 0x0fff); gen_and(b0, b1); b0 = b1; } off_macpl += 4; off_linktype += 4; #if 0 off_nl_nosnap += 4; off_nl += 4; #endif break; default: bpf_error("no VLAN support for data link type %d", linktype); /*NOTREACHED*/ } return (b0); } /* * support for MPLS */ struct block * gen_mpls(label_num) int label_num; { struct block *b0,*b1; /* * Change the offsets to point to the type and data fields within * the MPLS packet. Just increment the offsets, so that we * can support a hierarchy, e.g. "mpls 100000 && mpls 1024" to * capture packets with an outer label of 100000 and an inner * label of 1024. * * XXX - this is a bit of a kludge. See comments in gen_vlan(). */ orig_nl = off_nl; if (label_stack_depth > 0) { /* just match the bottom-of-stack bit clear */ b0 = gen_mcmp(OR_MACPL, orig_nl-2, BPF_B, 0, 0x01); } else { /* * Indicate that we're checking MPLS-encapsulated headers, * to make sure higher level code generators don't try to * match against IP-related protocols such as Q_ARP, Q_RARP * etc. */ switch (linktype) { case DLT_C_HDLC: /* fall through */ case DLT_EN10MB: case DLT_NETANALYZER: case DLT_NETANALYZER_TRANSPARENT: b0 = gen_linktype(ETHERTYPE_MPLS); break; case DLT_PPP: b0 = gen_linktype(PPP_MPLS_UCAST); break; /* FIXME add other DLT_s ... * for Frame-Relay/and ATM this may get messy due to SNAP headers * leave it for now */ default: bpf_error("no MPLS support for data link type %d", linktype); b0 = NULL; /*NOTREACHED*/ break; } } /* If a specific MPLS label is requested, check it */ if (label_num >= 0) { label_num = label_num << 12; /* label is shifted 12 bits on the wire */ b1 = gen_mcmp(OR_MACPL, orig_nl, BPF_W, (bpf_int32)label_num, 0xfffff000); /* only compare the first 20 bits */ gen_and(b0, b1); b0 = b1; } off_nl_nosnap += 4; off_nl += 4; label_stack_depth++; return (b0); } /* * Support PPPOE discovery and session. */ struct block * gen_pppoed() { /* check for PPPoE discovery */ return gen_linktype((bpf_int32)ETHERTYPE_PPPOED); } struct block * gen_pppoes() { struct block *b0; /* * Test against the PPPoE session link-layer type. */ b0 = gen_linktype((bpf_int32)ETHERTYPE_PPPOES); /* * Change the offsets to point to the type and data fields within * the PPP packet, and note that this is PPPoE rather than * raw PPP. * * XXX - this is a bit of a kludge. If we were to split the * compiler into a parser that parses an expression and * generates an expression tree, and a code generator that * takes an expression tree (which could come from our * parser or from some other parser) and generates BPF code, * we could perhaps make the offsets parameters of routines * and, in the handler for an "AND" node, pass to subnodes * other than the PPPoE node the adjusted offsets. * * This would mean that "pppoes" would, instead of changing the * behavior of *all* tests after it, change only the behavior * of tests ANDed with it. That would change the documented * semantics of "pppoes", which might break some expressions. * However, it would mean that "(pppoes and ip) or ip" would check * both for VLAN-encapsulated IP and IP-over-Ethernet, rather than * checking only for VLAN-encapsulated IP, so that could still * be considered worth doing; it wouldn't break expressions * that are of the form "pppoes and ..." which I suspect are the * most common expressions involving "pppoes". "pppoes or ..." * doesn't necessarily do what the user would really want, now, * as all the "or ..." tests would be done assuming PPPoE, even * though the "or" could be viewed as meaning "or, if this isn't * a PPPoE packet...". */ orig_linktype = off_linktype; /* save original values */ orig_nl = off_nl; is_pppoes = 1; /* * The "network-layer" protocol is PPPoE, which has a 6-byte * PPPoE header, followed by a PPP packet. * * There is no HDLC encapsulation for the PPP packet (it's * encapsulated in PPPoES instead), so the link-layer type * starts at the first byte of the PPP packet. For PPPoE, * that offset is relative to the beginning of the total * link-layer payload, including any 802.2 LLC header, so * it's 6 bytes past off_nl. */ off_linktype = off_nl + 6; /* * The network-layer offsets are relative to the beginning * of the MAC-layer payload; that's past the 6-byte * PPPoE header and the 2-byte PPP header. */ off_nl = 6+2; off_nl_nosnap = 6+2; return b0; } struct block * gen_atmfield_code(atmfield, jvalue, jtype, reverse) int atmfield; bpf_int32 jvalue; bpf_u_int32 jtype; int reverse; { struct block *b0; switch (atmfield) { case A_VPI: if (!is_atm) bpf_error("'vpi' supported only on raw ATM"); if (off_vpi == (u_int)-1) abort(); b0 = gen_ncmp(OR_LINK, off_vpi, BPF_B, 0xffffffff, jtype, reverse, jvalue); break; case A_VCI: if (!is_atm) bpf_error("'vci' supported only on raw ATM"); if (off_vci == (u_int)-1) abort(); b0 = gen_ncmp(OR_LINK, off_vci, BPF_H, 0xffffffff, jtype, reverse, jvalue); break; case A_PROTOTYPE: if (off_proto == (u_int)-1) abort(); /* XXX - this isn't on FreeBSD */ b0 = gen_ncmp(OR_LINK, off_proto, BPF_B, 0x0f, jtype, reverse, jvalue); break; case A_MSGTYPE: if (off_payload == (u_int)-1) abort(); b0 = gen_ncmp(OR_LINK, off_payload + MSG_TYPE_POS, BPF_B, 0xffffffff, jtype, reverse, jvalue); break; case A_CALLREFTYPE: if (!is_atm) bpf_error("'callref' supported only on raw ATM"); if (off_proto == (u_int)-1) abort(); b0 = gen_ncmp(OR_LINK, off_proto, BPF_B, 0xffffffff, jtype, reverse, jvalue); break; default: abort(); } return b0; } struct block * gen_atmtype_abbrev(type) int type; { struct block *b0, *b1; switch (type) { case A_METAC: /* Get all packets in Meta signalling Circuit */ if (!is_atm) bpf_error("'metac' supported only on raw ATM"); b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0); b1 = gen_atmfield_code(A_VCI, 1, BPF_JEQ, 0); gen_and(b0, b1); break; case A_BCC: /* Get all packets in Broadcast Circuit*/ if (!is_atm) bpf_error("'bcc' supported only on raw ATM"); b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0); b1 = gen_atmfield_code(A_VCI, 2, BPF_JEQ, 0); gen_and(b0, b1); break; case A_OAMF4SC: /* Get all cells in Segment OAM F4 circuit*/ if (!is_atm) bpf_error("'oam4sc' supported only on raw ATM"); b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0); b1 = gen_atmfield_code(A_VCI, 3, BPF_JEQ, 0); gen_and(b0, b1); break; case A_OAMF4EC: /* Get all cells in End-to-End OAM F4 Circuit*/ if (!is_atm) bpf_error("'oam4ec' supported only on raw ATM"); b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0); b1 = gen_atmfield_code(A_VCI, 4, BPF_JEQ, 0); gen_and(b0, b1); break; case A_SC: /* Get all packets in connection Signalling Circuit */ if (!is_atm) bpf_error("'sc' supported only on raw ATM"); b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0); b1 = gen_atmfield_code(A_VCI, 5, BPF_JEQ, 0); gen_and(b0, b1); break; case A_ILMIC: /* Get all packets in ILMI Circuit */ if (!is_atm) bpf_error("'ilmic' supported only on raw ATM"); b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0); b1 = gen_atmfield_code(A_VCI, 16, BPF_JEQ, 0); gen_and(b0, b1); break; case A_LANE: /* Get all LANE packets */ if (!is_atm) bpf_error("'lane' supported only on raw ATM"); b1 = gen_atmfield_code(A_PROTOTYPE, PT_LANE, BPF_JEQ, 0); /* * Arrange that all subsequent tests assume LANE * rather than LLC-encapsulated packets, and set * the offsets appropriately for LANE-encapsulated * Ethernet. * * "off_mac" is the offset of the Ethernet header, * which is 2 bytes past the ATM pseudo-header * (skipping the pseudo-header and 2-byte LE Client * field). The other offsets are Ethernet offsets * relative to "off_mac". */ is_lane = 1; off_mac = off_payload + 2; /* MAC header */ off_linktype = off_mac + 12; off_macpl = off_mac + 14; /* Ethernet */ off_nl = 0; /* Ethernet II */ off_nl_nosnap = 3; /* 802.3+802.2 */ break; case A_LLC: /* Get all LLC-encapsulated packets */ if (!is_atm) bpf_error("'llc' supported only on raw ATM"); b1 = gen_atmfield_code(A_PROTOTYPE, PT_LLC, BPF_JEQ, 0); is_lane = 0; break; default: abort(); } return b1; } /* * Filtering for MTP2 messages based on li value * FISU, length is null * LSSU, length is 1 or 2 * MSU, length is 3 or more */ struct block * gen_mtp2type_abbrev(type) int type; { struct block *b0, *b1; switch (type) { case M_FISU: if ( (linktype != DLT_MTP2) && (linktype != DLT_ERF) && (linktype != DLT_MTP2_WITH_PHDR) ) bpf_error("'fisu' supported only on MTP2"); /* gen_ncmp(offrel, offset, size, mask, jtype, reverse, value) */ b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JEQ, 0, 0); break; case M_LSSU: if ( (linktype != DLT_MTP2) && (linktype != DLT_ERF) && (linktype != DLT_MTP2_WITH_PHDR) ) bpf_error("'lssu' supported only on MTP2"); b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 1, 2); b1 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 0, 0); gen_and(b1, b0); break; case M_MSU: if ( (linktype != DLT_MTP2) && (linktype != DLT_ERF) && (linktype != DLT_MTP2_WITH_PHDR) ) bpf_error("'msu' supported only on MTP2"); b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 0, 2); break; default: abort(); } return b0; } struct block * gen_mtp3field_code(mtp3field, jvalue, jtype, reverse) int mtp3field; bpf_u_int32 jvalue; bpf_u_int32 jtype; int reverse; { struct block *b0; bpf_u_int32 val1 , val2 , val3; switch (mtp3field) { case M_SIO: if (off_sio == (u_int)-1) bpf_error("'sio' supported only on SS7"); /* sio coded on 1 byte so max value 255 */ if(jvalue > 255) bpf_error("sio value %u too big; max value = 255", jvalue); b0 = gen_ncmp(OR_PACKET, off_sio, BPF_B, 0xffffffff, (u_int)jtype, reverse, (u_int)jvalue); break; case M_OPC: if (off_opc == (u_int)-1) bpf_error("'opc' supported only on SS7"); /* opc coded on 14 bits so max value 16383 */ if (jvalue > 16383) bpf_error("opc value %u too big; max value = 16383", jvalue); /* the following instructions are made to convert jvalue * to the form used to write opc in an ss7 message*/ val1 = jvalue & 0x00003c00; val1 = val1 >>10; val2 = jvalue & 0x000003fc; val2 = val2 <<6; val3 = jvalue & 0x00000003; val3 = val3 <<22; jvalue = val1 + val2 + val3; b0 = gen_ncmp(OR_PACKET, off_opc, BPF_W, 0x00c0ff0f, (u_int)jtype, reverse, (u_int)jvalue); break; case M_DPC: if (off_dpc == (u_int)-1) bpf_error("'dpc' supported only on SS7"); /* dpc coded on 14 bits so max value 16383 */ if (jvalue > 16383) bpf_error("dpc value %u too big; max value = 16383", jvalue); /* the following instructions are made to convert jvalue * to the forme used to write dpc in an ss7 message*/ val1 = jvalue & 0x000000ff; val1 = val1 << 24; val2 = jvalue & 0x00003f00; val2 = val2 << 8; jvalue = val1 + val2; b0 = gen_ncmp(OR_PACKET, off_dpc, BPF_W, 0xff3f0000, (u_int)jtype, reverse, (u_int)jvalue); break; case M_SLS: if (off_sls == (u_int)-1) bpf_error("'sls' supported only on SS7"); /* sls coded on 4 bits so max value 15 */ if (jvalue > 15) bpf_error("sls value %u too big; max value = 15", jvalue); /* the following instruction is made to convert jvalue * to the forme used to write sls in an ss7 message*/ jvalue = jvalue << 4; b0 = gen_ncmp(OR_PACKET, off_sls, BPF_B, 0xf0, (u_int)jtype,reverse, (u_int)jvalue); break; default: abort(); } return b0; } static struct block * gen_msg_abbrev(type) int type; { struct block *b1; /* * Q.2931 signalling protocol messages for handling virtual circuits * establishment and teardown */ switch (type) { case A_SETUP: b1 = gen_atmfield_code(A_MSGTYPE, SETUP, BPF_JEQ, 0); break; case A_CALLPROCEED: b1 = gen_atmfield_code(A_MSGTYPE, CALL_PROCEED, BPF_JEQ, 0); break; case A_CONNECT: b1 = gen_atmfield_code(A_MSGTYPE, CONNECT, BPF_JEQ, 0); break; case A_CONNECTACK: b1 = gen_atmfield_code(A_MSGTYPE, CONNECT_ACK, BPF_JEQ, 0); break; case A_RELEASE: b1 = gen_atmfield_code(A_MSGTYPE, RELEASE, BPF_JEQ, 0); break; case A_RELEASE_DONE: b1 = gen_atmfield_code(A_MSGTYPE, RELEASE_DONE, BPF_JEQ, 0); break; default: abort(); } return b1; } struct block * gen_atmmulti_abbrev(type) int type; { struct block *b0, *b1; switch (type) { case A_OAM: if (!is_atm) bpf_error("'oam' supported only on raw ATM"); b1 = gen_atmmulti_abbrev(A_OAMF4); break; case A_OAMF4: if (!is_atm) bpf_error("'oamf4' supported only on raw ATM"); /* OAM F4 type */ b0 = gen_atmfield_code(A_VCI, 3, BPF_JEQ, 0); b1 = gen_atmfield_code(A_VCI, 4, BPF_JEQ, 0); gen_or(b0, b1); b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0); gen_and(b0, b1); break; case A_CONNECTMSG: /* * Get Q.2931 signalling messages for switched * virtual connection */ if (!is_atm) bpf_error("'connectmsg' supported only on raw ATM"); b0 = gen_msg_abbrev(A_SETUP); b1 = gen_msg_abbrev(A_CALLPROCEED); gen_or(b0, b1); b0 = gen_msg_abbrev(A_CONNECT); gen_or(b0, b1); b0 = gen_msg_abbrev(A_CONNECTACK); gen_or(b0, b1); b0 = gen_msg_abbrev(A_RELEASE); gen_or(b0, b1); b0 = gen_msg_abbrev(A_RELEASE_DONE); gen_or(b0, b1); b0 = gen_atmtype_abbrev(A_SC); gen_and(b0, b1); break; case A_METACONNECT: if (!is_atm) bpf_error("'metaconnect' supported only on raw ATM"); b0 = gen_msg_abbrev(A_SETUP); b1 = gen_msg_abbrev(A_CALLPROCEED); gen_or(b0, b1); b0 = gen_msg_abbrev(A_CONNECT); gen_or(b0, b1); b0 = gen_msg_abbrev(A_RELEASE); gen_or(b0, b1); b0 = gen_msg_abbrev(A_RELEASE_DONE); gen_or(b0, b1); b0 = gen_atmtype_abbrev(A_METAC); gen_and(b0, b1); break; default: abort(); } return b1; } Index: stable/9/contrib/libpcap/grammar.y =================================================================== --- stable/9/contrib/libpcap/grammar.y (revision 252280) +++ stable/9/contrib/libpcap/grammar.y (revision 252281) @@ -1,698 +1,698 @@ %{ /* * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * $FreeBSD$ */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/grammar.y,v 1.101 2007-11-18 02:03:52 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef WIN32 #include #else /* WIN32 */ #include #include #endif /* WIN32 */ #include #ifndef WIN32 #if __STDC__ struct mbuf; struct rtentry; #endif #include #include #endif /* WIN32 */ #include #include "pcap-int.h" #include "gencode.h" #ifdef HAVE_NET_PFVAR_H #include #include #include #endif #include "ieee80211.h" #include #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif #define QSET(q, p, d, a) (q).proto = (p),\ (q).dir = (d),\ (q).addr = (a) struct tok { int v; /* value */ const char *s; /* string */ }; static const struct tok ieee80211_types[] = { { IEEE80211_FC0_TYPE_DATA, "data" }, { IEEE80211_FC0_TYPE_MGT, "mgt" }, { IEEE80211_FC0_TYPE_MGT, "management" }, { IEEE80211_FC0_TYPE_CTL, "ctl" }, { IEEE80211_FC0_TYPE_CTL, "control" }, { 0, NULL } }; static const struct tok ieee80211_mgt_subtypes[] = { { IEEE80211_FC0_SUBTYPE_ASSOC_REQ, "assocreq" }, { IEEE80211_FC0_SUBTYPE_ASSOC_REQ, "assoc-req" }, { IEEE80211_FC0_SUBTYPE_ASSOC_RESP, "assocresp" }, { IEEE80211_FC0_SUBTYPE_ASSOC_RESP, "assoc-resp" }, { IEEE80211_FC0_SUBTYPE_REASSOC_REQ, "reassocreq" }, { IEEE80211_FC0_SUBTYPE_REASSOC_REQ, "reassoc-req" }, { IEEE80211_FC0_SUBTYPE_REASSOC_RESP, "reassocresp" }, { IEEE80211_FC0_SUBTYPE_REASSOC_RESP, "reassoc-resp" }, { IEEE80211_FC0_SUBTYPE_PROBE_REQ, "probereq" }, { IEEE80211_FC0_SUBTYPE_PROBE_REQ, "probe-req" }, { IEEE80211_FC0_SUBTYPE_PROBE_RESP, "proberesp" }, { IEEE80211_FC0_SUBTYPE_PROBE_RESP, "probe-resp" }, { IEEE80211_FC0_SUBTYPE_BEACON, "beacon" }, { IEEE80211_FC0_SUBTYPE_ATIM, "atim" }, { IEEE80211_FC0_SUBTYPE_DISASSOC, "disassoc" }, { IEEE80211_FC0_SUBTYPE_DISASSOC, "disassociation" }, { IEEE80211_FC0_SUBTYPE_AUTH, "auth" }, { IEEE80211_FC0_SUBTYPE_AUTH, "authentication" }, { IEEE80211_FC0_SUBTYPE_DEAUTH, "deauth" }, { IEEE80211_FC0_SUBTYPE_DEAUTH, "deauthentication" }, { 0, NULL } }; static const struct tok ieee80211_ctl_subtypes[] = { { IEEE80211_FC0_SUBTYPE_PS_POLL, "ps-poll" }, { IEEE80211_FC0_SUBTYPE_RTS, "rts" }, { IEEE80211_FC0_SUBTYPE_CTS, "cts" }, { IEEE80211_FC0_SUBTYPE_ACK, "ack" }, { IEEE80211_FC0_SUBTYPE_CF_END, "cf-end" }, { IEEE80211_FC0_SUBTYPE_CF_END_ACK, "cf-end-ack" }, { 0, NULL } }; static const struct tok ieee80211_data_subtypes[] = { { IEEE80211_FC0_SUBTYPE_DATA, "data" }, { IEEE80211_FC0_SUBTYPE_CF_ACK, "data-cf-ack" }, { IEEE80211_FC0_SUBTYPE_CF_POLL, "data-cf-poll" }, { IEEE80211_FC0_SUBTYPE_CF_ACPL, "data-cf-ack-poll" }, { IEEE80211_FC0_SUBTYPE_NODATA, "null" }, { IEEE80211_FC0_SUBTYPE_NODATA_CF_ACK, "cf-ack" }, { IEEE80211_FC0_SUBTYPE_NODATA_CF_POLL, "cf-poll" }, { IEEE80211_FC0_SUBTYPE_NODATA_CF_ACPL, "cf-ack-poll" }, { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_DATA, "qos-data" }, { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_CF_ACK, "qos-data-cf-ack" }, { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_CF_POLL, "qos-data-cf-poll" }, { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_CF_ACPL, "qos-data-cf-ack-poll" }, { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_NODATA, "qos" }, { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_NODATA_CF_POLL, "qos-cf-poll" }, { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_NODATA_CF_ACPL, "qos-cf-ack-poll" }, { 0, NULL } }; struct type2tok { int type; const struct tok *tok; }; static const struct type2tok ieee80211_type_subtypes[] = { { IEEE80211_FC0_TYPE_MGT, ieee80211_mgt_subtypes }, { IEEE80211_FC0_TYPE_CTL, ieee80211_ctl_subtypes }, { IEEE80211_FC0_TYPE_DATA, ieee80211_data_subtypes }, { 0, NULL } }; static int str2tok(const char *str, const struct tok *toks) { int i; for (i = 0; toks[i].s != NULL; i++) { if (pcap_strcasecmp(toks[i].s, str) == 0) return (toks[i].v); } return (-1); } int n_errors = 0; static struct qual qerr = { Q_UNDEF, Q_UNDEF, Q_UNDEF, Q_UNDEF }; static void yyerror(const char *msg) { ++n_errors; bpf_error("%s", msg); /* NOTREACHED */ } -#ifndef YYBISON +#ifdef NEED_YYPARSE_WRAPPER int yyparse(void); int pcap_parse() { return (yyparse()); } #endif #ifdef HAVE_NET_PFVAR_H static int pfreason_to_num(const char *reason) { const char *reasons[] = PFRES_NAMES; int i; for (i = 0; reasons[i]; i++) { if (pcap_strcasecmp(reason, reasons[i]) == 0) return (i); } bpf_error("unknown PF reason"); /*NOTREACHED*/ } static int pfaction_to_num(const char *action) { if (pcap_strcasecmp(action, "pass") == 0 || pcap_strcasecmp(action, "accept") == 0) return (PF_PASS); else if (pcap_strcasecmp(action, "drop") == 0 || pcap_strcasecmp(action, "block") == 0) return (PF_DROP); #if HAVE_PF_NAT_THROUGH_PF_NORDR else if (pcap_strcasecmp(action, "rdr") == 0) return (PF_RDR); else if (pcap_strcasecmp(action, "nat") == 0) return (PF_NAT); else if (pcap_strcasecmp(action, "binat") == 0) return (PF_BINAT); else if (pcap_strcasecmp(action, "nordr") == 0) return (PF_NORDR); #endif else { bpf_error("unknown PF action"); /*NOTREACHED*/ } } #else /* !HAVE_NET_PFVAR_H */ static int pfreason_to_num(const char *reason) { bpf_error("libpcap was compiled on a machine without pf support"); /*NOTREACHED*/ /* this is to make the VC compiler happy */ return -1; } static int pfaction_to_num(const char *action) { bpf_error("libpcap was compiled on a machine without pf support"); /*NOTREACHED*/ /* this is to make the VC compiler happy */ return -1; } #endif /* HAVE_NET_PFVAR_H */ %} %union { int i; bpf_u_int32 h; u_char *e; char *s; struct stmt *stmt; struct arth *a; struct { struct qual q; int atmfieldtype; int mtp3fieldtype; struct block *b; } blk; struct block *rblk; } %type expr id nid pid term rterm qid %type head %type pqual dqual aqual ndaqual %type arth narth %type byteop pname pnum relop irelop %type and or paren not null prog %type other pfvar p80211 %type atmtype atmmultitype %type atmfield %type atmfieldvalue atmvalue atmlistvalue %type mtp2type %type mtp3field %type mtp3fieldvalue mtp3value mtp3listvalue %token DST SRC HOST GATEWAY %token NET NETMASK PORT PORTRANGE LESS GREATER PROTO PROTOCHAIN CBYTE %token ARP RARP IP SCTP TCP UDP ICMP IGMP IGRP PIM VRRP CARP %token ATALK AARP DECNET LAT SCA MOPRC MOPDL %token TK_BROADCAST TK_MULTICAST %token NUM INBOUND OUTBOUND %token PF_IFNAME PF_RSET PF_RNR PF_SRNR PF_REASON PF_ACTION %token TYPE SUBTYPE DIR ADDR1 ADDR2 ADDR3 ADDR4 RA TA %token LINK %token GEQ LEQ NEQ %token ID EID HID HID6 AID %token LSH RSH %token LEN %token IPV6 ICMPV6 AH ESP %token VLAN MPLS %token PPPOED PPPOES %token ISO ESIS CLNP ISIS L1 L2 IIH LSP SNP CSNP PSNP %token STP %token IPX %token NETBEUI %token LANE LLC METAC BCC SC ILMIC OAMF4EC OAMF4SC %token OAM OAMF4 CONNECTMSG METACONNECT %token VPI VCI %token RADIO %token FISU LSSU MSU %token SIO OPC DPC SLS %type ID %type EID %type AID %type HID HID6 %type NUM action reason type subtype type_subtype dir %left OR AND %nonassoc '!' %left '|' %left '&' %left LSH RSH %left '+' '-' %left '*' '/' %nonassoc UMINUS %% prog: null expr { finish_parse($2.b); } | null ; null: /* null */ { $$.q = qerr; } ; expr: term | expr and term { gen_and($1.b, $3.b); $$ = $3; } | expr and id { gen_and($1.b, $3.b); $$ = $3; } | expr or term { gen_or($1.b, $3.b); $$ = $3; } | expr or id { gen_or($1.b, $3.b); $$ = $3; } ; and: AND { $$ = $0; } ; or: OR { $$ = $0; } ; id: nid | pnum { $$.b = gen_ncode(NULL, (bpf_u_int32)$1, $$.q = $0.q); } | paren pid ')' { $$ = $2; } ; nid: ID { $$.b = gen_scode($1, $$.q = $0.q); } | HID '/' NUM { $$.b = gen_mcode($1, NULL, $3, $$.q = $0.q); } | HID NETMASK HID { $$.b = gen_mcode($1, $3, 0, $$.q = $0.q); } | HID { /* Decide how to parse HID based on proto */ $$.q = $0.q; if ($$.q.addr == Q_PORT) bpf_error("'port' modifier applied to ip host"); else if ($$.q.addr == Q_PORTRANGE) bpf_error("'portrange' modifier applied to ip host"); else if ($$.q.addr == Q_PROTO) bpf_error("'proto' modifier applied to ip host"); else if ($$.q.addr == Q_PROTOCHAIN) bpf_error("'protochain' modifier applied to ip host"); $$.b = gen_ncode($1, 0, $$.q); } | HID6 '/' NUM { #ifdef INET6 $$.b = gen_mcode6($1, NULL, $3, $$.q = $0.q); #else bpf_error("'ip6addr/prefixlen' not supported " "in this configuration"); #endif /*INET6*/ } | HID6 { #ifdef INET6 $$.b = gen_mcode6($1, 0, 128, $$.q = $0.q); #else bpf_error("'ip6addr' not supported " "in this configuration"); #endif /*INET6*/ } | 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; } ; paren: '(' { $$ = $0; } ; pid: nid | qid and id { gen_and($1.b, $3.b); $$ = $3; } | qid or id { gen_or($1.b, $3.b); $$ = $3; } ; qid: pnum { $$.b = gen_ncode(NULL, (bpf_u_int32)$1, $$.q = $0.q); } | pid ; term: rterm | not term { gen_not($2.b); $$ = $2; } ; head: pqual dqual aqual { QSET($$.q, $1, $2, $3); } | pqual dqual { QSET($$.q, $1, $2, Q_DEFAULT); } | pqual aqual { QSET($$.q, $1, Q_DEFAULT, $2); } | pqual PROTO { QSET($$.q, $1, Q_DEFAULT, Q_PROTO); } | pqual PROTOCHAIN { QSET($$.q, $1, Q_DEFAULT, Q_PROTOCHAIN); } | pqual ndaqual { QSET($$.q, $1, Q_DEFAULT, $2); } ; rterm: head id { $$ = $2; } | paren expr ')' { $$.b = $2.b; $$.q = $1.q; } | pname { $$.b = gen_proto_abbrev($1); $$.q = qerr; } | arth relop arth { $$.b = gen_relation($2, $1, $3, 0); $$.q = qerr; } | arth irelop arth { $$.b = gen_relation($2, $1, $3, 1); $$.q = qerr; } | other { $$.b = $1; $$.q = qerr; } | atmtype { $$.b = gen_atmtype_abbrev($1); $$.q = qerr; } | atmmultitype { $$.b = gen_atmmulti_abbrev($1); $$.q = qerr; } | atmfield atmvalue { $$.b = $2.b; $$.q = qerr; } | mtp2type { $$.b = gen_mtp2type_abbrev($1); $$.q = qerr; } | mtp3field mtp3value { $$.b = $2.b; $$.q = qerr; } ; /* protocol level qualifiers */ pqual: pname | { $$ = Q_DEFAULT; } ; /* 'direction' qualifiers */ dqual: SRC { $$ = Q_SRC; } | DST { $$ = Q_DST; } | SRC OR DST { $$ = Q_OR; } | DST OR SRC { $$ = Q_OR; } | SRC AND DST { $$ = Q_AND; } | DST AND SRC { $$ = Q_AND; } | ADDR1 { $$ = Q_ADDR1; } | ADDR2 { $$ = Q_ADDR2; } | ADDR3 { $$ = Q_ADDR3; } | ADDR4 { $$ = Q_ADDR4; } | RA { $$ = Q_RA; } | TA { $$ = Q_TA; } ; /* address type qualifiers */ aqual: HOST { $$ = Q_HOST; } | NET { $$ = Q_NET; } | PORT { $$ = Q_PORT; } | PORTRANGE { $$ = Q_PORTRANGE; } ; /* non-directional address type qualifiers */ ndaqual: GATEWAY { $$ = Q_GATEWAY; } ; 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; } | CARP { $$ = Q_CARP; } | ATALK { $$ = Q_ATALK; } | AARP { $$ = Q_AARP; } | DECNET { $$ = Q_DECNET; } | LAT { $$ = Q_LAT; } | SCA { $$ = Q_SCA; } | MOPDL { $$ = Q_MOPDL; } | MOPRC { $$ = Q_MOPRC; } | IPV6 { $$ = Q_IPV6; } | ICMPV6 { $$ = Q_ICMPV6; } | AH { $$ = Q_AH; } | ESP { $$ = Q_ESP; } | ISO { $$ = Q_ISO; } | ESIS { $$ = Q_ESIS; } | ISIS { $$ = Q_ISIS; } | L1 { $$ = Q_ISIS_L1; } | L2 { $$ = Q_ISIS_L2; } | IIH { $$ = Q_ISIS_IIH; } | LSP { $$ = Q_ISIS_LSP; } | SNP { $$ = Q_ISIS_SNP; } | PSNP { $$ = Q_ISIS_PSNP; } | CSNP { $$ = Q_ISIS_CSNP; } | CLNP { $$ = Q_CLNP; } | STP { $$ = Q_STP; } | IPX { $$ = Q_IPX; } | NETBEUI { $$ = Q_NETBEUI; } | RADIO { $$ = Q_RADIO; } ; other: pqual TK_BROADCAST { $$ = gen_broadcast($1); } | pqual TK_MULTICAST { $$ = gen_multicast($1); } | LESS NUM { $$ = gen_less($2); } | GREATER NUM { $$ = gen_greater($2); } | CBYTE NUM byteop NUM { $$ = gen_byteop($3, $2, $4); } | INBOUND { $$ = gen_inbound(0); } | OUTBOUND { $$ = gen_inbound(1); } | VLAN pnum { $$ = gen_vlan($2); } | VLAN { $$ = gen_vlan(-1); } | MPLS pnum { $$ = gen_mpls($2); } | MPLS { $$ = gen_mpls(-1); } | PPPOED { $$ = gen_pppoed(); } | PPPOES { $$ = gen_pppoes(); } | pfvar { $$ = $1; } | pqual p80211 { $$ = $2; } ; pfvar: PF_IFNAME ID { $$ = gen_pf_ifname($2); } | PF_RSET ID { $$ = gen_pf_ruleset($2); } | PF_RNR NUM { $$ = gen_pf_rnr($2); } | PF_SRNR NUM { $$ = gen_pf_srnr($2); } | PF_REASON reason { $$ = gen_pf_reason($2); } | PF_ACTION action { $$ = gen_pf_action($2); } ; p80211: TYPE type SUBTYPE subtype { $$ = gen_p80211_type($2 | $4, IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK); } | TYPE type { $$ = gen_p80211_type($2, IEEE80211_FC0_TYPE_MASK); } | SUBTYPE type_subtype { $$ = gen_p80211_type($2, IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK); } | DIR dir { $$ = gen_p80211_fcdir($2); } ; type: NUM | ID { $$ = str2tok($1, ieee80211_types); if ($$ == -1) bpf_error("unknown 802.11 type name"); } ; subtype: NUM | ID { const struct tok *types = NULL; int i; for (i = 0;; i++) { if (ieee80211_type_subtypes[i].tok == NULL) { /* Ran out of types */ bpf_error("unknown 802.11 type"); break; } if ($-1 == ieee80211_type_subtypes[i].type) { types = ieee80211_type_subtypes[i].tok; break; } } $$ = str2tok($1, types); if ($$ == -1) bpf_error("unknown 802.11 subtype name"); } ; type_subtype: ID { int i; for (i = 0;; i++) { if (ieee80211_type_subtypes[i].tok == NULL) { /* Ran out of types */ bpf_error("unknown 802.11 type name"); break; } $$ = str2tok($1, ieee80211_type_subtypes[i].tok); if ($$ != -1) { $$ |= ieee80211_type_subtypes[i].type; break; } } } ; dir: NUM | ID { if (pcap_strcasecmp($1, "nods") == 0) $$ = IEEE80211_FC1_DIR_NODS; else if (pcap_strcasecmp($1, "tods") == 0) $$ = IEEE80211_FC1_DIR_TODS; else if (pcap_strcasecmp($1, "fromds") == 0) $$ = IEEE80211_FC1_DIR_FROMDS; else if (pcap_strcasecmp($1, "dstods") == 0) $$ = IEEE80211_FC1_DIR_DSTODS; else bpf_error("unknown 802.11 direction"); } ; reason: NUM { $$ = $1; } | ID { $$ = pfreason_to_num($1); } ; action: ID { $$ = pfaction_to_num($1); } ; relop: '>' { $$ = BPF_JGT; } | GEQ { $$ = BPF_JGE; } | '=' { $$ = BPF_JEQ; } ; irelop: LEQ { $$ = BPF_JGT; } | '<' { $$ = BPF_JGE; } | NEQ { $$ = BPF_JEQ; } ; arth: pnum { $$ = gen_loadi($1); } | narth ; narth: pname '[' arth ']' { $$ = gen_load($1, $3, 1); } | pname '[' arth ':' NUM ']' { $$ = gen_load($1, $3, $5); } | arth '+' arth { $$ = gen_arth(BPF_ADD, $1, $3); } | arth '-' arth { $$ = gen_arth(BPF_SUB, $1, $3); } | arth '*' arth { $$ = gen_arth(BPF_MUL, $1, $3); } | arth '/' arth { $$ = gen_arth(BPF_DIV, $1, $3); } | arth '&' arth { $$ = gen_arth(BPF_AND, $1, $3); } | arth '|' arth { $$ = gen_arth(BPF_OR, $1, $3); } | arth LSH arth { $$ = gen_arth(BPF_LSH, $1, $3); } | arth RSH arth { $$ = gen_arth(BPF_RSH, $1, $3); } | '-' arth %prec UMINUS { $$ = gen_neg($2); } | paren narth ')' { $$ = $2; } | LEN { $$ = gen_loadlen(); } ; byteop: '&' { $$ = '&'; } | '|' { $$ = '|'; } | '<' { $$ = '<'; } | '>' { $$ = '>'; } | '=' { $$ = '='; } ; pnum: NUM | paren pnum ')' { $$ = $2; } ; atmtype: LANE { $$ = A_LANE; } | LLC { $$ = A_LLC; } | METAC { $$ = A_METAC; } | BCC { $$ = A_BCC; } | OAMF4EC { $$ = A_OAMF4EC; } | OAMF4SC { $$ = A_OAMF4SC; } | SC { $$ = A_SC; } | ILMIC { $$ = A_ILMIC; } ; atmmultitype: OAM { $$ = A_OAM; } | OAMF4 { $$ = A_OAMF4; } | CONNECTMSG { $$ = A_CONNECTMSG; } | METACONNECT { $$ = A_METACONNECT; } ; /* ATM field types quantifier */ atmfield: VPI { $$.atmfieldtype = A_VPI; } | VCI { $$.atmfieldtype = A_VCI; } ; atmvalue: atmfieldvalue | relop NUM { $$.b = gen_atmfield_code($0.atmfieldtype, (bpf_int32)$2, (bpf_u_int32)$1, 0); } | irelop NUM { $$.b = gen_atmfield_code($0.atmfieldtype, (bpf_int32)$2, (bpf_u_int32)$1, 1); } | paren atmlistvalue ')' { $$.b = $2.b; $$.q = qerr; } ; atmfieldvalue: NUM { $$.atmfieldtype = $0.atmfieldtype; if ($$.atmfieldtype == A_VPI || $$.atmfieldtype == A_VCI) $$.b = gen_atmfield_code($$.atmfieldtype, (bpf_int32) $1, BPF_JEQ, 0); } ; atmlistvalue: atmfieldvalue | atmlistvalue or atmfieldvalue { gen_or($1.b, $3.b); $$ = $3; } ; /* MTP2 types quantifier */ mtp2type: FISU { $$ = M_FISU; } | LSSU { $$ = M_LSSU; } | MSU { $$ = M_MSU; } ; /* MTP3 field types quantifier */ mtp3field: SIO { $$.mtp3fieldtype = M_SIO; } | OPC { $$.mtp3fieldtype = M_OPC; } | DPC { $$.mtp3fieldtype = M_DPC; } | SLS { $$.mtp3fieldtype = M_SLS; } ; mtp3value: mtp3fieldvalue | relop NUM { $$.b = gen_mtp3field_code($0.mtp3fieldtype, (u_int)$2, (u_int)$1, 0); } | irelop NUM { $$.b = gen_mtp3field_code($0.mtp3fieldtype, (u_int)$2, (u_int)$1, 1); } | paren mtp3listvalue ')' { $$.b = $2.b; $$.q = qerr; } ; mtp3fieldvalue: NUM { $$.mtp3fieldtype = $0.mtp3fieldtype; if ($$.mtp3fieldtype == M_SIO || $$.mtp3fieldtype == M_OPC || $$.mtp3fieldtype == M_DPC || $$.mtp3fieldtype == M_SLS ) $$.b = gen_mtp3field_code($$.mtp3fieldtype, (u_int) $1, BPF_JEQ, 0); } ; mtp3listvalue: mtp3fieldvalue | mtp3listvalue or mtp3fieldvalue { gen_or($1.b, $3.b); $$ = $3; } ; %% Index: stable/9/contrib/libpcap/nametoaddr.c =================================================================== --- stable/9/contrib/libpcap/nametoaddr.c (revision 252280) +++ stable/9/contrib/libpcap/nametoaddr.c (revision 252281) @@ -1,522 +1,523 @@ /* * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Name to id translation routines used by the scanner. * These functions are not time critical. * * $FreeBSD$ */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/nametoaddr.c,v 1.83 2008-02-06 10:21:30 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef DECNETLIB #include #include #endif #ifdef WIN32 #include #else /* WIN32 */ #include #include /* concession to AIX */ #include #include #include #endif /* WIN32 */ #ifndef WIN32 #ifdef HAVE_ETHER_HOSTTON /* * XXX - do we need any of this if doesn't declare * ether_hostton()? */ #ifdef HAVE_NETINET_IF_ETHER_H struct mbuf; /* Squelch compiler warnings on some platforms for */ struct rtentry; /* declarations in */ #include /* for "struct ifnet" in "struct arpcom" on Solaris */ #include #endif /* HAVE_NETINET_IF_ETHER_H */ #ifdef NETINET_ETHER_H_DECLARES_ETHER_HOSTTON #include #endif /* NETINET_ETHER_H_DECLARES_ETHER_HOSTTON */ #endif /* HAVE_ETHER_HOSTTON */ #include #include #endif /* WIN32 */ #include #include #include #include #include #include "pcap-int.h" #include "gencode.h" #include #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif #ifndef NTOHL #define NTOHL(x) (x) = ntohl(x) #define NTOHS(x) (x) = ntohs(x) #endif static inline int xdtoi(int); /* * Convert host name to internet address. * Return 0 upon failure. */ bpf_u_int32 ** pcap_nametoaddr(const char *name) { #ifndef h_addr static bpf_u_int32 *hlist[2]; #endif bpf_u_int32 **p; struct hostent *hp; if ((hp = gethostbyname(name)) != NULL) { #ifndef h_addr hlist[0] = (bpf_u_int32 *)hp->h_addr; NTOHL(hp->h_addr); return hlist; #else for (p = (bpf_u_int32 **)hp->h_addr_list; *p; ++p) NTOHL(**p); return (bpf_u_int32 **)hp->h_addr_list; #endif } else return 0; } #ifdef INET6 struct addrinfo * pcap_nametoaddrinfo(const char *name) { struct addrinfo hints, *res; int error; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; /*not really*/ hints.ai_protocol = IPPROTO_TCP; /*not really*/ error = getaddrinfo(name, NULL, &hints, &res); if (error) return NULL; else return res; } #endif /*INET6*/ /* * Convert net name to internet address. * Return 0 upon failure. */ bpf_u_int32 pcap_nametonetaddr(const char *name) { #ifndef WIN32 struct netent *np; if ((np = getnetbyname(name)) != NULL) return np->n_net; else return 0; #else /* * There's no "getnetbyname()" on Windows. */ return 0; #endif } /* * Convert a port name to its port and protocol numbers. * We assume only TCP or UDP. * Return 0 upon failure. */ int pcap_nametoport(const char *name, int *port, int *proto) { struct servent *sp; int tcp_port = -1; int udp_port = -1; /* * We need to check /etc/services for ambiguous entries. * If we find the ambiguous entry, and it has the * same port number, change the proto to PROTO_UNDEF * so both TCP and UDP will be checked. */ sp = getservbyname(name, "tcp"); if (sp != NULL) tcp_port = ntohs(sp->s_port); sp = getservbyname(name, "udp"); if (sp != NULL) udp_port = ntohs(sp->s_port); if (tcp_port >= 0) { *port = tcp_port; *proto = IPPROTO_TCP; if (udp_port >= 0) { if (udp_port == tcp_port) *proto = PROTO_UNDEF; #ifdef notdef else /* Can't handle ambiguous names that refer to different port numbers. */ warning("ambiguous port %s in /etc/services", name); #endif } return 1; } if (udp_port >= 0) { *port = udp_port; *proto = IPPROTO_UDP; return 1; } #if defined(ultrix) || defined(__osf__) /* Special hack in case NFS isn't in /etc/services */ if (strcmp(name, "nfs") == 0) { *port = 2049; *proto = PROTO_UNDEF; return 1; } #endif return 0; } /* * Convert a string in the form PPP-PPP, where correspond to ports, to * a starting and ending port in a port range. * Return 0 on failure. */ int pcap_nametoportrange(const char *name, int *port1, int *port2, int *proto) { u_int p1, p2; char *off, *cpy; int save_proto; if (sscanf(name, "%d-%d", &p1, &p2) != 2) { if ((cpy = strdup(name)) == NULL) return 0; if ((off = strchr(cpy, '-')) == NULL) { free(cpy); return 0; } *off = '\0'; if (pcap_nametoport(cpy, port1, proto) == 0) { free(cpy); return 0; } save_proto = *proto; if (pcap_nametoport(off + 1, port2, proto) == 0) { free(cpy); return 0; } + free(cpy); if (*proto != save_proto) *proto = PROTO_UNDEF; } else { *port1 = p1; *port2 = p2; *proto = PROTO_UNDEF; } return 1; } int pcap_nametoproto(const char *str) { struct protoent *p; p = getprotobyname(str); if (p != 0) return p->p_proto; else return PROTO_UNDEF; } #include "ethertype.h" struct eproto { const char *s; u_short p; }; /* Static data base of ether protocol types. */ struct eproto eproto_db[] = { #if 0 /* The FreeBSD elf linker generates a request to copy this array * (including its size) when you link with -lpcap. In order to * not bump the major version number of this libpcap.so, we need * to ensure that the array stays the same size. Since PUP is * likely never seen in real life any more, it's the first to * be sacrificed (in favor of ip6). */ { "pup", ETHERTYPE_PUP }, #endif { "xns", ETHERTYPE_NS }, { "ip", ETHERTYPE_IP }, #ifdef INET6 { "ip6", ETHERTYPE_IPV6 }, #endif { "arp", ETHERTYPE_ARP }, { "rarp", ETHERTYPE_REVARP }, { "sprite", ETHERTYPE_SPRITE }, { "mopdl", ETHERTYPE_MOPDL }, { "moprc", ETHERTYPE_MOPRC }, { "decnet", ETHERTYPE_DN }, { "lat", ETHERTYPE_LAT }, { "sca", ETHERTYPE_SCA }, { "lanbridge", ETHERTYPE_LANBRIDGE }, { "vexp", ETHERTYPE_VEXP }, { "vprod", ETHERTYPE_VPROD }, { "atalk", ETHERTYPE_ATALK }, { "atalkarp", ETHERTYPE_AARP }, { "loopback", ETHERTYPE_LOOPBACK }, { "decdts", ETHERTYPE_DECDTS }, { "decdns", ETHERTYPE_DECDNS }, { (char *)0, 0 } }; int pcap_nametoeproto(const char *s) { struct eproto *p = eproto_db; while (p->s != 0) { if (strcmp(p->s, s) == 0) return p->p; p += 1; } return PROTO_UNDEF; } #include "llc.h" /* Static data base of LLC values. */ static struct eproto llc_db[] = { { "iso", LLCSAP_ISONS }, { "stp", LLCSAP_8021D }, { "ipx", LLCSAP_IPX }, { "netbeui", LLCSAP_NETBEUI }, { (char *)0, 0 } }; int pcap_nametollc(const char *s) { struct eproto *p = llc_db; while (p->s != 0) { if (strcmp(p->s, s) == 0) return p->p; p += 1; } return PROTO_UNDEF; } /* Hex digit to integer. */ static inline int xdtoi(c) register int c; { if (isdigit(c)) return c - '0'; else if (islower(c)) return c - 'a' + 10; else return c - 'A' + 10; } int __pcap_atoin(const char *s, bpf_u_int32 *addr) { u_int n; int len; *addr = 0; len = 0; while (1) { n = 0; while (*s && *s != '.') n = n * 10 + *s++ - '0'; *addr <<= 8; *addr |= n & 0xff; len += 8; if (*s == '\0') return len; ++s; } /* NOTREACHED */ } int __pcap_atodn(const char *s, bpf_u_int32 *addr) { #define AREASHIFT 10 #define AREAMASK 0176000 #define NODEMASK 01777 u_int node, area; if (sscanf(s, "%d.%d", &area, &node) != 2) bpf_error("malformed decnet address '%s'", s); *addr = (area << AREASHIFT) & AREAMASK; *addr |= (node & NODEMASK); return(32); } /* * Convert 's', which can have the one of the forms: * * "xx:xx:xx:xx:xx:xx" * "xx.xx.xx.xx.xx.xx" * "xx-xx-xx-xx-xx-xx" * "xxxx.xxxx.xxxx" * "xxxxxxxxxxxx" * * (or various mixes of ':', '.', and '-') into a new * ethernet address. Assumes 's' is well formed. */ u_char * pcap_ether_aton(const char *s) { register u_char *ep, *e; register u_int d; e = ep = (u_char *)malloc(6); while (*s) { if (*s == ':' || *s == '.' || *s == '-') s += 1; d = xdtoi(*s++); if (isxdigit((unsigned char)*s)) { d <<= 4; d |= xdtoi(*s++); } *ep++ = d; } return (e); } #ifndef HAVE_ETHER_HOSTTON /* Roll our own */ u_char * pcap_ether_hostton(const char *name) { register struct pcap_etherent *ep; register u_char *ap; static FILE *fp = NULL; static int init = 0; if (!init) { fp = fopen(PCAP_ETHERS_FILE, "r"); ++init; if (fp == NULL) return (NULL); } else if (fp == NULL) return (NULL); else rewind(fp); while ((ep = pcap_next_etherent(fp)) != NULL) { if (strcmp(ep->name, name) == 0) { ap = (u_char *)malloc(6); if (ap != NULL) { memcpy(ap, ep->addr, 6); return (ap); } break; } } return (NULL); } #else #if !defined(HAVE_DECL_ETHER_HOSTTON) || !HAVE_DECL_ETHER_HOSTTON #ifndef HAVE_STRUCT_ETHER_ADDR struct ether_addr { unsigned char ether_addr_octet[6]; }; #endif extern int ether_hostton(const char *, struct ether_addr *); #endif /* Use the os supplied routines */ u_char * pcap_ether_hostton(const char *name) { register u_char *ap; u_char a[6]; ap = NULL; if (ether_hostton(name, (struct ether_addr *)a) == 0) { ap = (u_char *)malloc(6); if (ap != NULL) memcpy((char *)ap, (char *)a, 6); } return (ap); } #endif u_short __pcap_nametodnaddr(const char *name) { #ifdef DECNETLIB struct nodeent *getnodebyname(); struct nodeent *nep; unsigned short res; nep = getnodebyname(name); if (nep == ((struct nodeent *)0)) bpf_error("unknown decnet host name '%s'\n", name); memcpy((char *)&res, (char *)nep->n_addr, sizeof(unsigned short)); return(res); #else bpf_error("decnet name support not included, '%s' cannot be translated\n", name); return(0); #endif } Index: stable/9/contrib/libpcap/optimize.c =================================================================== --- stable/9/contrib/libpcap/optimize.c (revision 252280) +++ stable/9/contrib/libpcap/optimize.c (revision 252281) @@ -1,2347 +1,2247 @@ /* * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994, 1995, 1996 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Optimization module for tcpdump intermediate representation. */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/optimize.c,v 1.91 2008-01-02 04:16:46 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef WIN32 #include #else /* WIN32 */ #if HAVE_INTTYPES_H #include #elif HAVE_STDINT_H #include #endif #ifdef HAVE_SYS_BITYPES_H #include #endif #include #endif /* WIN32 */ #include #include #include #include #include #include "pcap-int.h" #include "gencode.h" #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif #ifdef BDEBUG extern int dflag; #endif #if defined(MSDOS) && !defined(__DJGPP__) extern int _w32_ffs (int mask); #define ffs _w32_ffs #endif #if defined(WIN32) && defined (_MSC_VER) int ffs(int mask); #endif /* * Represents a deleted instruction. */ #define NOP -1 /* * Register numbers for use-def values. * 0 through BPF_MEMWORDS-1 represent the corresponding scratch memory * location. A_ATOM is the accumulator and X_ATOM is the index * register. */ #define A_ATOM BPF_MEMWORDS #define X_ATOM (BPF_MEMWORDS+1) /* * This define is used to represent *both* the accumulator and * x register in use-def computations. * Currently, the use-def code assumes only one definition per instruction. */ #define AX_ATOM N_ATOMS /* * A flag to indicate that further optimization is needed. * Iterative passes are continued until a given pass yields no * branch movement. */ static int done; /* * A block is marked if only if its mark equals the current mark. * Rather than traverse the code array, marking each item, 'cur_mark' is * incremented. This automatically makes each element unmarked. */ static int cur_mark; #define isMarked(p) ((p)->mark == cur_mark) #define unMarkAll() cur_mark += 1 #define Mark(p) ((p)->mark = cur_mark) static void opt_init(struct block *); static void opt_cleanup(void); -static void make_marks(struct block *); -static void mark_code(struct block *); - static void intern_blocks(struct block *); -static int eq_slist(struct slist *, struct slist *); - -static void find_levels_r(struct block *); - -static void find_levels(struct block *); -static void find_dom(struct block *); -static void propedom(struct edge *); -static void find_edom(struct block *); -static void find_closure(struct block *); -static int atomuse(struct stmt *); -static int atomdef(struct stmt *); -static void compute_local_ud(struct block *); -static void find_ud(struct block *); -static void init_val(void); -static int F(int, int, int); -static inline void vstore(struct stmt *, int *, int, int); -static void opt_blk(struct block *, int); -static int use_conflict(struct block *, struct block *); -static void opt_j(struct edge *); -static void or_pullup(struct block *); -static void and_pullup(struct block *); -static void opt_blks(struct block *, int); -static inline void link_inedge(struct edge *, struct block *); static void find_inedges(struct block *); -static void opt_root(struct block **); -static void opt_loop(struct block *, int); -static void fold_op(struct stmt *, int, int); -static inline struct slist *this_op(struct slist *); -static void opt_not(struct block *); -static void opt_peep(struct block *); -static void opt_stmt(struct stmt *, int[], int); -static void deadstmt(struct stmt *, struct stmt *[]); -static void opt_deadstores(struct block *); -static struct block *fold_edge(struct block *, struct edge *); -static inline int eq_blk(struct block *, struct block *); -static u_int slength(struct slist *); -static int count_blocks(struct block *); -static void number_blks_r(struct block *); -static u_int count_stmts(struct block *); -static int convert_code_r(struct block *); #ifdef BDEBUG static void opt_dump(struct block *); #endif static int n_blocks; struct block **blocks; static int n_edges; struct edge **edges; /* * A bit vector set representation of the dominators. * We round up the set size to the next power of two. */ static int nodewords; static int edgewords; struct block **levels; bpf_u_int32 *space; #define BITS_PER_WORD (8*sizeof(bpf_u_int32)) /* * True if a is in uset {p} */ #define SET_MEMBER(p, a) \ ((p)[(unsigned)(a) / BITS_PER_WORD] & (1 << ((unsigned)(a) % BITS_PER_WORD))) /* * Add 'a' to uset p. */ #define SET_INSERT(p, a) \ (p)[(unsigned)(a) / BITS_PER_WORD] |= (1 << ((unsigned)(a) % BITS_PER_WORD)) /* * Delete 'a' from uset p. */ #define SET_DELETE(p, a) \ (p)[(unsigned)(a) / BITS_PER_WORD] &= ~(1 << ((unsigned)(a) % BITS_PER_WORD)) /* * a := a intersect b */ #define SET_INTERSECT(a, b, n)\ {\ register bpf_u_int32 *_x = a, *_y = b;\ register int _n = n;\ while (--_n >= 0) *_x++ &= *_y++;\ } /* * a := a - b */ #define SET_SUBTRACT(a, b, n)\ {\ register bpf_u_int32 *_x = a, *_y = b;\ register int _n = n;\ while (--_n >= 0) *_x++ &=~ *_y++;\ } /* * a := a union b */ #define SET_UNION(a, b, n)\ {\ register bpf_u_int32 *_x = a, *_y = b;\ register int _n = n;\ while (--_n >= 0) *_x++ |= *_y++;\ } static uset all_dom_sets; static uset all_closure_sets; static uset all_edge_sets; #ifndef MAX #define MAX(a,b) ((a)>(b)?(a):(b)) #endif static void -find_levels_r(b) - struct block *b; +find_levels_r(struct block *b) { int level; if (isMarked(b)) return; Mark(b); b->link = 0; if (JT(b)) { find_levels_r(JT(b)); find_levels_r(JF(b)); level = MAX(JT(b)->level, JF(b)->level) + 1; } else level = 0; b->level = level; b->link = levels[level]; levels[level] = b; } /* * Level graph. The levels go from 0 at the leaves to * N_LEVELS at the root. The levels[] array points to the * first node of the level list, whose elements are linked * with the 'link' field of the struct block. */ static void -find_levels(root) - struct block *root; +find_levels(struct block *root) { memset((char *)levels, 0, n_blocks * sizeof(*levels)); unMarkAll(); find_levels_r(root); } /* * Find dominator relationships. * Assumes graph has been leveled. */ static void -find_dom(root) - struct block *root; +find_dom(struct block *root) { int i; struct block *b; bpf_u_int32 *x; /* * Initialize sets to contain all nodes. */ x = all_dom_sets; i = n_blocks * nodewords; while (--i >= 0) *x++ = ~0; /* Root starts off empty. */ for (i = nodewords; --i >= 0;) root->dom[i] = 0; /* root->level is the highest level no found. */ for (i = root->level; i >= 0; --i) { for (b = levels[i]; b; b = b->link) { SET_INSERT(b->dom, b->id); if (JT(b) == 0) continue; SET_INTERSECT(JT(b)->dom, b->dom, nodewords); SET_INTERSECT(JF(b)->dom, b->dom, nodewords); } } } static void -propedom(ep) - struct edge *ep; +propedom(struct edge *ep) { SET_INSERT(ep->edom, ep->id); if (ep->succ) { SET_INTERSECT(ep->succ->et.edom, ep->edom, edgewords); SET_INTERSECT(ep->succ->ef.edom, ep->edom, edgewords); } } /* * Compute edge dominators. * Assumes graph has been leveled and predecessors established. */ static void -find_edom(root) - struct block *root; +find_edom(struct block *root) { int i; uset x; struct block *b; x = all_edge_sets; for (i = n_edges * edgewords; --i >= 0; ) x[i] = ~0; /* root->level is the highest level no found. */ memset(root->et.edom, 0, edgewords * sizeof(*(uset)0)); memset(root->ef.edom, 0, edgewords * sizeof(*(uset)0)); for (i = root->level; i >= 0; --i) { for (b = levels[i]; b != 0; b = b->link) { propedom(&b->et); propedom(&b->ef); } } } /* * Find the backwards transitive closure of the flow graph. These sets * are backwards in the sense that we find the set of nodes that reach * a given node, not the set of nodes that can be reached by a node. * * Assumes graph has been leveled. */ static void -find_closure(root) - struct block *root; +find_closure(struct block *root) { int i; struct block *b; /* * Initialize sets to contain no nodes. */ memset((char *)all_closure_sets, 0, n_blocks * nodewords * sizeof(*all_closure_sets)); /* root->level is the highest level no found. */ for (i = root->level; i >= 0; --i) { for (b = levels[i]; b; b = b->link) { SET_INSERT(b->closure, b->id); if (JT(b) == 0) continue; SET_UNION(JT(b)->closure, b->closure, nodewords); SET_UNION(JF(b)->closure, b->closure, nodewords); } } } /* * Return the register number that is used by s. If A and X are both * used, return AX_ATOM. If no register is used, return -1. * * The implementation should probably change to an array access. */ static int -atomuse(s) - struct stmt *s; +atomuse(struct stmt *s) { register int c = s->code; if (c == NOP) return -1; switch (BPF_CLASS(c)) { case BPF_RET: return (BPF_RVAL(c) == BPF_A) ? A_ATOM : (BPF_RVAL(c) == BPF_X) ? X_ATOM : -1; case BPF_LD: case BPF_LDX: return (BPF_MODE(c) == BPF_IND) ? X_ATOM : (BPF_MODE(c) == BPF_MEM) ? s->k : -1; case BPF_ST: return A_ATOM; case BPF_STX: return X_ATOM; case BPF_JMP: case BPF_ALU: if (BPF_SRC(c) == BPF_X) return AX_ATOM; return A_ATOM; case BPF_MISC: return BPF_MISCOP(c) == BPF_TXA ? X_ATOM : A_ATOM; } abort(); /* NOTREACHED */ } /* * Return the register number that is defined by 's'. We assume that * a single stmt cannot define more than one register. If no register * is defined, return -1. * * The implementation should probably change to an array access. */ static int -atomdef(s) - struct stmt *s; +atomdef(struct stmt *s) { if (s->code == NOP) return -1; switch (BPF_CLASS(s->code)) { case BPF_LD: case BPF_ALU: return A_ATOM; case BPF_LDX: return X_ATOM; case BPF_ST: case BPF_STX: return s->k; case BPF_MISC: return BPF_MISCOP(s->code) == BPF_TAX ? X_ATOM : A_ATOM; } return -1; } /* * Compute the sets of registers used, defined, and killed by 'b'. * * "Used" means that a statement in 'b' uses the register before any * statement in 'b' defines it, i.e. it uses the value left in * that register by a predecessor block of this block. * "Defined" means that a statement in 'b' defines it. * "Killed" means that a statement in 'b' defines it before any * statement in 'b' uses it, i.e. it kills the value left in that * register by a predecessor block of this block. */ static void -compute_local_ud(b) - struct block *b; +compute_local_ud(struct block *b) { struct slist *s; atomset def = 0, use = 0, kill = 0; int atom; for (s = b->stmts; s; s = s->next) { if (s->s.code == NOP) continue; atom = atomuse(&s->s); if (atom >= 0) { if (atom == AX_ATOM) { if (!ATOMELEM(def, X_ATOM)) use |= ATOMMASK(X_ATOM); if (!ATOMELEM(def, A_ATOM)) use |= ATOMMASK(A_ATOM); } else if (atom < N_ATOMS) { if (!ATOMELEM(def, atom)) use |= ATOMMASK(atom); } else abort(); } atom = atomdef(&s->s); if (atom >= 0) { if (!ATOMELEM(use, atom)) kill |= ATOMMASK(atom); def |= ATOMMASK(atom); } } if (BPF_CLASS(b->s.code) == BPF_JMP) { /* * XXX - what about RET? */ atom = atomuse(&b->s); if (atom >= 0) { if (atom == AX_ATOM) { if (!ATOMELEM(def, X_ATOM)) use |= ATOMMASK(X_ATOM); if (!ATOMELEM(def, A_ATOM)) use |= ATOMMASK(A_ATOM); } else if (atom < N_ATOMS) { if (!ATOMELEM(def, atom)) use |= ATOMMASK(atom); } else abort(); } } b->def = def; b->kill = kill; b->in_use = use; } /* * Assume graph is already leveled. */ static void -find_ud(root) - struct block *root; +find_ud(struct block *root) { int i, maxlevel; struct block *p; /* * root->level is the highest level no found; * count down from there. */ maxlevel = root->level; for (i = maxlevel; i >= 0; --i) for (p = levels[i]; p; p = p->link) { compute_local_ud(p); p->out_use = 0; } for (i = 1; i <= maxlevel; ++i) { for (p = levels[i]; p; p = p->link) { p->out_use |= JT(p)->in_use | JF(p)->in_use; p->in_use |= p->out_use &~ p->kill; } } } /* * These data structures are used in a Cocke and Shwarz style * value numbering scheme. Since the flowgraph is acyclic, * exit values can be propagated from a node's predecessors * provided it is uniquely defined. */ struct valnode { int code; int v0, v1; int val; struct valnode *next; }; #define MODULUS 213 static struct valnode *hashtbl[MODULUS]; static int curval; static int maxval; /* Integer constants mapped with the load immediate opcode. */ #define K(i) F(BPF_LD|BPF_IMM|BPF_W, i, 0L) struct vmapinfo { int is_const; bpf_int32 const_val; }; struct vmapinfo *vmap; struct valnode *vnode_base; struct valnode *next_vnode; static void -init_val() +init_val(void) { curval = 0; next_vnode = vnode_base; memset((char *)vmap, 0, maxval * sizeof(*vmap)); memset((char *)hashtbl, 0, sizeof hashtbl); } /* Because we really don't have an IR, this stuff is a little messy. */ static int -F(code, v0, v1) - int code; - int v0, v1; +F(int code, int v0, int v1) { u_int hash; int val; struct valnode *p; hash = (u_int)code ^ (v0 << 4) ^ (v1 << 8); hash %= MODULUS; for (p = hashtbl[hash]; p; p = p->next) if (p->code == code && p->v0 == v0 && p->v1 == v1) return p->val; val = ++curval; if (BPF_MODE(code) == BPF_IMM && (BPF_CLASS(code) == BPF_LD || BPF_CLASS(code) == BPF_LDX)) { vmap[val].const_val = v0; vmap[val].is_const = 1; } p = next_vnode++; p->val = val; p->code = code; p->v0 = v0; p->v1 = v1; p->next = hashtbl[hash]; hashtbl[hash] = p; return val; } static inline void -vstore(s, valp, newval, alter) - struct stmt *s; - int *valp; - int newval; - int alter; +vstore(struct stmt *s, int *valp, int newval, int alter) { if (alter && *valp == newval) s->code = NOP; else *valp = newval; } static void -fold_op(s, v0, v1) - struct stmt *s; - int v0, v1; +fold_op(struct stmt *s, int v0, int v1) { bpf_u_int32 a, b; a = vmap[v0].const_val; b = vmap[v1].const_val; switch (BPF_OP(s->code)) { case BPF_ADD: a += b; break; case BPF_SUB: a -= b; break; case BPF_MUL: a *= b; break; case BPF_DIV: if (b == 0) bpf_error("division by zero"); a /= b; break; case BPF_AND: a &= b; break; case BPF_OR: a |= b; break; case BPF_LSH: a <<= b; break; case BPF_RSH: a >>= b; break; case BPF_NEG: a = -a; break; default: abort(); } s->k = a; s->code = BPF_LD|BPF_IMM; done = 0; } static inline struct slist * -this_op(s) - struct slist *s; +this_op(struct slist *s) { while (s != 0 && s->s.code == NOP) s = s->next; return s; } static void -opt_not(b) - struct block *b; +opt_not(struct block *b) { struct block *tmp = JT(b); JT(b) = JF(b); JF(b) = tmp; } static void -opt_peep(b) - struct block *b; +opt_peep(struct block *b) { struct slist *s; struct slist *next, *last; int val; s = b->stmts; if (s == 0) return; last = s; for (/*empty*/; /*empty*/; s = next) { /* * Skip over nops. */ s = this_op(s); if (s == 0) break; /* nothing left in the block */ /* * Find the next real instruction after that one * (skipping nops). */ next = this_op(s->next); if (next == 0) break; /* no next instruction */ last = next; /* * st M[k] --> st M[k] * ldx M[k] tax */ if (s->s.code == BPF_ST && next->s.code == (BPF_LDX|BPF_MEM) && s->s.k == next->s.k) { done = 0; next->s.code = BPF_MISC|BPF_TAX; } /* * ld #k --> ldx #k * tax txa */ if (s->s.code == (BPF_LD|BPF_IMM) && next->s.code == (BPF_MISC|BPF_TAX)) { s->s.code = BPF_LDX|BPF_IMM; next->s.code = BPF_MISC|BPF_TXA; done = 0; } /* * This is an ugly special case, but it happens * when you say tcp[k] or udp[k] where k is a constant. */ if (s->s.code == (BPF_LD|BPF_IMM)) { struct slist *add, *tax, *ild; /* * Check that X isn't used on exit from this * block (which the optimizer might cause). * We know the code generator won't generate * any local dependencies. */ if (ATOMELEM(b->out_use, X_ATOM)) continue; /* * Check that the instruction following the ldi * is an addx, or it's an ldxms with an addx * following it (with 0 or more nops between the * ldxms and addx). */ if (next->s.code != (BPF_LDX|BPF_MSH|BPF_B)) add = next; else add = this_op(next->next); if (add == 0 || add->s.code != (BPF_ALU|BPF_ADD|BPF_X)) continue; /* * Check that a tax follows that (with 0 or more * nops between them). */ tax = this_op(add->next); if (tax == 0 || tax->s.code != (BPF_MISC|BPF_TAX)) continue; /* * Check that an ild follows that (with 0 or more * nops between them). */ ild = this_op(tax->next); if (ild == 0 || BPF_CLASS(ild->s.code) != BPF_LD || BPF_MODE(ild->s.code) != BPF_IND) continue; /* * We want to turn this sequence: * * (004) ldi #0x2 {s} * (005) ldxms [14] {next} -- optional * (006) addx {add} * (007) tax {tax} * (008) ild [x+0] {ild} * * into this sequence: * * (004) nop * (005) ldxms [14] * (006) nop * (007) nop * (008) ild [x+2] * * XXX We need to check that X is not * subsequently used, because we want to change * what'll be in it after this sequence. * * We know we can eliminate the accumulator * modifications earlier in the sequence since * it is defined by the last stmt of this sequence * (i.e., the last statement of the sequence loads * a value into the accumulator, so we can eliminate * earlier operations on the accumulator). */ ild->s.k += s->s.k; s->s.code = NOP; add->s.code = NOP; tax->s.code = NOP; done = 0; } } /* * If the comparison at the end of a block is an equality * comparison against a constant, and nobody uses the value * we leave in the A register at the end of a block, and * the operation preceding the comparison is an arithmetic * operation, we can sometime optimize it away. */ if (b->s.code == (BPF_JMP|BPF_JEQ|BPF_K) && !ATOMELEM(b->out_use, A_ATOM)) { /* * We can optimize away certain subtractions of the * X register. */ if (last->s.code == (BPF_ALU|BPF_SUB|BPF_X)) { val = b->val[X_ATOM]; if (vmap[val].is_const) { /* * If we have a subtract to do a comparison, * and the X register is a known constant, * we can merge this value into the * comparison: * * sub x -> nop * jeq #y jeq #(x+y) */ b->s.k += vmap[val].const_val; last->s.code = NOP; done = 0; } else if (b->s.k == 0) { /* * If the X register isn't a constant, * and the comparison in the test is * against 0, we can compare with the * X register, instead: * * sub x -> nop * jeq #0 jeq x */ last->s.code = NOP; b->s.code = BPF_JMP|BPF_JEQ|BPF_X; done = 0; } } /* * Likewise, a constant subtract can be simplified: * * sub #x -> nop * jeq #y -> jeq #(x+y) */ else if (last->s.code == (BPF_ALU|BPF_SUB|BPF_K)) { last->s.code = NOP; b->s.k += last->s.k; done = 0; } /* * And, similarly, a constant AND can be simplified * if we're testing against 0, i.e.: * * and #k nop * jeq #0 -> jset #k */ else if (last->s.code == (BPF_ALU|BPF_AND|BPF_K) && b->s.k == 0) { b->s.k = last->s.k; b->s.code = BPF_JMP|BPF_K|BPF_JSET; last->s.code = NOP; done = 0; opt_not(b); } } /* * jset #0 -> never * jset #ffffffff -> always */ if (b->s.code == (BPF_JMP|BPF_K|BPF_JSET)) { if (b->s.k == 0) JT(b) = JF(b); if (b->s.k == 0xffffffff) JF(b) = JT(b); } /* * If we're comparing against the index register, and the index * register is a known constant, we can just compare against that * constant. */ val = b->val[X_ATOM]; if (vmap[val].is_const && BPF_SRC(b->s.code) == BPF_X) { bpf_int32 v = vmap[val].const_val; b->s.code &= ~BPF_X; b->s.k = v; } /* * If the accumulator is a known constant, we can compute the * comparison result. */ val = b->val[A_ATOM]; if (vmap[val].is_const && BPF_SRC(b->s.code) == BPF_K) { bpf_int32 v = vmap[val].const_val; switch (BPF_OP(b->s.code)) { case BPF_JEQ: v = v == b->s.k; break; case BPF_JGT: v = (unsigned)v > b->s.k; break; case BPF_JGE: v = (unsigned)v >= b->s.k; break; case BPF_JSET: v &= b->s.k; break; default: abort(); } if (JF(b) != JT(b)) done = 0; if (v) JF(b) = JT(b); else JT(b) = JF(b); } } /* * Compute the symbolic value of expression of 's', and update * anything it defines in the value table 'val'. If 'alter' is true, * do various optimizations. This code would be cleaner if symbolic * evaluation and code transformations weren't folded together. */ static void -opt_stmt(s, val, alter) - struct stmt *s; - int val[]; - int alter; +opt_stmt(struct stmt *s, int val[], int alter) { int op; int v; switch (s->code) { case BPF_LD|BPF_ABS|BPF_W: case BPF_LD|BPF_ABS|BPF_H: case BPF_LD|BPF_ABS|BPF_B: v = F(s->code, s->k, 0L); vstore(s, &val[A_ATOM], v, alter); break; case BPF_LD|BPF_IND|BPF_W: case BPF_LD|BPF_IND|BPF_H: case BPF_LD|BPF_IND|BPF_B: v = val[X_ATOM]; if (alter && vmap[v].is_const) { s->code = BPF_LD|BPF_ABS|BPF_SIZE(s->code); s->k += vmap[v].const_val; v = F(s->code, s->k, 0L); done = 0; } else v = F(s->code, s->k, v); vstore(s, &val[A_ATOM], v, alter); break; case BPF_LD|BPF_LEN: v = F(s->code, 0L, 0L); vstore(s, &val[A_ATOM], v, alter); break; case BPF_LD|BPF_IMM: v = K(s->k); vstore(s, &val[A_ATOM], v, alter); break; case BPF_LDX|BPF_IMM: v = K(s->k); vstore(s, &val[X_ATOM], v, alter); break; case BPF_LDX|BPF_MSH|BPF_B: v = F(s->code, s->k, 0L); vstore(s, &val[X_ATOM], v, alter); break; case BPF_ALU|BPF_NEG: if (alter && vmap[val[A_ATOM]].is_const) { s->code = BPF_LD|BPF_IMM; s->k = -vmap[val[A_ATOM]].const_val; val[A_ATOM] = K(s->k); } else val[A_ATOM] = F(s->code, val[A_ATOM], 0L); break; case BPF_ALU|BPF_ADD|BPF_K: case BPF_ALU|BPF_SUB|BPF_K: case BPF_ALU|BPF_MUL|BPF_K: case BPF_ALU|BPF_DIV|BPF_K: case BPF_ALU|BPF_AND|BPF_K: case BPF_ALU|BPF_OR|BPF_K: case BPF_ALU|BPF_LSH|BPF_K: case BPF_ALU|BPF_RSH|BPF_K: op = BPF_OP(s->code); if (alter) { if (s->k == 0) { /* 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; break; } if (op == BPF_MUL || op == BPF_AND) { s->code = BPF_LD|BPF_IMM; val[A_ATOM] = K(s->k); break; } } if (vmap[val[A_ATOM]].is_const) { fold_op(s, val[A_ATOM], K(s->k)); val[A_ATOM] = K(s->k); break; } } val[A_ATOM] = F(s->code, val[A_ATOM], K(s->k)); break; case BPF_ALU|BPF_ADD|BPF_X: case BPF_ALU|BPF_SUB|BPF_X: case BPF_ALU|BPF_MUL|BPF_X: case BPF_ALU|BPF_DIV|BPF_X: case BPF_ALU|BPF_AND|BPF_X: case BPF_ALU|BPF_OR|BPF_X: case BPF_ALU|BPF_LSH|BPF_X: case BPF_ALU|BPF_RSH|BPF_X: op = BPF_OP(s->code); if (alter && vmap[val[X_ATOM]].is_const) { if (vmap[val[A_ATOM]].is_const) { fold_op(s, val[A_ATOM], val[X_ATOM]); val[A_ATOM] = K(s->k); } else { s->code = BPF_ALU|BPF_K|op; s->k = vmap[val[X_ATOM]].const_val; done = 0; val[A_ATOM] = F(s->code, val[A_ATOM], K(s->k)); } break; } /* * Check if we're doing something to an accumulator * that is 0, and simplify. This may not seem like * much of a simplification but it could open up further * optimizations. * XXX We could also check for mul by 1, etc. */ if (alter && vmap[val[A_ATOM]].is_const && vmap[val[A_ATOM]].const_val == 0) { if (op == BPF_ADD || op == BPF_OR) { s->code = BPF_MISC|BPF_TXA; vstore(s, &val[A_ATOM], val[X_ATOM], alter); break; } else if (op == BPF_MUL || op == BPF_DIV || op == BPF_AND || op == BPF_LSH || op == BPF_RSH) { s->code = BPF_LD|BPF_IMM; s->k = 0; vstore(s, &val[A_ATOM], K(s->k), alter); break; } else if (op == BPF_NEG) { s->code = NOP; break; } } val[A_ATOM] = F(s->code, val[A_ATOM], val[X_ATOM]); break; case BPF_MISC|BPF_TXA: vstore(s, &val[A_ATOM], val[X_ATOM], alter); break; case BPF_LD|BPF_MEM: v = val[s->k]; if (alter && vmap[v].is_const) { s->code = BPF_LD|BPF_IMM; s->k = vmap[v].const_val; done = 0; } vstore(s, &val[A_ATOM], v, alter); break; case BPF_MISC|BPF_TAX: vstore(s, &val[X_ATOM], val[A_ATOM], alter); break; case BPF_LDX|BPF_MEM: v = val[s->k]; if (alter && vmap[v].is_const) { s->code = BPF_LDX|BPF_IMM; s->k = vmap[v].const_val; done = 0; } vstore(s, &val[X_ATOM], v, alter); break; case BPF_ST: vstore(s, &val[s->k], val[A_ATOM], alter); break; case BPF_STX: vstore(s, &val[s->k], val[X_ATOM], alter); break; } } static void -deadstmt(s, last) - register struct stmt *s; - register struct stmt *last[]; +deadstmt(register struct stmt *s, register struct stmt *last[]) { register int atom; atom = atomuse(s); if (atom >= 0) { if (atom == AX_ATOM) { last[X_ATOM] = 0; last[A_ATOM] = 0; } else last[atom] = 0; } atom = atomdef(s); if (atom >= 0) { if (last[atom]) { done = 0; last[atom]->code = NOP; } last[atom] = s; } } static void -opt_deadstores(b) - register struct block *b; +opt_deadstores(register struct block *b) { register struct slist *s; register int atom; struct stmt *last[N_ATOMS]; memset((char *)last, 0, sizeof last); for (s = b->stmts; s != 0; s = s->next) deadstmt(&s->s, last); deadstmt(&b->s, last); for (atom = 0; atom < N_ATOMS; ++atom) if (last[atom] && !ATOMELEM(b->out_use, atom)) { last[atom]->code = NOP; done = 0; } } static void -opt_blk(b, do_stmts) - struct block *b; - int do_stmts; +opt_blk(struct block *b, int do_stmts) { struct slist *s; struct edge *p; int i; bpf_int32 aval, xval; #if 0 for (s = b->stmts; s && s->next; s = s->next) if (BPF_CLASS(s->s.code) == BPF_JMP) { do_stmts = 0; break; } #endif /* * Initialize the atom values. */ p = b->in_edges; if (p == 0) { /* * We have no predecessors, so everything is undefined * upon entry to this block. */ memset((char *)b->val, 0, sizeof(b->val)); } else { /* * Inherit values from our predecessors. * * First, get the values from the predecessor along the * first edge leading to this node. */ memcpy((char *)b->val, (char *)p->pred->val, sizeof(b->val)); /* * Now look at all the other nodes leading to this node. * If, for the predecessor along that edge, a register * has a different value from the one we have (i.e., * control paths are merging, and the merging paths * assign different values to that register), give the * register the undefined value of 0. */ while ((p = p->next) != NULL) { for (i = 0; i < N_ATOMS; ++i) if (b->val[i] != p->pred->val[i]) b->val[i] = 0; } } aval = b->val[A_ATOM]; xval = b->val[X_ATOM]; for (s = b->stmts; s; s = s->next) opt_stmt(&s->s, b->val, do_stmts); /* * This is a special case: if we don't use anything from this * block, and we load the accumulator or index register with a * value that is already there, or if this block is a return, * eliminate all the statements. * * XXX - what if it does a store? * * XXX - why does it matter whether we use anything from this * block? If the accumulator or index register doesn't change * its value, isn't that OK even if we use that value? * * XXX - if we load the accumulator with a different value, * and the block ends with a conditional branch, we obviously * can't eliminate it, as the branch depends on that value. * For the index register, the conditional branch only depends * on the index register value if the test is against the index * register value rather than a constant; if nothing uses the * value we put into the index register, and we're not testing * against the index register's value, and there aren't any * other problems that would keep us from eliminating this * block, can we eliminate it? */ if (do_stmts && ((b->out_use == 0 && aval != 0 && b->val[A_ATOM] == aval && xval != 0 && b->val[X_ATOM] == xval) || BPF_CLASS(b->s.code) == BPF_RET)) { if (b->stmts != 0) { b->stmts = 0; done = 0; } } else { opt_peep(b); opt_deadstores(b); } /* * Set up values for branch optimizer. */ if (BPF_SRC(b->s.code) == BPF_K) b->oval = K(b->s.k); else b->oval = b->val[X_ATOM]; b->et.code = b->s.code; b->ef.code = -b->s.code; } /* * Return true if any register that is used on exit from 'succ', has * an exit value that is different from the corresponding exit value * from 'b'. */ static int -use_conflict(b, succ) - struct block *b, *succ; +use_conflict(struct block *b, struct block *succ) { int atom; atomset use = succ->out_use; if (use == 0) return 0; for (atom = 0; atom < N_ATOMS; ++atom) if (ATOMELEM(use, atom)) if (b->val[atom] != succ->val[atom]) return 1; return 0; } static struct block * -fold_edge(child, ep) - struct block *child; - struct edge *ep; +fold_edge(struct block *child, struct edge *ep) { int sense; int aval0, aval1, oval0, oval1; int code = ep->code; if (code < 0) { code = -code; sense = 0; } else sense = 1; if (child->s.code != code) return 0; aval0 = child->val[A_ATOM]; oval0 = child->oval; aval1 = ep->pred->val[A_ATOM]; oval1 = ep->pred->oval; if (aval0 != aval1) return 0; if (oval0 == oval1) /* * The operands of the branch instructions are * identical, so the result is true if a true * branch was taken to get here, otherwise false. */ return sense ? JT(child) : JF(child); if (sense && code == (BPF_JMP|BPF_JEQ|BPF_K)) /* * At this point, we only know the comparison if we * came down the true branch, and it was an equality * comparison with a constant. * * I.e., if we came down the true branch, and the branch * was an equality comparison with a constant, we know the * accumulator contains that constant. If we came down * the false branch, or the comparison wasn't with a * constant, we don't know what was in the accumulator. * * We rely on the fact that distinct constants have distinct * value numbers. */ return JF(child); return 0; } static void -opt_j(ep) - struct edge *ep; +opt_j(struct edge *ep) { register int i, k; register struct block *target; if (JT(ep->succ) == 0) return; if (JT(ep->succ) == JF(ep->succ)) { /* * Common branch targets can be eliminated, provided * there is no data dependency. */ if (!use_conflict(ep->pred, ep->succ->et.succ)) { done = 0; ep->succ = JT(ep->succ); } } /* * For each edge dominator that matches the successor of this * edge, promote the edge successor to the its grandchild. * * XXX We violate the set abstraction here in favor a reasonably * efficient loop. */ top: for (i = 0; i < edgewords; ++i) { register bpf_u_int32 x = ep->edom[i]; while (x != 0) { k = ffs(x) - 1; x &=~ (1 << k); k += i * BITS_PER_WORD; target = fold_edge(ep->succ, edges[k]); /* * Check that there is no data dependency between * nodes that will be violated if we move the edge. */ if (target != 0 && !use_conflict(ep->pred, target)) { done = 0; ep->succ = target; if (JT(target) != 0) /* * Start over unless we hit a leaf. */ goto top; return; } } } } static void -or_pullup(b) - struct block *b; +or_pullup(struct block *b) { int val, at_top; struct block *pull; struct block **diffp, **samep; struct edge *ep; ep = b->in_edges; if (ep == 0) return; /* * Make sure each predecessor loads the same value. * XXX why? */ val = ep->pred->val[A_ATOM]; for (ep = ep->next; ep != 0; ep = ep->next) if (val != ep->pred->val[A_ATOM]) return; if (JT(b->in_edges->pred) == b) diffp = &JT(b->in_edges->pred); else diffp = &JF(b->in_edges->pred); at_top = 1; while (1) { if (*diffp == 0) return; if (JT(*diffp) != JT(b)) return; if (!SET_MEMBER((*diffp)->dom, b->id)) return; if ((*diffp)->val[A_ATOM] != val) break; diffp = &JF(*diffp); at_top = 0; } samep = &JF(*diffp); while (1) { if (*samep == 0) return; if (JT(*samep) != JT(b)) return; if (!SET_MEMBER((*samep)->dom, b->id)) return; if ((*samep)->val[A_ATOM] == val) break; /* XXX Need to check that there are no data dependencies between dp0 and dp1. Currently, the code generator will not produce such dependencies. */ samep = &JF(*samep); } #ifdef notdef /* XXX This doesn't cover everything. */ for (i = 0; i < N_ATOMS; ++i) if ((*samep)->val[i] != pred->val[i]) return; #endif /* Pull up the node. */ pull = *samep; *samep = JF(pull); JF(pull) = *diffp; /* * At the top of the chain, each predecessor needs to point at the * pulled up node. Inside the chain, there is only one predecessor * to worry about. */ if (at_top) { for (ep = b->in_edges; ep != 0; ep = ep->next) { if (JT(ep->pred) == b) JT(ep->pred) = pull; else JF(ep->pred) = pull; } } else *diffp = pull; done = 0; } static void -and_pullup(b) - struct block *b; +and_pullup(struct block *b) { int val, at_top; struct block *pull; struct block **diffp, **samep; struct edge *ep; ep = b->in_edges; if (ep == 0) return; /* * Make sure each predecessor loads the same value. */ val = ep->pred->val[A_ATOM]; for (ep = ep->next; ep != 0; ep = ep->next) if (val != ep->pred->val[A_ATOM]) return; if (JT(b->in_edges->pred) == b) diffp = &JT(b->in_edges->pred); else diffp = &JF(b->in_edges->pred); at_top = 1; while (1) { if (*diffp == 0) return; if (JF(*diffp) != JF(b)) return; if (!SET_MEMBER((*diffp)->dom, b->id)) return; if ((*diffp)->val[A_ATOM] != val) break; diffp = &JT(*diffp); at_top = 0; } samep = &JT(*diffp); while (1) { if (*samep == 0) return; if (JF(*samep) != JF(b)) return; if (!SET_MEMBER((*samep)->dom, b->id)) return; if ((*samep)->val[A_ATOM] == val) break; /* XXX Need to check that there are no data dependencies between diffp and samep. Currently, the code generator will not produce such dependencies. */ samep = &JT(*samep); } #ifdef notdef /* XXX This doesn't cover everything. */ for (i = 0; i < N_ATOMS; ++i) if ((*samep)->val[i] != pred->val[i]) return; #endif /* Pull up the node. */ pull = *samep; *samep = JT(pull); JT(pull) = *diffp; /* * At the top of the chain, each predecessor needs to point at the * pulled up node. Inside the chain, there is only one predecessor * to worry about. */ if (at_top) { for (ep = b->in_edges; ep != 0; ep = ep->next) { if (JT(ep->pred) == b) JT(ep->pred) = pull; else JF(ep->pred) = pull; } } else *diffp = pull; done = 0; } static void -opt_blks(root, do_stmts) - struct block *root; - int do_stmts; +opt_blks(struct block *root, int do_stmts) { int i, maxlevel; struct block *p; init_val(); maxlevel = root->level; find_inedges(root); for (i = maxlevel; i >= 0; --i) for (p = levels[i]; p; p = p->link) opt_blk(p, do_stmts); if (do_stmts) /* * No point trying to move branches; it can't possibly * make a difference at this point. */ return; for (i = 1; i <= maxlevel; ++i) { for (p = levels[i]; p; p = p->link) { opt_j(&p->et); opt_j(&p->ef); } } find_inedges(root); for (i = 1; i <= maxlevel; ++i) { for (p = levels[i]; p; p = p->link) { or_pullup(p); and_pullup(p); } } } static inline void -link_inedge(parent, child) - struct edge *parent; - struct block *child; +link_inedge(struct edge *parent, struct block *child) { parent->next = child->in_edges; child->in_edges = parent; } static void -find_inedges(root) - struct block *root; +find_inedges(struct block *root) { int i; struct block *b; for (i = 0; i < n_blocks; ++i) blocks[i]->in_edges = 0; /* * Traverse the graph, adding each edge to the predecessor * list of its successors. Skip the leaves (i.e. level 0). */ for (i = root->level; i > 0; --i) { for (b = levels[i]; b != 0; b = b->link) { link_inedge(&b->et, JT(b)); link_inedge(&b->ef, JF(b)); } } } static void -opt_root(b) - struct block **b; +opt_root(struct block **b) { struct slist *tmp, *s; s = (*b)->stmts; (*b)->stmts = 0; while (BPF_CLASS((*b)->s.code) == BPF_JMP && JT(*b) == JF(*b)) *b = JT(*b); tmp = (*b)->stmts; if (tmp != 0) sappend(s, tmp); (*b)->stmts = s; /* * If the root node is a return, then there is no * point executing any statements (since the bpf machine * has no side effects). */ if (BPF_CLASS((*b)->s.code) == BPF_RET) (*b)->stmts = 0; } static void -opt_loop(root, do_stmts) - struct block *root; - int do_stmts; +opt_loop(struct block *root, int do_stmts) { #ifdef BDEBUG if (dflag > 1) { printf("opt_loop(root, %d) begin\n", do_stmts); opt_dump(root); } #endif do { done = 1; find_levels(root); find_dom(root); find_closure(root); find_ud(root); find_edom(root); opt_blks(root, do_stmts); #ifdef BDEBUG if (dflag > 1) { printf("opt_loop(root, %d) bottom, done=%d\n", do_stmts, done); opt_dump(root); } #endif } while (!done); } /* * Optimize the filter code in its dag representation. */ void -bpf_optimize(rootp) - struct block **rootp; +bpf_optimize(struct block **rootp) { struct block *root; root = *rootp; opt_init(root); 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(); } static void -make_marks(p) - struct block *p; +make_marks(struct block *p) { if (!isMarked(p)) { Mark(p); if (BPF_CLASS(p->s.code) != BPF_RET) { make_marks(JT(p)); make_marks(JF(p)); } } } /* * Mark code array such that isMarked(i) is true * only for nodes that are alive. */ static void -mark_code(p) - struct block *p; +mark_code(struct block *p) { cur_mark += 1; make_marks(p); } /* * True iff the two stmt lists load the same value from the packet into * the accumulator. */ static int -eq_slist(x, y) - struct slist *x, *y; +eq_slist(struct slist *x, struct slist *y) { while (1) { while (x && x->s.code == NOP) x = x->next; while (y && y->s.code == NOP) y = y->next; if (x == 0) return y == 0; if (y == 0) return x == 0; if (x->s.code != y->s.code || x->s.k != y->s.k) return 0; x = x->next; y = y->next; } } static inline int -eq_blk(b0, b1) - struct block *b0, *b1; +eq_blk(struct block *b0, struct block *b1) { if (b0->s.code == b1->s.code && b0->s.k == b1->s.k && b0->et.succ == b1->et.succ && b0->ef.succ == b1->ef.succ) return eq_slist(b0->stmts, b1->stmts); return 0; } static void -intern_blocks(root) - struct block *root; +intern_blocks(struct block *root) { struct block *p; int i, j; int done1; /* don't shadow global */ top: done1 = 1; for (i = 0; i < n_blocks; ++i) blocks[i]->link = 0; mark_code(root); for (i = n_blocks - 1; --i >= 0; ) { if (!isMarked(blocks[i])) continue; for (j = i + 1; j < n_blocks; ++j) { if (!isMarked(blocks[j])) continue; if (eq_blk(blocks[i], blocks[j])) { blocks[i]->link = blocks[j]->link ? blocks[j]->link : blocks[j]; break; } } } for (i = 0; i < n_blocks; ++i) { p = blocks[i]; if (JT(p) == 0) continue; if (JT(p)->link) { done1 = 0; JT(p) = JT(p)->link; } if (JF(p)->link) { done1 = 0; JF(p) = JF(p)->link; } } if (!done1) goto top; } static void -opt_cleanup() +opt_cleanup(void) { free((void *)vnode_base); free((void *)vmap); free((void *)edges); free((void *)space); free((void *)levels); free((void *)blocks); } /* * Return the number of stmts in 's'. */ static u_int -slength(s) - struct slist *s; +slength(struct slist *s) { u_int n = 0; for (; s; s = s->next) if (s->s.code != NOP) ++n; return n; } /* * Return the number of nodes reachable by 'p'. * All nodes should be initially unmarked. */ static int -count_blocks(p) - struct block *p; +count_blocks(struct block *p) { if (p == 0 || isMarked(p)) return 0; Mark(p); return count_blocks(JT(p)) + count_blocks(JF(p)) + 1; } /* * Do a depth first search on the flow graph, numbering the * the basic blocks, and entering them into the 'blocks' array.` */ static void -number_blks_r(p) - struct block *p; +number_blks_r(struct block *p) { int n; if (p == 0 || isMarked(p)) return; Mark(p); n = n_blocks++; p->id = n; blocks[n] = p; number_blks_r(JT(p)); number_blks_r(JF(p)); } /* * Return the number of stmts in the flowgraph reachable by 'p'. * The nodes should be unmarked before calling. * * Note that "stmts" means "instructions", and that this includes * * side-effect statements in 'p' (slength(p->stmts)); * * statements in the true branch from 'p' (count_stmts(JT(p))); * * statements in the false branch from 'p' (count_stmts(JF(p))); * * the conditional jump itself (1); * * an extra long jump if the true branch requires it (p->longjt); * * an extra long jump if the false branch requires it (p->longjf). */ static u_int -count_stmts(p) - struct block *p; +count_stmts(struct block *p) { u_int n; if (p == 0 || isMarked(p)) return 0; Mark(p); n = count_stmts(JT(p)) + count_stmts(JF(p)); return slength(p->stmts) + n + 1 + p->longjt + p->longjf; } /* * Allocate memory. All allocation is done before optimization * is begun. A linear bound on the size of all data structures is computed * from the total number of blocks and/or statements. */ static void -opt_init(root) - struct block *root; +opt_init(struct block *root) { bpf_u_int32 *p; int i, n, max_stmts; /* * First, count the blocks, so we can malloc an array to map * block number to block. Then, put the blocks into the array. */ unMarkAll(); n = count_blocks(root); blocks = (struct block **)calloc(n, sizeof(*blocks)); if (blocks == NULL) bpf_error("malloc"); unMarkAll(); n_blocks = 0; number_blks_r(root); n_edges = 2 * n_blocks; edges = (struct edge **)calloc(n_edges, sizeof(*edges)); if (edges == NULL) bpf_error("malloc"); /* * The number of levels is bounded by the number of nodes. */ levels = (struct block **)calloc(n_blocks, sizeof(*levels)); if (levels == NULL) bpf_error("malloc"); edgewords = n_edges / (8 * sizeof(bpf_u_int32)) + 1; nodewords = n_blocks / (8 * sizeof(bpf_u_int32)) + 1; /* XXX */ space = (bpf_u_int32 *)malloc(2 * n_blocks * nodewords * sizeof(*space) + n_edges * edgewords * sizeof(*space)); if (space == NULL) bpf_error("malloc"); p = space; all_dom_sets = p; for (i = 0; i < n; ++i) { blocks[i]->dom = p; p += nodewords; } all_closure_sets = p; for (i = 0; i < n; ++i) { blocks[i]->closure = p; p += nodewords; } all_edge_sets = p; for (i = 0; i < n; ++i) { register struct block *b = blocks[i]; b->et.edom = p; p += edgewords; b->ef.edom = p; p += edgewords; b->et.id = i; edges[i] = &b->et; b->ef.id = n_blocks + i; edges[n_blocks + i] = &b->ef; b->et.pred = b; b->ef.pred = b; } max_stmts = 0; for (i = 0; i < n; ++i) max_stmts += slength(blocks[i]->stmts) + 1; /* * We allocate at most 3 value numbers per statement, * so this is an upper bound on the number of valnodes * we'll need. */ maxval = 3 * max_stmts; vmap = (struct vmapinfo *)calloc(maxval, sizeof(*vmap)); vnode_base = (struct valnode *)calloc(maxval, sizeof(*vnode_base)); if (vmap == NULL || vnode_base == NULL) bpf_error("malloc"); } /* * Some pointers used to convert the basic block form of the code, * into the array form that BPF requires. 'fstart' will point to * the malloc'd array while 'ftail' is used during the recursive traversal. */ static struct bpf_insn *fstart; static struct bpf_insn *ftail; #ifdef BDEBUG int bids[1000]; #endif /* * Returns true if successful. Returns false if a branch has * an offset that is too large. If so, we have marked that * branch so that on a subsequent iteration, it will be treated * properly. */ static int -convert_code_r(p) - struct block *p; +convert_code_r(struct block *p) { struct bpf_insn *dst; struct slist *src; int slen; u_int off; int extrajmps; /* number of extra jumps inserted */ struct slist **offset = NULL; if (p == 0 || isMarked(p)) return (1); Mark(p); if (convert_code_r(JF(p)) == 0) return (0); if (convert_code_r(JT(p)) == 0) return (0); slen = slength(p->stmts); dst = ftail -= (slen + 1 + p->longjt + p->longjf); /* inflate length by any extra jumps */ p->offset = dst - fstart; /* generate offset[] for convenience */ if (slen) { offset = (struct slist **)calloc(slen, sizeof(struct slist *)); if (!offset) { bpf_error("not enough core"); /*NOTREACHED*/ } } src = p->stmts; for (off = 0; off < slen && src; off++) { #if 0 printf("off=%d src=%x\n", off, src); #endif offset[off] = src; src = src->next; } off = 0; for (src = p->stmts; src; src = src->next) { if (src->s.code == NOP) continue; dst->code = (u_short)src->s.code; dst->k = src->s.k; /* fill block-local relative jump */ if (BPF_CLASS(src->s.code) != BPF_JMP || src->s.code == (BPF_JMP|BPF_JA)) { #if 0 if (src->s.jt || src->s.jf) { bpf_error("illegal jmp destination"); /*NOTREACHED*/ } #endif goto filled; } if (off == slen - 2) /*???*/ goto filled; { int i; int jt, jf; const char *ljerr = "%s for block-local relative jump: off=%d"; #if 0 printf("code=%x off=%d %x %x\n", src->s.code, off, src->s.jt, src->s.jf); #endif if (!src->s.jt || !src->s.jf) { bpf_error(ljerr, "no jmp destination", off); /*NOTREACHED*/ } jt = jf = 0; for (i = 0; i < slen; i++) { if (offset[i] == src->s.jt) { if (jt) { bpf_error(ljerr, "multiple matches", off); /*NOTREACHED*/ } dst->jt = i - off - 1; jt++; } if (offset[i] == src->s.jf) { if (jf) { bpf_error(ljerr, "multiple matches", off); /*NOTREACHED*/ } dst->jf = i - off - 1; jf++; } } if (!jt || !jf) { bpf_error(ljerr, "no destination found", off); /*NOTREACHED*/ } } filled: ++dst; ++off; } if (offset) free(offset); #ifdef BDEBUG bids[dst - fstart] = p->id + 1; #endif dst->code = (u_short)p->s.code; dst->k = p->s.k; if (JT(p)) { extrajmps = 0; off = JT(p)->offset - (p->offset + slen) - 1; if (off >= 256) { /* offset too large for branch, must add a jump */ if (p->longjt == 0) { /* mark this instruction and retry */ p->longjt++; return(0); } /* branch if T to following jump */ dst->jt = extrajmps; extrajmps++; dst[extrajmps].code = BPF_JMP|BPF_JA; dst[extrajmps].k = off - extrajmps; } else dst->jt = off; off = JF(p)->offset - (p->offset + slen) - 1; if (off >= 256) { /* offset too large for branch, must add a jump */ if (p->longjf == 0) { /* mark this instruction and retry */ p->longjf++; return(0); } /* branch if F to following jump */ /* if two jumps are inserted, F goes to second one */ dst->jf = extrajmps; extrajmps++; dst[extrajmps].code = BPF_JMP|BPF_JA; dst[extrajmps].k = off - extrajmps; } else dst->jf = off; } return (1); } /* * Convert flowgraph intermediate representation to the * BPF array representation. Set *lenp to the number of instructions. * * This routine does *NOT* leak the memory pointed to by fp. It *must * not* do free(fp) before returning fp; doing so would make no sense, * as the BPF array pointed to by the return value of icode_to_fcode() * must be valid - it's being returned for use in a bpf_program structure. * * If it appears that icode_to_fcode() is leaking, the problem is that * the program using pcap_compile() is failing to free the memory in * the BPF program when it's done - the leak is in the program, not in * the routine that happens to be allocating the memory. (By analogy, if * a program calls fopen() without ever calling fclose() on the FILE *, * it will leak the FILE structure; the leak is not in fopen(), it's in * the program.) Change the program to use pcap_freecode() when it's * done with the filter program. See the pcap man page. */ struct bpf_insn * -icode_to_fcode(root, lenp) - struct block *root; - u_int *lenp; +icode_to_fcode(struct block *root, u_int *lenp) { u_int n; struct bpf_insn *fp; /* * Loop doing convert_code_r() until no branches remain * with too-large offsets. */ while (1) { unMarkAll(); n = *lenp = count_stmts(root); fp = (struct bpf_insn *)malloc(sizeof(*fp) * n); if (fp == NULL) bpf_error("malloc"); memset((char *)fp, 0, sizeof(*fp) * n); fstart = fp; ftail = fp + n; unMarkAll(); if (convert_code_r(root)) break; free(fp); } return fp; } /* * Make a copy of a BPF program and put it in the "fcode" member of * a "pcap_t". * * If we fail to allocate memory for the copy, fill in the "errbuf" * member of the "pcap_t" with an error message, and return -1; * otherwise, return 0. */ int install_bpf_program(pcap_t *p, struct bpf_program *fp) { size_t prog_size; /* * Validate the program. */ if (!bpf_validate(fp->bf_insns, fp->bf_len)) { snprintf(p->errbuf, sizeof(p->errbuf), "BPF program is not valid"); return (-1); } /* * Free up any already installed program. */ pcap_freecode(&p->fcode); prog_size = sizeof(*fp->bf_insns) * fp->bf_len; p->fcode.bf_len = fp->bf_len; p->fcode.bf_insns = (struct bpf_insn *)malloc(prog_size); if (p->fcode.bf_insns == NULL) { snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", pcap_strerror(errno)); return (-1); } memcpy(p->fcode.bf_insns, fp->bf_insns, prog_size); return (0); } #ifdef BDEBUG static void -opt_dump(root) - struct block *root; +opt_dump(struct block *root) { struct bpf_program f; memset(bids, 0, sizeof bids); f.bf_insns = icode_to_fcode(root, &f.bf_len); bpf_dump(&f, 1); putchar('\n'); free((char *)f.bf_insns); } #endif Index: stable/9/contrib/libpcap/pcap/bpf.h =================================================================== --- stable/9/contrib/libpcap/pcap/bpf.h (revision 252280) +++ stable/9/contrib/libpcap/pcap/bpf.h (revision 252281) @@ -1,1289 +1,1303 @@ /*- * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 * The Regents of the University of California. All rights reserved. * * This code is derived from the Stanford/CMU enet packet filter, * (net/enet.c) distributed as part of 4.3BSD, and code contributed * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence * Berkeley Laboratory. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)bpf.h 7.1 (Berkeley) 5/7/91 * * @(#) $Header: /tcpdump/master/libpcap/pcap/bpf.h,v 1.32 2008-12-23 20:13:29 guy Exp $ (LBL) */ /* * This is libpcap's cut-down version of bpf.h; it includes only * the stuff needed for the code generator and the userland BPF * interpreter, and the libpcap APIs for setting filters, etc.. * * "pcap-bpf.c" will include the native OS version, as it deals with * the OS's BPF implementation. * * At least two programs found by Google Code Search explicitly includes * (even though / includes it for you), * so moving that stuff to would break the build for some * programs. */ /* * If we've already included , don't re-define this stuff. * We assume BSD-style multiple-include protection in , * which is true of all but the oldest versions of FreeBSD and NetBSD, * or Tru64 UNIX-style multiple-include protection (or, at least, * Tru64 UNIX 5.x-style; I don't have earlier versions available to check), * or AIX-style multiple-include protection (or, at least, AIX 5.x-style; * I don't have earlier versions available to check). * * We do not check for BPF_MAJOR_VERSION, as that's defined by * , which is directly or indirectly included in some * programs that also include pcap.h, and doesn't * define stuff we need. * * This also provides our own multiple-include protection. */ #if !defined(_NET_BPF_H_) && !defined(_BPF_H_) && !defined(_H_BPF) && !defined(lib_pcap_bpf_h) #define lib_pcap_bpf_h #ifdef __cplusplus extern "C" { #endif /* BSD style release date */ #define BPF_RELEASE 199606 #ifdef MSDOS /* must be 32-bit */ typedef long bpf_int32; typedef unsigned long bpf_u_int32; #else typedef int bpf_int32; typedef u_int bpf_u_int32; #endif /* * Alignment macros. BPF_WORDALIGN rounds up to the next * even multiple of BPF_ALIGNMENT. * * Tcpdump's print-pflog.c uses this, so we define it here. */ #ifndef __NetBSD__ #define BPF_ALIGNMENT sizeof(bpf_int32) #else #define BPF_ALIGNMENT sizeof(long) #endif #define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1)) /* * Structure for "pcap_compile()", "pcap_setfilter()", etc.. */ struct bpf_program { u_int bf_len; struct bpf_insn *bf_insns; }; /* * Link-layer header type codes. * * Do *NOT* add new values to this list without asking * "tcpdump-workers@lists.tcpdump.org" for a value. Otherwise, you run * the risk of using a value that's already being used for some other * purpose, and of having tools that read libpcap-format captures not * being able to handle captures with your new DLT_ value, with no hope * that they will ever be changed to do so (as that would destroy their * ability to read captures using that value for that other purpose). * * See * * http://www.tcpdump.org/linktypes.html * * for detailed descriptions of some of these link-layer header types. */ /* * These are the types that are the same on all platforms, and that * have been defined by for ages. */ #define DLT_NULL 0 /* BSD loopback encapsulation */ #define DLT_EN10MB 1 /* Ethernet (10Mb) */ #define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */ #define DLT_AX25 3 /* Amateur Radio AX.25 */ #define DLT_PRONET 4 /* Proteon ProNET Token Ring */ #define DLT_CHAOS 5 /* Chaos */ #define DLT_IEEE802 6 /* 802.5 Token Ring */ #define DLT_ARCNET 7 /* ARCNET, with BSD-style header */ #define DLT_SLIP 8 /* Serial Line IP */ #define DLT_PPP 9 /* Point-to-point Protocol */ #define DLT_FDDI 10 /* FDDI */ /* * These are types that are different on some platforms, and that * have been defined by for ages. We use #ifdefs to * detect the BSDs that define them differently from the traditional * libpcap * * XXX - DLT_ATM_RFC1483 is 13 in BSD/OS, and DLT_RAW is 14 in BSD/OS, * but I don't know what the right #define is for BSD/OS. */ #define DLT_ATM_RFC1483 11 /* LLC-encapsulated ATM */ #ifdef __OpenBSD__ #define DLT_RAW 14 /* raw IP */ #else #define DLT_RAW 12 /* raw IP */ #endif /* * Given that the only OS that currently generates BSD/OS SLIP or PPP * is, well, BSD/OS, arguably everybody should have chosen its values * for DLT_SLIP_BSDOS and DLT_PPP_BSDOS, which are 15 and 16, but they * didn't. So it goes. */ #if defined(__NetBSD__) || defined(__FreeBSD__) #ifndef DLT_SLIP_BSDOS #define DLT_SLIP_BSDOS 13 /* BSD/OS Serial Line IP */ #define DLT_PPP_BSDOS 14 /* BSD/OS Point-to-point Protocol */ #endif #else #define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */ #define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */ #endif /* * 17 was used for DLT_PFLOG in OpenBSD; it no longer is. * * It was DLT_LANE8023 in SuSE 6.3, so we defined LINKTYPE_PFLOG * as 117 so that pflog captures would use a link-layer header type * value that didn't collide with any other values. On all * platforms other than OpenBSD, we defined DLT_PFLOG as 117, * and we mapped between LINKTYPE_PFLOG and DLT_PFLOG. * * OpenBSD eventually switched to using 117 for DLT_PFLOG as well. * * Don't use 17 for anything else. */ /* * 18 is used for DLT_PFSYNC in OpenBSD, NetBSD, DragonFly BSD and * Mac OS X; don't use it for anything else. (FreeBSD uses 121, * which collides with DLT_HHDLC, even though it doesn't use 18 * for anything and doesn't appear to have ever used it for anything.) * * We define it as 18 on those platforms; it is, unfortunately, used * for DLT_CIP in Suse 6.3, so we don't define it as DLT_PFSYNC * in general. As the packet format for it, like that for * DLT_PFLOG, is not only OS-dependent but OS-version-dependent, * we don't support printing it in tcpdump except on OSes that * have the relevant header files, so it's not that useful on * other platforms. */ #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__APPLE__) #define DLT_PFSYNC 18 #endif #define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */ /* * Apparently Redback uses this for its SmartEdge 400/800. I hope * nobody else decided to use it, too. */ #define DLT_REDBACK_SMARTEDGE 32 /* * These values are defined by NetBSD; other platforms should refrain from * using them for other purposes, so that NetBSD savefiles with link * types of 50 or 51 can be read as this type on all platforms. */ #define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */ #define DLT_PPP_ETHER 51 /* PPP over Ethernet */ /* * The Axent Raptor firewall - now the Symantec Enterprise Firewall - uses * a link-layer type of 99 for the tcpdump it supplies. The link-layer * header has 6 bytes of unknown data, something that appears to be an * Ethernet type, and 36 bytes that appear to be 0 in at least one capture * I've seen. */ #define DLT_SYMANTEC_FIREWALL 99 /* * Values between 100 and 103 are used in capture file headers as * link-layer header type LINKTYPE_ values corresponding to DLT_ types * that differ between platforms; don't use those values for new DLT_ * new types. */ /* * Values starting with 104 are used for newly-assigned link-layer * header type values; for those link-layer header types, the DLT_ * value returned by pcap_datalink() and passed to pcap_open_dead(), * and the LINKTYPE_ value that appears in capture files, are the * same. * * DLT_MATCHING_MIN is the lowest such value; DLT_MATCHING_MAX is * the highest such value. */ #define DLT_MATCHING_MIN 104 /* * This value was defined by libpcap 0.5; platforms that have defined * it with a different value should define it here with that value - * a link type of 104 in a save file will be mapped to DLT_C_HDLC, * whatever value that happens to be, so programs will correctly * handle files with that link type regardless of the value of * DLT_C_HDLC. * * The name DLT_C_HDLC was used by BSD/OS; we use that name for source * compatibility with programs written for BSD/OS. * * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well, * for source compatibility with programs written for libpcap 0.5. */ #define DLT_C_HDLC 104 /* Cisco HDLC */ #define DLT_CHDLC DLT_C_HDLC #define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */ /* * 106 is reserved for Linux Classical IP over ATM; it's like DLT_RAW, * except when it isn't. (I.e., sometimes it's just raw IP, and * sometimes it isn't.) We currently handle it as DLT_LINUX_SLL, * so that we don't have to worry about the link-layer header.) */ /* * Frame Relay; BSD/OS has a DLT_FR with a value of 11, but that collides * with other values. * DLT_FR and DLT_FRELAY packets start with the Q.922 Frame Relay header * (DLCI, etc.). */ #define DLT_FRELAY 107 /* * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except * that the AF_ type in the link-layer header is in network byte order. * * DLT_LOOP is 12 in OpenBSD, but that's DLT_RAW in other OSes, so * we don't use 12 for it in OSes other than OpenBSD. */ #ifdef __OpenBSD__ #define DLT_LOOP 12 #else #define DLT_LOOP 108 #endif /* * Encapsulated packets for IPsec; DLT_ENC is 13 in OpenBSD, but that's * DLT_SLIP_BSDOS in NetBSD, so we don't use 13 for it in OSes other * than OpenBSD. */ #ifdef __OpenBSD__ #define DLT_ENC 13 #else #define DLT_ENC 109 #endif /* * Values between 110 and 112 are reserved for use 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_ types * other than the corresponding DLT_ types. */ /* * This is for Linux cooked sockets. */ #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 /* * OpenBSD DLT_PFLOG. */ #define DLT_PFLOG 117 /* * Registered for Cisco-internal use. */ #define DLT_CISCO_IOS 118 /* * 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 /* * Sigh. * * This was reserved for Siemens HiPath HDLC on 2002-01-25, as * requested by Tomas Kukosa. * * On 2004-02-25, a FreeBSD checkin to sys/net/bpf.h was made that * assigned 121 as DLT_PFSYNC. Its libpcap does DLT_ <-> LINKTYPE_ * mapping, so it probably supports capturing on the pfsync device * but not saving the captured data to a pcap file. * * OpenBSD, from which pf came, however, uses 18 for DLT_PFSYNC; * their libpcap does no DLT_ <-> LINKTYPE_ mapping, so it would * use 18 in pcap files as well. * * NetBSD and DragonFly BSD also use 18 for DLT_PFSYNC; their * libpcaps do DLT_ <-> LINKTYPE_ mapping, and neither has an entry * for DLT_PFSYNC, so it might not be able to write out dump files * with 18 as the link-layer header type. (Earlier versions might * not have done mapping, in which case they'd work the same way * OpenBSD does.) * * Mac OS X defines it as 18, but doesn't appear to use it as of * Mac OS X 10.7.3. Its libpcap does DLT_ <-> LINKTYPE_ mapping. * * We'll define DLT_PFSYNC as 121 on FreeBSD and define it as 18 on * all other platforms. We'll define DLT_HHDLC as 121 on everything * except for FreeBSD; anybody who wants to compile, on FreeBSD, code * that uses DLT_HHDLC is out of luck. * * We'll define LINKTYPE_PFSYNC as 18, *even on FreeBSD*, and map * it, so that savefiles won't use 121 for PFSYNC - they'll all * use 18. Code that uses pcap_datalink() to determine the link-layer * header type of a savefile won't, when built and run on FreeBSD, * be able to distinguish between LINKTYPE_PFSYNC and LINKTYPE_HHDLC * capture files; code that doesn't, such as the code in Wireshark, * will be able to distinguish between them. */ #ifdef __FreeBSD__ #define DLT_PFSYNC 121 #else #define DLT_HHDLC 121 #endif /* * This is for RFC 2625 IP-over-Fibre Channel. * * This is not for use with raw Fibre Channel, where the link-layer * header starts with a Fibre Channel frame header; it's for IP-over-FC, * where the link-layer header starts with an RFC 2625 Network_Header * field. */ #define DLT_IP_OVER_FC 122 /* * This is for Full Frontal ATM on Solaris with SunATM, with a * pseudo-header followed by an AALn PDU. * * There may be other forms of Full Frontal ATM on other OSes, * with different pseudo-headers. * * If ATM software returns a pseudo-header with VPI/VCI information * (and, ideally, packet type information, e.g. signalling, ILMI, * LANE, LLC-multiplexed traffic, etc.), it should not use * DLT_ATM_RFC1483, but should get a new DLT_ value, so tcpdump * and the like don't have to infer the presence or absence of a * pseudo-header and the form of the pseudo-header. */ #define DLT_SUNATM 123 /* Solaris+SunATM */ /* * Reserved as per request from Kent Dahlgren * for private use. */ #define DLT_RIO 124 /* RapidIO */ #define DLT_PCI_EXP 125 /* PCI Express */ #define DLT_AURORA 126 /* Xilinx Aurora link layer */ /* * Header for 802.11 plus a number of bits of link-layer information * including radio information, used by some recent BSD drivers as * well as the madwifi Atheros driver for Linux. */ #define DLT_IEEE802_11_RADIO 127 /* 802.11 plus radiotap radio header */ /* * Reserved for the TZSP encapsulation, as per request from * Chris Waters * TZSP is a generic encapsulation for any other link type, * which includes a means to include meta-information * with the packet, e.g. signal strength and channel * for 802.11 packets. */ #define DLT_TZSP 128 /* Tazmen Sniffer Protocol */ /* * BSD's ARCNET headers have the source host, destination host, * and type at the beginning of the packet; that's what's handed * up to userland via BPF. * * Linux's ARCNET headers, however, have a 2-byte offset field * between the host IDs and the type; that's what's handed up * to userland via PF_PACKET sockets. * * We therefore have to have separate DLT_ values for them. */ #define DLT_ARCNET_LINUX 129 /* ARCNET */ /* * Juniper-private data link types, as per request from * Hannes Gredler . The DLT_s are used * for passing on chassis-internal metainformation such as * QOS profiles, etc.. */ #define DLT_JUNIPER_MLPPP 130 #define DLT_JUNIPER_MLFR 131 #define DLT_JUNIPER_ES 132 #define DLT_JUNIPER_GGSN 133 #define DLT_JUNIPER_MFR 134 #define DLT_JUNIPER_ATM2 135 #define DLT_JUNIPER_SERVICES 136 #define DLT_JUNIPER_ATM1 137 /* * Apple IP-over-IEEE 1394, as per a request from Dieter Siegmund * . The header that's presented is an Ethernet-like * header: * * #define FIREWIRE_EUI64_LEN 8 * struct firewire_header { * u_char firewire_dhost[FIREWIRE_EUI64_LEN]; * u_char firewire_shost[FIREWIRE_EUI64_LEN]; * u_short firewire_type; * }; * * with "firewire_type" being an Ethernet type value, rather than, * for example, raw GASP frames being handed up. */ #define DLT_APPLE_IP_OVER_IEEE1394 138 /* * Various SS7 encapsulations, as per a request from Jeff Morriss * and subsequent discussions. */ #define DLT_MTP2_WITH_PHDR 139 /* pseudo-header with various info, followed by MTP2 */ #define DLT_MTP2 140 /* MTP2, without pseudo-header */ #define DLT_MTP3 141 /* MTP3, without pseudo-header or MTP2 */ #define DLT_SCCP 142 /* SCCP, without pseudo-header or MTP2 or MTP3 */ /* * DOCSIS MAC frames. */ #define DLT_DOCSIS 143 /* * Linux-IrDA packets. Protocol defined at http://www.irda.org. * Those packets include IrLAP headers and above (IrLMP...), but * don't include Phy framing (SOF/EOF/CRC & byte stuffing), because Phy * framing can be handled by the hardware and depend on the bitrate. * This is exactly the format you would get capturing on a Linux-IrDA * interface (irdaX), but not on a raw serial port. * Note the capture is done in "Linux-cooked" mode, so each packet include * a fake packet header (struct sll_header). This is because IrDA packet * decoding is dependant on the direction of the packet (incomming or * outgoing). * When/if other platform implement IrDA capture, we may revisit the * issue and define a real DLT_IRDA... * Jean II */ #define DLT_LINUX_IRDA 144 /* * Reserved for IBM SP switch and IBM Next Federation switch. */ #define DLT_IBM_SP 145 #define DLT_IBM_SN 146 /* * Reserved for private use. If you have some link-layer header type * that you want to use within your organization, with the capture files * using that link-layer header type not ever be sent outside your * organization, you can use these values. * * No libpcap release will use these for any purpose, nor will any * tcpdump release use them, either. * * Do *NOT* use these in capture files that you expect anybody not using * your private versions of capture-file-reading tools to read; in * particular, do *NOT* use them in products, otherwise you may find that * people won't be able to use tcpdump, or snort, or Ethereal, or... to * read capture files from your firewall/intrusion detection/traffic * monitoring/etc. appliance, or whatever product uses that DLT_ value, * and you may also find that the developers of those applications will * not accept patches to let them read those files. * * Also, do not use them if somebody might send you a capture using them * for *their* private type and tools using them for *your* private type * would have to read them. * * Instead, ask "tcpdump-workers@lists.tcpdump.org" for a new DLT_ value, * as per the comment above, and use the type you're given. */ #define DLT_USER0 147 #define DLT_USER1 148 #define DLT_USER2 149 #define DLT_USER3 150 #define DLT_USER4 151 #define DLT_USER5 152 #define DLT_USER6 153 #define DLT_USER7 154 #define DLT_USER8 155 #define DLT_USER9 156 #define DLT_USER10 157 #define DLT_USER11 158 #define DLT_USER12 159 #define DLT_USER13 160 #define DLT_USER14 161 #define DLT_USER15 162 /* * For future use with 802.11 captures - defined by AbsoluteValue * Systems to store a number of bits of link-layer information * including radio information: * * http://www.shaftnet.org/~pizza/software/capturefrm.txt * * but it might be used by some non-AVS drivers now or in the * future. */ #define DLT_IEEE802_11_RADIO_AVS 163 /* 802.11 plus AVS radio header */ /* * Juniper-private data link type, as per request from * Hannes Gredler . The DLT_s are used * for passing on chassis-internal metainformation such as * QOS profiles, etc.. */ #define DLT_JUNIPER_MONITOR 164 /* * BACnet MS/TP frames. */ #define DLT_BACNET_MS_TP 165 /* * Another PPP variant as per request from Karsten Keil . * * This is used in some OSes to allow a kernel socket filter to distinguish * between incoming and outgoing packets, on a socket intended to * supply pppd with outgoing packets so it can do dial-on-demand and * hangup-on-lack-of-demand; incoming packets are filtered out so they * don't cause pppd to hold the connection up (you don't want random * input packets such as port scans, packets from old lost connections, * etc. to force the connection to stay up). * * The first byte of the PPP header (0xff03) is modified to accomodate * the direction - 0x00 = IN, 0x01 = OUT. */ #define DLT_PPP_PPPD 166 /* * Names for backwards compatibility with older versions of some PPP * software; new software should use DLT_PPP_PPPD. */ #define DLT_PPP_WITH_DIRECTION DLT_PPP_PPPD #define DLT_LINUX_PPP_WITHDIRECTION DLT_PPP_PPPD /* * Juniper-private data link type, as per request from * Hannes Gredler . The DLT_s are used * for passing on chassis-internal metainformation such as * QOS profiles, cookies, etc.. */ #define DLT_JUNIPER_PPPOE 167 #define DLT_JUNIPER_PPPOE_ATM 168 #define DLT_GPRS_LLC 169 /* GPRS LLC */ #define DLT_GPF_T 170 /* GPF-T (ITU-T G.7041/Y.1303) */ #define DLT_GPF_F 171 /* GPF-F (ITU-T G.7041/Y.1303) */ /* * Requested by Oolan Zimmer for use in Gcom's T1/E1 line * monitoring equipment. */ #define DLT_GCOM_T1E1 172 #define DLT_GCOM_SERIAL 173 /* * Juniper-private data link type, as per request from * Hannes Gredler . The DLT_ is used * for internal communication to Physical Interface Cards (PIC) */ #define DLT_JUNIPER_PIC_PEER 174 /* * Link types requested by Gregor Maier of Endace * Measurement Systems. They add an ERF header (see * http://www.endace.com/support/EndaceRecordFormat.pdf) in front of * the link-layer header. */ #define DLT_ERF_ETH 175 /* Ethernet */ #define DLT_ERF_POS 176 /* Packet-over-SONET */ /* * Requested by Daniele Orlandi for raw LAPD * for vISDN (http://www.orlandi.com/visdn/). Its link-layer header * includes additional information before the LAPD header, so it's * not necessarily a generic LAPD header. */ #define DLT_LINUX_LAPD 177 /* * Juniper-private data link type, as per request from * Hannes Gredler . * The DLT_ are used for prepending meta-information * like interface index, interface name * before standard Ethernet, PPP, Frelay & C-HDLC Frames */ #define DLT_JUNIPER_ETHER 178 #define DLT_JUNIPER_PPP 179 #define DLT_JUNIPER_FRELAY 180 #define DLT_JUNIPER_CHDLC 181 /* * Multi Link Frame Relay (FRF.16) */ #define DLT_MFR 182 /* * Juniper-private data link type, as per request from * Hannes Gredler . * The DLT_ is used for internal communication with a * voice Adapter Card (PIC) */ #define DLT_JUNIPER_VP 183 /* * Arinc 429 frames. * DLT_ requested by Gianluca Varenni . * Every frame contains a 32bit A429 label. * More documentation on Arinc 429 can be found at * http://www.condoreng.com/support/downloads/tutorials/ARINCTutorial.pdf */ #define DLT_A429 184 /* * Arinc 653 Interpartition Communication messages. * DLT_ requested by Gianluca Varenni . * Please refer to the A653-1 standard for more information. */ #define DLT_A653_ICM 185 /* * USB packets, beginning with a USB setup header; requested by * Paolo Abeni . */ #define DLT_USB 186 /* * Bluetooth HCI UART transport layer (part H:4); requested by * Paolo Abeni. */ #define DLT_BLUETOOTH_HCI_H4 187 /* * IEEE 802.16 MAC Common Part Sublayer; requested by Maria Cruz * . */ #define DLT_IEEE802_16_MAC_CPS 188 /* * USB packets, beginning with a Linux USB header; requested by * Paolo Abeni . */ #define DLT_USB_LINUX 189 /* * Controller Area Network (CAN) v. 2.0B packets. * DLT_ requested by Gianluca Varenni . * Used to dump CAN packets coming from a CAN Vector board. * More documentation on the CAN v2.0B frames can be found at * http://www.can-cia.org/downloads/?269 */ #define DLT_CAN20B 190 /* * IEEE 802.15.4, with address fields padded, as is done by Linux * drivers; requested by Juergen Schimmer. */ #define DLT_IEEE802_15_4_LINUX 191 /* * Per Packet Information encapsulated packets. * DLT_ requested by Gianluca Varenni . */ #define DLT_PPI 192 /* * Header for 802.16 MAC Common Part Sublayer plus a radiotap radio header; * requested by Charles Clancy. */ #define DLT_IEEE802_16_MAC_CPS_RADIO 193 /* * Juniper-private data link type, as per request from * Hannes Gredler . * The DLT_ is used for internal communication with a * integrated service module (ISM). */ #define DLT_JUNIPER_ISM 194 /* * IEEE 802.15.4, exactly as it appears in the spec (no padding, no * nothing); requested by Mikko Saarnivala . * For this one, we expect the FCS to be present at the end of the frame; * if the frame has no FCS, DLT_IEEE802_15_4_NOFCS should be used. */ #define DLT_IEEE802_15_4 195 /* * Various link-layer types, with a pseudo-header, for SITA * (http://www.sita.aero/); requested by Fulko Hew (fulko.hew@gmail.com). */ #define DLT_SITA 196 /* * Various link-layer types, with a pseudo-header, for Endace DAG cards; * encapsulates Endace ERF records. Requested by Stephen Donnelly * . */ #define DLT_ERF 197 /* * Special header prepended to Ethernet packets when capturing from a * u10 Networks board. Requested by Phil Mulholland * . */ #define DLT_RAIF1 198 /* * IPMB packet for IPMI, beginning with the I2C slave address, followed * by the netFn and LUN, etc.. Requested by Chanthy Toeung * . */ #define DLT_IPMB 199 /* * Juniper-private data link type, as per request from * Hannes Gredler . * The DLT_ is used for capturing data on a secure tunnel interface. */ #define DLT_JUNIPER_ST 200 /* * Bluetooth HCI UART transport layer (part H:4), with pseudo-header * that includes direction information; requested by Paolo Abeni. */ #define DLT_BLUETOOTH_HCI_H4_WITH_PHDR 201 /* * AX.25 packet with a 1-byte KISS header; see * * http://www.ax25.net/kiss.htm * * as per Richard Stearn . */ #define DLT_AX25_KISS 202 /* * LAPD packets from an ISDN channel, starting with the address field, * with no pseudo-header. * Requested by Varuna De Silva . */ #define DLT_LAPD 203 /* * Variants of various link-layer headers, with a one-byte direction * pseudo-header prepended - zero means "received by this host", * non-zero (any non-zero value) means "sent by this host" - as per * Will Barker . */ #define DLT_PPP_WITH_DIR 204 /* PPP - don't confuse with DLT_PPP_WITH_DIRECTION */ #define DLT_C_HDLC_WITH_DIR 205 /* Cisco HDLC */ #define DLT_FRELAY_WITH_DIR 206 /* Frame Relay */ #define DLT_LAPB_WITH_DIR 207 /* LAPB */ /* * 208 is reserved for an as-yet-unspecified proprietary link-layer * type, as requested by Will Barker. */ /* * IPMB with a Linux-specific pseudo-header; as requested by Alexey Neyman * . */ #define DLT_IPMB_LINUX 209 /* * FlexRay automotive bus - http://www.flexray.com/ - as requested * by Hannes Kaelber . */ #define DLT_FLEXRAY 210 /* * Media Oriented Systems Transport (MOST) bus for multimedia * transport - http://www.mostcooperation.com/ - as requested * by Hannes Kaelber . */ #define DLT_MOST 211 /* * Local Interconnect Network (LIN) bus for vehicle networks - * http://www.lin-subbus.org/ - as requested by Hannes Kaelber * . */ #define DLT_LIN 212 /* * X2E-private data link type used for serial line capture, * as requested by Hannes Kaelber . */ #define DLT_X2E_SERIAL 213 /* * X2E-private data link type used for the Xoraya data logger * family, as requested by Hannes Kaelber . */ #define DLT_X2E_XORAYA 214 /* * IEEE 802.15.4, exactly as it appears in the spec (no padding, no * nothing), but with the PHY-level data for non-ASK PHYs (4 octets * of 0 as preamble, one octet of SFD, one octet of frame length+ * reserved bit, and then the MAC-layer data, starting with the * frame control field). * * Requested by Max Filippov . */ #define DLT_IEEE802_15_4_NONASK_PHY 215 /* * David Gibson requested this for * captures from the Linux kernel /dev/input/eventN devices. This * is used to communicate keystrokes and mouse movements from the * Linux kernel to display systems, such as Xorg. */ #define DLT_LINUX_EVDEV 216 /* * GSM Um and Abis interfaces, preceded by a "gsmtap" header. * * Requested by Harald Welte . */ #define DLT_GSMTAP_UM 217 #define DLT_GSMTAP_ABIS 218 /* * MPLS, with an MPLS label as the link-layer header. * Requested by Michele Marchetto on behalf * of OpenBSD. */ #define DLT_MPLS 219 /* * USB packets, beginning with a Linux USB header, with the USB header * padded to 64 bytes; required for memory-mapped access. */ #define DLT_USB_LINUX_MMAPPED 220 /* * DECT packets, with a pseudo-header; requested by * Matthias Wenzel . */ #define DLT_DECT 221 /* * From: "Lidwa, Eric (GSFC-582.0)[SGT INC]" * Date: Mon, 11 May 2009 11:18:30 -0500 * * DLT_AOS. We need it for AOS Space Data Link Protocol. * I have already written dissectors for but need an OK from * legal before I can submit a patch. * */ #define DLT_AOS 222 /* * Wireless HART (Highway Addressable Remote Transducer) * From the HART Communication Foundation * IES/PAS 62591 * * Requested by Sam Roberts . */ #define DLT_WIHART 223 /* * Fibre Channel FC-2 frames, beginning with a Frame_Header. * Requested by Kahou Lei . */ #define DLT_FC_2 224 /* * Fibre Channel FC-2 frames, beginning with an encoding of the * SOF, and ending with an encoding of the EOF. * * The encodings represent the frame delimiters as 4-byte sequences * representing the corresponding ordered sets, with K28.5 * represented as 0xBC, and the D symbols as the corresponding * byte values; for example, SOFi2, which is K28.5 - D21.5 - D1.2 - D21.2, * is represented as 0xBC 0xB5 0x55 0x55. * * Requested by Kahou Lei . */ #define DLT_FC_2_WITH_FRAME_DELIMS 225 /* * Solaris ipnet pseudo-header; requested by Darren Reed . * * The pseudo-header starts with a one-byte version number; for version 2, * the pseudo-header is: * * struct dl_ipnetinfo { * u_int8_t dli_version; * u_int8_t dli_family; * u_int16_t dli_htype; * u_int32_t dli_pktlen; * u_int32_t dli_ifindex; * u_int32_t dli_grifindex; * u_int32_t dli_zsrc; * u_int32_t dli_zdst; * }; * * dli_version is 2 for the current version of the pseudo-header. * * dli_family is a Solaris address family value, so it's 2 for IPv4 * and 26 for IPv6. * * dli_htype is a "hook type" - 0 for incoming packets, 1 for outgoing * packets, and 2 for packets arriving from another zone on the same * machine. * * dli_pktlen is the length of the packet data following the pseudo-header * (so the captured length minus dli_pktlen is the length of the * pseudo-header, assuming the entire pseudo-header was captured). * * dli_ifindex is the interface index of the interface on which the * packet arrived. * * dli_grifindex is the group interface index number (for IPMP interfaces). * * dli_zsrc is the zone identifier for the source of the packet. * * dli_zdst is the zone identifier for the destination of the packet. * * A zone number of 0 is the global zone; a zone number of 0xffffffff * means that the packet arrived from another host on the network, not * from another zone on the same machine. * * An IPv4 or IPv6 datagram follows the pseudo-header; dli_family indicates * which of those it is. */ #define DLT_IPNET 226 /* * CAN (Controller Area Network) frames, with a pseudo-header as supplied * by Linux SocketCAN. See Documentation/networking/can.txt in the Linux * source. * * Requested by Felix Obenhuber . */ #define DLT_CAN_SOCKETCAN 227 /* * Raw IPv4/IPv6; different from DLT_RAW in that the DLT_ value specifies * whether it's v4 or v6. Requested by Darren Reed . */ #define DLT_IPV4 228 #define DLT_IPV6 229 /* * IEEE 802.15.4, exactly as it appears in the spec (no padding, no * nothing), and with no FCS at the end of the frame; requested by * Jon Smirl . */ #define DLT_IEEE802_15_4_NOFCS 230 /* * Raw D-Bus: * * http://www.freedesktop.org/wiki/Software/dbus * * messages: * * http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages * * starting with the endianness flag, followed by the message type, etc., * but without the authentication handshake before the message sequence: * * http://dbus.freedesktop.org/doc/dbus-specification.html#auth-protocol * * Requested by Martin Vidner . */ #define DLT_DBUS 231 /* * Juniper-private data link type, as per request from * Hannes Gredler . */ #define DLT_JUNIPER_VS 232 #define DLT_JUNIPER_SRX_E2E 233 #define DLT_JUNIPER_FIBRECHANNEL 234 /* * DVB-CI (DVB Common Interface for communication between a PC Card * module and a DVB receiver). See * * http://www.kaiser.cx/pcap-dvbci.html * * for the specification. * * Requested by Martin Kaiser . */ #define DLT_DVB_CI 235 /* * Variant of 3GPP TS 27.010 multiplexing protocol (similar to, but * *not* the same as, 27.010). Requested by Hans-Christoph Schemmel * . */ #define DLT_MUX27010 236 /* * STANAG 5066 D_PDUs. Requested by M. Baris Demiray * . */ #define DLT_STANAG_5066_D_PDU 237 /* * Juniper-private data link type, as per request from * Hannes Gredler . */ #define DLT_JUNIPER_ATM_CEMIC 238 /* * NetFilter LOG messages * (payload of netlink NFNL_SUBSYS_ULOG/NFULNL_MSG_PACKET packets) * * Requested by Jakub Zawadzki */ #define DLT_NFLOG 239 /* * Hilscher Gesellschaft fuer Systemautomation mbH link-layer type * for Ethernet packets with a 4-byte pseudo-header and always * with the payload including the FCS, as supplied by their * netANALYZER hardware and software. * * Requested by Holger P. Frommer */ #define DLT_NETANALYZER 240 /* * Hilscher Gesellschaft fuer Systemautomation mbH link-layer type * for Ethernet packets with a 4-byte pseudo-header and FCS and * with the Ethernet header preceded by 7 bytes of preamble and * 1 byte of SFD, as supplied by their netANALYZER hardware and * software. * * Requested by Holger P. Frommer */ #define DLT_NETANALYZER_TRANSPARENT 241 /* - * IP-over-Infiniband, as specified by RFC 4391. + * IP-over-InfiniBand, as specified by RFC 4391. * * Requested by Petr Sumbera . */ #define DLT_IPOIB 242 /* * MPEG-2 transport stream (ISO 13818-1/ITU-T H.222.0). * * Requested by Guy Martin . */ #define DLT_MPEG_2_TS 243 /* * ng4T GmbH's UMTS Iub/Iur-over-ATM and Iub/Iur-over-IP format as * used by their ng40 protocol tester. * * Requested by Jens Grimmer . */ #define DLT_NG40 244 /* * Pseudo-header giving adapter number and flags, followed by an NFC * (Near-Field Communications) Logical Link Control Protocol (LLCP) PDU, * as specified by NFC Forum Logical Link Control Protocol Technical * Specification LLCP 1.1. * * Requested by Mike Wakerly . */ #define DLT_NFC_LLCP 245 /* * 245 is used as LINKTYPE_PFSYNC; do not use it for any other purpose. * * DLT_PFSYNC has different values on different platforms, and all of * them collide with something used elsewhere. On platforms that * don't already define it, define it as 245. */ #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__DragonFly__) && !defined(__APPLE__) #define DLT_PFSYNC 246 #endif -#define DLT_MATCHING_MAX 246 /* highest value in the "matching" range */ +/* + * Raw InfiniBand packets, starting with the Local Routing Header. + * + * Requested by Oren Kladnitsky . + */ +#define DLT_INFINIBAND 247 + +/* + * SCTP, with no lower-level protocols (i.e., no IPv4 or IPv6). + * + * Requested by Michael Tuexen . + */ +#define DLT_SCTP 248 + +#define DLT_MATCHING_MAX 248 /* highest value in the "matching" range */ /* * DLT and savefile link type values are split into a class and * a member of that class. A class value of 0 indicates a regular * DLT_/LINKTYPE_ value. */ #define DLT_CLASS(x) ((x) & 0x03ff0000) /* * NetBSD-specific generic "raw" link type. The class value indicates * that this is the generic raw type, and the lower 16 bits are the * address family we're dealing with. Those values are NetBSD-specific; * do not assume that they correspond to AF_ values for your operating * system. */ #define DLT_CLASS_NETBSD_RAWAF 0x02240000 #define DLT_NETBSD_RAWAF(af) (DLT_CLASS_NETBSD_RAWAF | (af)) #define DLT_NETBSD_RAWAF_AF(x) ((x) & 0x0000ffff) #define DLT_IS_NETBSD_RAWAF(x) (DLT_CLASS(x) == DLT_CLASS_NETBSD_RAWAF) /* * The instruction encodings. */ /* instruction classes */ #define BPF_CLASS(code) ((code) & 0x07) #define BPF_LD 0x00 #define BPF_LDX 0x01 #define BPF_ST 0x02 #define BPF_STX 0x03 #define BPF_ALU 0x04 #define BPF_JMP 0x05 #define BPF_RET 0x06 #define BPF_MISC 0x07 /* ld/ldx fields */ #define BPF_SIZE(code) ((code) & 0x18) #define BPF_W 0x00 #define BPF_H 0x08 #define BPF_B 0x10 #define BPF_MODE(code) ((code) & 0xe0) #define BPF_IMM 0x00 #define BPF_ABS 0x20 #define BPF_IND 0x40 #define BPF_MEM 0x60 #define BPF_LEN 0x80 #define BPF_MSH 0xa0 /* alu/jmp fields */ #define BPF_OP(code) ((code) & 0xf0) #define BPF_ADD 0x00 #define BPF_SUB 0x10 #define BPF_MUL 0x20 #define BPF_DIV 0x30 #define BPF_OR 0x40 #define BPF_AND 0x50 #define BPF_LSH 0x60 #define BPF_RSH 0x70 #define BPF_NEG 0x80 #define BPF_JA 0x00 #define BPF_JEQ 0x10 #define BPF_JGT 0x20 #define BPF_JGE 0x30 #define BPF_JSET 0x40 #define BPF_SRC(code) ((code) & 0x08) #define BPF_K 0x00 #define BPF_X 0x08 /* ret - BPF_K and BPF_X also apply */ #define BPF_RVAL(code) ((code) & 0x18) #define BPF_A 0x10 /* misc */ #define BPF_MISCOP(code) ((code) & 0xf8) #define BPF_TAX 0x00 #define BPF_TXA 0x80 /* * The instruction data structure. */ struct bpf_insn { u_short code; u_char jt; u_char jf; bpf_u_int32 k; }; /* * Macros for insn array initializers. */ #define BPF_STMT(code, k) { (u_short)(code), 0, 0, k } #define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k } #if __STDC__ || defined(__cplusplus) extern int bpf_validate(const struct bpf_insn *, int); extern u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int); #else extern int bpf_validate(); extern u_int bpf_filter(); #endif /* * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST). */ #define BPF_MEMWORDS 16 #ifdef __cplusplus } #endif #endif /* !defined(_NET_BPF_H_) && !defined(_BPF_H_) && !defined(_H_BPF) && !defined(lib_pcap_bpf_h) */ Index: stable/9/contrib/libpcap/pcap/pcap.h =================================================================== --- stable/9/contrib/libpcap/pcap/pcap.h (revision 252280) +++ stable/9/contrib/libpcap/pcap/pcap.h (revision 252281) @@ -1,460 +1,461 @@ /* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ /* * Copyright (c) 1993, 1994, 1995, 1996, 1997 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Computer Systems * Engineering Group at Lawrence Berkeley Laboratory. * 4. Neither the name of the University nor of the Laboratory may be used * to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#) $Header: /tcpdump/master/libpcap/pcap/pcap.h,v 1.15 2008-10-06 15:27:32 gianluca Exp $ (LBL) */ #ifndef lib_pcap_pcap_h #define lib_pcap_pcap_h #if defined(WIN32) #include #elif defined(MSDOS) #include #include /* u_int, u_char etc. */ #else /* UN*X */ #include #include #endif /* WIN32/MSDOS/UN*X */ #include #include #ifdef __cplusplus extern "C" { #endif /* * Version number of the current version of the pcap file format. * * NOTE: this is *NOT* the version number of the libpcap library. * To fetch the version information for the version of libpcap * you're using, use pcap_lib_version(). */ #define PCAP_VERSION_MAJOR 2 #define PCAP_VERSION_MINOR 4 #define PCAP_ERRBUF_SIZE 256 /* * Compatibility for systems that have a bpf.h that * predates the bpf typedefs for 64-bit support. */ #if BPF_RELEASE - 0 < 199406 typedef int bpf_int32; typedef u_int bpf_u_int32; #endif typedef struct pcap pcap_t; typedef struct pcap_dumper pcap_dumper_t; typedef struct pcap_if pcap_if_t; typedef struct pcap_addr pcap_addr_t; /* * The first record in the file contains saved values for some * of the flags used in the printout phases of tcpdump. * Many fields here are 32 bit ints so compilers won't insert unwanted * padding; these files need to be interchangeable across architectures. * * Do not change the layout of this structure, in any way (this includes * changes that only affect the length of fields in this structure). * * Also, do not change the interpretation of any of the members of this * structure, in any way (this includes using values other than * LINKTYPE_ values, as defined in "savefile.c", in the "linktype" * field). * * Instead: * * introduce a new structure for the new format, if the layout * of the structure changed; * * send mail to "tcpdump-workers@lists.tcpdump.org", requesting * a new magic number for your new capture file format, and, when * you get the new magic number, put it in "savefile.c"; * * use that magic number for save files with the changed file * header; * * make the code in "savefile.c" capable of reading files with * the old file header as well as files with the new file header * (using the magic number to determine the header format). * - * Then supply the changes as a patch at + * Then supply the changes by forking the branch at * - * http://sourceforge.net/projects/libpcap/ + * https://github.com/mcr/libpcap/issues * - * so that future versions of libpcap and programs that use it (such as - * tcpdump) will be able to read your new capture file format. + * and issuing a pull request, so that future versions of libpcap and + * programs that use it (such as tcpdump) will be able to read your new + * capture file format. */ struct pcap_file_header { bpf_u_int32 magic; u_short version_major; u_short version_minor; bpf_int32 thiszone; /* gmt to local correction */ bpf_u_int32 sigfigs; /* accuracy of timestamps */ bpf_u_int32 snaplen; /* max length saved portion of each pkt */ bpf_u_int32 linktype; /* data link type (LINKTYPE_*) */ }; /* * Macros for the value returned by pcap_datalink_ext(). * * If LT_FCS_LENGTH_PRESENT(x) is true, the LT_FCS_LENGTH(x) macro * gives the FCS length of packets in the capture. */ #define LT_FCS_LENGTH_PRESENT(x) ((x) & 0x04000000) #define LT_FCS_LENGTH(x) (((x) & 0xF0000000) >> 28) #define LT_FCS_DATALINK_EXT(x) ((((x) & 0xF) << 28) | 0x04000000) typedef enum { PCAP_D_INOUT = 0, PCAP_D_IN, PCAP_D_OUT } pcap_direction_t; /* * Generic per-packet information, as supplied by libpcap. * * The time stamp can and should be a "struct timeval", regardless of * whether your system supports 32-bit tv_sec in "struct timeval", * 64-bit tv_sec in "struct timeval", or both if it supports both 32-bit * and 64-bit applications. The on-disk format of savefiles uses 32-bit * tv_sec (and tv_usec); this structure is irrelevant to that. 32-bit * and 64-bit versions of libpcap, even if they're on the same platform, * should supply the appropriate version of "struct timeval", even if * that's not what the underlying packet capture mechanism supplies. */ struct pcap_pkthdr { struct timeval ts; /* time stamp */ bpf_u_int32 caplen; /* length of portion present */ bpf_u_int32 len; /* length this packet (off wire) */ }; /* * As returned by the pcap_stats() */ struct pcap_stat { u_int ps_recv; /* number of packets received */ u_int ps_drop; /* number of packets dropped */ u_int ps_ifdrop; /* drops by interface -- only supported on some platforms */ #ifdef WIN32 u_int bs_capt; /* number of packets that reach the application */ #endif /* WIN32 */ }; #ifdef MSDOS /* * As returned by the pcap_stats_ex() */ struct pcap_stat_ex { u_long rx_packets; /* total packets received */ u_long tx_packets; /* total packets transmitted */ u_long rx_bytes; /* total bytes received */ u_long tx_bytes; /* total bytes transmitted */ u_long rx_errors; /* bad packets received */ u_long tx_errors; /* packet transmit problems */ u_long rx_dropped; /* no space in Rx buffers */ u_long tx_dropped; /* no space available for Tx */ u_long multicast; /* multicast packets received */ u_long collisions; /* detailed rx_errors: */ u_long rx_length_errors; u_long rx_over_errors; /* receiver ring buff overflow */ u_long rx_crc_errors; /* recv'd pkt with crc error */ u_long rx_frame_errors; /* recv'd frame alignment error */ u_long rx_fifo_errors; /* recv'r fifo overrun */ u_long rx_missed_errors; /* recv'r missed packet */ /* detailed tx_errors */ u_long tx_aborted_errors; u_long tx_carrier_errors; u_long tx_fifo_errors; u_long tx_heartbeat_errors; u_long tx_window_errors; }; #endif /* * Item in a list of interfaces. */ struct pcap_if { struct pcap_if *next; char *name; /* name to hand to "pcap_open_live()" */ char *description; /* textual description of interface, or NULL */ struct pcap_addr *addresses; bpf_u_int32 flags; /* PCAP_IF_ interface flags */ }; #define PCAP_IF_LOOPBACK 0x00000001 /* interface is loopback */ /* * Representation of an interface address. */ struct pcap_addr { struct pcap_addr *next; struct sockaddr *addr; /* address */ struct sockaddr *netmask; /* netmask for that address */ struct sockaddr *broadaddr; /* broadcast address for that address */ struct sockaddr *dstaddr; /* P2P destination address for that address */ }; typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *, const u_char *); /* * Error codes for the pcap API. * These will all be negative, so you can check for the success or * failure of a call that returns these codes by checking for a * negative value. */ #define PCAP_ERROR -1 /* generic error code */ #define PCAP_ERROR_BREAK -2 /* loop terminated by pcap_breakloop */ #define PCAP_ERROR_NOT_ACTIVATED -3 /* the capture needs to be activated */ #define PCAP_ERROR_ACTIVATED -4 /* the operation can't be performed on already activated captures */ #define PCAP_ERROR_NO_SUCH_DEVICE -5 /* no such device exists */ #define PCAP_ERROR_RFMON_NOTSUP -6 /* this device doesn't support rfmon (monitor) mode */ #define PCAP_ERROR_NOT_RFMON -7 /* operation supported only in monitor mode */ #define PCAP_ERROR_PERM_DENIED -8 /* no permission to open the device */ #define PCAP_ERROR_IFACE_NOT_UP -9 /* interface isn't up */ #define PCAP_ERROR_CANTSET_TSTAMP_TYPE -10 /* this device doesn't support setting the time stamp type */ #define PCAP_ERROR_PROMISC_PERM_DENIED -11 /* you don't have permission to capture in promiscuous mode */ /* * Warning codes for the pcap API. * These will all be positive and non-zero, so they won't look like * errors. */ #define PCAP_WARNING 1 /* generic warning code */ #define PCAP_WARNING_PROMISC_NOTSUP 2 /* this device doesn't support promiscuous mode */ #define PCAP_WARNING_TSTAMP_TYPE_NOTSUP 3 /* the requested time stamp type is not supported */ /* * Value to pass to pcap_compile() as the netmask if you don't know what * the netmask is. */ #define PCAP_NETMASK_UNKNOWN 0xffffffff char *pcap_lookupdev(char *); int pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *); pcap_t *pcap_create(const char *, char *); int pcap_set_snaplen(pcap_t *, int); int pcap_set_promisc(pcap_t *, int); int pcap_can_set_rfmon(pcap_t *); int pcap_set_rfmon(pcap_t *, int); int pcap_set_timeout(pcap_t *, int); int pcap_set_tstamp_type(pcap_t *, int); int pcap_set_buffer_size(pcap_t *, int); int pcap_activate(pcap_t *); int pcap_list_tstamp_types(pcap_t *, int **); void pcap_free_tstamp_types(int *); int pcap_tstamp_type_name_to_val(const char *); const char *pcap_tstamp_type_val_to_name(int); const char *pcap_tstamp_type_val_to_description(int); /* * Time stamp types. * Not all systems and interfaces will necessarily support all of these. * * A system that supports PCAP_TSTAMP_HOST is offering time stamps * provided by the host machine, rather than by the capture device, * but not committing to any characteristics of the time stamp; * it will not offer any of the PCAP_TSTAMP_HOST_ subtypes. * * PCAP_TSTAMP_HOST_LOWPREC is a time stamp, provided by the host machine, * that's low-precision but relatively cheap to fetch; it's normally done * using the system clock, so it's normally synchronized with times you'd * fetch from system calls. * * PCAP_TSTAMP_HOST_HIPREC is a time stamp, provided by the host machine, * that's high-precision; it might be more expensive to fetch. It might * or might not be synchronized with the system clock, and might have * problems with time stamps for packets received on different CPUs, * depending on the platform. * * PCAP_TSTAMP_ADAPTER is a high-precision time stamp supplied by the * capture device; it's synchronized with the system clock. * * PCAP_TSTAMP_ADAPTER_UNSYNCED is a high-precision time stamp supplied by * the capture device; it's not synchronized with the system clock. * * Note that time stamps synchronized with the system clock can go * backwards, as the system clock can go backwards. If a clock is * not in sync with the system clock, that could be because the * system clock isn't keeping accurate time, because the other * clock isn't keeping accurate time, or both. * * Note that host-provided time stamps generally correspond to the * time when the time-stamping code sees the packet; this could * be some unknown amount of time after the first or last bit of * the packet is received by the network adapter, due to batching * of interrupts for packet arrival, queueing delays, etc.. */ #define PCAP_TSTAMP_HOST 0 /* host-provided, unknown characteristics */ #define PCAP_TSTAMP_HOST_LOWPREC 1 /* host-provided, low precision */ #define PCAP_TSTAMP_HOST_HIPREC 2 /* host-provided, high precision */ #define PCAP_TSTAMP_ADAPTER 3 /* device-provided, synced with the system clock */ #define PCAP_TSTAMP_ADAPTER_UNSYNCED 4 /* device-provided, not synced with the system clock */ pcap_t *pcap_open_live(const char *, int, int, int, char *); pcap_t *pcap_open_dead(int, int); pcap_t *pcap_open_offline(const char *, char *); #if defined(WIN32) pcap_t *pcap_hopen_offline(intptr_t, char *); #if !defined(LIBPCAP_EXPORTS) #define pcap_fopen_offline(f,b) \ pcap_hopen_offline(_get_osfhandle(_fileno(f)), b) #else /*LIBPCAP_EXPORTS*/ static pcap_t *pcap_fopen_offline(FILE *, char *); #endif #else /*WIN32*/ pcap_t *pcap_fopen_offline(FILE *, char *); #endif /*WIN32*/ void pcap_close(pcap_t *); int pcap_loop(pcap_t *, int, pcap_handler, u_char *); int pcap_dispatch(pcap_t *, int, pcap_handler, u_char *); const u_char* pcap_next(pcap_t *, struct pcap_pkthdr *); int pcap_next_ex(pcap_t *, struct pcap_pkthdr **, const u_char **); void pcap_breakloop(pcap_t *); int pcap_stats(pcap_t *, struct pcap_stat *); int pcap_setfilter(pcap_t *, struct bpf_program *); int pcap_setdirection(pcap_t *, pcap_direction_t); int pcap_getnonblock(pcap_t *, char *); int pcap_setnonblock(pcap_t *, int, char *); int pcap_inject(pcap_t *, const void *, size_t); int pcap_sendpacket(pcap_t *, const u_char *, int); const char *pcap_statustostr(int); const char *pcap_strerror(int); char *pcap_geterr(pcap_t *); void pcap_perror(pcap_t *, char *); int pcap_compile(pcap_t *, struct bpf_program *, const char *, int, bpf_u_int32); int pcap_compile_nopcap(int, int, struct bpf_program *, const char *, int, bpf_u_int32); void pcap_freecode(struct bpf_program *); -int pcap_offline_filter(struct bpf_program *, const struct pcap_pkthdr *, - const u_char *); +int pcap_offline_filter(const struct bpf_program *, + const struct pcap_pkthdr *, const u_char *); int pcap_datalink(pcap_t *); int pcap_datalink_ext(pcap_t *); int pcap_list_datalinks(pcap_t *, int **); int pcap_set_datalink(pcap_t *, int); void pcap_free_datalinks(int *); int pcap_datalink_name_to_val(const char *); const char *pcap_datalink_val_to_name(int); const char *pcap_datalink_val_to_description(int); int pcap_snapshot(pcap_t *); int pcap_is_swapped(pcap_t *); int pcap_major_version(pcap_t *); int pcap_minor_version(pcap_t *); /* XXX */ FILE *pcap_file(pcap_t *); int pcap_fileno(pcap_t *); pcap_dumper_t *pcap_dump_open(pcap_t *, const char *); pcap_dumper_t *pcap_dump_fopen(pcap_t *, FILE *fp); FILE *pcap_dump_file(pcap_dumper_t *); long pcap_dump_ftell(pcap_dumper_t *); int pcap_dump_flush(pcap_dumper_t *); void pcap_dump_close(pcap_dumper_t *); void pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *); int pcap_findalldevs(pcap_if_t **, char *); void pcap_freealldevs(pcap_if_t *); const char *pcap_lib_version(void); /* * On at least some versions of NetBSD, we don't want to declare * bpf_filter() here, as it's also be declared in , with a * different signature, but, on other BSD-flavored UN*Xes, it's not * declared in , so we *do* want to declare it here, so it's * declared when we build pcap-bpf.c. */ #ifndef __NetBSD__ u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int); #endif int bpf_validate(const struct bpf_insn *f, int len); char *bpf_image(struct bpf_insn *, int); void bpf_dump(struct bpf_program *, int); #if defined(WIN32) /* * Win32 definitions */ int pcap_setbuff(pcap_t *p, int dim); int pcap_setmode(pcap_t *p, int mode); int pcap_setmintocopy(pcap_t *p, int size); #ifdef WPCAP /* Include file with the wpcap-specific extensions */ #include #endif /* WPCAP */ #define MODE_CAPT 0 #define MODE_STAT 1 #define MODE_MON 2 #elif defined(MSDOS) /* * MS-DOS definitions */ int pcap_stats_ex (pcap_t *, struct pcap_stat_ex *); void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait); u_long pcap_mac_packets (void); #else /* UN*X */ /* * UN*X definitions */ int pcap_get_selectable_fd(pcap_t *); #endif /* WIN32/MSDOS/UN*X */ #ifdef __cplusplus } #endif #endif /* lib_pcap_pcap_h */ Index: stable/9/contrib/libpcap/pcap-bpf.c =================================================================== --- stable/9/contrib/libpcap/pcap-bpf.c (revision 252280) +++ stable/9/contrib/libpcap/pcap-bpf.c (revision 252281) @@ -1,2752 +1,2717 @@ /* * Copyright (c) 1993, 1994, 1995, 1996, 1998 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * $FreeBSD$ */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.116 2008-09-16 18:42:29 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include /* optionally get BSD define */ #ifdef HAVE_ZEROCOPY_BPF #include #endif #include #include /* * defines ioctls, but doesn't include . * * We include as it might be necessary to declare ioctl(); * at least on *BSD and Mac OS X, it also defines various SIOC ioctls - * we could include , but if we're already including * , which includes on those platforms, * there's not much point in doing so. * * If we have , we include it as well, to handle systems * such as Solaris which don't arrange to include if you * include */ #include #ifdef HAVE_SYS_IOCCOM_H #include #endif #include #ifdef HAVE_ZEROCOPY_BPF #include #endif #include #ifdef _AIX /* * Make "pcap.h" not include "pcap/bpf.h"; we are going to include the * native OS version, as we need "struct bpf_config" from it. */ #define PCAP_DONT_INCLUDE_PCAP_BPF_H #include /* * Prevent bpf.h from redefining the DLT_ values to their * IFT_ values, as we're going to return the standard libpcap * values, not IBM's non-standard IFT_ values. */ #undef _AIX #include #define _AIX #include /* for IFT_ values */ #include #include #include #include #ifdef __64BIT__ #define domakedev makedev64 #define getmajor major64 #define bpf_hdr bpf_hdr32 #else /* __64BIT__ */ #define domakedev makedev #define getmajor major #endif /* __64BIT__ */ #define BPF_NAME "bpf" #define BPF_MINORS 4 #define DRIVER_PATH "/usr/lib/drivers" #define BPF_NODE "/dev/bpf" static int bpfloadedflag = 0; static int odmlockid = 0; static int bpf_load(char *errbuf); #else /* _AIX */ #include #endif /* _AIX */ #include #include #include #include #include #include #include #include #ifdef HAVE_NET_IF_MEDIA_H # include #endif #include "pcap-int.h" -#ifdef HAVE_DAG_API -#include "pcap-dag.h" -#endif /* HAVE_DAG_API */ - -#ifdef HAVE_SNF_API -#include "pcap-snf.h" -#endif /* HAVE_SNF_API */ - #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif #ifdef BIOCGDLTLIST # if (defined(HAVE_NET_IF_MEDIA_H) && defined(IFM_IEEE80211)) && !defined(__APPLE__) #define HAVE_BSD_IEEE80211 # endif # if defined(__APPLE__) || defined(HAVE_BSD_IEEE80211) static int find_802_11(struct bpf_dltlist *); # ifdef HAVE_BSD_IEEE80211 static int monitor_mode(pcap_t *, int); # endif # if defined(__APPLE__) static void remove_en(pcap_t *); static void remove_802_11(pcap_t *); # endif # endif /* defined(__APPLE__) || defined(HAVE_BSD_IEEE80211) */ #endif /* BIOCGDLTLIST */ #if defined(sun) && defined(LIFNAMSIZ) && defined(lifr_zoneid) #include #endif /* * We include the OS's , not our "pcap/bpf.h", so we probably * don't get DLT_DOCSIS defined. */ #ifndef DLT_DOCSIS #define DLT_DOCSIS 143 #endif /* * On OS X, we don't even get any of the 802.11-plus-radio-header DLT_'s * defined, even though some of them are used by various Airport drivers. */ #ifndef DLT_PRISM_HEADER #define DLT_PRISM_HEADER 119 #endif #ifndef DLT_AIRONET_HEADER #define DLT_AIRONET_HEADER 120 #endif #ifndef DLT_IEEE802_11_RADIO #define DLT_IEEE802_11_RADIO 127 #endif #ifndef DLT_IEEE802_11_RADIO_AVS #define DLT_IEEE802_11_RADIO_AVS 163 #endif static int pcap_can_set_rfmon_bpf(pcap_t *p); static int pcap_activate_bpf(pcap_t *p); static int pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp); static int pcap_setdirection_bpf(pcap_t *, pcap_direction_t); static int pcap_set_datalink_bpf(pcap_t *p, int dlt); /* * For zerocopy bpf, the setnonblock/getnonblock routines need to modify * p->md.timeout so we don't call select(2) if the pcap handle is in non- * blocking mode. We preserve the timeout supplied by pcap_open functions * to make sure it does not get clobbered if the pcap handle moves between * blocking and non-blocking mode. */ static int pcap_getnonblock_bpf(pcap_t *p, char *errbuf) { #ifdef HAVE_ZEROCOPY_BPF if (p->md.zerocopy) { /* * Use a negative value for the timeout to represent that the * pcap handle is in non-blocking mode. */ return (p->md.timeout < 0); } #endif return (pcap_getnonblock_fd(p, errbuf)); } static int pcap_setnonblock_bpf(pcap_t *p, int nonblock, char *errbuf) { #ifdef HAVE_ZEROCOPY_BPF if (p->md.zerocopy) { /* - * Map each value to the corresponding 2's complement, to + * Map each value to their corresponding negation to * preserve the timeout value provided with pcap_set_timeout. * (from pcap-linux.c). */ if (nonblock) { if (p->md.timeout >= 0) { /* - * Timeout is non-negative, so we're not - * currently in non-blocking mode; set it - * to the 2's complement, to make it - * negative, as an indication that we're - * in non-blocking mode. + * Indicate that we're switching to + * non-blocking mode. */ - p->md.timeout = p->md.timeout * -1 - 1; + p->md.timeout = ~p->md.timeout; } } else { if (p->md.timeout < 0) { - /* - * Timeout is negative, so we're currently - * in blocking mode; reverse the previous - * operation, to make the timeout non-negative - * again. - */ - p->md.timeout = (p->md.timeout + 1) * -1; + p->md.timeout = ~p->md.timeout; } } return (0); } #endif return (pcap_setnonblock_fd(p, nonblock, errbuf)); } #ifdef HAVE_ZEROCOPY_BPF /* * Zero-copy BPF buffer routines to check for and acknowledge BPF data in * shared memory buffers. * * pcap_next_zbuf_shm(): Check for a newly available shared memory buffer, * and set up p->buffer and cc to reflect one if available. Notice that if * there was no prior buffer, we select zbuf1 as this will be the first * buffer filled for a fresh BPF session. */ static int pcap_next_zbuf_shm(pcap_t *p, int *cc) { struct bpf_zbuf_header *bzh; if (p->md.zbuffer == p->md.zbuf2 || p->md.zbuffer == NULL) { bzh = (struct bpf_zbuf_header *)p->md.zbuf1; if (bzh->bzh_user_gen != atomic_load_acq_int(&bzh->bzh_kernel_gen)) { p->md.bzh = bzh; p->md.zbuffer = (u_char *)p->md.zbuf1; p->buffer = p->md.zbuffer + sizeof(*bzh); *cc = bzh->bzh_kernel_len; return (1); } } else if (p->md.zbuffer == p->md.zbuf1) { bzh = (struct bpf_zbuf_header *)p->md.zbuf2; if (bzh->bzh_user_gen != atomic_load_acq_int(&bzh->bzh_kernel_gen)) { p->md.bzh = bzh; p->md.zbuffer = (u_char *)p->md.zbuf2; p->buffer = p->md.zbuffer + sizeof(*bzh); *cc = bzh->bzh_kernel_len; return (1); } } *cc = 0; return (0); } /* * pcap_next_zbuf() -- Similar to pcap_next_zbuf_shm(), except wait using * select() for data or a timeout, and possibly force rotation of the buffer * in the event we time out or are in immediate mode. Invoke the shared * memory check before doing system calls in order to avoid doing avoidable * work. */ static int pcap_next_zbuf(pcap_t *p, int *cc) { struct bpf_zbuf bz; struct timeval tv; struct timespec cur; fd_set r_set; int data, r; int expire, tmout; #define TSTOMILLI(ts) (((ts)->tv_sec * 1000) + ((ts)->tv_nsec / 1000000)) /* * Start out by seeing whether anything is waiting by checking the * next shared memory buffer for data. */ data = pcap_next_zbuf_shm(p, cc); if (data) return (data); /* * If a previous sleep was interrupted due to signal delivery, make * sure that the timeout gets adjusted accordingly. This requires * that we analyze when the timeout should be been expired, and * subtract the current time from that. If after this operation, * our timeout is less then or equal to zero, handle it like a * regular timeout. */ tmout = p->md.timeout; if (tmout) (void) clock_gettime(CLOCK_MONOTONIC, &cur); if (p->md.interrupted && p->md.timeout) { expire = TSTOMILLI(&p->md.firstsel) + p->md.timeout; tmout = expire - TSTOMILLI(&cur); #undef TSTOMILLI if (tmout <= 0) { p->md.interrupted = 0; data = pcap_next_zbuf_shm(p, cc); if (data) return (data); if (ioctl(p->fd, BIOCROTZBUF, &bz) < 0) { (void) snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCROTZBUF: %s", strerror(errno)); return (PCAP_ERROR); } return (pcap_next_zbuf_shm(p, cc)); } } /* * No data in the buffer, so must use select() to wait for data or * the next timeout. Note that we only call select if the handle * is in blocking mode. */ if (p->md.timeout >= 0) { FD_ZERO(&r_set); FD_SET(p->fd, &r_set); if (tmout != 0) { tv.tv_sec = tmout / 1000; tv.tv_usec = (tmout * 1000) % 1000000; } r = select(p->fd + 1, &r_set, NULL, NULL, p->md.timeout != 0 ? &tv : NULL); if (r < 0 && errno == EINTR) { if (!p->md.interrupted && p->md.timeout) { p->md.interrupted = 1; p->md.firstsel = cur; } return (0); } else if (r < 0) { (void) snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "select: %s", strerror(errno)); return (PCAP_ERROR); } } p->md.interrupted = 0; /* * Check again for data, which may exist now that we've either been * woken up as a result of data or timed out. Try the "there's data" * case first since it doesn't require a system call. */ data = pcap_next_zbuf_shm(p, cc); if (data) return (data); /* * Try forcing a buffer rotation to dislodge timed out or immediate * data. */ if (ioctl(p->fd, BIOCROTZBUF, &bz) < 0) { (void) snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCROTZBUF: %s", strerror(errno)); return (PCAP_ERROR); } return (pcap_next_zbuf_shm(p, cc)); } /* * Notify kernel that we are done with the buffer. We don't reset zbuffer so * that we know which buffer to use next time around. */ static int pcap_ack_zbuf(pcap_t *p) { atomic_store_rel_int(&p->md.bzh->bzh_user_gen, p->md.bzh->bzh_kernel_gen); p->md.bzh = NULL; p->buffer = NULL; return (0); } #endif /* HAVE_ZEROCOPY_BPF */ pcap_t * -pcap_create(const char *device, char *ebuf) +pcap_create_interface(const char *device, char *ebuf) { pcap_t *p; -#ifdef HAVE_DAG_API - if (strstr(device, "dag")) - return (dag_create(device, ebuf)); -#endif /* HAVE_DAG_API */ -#ifdef HAVE_SNF_API - if (strstr(device, "snf")) - return (snf_create(device, ebuf)); -#endif /* HAVE_SNF_API */ - p = pcap_create_common(device, ebuf); if (p == NULL) return (NULL); p->activate_op = pcap_activate_bpf; p->can_set_rfmon_op = pcap_can_set_rfmon_bpf; return (p); } /* * On success, returns a file descriptor for a BPF device. * On failure, returns a PCAP_ERROR_ value, and sets p->errbuf. */ static int bpf_open(pcap_t *p) { int fd; #ifdef HAVE_CLONING_BPF static const char device[] = "/dev/bpf"; #else int n = 0; char device[sizeof "/dev/bpf0000000000"]; #endif #ifdef _AIX /* * Load the bpf driver, if it isn't already loaded, * and create the BPF device entries, if they don't * already exist. */ if (bpf_load(p->errbuf) == PCAP_ERROR) return (PCAP_ERROR); #endif #ifdef HAVE_CLONING_BPF if ((fd = open(device, O_RDWR)) == -1 && (errno != EACCES || (fd = open(device, O_RDONLY)) == -1)) { if (errno == EACCES) fd = PCAP_ERROR_PERM_DENIED; else fd = PCAP_ERROR; snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "(cannot open device) %s: %s", device, pcap_strerror(errno)); } #else /* * Go through all the minors and find one that isn't in use. */ do { (void)snprintf(device, sizeof(device), "/dev/bpf%d", n++); /* * Initially try a read/write open (to allow the inject * method to work). If that fails due to permission * issues, fall back to read-only. This allows a * non-root user to be granted specific access to pcap * capabilities via file permissions. * * XXX - we should have an API that has a flag that * controls whether to open read-only or read-write, * so that denial of permission to send (or inability * to send, if sending packets isn't supported on * the device in question) can be indicated at open * time. */ fd = open(device, O_RDWR); if (fd == -1 && errno == EACCES) fd = open(device, O_RDONLY); } while (fd < 0 && errno == EBUSY); /* * XXX better message for all minors used */ if (fd < 0) { switch (errno) { case ENOENT: fd = PCAP_ERROR; if (n == 1) { /* * /dev/bpf0 doesn't exist, which * means we probably have no BPF * devices. */ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "(there are no BPF devices)"); } else { /* * We got EBUSY on at least one * BPF device, so we have BPF * devices, but all the ones * that exist are busy. */ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "(all BPF devices are busy)"); } break; case EACCES: /* * Got EACCES on the last device we tried, * and EBUSY on all devices before that, * if any. */ fd = PCAP_ERROR_PERM_DENIED; snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "(cannot open BPF device) %s: %s", device, pcap_strerror(errno)); break; default: /* * Some other problem. */ fd = PCAP_ERROR; snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "(cannot open BPF device) %s: %s", device, pcap_strerror(errno)); break; } } #endif return (fd); } #ifdef BIOCGDLTLIST static int get_dlt_list(int fd, int v, struct bpf_dltlist *bdlp, char *ebuf) { memset(bdlp, 0, sizeof(*bdlp)); if (ioctl(fd, BIOCGDLTLIST, (caddr_t)bdlp) == 0) { u_int i; int is_ethernet; bdlp->bfl_list = (u_int *) malloc(sizeof(u_int) * (bdlp->bfl_len + 1)); if (bdlp->bfl_list == NULL) { (void)snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); return (PCAP_ERROR); } if (ioctl(fd, BIOCGDLTLIST, (caddr_t)bdlp) < 0) { (void)snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGDLTLIST: %s", pcap_strerror(errno)); free(bdlp->bfl_list); return (PCAP_ERROR); } /* * OK, for real Ethernet devices, add DLT_DOCSIS to the * list, so that an application can let you choose it, * in case you're capturing DOCSIS traffic that a Cisco * Cable Modem Termination System is putting out onto * an Ethernet (it doesn't put an Ethernet header onto * the wire, it puts raw DOCSIS frames out on the wire * inside the low-level Ethernet framing). * * A "real Ethernet device" is defined here as a device * that has a link-layer type of DLT_EN10MB and that has * no alternate link-layer types; that's done to exclude * 802.11 interfaces (which might or might not be the * right thing to do, but I suspect it is - Ethernet <-> * 802.11 bridges would probably badly mishandle frames * that don't have Ethernet headers). * * On Solaris with BPF, Ethernet devices also offer * DLT_IPNET, so we, if DLT_IPNET is defined, we don't * treat it as an indication that the device isn't an * Ethernet. */ if (v == DLT_EN10MB) { is_ethernet = 1; for (i = 0; i < bdlp->bfl_len; i++) { if (bdlp->bfl_list[i] != DLT_EN10MB #ifdef DLT_IPNET && bdlp->bfl_list[i] != DLT_IPNET #endif ) { is_ethernet = 0; break; } } if (is_ethernet) { /* * We reserved one more slot at the end of * the list. */ bdlp->bfl_list[bdlp->bfl_len] = DLT_DOCSIS; bdlp->bfl_len++; } } } else { /* * EINVAL just means "we don't support this ioctl on * this device"; don't treat it as an error. */ if (errno != EINVAL) { (void)snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGDLTLIST: %s", pcap_strerror(errno)); return (PCAP_ERROR); } } return (0); } #endif static int pcap_can_set_rfmon_bpf(pcap_t *p) { #if defined(__APPLE__) struct utsname osinfo; struct ifreq ifr; int fd; #ifdef BIOCGDLTLIST struct bpf_dltlist bdl; #endif /* * The joys of monitor mode on OS X. * * Prior to 10.4, it's not supported at all. * * In 10.4, if adapter enN supports monitor mode, there's a * wltN adapter corresponding to it; you open it, instead of * enN, to get monitor mode. You get whatever link-layer * headers it supplies. * * In 10.5, and, we assume, later releases, if adapter enN * supports monitor mode, it offers, among its selectable * DLT_ values, values that let you get the 802.11 header; * selecting one of those values puts the adapter into monitor * mode (i.e., you can't get 802.11 headers except in monitor * mode, and you can't get Ethernet headers in monitor mode). */ if (uname(&osinfo) == -1) { /* * Can't get the OS version; just say "no". */ return (0); } /* * We assume osinfo.sysname is "Darwin", because * __APPLE__ is defined. We just check the version. */ if (osinfo.release[0] < '8' && osinfo.release[1] == '.') { /* * 10.3 (Darwin 7.x) or earlier. * Monitor mode not supported. */ return (0); } if (osinfo.release[0] == '8' && osinfo.release[1] == '.') { /* * 10.4 (Darwin 8.x). s/en/wlt/, and check * whether the device exists. */ if (strncmp(p->opt.source, "en", 2) != 0) { /* * Not an enN device; no monitor mode. */ return (0); } fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd == -1) { (void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "socket: %s", pcap_strerror(errno)); return (PCAP_ERROR); } strlcpy(ifr.ifr_name, "wlt", sizeof(ifr.ifr_name)); strlcat(ifr.ifr_name, p->opt.source + 2, sizeof(ifr.ifr_name)); if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) { /* * No such device? */ close(fd); return (0); } close(fd); return (1); } #ifdef BIOCGDLTLIST /* * Everything else is 10.5 or later; for those, * we just open the enN device, and check whether * we have any 802.11 devices. * * First, open a BPF device. */ fd = bpf_open(p); if (fd < 0) return (fd); /* fd is the appropriate error code */ /* * Now bind to the device. */ (void)strncpy(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name)); if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) { switch (errno) { case ENXIO: /* * There's no such device. */ close(fd); return (PCAP_ERROR_NO_SUCH_DEVICE); case ENETDOWN: /* * Return a "network down" indication, so that * the application can report that rather than * saying we had a mysterious failure and * suggest that they report a problem to the * libpcap developers. */ close(fd); return (PCAP_ERROR_IFACE_NOT_UP); default: snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF: %s: %s", p->opt.source, pcap_strerror(errno)); close(fd); return (PCAP_ERROR); } } /* * We know the default link type -- now determine all the DLTs * this interface supports. If this fails with EINVAL, it's * not fatal; we just don't get to use the feature later. * (We don't care about DLT_DOCSIS, so we pass DLT_NULL * as the default DLT for this adapter.) */ if (get_dlt_list(fd, DLT_NULL, &bdl, p->errbuf) == PCAP_ERROR) { close(fd); return (PCAP_ERROR); } if (find_802_11(&bdl) != -1) { /* * We have an 802.11 DLT, so we can set monitor mode. */ free(bdl.bfl_list); close(fd); return (1); } free(bdl.bfl_list); #endif /* BIOCGDLTLIST */ return (0); #elif defined(HAVE_BSD_IEEE80211) int ret; ret = monitor_mode(p, 0); if (ret == PCAP_ERROR_RFMON_NOTSUP) return (0); /* not an error, just a "can't do" */ if (ret == 0) return (1); /* success */ return (ret); #else return (0); #endif } static int pcap_stats_bpf(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)); return (PCAP_ERROR); } ps->ps_recv = s.bs_recv; ps->ps_drop = s.bs_drop; ps->ps_ifdrop = 0; return (0); } static int pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { int cc; int n = 0; register u_char *bp, *ep; u_char *datap; #ifdef PCAP_FDDIPAD register int pad; #endif #ifdef HAVE_ZEROCOPY_BPF int i; #endif again: /* * Has "pcap_breakloop()" been called? */ if (p->break_loop) { /* * Yes - clear the flag that indicates that it * has, and return PCAP_ERROR_BREAK to indicate * that we were told to break out of the loop. */ p->break_loop = 0; return (PCAP_ERROR_BREAK); } cc = p->cc; if (p->cc == 0) { /* * When reading without zero-copy from a file descriptor, we * use a single buffer and return a length of data in the * buffer. With zero-copy, we update the p->buffer pointer * to point at whatever underlying buffer contains the next * data and update cc to reflect the data found in the * buffer. */ #ifdef HAVE_ZEROCOPY_BPF if (p->md.zerocopy) { if (p->buffer != NULL) pcap_ack_zbuf(p); i = pcap_next_zbuf(p, &cc); if (i == 0) goto again; if (i < 0) return (PCAP_ERROR); } else #endif { cc = read(p->fd, (char *)p->buffer, p->bufsize); } if (cc < 0) { /* Don't choke when we get ptraced */ switch (errno) { case EINTR: goto again; #ifdef _AIX case EFAULT: /* * Sigh. More AIX wonderfulness. * * For some unknown reason the uiomove() * operation in the bpf kernel extension * used to copy the buffer into user * space sometimes returns EFAULT. I have * no idea why this is the case given that * a kernel debugger shows the user buffer * is correct. This problem appears to * be mostly mitigated by the memset of * the buffer before it is first used. * Very strange.... Shaun Clowes * * In any case this means that we shouldn't * treat EFAULT as a fatal error; as we * don't have an API for returning * a "some packets were dropped since * the last packet you saw" indication, * we just ignore EFAULT and keep reading. */ goto again; #endif case EWOULDBLOCK: return (0); case ENXIO: /* * The device on which we're capturing * went away. * * XXX - we should really return * PCAP_ERROR_IFACE_NOT_UP, but * pcap_dispatch() etc. aren't * defined to retur that. */ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "The interface went down"); return (PCAP_ERROR); #if defined(sun) && !defined(BSD) && !defined(__svr4__) && !defined(__SVR4) /* * Due to a SunOS bug, after 2^31 bytes, the kernel * file offset overflows and read fails with EINVAL. * The lseek() to 0 will fix things. */ case EINVAL: if (lseek(p->fd, 0L, SEEK_CUR) + p->bufsize < 0) { (void)lseek(p->fd, 0L, SEEK_SET); goto again; } /* fall through */ #endif } snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read: %s", pcap_strerror(errno)); return (PCAP_ERROR); } bp = p->buffer; } else bp = p->bp; /* * Loop through each packet. */ #define bhp ((struct bpf_hdr *)bp) ep = bp + cc; #ifdef PCAP_FDDIPAD pad = p->fddipad; #endif while (bp < ep) { register int caplen, hdrlen; /* * Has "pcap_breakloop()" been called? * If so, return immediately - if we haven't read any * packets, clear the flag and return PCAP_ERROR_BREAK * to indicate that we were told to break out of the loop, * otherwise leave the flag set, so that the *next* call * will break out of the loop without having read any * packets, and return the number of packets we've * processed so far. */ if (p->break_loop) { p->bp = bp; p->cc = ep - bp; /* * ep is set based on the return value of read(), * but read() from a BPF device doesn't necessarily * return a value that's a multiple of the alignment * value for BPF_WORDALIGN(). However, whenever we * increment bp, we round up the increment value by * a value rounded up by BPF_WORDALIGN(), so we * could increment bp past ep after processing the * last packet in the buffer. * * We treat ep < bp as an indication that this * happened, and just set p->cc to 0. */ if (p->cc < 0) p->cc = 0; if (n == 0) { p->break_loop = 0; return (PCAP_ERROR_BREAK); } else return (n); } caplen = bhp->bh_caplen; hdrlen = bhp->bh_hdrlen; datap = bp + hdrlen; /* * Short-circuit evaluation: if using BPF filter * in kernel, no need to do it now - we already know * the packet passed the filter. * #ifdef PCAP_FDDIPAD * Note: the filter code was generated assuming * that p->fddipad was the amount of padding * before the header, as that's what's required * in the kernel, so we run the filter before * skipping that padding. #endif */ if (p->md.use_bpf || bpf_filter(p->fcode.bf_insns, datap, bhp->bh_datalen, caplen)) { struct pcap_pkthdr pkthdr; pkthdr.ts.tv_sec = bhp->bh_tstamp.tv_sec; #ifdef _AIX /* * AIX's BPF returns seconds/nanoseconds time * stamps, not seconds/microseconds time stamps. */ pkthdr.ts.tv_usec = bhp->bh_tstamp.tv_usec/1000; #else pkthdr.ts.tv_usec = bhp->bh_tstamp.tv_usec; #endif #ifdef PCAP_FDDIPAD if (caplen > pad) pkthdr.caplen = caplen - pad; else pkthdr.caplen = 0; if (bhp->bh_datalen > pad) pkthdr.len = bhp->bh_datalen - pad; else pkthdr.len = 0; datap += pad; #else pkthdr.caplen = caplen; pkthdr.len = bhp->bh_datalen; #endif (*callback)(user, &pkthdr, datap); bp += BPF_WORDALIGN(caplen + hdrlen); if (++n >= cnt && cnt > 0) { p->bp = bp; p->cc = ep - bp; /* * See comment above about p->cc < 0. */ if (p->cc < 0) p->cc = 0; return (n); } } else { /* * Skip this packet. */ bp += BPF_WORDALIGN(caplen + hdrlen); } } #undef bhp p->cc = 0; return (n); } static int pcap_inject_bpf(pcap_t *p, const void *buf, size_t size) { int ret; ret = write(p->fd, buf, size); #ifdef __APPLE__ if (ret == -1 && errno == EAFNOSUPPORT) { /* * In Mac OS X, there's a bug wherein setting the * BIOCSHDRCMPLT flag causes writes to fail; see, * for example: * * http://cerberus.sourcefire.com/~jeff/archives/patches/macosx/BIOCSHDRCMPLT-10.3.3.patch * * So, if, on OS X, we get EAFNOSUPPORT from the write, we * assume it's due to that bug, and turn off that flag * and try again. If we succeed, it either means that * somebody applied the fix from that URL, or other patches * for that bug from * * http://cerberus.sourcefire.com/~jeff/archives/patches/macosx/ * * and are running a Darwin kernel with those fixes, or * that Apple fixed the problem in some OS X release. */ u_int spoof_eth_src = 0; if (ioctl(p->fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1) { (void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: can't turn off BIOCSHDRCMPLT: %s", pcap_strerror(errno)); return (PCAP_ERROR); } /* * Now try the write again. */ ret = write(p->fd, buf, size); } #endif /* __APPLE__ */ if (ret == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s", pcap_strerror(errno)); return (PCAP_ERROR); } return (ret); } #ifdef _AIX static int bpf_odminit(char *errbuf) { char *errstr; if (odm_initialize() == -1) { if (odm_err_msg(odmerrno, &errstr) == -1) errstr = "Unknown error"; snprintf(errbuf, PCAP_ERRBUF_SIZE, "bpf_load: odm_initialize failed: %s", errstr); return (PCAP_ERROR); } if ((odmlockid = odm_lock("/etc/objrepos/config_lock", ODM_WAIT)) == -1) { if (odm_err_msg(odmerrno, &errstr) == -1) errstr = "Unknown error"; snprintf(errbuf, PCAP_ERRBUF_SIZE, "bpf_load: odm_lock of /etc/objrepos/config_lock failed: %s", errstr); (void)odm_terminate(); return (PCAP_ERROR); } return (0); } static int bpf_odmcleanup(char *errbuf) { char *errstr; if (odm_unlock(odmlockid) == -1) { if (errbuf != NULL) { if (odm_err_msg(odmerrno, &errstr) == -1) errstr = "Unknown error"; snprintf(errbuf, PCAP_ERRBUF_SIZE, "bpf_load: odm_unlock failed: %s", errstr); } return (PCAP_ERROR); } if (odm_terminate() == -1) { if (errbuf != NULL) { if (odm_err_msg(odmerrno, &errstr) == -1) errstr = "Unknown error"; snprintf(errbuf, PCAP_ERRBUF_SIZE, "bpf_load: odm_terminate failed: %s", errstr); } return (PCAP_ERROR); } return (0); } static int bpf_load(char *errbuf) { long major; int *minors; int numminors, i, rc; char buf[1024]; struct stat sbuf; struct bpf_config cfg_bpf; struct cfg_load cfg_ld; struct cfg_kmod cfg_km; /* * This is very very close to what happens in the real implementation * but I've fixed some (unlikely) bug situations. */ if (bpfloadedflag) return (0); if (bpf_odminit(errbuf) == PCAP_ERROR) return (PCAP_ERROR); major = genmajor(BPF_NAME); if (major == -1) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "bpf_load: genmajor failed: %s", pcap_strerror(errno)); (void)bpf_odmcleanup(NULL); return (PCAP_ERROR); } minors = getminor(major, &numminors, BPF_NAME); if (!minors) { minors = genminor("bpf", major, 0, BPF_MINORS, 1, 1); if (!minors) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "bpf_load: genminor failed: %s", pcap_strerror(errno)); (void)bpf_odmcleanup(NULL); return (PCAP_ERROR); } } if (bpf_odmcleanup(errbuf) == PCAP_ERROR) return (PCAP_ERROR); rc = stat(BPF_NODE "0", &sbuf); if (rc == -1 && errno != ENOENT) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "bpf_load: can't stat %s: %s", BPF_NODE "0", pcap_strerror(errno)); return (PCAP_ERROR); } if (rc == -1 || getmajor(sbuf.st_rdev) != major) { for (i = 0; i < BPF_MINORS; i++) { sprintf(buf, "%s%d", BPF_NODE, i); unlink(buf); if (mknod(buf, S_IRUSR | S_IFCHR, domakedev(major, i)) == -1) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "bpf_load: can't mknod %s: %s", buf, pcap_strerror(errno)); return (PCAP_ERROR); } } } /* Check if the driver is loaded */ memset(&cfg_ld, 0x0, sizeof(cfg_ld)); cfg_ld.path = buf; sprintf(cfg_ld.path, "%s/%s", DRIVER_PATH, BPF_NAME); if ((sysconfig(SYS_QUERYLOAD, (void *)&cfg_ld, sizeof(cfg_ld)) == -1) || (cfg_ld.kmid == 0)) { /* Driver isn't loaded, load it now */ if (sysconfig(SYS_SINGLELOAD, (void *)&cfg_ld, sizeof(cfg_ld)) == -1) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "bpf_load: could not load driver: %s", strerror(errno)); return (PCAP_ERROR); } } /* Configure the driver */ cfg_km.cmd = CFG_INIT; cfg_km.kmid = cfg_ld.kmid; cfg_km.mdilen = sizeof(cfg_bpf); cfg_km.mdiptr = (void *)&cfg_bpf; for (i = 0; i < BPF_MINORS; i++) { cfg_bpf.devno = domakedev(major, i); if (sysconfig(SYS_CFGKMOD, (void *)&cfg_km, sizeof(cfg_km)) == -1) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "bpf_load: could not configure driver: %s", strerror(errno)); return (PCAP_ERROR); } } bpfloadedflag = 1; return (0); } #endif /* * Turn off rfmon mode if necessary. */ static void pcap_cleanup_bpf(pcap_t *p) { #ifdef HAVE_BSD_IEEE80211 int sock; struct ifmediareq req; struct ifreq ifr; #endif if (p->md.must_do_on_close != 0) { /* * There's something we have to do when closing this * pcap_t. */ #ifdef HAVE_BSD_IEEE80211 if (p->md.must_do_on_close & MUST_CLEAR_RFMON) { /* * We put the interface into rfmon mode; * take it out of rfmon mode. * * XXX - if somebody else wants it in rfmon * mode, this code cannot know that, so it'll take * it out of rfmon mode. */ sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock == -1) { fprintf(stderr, "Can't restore interface flags (socket() failed: %s).\n" "Please adjust manually.\n", strerror(errno)); } else { memset(&req, 0, sizeof(req)); strncpy(req.ifm_name, p->md.device, sizeof(req.ifm_name)); if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) { fprintf(stderr, "Can't restore interface flags (SIOCGIFMEDIA failed: %s).\n" "Please adjust manually.\n", strerror(errno)); } else { if (req.ifm_current & IFM_IEEE80211_MONITOR) { /* * Rfmon mode is currently on; * turn it off. */ memset(&ifr, 0, sizeof(ifr)); (void)strncpy(ifr.ifr_name, p->md.device, sizeof(ifr.ifr_name)); ifr.ifr_media = req.ifm_current & ~IFM_IEEE80211_MONITOR; if (ioctl(sock, SIOCSIFMEDIA, &ifr) == -1) { fprintf(stderr, "Can't restore interface flags (SIOCSIFMEDIA failed: %s).\n" "Please adjust manually.\n", strerror(errno)); } } } close(sock); } } #endif /* HAVE_BSD_IEEE80211 */ /* * Take this pcap out of the list of pcaps for which we * have to take the interface out of some mode. */ pcap_remove_from_pcaps_to_close(p); p->md.must_do_on_close = 0; } #ifdef HAVE_ZEROCOPY_BPF if (p->md.zerocopy) { /* * Delete the mappings. Note that p->buffer gets * initialized to one of the mmapped regions in * this case, so do not try and free it directly; * null it out so that pcap_cleanup_live_common() * doesn't try to free it. */ if (p->md.zbuf1 != MAP_FAILED && p->md.zbuf1 != NULL) (void) munmap(p->md.zbuf1, p->md.zbufsize); if (p->md.zbuf2 != MAP_FAILED && p->md.zbuf2 != NULL) (void) munmap(p->md.zbuf2, p->md.zbufsize); p->buffer = NULL; p->buffer = NULL; } #endif if (p->md.device != NULL) { free(p->md.device); p->md.device = NULL; } pcap_cleanup_live_common(p); } static int check_setif_failure(pcap_t *p, int error) { #ifdef __APPLE__ int fd; struct ifreq ifr; int err; #endif if (error == ENXIO) { /* * No such device exists. */ #ifdef __APPLE__ if (p->opt.rfmon && strncmp(p->opt.source, "wlt", 3) == 0) { /* * Monitor mode was requested, and we're trying * to open a "wltN" device. Assume that this * is 10.4 and that we were asked to open an * "enN" device; if that device exists, return * "monitor mode not supported on the device". */ fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd != -1) { strlcpy(ifr.ifr_name, "en", sizeof(ifr.ifr_name)); strlcat(ifr.ifr_name, p->opt.source + 3, sizeof(ifr.ifr_name)); if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) { /* * We assume this failed because * the underlying device doesn't * exist. */ err = PCAP_ERROR_NO_SUCH_DEVICE; snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFFLAGS on %s failed: %s", ifr.ifr_name, pcap_strerror(errno)); } else { /* * The underlying "enN" device * exists, but there's no * corresponding "wltN" device; * that means that the "enN" * device doesn't support * monitor mode, probably because * it's an Ethernet device rather * than a wireless device. */ err = PCAP_ERROR_RFMON_NOTSUP; } close(fd); } else { /* * We can't find out whether there's * an underlying "enN" device, so * just report "no such device". */ err = PCAP_ERROR_NO_SUCH_DEVICE; snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "socket() failed: %s", pcap_strerror(errno)); } return (err); } #endif /* * No such device. */ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF failed: %s", pcap_strerror(errno)); return (PCAP_ERROR_NO_SUCH_DEVICE); } else if (errno == ENETDOWN) { /* * Return a "network down" indication, so that * the application can report that rather than * saying we had a mysterious failure and * suggest that they report a problem to the * libpcap developers. */ return (PCAP_ERROR_IFACE_NOT_UP); } else { /* * Some other error; fill in the error string, and * return PCAP_ERROR. */ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF: %s: %s", p->opt.source, pcap_strerror(errno)); return (PCAP_ERROR); } } /* * Default capture buffer size. * 32K isn't very much for modern machines with fast networks; we * pick .5M, as that's the maximum on at least some systems with BPF. * * However, on AIX 3.5, the larger buffer sized caused unrecoverable * read failures under stress, so we leave it as 32K; yet another * place where AIX's BPF is broken. */ #ifdef _AIX #define DEFAULT_BUFSIZE 32768 #else #define DEFAULT_BUFSIZE 524288 #endif static int pcap_activate_bpf(pcap_t *p) { int status = 0; int fd; #ifdef LIFNAMSIZ char *zonesep; struct lifreq ifr; char *ifrname = ifr.lifr_name; const size_t ifnamsiz = sizeof(ifr.lifr_name); #else struct ifreq ifr; char *ifrname = ifr.ifr_name; const size_t ifnamsiz = sizeof(ifr.ifr_name); #endif struct bpf_version bv; #ifdef __APPLE__ int sockfd; char *wltdev = NULL; #endif #ifdef BIOCGDLTLIST struct bpf_dltlist bdl; #if defined(__APPLE__) || defined(HAVE_BSD_IEEE80211) int new_dlt; #endif #endif /* BIOCGDLTLIST */ #if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT) u_int spoof_eth_src = 1; #endif u_int v; struct bpf_insn total_insn; struct bpf_program total_prog; struct utsname osinfo; #ifdef HAVE_DAG_API if (strstr(device, "dag")) { return dag_open_live(device, snaplen, promisc, to_ms, ebuf); } #endif /* HAVE_DAG_API */ #ifdef BIOCGDLTLIST memset(&bdl, 0, sizeof(bdl)); int have_osinfo = 0; #ifdef HAVE_ZEROCOPY_BPF struct bpf_zbuf bz; u_int bufmode, zbufmax; #endif fd = bpf_open(p); if (fd < 0) { status = fd; goto bad; } p->fd = fd; if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCVERSION: %s", pcap_strerror(errno)); status = PCAP_ERROR; goto bad; } if (bv.bv_major != BPF_MAJOR_VERSION || bv.bv_minor < BPF_MINOR_VERSION) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "kernel bpf filter out of date"); status = PCAP_ERROR; goto bad; } #if defined(LIFNAMSIZ) && defined(ZONENAME_MAX) && defined(lifr_zoneid) /* * Check if the given source network device has a '/' separated * zonename prefix string. The zonename prefixed source device * can be used by libpcap consumers to capture network traffic * in non-global zones from the global zone on Solaris 11 and * above. If the zonename prefix is present then we strip the * prefix and pass the zone ID as part of lifr_zoneid. */ if ((zonesep = strchr(p->opt.source, '/')) != NULL) { char zonename[ZONENAME_MAX]; int znamelen; char *lnamep; znamelen = zonesep - p->opt.source; (void) strlcpy(zonename, p->opt.source, znamelen + 1); lnamep = strdup(zonesep + 1); ifr.lifr_zoneid = getzoneidbyname(zonename); free(p->opt.source); p->opt.source = lnamep; } #endif p->md.device = strdup(p->opt.source); if (p->md.device == NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s", pcap_strerror(errno)); status = PCAP_ERROR; goto bad; } /* * Try finding a good size for the buffer; 32768 may be too * big, so keep cutting it in half until we find a size * that works, or run out of sizes to try. If the default * is larger, don't make it smaller. * * XXX - there should be a user-accessible hook to set the * initial buffer size. * Attempt to find out the version of the OS on which we're running. */ if (uname(&osinfo) == 0) have_osinfo = 1; #ifdef __APPLE__ /* * See comment in pcap_can_set_rfmon_bpf() for an explanation * of why we check the version number. */ if (p->opt.rfmon) { if (have_osinfo) { /* * We assume osinfo.sysname is "Darwin", because * __APPLE__ is defined. We just check the version. */ if (osinfo.release[0] < '8' && osinfo.release[1] == '.') { /* * 10.3 (Darwin 7.x) or earlier. */ status = PCAP_ERROR_RFMON_NOTSUP; goto bad; } if (osinfo.release[0] == '8' && osinfo.release[1] == '.') { /* * 10.4 (Darwin 8.x). s/en/wlt/ */ if (strncmp(p->opt.source, "en", 2) != 0) { /* * Not an enN device; check * whether the device even exists. */ sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd != -1) { strlcpy(ifrname, p->opt.source, ifnamsiz); if (ioctl(sockfd, SIOCGIFFLAGS, (char *)&ifr) < 0) { /* * We assume this * failed because * the underlying * device doesn't * exist. */ status = PCAP_ERROR_NO_SUCH_DEVICE; snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFFLAGS failed: %s", pcap_strerror(errno)); } else status = PCAP_ERROR_RFMON_NOTSUP; close(sockfd); } else { /* * We can't find out whether * the device exists, so just * report "no such device". */ status = PCAP_ERROR_NO_SUCH_DEVICE; snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "socket() failed: %s", pcap_strerror(errno)); } goto bad; } wltdev = malloc(strlen(p->opt.source) + 2); if (wltdev == NULL) { (void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); status = PCAP_ERROR; goto bad; } strcpy(wltdev, "wlt"); strcat(wltdev, p->opt.source + 2); free(p->opt.source); p->opt.source = wltdev; } /* * Everything else is 10.5 or later; for those, * we just open the enN device, and set the DLT. */ } } #endif /* __APPLE__ */ #ifdef HAVE_ZEROCOPY_BPF /* * If the BPF extension to set buffer mode is present, try setting * the mode to zero-copy. If that fails, use regular buffering. If * it succeeds but other setup fails, return an error to the user. */ bufmode = BPF_BUFMODE_ZBUF; if (ioctl(fd, BIOCSETBUFMODE, (caddr_t)&bufmode) == 0) { /* * We have zerocopy BPF; use it. */ p->md.zerocopy = 1; /* * How to pick a buffer size: first, query the maximum buffer * size supported by zero-copy. This also lets us quickly * determine whether the kernel generally supports zero-copy. * Then, if a buffer size was specified, use that, otherwise * query the default buffer size, which reflects kernel * policy for a desired default. Round to the nearest page * size. */ if (ioctl(fd, BIOCGETZMAX, (caddr_t)&zbufmax) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGETZMAX: %s", pcap_strerror(errno)); goto bad; } if (p->opt.buffer_size != 0) { /* * A buffer size was explicitly specified; use it. */ v = p->opt.buffer_size; } else { if ((ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) || v < DEFAULT_BUFSIZE) v = DEFAULT_BUFSIZE; } #ifndef roundup #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) /* to any y */ #endif p->md.zbufsize = roundup(v, getpagesize()); if (p->md.zbufsize > zbufmax) p->md.zbufsize = zbufmax; p->md.zbuf1 = mmap(NULL, p->md.zbufsize, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0); p->md.zbuf2 = mmap(NULL, p->md.zbufsize, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0); if (p->md.zbuf1 == MAP_FAILED || p->md.zbuf2 == MAP_FAILED) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "mmap: %s", pcap_strerror(errno)); goto bad; } - bzero(&bz, sizeof(bz)); + memset(&bz, 0, sizeof(bz)); /* bzero() deprecated, replaced with memset() */ bz.bz_bufa = p->md.zbuf1; bz.bz_bufb = p->md.zbuf2; bz.bz_buflen = p->md.zbufsize; if (ioctl(fd, BIOCSETZBUF, (caddr_t)&bz) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETZBUF: %s", pcap_strerror(errno)); goto bad; } (void)strncpy(ifrname, p->opt.source, ifnamsiz); if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF: %s: %s", p->opt.source, pcap_strerror(errno)); goto bad; } v = p->md.zbufsize - sizeof(struct bpf_zbuf_header); } else #endif { /* * We don't have zerocopy BPF. * Set the buffer size. */ if (p->opt.buffer_size != 0) { /* * A buffer size was explicitly specified; use it. */ if (ioctl(fd, BIOCSBLEN, (caddr_t)&p->opt.buffer_size) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSBLEN: %s: %s", p->opt.source, pcap_strerror(errno)); status = PCAP_ERROR; goto bad; } /* * Now bind to the device. */ (void)strncpy(ifrname, p->opt.source, ifnamsiz); #ifdef BIOCSETLIF if (ioctl(fd, BIOCSETLIF, (caddr_t)&ifr) < 0) #else if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) #endif { status = check_setif_failure(p, errno); goto bad; } } else { /* * No buffer size was explicitly specified. * * Try finding a good size for the buffer; * DEFAULT_BUFSIZE may be too big, so keep * cutting it in half until we find a size * that works, or run out of sizes to try. * If the default is larger, don't make it smaller. */ if ((ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) || v < DEFAULT_BUFSIZE) v = DEFAULT_BUFSIZE; for ( ; v != 0; v >>= 1) { /* * Ignore the return value - this is because the * call fails on BPF systems that don't have * kernel malloc. And if the call fails, it's * no big deal, we just continue to use the * standard buffer size. */ (void) ioctl(fd, BIOCSBLEN, (caddr_t)&v); (void)strncpy(ifrname, p->opt.source, ifnamsiz); #ifdef BIOCSETLIF if (ioctl(fd, BIOCSETLIF, (caddr_t)&ifr) >= 0) #else if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) >= 0) #endif break; /* that size worked; we're done */ if (errno != ENOBUFS) { status = check_setif_failure(p, errno); goto bad; } } if (v == 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSBLEN: %s: No buffer size worked", p->opt.source); status = PCAP_ERROR; goto bad; } } } #endif /* Get the data link layer type. */ if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGDLT: %s", pcap_strerror(errno)); status = PCAP_ERROR; goto bad; } #ifdef _AIX /* * AIX's BPF returns IFF_ types, not DLT_ types, in BIOCGDLT. */ switch (v) { case IFT_ETHER: case IFT_ISO88023: v = DLT_EN10MB; break; case IFT_FDDI: v = DLT_FDDI; break; case IFT_ISO88025: v = DLT_IEEE802; break; case IFT_LOOP: v = DLT_NULL; break; default: /* * We don't know what to map this to yet. */ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "unknown interface type %u", v); status = PCAP_ERROR; goto bad; } #endif #if _BSDI_VERSION - 0 >= 199510 /* The SLIP and PPP link layer header changed in BSD/OS 2.1 */ switch (v) { case DLT_SLIP: v = DLT_SLIP_BSDOS; break; case DLT_PPP: v = DLT_PPP_BSDOS; break; case 11: /*DLT_FR*/ v = DLT_FRELAY; break; case 12: /*DLT_C_HDLC*/ v = DLT_CHDLC; break; } #endif #ifdef BIOCGDLTLIST /* * We know the default link type -- now determine all the DLTs * this interface supports. If this fails with EINVAL, it's * not fatal; we just don't get to use the feature later. */ if (get_dlt_list(fd, v, &bdl, p->errbuf) == -1) { status = PCAP_ERROR; goto bad; } p->dlt_count = bdl.bfl_len; p->dlt_list = bdl.bfl_list; #ifdef __APPLE__ /* * Monitor mode fun, continued. * * For 10.5 and, we're assuming, later releases, as noted above, * 802.1 adapters that support monitor mode offer both DLT_EN10MB, * DLT_IEEE802_11, and possibly some 802.11-plus-radio-information * DLT_ value. Choosing one of the 802.11 DLT_ values will turn * monitor mode on. * * Therefore, if the user asked for monitor mode, we filter out * the DLT_EN10MB value, as you can't get that in monitor mode, * and, if the user didn't ask for monitor mode, we filter out * the 802.11 DLT_ values, because selecting those will turn * monitor mode on. Then, for monitor mode, if an 802.11-plus- * radio DLT_ value is offered, we try to select that, otherwise * we try to select DLT_IEEE802_11. */ if (have_osinfo) { if (isdigit((unsigned)osinfo.release[0]) && (osinfo.release[0] == '9' || isdigit((unsigned)osinfo.release[1]))) { /* * 10.5 (Darwin 9.x), or later. */ new_dlt = find_802_11(&bdl); if (new_dlt != -1) { /* * We have at least one 802.11 DLT_ value, * so this is an 802.11 interface. * new_dlt is the best of the 802.11 * DLT_ values in the list. */ if (p->opt.rfmon) { /* * Our caller wants monitor mode. * Purge DLT_EN10MB from the list * of link-layer types, as selecting * it will keep monitor mode off. */ remove_en(p); /* * If the new mode we want isn't * the default mode, attempt to * select the new mode. */ if (new_dlt != v) { if (ioctl(p->fd, BIOCSDLT, &new_dlt) != -1) { /* * We succeeded; * make this the * new DLT_ value. */ v = new_dlt; } } } else { /* * Our caller doesn't want * monitor mode. Unless this * is being done by pcap_open_live(), * purge the 802.11 link-layer types * from the list, as selecting * one of them will turn monitor * mode on. */ if (!p->oldstyle) remove_802_11(p); } } else { if (p->opt.rfmon) { /* * The caller requested monitor * mode, but we have no 802.11 * link-layer types, so they * can't have it. */ status = PCAP_ERROR_RFMON_NOTSUP; goto bad; } } } } #elif defined(HAVE_BSD_IEEE80211) /* * *BSD with the new 802.11 ioctls. * Do we want monitor mode? */ if (p->opt.rfmon) { /* * Try to put the interface into monitor mode. */ status = monitor_mode(p, 1); if (status != 0) { /* * We failed. */ goto bad; } /* * We're in monitor mode. * Try to find the best 802.11 DLT_ value and, if we * succeed, try to switch to that mode if we're not * already in that mode. */ new_dlt = find_802_11(&bdl); if (new_dlt != -1) { /* * We have at least one 802.11 DLT_ value. * new_dlt is the best of the 802.11 * DLT_ values in the list. * * If the new mode we want isn't the default mode, * attempt to select the new mode. */ if (new_dlt != v) { if (ioctl(p->fd, BIOCSDLT, &new_dlt) != -1) { /* * We succeeded; make this the * new DLT_ value. */ v = new_dlt; } } } } #endif /* various platforms */ #endif /* BIOCGDLTLIST */ /* * If this is an Ethernet device, and we don't have a DLT_ list, * give it a list with DLT_EN10MB and DLT_DOCSIS. (That'd give * 802.11 interfaces DLT_DOCSIS, which isn't the right thing to * do, but there's not much we can do about that without finding * some other way of determining whether it's an Ethernet or 802.11 * device.) */ if (v == DLT_EN10MB && p->dlt_count == 0) { p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); /* * If that fails, just leave the list empty. */ if (p->dlt_list != NULL) { p->dlt_list[0] = DLT_EN10MB; p->dlt_list[1] = DLT_DOCSIS; p->dlt_count = 2; } } #ifdef PCAP_FDDIPAD if (v == DLT_FDDI) p->fddipad = PCAP_FDDIPAD; else p->fddipad = 0; #endif p->linktype = v; #if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT) /* * Do a BIOCSHDRCMPLT, if defined, to turn that flag on, so * the link-layer source address isn't forcibly overwritten. * (Should we ignore errors? Should we do this only if * we're open for writing?) * * XXX - I seem to remember some packet-sending bug in some * BSDs - check CVS log for "bpf.c"? */ if (ioctl(fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1) { (void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSHDRCMPLT: %s", pcap_strerror(errno)); status = PCAP_ERROR; goto bad; } #endif /* set timeout */ #ifdef HAVE_ZEROCOPY_BPF if (p->md.timeout != 0 && !p->md.zerocopy) { #else if (p->md.timeout) { #endif /* * XXX - is this seconds/nanoseconds in AIX? * (Treating it as such doesn't fix the timeout * problem described below.) * * XXX - Mac OS X 10.6 mishandles BIOCSRTIMEOUT in * 64-bit userland - it takes, as an argument, a * "struct BPF_TIMEVAL", which has 32-bit tv_sec * and tv_usec, rather than a "struct timeval". * * If this platform defines "struct BPF_TIMEVAL", * we check whether the structure size in BIOCSRTIMEOUT * is that of a "struct timeval" and, if not, we use * a "struct BPF_TIMEVAL" rather than a "struct timeval". * (That way, if the bug is fixed in a future release, * we will still do the right thing.) */ struct timeval to; #ifdef HAVE_STRUCT_BPF_TIMEVAL struct BPF_TIMEVAL bpf_to; if (IOCPARM_LEN(BIOCSRTIMEOUT) != sizeof(struct timeval)) { bpf_to.tv_sec = p->md.timeout / 1000; bpf_to.tv_usec = (p->md.timeout * 1000) % 1000000; if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&bpf_to) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT: %s", pcap_strerror(errno)); status = PCAP_ERROR; goto bad; } } else { #endif to.tv_sec = p->md.timeout / 1000; to.tv_usec = (p->md.timeout * 1000) % 1000000; if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT: %s", pcap_strerror(errno)); status = PCAP_ERROR; goto bad; } #ifdef HAVE_STRUCT_BPF_TIMEVAL } #endif } #ifdef _AIX #ifdef BIOCIMMEDIATE /* * Darren Reed notes that * * On AIX (4.2 at least), if BIOCIMMEDIATE is not set, the * timeout appears to be ignored and it waits until the buffer * is filled before returning. The result of not having it * set is almost worse than useless if your BPF filter * is reducing things to only a few packets (i.e. one every * second or so). * * so we turn BIOCIMMEDIATE mode on if this is AIX. * * We don't turn it on for other platforms, as that means we * get woken up for every packet, which may not be what we want; * in the Winter 1993 USENIX paper on BPF, they say: * * Since a process might want to look at every packet on a * network and the time between packets can be only a few * microseconds, it is not possible to do a read system call * per packet and BPF must collect the data from several * packets and return it as a unit when the monitoring * application does a read. * * which I infer is the reason for the timeout - it means we * wait that amount of time, in the hopes that more packets * will arrive and we'll get them all with one read. * * Setting BIOCIMMEDIATE mode on FreeBSD (and probably other * BSDs) causes the timeout to be ignored. * * On the other hand, some platforms (e.g., Linux) don't support * timeouts, they just hand stuff to you as soon as it arrives; * if that doesn't cause a problem on those platforms, it may * be OK to have BIOCIMMEDIATE mode on BSD as well. * * (Note, though, that applications may depend on the read * completing, even if no packets have arrived, when the timeout * expires, e.g. GUI applications that have to check for input * while waiting for packets to arrive; a non-zero timeout * prevents "select()" from working right on FreeBSD and * possibly other BSDs, as the timer doesn't start until a * "read()" is done, so the timer isn't in effect if the * application is blocked on a "select()", and the "select()" * doesn't get woken up for a BPF device until the buffer * fills up.) */ v = 1; if (ioctl(p->fd, BIOCIMMEDIATE, &v) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCIMMEDIATE: %s", pcap_strerror(errno)); status = PCAP_ERROR; goto bad; } #endif /* BIOCIMMEDIATE */ #endif /* _AIX */ if (p->opt.promisc) { /* set promiscuous mode, just warn if it fails */ if (ioctl(p->fd, BIOCPROMISC, NULL) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCPROMISC: %s", pcap_strerror(errno)); status = PCAP_WARNING_PROMISC_NOTSUP; } } if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGBLEN: %s", pcap_strerror(errno)); status = PCAP_ERROR; goto bad; } p->bufsize = v; #ifdef HAVE_ZEROCOPY_BPF if (!p->md.zerocopy) { #endif p->buffer = (u_char *)malloc(p->bufsize); if (p->buffer == NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); status = PCAP_ERROR; goto bad; } #ifdef _AIX /* For some strange reason this seems to prevent the EFAULT * problems we have experienced from AIX BPF. */ memset(p->buffer, 0x0, p->bufsize); #endif #ifdef HAVE_ZEROCOPY_BPF } #endif /* * If there's no filter program installed, there's * no indication to the kernel of what the snapshot * length should be, so no snapshotting is done. * * Therefore, when we open the device, we install * an "accept everything" filter with the specified * snapshot length. */ total_insn.code = (u_short)(BPF_RET | BPF_K); total_insn.jt = 0; total_insn.jf = 0; total_insn.k = p->snapshot; total_prog.bf_len = 1; total_prog.bf_insns = &total_insn; if (ioctl(p->fd, BIOCSETF, (caddr_t)&total_prog) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s", pcap_strerror(errno)); status = PCAP_ERROR; goto bad; } /* * On most BPF platforms, either you can do a "select()" or * "poll()" on a BPF file descriptor and it works correctly, * or you can do it and it will return "readable" if the * hold buffer is full but not if the timeout expires *and* * a non-blocking read will, if the hold buffer is empty * but the store buffer isn't empty, rotate the buffers * and return what packets are available. * * In the latter case, the fact that a non-blocking read * will give you the available packets means you can work * around the failure of "select()" and "poll()" to wake up * and return "readable" when the timeout expires by using * the timeout as the "select()" or "poll()" timeout, putting * the BPF descriptor into non-blocking mode, and read from * it regardless of whether "select()" reports it as readable * or not. * * However, in FreeBSD 4.3 and 4.4, "select()" and "poll()" * won't wake up and return "readable" if the timer expires * and non-blocking reads return EWOULDBLOCK if the hold * buffer is empty, even if the store buffer is non-empty. * * This means the workaround in question won't work. * * Therefore, on FreeBSD 4.3 and 4.4, we set "p->selectable_fd" * to -1, which means "sorry, you can't use 'select()' or 'poll()' * here". On all other BPF platforms, we set it to the FD for * the BPF device; in NetBSD, OpenBSD, and Darwin, a non-blocking * read will, if the hold buffer is empty and the store buffer * isn't empty, rotate the buffers and return what packets are * there (and in sufficiently recent versions of OpenBSD * "select()" and "poll()" should work correctly). * * XXX - what about AIX? */ p->selectable_fd = p->fd; /* assume select() works until we know otherwise */ if (have_osinfo) { /* * We can check what OS this is. */ if (strcmp(osinfo.sysname, "FreeBSD") == 0) { if (strncmp(osinfo.release, "4.3-", 4) == 0 || strncmp(osinfo.release, "4.4-", 4) == 0) p->selectable_fd = -1; } } p->read_op = pcap_read_bpf; p->inject_op = pcap_inject_bpf; p->setfilter_op = pcap_setfilter_bpf; p->setdirection_op = pcap_setdirection_bpf; p->set_datalink_op = pcap_set_datalink_bpf; p->getnonblock_op = pcap_getnonblock_bpf; p->setnonblock_op = pcap_setnonblock_bpf; p->stats_op = pcap_stats_bpf; p->cleanup_op = pcap_cleanup_bpf; return (status); bad: pcap_cleanup_bpf(p); return (status); } int pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) { -#ifdef HAVE_DAG_API - if (dag_platform_finddevs(alldevsp, errbuf) < 0) - return (-1); -#endif /* HAVE_DAG_API */ -#ifdef HAVE_SNF_API - if (snf_platform_finddevs(alldevsp, errbuf) < 0) - return (-1); -#endif /* HAVE_SNF_API */ - return (0); } #ifdef HAVE_BSD_IEEE80211 static int monitor_mode(pcap_t *p, int set) { int sock; struct ifmediareq req; int *media_list; int i; int can_do; struct ifreq ifr; sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't open socket: %s", pcap_strerror(errno)); return (PCAP_ERROR); } memset(&req, 0, sizeof req); strncpy(req.ifm_name, p->opt.source, sizeof req.ifm_name); /* * Find out how many media types we have. */ if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) { /* * Can't get the media types. */ switch (errno) { case ENXIO: /* * There's no such device. */ close(sock); return (PCAP_ERROR_NO_SUCH_DEVICE); case EINVAL: /* * Interface doesn't support SIOC{G,S}IFMEDIA. */ close(sock); return (PCAP_ERROR_RFMON_NOTSUP); default: snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFMEDIA 1: %s", pcap_strerror(errno)); close(sock); return (PCAP_ERROR); } } if (req.ifm_count == 0) { /* * No media types. */ close(sock); return (PCAP_ERROR_RFMON_NOTSUP); } /* * Allocate a buffer to hold all the media types, and * get the media types. */ media_list = malloc(req.ifm_count * sizeof(int)); if (media_list == NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); close(sock); return (PCAP_ERROR); } req.ifm_ulist = media_list; if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFMEDIA: %s", pcap_strerror(errno)); free(media_list); close(sock); return (PCAP_ERROR); } /* * Look for an 802.11 "automatic" media type. * We assume that all 802.11 adapters have that media type, * and that it will carry the monitor mode supported flag. */ can_do = 0; for (i = 0; i < req.ifm_count; i++) { if (IFM_TYPE(media_list[i]) == IFM_IEEE80211 && IFM_SUBTYPE(media_list[i]) == IFM_AUTO) { /* OK, does it do monitor mode? */ if (media_list[i] & IFM_IEEE80211_MONITOR) { can_do = 1; break; } } } free(media_list); if (!can_do) { /* * This adapter doesn't support monitor mode. */ close(sock); return (PCAP_ERROR_RFMON_NOTSUP); } if (set) { /* * Don't just check whether we can enable monitor mode, * do so, if it's not already enabled. */ if ((req.ifm_current & IFM_IEEE80211_MONITOR) == 0) { /* * Monitor mode isn't currently on, so turn it on, * and remember that we should turn it off when the * pcap_t is closed. */ /* * If we haven't already done so, arrange to have * "pcap_close_all()" called when we exit. */ if (!pcap_do_addexit(p)) { /* * "atexit()" failed; don't put the interface * in monitor mode, just give up. */ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "atexit failed"); close(sock); return (PCAP_ERROR); } memset(&ifr, 0, sizeof(ifr)); (void)strncpy(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name)); ifr.ifr_media = req.ifm_current | IFM_IEEE80211_MONITOR; if (ioctl(sock, SIOCSIFMEDIA, &ifr) == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCSIFMEDIA: %s", pcap_strerror(errno)); close(sock); return (PCAP_ERROR); } p->md.must_do_on_close |= MUST_CLEAR_RFMON; /* * Add this to the list of pcaps to close when we exit. */ pcap_add_to_pcaps_to_close(p); } } return (0); } #endif /* HAVE_BSD_IEEE80211 */ #if defined(BIOCGDLTLIST) && (defined(__APPLE__) || defined(HAVE_BSD_IEEE80211)) /* * Check whether we have any 802.11 link-layer types; return the best * of the 802.11 link-layer types if we find one, and return -1 * otherwise. * * DLT_IEEE802_11_RADIO, with the radiotap header, is considered the * best 802.11 link-layer type; any of the other 802.11-plus-radio * headers are second-best; 802.11 with no radio information is * the least good. */ static int find_802_11(struct bpf_dltlist *bdlp) { int new_dlt; int i; /* * Scan the list of DLT_ values, looking for 802.11 values, * and, if we find any, choose the best of them. */ new_dlt = -1; for (i = 0; i < bdlp->bfl_len; i++) { switch (bdlp->bfl_list[i]) { case DLT_IEEE802_11: /* * 802.11, but no radio. * * Offer this, and select it as the new mode * unless we've already found an 802.11 * header with radio information. */ if (new_dlt == -1) new_dlt = bdlp->bfl_list[i]; break; case DLT_PRISM_HEADER: case DLT_AIRONET_HEADER: case DLT_IEEE802_11_RADIO_AVS: /* * 802.11 with radio, but not radiotap. * * Offer this, and select it as the new mode * unless we've already found the radiotap DLT_. */ if (new_dlt != DLT_IEEE802_11_RADIO) new_dlt = bdlp->bfl_list[i]; break; case DLT_IEEE802_11_RADIO: /* * 802.11 with radiotap. * * Offer this, and select it as the new mode. */ new_dlt = bdlp->bfl_list[i]; break; default: /* * Not 802.11. */ break; } } return (new_dlt); } #endif /* defined(BIOCGDLTLIST) && (defined(__APPLE__) || defined(HAVE_BSD_IEEE80211)) */ #if defined(__APPLE__) && defined(BIOCGDLTLIST) /* * Remove DLT_EN10MB from the list of DLT_ values, as we're in monitor mode, * and DLT_EN10MB isn't supported in monitor mode. */ static void remove_en(pcap_t *p) { int i, j; /* * Scan the list of DLT_ values and discard DLT_EN10MB. */ j = 0; for (i = 0; i < p->dlt_count; i++) { switch (p->dlt_list[i]) { case DLT_EN10MB: /* * Don't offer this one. */ continue; default: /* * Just copy this mode over. */ break; } /* * Copy this DLT_ value to its new position. */ p->dlt_list[j] = p->dlt_list[i]; j++; } /* * Set the DLT_ count to the number of entries we copied. */ p->dlt_count = j; } /* * Remove 802.11 link-layer types from the list of DLT_ values, as * we're not in monitor mode, and those DLT_ values will switch us * to monitor mode. */ static void remove_802_11(pcap_t *p) { int i, j; /* * Scan the list of DLT_ values and discard 802.11 values. */ j = 0; for (i = 0; i < p->dlt_count; i++) { switch (p->dlt_list[i]) { case DLT_IEEE802_11: case DLT_PRISM_HEADER: case DLT_AIRONET_HEADER: case DLT_IEEE802_11_RADIO: case DLT_IEEE802_11_RADIO_AVS: /* * 802.11. Don't offer this one. */ continue; default: /* * Just copy this mode over. */ break; } /* * Copy this DLT_ value to its new position. */ p->dlt_list[j] = p->dlt_list[i]; j++; } /* * Set the DLT_ count to the number of entries we copied. */ p->dlt_count = j; } #endif /* defined(__APPLE__) && defined(BIOCGDLTLIST) */ static int pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp) { /* * Free any user-mode filter we might happen to have installed. */ pcap_freecode(&p->fcode); /* * Try to install the kernel filter. */ if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) == 0) { /* * It worked. */ p->md.use_bpf = 1; /* filtering in the kernel */ /* * Discard any previously-received packets, as they might * have passed whatever filter was formerly in effect, but * might not pass this filter (BIOCSETF discards packets * buffered in the kernel, so you can lose packets in any * case). */ p->cc = 0; return (0); } /* * We failed. * * If it failed with EINVAL, that's probably because the program * is invalid or too big. Validate it ourselves; if we like it * (we currently allow backward branches, to support protochain), * run it in userland. (There's no notion of "too big" for * userland.) * * Otherwise, just give up. * XXX - if the copy of the program into the kernel failed, * we will get EINVAL rather than, say, EFAULT on at least * some kernels. */ if (errno != EINVAL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s", pcap_strerror(errno)); return (-1); } /* * install_bpf_program() validates the program. * * XXX - what if we already have a filter in the kernel? */ if (install_bpf_program(p, fp) < 0) return (-1); p->md.use_bpf = 0; /* filtering in userland */ return (0); } /* * Set direction flag: Which packets do we accept on a forwarding * single device? IN, OUT or both? */ static int pcap_setdirection_bpf(pcap_t *p, pcap_direction_t d) { #if defined(BIOCSDIRECTION) u_int direction; direction = (d == PCAP_D_IN) ? BPF_D_IN : ((d == PCAP_D_OUT) ? BPF_D_OUT : BPF_D_INOUT); if (ioctl(p->fd, BIOCSDIRECTION, &direction) == -1) { (void) snprintf(p->errbuf, sizeof(p->errbuf), "Cannot set direction to %s: %s", (d == PCAP_D_IN) ? "PCAP_D_IN" : ((d == PCAP_D_OUT) ? "PCAP_D_OUT" : "PCAP_D_INOUT"), strerror(errno)); return (-1); } return (0); #elif defined(BIOCSSEESENT) u_int seesent; /* * We don't support PCAP_D_OUT. */ if (d == PCAP_D_OUT) { snprintf(p->errbuf, sizeof(p->errbuf), "Setting direction to PCAP_D_OUT is not supported on BPF"); return -1; } seesent = (d == PCAP_D_INOUT); if (ioctl(p->fd, BIOCSSEESENT, &seesent) == -1) { (void) snprintf(p->errbuf, sizeof(p->errbuf), "Cannot set direction to %s: %s", (d == PCAP_D_INOUT) ? "PCAP_D_INOUT" : "PCAP_D_IN", strerror(errno)); return (-1); } return (0); #else (void) snprintf(p->errbuf, sizeof(p->errbuf), "This system doesn't support BIOCSSEESENT, so the direction can't be set"); return (-1); #endif } static int pcap_set_datalink_bpf(pcap_t *p, int dlt) { #ifdef BIOCSDLT if (ioctl(p->fd, BIOCSDLT, &dlt) == -1) { (void) snprintf(p->errbuf, sizeof(p->errbuf), "Cannot set DLT %d: %s", dlt, strerror(errno)); return (-1); } #endif return (0); } Index: stable/9/contrib/libpcap/pcap-bt-linux.c =================================================================== --- stable/9/contrib/libpcap/pcap-bt-linux.c (revision 252280) +++ stable/9/contrib/libpcap/pcap-bt-linux.c (revision 252281) @@ -1,374 +1,407 @@ /* * Copyright (c) 2006 Paolo Abeni (Italy) * 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. The name of the author may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT * OWNER 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. * * Bluetooth sniffing API implementation for Linux platform * By Paolo Abeni * */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/pcap-bt-linux.c,v 1.15 2008-07-01 07:05:54 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "pcap-int.h" #include "pcap-bt-linux.h" #include "pcap/bluetooth.h" #ifdef NEED_STRERROR_H #include "strerror.h" #endif #include #include #include #include #include #include #include #include #include #include #define BT_IFACE "bluetooth" #define BT_CTRL_SIZE 128 /* forward declaration */ static int bt_activate(pcap_t *); static int bt_read_linux(pcap_t *, int , pcap_handler , u_char *); static int bt_inject_linux(pcap_t *, const void *, size_t); static int bt_setdirection_linux(pcap_t *, pcap_direction_t); static int bt_stats_linux(pcap_t *, struct pcap_stat *); int -bt_platform_finddevs(pcap_if_t **alldevsp, char *err_str) +bt_findalldevs(pcap_if_t **alldevsp, char *err_str) { pcap_if_t *found_dev = *alldevsp; struct hci_dev_list_req *dev_list; struct hci_dev_req *dev_req; int i, sock; int ret = 0; - + sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); if (sock < 0) { /* if bluetooth is not supported this this is not fatal*/ if (errno == EAFNOSUPPORT) return 0; snprintf(err_str, PCAP_ERRBUF_SIZE, "Can't open raw Bluetooth socket: %s", strerror(errno)); return -1; } dev_list = malloc(HCI_MAX_DEV * sizeof(*dev_req) + sizeof(*dev_list)); if (!dev_list) { snprintf(err_str, PCAP_ERRBUF_SIZE, "Can't allocate %zu bytes for Bluetooth device list", HCI_MAX_DEV * sizeof(*dev_req) + sizeof(*dev_list)); ret = -1; goto done; } dev_list->dev_num = HCI_MAX_DEV; if (ioctl(sock, HCIGETDEVLIST, (void *) dev_list) < 0) { snprintf(err_str, PCAP_ERRBUF_SIZE, "Can't get Bluetooth device list via ioctl: %s", strerror(errno)); ret = -1; goto free; } dev_req = dev_list->dev_req; for (i = 0; i < dev_list->dev_num; i++, dev_req++) { char dev_name[20], dev_descr[30]; snprintf(dev_name, 20, BT_IFACE"%d", dev_req->dev_id); snprintf(dev_descr, 30, "Bluetooth adapter number %d", i); if (pcap_add_if(&found_dev, dev_name, 0, dev_descr, err_str) < 0) { ret = -1; break; } } free: free(dev_list); done: close(sock); return ret; } pcap_t * -bt_create(const char *device, char *ebuf) +bt_create(const char *device, char *ebuf, int *is_ours) { + const char *cp; + char *cpend; + long devnum; pcap_t *p; + /* Does this look like a Bluetooth device? */ + cp = strrchr(device, '/'); + if (cp == NULL) + cp = device; + /* Does it begin with BT_IFACE? */ + if (strncmp(cp, BT_IFACE, sizeof BT_IFACE - 1) != 0) { + /* Nope, doesn't begin with BT_IFACE */ + *is_ours = 0; + return NULL; + } + /* Yes - is BT_IFACE followed by a number? */ + cp += sizeof BT_IFACE - 1; + devnum = strtol(cp, &cpend, 10); + if (cpend == cp || *cpend != '\0') { + /* Not followed by a number. */ + *is_ours = 0; + return NULL; + } + if (devnum < 0) { + /* Followed by a non-valid number. */ + *is_ours = 0; + return NULL; + } + + /* OK, it's probably ours. */ + *is_ours = 1; + p = pcap_create_common(device, ebuf); if (p == NULL) return (NULL); p->activate_op = bt_activate; return (p); } static int bt_activate(pcap_t* handle) { struct sockaddr_hci addr; int opt; int dev_id; struct hci_filter flt; int err = PCAP_ERROR; /* get bt interface id */ if (sscanf(handle->opt.source, BT_IFACE"%d", &dev_id) != 1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't get Bluetooth device index from %s", handle->opt.source); return PCAP_ERROR; } /* Initialize some components of the pcap structure. */ handle->bufsize = handle->snapshot+BT_CTRL_SIZE+sizeof(pcap_bluetooth_h4_header); handle->offset = BT_CTRL_SIZE; handle->linktype = DLT_BLUETOOTH_HCI_H4_WITH_PHDR; handle->read_op = bt_read_linux; handle->inject_op = bt_inject_linux; handle->setfilter_op = install_bpf_program; /* no kernel filtering */ handle->setdirection_op = bt_setdirection_linux; handle->set_datalink_op = NULL; /* can't change data link type */ handle->getnonblock_op = pcap_getnonblock_fd; handle->setnonblock_op = pcap_setnonblock_fd; handle->stats_op = bt_stats_linux; handle->md.ifindex = dev_id; /* Create HCI socket */ handle->fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); if (handle->fd < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't create raw socket: %s", strerror(errno)); return PCAP_ERROR; } handle->buffer = malloc(handle->bufsize); if (!handle->buffer) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate dump buffer: %s", pcap_strerror(errno)); goto close_fail; } opt = 1; if (setsockopt(handle->fd, SOL_HCI, HCI_DATA_DIR, &opt, sizeof(opt)) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't enable data direction info: %s", strerror(errno)); goto close_fail; } opt = 1; if (setsockopt(handle->fd, SOL_HCI, HCI_TIME_STAMP, &opt, sizeof(opt)) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't enable time stamp: %s", strerror(errno)); goto close_fail; } /* Setup filter, do not call hci function to avoid dependence on * external libs */ memset(&flt, 0, sizeof(flt)); memset((void *) &flt.type_mask, 0xff, sizeof(flt.type_mask)); memset((void *) &flt.event_mask, 0xff, sizeof(flt.event_mask)); if (setsockopt(handle->fd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't set filter: %s", strerror(errno)); goto close_fail; } /* Bind socket to the HCI device */ addr.hci_family = AF_BLUETOOTH; addr.hci_dev = handle->md.ifindex; +#ifdef SOCKADDR_HCI_HAS_HCI_CHANNEL + addr.hci_channel = HCI_CHANNEL_RAW; +#endif if (bind(handle->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't attach to device %d: %s", handle->md.ifindex, strerror(errno)); goto close_fail; } if (handle->opt.rfmon) { /* * Monitor mode doesn't apply to Bluetooth devices. */ err = PCAP_ERROR_RFMON_NOTSUP; goto close_fail; } if (handle->opt.buffer_size != 0) { /* * Set the socket buffer size to the specified value. */ if (setsockopt(handle->fd, SOL_SOCKET, SO_RCVBUF, &handle->opt.buffer_size, sizeof(handle->opt.buffer_size)) == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "SO_RCVBUF: %s", pcap_strerror(errno)); goto close_fail; } } handle->selectable_fd = handle->fd; return 0; close_fail: pcap_cleanup_live_common(handle); return err; } static int bt_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) { struct cmsghdr *cmsg; struct msghdr msg; struct iovec iv; ssize_t ret; struct pcap_pkthdr pkth; pcap_bluetooth_h4_header* bthdr; bthdr = (pcap_bluetooth_h4_header*) &handle->buffer[handle->offset]; iv.iov_base = &handle->buffer[handle->offset+sizeof(pcap_bluetooth_h4_header)]; iv.iov_len = handle->snapshot; memset(&msg, 0, sizeof(msg)); msg.msg_iov = &iv; msg.msg_iovlen = 1; msg.msg_control = handle->buffer; msg.msg_controllen = handle->offset; /* ignore interrupt system call error */ do { ret = recvmsg(handle->fd, &msg, 0); if (handle->break_loop) { handle->break_loop = 0; return -2; } } while ((ret == -1) && (errno == EINTR)); if (ret < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't receive packet: %s", strerror(errno)); return -1; } pkth.caplen = ret; /* get direction and timestamp*/ cmsg = CMSG_FIRSTHDR(&msg); int in=0; while (cmsg) { switch (cmsg->cmsg_type) { case HCI_CMSG_DIR: memcpy(&in, CMSG_DATA(cmsg), sizeof in); break; case HCI_CMSG_TSTAMP: memcpy(&pkth.ts, CMSG_DATA(cmsg), sizeof pkth.ts); break; } cmsg = CMSG_NXTHDR(&msg, cmsg); } if ((in && (handle->direction == PCAP_D_OUT)) || ((!in) && (handle->direction == PCAP_D_IN))) return 0; bthdr->direction = htonl(in != 0); pkth.caplen+=sizeof(pcap_bluetooth_h4_header); pkth.len = pkth.caplen; if (handle->fcode.bf_insns == NULL || bpf_filter(handle->fcode.bf_insns, &handle->buffer[handle->offset], pkth.len, pkth.caplen)) { callback(user, &pkth, &handle->buffer[handle->offset]); return 1; } return 0; /* didn't pass filter */ } static int bt_inject_linux(pcap_t *handle, const void *buf, size_t size) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on " "bluetooth devices"); return (-1); } static int bt_stats_linux(pcap_t *handle, struct pcap_stat *stats) { int ret; struct hci_dev_info dev_info; struct hci_dev_stats * s = &dev_info.stat; dev_info.dev_id = handle->md.ifindex; /* ignore eintr */ do { ret = ioctl(handle->fd, HCIGETDEVINFO, (void *)&dev_info); } while ((ret == -1) && (errno == EINTR)); if (ret < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't get stats via ioctl: %s", strerror(errno)); return (-1); } /* we receive both rx and tx frames, so comulate all stats */ stats->ps_recv = s->evt_rx + s->acl_rx + s->sco_rx + s->cmd_tx + s->acl_tx +s->sco_tx; stats->ps_drop = s->err_rx + s->err_tx; stats->ps_ifdrop = 0; return 0; } static int bt_setdirection_linux(pcap_t *p, pcap_direction_t d) { p->direction = d; return 0; } Index: stable/9/contrib/libpcap/pcap-bt-linux.h =================================================================== --- stable/9/contrib/libpcap/pcap-bt-linux.h (revision 252280) +++ stable/9/contrib/libpcap/pcap-bt-linux.h (revision 252281) @@ -1,40 +1,40 @@ /* * Copyright (c) 2006 Paolo Abeni (Italy) * 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. The name of the author may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT * OWNER 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. * * Bluetooth sniffing API implementation for Linux platform * By Paolo Abeni * * @(#) $Header: /tcpdump/master/libpcap/pcap-bt-linux.h,v 1.5 2008-04-04 19:37:45 guy Exp $ (LBL) */ /* * Prototypes for Bluetooth-related functions */ -int bt_platform_finddevs(pcap_if_t **alldevsp, char *err_str); -pcap_t *bt_create(const char *device, char *ebuf); +int bt_findalldevs(pcap_if_t **alldevsp, char *err_str); +pcap_t *bt_create(const char *device, char *ebuf, int *is_ours); Index: stable/9/contrib/libpcap/pcap-can-linux.c =================================================================== --- stable/9/contrib/libpcap/pcap-can-linux.c (revision 252280) +++ stable/9/contrib/libpcap/pcap-can-linux.c (revision 252281) @@ -1,264 +1,311 @@ /* * Copyright (c) 2009 Felix Obenhuber * 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. The name of the author may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT * OWNER 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. * * SocketCan sniffing API implementation for Linux platform * By Felix Obenhuber * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "pcap-int.h" #include "pcap-can-linux.h" #ifdef NEED_STRERROR_H #include "strerror.h" #endif #include #include #include #include #include #include #include #include #include #include #include /* not yet defined anywhere */ #ifndef PF_CAN #define PF_CAN 29 #endif #ifndef AF_CAN #define AF_CAN PF_CAN #endif /* forward declaration */ static int can_activate(pcap_t *); static int can_read_linux(pcap_t *, int , pcap_handler , u_char *); static int can_inject_linux(pcap_t *, const void *, size_t); static int can_setfilter_linux(pcap_t *, struct bpf_program *); static int can_setdirection_linux(pcap_t *, pcap_direction_t); static int can_stats_linux(pcap_t *, struct pcap_stat *); +int +can_findalldevs(pcap_if_t **devlistp, char *errbuf) +{ + /* + * There are no platform-specific devices since each device + * exists as a regular network interface. + * + * XXX - true? + */ + return 0; +} + pcap_t * -can_create(const char *device, char *ebuf) +can_create(const char *device, char *ebuf, int *is_ours) { + const char *cp; + char *cpend; + long devnum; pcap_t* p; + + /* Does this look like a CANbus device? */ + cp = strrchr(device, '/'); + if (cp == NULL) + cp = device; + /* Does it begin with "can" or "vcan"? */ + if (strncmp(cp, "can", 3) == 0) { + /* Begins with "can" */ + cp += 3; /* skip past "can" */ + } else if (strncmp(cp, "vcan", 4) == 0) { + /* Begins with "vcan" */ + cp += 4; + } else { + /* Nope, doesn't begin with "can" or "vcan" */ + *is_ours = 0; + return NULL; + } + /* Yes - is "can" or "vcan" followed by a number from 0? */ + devnum = strtol(cp, &cpend, 10); + if (cpend == cp || *cpend != '\0') { + /* Not followed by a number. */ + *is_ours = 0; + return NULL; + } + if (devnum < 0) { + /* Followed by a non-valid number. */ + *is_ours = 0; + return NULL; + } + + /* OK, it's probably ours. */ + *is_ours = 1; p = pcap_create_common(device, ebuf); if (p == NULL) return (NULL); p->activate_op = can_activate; return (p); } static int can_activate(pcap_t* handle) { struct sockaddr_can addr; struct ifreq ifr; /* Initialize some components of the pcap structure. */ handle->bufsize = 24; handle->offset = 8; handle->linktype = DLT_CAN_SOCKETCAN; handle->read_op = can_read_linux; handle->inject_op = can_inject_linux; handle->setfilter_op = can_setfilter_linux; handle->setdirection_op = can_setdirection_linux; handle->set_datalink_op = NULL; handle->getnonblock_op = pcap_getnonblock_fd; handle->setnonblock_op = pcap_setnonblock_fd; handle->stats_op = can_stats_linux; /* Create socket */ handle->fd = socket(PF_CAN, SOCK_RAW, CAN_RAW); if (handle->fd < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't create raw socket %d:%s", errno, strerror(errno)); return PCAP_ERROR; } /* get interface index */ memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, handle->opt.source, sizeof(ifr.ifr_name)); if (ioctl(handle->fd, SIOCGIFINDEX, &ifr) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Unable to get interface index: %s", pcap_strerror(errno)); pcap_cleanup_live_common(handle); return PCAP_ERROR; } handle->md.ifindex = ifr.ifr_ifindex; /* allocate butter */ handle->buffer = malloc(handle->bufsize); if (!handle->buffer) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate dump buffer: %s", pcap_strerror(errno)); pcap_cleanup_live_common(handle); return PCAP_ERROR; } /* Bind to the socket */ addr.can_family = AF_CAN; addr.can_ifindex = handle->md.ifindex; if( bind( handle->fd, (struct sockaddr*)&addr, sizeof(addr) ) < 0 ) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't attach to device %d %d:%s", handle->md.ifindex, errno, strerror(errno)); pcap_cleanup_live_common(handle); return PCAP_ERROR; } if (handle->opt.rfmon) { /* Monitor mode doesn't apply to CAN devices. */ pcap_cleanup_live_common(handle); return PCAP_ERROR; } handle->selectable_fd = handle->fd; return 0; } static int can_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) { struct msghdr msg; struct pcap_pkthdr pkth; struct iovec iv; struct can_frame* cf; iv.iov_base = &handle->buffer[handle->offset]; iv.iov_len = handle->snapshot; memset(&msg, 0, sizeof(msg)); msg.msg_iov = &iv; msg.msg_iovlen = 1; msg.msg_control = handle->buffer; msg.msg_controllen = handle->offset; do { pkth.caplen = recvmsg(handle->fd, &msg, 0); if (handle->break_loop) { handle->break_loop = 0; return -2; } } while ((pkth.caplen == -1) && (errno == EINTR)); if (pkth.caplen < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't receive packet %d:%s", errno, strerror(errno)); return -1; } /* adjust capture len according to frame len */ cf = (struct can_frame*)&handle->buffer[8]; pkth.caplen -= 8 - cf->can_dlc; pkth.len = pkth.caplen; cf->can_id = htonl( cf->can_id ); if( -1 == gettimeofday(&pkth.ts, NULL) ) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't get time of day %d:%s", errno, strerror(errno)); return -1; } callback(user, &pkth, &handle->buffer[8]); return 1; } static int can_inject_linux(pcap_t *handle, const void *buf, size_t size) { /* not yet implemented */ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on " "can devices"); return (-1); } static int can_stats_linux(pcap_t *handle, struct pcap_stat *stats) { /* not yet implemented */ stats->ps_recv = 0; /* number of packets received */ stats->ps_drop = 0; /* number of packets dropped */ stats->ps_ifdrop = 0; /* drops by interface -- only supported on some platforms */ return 0; } static int can_setfilter_linux(pcap_t *p, struct bpf_program *fp) { /* not yet implemented */ return 0; } static int can_setdirection_linux(pcap_t *p, pcap_direction_t d) { /* no support for PCAP_D_OUT */ if (d == PCAP_D_OUT) { snprintf(p->errbuf, sizeof(p->errbuf), "Setting direction to PCAP_D_OUT is not supported on can"); return -1; } p->direction = d; return 0; } /* eof */ Index: stable/9/contrib/libpcap/pcap-can-linux.h =================================================================== --- stable/9/contrib/libpcap/pcap-can-linux.h (revision 252280) +++ stable/9/contrib/libpcap/pcap-can-linux.h (revision 252281) @@ -1,35 +1,36 @@ /* * Copyright (c) 2009 Felix Obenhuber * 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. The name of the author may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT * OWNER 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. * */ /* * Prototypes for SocketCAN related functions */ -pcap_t* can_create(const char *device, char *ebuf); +pcap_t* can_create(const char *device, char *ebuf, int *is_ours); +int can_findalldevs(pcap_if_t **devlistp, char *errbuf); Index: stable/9/contrib/libpcap/pcap-canusb-linux.c =================================================================== --- stable/9/contrib/libpcap/pcap-canusb-linux.c (revision 252280) +++ stable/9/contrib/libpcap/pcap-canusb-linux.c (revision 252281) @@ -1,428 +1,467 @@ /* * Copyright (c) 2009 Felix Obenhuber * 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. The name of the author may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT * OWNER 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. * * Sockettrace sniffing API implementation for Linux platform * By Felix Obenhuber * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "pcap-int.h" #include #include #include #include #define CANUSB_IFACE "canusb" #define CANUSB_VID 0x0403 #define CANUSB_PID 0x8990 #define USE_THREAD 1 #if USE_THREAD == 0 #include #endif /* forward declaration */ static int canusb_activate(pcap_t *); static int canusb_read_linux(pcap_t *, int , pcap_handler , u_char *); static int canusb_inject_linux(pcap_t *, const void *, size_t); static int canusb_setfilter_linux(pcap_t *, struct bpf_program *); static int canusb_setdirection_linux(pcap_t *, pcap_direction_t); static int canusb_stats_linux(pcap_t *, struct pcap_stat *); struct CAN_Msg { uint32_t timestamp; uint32_t id; uint32_t length; uint8_t data[8]; }; struct canusb_t { - libusb_context *ctx; - libusb_device_handle *dev; - char* src; - pthread_t worker; - int rdpipe, wrpipe; - volatile int* loop; + libusb_context *ctx; + libusb_device_handle *dev; + char *serial; + pthread_t worker; + int rdpipe, wrpipe; + volatile int* loop; }; static struct canusb_t canusb; static volatile int loop; - - -int canusb_platform_finddevs(pcap_if_t **alldevsp, char *err_str) +int canusb_findalldevs(pcap_if_t **alldevsp, char *err_str) { libusb_context *fdctx; libusb_device** devs; unsigned char sernum[65]; unsigned char buf[96]; int cnt, i; - libusb_init(&fdctx); - + if (libusb_init(&fdctx) != 0) { + /* + * XXX - if this doesn't just mean "no USB file system mounted", + * perhaps we should report a real error rather than just + * saying "no CANUSB devices". + */ + return 0; + } + cnt = libusb_get_device_list(fdctx,&devs); for(i=0;iactivate_op = canusb_activate; - - canusb.src = strdup(p->opt.source); - return (p); + const char *cp; + char *cpend; + long devnum; + pcap_t* p; + + libusb_init(&canusb.ctx); + + /* Does this look like a DAG device? */ + cp = strrchr(device, '/'); + if (cp == NULL) + cp = device; + /* Does it begin with "canusb"? */ + if (strncmp(cp, "canusb", 6) != 0) { + /* Nope, doesn't begin with "canusb" */ + *is_ours = 0; + return NULL; + } + /* Yes - is "canusb" followed by a number? */ + cp += 6; + devnum = strtol(cp, &cpend, 10); + if (cpend == cp || *cpend != '\0') { + /* Not followed by a number. */ + *is_ours = 0; + return NULL; + } + if (devnum < 0) { + /* Followed by a non-valid number. */ + *is_ours = 0; + return NULL; + } + + /* OK, it's probably ours. */ + *is_ours = 1; + + p = pcap_create_common(device, ebuf); + if (p == NULL) + return (NULL); + + memset(&canusb, 0x00, sizeof(canusb)); + + p->activate_op = canusb_activate; + + return (p); } static void* canusb_capture_thread(struct canusb_t *canusb) { - struct libusb_context *ctx; - libusb_device_handle *dev; - - int i, n; - struct - { - uint8_t rxsz, txsz; - } status; + struct libusb_context *ctx; + libusb_device_handle *dev; + int i, n; + struct + { + uint8_t rxsz, txsz; + } status; + char *serial; - libusb_init(&ctx); + libusb_init(&ctx); - char *serial = canusb->src + strlen(CANUSB_IFACE); - dev = canusb_opendevice(ctx, serial); + serial = canusb->serial; + dev = canusb_opendevice(ctx, serial); - fcntl(canusb->wrpipe, F_SETFL, O_NONBLOCK); + fcntl(canusb->wrpipe, F_SETFL, O_NONBLOCK); - while(*canusb->loop) - { - int sz, ret; - struct CAN_Msg msg; + while(*canusb->loop) + { + int sz, ret; + struct CAN_Msg msg; - libusb_interrupt_transfer(dev, 0x81, (unsigned char*)&status, sizeof(status), &sz, 100); - //HACK!!!!! -> drop buffered data, read new one by reading twice. - ret = libusb_interrupt_transfer(dev, 0x81, (unsigned char*)&status, sizeof(status), &sz, 100); + libusb_interrupt_transfer(dev, 0x81, (unsigned char*)&status, sizeof(status), &sz, 100); + //HACK!!!!! -> drop buffered data, read new one by reading twice. + ret = libusb_interrupt_transfer(dev, 0x81, (unsigned char*)&status, sizeof(status), &sz, 100); - for(i = 0; iwrpipe, &msg, sizeof(msg)); - } + for(i = 0; iwrpipe, &msg, sizeof(msg)); + } - } + } - libusb_close(dev); - libusb_exit(ctx); + libusb_close(dev); + libusb_exit(ctx); - return NULL; + return NULL; } static int canusb_startcapture(struct canusb_t* this) { - int pipefd[2]; + int pipefd[2]; - if (pipe(pipefd) == -1) return -1; + if (pipe(pipefd) == -1) + return -1; - canusb.rdpipe = pipefd[0]; - canusb.wrpipe = pipefd[1]; - canusb.loop = &loop; + canusb.rdpipe = pipefd[0]; + canusb.wrpipe = pipefd[1]; + canusb.loop = &loop; - loop = 1; - pthread_create(&this->worker, NULL, canusb_capture_thread, &canusb); + loop = 1; + pthread_create(&this->worker, NULL, canusb_capture_thread, &canusb); - return canusb.rdpipe; + return canusb.rdpipe; } static void canusb_clearbufs(struct canusb_t* this) { - unsigned char cmd[16]; - int al; + unsigned char cmd[16]; + int al; - cmd[0] = 1; //Empty incoming buffer - cmd[1] = 1; //Empty outgoing buffer - cmd[3] = 0; //Not a write to serial number - memset(&cmd[4],0,16-4); + cmd[0] = 1; //Empty incoming buffer + cmd[1] = 1; //Empty outgoing buffer + cmd[3] = 0; //Not a write to serial number + memset(&cmd[4],0,16-4); - libusb_interrupt_transfer(this->dev, 0x1,cmd,16,&al,100); + libusb_interrupt_transfer(this->dev, 0x1,cmd,16,&al,100); } static void canusb_close(pcap_t* handle) { - loop = 0; - pthread_join(canusb.worker, NULL); + loop = 0; + pthread_join(canusb.worker, NULL); - if (canusb.dev) - { - libusb_close(canusb.dev); - canusb.dev = NULL; - } + if (canusb.dev) + { + libusb_close(canusb.dev); + canusb.dev = NULL; + } } static int canusb_activate(pcap_t* handle) { - handle->read_op = canusb_read_linux; + char *serial; - handle->inject_op = canusb_inject_linux; - handle->setfilter_op = canusb_setfilter_linux; - handle->setdirection_op = canusb_setdirection_linux; - handle->getnonblock_op = pcap_getnonblock_fd; - handle->setnonblock_op = pcap_setnonblock_fd; - handle->stats_op = canusb_stats_linux; - handle->cleanup_op = canusb_close; + handle->read_op = canusb_read_linux; - /* Initialize some components of the pcap structure. */ - handle->bufsize = 32; - handle->offset = 8; - handle->linktype = DLT_CAN_SOCKETCAN; - handle->set_datalink_op = NULL; + handle->inject_op = canusb_inject_linux; + handle->setfilter_op = canusb_setfilter_linux; + handle->setdirection_op = canusb_setdirection_linux; + handle->getnonblock_op = pcap_getnonblock_fd; + handle->setnonblock_op = pcap_setnonblock_fd; + handle->stats_op = canusb_stats_linux; + handle->cleanup_op = canusb_close; - char* serial = handle->opt.source + strlen("canusb"); + /* Initialize some components of the pcap structure. */ + handle->bufsize = 32; + handle->offset = 8; + handle->linktype = DLT_CAN_SOCKETCAN; + handle->set_datalink_op = NULL; - canusb.dev = canusb_opendevice(canusb.ctx,serial); - if (!canusb.dev) - { - snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't open USB Device:"); - return PCAP_ERROR; - } + serial = handle->opt.source + strlen(CANUSB_IFACE); + canusb.serial = strdup(serial); - canusb_clearbufs(&canusb); + canusb.dev = canusb_opendevice(canusb.ctx,serial); + if (!canusb.dev) + { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't open USB Device:"); + return PCAP_ERROR; + } - handle->fd = canusb_startcapture(&canusb); - handle->selectable_fd = handle->fd; - - return 0; + canusb_clearbufs(&canusb); + + handle->fd = canusb_startcapture(&canusb); + handle->selectable_fd = handle->fd; + + return 0; } static int canusb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) { - static struct timeval firstpacket = { -1, -1}; + static struct timeval firstpacket = { -1, -1}; - int msgsent = 0; - int i = 0; - struct CAN_Msg msg; - struct pcap_pkthdr pkth; + int msgsent = 0; + int i = 0; + struct CAN_Msg msg; + struct pcap_pkthdr pkth; - while(i < max_packets) - { - usleep(10 * 1000); - int n = read(handle->fd, &msg, sizeof(msg)); - if (n <= 0) break; - pkth.caplen = pkth.len = n; - pkth.caplen -= 4; - pkth.caplen -= 8 - msg.length; + while(i < max_packets) + { + int n; + usleep(10 * 1000); + n = read(handle->fd, &msg, sizeof(msg)); + if (n <= 0) + break; + pkth.caplen = pkth.len = n; + pkth.caplen -= 4; + pkth.caplen -= 8 - msg.length; - if ((firstpacket.tv_sec == -1) && (firstpacket.tv_usec == -1)) - gettimeofday(&firstpacket, NULL); + if ((firstpacket.tv_sec == -1) && (firstpacket.tv_usec == -1)) + gettimeofday(&firstpacket, NULL); - pkth.ts.tv_usec = firstpacket.tv_usec + (msg.timestamp % 100) * 10000; - pkth.ts.tv_sec = firstpacket.tv_usec + (msg.timestamp / 100); - if (pkth.ts.tv_usec > 1000000) - { - pkth.ts.tv_usec -= 1000000; - pkth.ts.tv_sec++; - } + pkth.ts.tv_usec = firstpacket.tv_usec + (msg.timestamp % 100) * 10000; + pkth.ts.tv_sec = firstpacket.tv_usec + (msg.timestamp / 100); + if (pkth.ts.tv_usec > 1000000) + { + pkth.ts.tv_usec -= 1000000; + pkth.ts.tv_sec++; + } - callback(user, &pkth, (void*)&msg.id); - i++; - } + callback(user, &pkth, (void*)&msg.id); + i++; + } - return i; + return i; } static int canusb_inject_linux(pcap_t *handle, const void *buf, size_t size) { - /* not yet implemented */ - snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on canusb devices"); - return (-1); + /* not yet implemented */ + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on canusb devices"); + return (-1); } static int canusb_stats_linux(pcap_t *handle, struct pcap_stat *stats) { - /* not yet implemented */ - stats->ps_recv = 0; /* number of packets received */ - stats->ps_drop = 0; /* number of packets dropped */ - stats->ps_ifdrop = 0; /* drops by interface -- only supported on some platforms */ - return 0; + /* not yet implemented */ + stats->ps_recv = 0; /* number of packets received */ + stats->ps_drop = 0; /* number of packets dropped */ + stats->ps_ifdrop = 0; /* drops by interface -- only supported on some platforms */ + return 0; } static int canusb_setfilter_linux(pcap_t *p, struct bpf_program *fp) { - /* not yet implemented */ - return 0; + /* not yet implemented */ + return 0; } static int canusb_setdirection_linux(pcap_t *p, pcap_direction_t d) { - /* no support for PCAP_D_OUT */ - if (d == PCAP_D_OUT) - { - snprintf(p->errbuf, sizeof(p->errbuf), - "Setting direction to PCAP_D_OUT is not supported on this interface"); - return -1; - } + /* no support for PCAP_D_OUT */ + if (d == PCAP_D_OUT) + { + snprintf(p->errbuf, sizeof(p->errbuf), + "Setting direction to PCAP_D_OUT is not supported on this interface"); + return -1; + } - p->direction = d; + p->direction = d; - return 0; + return 0; } /* eof */ Index: stable/9/contrib/libpcap/pcap-canusb-linux.h =================================================================== --- stable/9/contrib/libpcap/pcap-canusb-linux.h (revision 252280) +++ stable/9/contrib/libpcap/pcap-canusb-linux.h (revision 252281) @@ -1,37 +1,37 @@ /* * Copyright (c) 2009 Felix Obenhuber * 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. The name of the author may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT * OWNER 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. * */ /* * Prototypes for SocketCAN related functions */ -pcap_t* canusb_create(const char *device, char *ebuf); -int canusb_listdevices(pcap_if_t **pdevlist, char* errbuf); +pcap_t* canusb_create(const char *device, char *ebuf, int *is_ours); +int canusb_findalldevs(pcap_if_t **pdevlist, char* errbuf); Index: stable/9/contrib/libpcap/pcap-common.c =================================================================== --- stable/9/contrib/libpcap/pcap-common.c (revision 252280) +++ stable/9/contrib/libpcap/pcap-common.c (revision 252281) @@ -1,1158 +1,1172 @@ /* * Copyright (c) 1993, 1994, 1995, 1996, 1997 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * pcap-common.c - common code for pcap and pcap-ng files */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef WIN32 #include #else /* WIN32 */ #if HAVE_INTTYPES_H #include #elif HAVE_STDINT_H #include #endif #ifdef HAVE_SYS_BITYPES_H #include #endif #include #endif /* WIN32 */ #include "pcap-int.h" #include "pcap/usb.h" #include "pcap-common.h" /* * We don't write DLT_* values to capture files, because they're not the * same on all platforms. * * Unfortunately, the various flavors of BSD have not always used the same * numerical values for the same data types, and various patches to * libpcap for non-BSD OSes have added their own DLT_* codes for link * layer encapsulation types seen on those OSes, and those codes have had, * in some cases, values that were also used, on other platforms, for other * link layer encapsulation types. * * This means that capture files of a type whose numerical DLT_* code * means different things on different BSDs, or with different versions * of libpcap, can't always be read on systems other than those like * the one running on the machine on which the capture was made. * * Instead, we define here a set of LINKTYPE_* codes, and map DLT_* codes * to LINKTYPE_* codes when writing a savefile header, and map LINKTYPE_* * codes to DLT_* codes when reading a savefile header. * * For those DLT_* codes that have, as far as we know, the same values on * all platforms (DLT_NULL through DLT_FDDI), we define LINKTYPE_xxx as * DLT_xxx; that way, captures of those types can still be read by * versions of libpcap that map LINKTYPE_* values to DLT_* values, and * captures of those types written by versions of libpcap that map DLT_ * values to LINKTYPE_ values can still be read by older versions * of libpcap. * * The other LINKTYPE_* codes are given values starting at 100, in the * hopes that no DLT_* code will be given one of those values. * * In order to ensure that a given LINKTYPE_* code's value will refer to * the same encapsulation type on all platforms, you should not allocate * a new LINKTYPE_* value without consulting * "tcpdump-workers@lists.tcpdump.org". The tcpdump developers will * allocate a value for you, and will not subsequently allocate it to * anybody else; that value will be added to the "pcap.h" in the * tcpdump.org Git repository, so that a future libpcap release will * include it. * * You should, if possible, also contribute patches to libpcap and tcpdump * to handle the new encapsulation type, so that they can also be checked * into the tcpdump.org Git repository and so that they will appear in * future libpcap and tcpdump releases. * * Do *NOT* assume that any values after the largest value in this file * are available; you might not have the most up-to-date version of this * file, and new values after that one might have been assigned. Also, * do *NOT* use any values below 100 - those might already have been * taken by one (or more!) organizations. * * Any platform that defines additional DLT_* codes should: * * request a LINKTYPE_* code and value from tcpdump.org, * as per the above; * * add, in their version of libpcap, an entry to map * those DLT_* codes to the corresponding LINKTYPE_* * code; * * redefine, in their "net/bpf.h", any DLT_* values * that collide with the values used by their additional * DLT_* codes, to remove those collisions (but without * making them collide with any of the LINKTYPE_* * values equal to 50 or above; they should also avoid * defining DLT_* values that collide with those * LINKTYPE_* values, either). */ #define LINKTYPE_NULL DLT_NULL #define LINKTYPE_ETHERNET DLT_EN10MB /* also for 100Mb and up */ #define LINKTYPE_EXP_ETHERNET DLT_EN3MB /* 3Mb experimental Ethernet */ #define LINKTYPE_AX25 DLT_AX25 #define LINKTYPE_PRONET DLT_PRONET #define LINKTYPE_CHAOS DLT_CHAOS #define LINKTYPE_IEEE802_5 DLT_IEEE802 /* DLT_IEEE802 is used for 802.5 Token Ring */ #define LINKTYPE_ARCNET_BSD DLT_ARCNET /* BSD-style headers */ #define LINKTYPE_SLIP DLT_SLIP #define LINKTYPE_PPP DLT_PPP #define LINKTYPE_FDDI DLT_FDDI /* * LINKTYPE_PPP is for use when there might, or might not, be an RFC 1662 * PPP in HDLC-like framing header (with 0xff 0x03 before the PPP protocol * field) at the beginning of the packet. * * This is for use when there is always such a header; the address field * might be 0xff, for regular PPP, or it might be an address field for Cisco * point-to-point with HDLC framing as per section 4.3.1 of RFC 1547 ("Cisco * HDLC"). This is, for example, what you get with NetBSD's DLT_PPP_SERIAL. * * We give it the same value as NetBSD's DLT_PPP_SERIAL, in the hopes that * nobody else will choose a DLT_ value of 50, and so that DLT_PPP_SERIAL * captures will be written out with a link type that NetBSD's tcpdump * can read. */ #define LINKTYPE_PPP_HDLC 50 /* PPP in HDLC-like framing */ #define LINKTYPE_PPP_ETHER 51 /* NetBSD PPP-over-Ethernet */ #define LINKTYPE_SYMANTEC_FIREWALL 99 /* Symantec Enterprise Firewall */ /* * These correspond to DLT_s that have different values on different * platforms; we map between these values in capture files and * the DLT_ values as returned by pcap_datalink() and passed to * pcap_open_dead(). */ #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 */ /* * Values starting with 104 are used for newly-assigned link-layer * header type values; for those link-layer header types, the DLT_ * value returned by pcap_datalink() and passed to pcap_open_dead(), * and the LINKTYPE_ value that appears in capture files, are the * same. * * LINKTYPE_MATCHING_MIN is the lowest such value; LINKTYPE_MATCHING_MAX * is the highest such value. */ #define LINKTYPE_MATCHING_MIN 104 /* lowest value in the "matching" range */ #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_FRELAY 107 /* Frame Relay */ #define LINKTYPE_LOOP 108 /* OpenBSD loopback */ #define LINKTYPE_ENC 109 /* OpenBSD IPSEC enc */ /* * These three types are reserved for future use. */ #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_LTALK 114 /* Apple LocalTalk hardware */ #define LINKTYPE_ECONET 115 /* Acorn Econet */ /* * Reserved for use with OpenBSD ipfilter. */ #define LINKTYPE_IPFILTER 116 #define LINKTYPE_PFLOG 117 /* OpenBSD DLT_PFLOG */ #define LINKTYPE_CISCO_IOS 118 /* For Cisco-internal use */ #define LINKTYPE_IEEE802_11_PRISM 119 /* 802.11 plus Prism II monitor mode radio metadata header */ #define LINKTYPE_IEEE802_11_AIRONET 120 /* 802.11 plus FreeBSD Aironet driver radio metadata header */ /* * Reserved for Siemens HiPath HDLC. */ #define LINKTYPE_HHDLC 121 #define LINKTYPE_IP_OVER_FC 122 /* RFC 2625 IP-over-Fibre Channel */ #define LINKTYPE_SUNATM 123 /* Solaris+SunATM */ /* * Reserved as per request from Kent Dahlgren * for private use. */ #define LINKTYPE_RIO 124 /* RapidIO */ #define LINKTYPE_PCI_EXP 125 /* PCI Express */ #define LINKTYPE_AURORA 126 /* Xilinx Aurora link layer */ #define LINKTYPE_IEEE802_11_RADIOTAP 127 /* 802.11 plus radiotap radio metadata header */ /* * Reserved for the TZSP encapsulation, as per request from * Chris Waters * TZSP is a generic encapsulation for any other link type, * which includes a means to include meta-information * with the packet, e.g. signal strength and channel * for 802.11 packets. */ #define LINKTYPE_TZSP 128 /* Tazmen Sniffer Protocol */ #define LINKTYPE_ARCNET_LINUX 129 /* Linux-style headers */ /* * Juniper-private data link types, as per request from * Hannes Gredler . The corresponding * DLT_s are used for passing on chassis-internal * metainformation such as QOS profiles, etc.. */ #define LINKTYPE_JUNIPER_MLPPP 130 #define LINKTYPE_JUNIPER_MLFR 131 #define LINKTYPE_JUNIPER_ES 132 #define LINKTYPE_JUNIPER_GGSN 133 #define LINKTYPE_JUNIPER_MFR 134 #define LINKTYPE_JUNIPER_ATM2 135 #define LINKTYPE_JUNIPER_SERVICES 136 #define LINKTYPE_JUNIPER_ATM1 137 #define LINKTYPE_APPLE_IP_OVER_IEEE1394 138 /* Apple IP-over-IEEE 1394 cooked header */ #define LINKTYPE_MTP2_WITH_PHDR 139 #define LINKTYPE_MTP2 140 #define LINKTYPE_MTP3 141 #define LINKTYPE_SCCP 142 #define LINKTYPE_DOCSIS 143 /* DOCSIS MAC frames */ #define LINKTYPE_LINUX_IRDA 144 /* Linux-IrDA */ /* * Reserved for IBM SP switch and IBM Next Federation switch. */ #define LINKTYPE_IBM_SP 145 #define LINKTYPE_IBM_SN 146 /* * Reserved for private use. If you have some link-layer header type * that you want to use within your organization, with the capture files * using that link-layer header type not ever be sent outside your * organization, you can use these values. * * No libpcap release will use these for any purpose, nor will any * tcpdump release use them, either. * * Do *NOT* use these in capture files that you expect anybody not using * your private versions of capture-file-reading tools to read; in * particular, do *NOT* use them in products, otherwise you may find that * people won't be able to use tcpdump, or snort, or Ethereal, or... to * read capture files from your firewall/intrusion detection/traffic * monitoring/etc. appliance, or whatever product uses that LINKTYPE_ value, * and you may also find that the developers of those applications will * not accept patches to let them read those files. * * Also, do not use them if somebody might send you a capture using them * for *their* private type and tools using them for *your* private type * would have to read them. * * Instead, in those cases, ask "tcpdump-workers@lists.tcpdump.org" for a * new DLT_ and LINKTYPE_ value, as per the comment in pcap/bpf.h, and use * the type you're given. */ #define LINKTYPE_USER0 147 #define LINKTYPE_USER1 148 #define LINKTYPE_USER2 149 #define LINKTYPE_USER3 150 #define LINKTYPE_USER4 151 #define LINKTYPE_USER5 152 #define LINKTYPE_USER6 153 #define LINKTYPE_USER7 154 #define LINKTYPE_USER8 155 #define LINKTYPE_USER9 156 #define LINKTYPE_USER10 157 #define LINKTYPE_USER11 158 #define LINKTYPE_USER12 159 #define LINKTYPE_USER13 160 #define LINKTYPE_USER14 161 #define LINKTYPE_USER15 162 /* * For future use with 802.11 captures - defined by AbsoluteValue * Systems to store a number of bits of link-layer information * including radio information: * * http://www.shaftnet.org/~pizza/software/capturefrm.txt */ #define LINKTYPE_IEEE802_11_AVS 163 /* 802.11 plus AVS radio metadata header */ /* * Juniper-private data link type, as per request from * Hannes Gredler . The corresponding * DLT_s are used for passing on chassis-internal * metainformation such as QOS profiles, etc.. */ #define LINKTYPE_JUNIPER_MONITOR 164 /* * BACnet MS/TP frames. */ #define LINKTYPE_BACNET_MS_TP 165 /* * Another PPP variant as per request from Karsten Keil . * * This is used in some OSes to allow a kernel socket filter to distinguish * between incoming and outgoing packets, on a socket intended to * supply pppd with outgoing packets so it can do dial-on-demand and * hangup-on-lack-of-demand; incoming packets are filtered out so they * don't cause pppd to hold the connection up (you don't want random * input packets such as port scans, packets from old lost connections, * etc. to force the connection to stay up). * * The first byte of the PPP header (0xff03) is modified to accomodate * the direction - 0x00 = IN, 0x01 = OUT. */ #define LINKTYPE_PPP_PPPD 166 /* * Juniper-private data link type, as per request from * Hannes Gredler . The DLT_s are used * for passing on chassis-internal metainformation such as * QOS profiles, cookies, etc.. */ #define LINKTYPE_JUNIPER_PPPOE 167 #define LINKTYPE_JUNIPER_PPPOE_ATM 168 #define LINKTYPE_GPRS_LLC 169 /* GPRS LLC */ #define LINKTYPE_GPF_T 170 /* GPF-T (ITU-T G.7041/Y.1303) */ #define LINKTYPE_GPF_F 171 /* GPF-T (ITU-T G.7041/Y.1303) */ /* * Requested by Oolan Zimmer for use in Gcom's T1/E1 line * monitoring equipment. */ #define LINKTYPE_GCOM_T1E1 172 #define LINKTYPE_GCOM_SERIAL 173 /* * Juniper-private data link type, as per request from * Hannes Gredler . The DLT_ is used * for internal communication to Physical Interface Cards (PIC) */ #define LINKTYPE_JUNIPER_PIC_PEER 174 /* * Link types requested by Gregor Maier of Endace * Measurement Systems. They add an ERF header (see * http://www.endace.com/support/EndaceRecordFormat.pdf) in front of * the link-layer header. */ #define LINKTYPE_ERF_ETH 175 /* Ethernet */ #define LINKTYPE_ERF_POS 176 /* Packet-over-SONET */ /* * Requested by Daniele Orlandi for raw LAPD * for vISDN (http://www.orlandi.com/visdn/). Its link-layer header * includes additional information before the LAPD header, so it's * not necessarily a generic LAPD header. */ #define LINKTYPE_LINUX_LAPD 177 /* * Juniper-private data link type, as per request from * Hannes Gredler . * The Link Types are used for prepending meta-information * like interface index, interface name * before standard Ethernet, PPP, Frelay & C-HDLC Frames */ #define LINKTYPE_JUNIPER_ETHER 178 #define LINKTYPE_JUNIPER_PPP 179 #define LINKTYPE_JUNIPER_FRELAY 180 #define LINKTYPE_JUNIPER_CHDLC 181 /* * Multi Link Frame Relay (FRF.16) */ #define LINKTYPE_MFR 182 /* * Juniper-private data link type, as per request from * Hannes Gredler . * The DLT_ is used for internal communication with a * voice Adapter Card (PIC) */ #define LINKTYPE_JUNIPER_VP 183 /* * Arinc 429 frames. * DLT_ requested by Gianluca Varenni . * Every frame contains a 32bit A429 label. * More documentation on Arinc 429 can be found at * http://www.condoreng.com/support/downloads/tutorials/ARINCTutorial.pdf */ #define LINKTYPE_A429 184 /* * Arinc 653 Interpartition Communication messages. * DLT_ requested by Gianluca Varenni . * Please refer to the A653-1 standard for more information. */ #define LINKTYPE_A653_ICM 185 /* * USB packets, beginning with a USB setup header; requested by * Paolo Abeni . */ #define LINKTYPE_USB 186 /* * Bluetooth HCI UART transport layer (part H:4); requested by * Paolo Abeni. */ #define LINKTYPE_BLUETOOTH_HCI_H4 187 /* * IEEE 802.16 MAC Common Part Sublayer; requested by Maria Cruz * . */ #define LINKTYPE_IEEE802_16_MAC_CPS 188 /* * USB packets, beginning with a Linux USB header; requested by * Paolo Abeni . */ #define LINKTYPE_USB_LINUX 189 /* * Controller Area Network (CAN) v. 2.0B packets. * DLT_ requested by Gianluca Varenni . * Used to dump CAN packets coming from a CAN Vector board. * More documentation on the CAN v2.0B frames can be found at * http://www.can-cia.org/downloads/?269 */ #define LINKTYPE_CAN20B 190 /* * IEEE 802.15.4, with address fields padded, as is done by Linux * drivers; requested by Juergen Schimmer. */ #define LINKTYPE_IEEE802_15_4_LINUX 191 /* * Per Packet Information encapsulated packets. * LINKTYPE_ requested by Gianluca Varenni . */ #define LINKTYPE_PPI 192 /* * Header for 802.16 MAC Common Part Sublayer plus a radiotap radio header; * requested by Charles Clancy. */ #define LINKTYPE_IEEE802_16_MAC_CPS_RADIO 193 /* * Juniper-private data link type, as per request from * Hannes Gredler . * The DLT_ is used for internal communication with a * integrated service module (ISM). */ #define LINKTYPE_JUNIPER_ISM 194 /* * IEEE 802.15.4, exactly as it appears in the spec (no padding, no * nothing); requested by Mikko Saarnivala . */ #define LINKTYPE_IEEE802_15_4 195 /* * Various link-layer types, with a pseudo-header, for SITA * (http://www.sita.aero/); requested by Fulko Hew (fulko.hew@gmail.com). */ #define LINKTYPE_SITA 196 /* * Various link-layer types, with a pseudo-header, for Endace DAG cards; * encapsulates Endace ERF records. Requested by Stephen Donnelly * . */ #define LINKTYPE_ERF 197 /* * Special header prepended to Ethernet packets when capturing from a * u10 Networks board. Requested by Phil Mulholland * . */ #define LINKTYPE_RAIF1 198 /* * IPMB packet for IPMI, beginning with the I2C slave address, followed * by the netFn and LUN, etc.. Requested by Chanthy Toeung * . */ #define LINKTYPE_IPMB 199 /* * Juniper-private data link type, as per request from * Hannes Gredler . * The DLT_ is used for capturing data on a secure tunnel interface. */ #define LINKTYPE_JUNIPER_ST 200 /* * Bluetooth HCI UART transport layer (part H:4), with pseudo-header * that includes direction information; requested by Paolo Abeni. */ #define LINKTYPE_BLUETOOTH_HCI_H4_WITH_PHDR 201 /* * AX.25 packet with a 1-byte KISS header; see * * http://www.ax25.net/kiss.htm * * as per Richard Stearn . */ #define LINKTYPE_AX25_KISS 202 /* * LAPD packets from an ISDN channel, starting with the address field, * with no pseudo-header. * Requested by Varuna De Silva . */ #define LINKTYPE_LAPD 203 /* * Variants of various link-layer headers, with a one-byte direction * pseudo-header prepended - zero means "received by this host", * non-zero (any non-zero value) means "sent by this host" - as per * Will Barker . */ #define LINKTYPE_PPP_WITH_DIR 204 /* PPP */ #define LINKTYPE_C_HDLC_WITH_DIR 205 /* Cisco HDLC */ #define LINKTYPE_FRELAY_WITH_DIR 206 /* Frame Relay */ #define LINKTYPE_LAPB_WITH_DIR 207 /* LAPB */ /* * 208 is reserved for an as-yet-unspecified proprietary link-layer * type, as requested by Will Barker. */ /* * IPMB with a Linux-specific pseudo-header; as requested by Alexey Neyman * . */ #define LINKTYPE_IPMB_LINUX 209 /* * FlexRay automotive bus - http://www.flexray.com/ - as requested * by Hannes Kaelber . */ #define LINKTYPE_FLEXRAY 210 /* * Media Oriented Systems Transport (MOST) bus for multimedia * transport - http://www.mostcooperation.com/ - as requested * by Hannes Kaelber . */ #define LINKTYPE_MOST 211 /* * Local Interconnect Network (LIN) bus for vehicle networks - * http://www.lin-subbus.org/ - as requested by Hannes Kaelber * . */ #define LINKTYPE_LIN 212 /* * X2E-private data link type used for serial line capture, * as requested by Hannes Kaelber . */ #define LINKTYPE_X2E_SERIAL 213 /* * X2E-private data link type used for the Xoraya data logger * family, as requested by Hannes Kaelber . */ #define LINKTYPE_X2E_XORAYA 214 /* * IEEE 802.15.4, exactly as it appears in the spec (no padding, no * nothing), but with the PHY-level data for non-ASK PHYs (4 octets * of 0 as preamble, one octet of SFD, one octet of frame length+ * reserved bit, and then the MAC-layer data, starting with the * frame control field). * * Requested by Max Filippov . */ #define LINKTYPE_IEEE802_15_4_NONASK_PHY 215 /* * David Gibson requested this for * captures from the Linux kernel /dev/input/eventN devices. This * is used to communicate keystrokes and mouse movements from the * Linux kernel to display systems, such as Xorg. */ #define LINKTYPE_LINUX_EVDEV 216 /* * GSM Um and Abis interfaces, preceded by a "gsmtap" header. * * Requested by Harald Welte . */ #define LINKTYPE_GSMTAP_UM 217 #define LINKTYPE_GSMTAP_ABIS 218 /* * MPLS, with an MPLS label as the link-layer header. * Requested by Michele Marchetto on behalf * of OpenBSD. */ #define LINKTYPE_MPLS 219 /* * USB packets, beginning with a Linux USB header, with the USB header * padded to 64 bytes; required for memory-mapped access. */ #define LINKTYPE_USB_LINUX_MMAPPED 220 /* * DECT packets, with a pseudo-header; requested by * Matthias Wenzel . */ #define LINKTYPE_DECT 221 /* * From: "Lidwa, Eric (GSFC-582.0)[SGT INC]" * Date: Mon, 11 May 2009 11:18:30 -0500 * * DLT_AOS. We need it for AOS Space Data Link Protocol. * I have already written dissectors for but need an OK from * legal before I can submit a patch. * */ #define LINKTYPE_AOS 222 /* * Wireless HART (Highway Addressable Remote Transducer) * From the HART Communication Foundation * IES/PAS 62591 * * Requested by Sam Roberts . */ #define LINKTYPE_WIHART 223 /* * Fibre Channel FC-2 frames, beginning with a Frame_Header. * Requested by Kahou Lei . */ #define LINKTYPE_FC_2 224 /* * Fibre Channel FC-2 frames, beginning with an encoding of the * SOF, and ending with an encoding of the EOF. * * The encodings represent the frame delimiters as 4-byte sequences * representing the corresponding ordered sets, with K28.5 * represented as 0xBC, and the D symbols as the corresponding * byte values; for example, SOFi2, which is K28.5 - D21.5 - D1.2 - D21.2, * is represented as 0xBC 0xB5 0x55 0x55. * * Requested by Kahou Lei . */ #define LINKTYPE_FC_2_WITH_FRAME_DELIMS 225 /* * Solaris ipnet pseudo-header; requested by Darren Reed . * * The pseudo-header starts with a one-byte version number; for version 2, * the pseudo-header is: * * struct dl_ipnetinfo { * u_int8_t dli_version; * u_int8_t dli_family; * u_int16_t dli_htype; * u_int32_t dli_pktlen; * u_int32_t dli_ifindex; * u_int32_t dli_grifindex; * u_int32_t dli_zsrc; * u_int32_t dli_zdst; * }; * * dli_version is 2 for the current version of the pseudo-header. * * dli_family is a Solaris address family value, so it's 2 for IPv4 * and 26 for IPv6. * * dli_htype is a "hook type" - 0 for incoming packets, 1 for outgoing * packets, and 2 for packets arriving from another zone on the same * machine. * * dli_pktlen is the length of the packet data following the pseudo-header * (so the captured length minus dli_pktlen is the length of the * pseudo-header, assuming the entire pseudo-header was captured). * * dli_ifindex is the interface index of the interface on which the * packet arrived. * * dli_grifindex is the group interface index number (for IPMP interfaces). * * dli_zsrc is the zone identifier for the source of the packet. * * dli_zdst is the zone identifier for the destination of the packet. * * A zone number of 0 is the global zone; a zone number of 0xffffffff * means that the packet arrived from another host on the network, not * from another zone on the same machine. * * An IPv4 or IPv6 datagram follows the pseudo-header; dli_family indicates * which of those it is. */ #define LINKTYPE_IPNET 226 /* * CAN (Controller Area Network) frames, with a pseudo-header as supplied * by Linux SocketCAN. See Documentation/networking/can.txt in the Linux * source. * * Requested by Felix Obenhuber . */ #define LINKTYPE_CAN_SOCKETCAN 227 /* * Raw IPv4/IPv6; different from DLT_RAW in that the DLT_ value specifies * whether it's v4 or v6. Requested by Darren Reed . */ #define LINKTYPE_IPV4 228 #define LINKTYPE_IPV6 229 /* * IEEE 802.15.4, exactly as it appears in the spec (no padding, no * nothing), and with no FCS at the end of the frame; requested by * Jon Smirl . */ #define LINKTYPE_IEEE802_15_4_NOFCS 230 /* * Raw D-Bus: * * http://www.freedesktop.org/wiki/Software/dbus * * messages: * * http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages * * starting with the endianness flag, followed by the message type, etc., * but without the authentication handshake before the message sequence: * * http://dbus.freedesktop.org/doc/dbus-specification.html#auth-protocol * * Requested by Martin Vidner . */ #define LINKTYPE_DBUS 231 /* * Juniper-private data link type, as per request from * Hannes Gredler . */ #define LINKTYPE_JUNIPER_VS 232 #define LINKTYPE_JUNIPER_SRX_E2E 233 #define LINKTYPE_JUNIPER_FIBRECHANNEL 234 /* * DVB-CI (DVB Common Interface for communication between a PC Card * module and a DVB receiver). See * * http://www.kaiser.cx/pcap-dvbci.html * * for the specification. * * Requested by Martin Kaiser . */ #define LINKTYPE_DVB_CI 235 /* * Variant of 3GPP TS 27.010 multiplexing protocol. Requested * by Hans-Christoph Schemmel . */ #define LINKTYPE_MUX27010 236 /* * STANAG 5066 D_PDUs. Requested by M. Baris Demiray * . */ #define LINKTYPE_STANAG_5066_D_PDU 237 /* * Juniper-private data link type, as per request from * Hannes Gredler . */ #define LINKTYPE_JUNIPER_ATM_CEMIC 238 /* * NetFilter LOG messages * (payload of netlink NFNL_SUBSYS_ULOG/NFULNL_MSG_PACKET packets) * * Requested by Jakub Zawadzki */ #define LINKTYPE_NFLOG 239 /* * Hilscher Gesellschaft fuer Systemautomation mbH link-layer type * for Ethernet packets with a 4-byte pseudo-header and always * with the payload including the FCS, as supplied by their * netANALYZER hardware and software. * * Requested by Holger P. Frommer */ #define LINKTYPE_NETANALYZER 240 /* * Hilscher Gesellschaft fuer Systemautomation mbH link-layer type * for Ethernet packets with a 4-byte pseudo-header and FCS and * 1 byte of SFD, as supplied by their netANALYZER hardware and * software. * * Requested by Holger P. Frommer */ #define LINKTYPE_NETANALYZER_TRANSPARENT 241 /* - * IP-over-Infiniband, as specified by RFC 4391. + * IP-over-InfiniBand, as specified by RFC 4391. * * Requested by Petr Sumbera . */ #define LINKTYPE_IPOIB 242 /* * MPEG-2 transport stream (ISO 13818-1/ITU-T H.222.0). * * Requested by Guy Martin . */ #define LINKTYPE_MPEG_2_TS 243 /* * ng4T GmbH's UMTS Iub/Iur-over-ATM and Iub/Iur-over-IP format as * used by their ng40 protocol tester. * * Requested by Jens Grimmer . */ #define LINKTYPE_NG40 244 /* * Pseudo-header giving adapter number and flags, followed by an NFC * (Near-Field Communications) Logical Link Control Protocol (LLCP) PDU, * as specified by NFC Forum Logical Link Control Protocol Technical * Specification LLCP 1.1. * * Requested by Mike Wakerly . */ #define LINKTYPE_NFC_LLCP 245 /* * pfsync output; DLT_PFSYNC is 18, which collides with DLT_CIP in * SuSE 6.3, on OpenBSD, NetBSD, DragonFly BSD, and Mac OS X, and * is 121, which collides with DLT_HHDLC, in FreeBSD. We pick a * shiny new link-layer header type value that doesn't collide with * anything, in the hopes that future pfsync savefiles, if any, * won't require special hacks to distinguish from other savefiles. * */ #define LINKTYPE_PFSYNC 246 -#define LINKTYPE_MATCHING_MAX 246 /* highest value in the "matching" range */ +/* + * Raw InfiniBand packets, starting with the Local Routing Header. + * + * Requested by Oren Kladnitsky . + */ +#define LINKTYPE_INFINIBAND 247 + +/* + * SCTP, with no lower-level protocols (i.e., no IPv4 or IPv6). + * + * Requested by Michael Tuexen . + */ +#define LINKTYPE_SCTP 248 + +#define LINKTYPE_MATCHING_MAX 248 /* highest value in the "matching" range */ static struct linktype_map { int dlt; int linktype; } map[] = { /* * These DLT_* codes have LINKTYPE_* codes with values identical * to the values of the corresponding DLT_* code. */ { DLT_NULL, LINKTYPE_NULL }, { DLT_EN10MB, LINKTYPE_ETHERNET }, { DLT_EN3MB, LINKTYPE_EXP_ETHERNET }, { DLT_AX25, LINKTYPE_AX25 }, { DLT_PRONET, LINKTYPE_PRONET }, { DLT_CHAOS, LINKTYPE_CHAOS }, { DLT_IEEE802, LINKTYPE_IEEE802_5 }, { DLT_ARCNET, LINKTYPE_ARCNET_BSD }, { DLT_SLIP, LINKTYPE_SLIP }, { DLT_PPP, LINKTYPE_PPP }, { DLT_FDDI, LINKTYPE_FDDI }, { DLT_SYMANTEC_FIREWALL, LINKTYPE_SYMANTEC_FIREWALL }, /* * These DLT_* codes have different values on different * platforms; we map them to LINKTYPE_* codes that * have values that should never be equal to any DLT_* * code. */ #ifdef DLT_FR /* BSD/OS Frame Relay */ { DLT_FR, LINKTYPE_FRELAY }, #endif { DLT_ATM_RFC1483, LINKTYPE_ATM_RFC1483 }, { DLT_RAW, LINKTYPE_RAW }, { DLT_SLIP_BSDOS, LINKTYPE_SLIP_BSDOS }, { DLT_PPP_BSDOS, LINKTYPE_PPP_BSDOS }, /* BSD/OS Cisco HDLC */ { DLT_C_HDLC, LINKTYPE_C_HDLC }, /* * These DLT_* codes are not on all platforms, but, so far, * there don't appear to be any platforms that define * other codes with those values; we map them to * different LINKTYPE_* values anyway, just in case. */ /* Linux ATM Classical IP */ { DLT_ATM_CLIP, LINKTYPE_ATM_CLIP }, /* NetBSD sync/async serial PPP (or Cisco HDLC) */ { DLT_PPP_SERIAL, LINKTYPE_PPP_HDLC }, /* NetBSD PPP over Ethernet */ { DLT_PPP_ETHER, LINKTYPE_PPP_ETHER }, /* * All LINKTYPE_ values between LINKTYPE_MATCHING_MIN * and LINKTYPE_MATCHING_MAX are mapped to identical * DLT_ values. */ { -1, -1 } }; int dlt_to_linktype(int dlt) { int i; /* * Map DLT_PFSYNC, whatever it might be, to LINKTYPE_PFSYNC. */ if (dlt == DLT_PFSYNC) return (LINKTYPE_PFSYNC); /* * Map the values in the matching range. */ if (dlt >= DLT_MATCHING_MIN && dlt <= DLT_MATCHING_MAX) return (dlt); /* * Map the values outside that range. */ for (i = 0; map[i].dlt != -1; i++) { if (map[i].dlt == dlt) return (map[i].linktype); } /* * If we don't have a mapping for this DLT_ code, return an * error; that means that this is a value with no corresponding * LINKTYPE_ code, and we need to assign one. */ return (-1); } int linktype_to_dlt(int linktype) { int i; /* * Map LINKTYPE_PFSYNC to DLT_PFSYNC, whatever it might be. * LINKTYPE_PFSYNC is in the matching range, to make sure * it's as safe from reuse as we can arrange, so we do * this test first. */ if (linktype == LINKTYPE_PFSYNC) return (DLT_PFSYNC); /* * Map the values in the matching range. */ if (linktype >= LINKTYPE_MATCHING_MIN && linktype <= LINKTYPE_MATCHING_MAX) return (linktype); /* * Map the values outside that range. */ for (i = 0; map[i].linktype != -1; i++) { if (map[i].linktype == linktype) return (map[i].dlt); } /* * If we don't have an entry for this link type, return * the link type value; it may be a DLT_ value from an * older version of libpcap. */ return linktype; } /* * The DLT_USB_LINUX and DLT_USB_LINUX_MMAPPED headers are in host * byte order when capturing (it's supplied directly from a * memory-mapped buffer shared by the kernel). * * When reading a DLT_USB_LINUX or DLT_USB_LINUX_MMAPPED capture file, * we need to convert it from the capturing host's byte order to * the reading host's byte order. */ void swap_linux_usb_header(const struct pcap_pkthdr *hdr, u_char *buf, int header_len_64_bytes) { pcap_usb_header_mmapped *uhdr = (pcap_usb_header_mmapped *)buf; bpf_u_int32 offset = 0; usb_isodesc *pisodesc; int32_t numdesc, i; /* * "offset" is the offset *past* the field we're swapping; * we skip the field *before* checking to make sure * the captured data length includes the entire field. */ /* * The URB id is a totally opaque value; do we really need to * convert it to the reading host's byte order??? */ offset += 8; /* skip past id */ if (hdr->caplen < offset) return; uhdr->id = SWAPLL(uhdr->id); offset += 4; /* skip past various 1-byte fields */ offset += 2; /* skip past bus_id */ if (hdr->caplen < offset) return; uhdr->bus_id = SWAPSHORT(uhdr->bus_id); offset += 2; /* skip past various 1-byte fields */ offset += 8; /* skip past ts_sec */ if (hdr->caplen < offset) return; uhdr->ts_sec = SWAPLL(uhdr->ts_sec); offset += 4; /* skip past ts_usec */ if (hdr->caplen < offset) return; uhdr->ts_usec = SWAPLONG(uhdr->ts_usec); offset += 4; /* skip past status */ if (hdr->caplen < offset) return; uhdr->status = SWAPLONG(uhdr->status); offset += 4; /* skip past urb_len */ if (hdr->caplen < offset) return; uhdr->urb_len = SWAPLONG(uhdr->urb_len); offset += 4; /* skip past data_len */ if (hdr->caplen < offset) return; uhdr->data_len = SWAPLONG(uhdr->data_len); if (uhdr->transfer_type == URB_ISOCHRONOUS) { offset += 4; /* skip past s.iso.error_count */ if (hdr->caplen < offset) return; uhdr->s.iso.error_count = SWAPLONG(uhdr->s.iso.error_count); offset += 4; /* skip past s.iso.numdesc */ if (hdr->caplen < offset) return; uhdr->s.iso.numdesc = SWAPLONG(uhdr->s.iso.numdesc); } else offset += 8; /* skip USB setup header */ if (header_len_64_bytes) { /* * This is either the "version 1" header, with * 16 bytes of additional fields at the end, or * a "version 0" header from a memory-mapped * capture, with 16 bytes of zeroed-out padding * at the end. Byte swap them as if this were * a "version 1" header. */ offset += 4; /* skip past interval */ if (hdr->caplen < offset) return; uhdr->interval = SWAPLONG(uhdr->interval); offset += 4; /* skip past start_frame */ if (hdr->caplen < offset) return; uhdr->start_frame = SWAPLONG(uhdr->start_frame); offset += 4; /* skip past xfer_flags */ if (hdr->caplen < offset) return; uhdr->xfer_flags = SWAPLONG(uhdr->xfer_flags); offset += 4; /* skip past ndesc */ if (hdr->caplen < offset) return; uhdr->ndesc = SWAPLONG(uhdr->ndesc); } if (uhdr->transfer_type == URB_ISOCHRONOUS) { /* swap the values in struct linux_usb_isodesc */ pisodesc = (usb_isodesc *)(void *)(buf+offset); numdesc = uhdr->s.iso.numdesc; for (i = 0; i < numdesc; i++) { offset += 4; /* skip past status */ if (hdr->caplen < offset) return; pisodesc->status = SWAPLONG(pisodesc->status); offset += 4; /* skip past offset */ if (hdr->caplen < offset) return; pisodesc->offset = SWAPLONG(pisodesc->offset); offset += 4; /* skip past len */ if (hdr->caplen < offset) return; pisodesc->len = SWAPLONG(pisodesc->len); offset += 4; /* skip past padding */ pisodesc++; } } } Index: stable/9/contrib/libpcap/pcap-dag.c =================================================================== --- stable/9/contrib/libpcap/pcap-dag.c (revision 252280) +++ stable/9/contrib/libpcap/pcap-dag.c (revision 252281) @@ -1,1141 +1,1168 @@ /* * pcap-dag.c: Packet capture interface for Endace DAG card. * * The functionality of this code attempts to mimic that of pcap-linux as much * as possible. This code is compiled in several different ways depending on * whether DAG_ONLY and HAVE_DAG_API are defined. If HAVE_DAG_API is not * defined it should not get compiled in, otherwise if DAG_ONLY is defined then * the 'dag_' function calls are renamed to 'pcap_' equivalents. If DAG_ONLY * is not defined then nothing is altered - the dag_ functions will be * called as required from their pcap-linux/bpf equivalents. * * Authors: Richard Littin, Sean Irvine ({richard,sean}@reeltwo.com) * Modifications: Jesper Peterson * Koryn Grant * Stephen Donnelly */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.39 2008-04-14 20:40:58 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include /* optionally get BSD define */ #include #include #include #include "pcap-int.h" #include #include #include #include #include #include struct mbuf; /* Squelch compiler warnings on some platforms for */ struct rtentry; /* declarations in */ #include #include "dagnew.h" #include "dagapi.h" #include "pcap-dag.h" +/* + * DAG devices have names beginning with "dag", followed by a number + * from 0 to MAXDAG. + */ +#define MAXDAG 31 + #define ATM_CELL_SIZE 52 #define ATM_HDR_SIZE 4 /* * A header containing additional MTP information. */ #define MTP2_SENT_OFFSET 0 /* 1 byte */ #define MTP2_ANNEX_A_USED_OFFSET 1 /* 1 byte */ #define MTP2_LINK_NUMBER_OFFSET 2 /* 2 bytes */ #define MTP2_HDR_LEN 4 /* length of the header */ #define MTP2_ANNEX_A_NOT_USED 0 #define MTP2_ANNEX_A_USED 1 #define MTP2_ANNEX_A_USED_UNKNOWN 2 /* SunATM pseudo header */ struct sunatm_hdr { unsigned char flags; /* destination and traffic type */ unsigned char vpi; /* VPI */ unsigned short vci; /* VCI */ }; typedef struct pcap_dag_node { struct pcap_dag_node *next; pcap_t *p; pid_t pid; } pcap_dag_node_t; static pcap_dag_node_t *pcap_dags = NULL; static int atexit_handler_installed = 0; static const unsigned short endian_test_word = 0x0100; #define IS_BIGENDIAN() (*((unsigned char *)&endian_test_word)) - -#ifdef DAG_ONLY -/* This code is required when compiling for a DAG device only. */ - -/* Replace dag function names with pcap equivalent. */ -#define dag_create pcap_create -#define dag_platform_finddevs pcap_platform_finddevs -#endif /* DAG_ONLY */ - #define MAX_DAG_PACKET 65536 static unsigned char TempPkt[MAX_DAG_PACKET]; static int dag_setfilter(pcap_t *p, struct bpf_program *fp); static int dag_stats(pcap_t *p, struct pcap_stat *ps); static int dag_set_datalink(pcap_t *p, int dlt); static int dag_get_datalink(pcap_t *p); static int dag_setnonblock(pcap_t *p, int nonblock, char *errbuf); static void delete_pcap_dag(pcap_t *p) { pcap_dag_node_t *curr = NULL, *prev = NULL; for (prev = NULL, curr = pcap_dags; curr != NULL && curr->p != p; prev = curr, curr = curr->next) { /* empty */ } if (curr != NULL && curr->p == p) { if (prev != NULL) { prev->next = curr->next; } else { pcap_dags = curr->next; } } } /* * Performs a graceful shutdown of the DAG card, frees dynamic memory held * in the pcap_t structure, and closes the file descriptor for the DAG card. */ static void dag_platform_cleanup(pcap_t *p) { if (p != NULL) { #ifdef HAVE_DAG_STREAMS_API if(dag_stop_stream(p->fd, p->md.dag_stream) < 0) fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno)); if(dag_detach_stream(p->fd, p->md.dag_stream) < 0) fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno)); #else if(dag_stop(p->fd) < 0) fprintf(stderr,"dag_stop: %s\n", strerror(errno)); #endif /* HAVE_DAG_STREAMS_API */ if(p->fd != -1) { if(dag_close(p->fd) < 0) fprintf(stderr,"dag_close: %s\n", strerror(errno)); p->fd = -1; } delete_pcap_dag(p); pcap_cleanup_live_common(p); } /* Note: don't need to call close(p->fd) here as dag_close(p->fd) does this. */ } static void atexit_handler(void) { while (pcap_dags != NULL) { if (pcap_dags->pid == getpid()) { dag_platform_cleanup(pcap_dags->p); } else { delete_pcap_dag(pcap_dags->p); } } } static int new_pcap_dag(pcap_t *p) { pcap_dag_node_t *node = NULL; if ((node = malloc(sizeof(pcap_dag_node_t))) == NULL) { return -1; } if (!atexit_handler_installed) { atexit(atexit_handler); atexit_handler_installed = 1; } node->next = pcap_dags; node->p = p; node->pid = getpid(); pcap_dags = node; return 0; } static unsigned int dag_erf_ext_header_count(uint8_t * erf, size_t len) { uint32_t hdr_num = 0; uint8_t hdr_type; /* basic sanity checks */ if ( erf == NULL ) return 0; if ( len < 16 ) return 0; /* check if we have any extension headers */ if ( (erf[8] & 0x80) == 0x00 ) return 0; /* loop over the extension headers */ do { /* sanity check we have enough bytes */ if ( len <= (24 + (hdr_num * 8)) ) return hdr_num; /* get the header type */ hdr_type = erf[(16 + (hdr_num * 8))]; hdr_num++; } while ( hdr_type & 0x80 ); return hdr_num; } /* * Read at most max_packets from the capture stream and call the callback * for each of them. Returns the number of packets handled, -1 if an * error occured, or -2 if we were told to break out of the loop. */ static int dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { unsigned int processed = 0; int flags = p->md.dag_offset_flags; unsigned int nonblocking = flags & DAGF_NONBLOCK; unsigned int num_ext_hdr = 0; /* Get the next bufferful of packets (if necessary). */ while (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size) { /* * Has "pcap_breakloop()" been called? */ if (p->break_loop) { /* * Yes - clear the flag that indicates that * it has, and return -2 to indicate that * we were told to break out of the loop. */ p->break_loop = 0; return -2; } #ifdef HAVE_DAG_STREAMS_API /* dag_advance_stream() will block (unless nonblock is called) * until 64kB of data has accumulated. * If to_ms is set, it will timeout before 64kB has accumulated. * We wait for 64kB because processing a few packets at a time * can cause problems at high packet rates (>200kpps) due * to inefficiencies. * This does mean if to_ms is not specified the capture may 'hang' * for long periods if the data rate is extremely slow (<64kB/sec) * If non-block is specified it will return immediately. The user * is then responsible for efficiency. */ if ( NULL == (p->md.dag_mem_top = dag_advance_stream(p->fd, p->md.dag_stream, &(p->md.dag_mem_bottom))) ) { return -1; } #else /* dag_offset does not support timeouts */ p->md.dag_mem_top = dag_offset(p->fd, &(p->md.dag_mem_bottom), flags); #endif /* HAVE_DAG_STREAMS_API */ if (nonblocking && (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size)) { /* Pcap is configured to process only available packets, and there aren't any, return immediately. */ return 0; } if(!nonblocking && p->md.dag_timeout && (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size)) { /* Blocking mode, but timeout set and no data has arrived, return anyway.*/ return 0; } } /* Process the packets. */ while (p->md.dag_mem_top - p->md.dag_mem_bottom >= dag_record_size) { unsigned short packet_len = 0; int caplen = 0; struct pcap_pkthdr pcap_header; #ifdef HAVE_DAG_STREAMS_API dag_record_t *header = (dag_record_t *)(p->md.dag_mem_bottom); #else dag_record_t *header = (dag_record_t *)(p->md.dag_mem_base + p->md.dag_mem_bottom); #endif /* HAVE_DAG_STREAMS_API */ u_char *dp = ((u_char *)header); /* + dag_record_size; */ unsigned short rlen; /* * Has "pcap_breakloop()" been called? */ if (p->break_loop) { /* * Yes - clear the flag that indicates that * it has, and return -2 to indicate that * we were told to break out of the loop. */ p->break_loop = 0; return -2; } rlen = ntohs(header->rlen); if (rlen < dag_record_size) { strncpy(p->errbuf, "dag_read: record too small", PCAP_ERRBUF_SIZE); return -1; } p->md.dag_mem_bottom += rlen; /* Count lost packets. */ switch((header->type & 0x7f)) { /* in these types the color value overwrites the lctr */ case TYPE_COLOR_HDLC_POS: case TYPE_COLOR_ETH: case TYPE_DSM_COLOR_HDLC_POS: case TYPE_DSM_COLOR_ETH: case TYPE_COLOR_MC_HDLC_POS: case TYPE_COLOR_HASH_ETH: case TYPE_COLOR_HASH_POS: break; default: if (header->lctr) { if (p->md.stat.ps_drop > (UINT_MAX - ntohs(header->lctr))) { p->md.stat.ps_drop = UINT_MAX; } else { p->md.stat.ps_drop += ntohs(header->lctr); } } } if ((header->type & 0x7f) == TYPE_PAD) { continue; } num_ext_hdr = dag_erf_ext_header_count(dp, rlen); /* ERF encapsulation */ /* The Extensible Record Format is not dropped for this kind of encapsulation, * and will be handled as a pseudo header by the decoding application. * The information carried in the ERF header and in the optional subheader (if present) * could be merged with the libpcap information, to offer a better decoding. * The packet length is * o the length of the packet on the link (header->wlen), * o plus the length of the ERF header (dag_record_size), as the length of the * pseudo header will be adjusted during the decoding, * o plus the length of the optional subheader (if present). * * The capture length is header.rlen and the byte stuffing for alignment will be dropped * if the capture length is greater than the packet length. */ if (p->linktype == DLT_ERF) { packet_len = ntohs(header->wlen) + dag_record_size; caplen = rlen; switch ((header->type & 0x7f)) { case TYPE_MC_AAL5: case TYPE_MC_ATM: case TYPE_MC_HDLC: case TYPE_MC_RAW_CHANNEL: case TYPE_MC_RAW: case TYPE_MC_AAL2: case TYPE_COLOR_MC_HDLC_POS: packet_len += 4; /* MC header */ break; case TYPE_COLOR_HASH_ETH: case TYPE_DSM_COLOR_ETH: case TYPE_COLOR_ETH: case TYPE_ETH: packet_len += 2; /* ETH header */ break; } /* switch type */ /* Include ERF extension headers */ packet_len += (8 * num_ext_hdr); if (caplen > packet_len) { caplen = packet_len; } } else { /* Other kind of encapsulation according to the header Type */ /* Skip over generic ERF header */ dp += dag_record_size; /* Skip over extension headers */ dp += 8 * num_ext_hdr; switch((header->type & 0x7f)) { case TYPE_ATM: case TYPE_AAL5: if (header->type == TYPE_AAL5) { packet_len = ntohs(header->wlen); caplen = rlen - dag_record_size; } case TYPE_MC_ATM: if (header->type == TYPE_MC_ATM) { caplen = packet_len = ATM_CELL_SIZE; dp+=4; } case TYPE_MC_AAL5: if (header->type == TYPE_MC_AAL5) { packet_len = ntohs(header->wlen); caplen = rlen - dag_record_size - 4; dp+=4; } if (header->type == TYPE_ATM) { caplen = packet_len = ATM_CELL_SIZE; } if (p->linktype == DLT_SUNATM) { struct sunatm_hdr *sunatm = (struct sunatm_hdr *)dp; unsigned long rawatm; rawatm = ntohl(*((unsigned long *)dp)); sunatm->vci = htons((rawatm >> 4) & 0xffff); sunatm->vpi = (rawatm >> 20) & 0x00ff; sunatm->flags = ((header->flags.iface & 1) ? 0x80 : 0x00) | ((sunatm->vpi == 0 && sunatm->vci == htons(5)) ? 6 : ((sunatm->vpi == 0 && sunatm->vci == htons(16)) ? 5 : ((dp[ATM_HDR_SIZE] == 0xaa && dp[ATM_HDR_SIZE+1] == 0xaa && dp[ATM_HDR_SIZE+2] == 0x03) ? 2 : 1))); } else { packet_len -= ATM_HDR_SIZE; caplen -= ATM_HDR_SIZE; dp += ATM_HDR_SIZE; } break; case TYPE_COLOR_HASH_ETH: case TYPE_DSM_COLOR_ETH: case TYPE_COLOR_ETH: case TYPE_ETH: packet_len = ntohs(header->wlen); packet_len -= (p->md.dag_fcs_bits >> 3); caplen = rlen - dag_record_size - 2; if (caplen > packet_len) { caplen = packet_len; } dp += 2; break; case TYPE_COLOR_HASH_POS: case TYPE_DSM_COLOR_HDLC_POS: case TYPE_COLOR_HDLC_POS: case TYPE_HDLC_POS: packet_len = ntohs(header->wlen); packet_len -= (p->md.dag_fcs_bits >> 3); caplen = rlen - dag_record_size; if (caplen > packet_len) { caplen = packet_len; } break; case TYPE_COLOR_MC_HDLC_POS: case TYPE_MC_HDLC: packet_len = ntohs(header->wlen); packet_len -= (p->md.dag_fcs_bits >> 3); caplen = rlen - dag_record_size - 4; if (caplen > packet_len) { caplen = packet_len; } /* jump the MC_HDLC_HEADER */ dp += 4; #ifdef DLT_MTP2_WITH_PHDR if (p->linktype == DLT_MTP2_WITH_PHDR) { /* Add the MTP2 Pseudo Header */ caplen += MTP2_HDR_LEN; packet_len += MTP2_HDR_LEN; TempPkt[MTP2_SENT_OFFSET] = 0; TempPkt[MTP2_ANNEX_A_USED_OFFSET] = MTP2_ANNEX_A_USED_UNKNOWN; *(TempPkt+MTP2_LINK_NUMBER_OFFSET) = ((header->rec.mc_hdlc.mc_header>>16)&0x01); *(TempPkt+MTP2_LINK_NUMBER_OFFSET+1) = ((header->rec.mc_hdlc.mc_header>>24)&0xff); memcpy(TempPkt+MTP2_HDR_LEN, dp, caplen); dp = TempPkt; } #endif break; case TYPE_IPV4: case TYPE_IPV6: packet_len = ntohs(header->wlen); caplen = rlen - dag_record_size; if (caplen > packet_len) { caplen = packet_len; } break; /* These types have no matching 'native' DLT, but can be used with DLT_ERF above */ case TYPE_MC_RAW: case TYPE_MC_RAW_CHANNEL: case TYPE_IP_COUNTER: case TYPE_TCP_FLOW_COUNTER: case TYPE_INFINIBAND: case TYPE_RAW_LINK: case TYPE_INFINIBAND_LINK: default: /* Unhandled ERF type. * Ignore rather than generating error */ continue; } /* switch type */ /* Skip over extension headers */ caplen -= (8 * num_ext_hdr); } /* ERF encapsulation */ if (caplen > p->snapshot) caplen = p->snapshot; /* Run the packet filter if there is one. */ if ((p->fcode.bf_insns == NULL) || bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen)) { /* convert between timestamp formats */ register unsigned long long ts; if (IS_BIGENDIAN()) { ts = SWAPLL(header->ts); } else { ts = header->ts; } pcap_header.ts.tv_sec = ts >> 32; ts = (ts & 0xffffffffULL) * 1000000; ts += 0x80000000; /* rounding */ pcap_header.ts.tv_usec = ts >> 32; if (pcap_header.ts.tv_usec >= 1000000) { pcap_header.ts.tv_usec -= 1000000; pcap_header.ts.tv_sec++; } /* Fill in our own header data */ pcap_header.caplen = caplen; pcap_header.len = packet_len; /* Count the packet. */ p->md.stat.ps_recv++; /* Call the user supplied callback function */ callback(user, &pcap_header, dp); /* Only count packets that pass the filter, for consistency with standard Linux behaviour. */ processed++; if (processed == cnt && cnt > 0) { /* Reached the user-specified limit. */ return cnt; } } } return processed; } static int dag_inject(pcap_t *p, const void *buf _U_, size_t size _U_) { strlcpy(p->errbuf, "Sending packets isn't supported on DAG cards", PCAP_ERRBUF_SIZE); return (-1); } /* * Get a handle for a live capture from the given DAG device. Passing a NULL * device will result in a failure. The promisc flag is ignored because DAG * cards are always promiscuous. The to_ms parameter is used in setting the * API polling parameters. * * snaplen is now also ignored, until we get per-stream slen support. Set * slen with approprite DAG tool BEFORE pcap_activate(). * * See also pcap(3). */ static int dag_activate(pcap_t* handle) { #if 0 char conf[30]; /* dag configure string */ #endif char *s; int n; daginf_t* daginf; char * newDev = NULL; char * device = handle->opt.source; #ifdef HAVE_DAG_STREAMS_API uint32_t mindata; struct timeval maxwait; struct timeval poll; #endif if (device == NULL) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "device is NULL: %s", pcap_strerror(errno)); return -1; } /* Initialize some components of the pcap structure. */ #ifdef HAVE_DAG_STREAMS_API newDev = (char *)malloc(strlen(device) + 16); if (newDev == NULL) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s\n", pcap_strerror(errno)); goto fail; } /* Parse input name to get dag device and stream number if provided */ if (dag_parse_name(device, newDev, strlen(device) + 16, &handle->md.dag_stream) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: %s\n", pcap_strerror(errno)); goto fail; } device = newDev; if (handle->md.dag_stream%2) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: tx (even numbered) streams not supported for capture\n"); goto fail; } #else if (strncmp(device, "/dev/", 5) != 0) { newDev = (char *)malloc(strlen(device) + 5); if (newDev == NULL) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s\n", pcap_strerror(errno)); goto fail; } strcpy(newDev, "/dev/"); strcat(newDev, device); device = newDev; } #endif /* HAVE_DAG_STREAMS_API */ /* setup device parameters */ if((handle->fd = dag_open((char *)device)) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_open %s: %s", device, pcap_strerror(errno)); goto fail; } #ifdef HAVE_DAG_STREAMS_API /* Open requested stream. Can fail if already locked or on error */ if (dag_attach_stream(handle->fd, handle->md.dag_stream, 0, 0) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_attach_stream: %s\n", pcap_strerror(errno)); goto failclose; } /* Set up default poll parameters for stream * Can be overridden by pcap_set_nonblock() */ if (dag_get_stream_poll(handle->fd, handle->md.dag_stream, &mindata, &maxwait, &poll) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno)); goto faildetach; } /* Amount of data to collect in Bytes before calling callbacks. * Important for efficiency, but can introduce latency * at low packet rates if to_ms not set! */ mindata = 65536; /* Obey md.timeout (was to_ms) if supplied. This is a good idea! * Recommend 10-100ms. Calls will time out even if no data arrived. */ maxwait.tv_sec = handle->md.timeout/1000; maxwait.tv_usec = (handle->md.timeout%1000) * 1000; if (dag_set_stream_poll(handle->fd, handle->md.dag_stream, mindata, &maxwait, &poll) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno)); goto faildetach; } #else if((handle->md.dag_mem_base = dag_mmap(handle->fd)) == MAP_FAILED) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,"dag_mmap %s: %s\n", device, pcap_strerror(errno)); goto failclose; } #endif /* HAVE_DAG_STREAMS_API */ /* XXX Not calling dag_configure() to set slen; this is unsafe in * multi-stream environments as the gpp config is global. * Once the firmware provides 'per-stream slen' this can be supported * again via the Config API without side-effects */ #if 0 /* set the card snap length to the specified snaplen parameter */ /* This is a really bad idea, as different cards have different * valid slen ranges. Should fix in Config API. */ if (handle->snapshot == 0 || handle->snapshot > MAX_DAG_SNAPLEN) { handle->snapshot = MAX_DAG_SNAPLEN; } else if (snaplen < MIN_DAG_SNAPLEN) { handle->snapshot = MIN_DAG_SNAPLEN; } /* snap len has to be a multiple of 4 */ snprintf(conf, 30, "varlen slen=%d", (snaplen + 3) & ~3); if(dag_configure(handle->fd, conf) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,"dag_configure %s: %s\n", device, pcap_strerror(errno)); goto faildetach; } #endif #ifdef HAVE_DAG_STREAMS_API if(dag_start_stream(handle->fd, handle->md.dag_stream) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_start_stream %s: %s\n", device, pcap_strerror(errno)); goto faildetach; } #else if(dag_start(handle->fd) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_start %s: %s\n", device, pcap_strerror(errno)); goto failclose; } #endif /* HAVE_DAG_STREAMS_API */ /* * Important! You have to ensure bottom is properly * initialized to zero on startup, it won't give you * a compiler warning if you make this mistake! */ handle->md.dag_mem_bottom = 0; handle->md.dag_mem_top = 0; /* * Find out how many FCS bits we should strip. * First, query the card to see if it strips the FCS. */ daginf = dag_info(handle->fd); if ((0x4200 == daginf->device_code) || (0x4230 == daginf->device_code)) { /* DAG 4.2S and 4.23S already strip the FCS. Stripping the final word again truncates the packet. */ handle->md.dag_fcs_bits = 0; /* Note that no FCS will be supplied. */ handle->linktype_ext = LT_FCS_DATALINK_EXT(0); } else { /* * Start out assuming it's 32 bits. */ handle->md.dag_fcs_bits = 32; /* Allow an environment variable to override. */ if ((s = getenv("ERF_FCS_BITS")) != NULL) { if ((n = atoi(s)) == 0 || n == 16 || n == 32) { handle->md.dag_fcs_bits = n; } else { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "pcap_activate %s: bad ERF_FCS_BITS value (%d) in environment\n", device, n); goto failstop; } } /* * Did the user request that they not be stripped? */ if ((s = getenv("ERF_DONT_STRIP_FCS")) != NULL) { /* Yes. Note the number of bytes that will be supplied. */ handle->linktype_ext = LT_FCS_DATALINK_EXT(handle->md.dag_fcs_bits/16); /* And don't strip them. */ handle->md.dag_fcs_bits = 0; } } handle->md.dag_timeout = handle->md.timeout; handle->linktype = -1; if (dag_get_datalink(handle) < 0) goto failstop; handle->bufsize = 0; if (new_pcap_dag(handle) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "new_pcap_dag %s: %s\n", device, pcap_strerror(errno)); goto failstop; } /* * "select()" and "poll()" don't work on DAG device descriptors. */ handle->selectable_fd = -1; if (newDev != NULL) { free((char *)newDev); } handle->read_op = dag_read; handle->inject_op = dag_inject; handle->setfilter_op = dag_setfilter; handle->setdirection_op = NULL; /* Not implemented.*/ handle->set_datalink_op = dag_set_datalink; handle->getnonblock_op = pcap_getnonblock_fd; handle->setnonblock_op = dag_setnonblock; handle->stats_op = dag_stats; handle->cleanup_op = dag_platform_cleanup; handle->md.stat.ps_drop = 0; handle->md.stat.ps_recv = 0; handle->md.stat.ps_ifdrop = 0; return 0; #ifdef HAVE_DAG_STREAMS_API failstop: if (dag_stop_stream(handle->fd, handle->md.dag_stream) < 0) { fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno)); } faildetach: if (dag_detach_stream(handle->fd, handle->md.dag_stream) < 0) fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno)); #else failstop: if (dag_stop(handle->fd) < 0) fprintf(stderr,"dag_stop: %s\n", strerror(errno)); #endif /* HAVE_DAG_STREAMS_API */ failclose: if (dag_close(handle->fd) < 0) fprintf(stderr,"dag_close: %s\n", strerror(errno)); delete_pcap_dag(handle); fail: pcap_cleanup_live_common(handle); if (newDev != NULL) { free((char *)newDev); } return PCAP_ERROR; } -pcap_t *dag_create(const char *device, char *ebuf) +pcap_t *dag_create(const char *device, char *ebuf, int *is_ours) { + const char *cp; + char *cpend; + long devnum; pcap_t *p; + /* Does this look like a DAG device? */ + cp = strrchr(device, '/'); + if (cp == NULL) + cp = device; + /* Does it begin with "dag"? */ + if (strncmp(cp, "dag", 3) != 0) { + /* Nope, doesn't begin with "dag" */ + *is_ours = 0; + return NULL; + } + /* Yes - is "dag" followed by a number from 0 to MAXDAG? */ + cp += 3; + devnum = strtol(cp, &cpend, 10); + if (cpend == cp || *cpend != '\0') { + /* Not followed by a number. */ + *is_ours = 0; + return NULL; + } + if (devnum < 0 || devnum > MAXDAG) { + /* Followed by a non-valid number. */ + *is_ours = 0; + return NULL; + } + + /* OK, it's probably ours. */ + *is_ours = 1; + p = pcap_create_common(device, ebuf); if (p == NULL) return NULL; p->activate_op = dag_activate; return p; } static int dag_stats(pcap_t *p, struct pcap_stat *ps) { /* This needs to be filled out correctly. Hopefully a dagapi call will provide all necessary information. */ /*p->md.stat.ps_recv = 0;*/ /*p->md.stat.ps_drop = 0;*/ *ps = p->md.stat; return 0; } /* * Previously we just generated a list of all possible names and let * pcap_add_if() attempt to open each one, but with streams this adds up * to 81 possibilities which is inefficient. * * Since we know more about the devices we can prune the tree here. * pcap_add_if() will still retest each device but the total number of * open attempts will still be much less than the naive approach. */ int -dag_platform_finddevs(pcap_if_t **devlistp, char *errbuf) +dag_findalldevs(pcap_if_t **devlistp, char *errbuf) { char name[12]; /* XXX - pick a size */ int ret = 0; int c; char dagname[DAGNAME_BUFSIZE]; int dagstream; int dagfd; - /* Try all the DAGs 0-31 */ - for (c = 0; c < 32; c++) { + /* Try all the DAGs 0-MAXDAG */ + for (c = 0; c <= MAXDAG; c++) { snprintf(name, 12, "dag%d", c); if (-1 == dag_parse_name(name, dagname, DAGNAME_BUFSIZE, &dagstream)) { return -1; } if ( (dagfd = dag_open(dagname)) >= 0 ) { if (pcap_add_if(devlistp, name, 0, NULL, errbuf) == -1) { /* * Failure. */ ret = -1; } #ifdef HAVE_DAG_STREAMS_API { int stream, rxstreams; rxstreams = dag_rx_get_stream_count(dagfd); for(stream=0;streamerrbuf, "setfilter: No filter specified", sizeof(p->errbuf)); return -1; } /* Make our private copy of the filter */ if (install_bpf_program(p, fp) < 0) return -1; p->md.use_bpf = 0; return (0); } static int dag_set_datalink(pcap_t *p, int dlt) { p->linktype = dlt; return (0); } static int dag_setnonblock(pcap_t *p, int nonblock, char *errbuf) { /* * Set non-blocking mode on the FD. * XXX - is that necessary? If not, don't bother calling it, * and have a "dag_getnonblock()" function that looks at * "p->md.dag_offset_flags". */ if (pcap_setnonblock_fd(p, nonblock, errbuf) < 0) return (-1); #ifdef HAVE_DAG_STREAMS_API { uint32_t mindata; struct timeval maxwait; struct timeval poll; if (dag_get_stream_poll(p->fd, p->md.dag_stream, &mindata, &maxwait, &poll) < 0) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno)); return -1; } /* Amount of data to collect in Bytes before calling callbacks. * Important for efficiency, but can introduce latency * at low packet rates if to_ms not set! */ if(nonblock) mindata = 0; else mindata = 65536; if (dag_set_stream_poll(p->fd, p->md.dag_stream, mindata, &maxwait, &poll) < 0) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno)); return -1; } } #endif /* HAVE_DAG_STREAMS_API */ if (nonblock) { p->md.dag_offset_flags |= DAGF_NONBLOCK; } else { p->md.dag_offset_flags &= ~DAGF_NONBLOCK; } return (0); } static int dag_get_datalink(pcap_t *p) { int index=0, dlt_index=0; uint8_t types[255]; memset(types, 0, 255); if (p->dlt_list == NULL && (p->dlt_list = malloc(255*sizeof(*(p->dlt_list)))) == NULL) { (void)snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", pcap_strerror(errno)); return (-1); } p->linktype = 0; #ifdef HAVE_DAG_GET_STREAM_ERF_TYPES /* Get list of possible ERF types for this card */ if (dag_get_stream_erf_types(p->fd, p->md.dag_stream, types, 255) < 0) { snprintf(p->errbuf, sizeof(p->errbuf), "dag_get_stream_erf_types: %s", pcap_strerror(errno)); return (-1); } while (types[index]) { #elif defined HAVE_DAG_GET_ERF_TYPES /* Get list of possible ERF types for this card */ if (dag_get_erf_types(p->fd, types, 255) < 0) { snprintf(p->errbuf, sizeof(p->errbuf), "dag_get_erf_types: %s", pcap_strerror(errno)); return (-1); } while (types[index]) { #else /* Check the type through a dagapi call. */ types[index] = dag_linktype(p->fd); { #endif switch((types[index] & 0x7f)) { case TYPE_HDLC_POS: case TYPE_COLOR_HDLC_POS: case TYPE_DSM_COLOR_HDLC_POS: case TYPE_COLOR_HASH_POS: if (p->dlt_list != NULL) { p->dlt_list[dlt_index++] = DLT_CHDLC; p->dlt_list[dlt_index++] = DLT_PPP_SERIAL; p->dlt_list[dlt_index++] = DLT_FRELAY; } if(!p->linktype) p->linktype = DLT_CHDLC; break; case TYPE_ETH: case TYPE_COLOR_ETH: case TYPE_DSM_COLOR_ETH: case TYPE_COLOR_HASH_ETH: /* * This is (presumably) a real Ethernet capture; give it a * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so * that an application can let you choose it, in case you're * capturing DOCSIS traffic that a Cisco Cable Modem * Termination System is putting out onto an Ethernet (it * doesn't put an Ethernet header onto the wire, it puts raw * DOCSIS frames out on the wire inside the low-level * Ethernet framing). */ if (p->dlt_list != NULL) { p->dlt_list[dlt_index++] = DLT_EN10MB; p->dlt_list[dlt_index++] = DLT_DOCSIS; } if(!p->linktype) p->linktype = DLT_EN10MB; break; case TYPE_ATM: case TYPE_AAL5: case TYPE_MC_ATM: case TYPE_MC_AAL5: if (p->dlt_list != NULL) { p->dlt_list[dlt_index++] = DLT_ATM_RFC1483; p->dlt_list[dlt_index++] = DLT_SUNATM; } if(!p->linktype) p->linktype = DLT_ATM_RFC1483; break; case TYPE_COLOR_MC_HDLC_POS: case TYPE_MC_HDLC: if (p->dlt_list != NULL) { p->dlt_list[dlt_index++] = DLT_CHDLC; p->dlt_list[dlt_index++] = DLT_PPP_SERIAL; p->dlt_list[dlt_index++] = DLT_FRELAY; p->dlt_list[dlt_index++] = DLT_MTP2; p->dlt_list[dlt_index++] = DLT_MTP2_WITH_PHDR; p->dlt_list[dlt_index++] = DLT_LAPD; } if(!p->linktype) p->linktype = DLT_CHDLC; break; case TYPE_IPV4: case TYPE_IPV6: if(!p->linktype) p->linktype = DLT_RAW; break; case TYPE_LEGACY: case TYPE_MC_RAW: case TYPE_MC_RAW_CHANNEL: case TYPE_IP_COUNTER: case TYPE_TCP_FLOW_COUNTER: case TYPE_INFINIBAND: case TYPE_RAW_LINK: case TYPE_INFINIBAND_LINK: default: /* Libpcap cannot deal with these types yet */ /* Add no 'native' DLTs, but still covered by DLT_ERF */ break; } /* switch */ index++; } p->dlt_list[dlt_index++] = DLT_ERF; p->dlt_count = dlt_index; if(!p->linktype) p->linktype = DLT_ERF; return p->linktype; } Index: stable/9/contrib/libpcap/pcap-dag.h =================================================================== --- stable/9/contrib/libpcap/pcap-dag.h (revision 252280) +++ stable/9/contrib/libpcap/pcap-dag.h (revision 252281) @@ -1,108 +1,108 @@ /* * pcap-dag.c: Packet capture interface for Endace DAG card. * * The functionality of this code attempts to mimic that of pcap-linux as much * as possible. This code is only needed when compiling in the DAG card code * at the same time as another type of device. * * Author: Richard Littin, Sean Irvine ({richard,sean}@reeltwo.com) * * @(#) $Header: /tcpdump/master/libpcap/pcap-dag.h,v 1.7 2008-04-04 19:37:45 guy Exp $ (LBL) */ -pcap_t *dag_create(const char *, char *); -int dag_platform_finddevs(pcap_if_t **devlistp, char *errbuf); +pcap_t *dag_create(const char *, char *, int *); +int dag_findalldevs(pcap_if_t **devlistp, char *errbuf); #ifndef TYPE_AAL5 #define TYPE_AAL5 4 #endif #ifndef TYPE_MC_HDLC #define TYPE_MC_HDLC 5 #endif #ifndef TYPE_MC_RAW #define TYPE_MC_RAW 6 #endif #ifndef TYPE_MC_ATM #define TYPE_MC_ATM 7 #endif #ifndef TYPE_MC_RAW_CHANNEL #define TYPE_MC_RAW_CHANNEL 8 #endif #ifndef TYPE_MC_AAL5 #define TYPE_MC_AAL5 9 #endif #ifndef TYPE_COLOR_HDLC_POS #define TYPE_COLOR_HDLC_POS 10 #endif #ifndef TYPE_COLOR_ETH #define TYPE_COLOR_ETH 11 #endif #ifndef TYPE_MC_AAL2 #define TYPE_MC_AAL2 12 #endif #ifndef TYPE_IP_COUNTER #define TYPE_IP_COUNTER 13 #endif #ifndef TYPE_TCP_FLOW_COUNTER #define TYPE_TCP_FLOW_COUNTER 14 #endif #ifndef TYPE_DSM_COLOR_HDLC_POS #define TYPE_DSM_COLOR_HDLC_POS 15 #endif #ifndef TYPE_DSM_COLOR_ETH #define TYPE_DSM_COLOR_ETH 16 #endif #ifndef TYPE_COLOR_MC_HDLC_POS #define TYPE_COLOR_MC_HDLC_POS 17 #endif #ifndef TYPE_AAL2 #define TYPE_AAL2 18 #endif #ifndef TYPE_COLOR_HASH_POS #define TYPE_COLOR_HASH_POS 19 #endif #ifndef TYPE_COLOR_HASH_ETH #define TYPE_COLOR_HASH_ETH 20 #endif #ifndef TYPE_INFINIBAND #define TYPE_INFINIBAND 21 #endif #ifndef TYPE_IPV4 #define TYPE_IPV4 22 #endif #ifndef TYPE_IPV6 #define TYPE_IPV6 23 #endif #ifndef TYPE_RAW_LINK #define TYPE_RAW_LINK 24 #endif #ifndef TYPE_INFINIBAND_LINK #define TYPE_INFINIBAND_LINK 25 #endif #ifndef TYPE_PAD #define TYPE_PAD 48 #endif Index: stable/9/contrib/libpcap/pcap-dlpi.c =================================================================== --- stable/9/contrib/libpcap/pcap-dlpi.c (revision 252280) +++ stable/9/contrib/libpcap/pcap-dlpi.c (revision 252281) @@ -1,1708 +1,1708 @@ /* * Copyright (c) 1993, 1994, 1995, 1996, 1997 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * This code contributed by Atanu Ghosh (atanu@cs.ucl.ac.uk), * University College London, and subsequently modified by * Guy Harris (guy@alum.mit.edu), Mark Pizzolato * , * Mark C. Brown (mbrown@hp.com), and Sagun Shakya . */ /* * Packet capture routine for DLPI under SunOS 5, HP-UX 9/10/11, and AIX. * * Notes: * * - The DLIOCRAW ioctl() is specific to SunOS. * * - There is a bug in bufmod(7) such that setting the snapshot * length results in data being left of the front of the packet. * * - It might be desirable to use pfmod(7) to filter packets in the * kernel when possible. * * - An older version of the HP-UX DLPI Programmer's Guide, which * I think was advertised as the 10.20 version, used to be available * at * * http://docs.hp.com/hpux/onlinedocs/B2355-90093/B2355-90093.html * * but is no longer available; it can still be found at * * http://h21007.www2.hp.com/dspp/files/unprotected/Drivers/Docs/Refs/B2355-90093.pdf * * in PDF form. * * - The HP-UX 10.x, 11.0, and 11i v1.6 version of the HP-UX DLPI * Programmer's Guide, which I think was once advertised as the * 11.00 version is available at * * http://docs.hp.com/en/B2355-90139/index.html * * - The HP-UX 11i v2 version of the HP-UX DLPI Programmer's Guide * is available at * * http://docs.hp.com/en/B2355-90871/index.html * * - All of the HP documents describe raw-mode services, which are * what we use if DL_HP_RAWDLS is defined. XXX - we use __hpux * in some places to test for HP-UX, but use DL_HP_RAWDLS in * other places; do we support any versions of HP-UX without * DL_HP_RAWDLS? */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.128 2008-12-02 16:20:23 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #ifdef HAVE_SYS_BUFMOD_H #include #endif #include #ifdef HAVE_SYS_DLPI_EXT_H #include #endif #ifdef HAVE_HPUX9 #include #endif #ifdef DL_HP_PPA_REQ #include #endif #include #if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H) #include #endif #ifdef HAVE_HPUX9 #include #endif #include #ifdef HAVE_HPUX9 #include #endif #include #include #include #include #include #include #include #include #ifdef HAVE_LIMITS_H #include #else #define INT_MAX 2147483647 #endif #include "pcap-int.h" #include "dlpisubs.h" #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #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 dl_doattach(int, int, char *); #ifdef DL_HP_RAWDLS static int dl_dohpuxbind(int, char *); #endif static int dlpromiscon(pcap_t *, bpf_u_int32); static int dlbindreq(int, bpf_u_int32, char *); static int dlbindack(int, char *, char *, int *); static int dlokack(int, const char *, char *, char *); static int dlinforeq(int, char *); static int dlinfoack(int, char *, char *); #ifdef HAVE_DLPI_PASSIVE static void dlpassive(int, char *); #endif #ifdef DL_HP_RAWDLS static int dlrawdatareq(int, const u_char *, int); #endif static int recv_ack(int, int, const char *, char *, char *, int *); static char *dlstrerror(bpf_u_int32); static char *dlprim(bpf_u_int32); #if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H) static char *get_release(bpf_u_int32 *, bpf_u_int32 *, bpf_u_int32 *); #endif static int send_request(int, char *, int, char *, char *); #ifdef HAVE_HPUX9 static int dlpi_kread(int, off_t, void *, u_int, char *); #endif #ifdef HAVE_DEV_DLPI static int get_dlpi_ppa(int, const char *, int, char *); #endif /* XXX Needed by HP-UX (at least) */ static bpf_u_int32 ctlbuf[MAXDLBUF]; static struct strbuf ctl = { MAXDLBUF, 0, (char *)ctlbuf }; /* * Cast a buffer to "union DL_primitives" without provoking warnings * from the compiler. */ #define MAKE_DL_PRIMITIVES(ptr) ((union DL_primitives *)(void *)(ptr)) static int pcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { int cc; u_char *bp; int flags; struct strbuf data; flags = 0; cc = p->cc; if (cc == 0) { data.buf = (char *)p->buffer + p->offset; data.maxlen = p->bufsize; data.len = 0; do { /* * Has "pcap_breakloop()" been called? */ if (p->break_loop) { /* * Yes - clear the flag that indicates * that it has, and return -2 to * indicate that we were told to * break out of the loop. */ p->break_loop = 0; return (-2); } /* * XXX - check for the DLPI primitive, which * would be DL_HP_RAWDATA_IND on HP-UX * if we're in raw mode? */ if (getmsg(p->fd, &ctl, &data, &flags) < 0) { /* Don't choke when we get ptraced */ switch (errno) { case EINTR: cc = 0; continue; case EAGAIN: return (0); } strlcpy(p->errbuf, pcap_strerror(errno), sizeof(p->errbuf)); return (-1); } cc = data.len; } while (cc == 0); bp = p->buffer + p->offset; } else bp = p->bp; return (pcap_process_pkts(p, callback, user, cnt, bp, cc)); } static int pcap_inject_dlpi(pcap_t *p, const void *buf, size_t size) { int ret; #if defined(DLIOCRAW) ret = write(p->fd, buf, size); if (ret == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s", pcap_strerror(errno)); return (-1); } #elif defined(DL_HP_RAWDLS) if (p->send_fd < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: Output FD couldn't be opened"); return (-1); } ret = dlrawdatareq(p->send_fd, buf, size); if (ret == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s", pcap_strerror(errno)); return (-1); } /* * putmsg() returns either 0 or -1; it doesn't indicate how * many bytes were written (presumably they were all written * or none of them were written). OpenBSD's pcap_inject() * returns the number of bytes written, so, for API compatibility, * we return the number of bytes we were told to write. */ ret = size; #else /* no raw mode */ /* * XXX - this is a pain, because you might have to extract * the address from the packet and use it in a DL_UNITDATA_REQ * request. That would be dependent on the link-layer type. * * I also don't know what SAP you'd have to bind the descriptor * to, or whether you'd need separate "receive" and "send" FDs, * nor do I know whether you'd need different bindings for * D/I/X Ethernet and 802.3, or for {FDDI,Token Ring} plus * 802.2 and {FDDI,Token Ring} plus 802.2 plus SNAP. * * So, for now, we just return a "you can't send" indication, * and leave it up to somebody with a DLPI-based system lacking * both DLIOCRAW and DL_HP_RAWDLS to supply code to implement * packet transmission on that system. If they do, they should * send it to us - but should not send us code that assumes * Ethernet; if the code doesn't work on non-Ethernet interfaces, * it should check "p->linktype" and reject the send request if * it's anything other than DLT_EN10MB. */ strlcpy(p->errbuf, "send: Not supported on this version of this OS", PCAP_ERRBUF_SIZE); ret = -1; #endif /* raw mode */ return (ret); } #ifndef DL_IPATM #define DL_IPATM 0x12 /* ATM Classical IP interface */ #endif #ifdef HAVE_SOLARIS /* * For SunATM. */ #ifndef A_GET_UNITS #define A_GET_UNITS (('A'<<8)|118) #endif /* A_GET_UNITS */ #ifndef A_PROMISCON_REQ #define A_PROMISCON_REQ (('A'<<8)|121) #endif /* A_PROMISCON_REQ */ #endif /* HAVE_SOLARIS */ static void pcap_cleanup_dlpi(pcap_t *p) { if (p->send_fd >= 0) { close(p->send_fd); p->send_fd = -1; } pcap_cleanup_live_common(p); } static int pcap_activate_dlpi(pcap_t *p) { register char *cp; int ppa; #ifdef HAVE_SOLARIS int isatm = 0; #endif register dl_info_ack_t *infop; #ifdef HAVE_SYS_BUFMOD_H bpf_u_int32 ss; #ifdef HAVE_SOLARIS register char *release; bpf_u_int32 osmajor, osminor, osmicro; #endif #endif bpf_u_int32 buf[MAXDLBUF]; char dname[100]; #ifndef HAVE_DEV_DLPI char dname2[100]; #endif int status = PCAP_ERROR; #ifdef HAVE_DEV_DLPI /* ** Remove any "/dev/" on the front of the device. */ cp = strrchr(p->opt.source, '/'); if (cp == NULL) strlcpy(dname, p->opt.source, sizeof(dname)); else strlcpy(dname, cp + 1, sizeof(dname)); /* * 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 = split_dname(dname, &ppa, p->errbuf); if (cp == NULL) { status = PCAP_ERROR_NO_SUCH_DEVICE; goto bad; } *cp = '\0'; /* * Use "/dev/dlpi" as the device. * * XXX - HP's DLPI Programmer's Guide for HP-UX 11.00 says that * the "dl_mjr_num" field is for the "major number of interface * driver"; that's the major of "/dev/dlpi" on the system on * which I tried this, but there may be DLPI devices that * use a different driver, in which case we may need to * search "/dev" for the appropriate device with that major * device number, rather than hardwiring "/dev/dlpi". */ cp = "/dev/dlpi"; if ((p->fd = open(cp, O_RDWR)) < 0) { if (errno == EPERM || errno == EACCES) status = PCAP_ERROR_PERM_DENIED; snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", cp, pcap_strerror(errno)); goto bad; } #ifdef DL_HP_RAWDLS /* * XXX - HP-UX 10.20 and 11.xx don't appear to support sending and * receiving packets on the same descriptor - you need separate * descriptors for sending and receiving, bound to different SAPs. * * If the open fails, we just leave -1 in "p->send_fd" and reject * attempts to send packets, just as if, in pcap-bpf.c, we fail * to open the BPF device for reading and writing, we just try * to open it for reading only and, if that succeeds, just let * the send attempts fail. */ p->send_fd = open(cp, O_RDWR); #endif /* * Get a table of all PPAs for that device, and search that * table for the specified device type name and unit number. */ ppa = get_dlpi_ppa(p->fd, dname, ppa, p->errbuf); if (ppa < 0) { status = ppa; goto bad; } #else /* * 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 (*p->opt.source == '/') strlcpy(dname, p->opt.source, sizeof(dname)); else snprintf(dname, sizeof(dname), "%s/%s", PCAP_DEV_PREFIX, p->opt.source); /* * Get the unit number, and a pointer to the end of the device * type name. */ cp = split_dname(dname, &ppa, p->errbuf); if (cp == NULL) { status = PCAP_ERROR_NO_SUCH_DEVICE; goto bad; } /* * Make a copy of the device pathname, and then remove the unit * number from the device pathname. */ strlcpy(dname2, dname, sizeof(dname)); *cp = '\0'; /* Try device without unit number */ if ((p->fd = open(dname, O_RDWR)) < 0) { if (errno != ENOENT) { if (errno == EPERM || errno == EACCES) status = PCAP_ERROR_PERM_DENIED; snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", dname, pcap_strerror(errno)); goto bad; } /* Try again with unit number */ if ((p->fd = open(dname2, O_RDWR)) < 0) { if (errno == ENOENT) { status = PCAP_ERROR_NO_SUCH_DEVICE; /* * We provide an error message even * for this error, for diagnostic * purposes (so that, for example, * the app can show the message if the * user requests it). * * In it, we just report "No DLPI device * found" with the device name, so people * don't get confused and think, for example, * that if they can't capture on "lo0" * on Solaris the fix is to change libpcap * (or the application that uses it) to * look for something other than "/dev/lo0", * as the fix is to look for an operating * system other than Solaris - you just * *can't* capture on a loopback interface * on Solaris, the lack of a DLPI device * for the loopback interface is just a * symptom of that inability. */ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: No DLPI device found", p->opt.source); } else { if (errno == EPERM || errno == EACCES) status = PCAP_ERROR_PERM_DENIED; snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", dname2, pcap_strerror(errno)); } goto bad; } /* XXX Assume unit zero */ ppa = 0; } #endif /* ** Attach if "style 2" provider */ if (dlinforeq(p->fd, p->errbuf) < 0 || dlinfoack(p->fd, (char *)buf, p->errbuf) < 0) goto bad; infop = &(MAKE_DL_PRIMITIVES(buf))->info_ack; #ifdef HAVE_SOLARIS if (infop->dl_mac_type == DL_IPATM) isatm = 1; #endif if (infop->dl_provider_style == DL_STYLE2) { status = dl_doattach(p->fd, ppa, p->errbuf); if (status < 0) goto bad; #ifdef DL_HP_RAWDLS if (p->send_fd >= 0) { if (dl_doattach(p->send_fd, ppa, p->errbuf) < 0) goto bad; } #endif } if (p->opt.rfmon) { /* * This device exists, but we don't support monitor mode * any platforms that support DLPI. */ status = PCAP_ERROR_RFMON_NOTSUP; goto bad; } #ifdef HAVE_DLPI_PASSIVE /* * Enable Passive mode to be able to capture on aggregated link. * Not supported in all Solaris versions. */ dlpassive(p->fd, p->errbuf); #endif /* ** Bind (defer if using HP-UX 9 or HP-UX 10.20 or later, totally ** skip if using SINIX) */ #if !defined(HAVE_HPUX9) && !defined(HAVE_HPUX10_20_OR_LATER) && !defined(sinix) #ifdef _AIX /* ** AIX. ** 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, p->errbuf) < 0 && dlbindreq(p->fd, 2, p->errbuf) < 0) || dlbindack(p->fd, (char *)buf, p->errbuf, NULL) < 0) goto bad; #elif defined(DL_HP_RAWDLS) /* ** HP-UX 10.0x and 10.1x. */ if (dl_dohpuxbind(p->fd, p->errbuf) < 0) goto bad; if (p->send_fd >= 0) { /* ** XXX - if this fails, just close send_fd and ** set it to -1, so that you can't send but can ** still receive? */ if (dl_dohpuxbind(p->send_fd, p->errbuf) < 0) goto bad; } #else /* neither AIX nor HP-UX */ /* ** Not Sinix, and neither AIX nor HP-UX - Solaris, and any other ** OS using DLPI. **/ if (dlbindreq(p->fd, 0, p->errbuf) < 0 || dlbindack(p->fd, (char *)buf, p->errbuf, NULL) < 0) goto bad; #endif /* AIX vs. HP-UX vs. other */ #endif /* !HP-UX 9 and !HP-UX 10.20 or later and !SINIX */ #ifdef HAVE_SOLARIS if (isatm) { /* ** Have to turn on some special ATM promiscuous mode ** for SunATM. ** Do *NOT* turn regular promiscuous mode on; it doesn't ** help, and may break things. */ if (strioctl(p->fd, A_PROMISCON_REQ, 0, NULL) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "A_PROMISCON_REQ: %s", pcap_strerror(errno)); goto bad; } } else #endif if (p->opt.promisc) { /* ** Enable promiscuous (not necessary on send FD) */ status = dlpromiscon(p, DL_PROMISC_PHYS); if (status < 0) { if (status == PCAP_ERROR_PERM_DENIED) status = PCAP_ERROR_PROMISC_PERM_DENIED; goto bad; } /* ** Try to enable multicast (you would have thought ** promiscuous would be sufficient). (Skip if using ** HP-UX or SINIX) (Not necessary on send FD) */ #if !defined(__hpux) && !defined(sinix) status = dlpromiscon(p, DL_PROMISC_MULTI); if (status < 0) status = PCAP_WARNING; #endif } /* ** Try to enable SAP promiscuity (when not in promiscuous mode ** when using HP-UX, when not doing SunATM on Solaris, and never ** under SINIX) (Not necessary on send FD) */ #ifndef sinix #if defined(__hpux) /* HP-UX - only do this when not in promiscuous mode */ if (!p->opt.promisc) { #elif defined(HAVE_SOLARIS) /* Solaris - don't do this on SunATM devices */ if (!isatm) { #else /* Everything else (except for SINIX) - always do this */ { #endif status = dlpromiscon(p, DL_PROMISC_SAP); if (status < 0) { /* * Not fatal, since the DL_PROMISC_PHYS mode worked. * Report it as a warning, however. */ if (p->opt.promisc) status = PCAP_WARNING; else goto bad; } } #endif /* sinix */ /* ** HP-UX 9, and HP-UX 10.20 or later, must bind after setting ** promiscuous options. */ #if defined(HAVE_HPUX9) || defined(HAVE_HPUX10_20_OR_LATER) if (dl_dohpuxbind(p->fd, p->errbuf) < 0) goto bad; /* ** We don't set promiscuous mode on the send FD, but we'll defer ** binding it anyway, just to keep the HP-UX 9/10.20 or later ** code together. */ if (p->send_fd >= 0) { /* ** XXX - if this fails, just close send_fd and ** set it to -1, so that you can't send but can ** still receive? */ if (dl_dohpuxbind(p->send_fd, p->errbuf) < 0) goto bad; } #endif /* ** Determine link type ** XXX - get SAP length and address length as well, for use ** when sending packets. */ if (dlinforeq(p->fd, p->errbuf) < 0 || dlinfoack(p->fd, (char *)buf, p->errbuf) < 0) goto bad; infop = &(MAKE_DL_PRIMITIVES(buf))->info_ack; if (pcap_process_mactype(p, infop->dl_mac_type) != 0) goto bad; #ifdef DLIOCRAW /* ** This is a non standard SunOS hack to get the full raw link-layer ** header. */ if (strioctl(p->fd, DLIOCRAW, 0, NULL) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "DLIOCRAW: %s", pcap_strerror(errno)); goto bad; } #endif #ifdef HAVE_SYS_BUFMOD_H ss = p->snapshot; /* ** There is a bug in bufmod(7). When dealing with messages of ** less than snaplen size it strips data from the beginning not ** the end. ** ** This bug is fixed in 5.3.2. Also, there is a patch available. ** Ask for bugid 1149065. */ #ifdef HAVE_SOLARIS release = get_release(&osmajor, &osminor, &osmicro); if (osmajor == 5 && (osminor <= 2 || (osminor == 3 && osmicro < 2)) && getenv("BUFMOD_FIXED") == NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "WARNING: bufmod is broken in SunOS %s; ignoring snaplen.", release); ss = 0; status = PCAP_WARNING; } #endif /* Push and configure bufmod. */ if (pcap_conf_bufmod(p, ss, p->md.timeout) != 0) goto bad; #endif /* ** As the last operation flush the read side. */ if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s", pcap_strerror(errno)); goto bad; } /* Allocate data buffer. */ if (pcap_alloc_databuf(p) != 0) goto bad; /* Success - but perhaps with a warning */ if (status < 0) status = 0; /* * "p->fd" is an FD for a STREAMS device, so "select()" and * "poll()" should work on it. */ p->selectable_fd = p->fd; p->read_op = pcap_read_dlpi; p->inject_op = pcap_inject_dlpi; p->setfilter_op = install_bpf_program; /* no kernel filtering */ p->setdirection_op = NULL; /* Not implemented.*/ p->set_datalink_op = NULL; /* can't change data link type */ p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; p->stats_op = pcap_stats_dlpi; p->cleanup_op = pcap_cleanup_dlpi; return (status); bad: pcap_cleanup_dlpi(p); return (status); } /* * 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; long 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--; errno = 0; unit = strtol(cp, &eos, 10); if (*eos != '\0') { snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s bad unit number", device); return (NULL); } if (errno == ERANGE || unit > INT_MAX) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number too large", device); return (NULL); } if (unit < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number is negative", device); return (NULL); } *unitp = (int)unit; return (cp); } static int dl_doattach(int fd, int ppa, char *ebuf) { dl_attach_req_t req; bpf_u_int32 buf[MAXDLBUF]; int err; req.dl_primitive = DL_ATTACH_REQ; req.dl_ppa = ppa; if (send_request(fd, (char *)&req, sizeof(req), "attach", ebuf) < 0) return (PCAP_ERROR); err = dlokack(fd, "attach", (char *)buf, ebuf); if (err < 0) return (err); return (0); } #ifdef DL_HP_RAWDLS static int dl_dohpuxbind(int fd, char *ebuf) { int hpsap; int uerror; bpf_u_int32 buf[MAXDLBUF]; /* * XXX - we start at 22 because we used to use only 22, but * that was just because that was the value used in some * sample code from HP. With what value *should* we start? * Does it matter, given that we're enabling SAP promiscuity * on the input FD? */ hpsap = 22; for (;;) { if (dlbindreq(fd, hpsap, ebuf) < 0) return (-1); if (dlbindack(fd, (char *)buf, ebuf, &uerror) >= 0) break; /* * For any error other than a UNIX EBUSY, give up. */ if (uerror != EBUSY) { /* * dlbindack() has already filled in ebuf for * this error. */ return (-1); } /* * For EBUSY, try the next SAP value; that means that * somebody else is using that SAP. Clear ebuf so * that application doesn't report the "Device busy" * error as a warning. */ *ebuf = '\0'; hpsap++; if (hpsap > 100) { strlcpy(ebuf, "All SAPs from 22 through 100 are in use", PCAP_ERRBUF_SIZE); return (-1); } } return (0); } #endif #define STRINGIFY(n) #n static int dlpromiscon(pcap_t *p, bpf_u_int32 level) { dl_promiscon_req_t req; bpf_u_int32 buf[MAXDLBUF]; int err; req.dl_primitive = DL_PROMISCON_REQ; req.dl_level = level; if (send_request(p->fd, (char *)&req, sizeof(req), "promiscon", p->errbuf) < 0) return (PCAP_ERROR); err = dlokack(p->fd, "promiscon" STRINGIFY(level), (char *)buf, p->errbuf); if (err < 0) return (err); return (0); } int pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) { #ifdef HAVE_SOLARIS int fd; union { u_int nunits; char pad[516]; /* XXX - must be at least 513; is 516 in "atmgetunits" */ } buf; char baname[2+1+1]; u_int i; /* * We may have to do special magic to get ATM devices. */ if ((fd = open("/dev/ba", O_RDWR)) < 0) { /* * We couldn't open the "ba" device. * For now, just give up; perhaps we should * return an error if the problem is neither * a "that device doesn't exist" error (ENOENT, * ENXIO, etc.) or a "you're not allowed to do * that" error (EPERM, EACCES). */ return (0); } if (strioctl(fd, A_GET_UNITS, sizeof(buf), (char *)&buf) < 0) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "A_GET_UNITS: %s", pcap_strerror(errno)); return (-1); } for (i = 0; i < buf.nunits; i++) { snprintf(baname, sizeof baname, "ba%u", i); if (pcap_add_if(alldevsp, baname, 0, NULL, errbuf) < 0) return (-1); } #endif return (0); } static int send_request(int fd, char *ptr, int len, char *what, char *ebuf) { struct strbuf ctl; int flags; ctl.maxlen = 0; ctl.len = len; ctl.buf = ptr; flags = 0; if (putmsg(fd, &ctl, (struct strbuf *) NULL, flags) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "send_request: putmsg \"%s\": %s", what, pcap_strerror(errno)); return (-1); } return (0); } static int recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf, int *uerror) { union DL_primitives *dlp; struct strbuf ctl; int flags; /* * Clear out "*uerror", so it's only set for DL_ERROR_ACK/DL_SYSERR, * making that the only place where EBUSY is treated specially. */ if (uerror != NULL) *uerror = 0; ctl.maxlen = MAXDLBUF; ctl.len = 0; ctl.buf = bufp; flags = 0; if (getmsg(fd, &ctl, (struct strbuf*)NULL, &flags) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s getmsg: %s", what, pcap_strerror(errno)); return (PCAP_ERROR); } dlp = MAKE_DL_PRIMITIVES(ctl.buf); switch (dlp->dl_primitive) { case DL_INFO_ACK: case DL_BIND_ACK: case DL_OK_ACK: #ifdef DL_HP_PPA_ACK case DL_HP_PPA_ACK: #endif /* These are OK */ break; case DL_ERROR_ACK: switch (dlp->error_ack.dl_errno) { case DL_SYSERR: if (uerror != NULL) *uerror = dlp->error_ack.dl_unix_errno; snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: UNIX error - %s", what, pcap_strerror(dlp->error_ack.dl_unix_errno)); if (dlp->error_ack.dl_unix_errno == EPERM || dlp->error_ack.dl_unix_errno == EACCES) return (PCAP_ERROR_PERM_DENIED); break; default: snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: %s", what, dlstrerror(dlp->error_ack.dl_errno)); if (dlp->error_ack.dl_errno == DL_BADPPA) return (PCAP_ERROR_NO_SUCH_DEVICE); else if (dlp->error_ack.dl_errno == DL_ACCESS) return (PCAP_ERROR_PERM_DENIED); break; } return (PCAP_ERROR); default: snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: Unexpected primitive ack %s", what, dlprim(dlp->dl_primitive)); return (PCAP_ERROR); } if (ctl.len < size) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: Ack too small (%d < %d)", what, ctl.len, size); return (PCAP_ERROR); } 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 dlbindreq(int fd, bpf_u_int32 sap, char *ebuf) { dl_bind_req_t req; memset((char *)&req, 0, sizeof(req)); req.dl_primitive = DL_BIND_REQ; /* XXX - what if neither of these are defined? */ #if defined(DL_HP_RAWDLS) req.dl_max_conind = 1; /* XXX magic number */ req.dl_service_mode = DL_HP_RAWDLS; #elif defined(DL_CLDLS) req.dl_service_mode = DL_CLDLS; #endif req.dl_sap = sap; return (send_request(fd, (char *)&req, sizeof(req), "bind", ebuf)); } static int dlbindack(int fd, char *bufp, char *ebuf, int *uerror) { return (recv_ack(fd, DL_BIND_ACK_SIZE, "bind", bufp, ebuf, uerror)); } static int dlokack(int fd, const char *what, char *bufp, char *ebuf) { return (recv_ack(fd, DL_OK_ACK_SIZE, what, bufp, ebuf, NULL)); } static int dlinforeq(int fd, char *ebuf) { dl_info_req_t req; req.dl_primitive = DL_INFO_REQ; return (send_request(fd, (char *)&req, sizeof(req), "info", ebuf)); } static int dlinfoack(int fd, char *bufp, char *ebuf) { return (recv_ack(fd, DL_INFO_ACK_SIZE, "info", bufp, ebuf, NULL)); } #ifdef HAVE_DLPI_PASSIVE /* * Enable DLPI passive mode. We do not care if this request fails, as this * indicates the underlying DLPI device does not support link aggregation. */ static void dlpassive(int fd, char *ebuf) { dl_passive_req_t req; bpf_u_int32 buf[MAXDLBUF]; req.dl_primitive = DL_PASSIVE_REQ; if (send_request(fd, (char *)&req, sizeof(req), "dlpassive", ebuf) == 0) (void) dlokack(fd, "dlpassive", (char *)buf, ebuf); } #endif #ifdef DL_HP_RAWDLS /* * There's an ack *if* there's an error. */ static int dlrawdatareq(int fd, const u_char *datap, int datalen) { struct strbuf ctl, data; long buf[MAXDLBUF]; /* XXX - char? */ union DL_primitives *dlp; int dlen; dlp = MAKE_DL_PRIMITIVES(buf); dlp->dl_primitive = DL_HP_RAWDATA_REQ; dlen = DL_HP_RAWDATA_REQ_SIZE; /* * HP's documentation doesn't appear to show us supplying any * address pointed to by the control part of the message. * I think that's what raw mode means - you just send the raw * packet, you don't specify where to send it to, as that's * implied by the destination address. */ ctl.maxlen = 0; ctl.len = dlen; ctl.buf = (void *)buf; data.maxlen = 0; data.len = datalen; data.buf = (void *)datap; return (putmsg(fd, &ctl, &data, 0)); } #endif /* DL_HP_RAWDLS */ #if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H) static char * get_release(bpf_u_int32 *majorp, bpf_u_int32 *minorp, bpf_u_int32 *microp) { char *cp; static char buf[32]; *majorp = 0; *minorp = 0; *microp = 0; if (sysinfo(SI_RELEASE, buf, sizeof(buf)) < 0) return ("?"); cp = buf; if (!isdigit((unsigned char)*cp)) return (buf); *majorp = strtol(cp, &cp, 10); if (*cp++ != '.') return (buf); *minorp = strtol(cp, &cp, 10); if (*cp++ != '.') return (buf); *microp = strtol(cp, &cp, 10); return (buf); } #endif #ifdef DL_HP_PPA_REQ /* * Under HP-UX 10 and HP-UX 11, we can ask for the ppa */ /* * Determine ppa number that specifies ifname. * * If the "dl_hp_ppa_info_t" doesn't have a "dl_module_id_1" member, * the code that's used here is the old code for HP-UX 10.x. * * However, HP-UX 10.20, at least, appears to have such a member * in its "dl_hp_ppa_info_t" structure, so the new code is used. * The new code didn't work on an old 10.20 system on which Rick * Jones of HP tried it, but with later patches installed, it * worked - it appears that the older system had those members but * didn't put anything in them, so, if the search by name fails, we * do the old search. * * Rick suggests that making sure your system is "up on the latest * lancommon/DLPI/driver patches" is probably a good idea; it'd fix * that problem, as well as allowing libpcap to see packets sent * from the system on which the libpcap application is being run. * (On 10.20, in addition to getting the latest patches, you need * to turn the kernel "lanc_outbound_promisc_flag" flag on with ADB; * a posting to "comp.sys.hp.hpux" at * * http://www.deja.com/[ST_rn=ps]/getdoc.xp?AN=558092266 * * says that, to see the machine's outgoing traffic, you'd need to * apply the right patches to your system, and also set that variable * with: echo 'lanc_outbound_promisc_flag/W1' | /usr/bin/adb -w /stand/vmunix /dev/kmem * which could be put in, for example, "/sbin/init.d/lan". * * Setting the variable is not necessary on HP-UX 11.x. */ static int get_dlpi_ppa(register int fd, register const char *device, register int unit, register char *ebuf) { register dl_hp_ppa_ack_t *ap; register dl_hp_ppa_info_t *ipstart, *ip; register int i; char dname[100]; register u_long majdev; struct stat statbuf; dl_hp_ppa_req_t req; 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) return (PCAP_ERROR); 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 (PCAP_ERROR); } 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 (PCAP_ERROR); } if (ctl.len < DL_HP_PPA_ACK_SIZE) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "get_dlpi_ppa: hpppa ack too small (%d < %lu)", ctl.len, (unsigned long)DL_HP_PPA_ACK_SIZE); return (PCAP_ERROR); } /* 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 (PCAP_ERROR); } 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 (PCAP_ERROR); } if (ctl.len < dlp->dl_length) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "get_dlpi_ppa: hpppa ack too small (%d < %lu)", ctl.len, (unsigned long)dlp->dl_length); free(ppa_data_buf); return (PCAP_ERROR); } ap = (dl_hp_ppa_ack_t *)buf; ipstart = (dl_hp_ppa_info_t *)ppa_data_buf; ip = ipstart; #ifdef HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1 /* * The "dl_hp_ppa_info_t" structure has a "dl_module_id_1" * member that should, in theory, contain the part of the * name for the device that comes before the unit number, * and should also have a "dl_module_id_2" member that may * contain an alternate name (e.g., I think Ethernet devices * have both "lan", for "lanN", and "snap", for "snapN", with * the former being for Ethernet packets and the latter being * for 802.3/802.2 packets). * * Search for the device that has the specified name and * instance number. */ for (i = 0; i < ap->dl_count; i++) { 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; ip = (dl_hp_ppa_info_t *)((u_char *)ipstart + ip->dl_next_offset); } #else /* * We don't have that member, so the search is impossible; make it * look as if the search failed. */ i = ap->dl_count; #endif if (i == ap->dl_count) { /* * Well, we didn't, or can't, find the device by name. * * HP-UX 10.20, whilst it has "dl_module_id_1" and * "dl_module_id_2" fields in the "dl_hp_ppa_info_t", * doesn't seem to fill them in unless the system is * at a reasonably up-to-date patch level. * * Older HP-UX 10.x systems might not have those fields * at all. * * Therefore, we'll search for the entry with the major * device number of a device with the name "/dev/", * if such a device exists, as the old code did. */ snprintf(dname, sizeof(dname), "/dev/%s%d", device, unit); if (stat(dname, &statbuf) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "stat: %s: %s", dname, pcap_strerror(errno)); return (PCAP_ERROR); } majdev = major(statbuf.st_rdev); ip = ipstart; for (i = 0; i < ap->dl_count; i++) { if (ip->dl_mjr_num == majdev && ip->dl_instance_num == unit) break; ip = (dl_hp_ppa_info_t *)((u_char *)ipstart + ip->dl_next_offset); } } if (i == ap->dl_count) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "can't find /dev/dlpi PPA for %s%d", device, unit); return (PCAP_ERROR_NO_SUCH_DEVICE); } 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 (PCAP_ERROR); } ppa = ip->dl_ppa; free(ppa_data_buf); return (ppa); } #endif #ifdef HAVE_HPUX9 /* * Under HP-UX 9, there is no good way to determine the ppa. * So punt and read it from /dev/kmem. */ static struct nlist nl[] = { #define NL_IFNET 0 { "ifnet" }, { "" } }; static char path_vmunix[] = "/hp-ux"; /* Determine ppa number that specifies ifname */ static int get_dlpi_ppa(register int fd, register const char *ifname, register int unit, register char *ebuf) { register const char *cp; register int kd; void *addr; struct ifnet ifnet; char if_name[sizeof(ifnet.if_name) + 1]; cp = strrchr(ifname, '/'); if (cp != NULL) ifname = cp + 1; if (nlist(path_vmunix, &nl) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "nlist %s failed", path_vmunix); return (-1); } if (nl[NL_IFNET].n_value == 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "could't find %s kernel symbol", nl[NL_IFNET].n_name); return (-1); } kd = open("/dev/kmem", O_RDONLY); if (kd < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "kmem open: %s", pcap_strerror(errno)); return (-1); } if (dlpi_kread(kd, nl[NL_IFNET].n_value, &addr, sizeof(addr), ebuf) < 0) { close(kd); return (-1); } for (; addr != NULL; addr = ifnet.if_next) { if (dlpi_kread(kd, (off_t)addr, &ifnet, sizeof(ifnet), ebuf) < 0 || dlpi_kread(kd, (off_t)ifnet.if_name, if_name, sizeof(ifnet.if_name), ebuf) < 0) { (void)close(kd); return (-1); } if_name[sizeof(ifnet.if_name)] = '\0'; if (strcmp(if_name, ifname) == 0 && ifnet.if_unit == unit) return (ifnet.if_index); } snprintf(ebuf, PCAP_ERRBUF_SIZE, "Can't find %s", ifname); return (-1); } static int dlpi_kread(register int fd, register off_t addr, register void *buf, register u_int len, register char *ebuf) { register int cc; if (lseek(fd, addr, SEEK_SET) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "lseek: %s", pcap_strerror(errno)); return (-1); } cc = read(fd, buf, len); if (cc < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "read: %s", pcap_strerror(errno)); return (-1); } else if (cc != len) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "short read (%d != %d)", cc, len); return (-1); } return (cc); } #endif pcap_t * -pcap_create(const char *device, char *ebuf) +pcap_create_interface(const char *device, char *ebuf) { pcap_t *p; p = pcap_create_common(device, ebuf); if (p == NULL) return (NULL); p->send_fd = -1; /* it hasn't been opened yet */ p->activate_op = pcap_activate_dlpi; return (p); } Index: stable/9/contrib/libpcap/pcap-filter.manmisc =================================================================== --- stable/9/contrib/libpcap/pcap-filter.manmisc (revision 252280) +++ stable/9/contrib/libpcap/pcap-filter.manmisc (revision 252281) @@ -1,962 +1,952 @@ .\" @(#) $Header: /tcpdump/master/libpcap/pcap-filter.manmisc.in,v 1.1 2008-10-21 07:33:01 guy Exp $ (LBL) .\" .\" Copyright (c) 1987, 1988, 1989, 1990, 1991, 1992, 1994, 1995, 1996, 1997 .\" The Regents of the University of California. All rights reserved. .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that: (1) source code distributions .\" retain the above copyright notice and this paragraph in its entirety, (2) .\" distributions including binary code include the above copyright notice and .\" this paragraph in its entirety in the documentation or other materials .\" provided with the distribution, and (3) all advertising materials mentioning .\" features or use of this software display the following acknowledgement: .\" ``This product includes software developed by the University of California, .\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of .\" the University nor the names of its contributors may be used to endorse .\" or promote products derived from this software without specific prior .\" written permission. .\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. .\" .TH PCAP-FILTER 7 "6 January 2008" .SH NAME pcap-filter \- packet filter syntax .br .ad .SH DESCRIPTION .LP .B pcap_compile() is used to compile a string into a filter program. The resulting filter program can then be applied to some stream of packets to determine which packets will be supplied to .BR pcap_loop() , .BR pcap_dispatch() , .BR pcap_next() , or .BR pcap_next_ex() . .LP The \fIfilter expression\fP consists of one or more .IR primitives . Primitives usually consist of an .I id (name or number) preceded by one or more qualifiers. There are three different kinds of qualifier: .IP \fItype\fP +.I type qualifiers say what kind of thing the id name or number refers to. Possible types are .BR host , .B net , .B port and .BR portrange . E.g., `host foo', `net 128.3', `port 20', `portrange 6000-6008'. If there is no type qualifier, .B host is assumed. .IP \fIdir\fP +.I dir qualifiers specify a particular transfer direction to and/or from .IR id . Possible directions are .BR src , .BR dst , .BR "src or dst" , .BR "src and dst" , .BR ra , .BR ta , .BR addr1 , .BR addr2 , .BR addr3 , and .BR addr4 . E.g., `src foo', `dst net 128.3', `src or dst port ftp-data'. If there is no dir qualifier, .B "src or dst" is assumed. The .BR ra , .BR ta , .BR addr1 , .BR addr2 , .BR addr3 , and .B addr4 qualifiers are only valid for IEEE 802.11 Wireless LAN link layers. For some link layers, such as SLIP and the ``cooked'' Linux capture mode used for the ``any'' device and for some other device types, the .B inbound and .B outbound qualifiers can be used to specify a desired direction. .IP \fIproto\fP +.I proto qualifiers restrict the match to a particular protocol. Possible protos are: .BR ether , .BR fddi , .BR tr , .BR wlan , .BR ip , .BR ip6 , .BR arp , .BR rarp , .BR decnet , .B tcp and .BR udp . E.g., `ether src foo', `arp net 128.3', `tcp port 21', `udp portrange 7000-7009', `wlan addr2 0:2:3:4:5:6'. If there is no proto qualifier, all protocols consistent with the type are assumed. E.g., `src foo' means `(ip or arp or rarp) src foo' (except the latter is not legal syntax), `net bar' means `(ip or arp or rarp) net bar' and `port 53' means `(tcp or udp) port 53'. .LP [`fddi' is actually an alias for `ether'; the parser treats them identically as meaning ``the data link level used on the specified network interface.'' FDDI headers contain Ethernet-like source and destination addresses, and often contain Ethernet-like packet types, so you can filter on these FDDI fields just as with the analogous Ethernet fields. FDDI headers also contain other fields, but you cannot name them explicitly in a filter expression. .LP Similarly, `tr' and `wlan' are aliases for `ether'; the previous paragraph's statements about FDDI headers also apply to Token Ring and 802.11 wireless LAN headers. For 802.11 headers, the destination address is the DA field and the source address is the SA field; the BSSID, RA, and TA fields aren't tested.] .LP In addition to the above, there are some special `primitive' keywords that don't follow the pattern: .BR gateway , .BR broadcast , .BR less , .B greater and arithmetic expressions. All of these are described below. .LP More complex filter expressions are built up by using the words .BR and , .B or and .B not to combine primitives. E.g., `host foo and not port ftp and not port ftp-data'. To save typing, identical qualifier lists can be omitted. E.g., `tcp dst port ftp or ftp-data or domain' is exactly the same as `tcp dst port ftp or tcp dst port ftp-data or tcp dst port domain'. .LP Allowable primitives are: .IP "\fBdst host \fIhost\fR" True if the IPv4/v6 destination field of the packet is \fIhost\fP, which may be either an address or a name. .IP "\fBsrc host \fIhost\fR" True if the IPv4/v6 source field of the packet is \fIhost\fP. -.IP "\fBhost \fIhost\fP +.IP "\fBhost \fIhost\fP" True if either the IPv4/v6 source or destination of the packet is \fIhost\fP. .IP Any of the above host expressions can be prepended with the keywords, \fBip\fP, \fBarp\fP, \fBrarp\fP, or \fBip6\fP as in: .in +.5i .nf \fBip host \fIhost\fR .fi .in -.5i which is equivalent to: .in +.5i .nf \fBether proto \fI\\ip\fB and host \fIhost\fR .fi .in -.5i If \fIhost\fR is a name with multiple IP addresses, each address will be checked for a match. -.IP "\fBether dst \fIehost\fP +.IP "\fBether dst \fIehost\fP" True if the Ethernet destination address is \fIehost\fP. \fIEhost\fP may be either a name from /etc/ethers or a number (see .IR ethers (3N) for numeric format). -.IP "\fBether src \fIehost\fP +.IP "\fBether src \fIehost\fP" True if the Ethernet source address is \fIehost\fP. -.IP "\fBether host \fIehost\fP +.IP "\fBether host \fIehost\fP" True if either the Ethernet source or destination address is \fIehost\fP. -.IP "\fBgateway\fP \fIhost\fP +.IP "\fBgateway\fP \fIhost\fP" True if the packet used \fIhost\fP as a gateway. I.e., the Ethernet source or destination address was \fIhost\fP but neither the IP source nor the IP destination was \fIhost\fP. \fIHost\fP must be a name and must be found both by the machine's host-name-to-IP-address resolution mechanisms (host name file, DNS, NIS, etc.) and by the machine's host-name-to-Ethernet-address resolution mechanism (/etc/ethers, etc.). (An equivalent expression is .in +.5i .nf \fBether host \fIehost \fBand not host \fIhost\fR .fi .in -.5i which can be used with either names or numbers for \fIhost / ehost\fP.) This syntax does not work in IPv6-enabled configuration at this moment. .IP "\fBdst net \fInet\fR" True if the IPv4/v6 destination address of the packet has a network number of \fInet\fP. \fINet\fP may be either a name from the networks database (/etc/networks, etc.) or a network number. An IPv4 network number can be written as a dotted quad (e.g., 192.168.1.0), dotted triple (e.g., 192.168.1), dotted pair (e.g, 172.16), or single number (e.g., 10); the netmask is 255.255.255.255 for a dotted quad (which means that it's really a host match), 255.255.255.0 for a dotted triple, 255.255.0.0 for a dotted pair, or 255.0.0.0 for a single number. An IPv6 network number must be written out fully; the netmask is ff:ff:ff:ff:ff:ff:ff:ff, so IPv6 "network" matches are really always host matches, and a network match requires a netmask length. .IP "\fBsrc net \fInet\fR" True if the IPv4/v6 source address of the packet has a network number of \fInet\fP. .IP "\fBnet \fInet\fR" True if either the IPv4/v6 source or destination address of the packet has a network number of \fInet\fP. .IP "\fBnet \fInet\fR \fBmask \fInetmask\fR" True if the IPv4 address matches \fInet\fR with the specific \fInetmask\fR. May be qualified with \fBsrc\fR or \fBdst\fR. Note that this syntax is not valid for IPv6 \fInet\fR. .IP "\fBnet \fInet\fR/\fIlen\fR" True if the IPv4/v6 address matches \fInet\fR with a netmask \fIlen\fR bits wide. May be qualified with \fBsrc\fR or \fBdst\fR. .IP "\fBdst port \fIport\fR" True if the packet is ip/tcp, ip/udp, ip6/tcp or ip6/udp and has a destination port value of \fIport\fP. The \fIport\fP can be a number or a name used in /etc/services (see .IR tcp (4P) and .IR udp (4P)). If a name is used, both the port number and protocol are checked. If a number or ambiguous name is used, only the port number is checked (e.g., \fBdst port 513\fR will print both tcp/login traffic and udp/who traffic, and \fBport domain\fR will print both tcp/domain and udp/domain traffic). .IP "\fBsrc port \fIport\fR" True if the packet has a source port value of \fIport\fP. .IP "\fBport \fIport\fR" True if either the source or destination port of the packet is \fIport\fP. .IP "\fBdst portrange \fIport1\fB-\fIport2\fR" True if the packet is ip/tcp, ip/udp, ip6/tcp or ip6/udp and has a destination port value between \fIport1\fP and \fIport2\fP. .I port1 and .I port2 are interpreted in the same fashion as the .I port parameter for .BR port . .IP "\fBsrc portrange \fIport1\fB-\fIport2\fR" True if the packet has a source port value between \fIport1\fP and \fIport2\fP. .IP "\fBportrange \fIport1\fB-\fIport2\fR" True if either the source or destination port of the packet is between \fIport1\fP and \fIport2\fP. .IP Any of the above port or port range expressions can be prepended with the keywords, \fBtcp\fP or \fBudp\fP, as in: .in +.5i .nf \fBtcp src port \fIport\fR .fi .in -.5i which matches only tcp packets whose source port is \fIport\fP. .IP "\fBless \fIlength\fR" True if the packet has a length less than or equal to \fIlength\fP. This is equivalent to: .in +.5i .nf \fBlen <= \fIlength\fP. .fi .in -.5i .IP "\fBgreater \fIlength\fR" True if the packet has a length greater than or equal to \fIlength\fP. This is equivalent to: .in +.5i .nf \fBlen >= \fIlength\fP. .fi .in -.5i .IP "\fBip proto \fIprotocol\fR" True if the packet is an IPv4 packet (see .IR ip (4P)) of protocol type \fIprotocol\fP. \fIProtocol\fP can be a number or one of the names \fBicmp\fP, \fBicmp6\fP, \fBigmp\fP, \fBigrp\fP, \fBpim\fP, \fBah\fP, \fBesp\fP, \fBvrrp\fP, \fBudp\fP, or \fBtcp\fP. Note that the identifiers \fBtcp\fP, \fBudp\fP, and \fBicmp\fP are also keywords and must be escaped via backslash (\\), which is \\\\ in the C-shell. Note that this primitive does not chase the protocol header chain. .IP "\fBip6 proto \fIprotocol\fR" True if the packet is an IPv6 packet of protocol type \fIprotocol\fP. Note that this primitive does not chase the protocol header chain. +.IP "\fBproto \fIprotocol\fR" +True if the packet is an IPv4 or IPv6 packet of protocol type +\fIprotocol\fP. Note that this primitive does not chase the protocol +header chain. +.IP "\fBtcp\fR, \fBudp\fR, \fBicmp\fR" +Abbreviations for: +.in +.5i +.nf +\fBproto \fIp\fR\fB +.fi +.in -.5i +where \fIp\fR is one of the above protocols. .IP "\fBip6 protochain \fIprotocol\fR" True if the packet is IPv6 packet, and contains protocol header with type \fIprotocol\fR in its protocol header chain. For example, .in +.5i .nf \fBip6 protochain 6\fR .fi .in -.5i matches any IPv6 packet with TCP protocol header in the protocol header chain. The packet may contain, for example, authentication header, routing header, or hop-by-hop option header, between IPv6 header and TCP header. The BPF code emitted by this primitive is complex and cannot be optimized by the BPF optimizer code, so this can be somewhat slow. .IP "\fBip protochain \fIprotocol\fR" Equivalent to \fBip6 protochain \fIprotocol\fR, but this is for IPv4. +.IP "\fBprotochain \fIprotocol\fR" +True if the packet is an IPv4 or IPv6 packet of protocol type +\fIprotocol\fP. Note that this primitive chases the protocol +header chain. .IP "\fBether broadcast\fR" True if the packet is an Ethernet broadcast packet. The \fIether\fP keyword is optional. .IP "\fBip broadcast\fR" True if the packet is an IPv4 broadcast packet. It checks for both the all-zeroes and all-ones broadcast conventions, and looks up the subnet mask on the interface on which the capture is being done. .IP If the subnet mask of the interface on which the capture is being done is not available, either because the interface on which capture is being done has no netmask or because the capture is being done on the Linux "any" interface, which can capture on more than one interface, this check will not work correctly. .IP "\fBether multicast\fR" True if the packet is an Ethernet multicast packet. The \fBether\fP keyword is optional. This is shorthand for `\fBether[0] & 1 != 0\fP'. .IP "\fBip multicast\fR" True if the packet is an IPv4 multicast packet. .IP "\fBip6 multicast\fR" True if the packet is an IPv6 multicast packet. .IP "\fBether proto \fIprotocol\fR" True if the packet is of ether type \fIprotocol\fR. \fIProtocol\fP can be a number or one of the names \fBip\fP, \fBip6\fP, \fBarp\fP, \fBrarp\fP, \fBatalk\fP, \fBaarp\fP, \fBdecnet\fP, \fBsca\fP, \fBlat\fP, \fBmopdl\fP, \fBmoprc\fP, \fBiso\fP, \fBstp\fP, \fBipx\fP, or \fBnetbeui\fP. Note these identifiers are also keywords and must be escaped via backslash (\\). .IP [In the case of FDDI (e.g., `\fBfddi protocol arp\fR'), Token Ring (e.g., `\fBtr protocol arp\fR'), and IEEE 802.11 wireless LANS (e.g., `\fBwlan protocol arp\fR'), for most of those protocols, the protocol identification comes from the 802.2 Logical Link Control (LLC) header, which is usually layered on top of the FDDI, Token Ring, or 802.11 header. .IP When filtering for most protocol identifiers on FDDI, Token Ring, or 802.11, the filter checks only the protocol ID field of an LLC header in so-called SNAP format with an Organizational Unit Identifier (OUI) of 0x000000, for encapsulated Ethernet; it doesn't check whether the packet is in SNAP format with an OUI of 0x000000. The exceptions are: .RS .TP \fBiso\fP the filter checks the DSAP (Destination Service Access Point) and SSAP (Source Service Access Point) fields of the LLC header; .TP \fBstp\fP and \fBnetbeui\fP the filter checks the DSAP of the LLC header; .TP \fBatalk\fP the filter checks for a SNAP-format packet with an OUI of 0x080007 and the AppleTalk etype. .RE .IP In the case of Ethernet, the filter checks the Ethernet type field for most of those protocols. The exceptions are: .RS .TP \fBiso\fP, \fBstp\fP, and \fBnetbeui\fP the filter checks for an 802.3 frame and then checks the LLC header as it does for FDDI, Token Ring, and 802.11; .TP \fBatalk\fP the filter checks both for the AppleTalk etype in an Ethernet frame and for a SNAP-format packet as it does for FDDI, Token Ring, and 802.11; .TP \fBaarp\fP the filter checks for the AppleTalk ARP etype in either an Ethernet frame or an 802.2 SNAP frame with an OUI of 0x000000; .TP \fBipx\fP the filter checks for the IPX etype in an Ethernet frame, the IPX DSAP in the LLC header, the 802.3-with-no-LLC-header encapsulation of IPX, and the IPX etype in a SNAP frame. .RE +.IP "\fBip\fR, \fBip6\fR, \fBarp\fR, \fBrarp\fR, \fBatalk\fR, \fBaarp\fR, \fBdecnet\fR, \fBiso\fR, \fBstp\fR, \fBipx\fR, \fBnetbeui\fP" +Abbreviations for: +.in +.5i +.nf +\fBether proto \fIp\fR +.fi +.in -.5i +where \fIp\fR is one of the above protocols. +.IP "\fBlat\fR, \fBmoprc\fR, \fBmopdl\fR" +Abbreviations for: +.in +.5i +.nf +\fBether proto \fIp\fR +.fi +.in -.5i +where \fIp\fR is one of the above protocols. +Note that not all applications using +.BR pcap (3PCAP) +currently know how to parse these protocols. .IP "\fBdecnet src \fIhost\fR" True if the DECNET source address is .IR host , which may be an address of the form ``10.123'', or a DECNET host name. [DECNET host name support is only available on ULTRIX systems that are configured to run DECNET.] .IP "\fBdecnet dst \fIhost\fR" True if the DECNET destination address is .IR host . .IP "\fBdecnet host \fIhost\fR" True if either the DECNET source or destination address is .IR host . .IP "\fBifname \fIinterface\fR" True if the packet was logged as coming from the specified interface (applies only to packets logged by OpenBSD's or FreeBSD's .BR pf (4)). .IP "\fBon \fIinterface\fR" Synonymous with the .B ifname modifier. .IP "\fBrnr \fInum\fR" True if the packet was logged as matching the specified PF rule number (applies only to packets logged by OpenBSD's or FreeBSD's .BR pf (4)). .IP "\fBrulenum \fInum\fR" Synonymous with the .B rnr modifier. .IP "\fBreason \fIcode\fR" True if the packet was logged with the specified PF reason code. The known codes are: .BR match , .BR bad-offset , .BR fragment , .BR short , .BR normalize , and .B memory (applies only to packets logged by OpenBSD's or FreeBSD's .BR pf (4)). .IP "\fBrset \fIname\fR" True if the packet was logged as matching the specified PF ruleset name of an anchored ruleset (applies only to packets logged by OpenBSD's or FreeBSD's .BR pf (4)). .IP "\fBruleset \fIname\fR" Synonomous with the .B rset modifier. .IP "\fBsrnr \fInum\fR" True if the packet was logged as matching the specified PF rule number of an anchored ruleset (applies only to packets logged by OpenBSD's or FreeBSD's .BR pf (4)). .IP "\fBsubrulenum \fInum\fR" Synonomous with the .B srnr modifier. .IP "\fBaction \fIact\fR" True if PF took the specified action when the packet was logged. Known actions are: .B pass and .B block and, with later versions of .BR pf (4)), .BR nat , .BR rdr , .B binat and .B scrub (applies only to packets logged by OpenBSD's or FreeBSD's .BR pf (4)). .IP "\fBwlan ra \fIehost\fR" True if the IEEE 802.11 RA is .IR ehost . The RA field is used in all frames except for management frames. .IP "\fBwlan ta \fIehost\fR" True if the IEEE 802.11 TA is .IR ehost . The TA field is used in all frames except for management frames and CTS (Clear To Send) and ACK (Acknowledgment) control frames. .IP "\fBwlan addr1 \fIehost\fR" True if the first IEEE 802.11 address is .IR ehost . .IP "\fBwlan addr2 \fIehost\fR" True if the second IEEE 802.11 address, if present, is .IR ehost . The second address field is used in all frames except for CTS (Clear To Send) and ACK (Acknowledgment) control frames. .IP "\fBwlan addr3 \fIehost\fR" True if the third IEEE 802.11 address, if present, is .IR ehost . The third address field is used in management and data frames, but not in control frames. .IP "\fBwlan addr4 \fIehost\fR" True if the fourth IEEE 802.11 address, if present, is .IR ehost . The fourth address field is only used for WDS (Wireless Distribution System) frames. -.IP "\fBip\fR, \fBip6\fR, \fBarp\fR, \fBrarp\fR, \fBatalk\fR, \fBaarp\fR, \fBdecnet\fR, \fBiso\fR, \fBstp\fR, \fBipx\fR, \fBnetbeui\fP" -Abbreviations for: -.in +.5i -.nf -\fBether proto \fIp\fR -.fi -.in -.5i -where \fIp\fR is one of the above protocols. -.IP "\fBlat\fR, \fBmoprc\fR, \fBmopdl\fR" -Abbreviations for: -.in +.5i -.nf -\fBether proto \fIp\fR -.fi -.in -.5i -where \fIp\fR is one of the above protocols. -Note that not all applications using -.BR pcap (3) -currently know how to parse these protocols. .IP "\fBtype \fIwlan_type\fR" True if the IEEE 802.11 frame type matches the specified \fIwlan_type\fR. Valid \fIwlan_type\fRs are: \fBmgt\fP, \fBctl\fP and \fBdata\fP. .IP "\fBtype \fIwlan_type \fBsubtype \fIwlan_subtype\fR" True if the IEEE 802.11 frame type matches the specified \fIwlan_type\fR and frame subtype matches the specified \fIwlan_subtype\fR. .IP If the specified \fIwlan_type\fR is \fBmgt\fP, then valid \fIwlan_subtype\fRs are: \fBassoc-req\fP, \fBassoc-resp\fP, \fBreassoc-req\fP, \fBreassoc-resp\fP, \fBprobe-req\fP, \fBprobe-resp\fP, \fBbeacon\fP, \fBatim\fP, \fBdisassoc\fP, \fBauth\fP and \fBdeauth\fP. .IP If the specified \fIwlan_type\fR is \fBctl\fP, then valid \fIwlan_subtype\fRs are: \fBps-poll\fP, \fBrts\fP, \fBcts\fP, \fBack\fP, \fBcf-end\fP and \fBcf-end-ack\fP. .IP If the specified \fIwlan_type\fR is \fBdata\fP, then valid \fIwlan_subtype\fRs are: \fBdata\fP, \fBdata-cf-ack\fP, \fBdata-cf-poll\fP, \fBdata-cf-ack-poll\fP, \fBnull\fP, \fBcf-ack\fP, \fBcf-poll\fP, \fBcf-ack-poll\fP, \fBqos-data\fP, \fBqos-data-cf-ack\fP, \fBqos-data-cf-poll\fP, \fBqos-data-cf-ack-poll\fP, \fBqos\fP, \fBqos-cf-poll\fP and \fBqos-cf-ack-poll\fP. .IP "\fBsubtype \fIwlan_subtype\fR" True if the IEEE 802.11 frame subtype matches the specified \fIwlan_subtype\fR and frame has the type to which the specified \fIwlan_subtype\fR belongs. .IP "\fBdir \fIdir\fR" True if the IEEE 802.11 frame direction matches the specified .IR dir . Valid directions are: .BR nods , .BR tods , .BR fromds , .BR dstods , or a numeric value. .IP "\fBvlan \fI[vlan_id]\fR" True if the packet is an IEEE 802.1Q VLAN packet. If \fI[vlan_id]\fR is specified, only true if the packet has the specified \fIvlan_id\fR. Note that the first \fBvlan\fR keyword encountered in \fIexpression\fR changes the decoding offsets for the remainder of \fIexpression\fR on the assumption that the packet is a VLAN packet. The \fBvlan \fI[vlan_id]\fR expression may be used more than once, to filter on VLAN hierarchies. Each use of that expression increments the filter offsets by 4. .IP For example: .in +.5i .nf \fBvlan 100 && vlan 200\fR .fi .in -.5i filters on VLAN 200 encapsulated within VLAN 100, and .in +.5i .nf \fBvlan && vlan 300 && ip\fR .fi .in -.5i filters IPv4 protocols encapsulated in VLAN 300 encapsulated within any higher order VLAN. .IP "\fBmpls \fI[label_num]\fR" True if the packet is an MPLS packet. If \fI[label_num]\fR is specified, only true is the packet has the specified \fIlabel_num\fR. Note that the first \fBmpls\fR keyword encountered in \fIexpression\fR changes the decoding offsets for the remainder of \fIexpression\fR on the assumption that the packet is a MPLS-encapsulated IP packet. The \fBmpls \fI[label_num]\fR expression may be used more than once, to filter on MPLS hierarchies. Each use of that expression increments the filter offsets by 4. .IP For example: .in +.5i .nf \fBmpls 100000 && mpls 1024\fR .fi .in -.5i filters packets with an outer label of 100000 and an inner label of 1024, and .in +.5i .nf \fBmpls && mpls 1024 && host 192.9.200.1\fR .fi .in -.5i filters packets to or from 192.9.200.1 with an inner label of 1024 and any outer label. .IP \fBpppoed\fP True if the packet is a PPP-over-Ethernet Discovery packet (Ethernet type 0x8863). .IP \fBpppoes\fP True if the packet is a PPP-over-Ethernet Session packet (Ethernet type 0x8864). Note that the first \fBpppoes\fR keyword encountered in \fIexpression\fR changes the decoding offsets for the remainder of \fIexpression\fR on the assumption that the packet is a PPPoE session packet. .IP For example: .in +.5i .nf \fBpppoes && ip\fR .fi .in -.5i filters IPv4 protocols encapsulated in PPPoE. -.IP "\fBtcp\fR, \fBudp\fR, \fBicmp\fR" -Abbreviations for: -.in +.5i -.nf -\fBip proto \fIp\fR\fB or ip6 proto \fIp\fR -.fi -.in -.5i -where \fIp\fR is one of the above protocols. .IP "\fBiso proto \fIprotocol\fR" True if the packet is an OSI packet of protocol type \fIprotocol\fP. \fIProtocol\fP can be a number or one of the names \fBclnp\fP, \fBesis\fP, or \fBisis\fP. .IP "\fBclnp\fR, \fBesis\fR, \fBisis\fR" Abbreviations for: .in +.5i .nf \fBiso proto \fIp\fR .fi .in -.5i where \fIp\fR is one of the above protocols. .IP "\fBl1\fR, \fBl2\fR, \fBiih\fR, \fBlsp\fR, \fBsnp\fR, \fBcsnp\fR, \fBpsnp\fR" Abbreviations for IS-IS PDU types. -.IP "\fBvpi\fP \fIn\fR +.IP "\fBvpi\fP \fIn\fR" True if the packet is an ATM packet, for SunATM on Solaris, with a virtual path identifier of .IR n . -.IP "\fBvci\fP \fIn\fR +.IP "\fBvci\fP \fIn\fR" True if the packet is an ATM packet, for SunATM on Solaris, with a virtual channel identifier of .IR n . .IP \fBlane\fP True if the packet is an ATM packet, for SunATM on Solaris, and is an ATM LANE packet. Note that the first \fBlane\fR keyword encountered in \fIexpression\fR changes the tests done in the remainder of \fIexpression\fR on the assumption that the packet is either a LANE emulated Ethernet packet or a LANE LE Control packet. If \fBlane\fR isn't specified, the tests are done under the assumption that the packet is an LLC-encapsulated packet. .IP \fBllc\fP True if the packet is an ATM packet, for SunATM on Solaris, and is an LLC-encapsulated packet. .IP \fBoamf4s\fP True if the packet is an ATM packet, for SunATM on Solaris, and is a segment OAM F4 flow cell (VPI=0 & VCI=3). .IP \fBoamf4e\fP True if the packet is an ATM packet, for SunATM on Solaris, and is an end-to-end OAM F4 flow cell (VPI=0 & VCI=4). .IP \fBoamf4\fP True if the packet is an ATM packet, for SunATM on Solaris, and is a segment or end-to-end OAM F4 flow cell (VPI=0 & (VCI=3 | VCI=4)). .IP \fBoam\fP True if the packet is an ATM packet, for SunATM on Solaris, and is a segment or end-to-end OAM F4 flow cell (VPI=0 & (VCI=3 | VCI=4)). .IP \fBmetac\fP True if the packet is an ATM packet, for SunATM on Solaris, and is on a meta signaling circuit (VPI=0 & VCI=1). .IP \fBbcc\fP True if the packet is an ATM packet, for SunATM on Solaris, and is on a broadcast signaling circuit (VPI=0 & VCI=2). .IP \fBsc\fP True if the packet is an ATM packet, for SunATM on Solaris, and is on a signaling circuit (VPI=0 & VCI=5). .IP \fBilmic\fP True if the packet is an ATM packet, for SunATM on Solaris, and is on an ILMI circuit (VPI=0 & VCI=16). .IP \fBconnectmsg\fP True if the packet is an ATM packet, for SunATM on Solaris, and is on a signaling circuit and is a Q.2931 Setup, Call Proceeding, Connect, Connect Ack, Release, or Release Done message. .IP \fBmetaconnect\fP True if the packet is an ATM packet, for SunATM on Solaris, and is on a meta signaling circuit and is a Q.2931 Setup, Call Proceeding, Connect, Release, or Release Done message. .IP "\fIexpr relop expr\fR" True if the relation holds, where \fIrelop\fR is one of >, <, >=, <=, =, !=, and \fIexpr\fR is an arithmetic expression composed of integer constants (expressed in standard C syntax), the normal binary operators [+, -, *, /, &, |, <<, >>], a length operator, and special packet data accessors. Note that all comparisons are unsigned, so that, for example, 0x80000000 and 0xffffffff are > 0. To access data inside the packet, use the following syntax: .in +.5i .nf \fIproto\fB [ \fIexpr\fB : \fIsize\fB ]\fR .fi .in -.5i \fIProto\fR is one of \fBether, fddi, tr, wlan, ppp, slip, link, ip, arp, rarp, tcp, udp, icmp, ip6\fR or \fBradio\fR, and indicates the protocol layer for the index operation. (\fBether, fddi, wlan, tr, ppp, slip\fR and \fBlink\fR all refer to the link layer. \fBradio\fR refers to the "radio header" added to some 802.11 captures.) Note that \fItcp, udp\fR and other upper-layer protocol types only apply to IPv4, not IPv6 (this will be fixed in the future). The byte offset, relative to the indicated protocol layer, is given by \fIexpr\fR. \fISize\fR is optional and indicates the number of bytes in the field of interest; it can be either one, two, or four, and defaults to one. The length operator, indicated by the keyword \fBlen\fP, gives the length of the packet. For example, `\fBether[0] & 1 != 0\fP' catches all multicast traffic. The expression `\fBip[0] & 0xf != 5\fP' catches all IPv4 packets with options. The expression `\fBip[6:2] & 0x1fff = 0\fP' catches only unfragmented IPv4 datagrams and frag zero of fragmented IPv4 datagrams. This check is implicitly applied to the \fBtcp\fP and \fBudp\fP index operations. For instance, \fBtcp[0]\fP always means the first byte of the TCP \fIheader\fP, and never means the first byte of an intervening fragment. Some offsets and field values may be expressed as names rather than as numeric values. The following protocol header field offsets are available: \fBicmptype\fP (ICMP type field), \fBicmpcode\fP (ICMP code field), and \fBtcpflags\fP (TCP flags field). The following ICMP type field values are available: \fBicmp-echoreply\fP, \fBicmp-unreach\fP, \fBicmp-sourcequench\fP, \fBicmp-redirect\fP, \fBicmp-echo\fP, \fBicmp-routeradvert\fP, \fBicmp-routersolicit\fP, \fBicmp-timxceed\fP, \fBicmp-paramprob\fP, \fBicmp-tstamp\fP, \fBicmp-tstampreply\fP, \fBicmp-ireq\fP, \fBicmp-ireqreply\fP, \fBicmp-maskreq\fP, \fBicmp-maskreply\fP. The following TCP flags field values are available: \fBtcp-fin\fP, \fBtcp-syn\fP, \fBtcp-rst\fP, \fBtcp-push\fP, \fBtcp-ack\fP, \fBtcp-urg\fP. .LP Primitives may be combined using: .IP A parenthesized group of primitives and operators (parentheses are special to the Shell and must be escaped). .IP Negation (`\fB!\fP' or `\fBnot\fP'). .IP Concatenation (`\fB&&\fP' or `\fBand\fP'). .IP Alternation (`\fB||\fP' or `\fBor\fP'). .LP Negation has highest precedence. Alternation and concatenation have equal precedence and associate left to right. Note that explicit \fBand\fR tokens, not juxtaposition, are now required for concatenation. .LP If an identifier is given without a keyword, the most recent keyword is assumed. For example, .in +.5i .nf \fBnot host vs and ace\fR .fi .in -.5i is short for .in +.5i .nf \fBnot host vs and host ace\fR .fi .in -.5i which should not be confused with .in +.5i .nf \fBnot ( host vs or ace )\fR .fi .in -.5i .SH EXAMPLES .LP To select all packets arriving at or departing from \fIsundown\fP: .RS .nf \fBhost sundown\fP .fi .RE .LP To select traffic between \fIhelios\fR and either \fIhot\fR or \fIace\fR: .RS .nf \fBhost helios and \\( hot or ace \\)\fP .fi .RE .LP To select all IP packets between \fIace\fR and any host except \fIhelios\fR: .RS .nf \fBip host ace and not helios\fP .fi .RE .LP To select all traffic between local hosts and hosts at Berkeley: .RS .nf .B net ucb-ether .fi .RE .LP To select all ftp traffic through internet gateway \fIsnup\fP: .RS .nf .B gateway snup and (port ftp or ftp-data) .fi .RE .LP To select traffic neither sourced from nor destined for local hosts (if you gateway to one other net, this stuff should never make it onto your local net). .RS .nf .B ip and not net \fIlocalnet\fP .fi .RE .LP To select the start and end packets (the SYN and FIN packets) of each TCP conversation that involves a non-local host. .RS .nf .B tcp[tcpflags] & (tcp-syn|tcp-fin) != 0 and not src and dst net \fIlocalnet\fP .fi .RE .LP To select all IPv4 HTTP packets to and from port 80, i.e. print only packets that contain data, not, for example, SYN and FIN packets and ACK-only packets. (IPv6 is left as an exercise for the reader.) .RS .nf .B tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0) .fi .RE .LP To select IP packets longer than 576 bytes sent through gateway \fIsnup\fP: .RS .nf .B gateway snup and ip[2:2] > 576 .fi .RE .LP To select IP broadcast or multicast packets that were .I not sent via Ethernet broadcast or multicast: .RS .nf .B ether[0] & 1 = 0 and ip[16] >= 224 .fi .RE .LP To select all ICMP packets that are not echo requests/replies (i.e., not ping packets): .RS .nf .B icmp[icmptype] != icmp-echo and icmp[icmptype] != icmp-echoreply .fi .RE .SH "SEE ALSO" pcap(3PCAP) -.SH AUTHORS -The original authors are: -.LP -Van Jacobson, -Craig Leres and -Steven McCanne, all of the -Lawrence Berkeley National Laboratory, University of California, Berkeley, CA. -.LP -It is currently being maintained by tcpdump.org. -.LP -The current version of libpcap is available via http: -.LP -.RS -.I http://www.tcpdump.org/ -.RE -.LP -The original distribution is available via anonymous ftp: -.LP -.RS -.I ftp://ftp.ee.lbl.gov/tcpdump.tar.Z -.RE .SH BUGS Please send problems, bugs, questions, desirable enhancements, etc. to: .LP .RS tcpdump-workers@lists.tcpdump.org .RE .LP Filter expressions on fields other than those in Token Ring headers will not correctly handle source-routed Token Ring packets. .LP Filter expressions on fields other than those in 802.11 headers will not correctly handle 802.11 data packets with both To DS and From DS set. .LP .BR "ip6 proto" should chase header chain, but at this moment it does not. .BR "ip6 protochain" is supplied for this behavior. .LP Arithmetic expression against transport layer headers, like \fBtcp[0]\fP, does not work against IPv6 packets. It only looks at IPv4 packets. Index: stable/9/contrib/libpcap/pcap-filter.manmisc.in =================================================================== --- stable/9/contrib/libpcap/pcap-filter.manmisc.in (revision 252280) +++ stable/9/contrib/libpcap/pcap-filter.manmisc.in (revision 252281) @@ -1,962 +1,952 @@ .\" @(#) $Header: /tcpdump/master/libpcap/pcap-filter.manmisc.in,v 1.1 2008-10-21 07:33:01 guy Exp $ (LBL) .\" .\" Copyright (c) 1987, 1988, 1989, 1990, 1991, 1992, 1994, 1995, 1996, 1997 .\" The Regents of the University of California. All rights reserved. .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that: (1) source code distributions .\" retain the above copyright notice and this paragraph in its entirety, (2) .\" distributions including binary code include the above copyright notice and .\" this paragraph in its entirety in the documentation or other materials .\" provided with the distribution, and (3) all advertising materials mentioning .\" features or use of this software display the following acknowledgement: .\" ``This product includes software developed by the University of California, .\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of .\" the University nor the names of its contributors may be used to endorse .\" or promote products derived from this software without specific prior .\" written permission. .\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. .\" .TH PCAP-FILTER @MAN_MISC_INFO@ "6 January 2008" .SH NAME pcap-filter \- packet filter syntax .br .ad .SH DESCRIPTION .LP .B pcap_compile() is used to compile a string into a filter program. The resulting filter program can then be applied to some stream of packets to determine which packets will be supplied to .BR pcap_loop() , .BR pcap_dispatch() , .BR pcap_next() , or .BR pcap_next_ex() . .LP The \fIfilter expression\fP consists of one or more .IR primitives . Primitives usually consist of an .I id (name or number) preceded by one or more qualifiers. There are three different kinds of qualifier: .IP \fItype\fP +.I type qualifiers say what kind of thing the id name or number refers to. Possible types are .BR host , .B net , .B port and .BR portrange . E.g., `host foo', `net 128.3', `port 20', `portrange 6000-6008'. If there is no type qualifier, .B host is assumed. .IP \fIdir\fP +.I dir qualifiers specify a particular transfer direction to and/or from .IR id . Possible directions are .BR src , .BR dst , .BR "src or dst" , .BR "src and dst" , .BR ra , .BR ta , .BR addr1 , .BR addr2 , .BR addr3 , and .BR addr4 . E.g., `src foo', `dst net 128.3', `src or dst port ftp-data'. If there is no dir qualifier, .B "src or dst" is assumed. The .BR ra , .BR ta , .BR addr1 , .BR addr2 , .BR addr3 , and .B addr4 qualifiers are only valid for IEEE 802.11 Wireless LAN link layers. For some link layers, such as SLIP and the ``cooked'' Linux capture mode used for the ``any'' device and for some other device types, the .B inbound and .B outbound qualifiers can be used to specify a desired direction. .IP \fIproto\fP +.I proto qualifiers restrict the match to a particular protocol. Possible protos are: .BR ether , .BR fddi , .BR tr , .BR wlan , .BR ip , .BR ip6 , .BR arp , .BR rarp , .BR decnet , .B tcp and .BR udp . E.g., `ether src foo', `arp net 128.3', `tcp port 21', `udp portrange 7000-7009', `wlan addr2 0:2:3:4:5:6'. If there is no proto qualifier, all protocols consistent with the type are assumed. E.g., `src foo' means `(ip or arp or rarp) src foo' (except the latter is not legal syntax), `net bar' means `(ip or arp or rarp) net bar' and `port 53' means `(tcp or udp) port 53'. .LP [`fddi' is actually an alias for `ether'; the parser treats them identically as meaning ``the data link level used on the specified network interface.'' FDDI headers contain Ethernet-like source and destination addresses, and often contain Ethernet-like packet types, so you can filter on these FDDI fields just as with the analogous Ethernet fields. FDDI headers also contain other fields, but you cannot name them explicitly in a filter expression. .LP Similarly, `tr' and `wlan' are aliases for `ether'; the previous paragraph's statements about FDDI headers also apply to Token Ring and 802.11 wireless LAN headers. For 802.11 headers, the destination address is the DA field and the source address is the SA field; the BSSID, RA, and TA fields aren't tested.] .LP In addition to the above, there are some special `primitive' keywords that don't follow the pattern: .BR gateway , .BR broadcast , .BR less , .B greater and arithmetic expressions. All of these are described below. .LP More complex filter expressions are built up by using the words .BR and , .B or and .B not to combine primitives. E.g., `host foo and not port ftp and not port ftp-data'. To save typing, identical qualifier lists can be omitted. E.g., `tcp dst port ftp or ftp-data or domain' is exactly the same as `tcp dst port ftp or tcp dst port ftp-data or tcp dst port domain'. .LP Allowable primitives are: .IP "\fBdst host \fIhost\fR" True if the IPv4/v6 destination field of the packet is \fIhost\fP, which may be either an address or a name. .IP "\fBsrc host \fIhost\fR" True if the IPv4/v6 source field of the packet is \fIhost\fP. -.IP "\fBhost \fIhost\fP +.IP "\fBhost \fIhost\fP" True if either the IPv4/v6 source or destination of the packet is \fIhost\fP. .IP Any of the above host expressions can be prepended with the keywords, \fBip\fP, \fBarp\fP, \fBrarp\fP, or \fBip6\fP as in: .in +.5i .nf \fBip host \fIhost\fR .fi .in -.5i which is equivalent to: .in +.5i .nf \fBether proto \fI\\ip\fB and host \fIhost\fR .fi .in -.5i If \fIhost\fR is a name with multiple IP addresses, each address will be checked for a match. -.IP "\fBether dst \fIehost\fP +.IP "\fBether dst \fIehost\fP" True if the Ethernet destination address is \fIehost\fP. \fIEhost\fP may be either a name from /etc/ethers or a number (see .IR ethers (3N) for numeric format). -.IP "\fBether src \fIehost\fP +.IP "\fBether src \fIehost\fP" True if the Ethernet source address is \fIehost\fP. -.IP "\fBether host \fIehost\fP +.IP "\fBether host \fIehost\fP" True if either the Ethernet source or destination address is \fIehost\fP. -.IP "\fBgateway\fP \fIhost\fP +.IP "\fBgateway\fP \fIhost\fP" True if the packet used \fIhost\fP as a gateway. I.e., the Ethernet source or destination address was \fIhost\fP but neither the IP source nor the IP destination was \fIhost\fP. \fIHost\fP must be a name and must be found both by the machine's host-name-to-IP-address resolution mechanisms (host name file, DNS, NIS, etc.) and by the machine's host-name-to-Ethernet-address resolution mechanism (/etc/ethers, etc.). (An equivalent expression is .in +.5i .nf \fBether host \fIehost \fBand not host \fIhost\fR .fi .in -.5i which can be used with either names or numbers for \fIhost / ehost\fP.) This syntax does not work in IPv6-enabled configuration at this moment. .IP "\fBdst net \fInet\fR" True if the IPv4/v6 destination address of the packet has a network number of \fInet\fP. \fINet\fP may be either a name from the networks database (/etc/networks, etc.) or a network number. An IPv4 network number can be written as a dotted quad (e.g., 192.168.1.0), dotted triple (e.g., 192.168.1), dotted pair (e.g, 172.16), or single number (e.g., 10); the netmask is 255.255.255.255 for a dotted quad (which means that it's really a host match), 255.255.255.0 for a dotted triple, 255.255.0.0 for a dotted pair, or 255.0.0.0 for a single number. An IPv6 network number must be written out fully; the netmask is ff:ff:ff:ff:ff:ff:ff:ff, so IPv6 "network" matches are really always host matches, and a network match requires a netmask length. .IP "\fBsrc net \fInet\fR" True if the IPv4/v6 source address of the packet has a network number of \fInet\fP. .IP "\fBnet \fInet\fR" True if either the IPv4/v6 source or destination address of the packet has a network number of \fInet\fP. .IP "\fBnet \fInet\fR \fBmask \fInetmask\fR" True if the IPv4 address matches \fInet\fR with the specific \fInetmask\fR. May be qualified with \fBsrc\fR or \fBdst\fR. Note that this syntax is not valid for IPv6 \fInet\fR. .IP "\fBnet \fInet\fR/\fIlen\fR" True if the IPv4/v6 address matches \fInet\fR with a netmask \fIlen\fR bits wide. May be qualified with \fBsrc\fR or \fBdst\fR. .IP "\fBdst port \fIport\fR" True if the packet is ip/tcp, ip/udp, ip6/tcp or ip6/udp and has a destination port value of \fIport\fP. The \fIport\fP can be a number or a name used in /etc/services (see .IR tcp (4P) and .IR udp (4P)). If a name is used, both the port number and protocol are checked. If a number or ambiguous name is used, only the port number is checked (e.g., \fBdst port 513\fR will print both tcp/login traffic and udp/who traffic, and \fBport domain\fR will print both tcp/domain and udp/domain traffic). .IP "\fBsrc port \fIport\fR" True if the packet has a source port value of \fIport\fP. .IP "\fBport \fIport\fR" True if either the source or destination port of the packet is \fIport\fP. .IP "\fBdst portrange \fIport1\fB-\fIport2\fR" True if the packet is ip/tcp, ip/udp, ip6/tcp or ip6/udp and has a destination port value between \fIport1\fP and \fIport2\fP. .I port1 and .I port2 are interpreted in the same fashion as the .I port parameter for .BR port . .IP "\fBsrc portrange \fIport1\fB-\fIport2\fR" True if the packet has a source port value between \fIport1\fP and \fIport2\fP. .IP "\fBportrange \fIport1\fB-\fIport2\fR" True if either the source or destination port of the packet is between \fIport1\fP and \fIport2\fP. .IP Any of the above port or port range expressions can be prepended with the keywords, \fBtcp\fP or \fBudp\fP, as in: .in +.5i .nf \fBtcp src port \fIport\fR .fi .in -.5i which matches only tcp packets whose source port is \fIport\fP. .IP "\fBless \fIlength\fR" True if the packet has a length less than or equal to \fIlength\fP. This is equivalent to: .in +.5i .nf \fBlen <= \fIlength\fP. .fi .in -.5i .IP "\fBgreater \fIlength\fR" True if the packet has a length greater than or equal to \fIlength\fP. This is equivalent to: .in +.5i .nf \fBlen >= \fIlength\fP. .fi .in -.5i .IP "\fBip proto \fIprotocol\fR" True if the packet is an IPv4 packet (see .IR ip (4P)) of protocol type \fIprotocol\fP. \fIProtocol\fP can be a number or one of the names \fBicmp\fP, \fBicmp6\fP, \fBigmp\fP, \fBigrp\fP, \fBpim\fP, \fBah\fP, \fBesp\fP, \fBvrrp\fP, \fBudp\fP, or \fBtcp\fP. Note that the identifiers \fBtcp\fP, \fBudp\fP, and \fBicmp\fP are also keywords and must be escaped via backslash (\\), which is \\\\ in the C-shell. Note that this primitive does not chase the protocol header chain. .IP "\fBip6 proto \fIprotocol\fR" True if the packet is an IPv6 packet of protocol type \fIprotocol\fP. Note that this primitive does not chase the protocol header chain. +.IP "\fBproto \fIprotocol\fR" +True if the packet is an IPv4 or IPv6 packet of protocol type +\fIprotocol\fP. Note that this primitive does not chase the protocol +header chain. +.IP "\fBtcp\fR, \fBudp\fR, \fBicmp\fR" +Abbreviations for: +.in +.5i +.nf +\fBproto \fIp\fR\fB +.fi +.in -.5i +where \fIp\fR is one of the above protocols. .IP "\fBip6 protochain \fIprotocol\fR" True if the packet is IPv6 packet, and contains protocol header with type \fIprotocol\fR in its protocol header chain. For example, .in +.5i .nf \fBip6 protochain 6\fR .fi .in -.5i matches any IPv6 packet with TCP protocol header in the protocol header chain. The packet may contain, for example, authentication header, routing header, or hop-by-hop option header, between IPv6 header and TCP header. The BPF code emitted by this primitive is complex and cannot be optimized by the BPF optimizer code, so this can be somewhat slow. .IP "\fBip protochain \fIprotocol\fR" Equivalent to \fBip6 protochain \fIprotocol\fR, but this is for IPv4. +.IP "\fBprotochain \fIprotocol\fR" +True if the packet is an IPv4 or IPv6 packet of protocol type +\fIprotocol\fP. Note that this primitive chases the protocol +header chain. .IP "\fBether broadcast\fR" True if the packet is an Ethernet broadcast packet. The \fIether\fP keyword is optional. .IP "\fBip broadcast\fR" True if the packet is an IPv4 broadcast packet. It checks for both the all-zeroes and all-ones broadcast conventions, and looks up the subnet mask on the interface on which the capture is being done. .IP If the subnet mask of the interface on which the capture is being done is not available, either because the interface on which capture is being done has no netmask or because the capture is being done on the Linux "any" interface, which can capture on more than one interface, this check will not work correctly. .IP "\fBether multicast\fR" True if the packet is an Ethernet multicast packet. The \fBether\fP keyword is optional. This is shorthand for `\fBether[0] & 1 != 0\fP'. .IP "\fBip multicast\fR" True if the packet is an IPv4 multicast packet. .IP "\fBip6 multicast\fR" True if the packet is an IPv6 multicast packet. .IP "\fBether proto \fIprotocol\fR" True if the packet is of ether type \fIprotocol\fR. \fIProtocol\fP can be a number or one of the names \fBip\fP, \fBip6\fP, \fBarp\fP, \fBrarp\fP, \fBatalk\fP, \fBaarp\fP, \fBdecnet\fP, \fBsca\fP, \fBlat\fP, \fBmopdl\fP, \fBmoprc\fP, \fBiso\fP, \fBstp\fP, \fBipx\fP, or \fBnetbeui\fP. Note these identifiers are also keywords and must be escaped via backslash (\\). .IP [In the case of FDDI (e.g., `\fBfddi protocol arp\fR'), Token Ring (e.g., `\fBtr protocol arp\fR'), and IEEE 802.11 wireless LANS (e.g., `\fBwlan protocol arp\fR'), for most of those protocols, the protocol identification comes from the 802.2 Logical Link Control (LLC) header, which is usually layered on top of the FDDI, Token Ring, or 802.11 header. .IP When filtering for most protocol identifiers on FDDI, Token Ring, or 802.11, the filter checks only the protocol ID field of an LLC header in so-called SNAP format with an Organizational Unit Identifier (OUI) of 0x000000, for encapsulated Ethernet; it doesn't check whether the packet is in SNAP format with an OUI of 0x000000. The exceptions are: .RS .TP \fBiso\fP the filter checks the DSAP (Destination Service Access Point) and SSAP (Source Service Access Point) fields of the LLC header; .TP \fBstp\fP and \fBnetbeui\fP the filter checks the DSAP of the LLC header; .TP \fBatalk\fP the filter checks for a SNAP-format packet with an OUI of 0x080007 and the AppleTalk etype. .RE .IP In the case of Ethernet, the filter checks the Ethernet type field for most of those protocols. The exceptions are: .RS .TP \fBiso\fP, \fBstp\fP, and \fBnetbeui\fP the filter checks for an 802.3 frame and then checks the LLC header as it does for FDDI, Token Ring, and 802.11; .TP \fBatalk\fP the filter checks both for the AppleTalk etype in an Ethernet frame and for a SNAP-format packet as it does for FDDI, Token Ring, and 802.11; .TP \fBaarp\fP the filter checks for the AppleTalk ARP etype in either an Ethernet frame or an 802.2 SNAP frame with an OUI of 0x000000; .TP \fBipx\fP the filter checks for the IPX etype in an Ethernet frame, the IPX DSAP in the LLC header, the 802.3-with-no-LLC-header encapsulation of IPX, and the IPX etype in a SNAP frame. .RE +.IP "\fBip\fR, \fBip6\fR, \fBarp\fR, \fBrarp\fR, \fBatalk\fR, \fBaarp\fR, \fBdecnet\fR, \fBiso\fR, \fBstp\fR, \fBipx\fR, \fBnetbeui\fP" +Abbreviations for: +.in +.5i +.nf +\fBether proto \fIp\fR +.fi +.in -.5i +where \fIp\fR is one of the above protocols. +.IP "\fBlat\fR, \fBmoprc\fR, \fBmopdl\fR" +Abbreviations for: +.in +.5i +.nf +\fBether proto \fIp\fR +.fi +.in -.5i +where \fIp\fR is one of the above protocols. +Note that not all applications using +.BR pcap (3PCAP) +currently know how to parse these protocols. .IP "\fBdecnet src \fIhost\fR" True if the DECNET source address is .IR host , which may be an address of the form ``10.123'', or a DECNET host name. [DECNET host name support is only available on ULTRIX systems that are configured to run DECNET.] .IP "\fBdecnet dst \fIhost\fR" True if the DECNET destination address is .IR host . .IP "\fBdecnet host \fIhost\fR" True if either the DECNET source or destination address is .IR host . .IP "\fBifname \fIinterface\fR" True if the packet was logged as coming from the specified interface (applies only to packets logged by OpenBSD's or FreeBSD's .BR pf (4)). .IP "\fBon \fIinterface\fR" Synonymous with the .B ifname modifier. .IP "\fBrnr \fInum\fR" True if the packet was logged as matching the specified PF rule number (applies only to packets logged by OpenBSD's or FreeBSD's .BR pf (4)). .IP "\fBrulenum \fInum\fR" Synonymous with the .B rnr modifier. .IP "\fBreason \fIcode\fR" True if the packet was logged with the specified PF reason code. The known codes are: .BR match , .BR bad-offset , .BR fragment , .BR short , .BR normalize , and .B memory (applies only to packets logged by OpenBSD's or FreeBSD's .BR pf (4)). .IP "\fBrset \fIname\fR" True if the packet was logged as matching the specified PF ruleset name of an anchored ruleset (applies only to packets logged by OpenBSD's or FreeBSD's .BR pf (4)). .IP "\fBruleset \fIname\fR" Synonomous with the .B rset modifier. .IP "\fBsrnr \fInum\fR" True if the packet was logged as matching the specified PF rule number of an anchored ruleset (applies only to packets logged by OpenBSD's or FreeBSD's .BR pf (4)). .IP "\fBsubrulenum \fInum\fR" Synonomous with the .B srnr modifier. .IP "\fBaction \fIact\fR" True if PF took the specified action when the packet was logged. Known actions are: .B pass and .B block and, with later versions of .BR pf (4)), .BR nat , .BR rdr , .B binat and .B scrub (applies only to packets logged by OpenBSD's or FreeBSD's .BR pf (4)). .IP "\fBwlan ra \fIehost\fR" True if the IEEE 802.11 RA is .IR ehost . The RA field is used in all frames except for management frames. .IP "\fBwlan ta \fIehost\fR" True if the IEEE 802.11 TA is .IR ehost . The TA field is used in all frames except for management frames and CTS (Clear To Send) and ACK (Acknowledgment) control frames. .IP "\fBwlan addr1 \fIehost\fR" True if the first IEEE 802.11 address is .IR ehost . .IP "\fBwlan addr2 \fIehost\fR" True if the second IEEE 802.11 address, if present, is .IR ehost . The second address field is used in all frames except for CTS (Clear To Send) and ACK (Acknowledgment) control frames. .IP "\fBwlan addr3 \fIehost\fR" True if the third IEEE 802.11 address, if present, is .IR ehost . The third address field is used in management and data frames, but not in control frames. .IP "\fBwlan addr4 \fIehost\fR" True if the fourth IEEE 802.11 address, if present, is .IR ehost . The fourth address field is only used for WDS (Wireless Distribution System) frames. -.IP "\fBip\fR, \fBip6\fR, \fBarp\fR, \fBrarp\fR, \fBatalk\fR, \fBaarp\fR, \fBdecnet\fR, \fBiso\fR, \fBstp\fR, \fBipx\fR, \fBnetbeui\fP" -Abbreviations for: -.in +.5i -.nf -\fBether proto \fIp\fR -.fi -.in -.5i -where \fIp\fR is one of the above protocols. -.IP "\fBlat\fR, \fBmoprc\fR, \fBmopdl\fR" -Abbreviations for: -.in +.5i -.nf -\fBether proto \fIp\fR -.fi -.in -.5i -where \fIp\fR is one of the above protocols. -Note that not all applications using -.BR pcap (3) -currently know how to parse these protocols. .IP "\fBtype \fIwlan_type\fR" True if the IEEE 802.11 frame type matches the specified \fIwlan_type\fR. Valid \fIwlan_type\fRs are: \fBmgt\fP, \fBctl\fP and \fBdata\fP. .IP "\fBtype \fIwlan_type \fBsubtype \fIwlan_subtype\fR" True if the IEEE 802.11 frame type matches the specified \fIwlan_type\fR and frame subtype matches the specified \fIwlan_subtype\fR. .IP If the specified \fIwlan_type\fR is \fBmgt\fP, then valid \fIwlan_subtype\fRs are: \fBassoc-req\fP, \fBassoc-resp\fP, \fBreassoc-req\fP, \fBreassoc-resp\fP, \fBprobe-req\fP, \fBprobe-resp\fP, \fBbeacon\fP, \fBatim\fP, \fBdisassoc\fP, \fBauth\fP and \fBdeauth\fP. .IP If the specified \fIwlan_type\fR is \fBctl\fP, then valid \fIwlan_subtype\fRs are: \fBps-poll\fP, \fBrts\fP, \fBcts\fP, \fBack\fP, \fBcf-end\fP and \fBcf-end-ack\fP. .IP If the specified \fIwlan_type\fR is \fBdata\fP, then valid \fIwlan_subtype\fRs are: \fBdata\fP, \fBdata-cf-ack\fP, \fBdata-cf-poll\fP, \fBdata-cf-ack-poll\fP, \fBnull\fP, \fBcf-ack\fP, \fBcf-poll\fP, \fBcf-ack-poll\fP, \fBqos-data\fP, \fBqos-data-cf-ack\fP, \fBqos-data-cf-poll\fP, \fBqos-data-cf-ack-poll\fP, \fBqos\fP, \fBqos-cf-poll\fP and \fBqos-cf-ack-poll\fP. .IP "\fBsubtype \fIwlan_subtype\fR" True if the IEEE 802.11 frame subtype matches the specified \fIwlan_subtype\fR and frame has the type to which the specified \fIwlan_subtype\fR belongs. .IP "\fBdir \fIdir\fR" True if the IEEE 802.11 frame direction matches the specified .IR dir . Valid directions are: .BR nods , .BR tods , .BR fromds , .BR dstods , or a numeric value. .IP "\fBvlan \fI[vlan_id]\fR" True if the packet is an IEEE 802.1Q VLAN packet. If \fI[vlan_id]\fR is specified, only true if the packet has the specified \fIvlan_id\fR. Note that the first \fBvlan\fR keyword encountered in \fIexpression\fR changes the decoding offsets for the remainder of \fIexpression\fR on the assumption that the packet is a VLAN packet. The \fBvlan \fI[vlan_id]\fR expression may be used more than once, to filter on VLAN hierarchies. Each use of that expression increments the filter offsets by 4. .IP For example: .in +.5i .nf \fBvlan 100 && vlan 200\fR .fi .in -.5i filters on VLAN 200 encapsulated within VLAN 100, and .in +.5i .nf \fBvlan && vlan 300 && ip\fR .fi .in -.5i filters IPv4 protocols encapsulated in VLAN 300 encapsulated within any higher order VLAN. .IP "\fBmpls \fI[label_num]\fR" True if the packet is an MPLS packet. If \fI[label_num]\fR is specified, only true is the packet has the specified \fIlabel_num\fR. Note that the first \fBmpls\fR keyword encountered in \fIexpression\fR changes the decoding offsets for the remainder of \fIexpression\fR on the assumption that the packet is a MPLS-encapsulated IP packet. The \fBmpls \fI[label_num]\fR expression may be used more than once, to filter on MPLS hierarchies. Each use of that expression increments the filter offsets by 4. .IP For example: .in +.5i .nf \fBmpls 100000 && mpls 1024\fR .fi .in -.5i filters packets with an outer label of 100000 and an inner label of 1024, and .in +.5i .nf \fBmpls && mpls 1024 && host 192.9.200.1\fR .fi .in -.5i filters packets to or from 192.9.200.1 with an inner label of 1024 and any outer label. .IP \fBpppoed\fP True if the packet is a PPP-over-Ethernet Discovery packet (Ethernet type 0x8863). .IP \fBpppoes\fP True if the packet is a PPP-over-Ethernet Session packet (Ethernet type 0x8864). Note that the first \fBpppoes\fR keyword encountered in \fIexpression\fR changes the decoding offsets for the remainder of \fIexpression\fR on the assumption that the packet is a PPPoE session packet. .IP For example: .in +.5i .nf \fBpppoes && ip\fR .fi .in -.5i filters IPv4 protocols encapsulated in PPPoE. -.IP "\fBtcp\fR, \fBudp\fR, \fBicmp\fR" -Abbreviations for: -.in +.5i -.nf -\fBip proto \fIp\fR\fB or ip6 proto \fIp\fR -.fi -.in -.5i -where \fIp\fR is one of the above protocols. .IP "\fBiso proto \fIprotocol\fR" True if the packet is an OSI packet of protocol type \fIprotocol\fP. \fIProtocol\fP can be a number or one of the names \fBclnp\fP, \fBesis\fP, or \fBisis\fP. .IP "\fBclnp\fR, \fBesis\fR, \fBisis\fR" Abbreviations for: .in +.5i .nf \fBiso proto \fIp\fR .fi .in -.5i where \fIp\fR is one of the above protocols. .IP "\fBl1\fR, \fBl2\fR, \fBiih\fR, \fBlsp\fR, \fBsnp\fR, \fBcsnp\fR, \fBpsnp\fR" Abbreviations for IS-IS PDU types. -.IP "\fBvpi\fP \fIn\fR +.IP "\fBvpi\fP \fIn\fR" True if the packet is an ATM packet, for SunATM on Solaris, with a virtual path identifier of .IR n . -.IP "\fBvci\fP \fIn\fR +.IP "\fBvci\fP \fIn\fR" True if the packet is an ATM packet, for SunATM on Solaris, with a virtual channel identifier of .IR n . .IP \fBlane\fP True if the packet is an ATM packet, for SunATM on Solaris, and is an ATM LANE packet. Note that the first \fBlane\fR keyword encountered in \fIexpression\fR changes the tests done in the remainder of \fIexpression\fR on the assumption that the packet is either a LANE emulated Ethernet packet or a LANE LE Control packet. If \fBlane\fR isn't specified, the tests are done under the assumption that the packet is an LLC-encapsulated packet. .IP \fBllc\fP True if the packet is an ATM packet, for SunATM on Solaris, and is an LLC-encapsulated packet. .IP \fBoamf4s\fP True if the packet is an ATM packet, for SunATM on Solaris, and is a segment OAM F4 flow cell (VPI=0 & VCI=3). .IP \fBoamf4e\fP True if the packet is an ATM packet, for SunATM on Solaris, and is an end-to-end OAM F4 flow cell (VPI=0 & VCI=4). .IP \fBoamf4\fP True if the packet is an ATM packet, for SunATM on Solaris, and is a segment or end-to-end OAM F4 flow cell (VPI=0 & (VCI=3 | VCI=4)). .IP \fBoam\fP True if the packet is an ATM packet, for SunATM on Solaris, and is a segment or end-to-end OAM F4 flow cell (VPI=0 & (VCI=3 | VCI=4)). .IP \fBmetac\fP True if the packet is an ATM packet, for SunATM on Solaris, and is on a meta signaling circuit (VPI=0 & VCI=1). .IP \fBbcc\fP True if the packet is an ATM packet, for SunATM on Solaris, and is on a broadcast signaling circuit (VPI=0 & VCI=2). .IP \fBsc\fP True if the packet is an ATM packet, for SunATM on Solaris, and is on a signaling circuit (VPI=0 & VCI=5). .IP \fBilmic\fP True if the packet is an ATM packet, for SunATM on Solaris, and is on an ILMI circuit (VPI=0 & VCI=16). .IP \fBconnectmsg\fP True if the packet is an ATM packet, for SunATM on Solaris, and is on a signaling circuit and is a Q.2931 Setup, Call Proceeding, Connect, Connect Ack, Release, or Release Done message. .IP \fBmetaconnect\fP True if the packet is an ATM packet, for SunATM on Solaris, and is on a meta signaling circuit and is a Q.2931 Setup, Call Proceeding, Connect, Release, or Release Done message. .IP "\fIexpr relop expr\fR" True if the relation holds, where \fIrelop\fR is one of >, <, >=, <=, =, !=, and \fIexpr\fR is an arithmetic expression composed of integer constants (expressed in standard C syntax), the normal binary operators [+, -, *, /, &, |, <<, >>], a length operator, and special packet data accessors. Note that all comparisons are unsigned, so that, for example, 0x80000000 and 0xffffffff are > 0. To access data inside the packet, use the following syntax: .in +.5i .nf \fIproto\fB [ \fIexpr\fB : \fIsize\fB ]\fR .fi .in -.5i \fIProto\fR is one of \fBether, fddi, tr, wlan, ppp, slip, link, ip, arp, rarp, tcp, udp, icmp, ip6\fR or \fBradio\fR, and indicates the protocol layer for the index operation. (\fBether, fddi, wlan, tr, ppp, slip\fR and \fBlink\fR all refer to the link layer. \fBradio\fR refers to the "radio header" added to some 802.11 captures.) Note that \fItcp, udp\fR and other upper-layer protocol types only apply to IPv4, not IPv6 (this will be fixed in the future). The byte offset, relative to the indicated protocol layer, is given by \fIexpr\fR. \fISize\fR is optional and indicates the number of bytes in the field of interest; it can be either one, two, or four, and defaults to one. The length operator, indicated by the keyword \fBlen\fP, gives the length of the packet. For example, `\fBether[0] & 1 != 0\fP' catches all multicast traffic. The expression `\fBip[0] & 0xf != 5\fP' catches all IPv4 packets with options. The expression `\fBip[6:2] & 0x1fff = 0\fP' catches only unfragmented IPv4 datagrams and frag zero of fragmented IPv4 datagrams. This check is implicitly applied to the \fBtcp\fP and \fBudp\fP index operations. For instance, \fBtcp[0]\fP always means the first byte of the TCP \fIheader\fP, and never means the first byte of an intervening fragment. Some offsets and field values may be expressed as names rather than as numeric values. The following protocol header field offsets are available: \fBicmptype\fP (ICMP type field), \fBicmpcode\fP (ICMP code field), and \fBtcpflags\fP (TCP flags field). The following ICMP type field values are available: \fBicmp-echoreply\fP, \fBicmp-unreach\fP, \fBicmp-sourcequench\fP, \fBicmp-redirect\fP, \fBicmp-echo\fP, \fBicmp-routeradvert\fP, \fBicmp-routersolicit\fP, \fBicmp-timxceed\fP, \fBicmp-paramprob\fP, \fBicmp-tstamp\fP, \fBicmp-tstampreply\fP, \fBicmp-ireq\fP, \fBicmp-ireqreply\fP, \fBicmp-maskreq\fP, \fBicmp-maskreply\fP. The following TCP flags field values are available: \fBtcp-fin\fP, \fBtcp-syn\fP, \fBtcp-rst\fP, \fBtcp-push\fP, \fBtcp-ack\fP, \fBtcp-urg\fP. .LP Primitives may be combined using: .IP A parenthesized group of primitives and operators (parentheses are special to the Shell and must be escaped). .IP Negation (`\fB!\fP' or `\fBnot\fP'). .IP Concatenation (`\fB&&\fP' or `\fBand\fP'). .IP Alternation (`\fB||\fP' or `\fBor\fP'). .LP Negation has highest precedence. Alternation and concatenation have equal precedence and associate left to right. Note that explicit \fBand\fR tokens, not juxtaposition, are now required for concatenation. .LP If an identifier is given without a keyword, the most recent keyword is assumed. For example, .in +.5i .nf \fBnot host vs and ace\fR .fi .in -.5i is short for .in +.5i .nf \fBnot host vs and host ace\fR .fi .in -.5i which should not be confused with .in +.5i .nf \fBnot ( host vs or ace )\fR .fi .in -.5i .SH EXAMPLES .LP To select all packets arriving at or departing from \fIsundown\fP: .RS .nf \fBhost sundown\fP .fi .RE .LP To select traffic between \fIhelios\fR and either \fIhot\fR or \fIace\fR: .RS .nf \fBhost helios and \\( hot or ace \\)\fP .fi .RE .LP To select all IP packets between \fIace\fR and any host except \fIhelios\fR: .RS .nf \fBip host ace and not helios\fP .fi .RE .LP To select all traffic between local hosts and hosts at Berkeley: .RS .nf .B net ucb-ether .fi .RE .LP To select all ftp traffic through internet gateway \fIsnup\fP: .RS .nf .B gateway snup and (port ftp or ftp-data) .fi .RE .LP To select traffic neither sourced from nor destined for local hosts (if you gateway to one other net, this stuff should never make it onto your local net). .RS .nf .B ip and not net \fIlocalnet\fP .fi .RE .LP To select the start and end packets (the SYN and FIN packets) of each TCP conversation that involves a non-local host. .RS .nf .B tcp[tcpflags] & (tcp-syn|tcp-fin) != 0 and not src and dst net \fIlocalnet\fP .fi .RE .LP To select all IPv4 HTTP packets to and from port 80, i.e. print only packets that contain data, not, for example, SYN and FIN packets and ACK-only packets. (IPv6 is left as an exercise for the reader.) .RS .nf .B tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0) .fi .RE .LP To select IP packets longer than 576 bytes sent through gateway \fIsnup\fP: .RS .nf .B gateway snup and ip[2:2] > 576 .fi .RE .LP To select IP broadcast or multicast packets that were .I not sent via Ethernet broadcast or multicast: .RS .nf .B ether[0] & 1 = 0 and ip[16] >= 224 .fi .RE .LP To select all ICMP packets that are not echo requests/replies (i.e., not ping packets): .RS .nf .B icmp[icmptype] != icmp-echo and icmp[icmptype] != icmp-echoreply .fi .RE .SH "SEE ALSO" pcap(3PCAP) -.SH AUTHORS -The original authors are: -.LP -Van Jacobson, -Craig Leres and -Steven McCanne, all of the -Lawrence Berkeley National Laboratory, University of California, Berkeley, CA. -.LP -It is currently being maintained by tcpdump.org. -.LP -The current version of libpcap is available via http: -.LP -.RS -.I http://www.tcpdump.org/ -.RE -.LP -The original distribution is available via anonymous ftp: -.LP -.RS -.I ftp://ftp.ee.lbl.gov/tcpdump.tar.Z -.RE .SH BUGS Please send problems, bugs, questions, desirable enhancements, etc. to: .LP .RS tcpdump-workers@lists.tcpdump.org .RE .LP Filter expressions on fields other than those in Token Ring headers will not correctly handle source-routed Token Ring packets. .LP Filter expressions on fields other than those in 802.11 headers will not correctly handle 802.11 data packets with both To DS and From DS set. .LP .BR "ip6 proto" should chase header chain, but at this moment it does not. .BR "ip6 protochain" is supplied for this behavior. .LP Arithmetic expression against transport layer headers, like \fBtcp[0]\fP, does not work against IPv6 packets. It only looks at IPv4 packets. Index: stable/9/contrib/libpcap/pcap-int.h =================================================================== --- stable/9/contrib/libpcap/pcap-int.h (revision 252280) +++ stable/9/contrib/libpcap/pcap-int.h (revision 252281) @@ -1,495 +1,513 @@ /* * Copyright (c) 1994, 1995, 1996 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Computer Systems * Engineering Group at Lawrence Berkeley Laboratory. * 4. Neither the name of the University nor of the Laboratory may be used * to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.94 2008-09-16 00:20:23 guy Exp $ (LBL) */ #ifndef pcap_int_h #define pcap_int_h #include #ifdef __cplusplus extern "C" { #endif #ifdef HAVE_LIBDLPI #include #endif #ifdef WIN32 #include extern CRITICAL_SECTION g_PcapCompileCriticalSection; #endif /* WIN32 */ #ifdef MSDOS #include #include #endif #ifdef HAVE_SNF_API #include #endif #if (defined(_MSC_VER) && (_MSC_VER <= 1200)) /* we are compiling with Visual Studio 6, that doesn't support the LL suffix*/ /* * Swap byte ordering of unsigned long long timestamp on a big endian * machine. */ #define SWAPLL(ull) ((ull & 0xff00000000000000) >> 56) | \ ((ull & 0x00ff000000000000) >> 40) | \ ((ull & 0x0000ff0000000000) >> 24) | \ ((ull & 0x000000ff00000000) >> 8) | \ ((ull & 0x00000000ff000000) << 8) | \ ((ull & 0x0000000000ff0000) << 24) | \ ((ull & 0x000000000000ff00) << 40) | \ ((ull & 0x00000000000000ff) << 56) #else /* A recent Visual studio compiler or not VC */ /* * Swap byte ordering of unsigned long long timestamp on a big endian * machine. */ #define SWAPLL(ull) ((ull & 0xff00000000000000LL) >> 56) | \ ((ull & 0x00ff000000000000LL) >> 40) | \ ((ull & 0x0000ff0000000000LL) >> 24) | \ ((ull & 0x000000ff00000000LL) >> 8) | \ ((ull & 0x00000000ff000000LL) << 8) | \ ((ull & 0x0000000000ff0000LL) << 24) | \ ((ull & 0x000000000000ff00LL) << 40) | \ ((ull & 0x00000000000000ffLL) << 56) #endif /* _MSC_VER */ /* * Savefile */ typedef enum { NOT_SWAPPED, SWAPPED, MAYBE_SWAPPED } swapped_type_t; /* * Used when reading a savefile. */ struct pcap_sf { FILE *rfile; int (*next_packet_op)(pcap_t *, struct pcap_pkthdr *, u_char **); int swapped; size_t hdrsize; swapped_type_t lengths_swapped; int version_major; int version_minor; bpf_u_int32 ifcount; /* number of interfaces seen in this capture */ u_int tsresol; /* time stamp resolution */ u_int tsscale; /* scaling factor for resolution -> microseconds */ u_int64_t tsoffset; /* time stamp offset */ }; /* * Used when doing a live capture. */ struct pcap_md { struct pcap_stat stat; /*XXX*/ int use_bpf; /* using kernel filter */ u_long TotPkts; /* can't oflow for 79 hrs on ether */ u_long TotAccepted; /* count accepted by filter */ u_long TotDrops; /* count of dropped packets */ long TotMissed; /* missed by i/f during this run */ long OrigMissed; /* missed by i/f before this run */ char *device; /* device name */ int timeout; /* timeout for buffering */ int must_do_on_close; /* stuff we must do when we close */ struct pcap *next; /* list of open pcaps that need stuff cleared on close */ #ifdef linux int sock_packet; /* using Linux 2.0 compatible interface */ int cooked; /* using SOCK_DGRAM rather than SOCK_RAW */ int ifindex; /* interface index of device we're bound to */ int lo_ifindex; /* interface index of the loopback device */ u_int packets_read; /* count of packets read with recvfrom() */ bpf_u_int32 oldmode; /* mode to restore when turning monitor mode off */ char *mondevice; /* mac80211 monitor device we created */ u_char *mmapbuf; /* memory-mapped region pointer */ size_t mmapbuflen; /* size of region */ + int vlan_offset; /* offset at which to insert vlan tags; if -1, don't insert */ u_int tp_version; /* version of tpacket_hdr for mmaped ring */ u_int tp_hdrlen; /* hdrlen of tpacket_hdr for mmaped ring */ u_char *oneshot_buffer; /* buffer for copy of packet */ long proc_dropped; /* packets reported dropped by /proc/net/dev */ #endif /* linux */ #ifdef HAVE_DAG_API #ifdef HAVE_DAG_STREAMS_API u_char *dag_mem_bottom; /* DAG card current memory bottom pointer */ u_char *dag_mem_top; /* DAG card current memory top pointer */ #else /* HAVE_DAG_STREAMS_API */ void *dag_mem_base; /* DAG card memory base address */ u_int dag_mem_bottom; /* DAG card current memory bottom offset */ u_int dag_mem_top; /* DAG card current memory top offset */ #endif /* HAVE_DAG_STREAMS_API */ int dag_fcs_bits; /* Number of checksum bits from link layer */ int dag_offset_flags; /* Flags to pass to dag_offset(). */ int dag_stream; /* DAG stream number */ int dag_timeout; /* timeout specified to pcap_open_live. * Same as in linux above, introduce * generally? */ #endif /* HAVE_DAG_API */ #ifdef HAVE_SNF_API snf_handle_t snf_handle; /* opaque device handle */ snf_ring_t snf_ring; /* opaque device ring handle */ int snf_timeout; int snf_boardnum; #endif /*HAVE_SNF_API*/ #ifdef HAVE_ZEROCOPY_BPF /* * Zero-copy read buffer -- for zero-copy BPF. 'buffer' above will * alternative between these two actual mmap'd buffers as required. * As there is a header on the front size of the mmap'd buffer, only * some of the buffer is exposed to libpcap as a whole via bufsize; * zbufsize is the true size. zbuffer tracks the current zbuf * assocated with buffer so that it can be used to decide which the * next buffer to read will be. */ u_char *zbuf1, *zbuf2, *zbuffer; u_int zbufsize; u_int zerocopy; u_int interrupted; struct timespec firstsel; /* * If there's currently a buffer being actively processed, then it is * referenced here; 'buffer' is also pointed at it, but offset by the * size of the header. */ struct bpf_zbuf_header *bzh; #endif /* HAVE_ZEROCOPY_BPF */ }; /* * Stuff to do when we close. */ #define MUST_CLEAR_PROMISC 0x00000001 /* clear promiscuous mode */ #define MUST_CLEAR_RFMON 0x00000002 /* clear rfmon (monitor) mode */ #define MUST_DELETE_MONIF 0x00000004 /* delete monitor-mode interface */ struct pcap_opt { int buffer_size; char *source; int promisc; int rfmon; int tstamp_type; }; /* * Ultrix, DEC OSF/1^H^H^H^H^H^H^H^H^HDigital UNIX^H^H^H^H^H^H^H^H^H^H^H^H * Tru64 UNIX, and some versions of NetBSD pad FDDI packets to make everything * line up on a nice boundary. */ #ifdef __NetBSD__ #include /* needed to declare __NetBSD_Version__ */ #endif #if defined(ultrix) || defined(__osf__) || (defined(__NetBSD__) && __NetBSD_Version__ > 106000000) #define PCAP_FDDIPAD 3 #endif typedef int (*activate_op_t)(pcap_t *); typedef int (*can_set_rfmon_op_t)(pcap_t *); typedef int (*read_op_t)(pcap_t *, int cnt, pcap_handler, u_char *); typedef int (*inject_op_t)(pcap_t *, const void *, size_t); typedef int (*setfilter_op_t)(pcap_t *, struct bpf_program *); typedef int (*setdirection_op_t)(pcap_t *, pcap_direction_t); typedef int (*set_datalink_op_t)(pcap_t *, int); typedef int (*getnonblock_op_t)(pcap_t *, char *); typedef int (*setnonblock_op_t)(pcap_t *, int, char *); typedef int (*stats_op_t)(pcap_t *, struct pcap_stat *); #ifdef WIN32 typedef int (*setbuff_op_t)(pcap_t *, int); typedef int (*setmode_op_t)(pcap_t *, int); typedef int (*setmintocopy_op_t)(pcap_t *, int); #endif typedef void (*cleanup_op_t)(pcap_t *); struct pcap { #ifdef WIN32 ADAPTER *adapter; LPPACKET Packet; int nonblock; #else int fd; int selectable_fd; int send_fd; #endif /* WIN32 */ #ifdef HAVE_LIBDLPI dlpi_handle_t dlpi_hd; #endif int snapshot; int linktype; /* Network linktype */ int linktype_ext; /* Extended information stored in the linktype field of a file */ int tzoff; /* timezone offset */ int offset; /* offset for proper alignment */ int activated; /* true if the capture is really started */ int oldstyle; /* if we're opening with pcap_open_live() */ int break_loop; /* flag set to force break from packet-reading loop */ #ifdef PCAP_FDDIPAD int fddipad; #endif #ifdef MSDOS void (*wait_proc)(void); /* call proc while waiting */ #endif struct pcap_sf sf; struct pcap_md md; struct pcap_opt opt; /* * Read buffer. */ int bufsize; u_char *buffer; u_char *bp; int cc; /* * Place holder for pcap_next(). */ u_char *pkt; /* We're accepting only packets in this direction/these directions. */ pcap_direction_t direction; /* * Methods. */ activate_op_t activate_op; can_set_rfmon_op_t can_set_rfmon_op; read_op_t read_op; inject_op_t inject_op; setfilter_op_t setfilter_op; setdirection_op_t setdirection_op; set_datalink_op_t set_datalink_op; getnonblock_op_t getnonblock_op; setnonblock_op_t setnonblock_op; stats_op_t stats_op; /* * Routine to use as callback for pcap_next()/pcap_next_ex(). */ pcap_handler oneshot_callback; #ifdef WIN32 /* * These are, at least currently, specific to the Win32 NPF * driver. */ setbuff_op_t setbuff_op; setmode_op_t setmode_op; setmintocopy_op_t setmintocopy_op; #endif cleanup_op_t cleanup_op; /* * Placeholder for filter code if bpf not in kernel. */ struct bpf_program fcode; char errbuf[PCAP_ERRBUF_SIZE + 1]; int dlt_count; u_int *dlt_list; int tstamp_type_count; u_int *tstamp_type_list; struct pcap_pkthdr pcap_header; /* This is needed for the pcap_next_ex() to work */ }; /* * This is a timeval as stored in a savefile. * It has to use the same types everywhere, independent of the actual * `struct timeval'; `struct timeval' has 32-bit tv_sec values on some * platforms and 64-bit tv_sec values on other platforms, and writing * out native `struct timeval' values would mean files could only be * read on systems with the same tv_sec size as the system on which * the file was written. */ struct pcap_timeval { bpf_int32 tv_sec; /* seconds */ bpf_int32 tv_usec; /* microseconds */ }; /* * This is a `pcap_pkthdr' as actually stored in a savefile. * * Do not change the format of this structure, in any way (this includes * changes that only affect the length of fields in this structure), * and do not make the time stamp anything other than seconds and * microseconds (e.g., seconds and nanoseconds). Instead: * * introduce a new structure for the new format; * * send mail to "tcpdump-workers@lists.tcpdump.org", requesting * a new magic number for your new capture file format, and, when * you get the new magic number, put it in "savefile.c"; * * use that magic number for save files with the changed record * header; * * make the code in "savefile.c" capable of reading files with * the old record header as well as files with the new record header * (using the magic number to determine the header format). * - * Then supply the changes as a patch at + * Then supply the changes by forking the branch at * - * http://sourceforge.net/projects/libpcap/ + * https://github.com/mcr/libpcap/issues * - * so that future versions of libpcap and programs that use it (such as - * tcpdump) will be able to read your new capture file format. + * and issuing a pull request, so that future versions of libpcap and + * programs that use it (such as tcpdump) will be able to read your new + * capture file format. */ struct pcap_sf_pkthdr { struct pcap_timeval ts; /* time stamp */ bpf_u_int32 caplen; /* length of portion present */ bpf_u_int32 len; /* length this packet (off wire) */ }; /* * How a `pcap_pkthdr' is actually stored in savefiles written * by some patched versions of libpcap (e.g. the ones in Red * Hat Linux 6.1 and 6.2). * * Do not change the format of this structure, in any way (this includes * changes that only affect the length of fields in this structure). * Instead, introduce a new structure, as per the above. */ struct pcap_sf_patched_pkthdr { struct pcap_timeval ts; /* time stamp */ bpf_u_int32 caplen; /* length of portion present */ bpf_u_int32 len; /* length this packet (off wire) */ int index; unsigned short protocol; unsigned char pkt_type; }; /* * User data structure for the one-shot callback used for pcap_next() * and pcap_next_ex(). */ struct oneshot_userdata { struct pcap_pkthdr *hdr; const u_char **pkt; pcap_t *pd; }; int yylex(void); #ifndef min #define min(a, b) ((a) > (b) ? (b) : (a)) #endif /* XXX should these be in pcap.h? */ int pcap_offline_read(pcap_t *, int, pcap_handler, u_char *); int pcap_read(pcap_t *, int cnt, pcap_handler, u_char *); #ifndef HAVE_STRLCPY #define strlcpy(x, y, z) \ (strncpy((x), (y), (z)), \ ((z) <= 0 ? 0 : ((x)[(z) - 1] = '\0')), \ strlen((y))) #endif #include #if !defined(HAVE_SNPRINTF) #define snprintf pcap_snprintf extern int snprintf (char *, size_t, const char *, ...); #endif #if !defined(HAVE_VSNPRINTF) #define vsnprintf pcap_vsnprintf extern int vsnprintf (char *, size_t, const char *, va_list ap); #endif /* * Routines that most pcap implementations can use for non-blocking mode. */ #if !defined(WIN32) && !defined(MSDOS) int pcap_getnonblock_fd(pcap_t *, char *); int pcap_setnonblock_fd(pcap_t *p, int, char *); #endif +/* + * Internal interfaces for "pcap_create()". + * + * "pcap_create_interface()" is the routine to do a pcap_create on + * a regular network interface. There are multiple implementations + * of this, one for each platform type (Linux, BPF, DLPI, etc.), + * with the one used chosen by the configure script. + * + * "pcap_create_common()" allocates and fills in a pcap_t, for use + * by pcap_create routines. + */ +pcap_t *pcap_create_interface(const char *, char *); pcap_t *pcap_create_common(const char *, char *); int pcap_do_addexit(pcap_t *); void pcap_add_to_pcaps_to_close(pcap_t *); void pcap_remove_from_pcaps_to_close(pcap_t *); void pcap_cleanup_live_common(pcap_t *); int pcap_not_initialized(pcap_t *); int pcap_check_activated(pcap_t *); /* * Internal interfaces for "pcap_findalldevs()". * + * "pcap_findalldevs_interfaces()" finds interfaces using the + * "standard" mechanisms (SIOCGIFCONF, "getifaddrs()", etc.). + * * "pcap_platform_finddevs()" is a platform-dependent routine to - * add devices not found by the "standard" mechanisms (SIOCGIFCONF, - * "getifaddrs()", etc.. + * add devices not found by the "standard" mechanisms. * - * "pcap_add_if()" adds an interface to the list of interfaces. + * "pcap_add_if()" adds an interface to the list of interfaces, for + * use by various "find interfaces" routines. */ +int pcap_findalldevs_interfaces(pcap_if_t **, char *); int pcap_platform_finddevs(pcap_if_t **, char *); int add_addr_to_iflist(pcap_if_t **, const char *, u_int, struct sockaddr *, size_t, struct sockaddr *, size_t, struct sockaddr *, size_t, struct sockaddr *, size_t, char *); int pcap_add_if(pcap_if_t **, const char *, u_int, const char *, char *); struct sockaddr *dup_sockaddr(struct sockaddr *, size_t); int add_or_find_if(pcap_if_t **, pcap_if_t **, const char *, u_int, const char *, char *); #ifdef WIN32 char *pcap_win32strerror(void); #endif int install_bpf_program(pcap_t *, struct bpf_program *); int pcap_strcasecmp(const char *, const char *); #ifdef __cplusplus } #endif #endif Index: stable/9/contrib/libpcap/pcap-libdlpi.c =================================================================== --- stable/9/contrib/libpcap/pcap-libdlpi.c (revision 252280) +++ stable/9/contrib/libpcap/pcap-libdlpi.c (revision 252281) @@ -1,404 +1,404 @@ /* * Copyright (c) 1993, 1994, 1995, 1996, 1997 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * This code contributed by Sagun Shakya (sagun.shakya@sun.com) */ /* * Packet capture routines for DLPI using libdlpi under SunOS 5.11. */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/pcap-libdlpi.c,v 1.6 2008-04-14 20:40:58 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include "pcap-int.h" #include "dlpisubs.h" /* Forwards. */ static int dlpromiscon(pcap_t *, bpf_u_int32); static int pcap_read_libdlpi(pcap_t *, int, pcap_handler, u_char *); static int pcap_inject_libdlpi(pcap_t *, const void *, size_t); static void pcap_close_libdlpi(pcap_t *); static void pcap_libdlpi_err(const char *, const char *, int, char *); static void pcap_cleanup_libdlpi(pcap_t *); /* * list_interfaces() will list all the network links that are * available on a system. */ static boolean_t list_interfaces(const char *, void *); typedef struct linknamelist { char linkname[DLPI_LINKNAME_MAX]; struct linknamelist *lnl_next; } linknamelist_t; typedef struct linkwalk { linknamelist_t *lw_list; int lw_err; } linkwalk_t; /* * The caller of this function should free the memory allocated * for each linknamelist_t "entry" allocated. */ static boolean_t list_interfaces(const char *linkname, void *arg) { linkwalk_t *lwp = arg; linknamelist_t *entry; if ((entry = calloc(1, sizeof(linknamelist_t))) == NULL) { lwp->lw_err = ENOMEM; return (B_TRUE); } (void) strlcpy(entry->linkname, linkname, DLPI_LINKNAME_MAX); if (lwp->lw_list == NULL) { lwp->lw_list = entry; } else { entry->lnl_next = lwp->lw_list; lwp->lw_list = entry; } return (B_FALSE); } static int pcap_activate_libdlpi(pcap_t *p) { int retv; dlpi_handle_t dh; dlpi_info_t dlinfo; int err = PCAP_ERROR; /* * Enable Solaris raw and passive DLPI extensions; * dlpi_open() will not fail if the underlying link does not support * passive mode. See dlpi(7P) for details. */ retv = dlpi_open(p->opt.source, &dh, DLPI_RAW|DLPI_PASSIVE); if (retv != DLPI_SUCCESS) { if (retv == DLPI_ELINKNAMEINVAL || retv == DLPI_ENOLINK) err = PCAP_ERROR_NO_SUCH_DEVICE; else if (retv == DL_SYSERR && (errno == EPERM || errno == EACCES)) err = PCAP_ERROR_PERM_DENIED; pcap_libdlpi_err(p->opt.source, "dlpi_open", retv, p->errbuf); return (err); } p->dlpi_hd = dh; if (p->opt.rfmon) { /* * This device exists, but we don't support monitor mode * any platforms that support DLPI. */ err = PCAP_ERROR_RFMON_NOTSUP; goto bad; } /* Bind with DLPI_ANY_SAP. */ if ((retv = dlpi_bind(p->dlpi_hd, DLPI_ANY_SAP, 0)) != DLPI_SUCCESS) { pcap_libdlpi_err(p->opt.source, "dlpi_bind", retv, p->errbuf); goto bad; } /* Enable promiscuous mode. */ if (p->opt.promisc) { err = dlpromiscon(p, DL_PROMISC_PHYS); if (err < 0) { /* * "You don't have permission to capture on * this device" and "you don't have permission * to capture in promiscuous mode on this * device" are different; let the user know, * so if they can't get permission to * capture in promiscuous mode, they can at * least try to capture in non-promiscuous * mode. * * XXX - you might have to capture in * promiscuous mode to see outgoing packets. */ if (err == PCAP_ERROR_PERM_DENIED) err = PCAP_ERROR_PROMISC_PERM_DENIED; goto bad; } } else { /* Try to enable multicast. */ err = dlpromiscon(p, DL_PROMISC_MULTI); if (err < 0) goto bad; } /* Try to enable SAP promiscuity. */ err = dlpromiscon(p, DL_PROMISC_SAP); if (err < 0) { /* * Not fatal, since the DL_PROMISC_PHYS mode worked. * Report it as a warning, however. */ if (p->opt.promisc) err = PCAP_WARNING; else goto bad; } /* Determine link type. */ if ((retv = dlpi_info(p->dlpi_hd, &dlinfo, 0)) != DLPI_SUCCESS) { pcap_libdlpi_err(p->opt.source, "dlpi_info", retv, p->errbuf); goto bad; } if (pcap_process_mactype(p, dlinfo.di_mactype) != 0) goto bad; p->fd = dlpi_fd(p->dlpi_hd); /* Push and configure bufmod. */ if (pcap_conf_bufmod(p, p->snapshot, p->md.timeout) != 0) goto bad; /* * Flush the read side. */ if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s", pcap_strerror(errno)); goto bad; } /* Allocate data buffer. */ if (pcap_alloc_databuf(p) != 0) goto bad; /* * "p->fd" is a FD for a STREAMS device, so "select()" and * "poll()" should work on it. */ p->selectable_fd = p->fd; p->read_op = pcap_read_libdlpi; p->inject_op = pcap_inject_libdlpi; p->setfilter_op = install_bpf_program; /* No kernel filtering */ p->setdirection_op = NULL; /* Not implemented */ p->set_datalink_op = NULL; /* Can't change data link type */ p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; p->stats_op = pcap_stats_dlpi; p->cleanup_op = pcap_cleanup_libdlpi; return (0); bad: pcap_cleanup_libdlpi(p); return (err); } #define STRINGIFY(n) #n static int dlpromiscon(pcap_t *p, bpf_u_int32 level) { int err; - retv = dlpi_promiscon(p->hd, level); + retv = dlpi_promiscon(p->dlpi_hd, level); if (retv != DLPI_SUCCESS) { if (retv == DL_SYSERR && (errno == EPERM || errno == EACCES)) err = PCAP_ERROR_PERM_DENIED; else err = PCAP_ERROR; pcap_libdlpi_err(p->opt.source, "dlpi_promiscon" STRINGIFY(level), retv, p->errbuf); return (err); } return (0); } /* * In Solaris, the "standard" mechanism" i.e SIOCGLIFCONF will only find * network links that are plumbed and are up. dlpi_walk(3DLPI) will find * additional network links present in the system. */ int pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) { int retv = 0; linknamelist_t *entry, *next; linkwalk_t lw = {NULL, 0}; int save_errno; /* dlpi_walk() for loopback will be added here. */ dlpi_walk(list_interfaces, &lw, 0); if (lw.lw_err != 0) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "dlpi_walk: %s", pcap_strerror(lw.lw_err)); retv = -1; goto done; } /* Add linkname if it does not exist on the list. */ for (entry = lw.lw_list; entry != NULL; entry = entry->lnl_next) { if (pcap_add_if(alldevsp, entry->linkname, 0, NULL, errbuf) < 0) retv = -1; } done: save_errno = errno; for (entry = lw.lw_list; entry != NULL; entry = next) { next = entry->lnl_next; free(entry); } errno = save_errno; return (retv); } /* * Read data received on DLPI handle. Returns -2 if told to terminate, else * returns the number of packets read. */ static int pcap_read_libdlpi(pcap_t *p, int count, pcap_handler callback, u_char *user) { int len; u_char *bufp; size_t msglen; int retv; len = p->cc; if (len != 0) { bufp = p->bp; goto process_pkts; } do { /* Has "pcap_breakloop()" been called? */ if (p->break_loop) { /* * Yes - clear the flag that indicates that it has, * and return -2 to indicate that we were told to * break out of the loop. */ p->break_loop = 0; return (-2); } msglen = p->bufsize; bufp = p->buffer + p->offset; retv = dlpi_recv(p->dlpi_hd, NULL, NULL, bufp, &msglen, -1, NULL); if (retv != DLPI_SUCCESS) { /* * This is most likely a call to terminate out of the * loop. So, do not return an error message, instead * check if "pcap_breakloop()" has been called above. */ if (retv == DL_SYSERR && errno == EINTR) { len = 0; continue; } pcap_libdlpi_err(dlpi_linkname(p->dlpi_hd), "dlpi_recv", retv, p->errbuf); return (-1); } len = msglen; } while (len == 0); process_pkts: return (pcap_process_pkts(p, callback, user, count, bufp, len)); } static int pcap_inject_libdlpi(pcap_t *p, const void *buf, size_t size) { int retv; retv = dlpi_send(p->dlpi_hd, NULL, 0, buf, size, NULL); if (retv != DLPI_SUCCESS) { pcap_libdlpi_err(dlpi_linkname(p->dlpi_hd), "dlpi_send", retv, p->errbuf); return (-1); } /* * dlpi_send(3DLPI) does not provide a way to return the number of * bytes sent on the wire. Based on the fact that DLPI_SUCCESS was * returned we are assuming 'size' bytes were sent. */ return (size); } /* * Close dlpi handle. */ static void pcap_cleanup_libdlpi(pcap_t *p) { if (p->dlpi_hd != NULL) { dlpi_close(p->dlpi_hd); p->dlpi_hd = NULL; p->fd = -1; } pcap_cleanup_live_common(p); } /* * Write error message to buffer. */ static void pcap_libdlpi_err(const char *linkname, const char *func, int err, char *errbuf) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "libpcap: %s failed on %s: %s", func, linkname, dlpi_strerror(err)); } pcap_t * -pcap_create(const char *device, char *ebuf) +pcap_create_interface(const char *device, char *ebuf) { pcap_t *p; p = pcap_create_common(device, ebuf); if (p == NULL) return (NULL); p->activate_op = pcap_activate_libdlpi; return (p); } Index: stable/9/contrib/libpcap/pcap-linux.c =================================================================== --- stable/9/contrib/libpcap/pcap-linux.c (revision 252280) +++ stable/9/contrib/libpcap/pcap-linux.c (revision 252281) @@ -1,5561 +1,5490 @@ /* * pcap-linux.c: Packet capture interface to the Linux kernel * * Copyright (c) 2000 Torsten Landschoff * Sebastian Krahmer * * License: BSD * * 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. The names of the authors may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Modifications: Added PACKET_MMAP support * Paolo Abeni * * based on previous works of: * Simon Patarin * Phil Wood * * Monitor-mode support for mac80211 includes code taken from the iw * command; the copyright notice for that code is * * Copyright (c) 2007, 2008 Johannes Berg * Copyright (c) 2007 Andy Lutomirski * Copyright (c) 2007 Mike Kershaw * Copyright (c) 2008 Gábor Stefanik * * 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. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.164 2008-12-14 22:00:57 guy Exp $ (LBL)"; #endif /* * Known problems with 2.0[.x] kernels: * * - The loopback device gives every packet twice; on 2.2[.x] kernels, * if we use PF_PACKET, we can filter out the transmitted version * of the packet by using data in the "sockaddr_ll" returned by * "recvfrom()", but, on 2.0[.x] kernels, we have to use * PF_INET/SOCK_PACKET, which means "recvfrom()" supplies a * "sockaddr_pkt" which doesn't give us enough information to let * us do that. * * - We have to set the interface's IFF_PROMISC flag ourselves, if * we're to run in promiscuous mode, which means we have to turn * it off ourselves when we're done; the kernel doesn't keep track * of how many sockets are listening promiscuously, which means * it won't get turned off automatically when no sockets are * listening promiscuously. We catch "pcap_close()" and, for * interfaces we put into promiscuous mode, take them out of * promiscuous mode - which isn't necessarily the right thing to * 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. */ #define _GNU_SOURCE #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include +#include #include #include #include #include #include +#include #include #include #include #include #include #include "pcap-int.h" #include "pcap/sll.h" #include "pcap/vlan.h" -#ifdef HAVE_DAG_API -#include "pcap-dag.h" -#endif /* HAVE_DAG_API */ - -#ifdef HAVE_SEPTEL_API -#include "pcap-septel.h" -#endif /* HAVE_SEPTEL_API */ - -#ifdef HAVE_SNF_API -#include "pcap-snf.h" -#endif /* HAVE_SNF_API */ - -#ifdef PCAP_SUPPORT_USB -#include "pcap-usb-linux.h" -#endif - -#ifdef PCAP_SUPPORT_BT -#include "pcap-bt-linux.h" -#endif - -#ifdef PCAP_SUPPORT_CAN -#include "pcap-can-linux.h" -#endif - -#if PCAP_SUPPORT_CANUSB -#include "pcap-canusb-linux.h" -#endif - -#ifdef PCAP_SUPPORT_NETFILTER -#include "pcap-netfilter-linux.h" -#endif - /* * 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 /* * 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. * * So we check whether PACKET_HOST is defined, and assume that we have * PF_PACKET sockets only if it is defined. */ # ifdef PACKET_HOST # define HAVE_PF_PACKET_SOCKETS # ifdef PACKET_AUXDATA # define HAVE_PACKET_AUXDATA # endif /* PACKET_AUXDATA */ # endif /* PACKET_HOST */ /* check for memory mapped access avaibility. We assume every needed * struct is defined if the macro TPACKET_HDRLEN is defined, because it * uses many ring related structs and macros */ # ifdef TPACKET_HDRLEN # define HAVE_PACKET_RING # ifdef TPACKET2_HDRLEN # define HAVE_TPACKET2 # else # define TPACKET_V1 0 # endif /* TPACKET2_HDRLEN */ # endif /* TPACKET_HDRLEN */ #endif /* PF_PACKET */ #ifdef SO_ATTACH_FILTER #include #include #endif /* * We need linux/sockios.h if we have linux/net_tstamp.h (for time stamp * specification) or linux/ethtool.h (for ethtool ioctls to get offloading * information). */ #if defined(HAVE_LINUX_NET_TSTAMP_H) || defined(HAVE_LINUX_ETHTOOL_H) #include #endif #ifdef HAVE_LINUX_NET_TSTAMP_H #include #endif /* * Got Wireless Extensions? */ #ifdef HAVE_LINUX_WIRELESS_H #include #endif /* HAVE_LINUX_WIRELESS_H */ /* * Got libnl? */ #ifdef HAVE_LIBNL #include #include #include #include #include #include #endif /* HAVE_LIBNL */ /* * Got ethtool support? */ #ifdef HAVE_LINUX_ETHTOOL_H #include #endif #ifndef HAVE_SOCKLEN_T typedef int socklen_t; #endif #ifndef MSG_TRUNC /* * 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 #ifndef SOL_PACKET /* * This is being compiled on a system that lacks SOL_PACKET; define it * with the value it has in the 2.2 and later kernels, so that we can * set promiscuous mode in the good modern way rather than the old * 2.0-kernel crappy way. */ #define SOL_PACKET 263 #endif #define MAX_LINKHEADER_SIZE 256 /* * When capturing on all interfaces we use this as the buffer size. * Should be bigger then all MTUs that occur in real life. * 64kB should be enough for now. */ #define BIGGER_THAN_ALL_MTUS (64*1024) /* * Prototypes for internal functions and methods. */ static void map_arphrd_to_dlt(pcap_t *, int, int); #ifdef HAVE_PF_PACKET_SOCKETS static short int map_packet_type_to_sll_type(short int); #endif static int pcap_activate_linux(pcap_t *); static int activate_old(pcap_t *); static int activate_new(pcap_t *); static int activate_mmap(pcap_t *, int *); static int pcap_can_set_rfmon_linux(pcap_t *); static int pcap_read_linux(pcap_t *, int, pcap_handler, u_char *); static int pcap_read_packet(pcap_t *, pcap_handler, u_char *); static int pcap_inject_linux(pcap_t *, const void *, size_t); static int pcap_stats_linux(pcap_t *, struct pcap_stat *); static int pcap_setfilter_linux(pcap_t *, struct bpf_program *); static int pcap_setdirection_linux(pcap_t *, pcap_direction_t); static void pcap_cleanup_linux(pcap_t *); union thdr { struct tpacket_hdr *h1; struct tpacket2_hdr *h2; void *raw; }; #ifdef HAVE_PACKET_RING #define RING_GET_FRAME(h) (((union thdr **)h->buffer)[h->offset]) static void destroy_ring(pcap_t *handle); static int create_ring(pcap_t *handle, int *status); static int prepare_tpacket_socket(pcap_t *handle); static void pcap_cleanup_linux_mmap(pcap_t *); static int pcap_read_linux_mmap(pcap_t *, int, pcap_handler , u_char *); static int pcap_setfilter_linux_mmap(pcap_t *, struct bpf_program *); static int pcap_setnonblock_mmap(pcap_t *p, int nonblock, char *errbuf); static int pcap_getnonblock_mmap(pcap_t *p, char *errbuf); static void pcap_oneshot_mmap(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes); #endif /* * Wrap some ioctl calls */ #ifdef HAVE_PF_PACKET_SOCKETS static int iface_get_id(int fd, const char *device, char *ebuf); #endif /* HAVE_PF_PACKET_SOCKETS */ static int iface_get_mtu(int fd, const char *device, char *ebuf); static int iface_get_arptype(int fd, const char *device, char *ebuf); #ifdef HAVE_PF_PACKET_SOCKETS static int iface_bind(int fd, int ifindex, char *ebuf); #ifdef IW_MODE_MONITOR static int has_wext(int sock_fd, const char *device, char *ebuf); #endif /* IW_MODE_MONITOR */ static int enter_rfmon_mode(pcap_t *handle, int sock_fd, const char *device); #endif /* HAVE_PF_PACKET_SOCKETS */ static int iface_get_offload(pcap_t *handle); 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, int is_mapped); 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 /* SO_ATTACH_FILTER */ pcap_t * -pcap_create(const char *device, char *ebuf) +pcap_create_interface(const char *device, char *ebuf) { pcap_t *handle; - /* - * A null device name is equivalent to the "any" device. - */ - if (device == NULL) - device = "any"; - -#ifdef HAVE_DAG_API - if (strstr(device, "dag")) { - return dag_create(device, ebuf); - } -#endif /* HAVE_DAG_API */ - -#ifdef HAVE_SEPTEL_API - if (strstr(device, "septel")) { - return septel_create(device, ebuf); - } -#endif /* HAVE_SEPTEL_API */ - -#ifdef HAVE_SNF_API - handle = snf_create(device, ebuf); - if (strstr(device, "snf") || handle != NULL) - return handle; - -#endif /* HAVE_SNF_API */ - -#ifdef PCAP_SUPPORT_BT - if (strstr(device, "bluetooth")) { - return bt_create(device, ebuf); - } -#endif - -#if PCAP_SUPPORT_CANUSB - if (strstr(device, "canusb")) { - return canusb_create(device, ebuf); - } -#endif - -#ifdef PCAP_SUPPORT_CAN - if ((strncmp(device, "can", 3) == 0 && isdigit(device[3])) || - (strncmp(device, "vcan", 4) == 0 && isdigit(device[4]))) { - return can_create(device, ebuf); - } -#endif - -#ifdef PCAP_SUPPORT_USB - if (strstr(device, "usbmon")) { - return usb_create(device, ebuf); - } -#endif - -#ifdef PCAP_SUPPORT_NETFILTER - if (strncmp(device, "nflog", strlen("nflog")) == 0) { - return nflog_create(device, ebuf); - } -#endif - handle = pcap_create_common(device, ebuf); if (handle == NULL) return NULL; handle->activate_op = pcap_activate_linux; handle->can_set_rfmon_op = pcap_can_set_rfmon_linux; #if defined(HAVE_LINUX_NET_TSTAMP_H) && defined(PACKET_TIMESTAMP) /* * We claim that we support: * * software time stamps, with no details about their precision; * hardware time stamps, synced to the host time; * hardware time stamps, not synced to the host time. * * XXX - we can't ask a device whether it supports * hardware time stamps, so we just claim all devices do. */ handle->tstamp_type_count = 3; handle->tstamp_type_list = malloc(3 * sizeof(u_int)); if (handle->tstamp_type_list == NULL) { free(handle); return NULL; } handle->tstamp_type_list[0] = PCAP_TSTAMP_HOST; handle->tstamp_type_list[1] = PCAP_TSTAMP_ADAPTER; handle->tstamp_type_list[2] = PCAP_TSTAMP_ADAPTER_UNSYNCED; #endif return handle; } #ifdef HAVE_LIBNL /* * If interface {if} is a mac80211 driver, the file * /sys/class/net/{if}/phy80211 is a symlink to * /sys/class/ieee80211/{phydev}, for some {phydev}. * * On Fedora 9, with a 2.6.26.3-29 kernel, my Zydas stick, at * least, has a "wmaster0" device and a "wlan0" device; the * latter is the one with the IP address. Both show up in * "tcpdump -D" output. Capturing on the wmaster0 device * captures with 802.11 headers. * * airmon-ng searches through /sys/class/net for devices named * monN, starting with mon0; as soon as one *doesn't* exist, * it chooses that as the monitor device name. If the "iw" * command exists, it does "iw dev {if} interface add {monif} * type monitor", where {monif} is the monitor device. It * then (sigh) sleeps .1 second, and then configures the * device up. Otherwise, if /sys/class/ieee80211/{phydev}/add_iface * is a file, it writes {mondev}, without a newline, to that file, * and again (sigh) sleeps .1 second, and then iwconfig's that * device into monitor mode and configures it up. Otherwise, * you can't do monitor mode. * * All these devices are "glued" together by having the * /sys/class/net/{device}/phy80211 links pointing to the same * place, so, given a wmaster, wlan, or mon device, you can * find the other devices by looking for devices with * the same phy80211 link. * * To turn monitor mode off, delete the monitor interface, * either with "iw dev {monif} interface del" or by sending * {monif}, with no NL, down /sys/class/ieee80211/{phydev}/remove_iface * * Note: if you try to create a monitor device named "monN", and * there's already a "monN" device, it fails, as least with * the netlink interface (which is what iw uses), with a return * value of -ENFILE. (Return values are negative errnos.) We * could probably use that to find an unused device. * * Yes, you can have multiple monitor devices for a given * physical device. */ /* * Is this a mac80211 device? If so, fill in the physical device path and * return 1; if not, return 0. On an error, fill in handle->errbuf and * return PCAP_ERROR. */ static int get_mac80211_phydev(pcap_t *handle, const char *device, char *phydev_path, size_t phydev_max_pathlen) { char *pathstr; ssize_t bytes_read; /* * Generate the path string for the symlink to the physical device. */ if (asprintf(&pathstr, "/sys/class/net/%s/phy80211", device) == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "%s: Can't generate path name string for /sys/class/net device", device); return PCAP_ERROR; } bytes_read = readlink(pathstr, phydev_path, phydev_max_pathlen); if (bytes_read == -1) { if (errno == ENOENT || errno == EINVAL) { /* * Doesn't exist, or not a symlink; assume that * means it's not a mac80211 device. */ free(pathstr); return 0; } snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "%s: Can't readlink %s: %s", device, pathstr, strerror(errno)); free(pathstr); return PCAP_ERROR; } free(pathstr); phydev_path[bytes_read] = '\0'; return 1; } -#ifdef HAVE_LIBNL_2_x +#ifdef HAVE_LIBNL_SOCKETS #define get_nl_errmsg nl_geterror #else /* libnl 2.x compatibility code */ #define nl_sock nl_handle static inline struct nl_handle * nl_socket_alloc(void) { return nl_handle_alloc(); } static inline void nl_socket_free(struct nl_handle *h) { nl_handle_destroy(h); } #define get_nl_errmsg strerror static inline int __genl_ctrl_alloc_cache(struct nl_handle *h, struct nl_cache **cache) { struct nl_cache *tmp = genl_ctrl_alloc_cache(h); if (!tmp) return -ENOMEM; *cache = tmp; return 0; } #define genl_ctrl_alloc_cache __genl_ctrl_alloc_cache -#endif /* !HAVE_LIBNL_2_x */ +#endif /* !HAVE_LIBNL_SOCKETS */ struct nl80211_state { struct nl_sock *nl_sock; struct nl_cache *nl_cache; struct genl_family *nl80211; }; static int nl80211_init(pcap_t *handle, struct nl80211_state *state, const char *device) { int err; state->nl_sock = nl_socket_alloc(); if (!state->nl_sock) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "%s: failed to allocate netlink handle", device); return PCAP_ERROR; } if (genl_connect(state->nl_sock)) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "%s: failed to connect to generic netlink", device); goto out_handle_destroy; } err = genl_ctrl_alloc_cache(state->nl_sock, &state->nl_cache); if (err < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "%s: failed to allocate generic netlink cache: %s", device, get_nl_errmsg(-err)); goto out_handle_destroy; } state->nl80211 = genl_ctrl_search_by_name(state->nl_cache, "nl80211"); if (!state->nl80211) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "%s: nl80211 not found", device); goto out_cache_free; } return 0; out_cache_free: nl_cache_free(state->nl_cache); out_handle_destroy: nl_socket_free(state->nl_sock); return PCAP_ERROR; } static void nl80211_cleanup(struct nl80211_state *state) { genl_family_put(state->nl80211); nl_cache_free(state->nl_cache); nl_socket_free(state->nl_sock); } static int add_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state, const char *device, const char *mondevice) { int ifindex; struct nl_msg *msg; int err; ifindex = iface_get_id(sock_fd, device, handle->errbuf); if (ifindex == -1) return PCAP_ERROR; msg = nlmsg_alloc(); if (!msg) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "%s: failed to allocate netlink msg", device); return PCAP_ERROR; } genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0, 0, NL80211_CMD_NEW_INTERFACE, 0); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex); NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, mondevice); NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_MONITOR); err = nl_send_auto_complete(state->nl_sock, msg); if (err < 0) { -#ifdef HAVE_LIBNL_2_x +#if defined HAVE_LIBNL_NLE if (err == -NLE_FAILURE) { #else if (err == -ENFILE) { #endif /* * Device not available; our caller should just * keep trying. (libnl 2.x maps ENFILE to * NLE_FAILURE; it can also map other errors * to that, but there's not much we can do * about that.) */ nlmsg_free(msg); return 0; } else { /* * Real failure, not just "that device is not * available. */ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "%s: nl_send_auto_complete failed adding %s interface: %s", device, mondevice, get_nl_errmsg(-err)); nlmsg_free(msg); return PCAP_ERROR; } } err = nl_wait_for_ack(state->nl_sock); if (err < 0) { -#ifdef HAVE_LIBNL_2_x +#if defined HAVE_LIBNL_NLE if (err == -NLE_FAILURE) { #else if (err == -ENFILE) { #endif /* * Device not available; our caller should just * keep trying. (libnl 2.x maps ENFILE to * NLE_FAILURE; it can also map other errors * to that, but there's not much we can do * about that.) */ nlmsg_free(msg); return 0; } else { /* * Real failure, not just "that device is not * available. */ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "%s: nl_wait_for_ack failed adding %s interface: %s", device, mondevice, get_nl_errmsg(-err)); nlmsg_free(msg); return PCAP_ERROR; } } /* * Success. */ nlmsg_free(msg); return 1; nla_put_failure: snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "%s: nl_put failed adding %s interface", device, mondevice); nlmsg_free(msg); return PCAP_ERROR; } static int del_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state, const char *device, const char *mondevice) { int ifindex; struct nl_msg *msg; int err; ifindex = iface_get_id(sock_fd, mondevice, handle->errbuf); if (ifindex == -1) return PCAP_ERROR; msg = nlmsg_alloc(); if (!msg) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "%s: failed to allocate netlink msg", device); return PCAP_ERROR; } genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0, 0, NL80211_CMD_DEL_INTERFACE, 0); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex); err = nl_send_auto_complete(state->nl_sock, msg); if (err < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "%s: nl_send_auto_complete failed deleting %s interface: %s", device, mondevice, get_nl_errmsg(-err)); nlmsg_free(msg); return PCAP_ERROR; } err = nl_wait_for_ack(state->nl_sock); if (err < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "%s: nl_wait_for_ack failed adding %s interface: %s", device, mondevice, get_nl_errmsg(-err)); nlmsg_free(msg); return PCAP_ERROR; } /* * Success. */ nlmsg_free(msg); return 1; nla_put_failure: snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "%s: nl_put failed deleting %s interface", device, mondevice); nlmsg_free(msg); return PCAP_ERROR; } static int enter_rfmon_mode_mac80211(pcap_t *handle, int sock_fd, const char *device) { int ret; char phydev_path[PATH_MAX+1]; struct nl80211_state nlstate; struct ifreq ifr; u_int n; /* * Is this a mac80211 device? */ ret = get_mac80211_phydev(handle, device, phydev_path, PATH_MAX); if (ret < 0) return ret; /* error */ if (ret == 0) return 0; /* no error, but not mac80211 device */ /* * XXX - is this already a monN device? * If so, we're done. * Is that determined by old Wireless Extensions ioctls? */ /* * OK, it's apparently a mac80211 device. * Try to find an unused monN device for it. */ ret = nl80211_init(handle, &nlstate, device); if (ret != 0) return ret; for (n = 0; n < UINT_MAX; n++) { /* * Try mon{n}. */ char mondevice[3+10+1]; /* mon{UINT_MAX}\0 */ snprintf(mondevice, sizeof mondevice, "mon%u", n); ret = add_mon_if(handle, sock_fd, &nlstate, device, mondevice); if (ret == 1) { handle->md.mondevice = strdup(mondevice); goto added; } if (ret < 0) { /* * Hard failure. Just return ret; handle->errbuf * has already been set. */ nl80211_cleanup(&nlstate); return ret; } } snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "%s: No free monN interfaces", device); nl80211_cleanup(&nlstate); return PCAP_ERROR; added: #if 0 /* * Sleep for .1 seconds. */ delay.tv_sec = 0; delay.tv_nsec = 500000000; nanosleep(&delay, NULL); #endif /* * If we haven't already done so, arrange to have * "pcap_close_all()" called when we exit. */ if (!pcap_do_addexit(handle)) { /* * "atexit()" failed; don't put the interface * in rfmon mode, just give up. */ return PCAP_ERROR_RFMON_NOTSUP; } /* * Now configure the monitor interface up. */ memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, handle->md.mondevice, sizeof(ifr.ifr_name)); if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "%s: Can't get flags for %s: %s", device, handle->md.mondevice, strerror(errno)); del_mon_if(handle, sock_fd, &nlstate, device, handle->md.mondevice); nl80211_cleanup(&nlstate); return PCAP_ERROR; } ifr.ifr_flags |= IFF_UP|IFF_RUNNING; if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "%s: Can't set flags for %s: %s", device, handle->md.mondevice, strerror(errno)); del_mon_if(handle, sock_fd, &nlstate, device, handle->md.mondevice); nl80211_cleanup(&nlstate); return PCAP_ERROR; } /* * Success. Clean up the libnl state. */ nl80211_cleanup(&nlstate); /* * Note that we have to delete the monitor device when we close * the handle. */ handle->md.must_do_on_close |= MUST_DELETE_MONIF; /* * Add this to the list of pcaps to close when we exit. */ pcap_add_to_pcaps_to_close(handle); return 1; } #endif /* HAVE_LIBNL */ static int pcap_can_set_rfmon_linux(pcap_t *handle) { #ifdef HAVE_LIBNL char phydev_path[PATH_MAX+1]; int ret; #endif #ifdef IW_MODE_MONITOR int sock_fd; struct iwreq ireq; #endif if (strcmp(handle->opt.source, "any") == 0) { /* * Monitor mode makes no sense on the "any" device. */ return 0; } #ifdef HAVE_LIBNL /* * Bleah. There doesn't seem to be a way to ask a mac80211 * device, through libnl, whether it supports monitor mode; * we'll just check whether the device appears to be a * mac80211 device and, if so, assume the device supports * monitor mode. * * wmaster devices don't appear to support the Wireless * Extensions, but we can create a mon device for a * wmaster device, so we don't bother checking whether * a mac80211 device supports the Wireless Extensions. */ ret = get_mac80211_phydev(handle, handle->opt.source, phydev_path, PATH_MAX); if (ret < 0) return ret; /* error */ if (ret == 1) return 1; /* mac80211 device */ #endif #ifdef IW_MODE_MONITOR /* * Bleah. There doesn't appear to be an ioctl to use to ask * whether a device supports monitor mode; we'll just do * SIOCGIWMODE and, if it succeeds, assume the device supports * monitor mode. * * Open a socket on which to attempt to get the mode. * (We assume that if we have Wireless Extensions support * we also have PF_PACKET support.) */ sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (sock_fd == -1) { (void)snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "socket: %s", pcap_strerror(errno)); return PCAP_ERROR; } /* * Attempt to get the current mode. */ strncpy(ireq.ifr_ifrn.ifrn_name, handle->opt.source, sizeof ireq.ifr_ifrn.ifrn_name); ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0; if (ioctl(sock_fd, SIOCGIWMODE, &ireq) != -1) { /* * Well, we got the mode; assume we can set it. */ close(sock_fd); return 1; } if (errno == ENODEV) { /* The device doesn't even exist. */ (void)snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "SIOCGIWMODE failed: %s", pcap_strerror(errno)); close(sock_fd); return PCAP_ERROR_NO_SUCH_DEVICE; } close(sock_fd); #endif return 0; } /* * Grabs the number of dropped packets by the interface from /proc/net/dev. * * XXX - what about /sys/class/net/{interface name}/rx_*? There are * individual devices giving, in ASCII, various rx_ and tx_ statistics. * * Or can we get them in binary form from netlink? */ static long int linux_if_drops(const char * if_name) { char buffer[512]; char * bufptr; FILE * file; int field_to_convert = 3, if_name_sz = strlen(if_name); long int dropped_pkts = 0; file = fopen("/proc/net/dev", "r"); if (!file) return 0; while (!dropped_pkts && fgets( buffer, sizeof(buffer), file )) { /* search for 'bytes' -- if its in there, then that means we need to grab the fourth field. otherwise grab the third field. */ if (field_to_convert != 4 && strstr(buffer, "bytes")) { field_to_convert = 4; continue; } /* find iface and make sure it actually matches -- space before the name and : after it */ if ((bufptr = strstr(buffer, if_name)) && (bufptr == buffer || *(bufptr-1) == ' ') && *(bufptr + if_name_sz) == ':') { bufptr = bufptr + if_name_sz + 1; /* grab the nth field from it */ while( --field_to_convert && *bufptr != '\0') { while (*bufptr != '\0' && *(bufptr++) == ' '); while (*bufptr != '\0' && *(bufptr++) != ' '); } /* get rid of any final spaces */ while (*bufptr != '\0' && *bufptr == ' ') bufptr++; if (*bufptr != '\0') dropped_pkts = strtol(bufptr, NULL, 10); break; } } fclose(file); return dropped_pkts; } /* * With older kernels promiscuous mode is kind of interesting because we * have to reset the interface before exiting. The problem can't really * be solved without some daemon taking care of managing usage counts. * If we put the interface into promiscuous mode, we set a flag indicating * that we must take it out of that mode when the interface is closed, * and, when closing the interface, if that flag is set we take it out * of promiscuous mode. * * Even with newer kernels, we have the same issue with rfmon mode. */ static void pcap_cleanup_linux( pcap_t *handle ) { struct ifreq ifr; #ifdef HAVE_LIBNL struct nl80211_state nlstate; int ret; #endif /* HAVE_LIBNL */ #ifdef IW_MODE_MONITOR int oldflags; struct iwreq ireq; #endif /* IW_MODE_MONITOR */ if (handle->md.must_do_on_close != 0) { /* * There's something we have to do when closing this * pcap_t. */ if (handle->md.must_do_on_close & MUST_CLEAR_PROMISC) { /* * We put the interface into promiscuous mode; * take it out of promiscuous mode. * * XXX - if somebody else wants it in promiscuous * mode, this code cannot know that, so it'll take * it out of promiscuous mode. That's not fixable * in 2.0[.x] kernels. */ memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, handle->md.device, sizeof(ifr.ifr_name)); if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) { fprintf(stderr, "Can't restore interface %s flags (SIOCGIFFLAGS failed: %s).\n" "Please adjust manually.\n" "Hint: This can't happen with Linux >= 2.2.0.\n", handle->md.device, strerror(errno)); } else { if (ifr.ifr_flags & IFF_PROMISC) { /* * Promiscuous mode is currently on; * turn it off. */ ifr.ifr_flags &= ~IFF_PROMISC; if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) { fprintf(stderr, "Can't restore interface %s flags (SIOCSIFFLAGS failed: %s).\n" "Please adjust manually.\n" "Hint: This can't happen with Linux >= 2.2.0.\n", handle->md.device, strerror(errno)); } } } } #ifdef HAVE_LIBNL if (handle->md.must_do_on_close & MUST_DELETE_MONIF) { ret = nl80211_init(handle, &nlstate, handle->md.device); if (ret >= 0) { ret = del_mon_if(handle, handle->fd, &nlstate, handle->md.device, handle->md.mondevice); nl80211_cleanup(&nlstate); } if (ret < 0) { fprintf(stderr, "Can't delete monitor interface %s (%s).\n" "Please delete manually.\n", handle->md.mondevice, handle->errbuf); } } #endif /* HAVE_LIBNL */ #ifdef IW_MODE_MONITOR if (handle->md.must_do_on_close & MUST_CLEAR_RFMON) { /* * We put the interface into rfmon mode; * take it out of rfmon mode. * * XXX - if somebody else wants it in rfmon * mode, this code cannot know that, so it'll take * it out of rfmon mode. */ /* * First, take the interface down if it's up; * otherwise, we might get EBUSY. * If we get errors, just drive on and print * a warning if we can't restore the mode. */ oldflags = 0; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, handle->md.device, sizeof(ifr.ifr_name)); if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) != -1) { if (ifr.ifr_flags & IFF_UP) { oldflags = ifr.ifr_flags; ifr.ifr_flags &= ~IFF_UP; if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) oldflags = 0; /* didn't set, don't restore */ } } /* * Now restore the mode. */ strncpy(ireq.ifr_ifrn.ifrn_name, handle->md.device, sizeof ireq.ifr_ifrn.ifrn_name); ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0; ireq.u.mode = handle->md.oldmode; if (ioctl(handle->fd, SIOCSIWMODE, &ireq) == -1) { /* * Scientist, you've failed. */ fprintf(stderr, "Can't restore interface %s wireless mode (SIOCSIWMODE failed: %s).\n" "Please adjust manually.\n", handle->md.device, strerror(errno)); } /* * Now bring the interface back up if we brought * it down. */ if (oldflags != 0) { ifr.ifr_flags = oldflags; if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) { fprintf(stderr, "Can't bring interface %s back up (SIOCSIFFLAGS failed: %s).\n" "Please adjust manually.\n", handle->md.device, strerror(errno)); } } } #endif /* IW_MODE_MONITOR */ /* * Take this pcap out of the list of pcaps for which we * have to take the interface out of some mode. */ pcap_remove_from_pcaps_to_close(handle); } if (handle->md.mondevice != NULL) { free(handle->md.mondevice); handle->md.mondevice = NULL; } if (handle->md.device != NULL) { free(handle->md.device); handle->md.device = NULL; } pcap_cleanup_live_common(handle); } /* * Get a handle for a live capture from the given device. You can * pass NULL as device to get all packages (without link level * information of course). If you pass 1 as promisc the interface * will be set to promiscous mode (XXX: I think this usage should * be deprecated and functions be added to select that later allow * modification of that values -- Torsten). */ static int pcap_activate_linux(pcap_t *handle) { const char *device; int status = 0; device = handle->opt.source; handle->inject_op = pcap_inject_linux; handle->setfilter_op = pcap_setfilter_linux; handle->setdirection_op = pcap_setdirection_linux; handle->set_datalink_op = NULL; /* can't change data link type */ handle->getnonblock_op = pcap_getnonblock_fd; handle->setnonblock_op = pcap_setnonblock_fd; handle->cleanup_op = pcap_cleanup_linux; handle->read_op = pcap_read_linux; handle->stats_op = pcap_stats_linux; /* * The "any" device is a special device which causes us not * to bind to a particular device and thus to look at all * devices. */ if (strcmp(device, "any") == 0) { if (handle->opt.promisc) { handle->opt.promisc = 0; /* Just a warning. */ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Promiscuous mode not supported on the \"any\" device"); status = PCAP_WARNING_PROMISC_NOTSUP; } } handle->md.device = strdup(device); if (handle->md.device == NULL) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s", pcap_strerror(errno) ); return PCAP_ERROR; } /* * If we're in promiscuous mode, then we probably want * to see when the interface drops packets too, so get an * initial count from /proc/net/dev */ if (handle->opt.promisc) handle->md.proc_dropped = linux_if_drops(handle->md.device); /* * Current Linux kernels use the protocol family PF_PACKET to * allow direct access to all packets on the network while * older kernels had a special socket type SOCK_PACKET to * implement this feature. * While this old implementation is kind of obsolete we need * to be compatible with older kernels for a while so we are * trying both methods with the newer method preferred. */ status = activate_new(handle); if (status < 0) { /* * Fatal error with the new way; just fail. * status has the error return; if it's PCAP_ERROR, * handle->errbuf has been set appropriately. */ goto fail; } if (status == 1) { /* * Success. * Try to use memory-mapped access. */ switch (activate_mmap(handle, &status)) { case 1: /* * We succeeded. status has been * set to the status to return, * which might be 0, or might be * a PCAP_WARNING_ value. */ return status; case 0: /* * Kernel doesn't support it - just continue * with non-memory-mapped access. */ break; case -1: /* * We failed to set up to use it, or the kernel * supports it, but we failed to enable it. * status has been set to the error status to * return and, if it's PCAP_ERROR, handle->errbuf * contains the error message. */ goto fail; } } else if (status == 0) { /* Non-fatal error; try old way */ if ((status = activate_old(handle)) != 1) { /* * Both methods to open the packet socket failed. * Tidy up and report our failure (handle->errbuf * is expected to be set by the functions above). */ goto fail; } } /* * We set up the socket, but not with memory-mapped access. */ status = 0; if (handle->opt.buffer_size != 0) { /* * Set the socket buffer size to the specified value. */ if (setsockopt(handle->fd, SOL_SOCKET, SO_RCVBUF, &handle->opt.buffer_size, sizeof(handle->opt.buffer_size)) == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "SO_RCVBUF: %s", pcap_strerror(errno)); status = PCAP_ERROR; goto fail; } } /* Allocate the buffer */ handle->buffer = malloc(handle->bufsize + handle->offset); if (!handle->buffer) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); status = PCAP_ERROR; goto fail; } /* * "handle->fd" is a socket, so "select()" and "poll()" * should work on it. */ handle->selectable_fd = handle->fd; return status; fail: pcap_cleanup_linux(handle); return status; } /* * Read at most max_packets from the capture stream and call the callback * for each of them. Returns the number of packets handled or -1 if an * error occured. */ static int pcap_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) { /* * Currently, on Linux only one packet is delivered per read, * so we don't loop. */ return pcap_read_packet(handle, callback, user); } /* * Read a packet from the socket calling the handler provided by * the user. Returns the number of packets received or -1 if an * error occured. */ 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; struct sll_header *hdrp; #else struct sockaddr from; #endif #if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) struct iovec iov; struct msghdr msg; struct cmsghdr *cmsg; union { struct cmsghdr cmsg; char buf[CMSG_SPACE(sizeof(struct tpacket_auxdata))]; } cmsg_buf; #else /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */ socklen_t fromlen; #endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */ int packet_len, caplen; struct pcap_pkthdr pcap_header; #ifdef HAVE_PF_PACKET_SOCKETS /* * If this is a cooked device, leave extra room for a * fake packet header. */ if (handle->md.cooked) offset = SLL_HDR_LEN; else offset = 0; #else /* * This system doesn't have PF_PACKET sockets, so it doesn't * support cooked devices. */ offset = 0; #endif /* * Receive a single packet from the kernel. * We ignore EINTR, as that might just be due to a signal * being delivered - if the signal should interrupt the * loop, the signal handler should call pcap_breakloop() * to set handle->break_loop (we ignore it on other * platforms as well). * We also ignore ENETDOWN, so that we can continue to * capture traffic if the interface goes down and comes * back up again; comments in the kernel indicate that * we'll just block waiting for packets if we try to * receive from a socket that delivered ENETDOWN, and, * if we're using a memory-mapped buffer, we won't even * get notified of "network down" events. */ bp = handle->buffer + handle->offset; #if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) msg.msg_name = &from; msg.msg_namelen = sizeof(from); msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = &cmsg_buf; msg.msg_controllen = sizeof(cmsg_buf); msg.msg_flags = 0; iov.iov_len = handle->bufsize - offset; iov.iov_base = bp + offset; #endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */ do { /* * Has "pcap_breakloop()" been called? */ if (handle->break_loop) { /* * Yes - clear the flag that indicates that it has, * and return PCAP_ERROR_BREAK as an indication that * we were told to break out of the loop. */ handle->break_loop = 0; return PCAP_ERROR_BREAK; } #if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) packet_len = recvmsg(handle->fd, &msg, MSG_TRUNC); #else /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */ fromlen = sizeof(from); packet_len = recvfrom( handle->fd, bp + offset, handle->bufsize - offset, MSG_TRUNC, (struct sockaddr *) &from, &fromlen); #endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */ } while (packet_len == -1 && errno == EINTR); /* Check if an error occured */ if (packet_len == -1) { switch (errno) { case EAGAIN: return 0; /* no packet there */ case ENETDOWN: /* * The device on which we're capturing went away. * * XXX - we should really return * PCAP_ERROR_IFACE_NOT_UP, but pcap_dispatch() * etc. aren't defined to return that. */ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "The interface went down"); return PCAP_ERROR; default: snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "recvfrom: %s", pcap_strerror(errno)); return PCAP_ERROR; } } #ifdef HAVE_PF_PACKET_SOCKETS if (!handle->md.sock_packet) { /* * Unfortunately, there is a window between socket() and * bind() where the kernel may queue packets from any * interface. If we're bound to a particular interface, * discard packets not from that interface. * * (If socket filters are supported, we could do the * same thing we do when changing the filter; however, * that won't handle packet sockets without socket * filter support, and it's a bit more complicated. * It would save some instructions per packet, however.) */ if (handle->md.ifindex != -1 && from.sll_ifindex != handle->md.ifindex) return 0; /* * Do checks based on packet direction. * We can only do this if we're using PF_PACKET; the * address returned for SOCK_PACKET is a "sockaddr_pkt" * which lacks the relevant packet type information. */ if (from.sll_pkttype == PACKET_OUTGOING) { /* * Outgoing packet. * If this is from the loopback device, reject it; * we'll see the packet as an incoming packet as well, * and we don't want to see it twice. */ if (from.sll_ifindex == handle->md.lo_ifindex) return 0; /* * If the user only wants incoming packets, reject it. */ if (handle->direction == PCAP_D_IN) return 0; } else { /* * Incoming packet. * If the user only wants outgoing packets, reject it. */ if (handle->direction == PCAP_D_OUT) return 0; } } #endif #ifdef HAVE_PF_PACKET_SOCKETS /* * If this is a cooked device, fill in the fake packet header. */ if (handle->md.cooked) { /* * Add the length of the fake header to the length * of packet data we read. */ packet_len += SLL_HDR_LEN; hdrp = (struct sll_header *)bp; hdrp->sll_pkttype = map_packet_type_to_sll_type(from.sll_pkttype); hdrp->sll_hatype = htons(from.sll_hatype); hdrp->sll_halen = htons(from.sll_halen); memcpy(hdrp->sll_addr, from.sll_addr, (from.sll_halen > SLL_ADDRLEN) ? SLL_ADDRLEN : from.sll_halen); hdrp->sll_protocol = from.sll_protocol; } #if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) - for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { - struct tpacket_auxdata *aux; - unsigned int len; - struct vlan_tag *tag; + if (handle->md.vlan_offset != -1) { + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { + struct tpacket_auxdata *aux; + unsigned int len; + struct vlan_tag *tag; - if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct tpacket_auxdata)) || - cmsg->cmsg_level != SOL_PACKET || - cmsg->cmsg_type != PACKET_AUXDATA) - continue; + if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct tpacket_auxdata)) || + cmsg->cmsg_level != SOL_PACKET || + cmsg->cmsg_type != PACKET_AUXDATA) + continue; - aux = (struct tpacket_auxdata *)CMSG_DATA(cmsg); - if (aux->tp_vlan_tci == 0) - continue; + aux = (struct tpacket_auxdata *)CMSG_DATA(cmsg); +#if defined(TP_STATUS_VLAN_VALID) + if ((aux->tp_vlan_tci == 0) && !(aux->tp_status & TP_STATUS_VLAN_VALID)) +#else + if (aux->tp_vlan_tci == 0) /* this is ambigious but without the + TP_STATUS_VLAN_VALID flag, there is + nothing that we can do */ +#endif + continue; - len = packet_len > iov.iov_len ? iov.iov_len : packet_len; - if (len < 2 * ETH_ALEN) - break; + len = packet_len > iov.iov_len ? iov.iov_len : packet_len; + if (len < (unsigned int) handle->md.vlan_offset) + break; - bp -= VLAN_TAG_LEN; - memmove(bp, bp + VLAN_TAG_LEN, 2 * ETH_ALEN); + bp -= VLAN_TAG_LEN; + memmove(bp, bp + VLAN_TAG_LEN, handle->md.vlan_offset); - tag = (struct vlan_tag *)(bp + 2 * ETH_ALEN); - tag->vlan_tpid = htons(ETH_P_8021Q); - tag->vlan_tci = htons(aux->tp_vlan_tci); + tag = (struct vlan_tag *)(bp + handle->md.vlan_offset); + tag->vlan_tpid = htons(ETH_P_8021Q); + tag->vlan_tci = htons(aux->tp_vlan_tci); - packet_len += VLAN_TAG_LEN; + packet_len += VLAN_TAG_LEN; + } } #endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */ #endif /* HAVE_PF_PACKET_SOCKETS */ /* * XXX: According to the kernel source we should get the real * packet len if calling recvfrom with MSG_TRUNC set. It does * not seem to work here :(, but it is supported by this code * anyway. * To be honest the code RELIES on that feature so this is really * broken with 2.2.x kernels. * I spend a day to figure out what's going on and I found out * that the following is happening: * * The packet comes from a random interface and the packet_rcv * hook is called with a clone of the packet. That code inserts * the packet into the receive queue of the packet socket. * If a filter is attached to that socket that filter is run * first - and there lies the problem. The default filter always * cuts the packet at the snaplen: * * # tcpdump -d * (000) ret #68 * * So the packet filter cuts down the packet. The recvfrom call * says "hey, it's only 68 bytes, it fits into the buffer" with * the result that we don't get the real packet length. This * is valid at least until kernel 2.2.17pre6. * * We currently handle this by making a copy of the filter * program, fixing all "ret" instructions with non-zero * operands to have an operand of 65535 so that the filter * doesn't truncate the packet, and supplying that modified * filter to the kernel. */ caplen = packet_len; if (caplen > handle->snapshot) caplen = handle->snapshot; /* 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, bp, packet_len, caplen) == 0) { /* rejected by filter */ return 0; } } /* Fill in our own header data */ if (ioctl(handle->fd, SIOCGSTAMP, &pcap_header.ts) == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "SIOCGSTAMP: %s", pcap_strerror(errno)); return PCAP_ERROR; } pcap_header.caplen = caplen; pcap_header.len = packet_len; /* * 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. * * We keep the count in "md.packets_read", and use that for * "ps_recv" if we can't get the statistics from the kernel. * We do that because, if we *can* get the statistics from * the kernel, we use "md.stat.ps_recv" and "md.stat.ps_drop" * as running counts, as reading the statistics from the * kernel resets the kernel statistics, and if we directly * increment "md.stat.ps_recv" here, that means it will * count packets *twice* on systems where we can get kernel * statistics - once here, and once in pcap_stats_linux(). */ handle->md.packets_read++; /* Call the user supplied callback function */ callback(userdata, &pcap_header, bp); return 1; } static int pcap_inject_linux(pcap_t *handle, const void *buf, size_t size) { int ret; #ifdef HAVE_PF_PACKET_SOCKETS if (!handle->md.sock_packet) { /* PF_PACKET socket */ if (handle->md.ifindex == -1) { /* * We don't support sending on the "any" device. */ strlcpy(handle->errbuf, "Sending packets isn't supported on the \"any\" device", PCAP_ERRBUF_SIZE); return (-1); } if (handle->md.cooked) { /* * We don't support sending on the "any" device. * * XXX - how do you send on a bound cooked-mode * socket? * Is a "sendto()" required there? */ strlcpy(handle->errbuf, "Sending packets isn't supported in cooked mode", PCAP_ERRBUF_SIZE); return (-1); } } #endif ret = send(handle->fd, buf, size, 0); if (ret == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "send: %s", pcap_strerror(errno)); return (-1); } return (ret); } /* * Get the statistics for the given packet capture handle. * Reports the number of dropped packets iff the kernel supports * 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. */ static int pcap_stats_linux(pcap_t *handle, struct pcap_stat *stats) { #ifdef HAVE_TPACKET_STATS struct tpacket_stats kstats; socklen_t len = sizeof (struct tpacket_stats); #endif long if_dropped = 0; /* * To fill in ps_ifdrop, we parse /proc/net/dev for the number */ if (handle->opt.promisc) { if_dropped = handle->md.proc_dropped; handle->md.proc_dropped = linux_if_drops(handle->md.device); handle->md.stat.ps_ifdrop += (handle->md.proc_dropped - if_dropped); } #ifdef HAVE_TPACKET_STATS /* * Try to get the packet counts from the kernel. */ if (getsockopt(handle->fd, SOL_PACKET, PACKET_STATISTICS, &kstats, &len) > -1) { /* * 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. * * See above for ps_ifdrop. * * Both statistics include packets not yet read from * the kernel by libpcap, and thus not yet seen by * the application. * * 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. * * Keep a running total because each call to * getsockopt(handle->fd, SOL_PACKET, PACKET_STATISTICS, .... * resets the counters to zero. */ handle->md.stat.ps_recv += kstats.tp_packets; handle->md.stat.ps_drop += kstats.tp_drops; *stats = handle->md.stat; return 0; } 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 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_ifdrop" is supported. It will return the number * of drops the interface reports in /proc/net/dev, * if that is available. * * "ps_recv" doesn't include packets not yet read from * the kernel by libpcap. * * We maintain the count of packets processed by libpcap in * "md.packets_read", for reasons described in the comment * at the end of pcap_read_packet(). We have no idea how many * packets were dropped by the kernel buffers -- but we know * how many the interface dropped, so we can return that. */ stats->ps_recv = handle->md.packets_read; stats->ps_drop = 0; stats->ps_ifdrop = handle->md.stat.ps_ifdrop; return 0; } /* * Get from "/sys/class/net" 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 "/sys/class/net"; we just leave * the list of interfaces as is, and return 0, so that we can try * scanning /proc/net/dev. */ static int scan_sys_class_net(pcap_if_t **devlistp, char *errbuf) { DIR *sys_class_net_d; int fd; struct dirent *ent; + char subsystem_path[PATH_MAX+1]; + struct stat statb; char *p; char name[512]; /* XXX - pick a size */ char *q, *saveq; struct ifreq ifrflags; int ret = 1; sys_class_net_d = opendir("/sys/class/net"); if (sys_class_net_d == NULL) { /* * Don't fail if it doesn't exist at all. */ if (errno == ENOENT) return (0); /* * Fail if we got some other error. */ (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "Can't open /sys/class/net: %s", pcap_strerror(errno)); return (-1); } /* * Create a socket from which to fetch interface information. */ fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s", pcap_strerror(errno)); (void)closedir(sys_class_net_d); return (-1); } for (;;) { errno = 0; ent = readdir(sys_class_net_d); if (ent == NULL) { /* * Error or EOF; if errno != 0, it's an error. */ break; } /* - * Ignore directories (".", "..", and any subdirectories). + * Ignore "." and "..". */ - if (ent->d_type == DT_DIR) + if (strcmp(ent->d_name, ".") == 0 || + strcmp(ent->d_name, "..") == 0) continue; /* + * Ignore plain files; they do not have subdirectories + * and thus have no attributes. + */ + if (ent->d_type == DT_REG) + continue; + + /* + * Is there an "ifindex" file under that name? + * (We don't care whether it's a directory or + * a symlink; older kernels have directories + * for devices, newer kernels have symlinks to + * directories.) + */ + snprintf(subsystem_path, sizeof subsystem_path, + "/sys/class/net/%s/ifindex", ent->d_name); + if (lstat(subsystem_path, &statb) != 0) { + /* + * Stat failed. Either there was an error + * other than ENOENT, and we don't know if + * this is an interface, or it's ENOENT, + * and either some part of "/sys/class/net/{if}" + * disappeared, in which case it probably means + * the interface disappeared, or there's no + * "ifindex" file, which means it's not a + * network interface. + */ + continue; + } + + /* * Get the interface name. */ p = &ent->d_name[0]; q = &name[0]; while (*p != '\0' && isascii(*p) && !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 (isascii(*p) && 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 || errno == ENODEV) 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 directory? */ if (errno != 0) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error reading /sys/class/net: %s", pcap_strerror(errno)); ret = -1; } } (void)close(fd); (void)closedir(sys_class_net_d); return (ret); } /* * 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. * * See comments from scan_sys_class_net(). */ static int scan_proc_net_dev(pcap_if_t **devlistp, char *errbuf) { FILE *proc_net_f; int fd; char linebuf[512]; int linenum; 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) { /* * Don't fail if it doesn't exist at all. */ if (errno == ENOENT) return (0); /* * Fail if we got some other error. */ (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "Can't open /proc/net/dev: %s", pcap_strerror(errno)); return (-1); } /* * Create a socket from which to fetch interface information. */ fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s", pcap_strerror(errno)); (void)fclose(proc_net_f); return (-1); } 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' && isascii(*p) && isspace(*p)) p++; if (*p == '\0' || *p == '\n') continue; /* blank line */ /* * Get the interface name. */ q = &name[0]; while (*p != '\0' && isascii(*p) && !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 (isascii(*p) && 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)close(fd); (void)fclose(proc_net_f); return (ret); } /* * Description string for the "any" device. */ static const char any_descr[] = "Pseudo-device that captures on all interfaces"; int pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) { int ret; /* * Read "/sys/class/net", 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, * and even getifaddrs() won't return information about * interfaces with no addresses, so you need to read "/sys/class/net" * to get the names of the rest of the interfaces. */ ret = scan_sys_class_net(alldevsp, errbuf); if (ret == -1) return (-1); /* failed */ if (ret == 0) { /* * No /sys/class/net; try reading /proc/net/dev instead. */ if (scan_proc_net_dev(alldevsp, errbuf) == -1) return (-1); } /* * Add the "any" device. */ if (pcap_add_if(alldevsp, "any", 0, any_descr, errbuf) < 0) return (-1); -#ifdef HAVE_DAG_API - /* - * Add DAG devices. - */ - if (dag_platform_finddevs(alldevsp, errbuf) < 0) - return (-1); -#endif /* HAVE_DAG_API */ - -#ifdef HAVE_SEPTEL_API - /* - * Add Septel devices. - */ - if (septel_platform_finddevs(alldevsp, errbuf) < 0) - return (-1); -#endif /* HAVE_SEPTEL_API */ - -#ifdef HAVE_SNF_API - if (snf_platform_finddevs(alldevsp, errbuf) < 0) - return (-1); -#endif /* HAVE_SNF_API */ - -#ifdef PCAP_SUPPORT_BT - /* - * Add Bluetooth devices. - */ - if (bt_platform_finddevs(alldevsp, errbuf) < 0) - return (-1); -#endif - -#ifdef PCAP_SUPPORT_USB - /* - * Add USB devices. - */ - if (usb_platform_finddevs(alldevsp, errbuf) < 0) - return (-1); -#endif - -#ifdef PCAP_SUPPORT_NETFILTER - /* - * Add netfilter devices. - */ - if (netfilter_platform_finddevs(alldevsp, errbuf) < 0) - return (-1); -#endif - -#if PCAP_SUPPORT_CANUSB - if (canusb_platform_finddevs(alldevsp, errbuf) < 0) - return (-1); -#endif - return (0); } /* * Attach the given BPF code to the packet capture device. */ static int pcap_setfilter_linux_common(pcap_t *handle, struct bpf_program *filter, int is_mmapped) { #ifdef SO_ATTACH_FILTER struct sock_fprog fcode; int can_filter_in_kernel; int err = 0; #endif if (!handle) return -1; if (!filter) { strncpy(handle->errbuf, "setfilter: No filter specified", PCAP_ERRBUF_SIZE); return -1; } /* Make our private copy of the filter */ if (install_bpf_program(handle, filter) < 0) /* install_bpf_program() filled in errbuf */ return -1; /* * Run user level packet filter by default. Will be overriden if * installing a kernel filter succeeds. */ handle->md.use_bpf = 0; /* Install kernel level filter if possible */ #ifdef SO_ATTACH_FILTER #ifdef USHRT_MAX if (handle->fcode.bf_len > USHRT_MAX) { /* * fcode.len is an unsigned short for current kernel. * I have yet to see BPF-Code with that much * instructions but still it is possible. So for the * sake of correctness I added this check. */ fprintf(stderr, "Warning: Filter too complex for kernel\n"); fcode.len = 0; fcode.filter = NULL; can_filter_in_kernel = 0; } else #endif /* USHRT_MAX */ { /* * Oh joy, the Linux kernel uses struct sock_fprog instead * of struct bpf_program and of course the length field is * of different size. Pointed out by Sebastian * * Oh, and we also need to fix it up so that all "ret" * instructions with non-zero operands have 65535 as the * operand if we're not capturing in memory-mapped modee, * and so that, if we're in cooked mode, all memory-reference * instructions use special magic offsets in references to * the link-layer header and assume that the link-layer * payload begins at 0; "fix_program()" will do that. */ switch (fix_program(handle, &fcode, is_mmapped)) { case -1: default: /* * Fatal error; just quit. * (The "default" case shouldn't happen; we * return -1 for that reason.) */ return -1; case 0: /* * The program performed checks that we can't make * work in the kernel. */ can_filter_in_kernel = 0; break; case 1: /* * We have a filter that'll work in the kernel. */ can_filter_in_kernel = 1; break; } } /* * NOTE: at this point, we've set both the "len" and "filter" * fields of "fcode". As of the 2.6.32.4 kernel, at least, * those are the only members of the "sock_fprog" structure, * so we initialize every member of that structure. * * If there is anything in "fcode" that is not initialized, * it is either a field added in a later kernel, or it's * padding. * * If a new field is added, this code needs to be updated * to set it correctly. * * If there are no other fields, then: * * if the Linux kernel looks at the padding, it's * buggy; * * if the Linux kernel doesn't look at the padding, * then if some tool complains that we're passing * uninitialized data to the kernel, then the tool * is buggy and needs to understand that it's just * padding. */ if (can_filter_in_kernel) { if ((err = set_kernel_filter(handle, &fcode)) == 0) { /* Installation succeded - using kernel filter. */ handle->md.use_bpf = 1; } else if (err == -1) /* Non-fatal error */ { /* * Print a warning if we weren't able to install * the filter for a reason other than "this kernel * isn't configured to support socket filters. */ if (errno != ENOPROTOOPT && errno != EOPNOTSUPP) { fprintf(stderr, "Warning: Kernel filter failed: %s\n", pcap_strerror(errno)); } } } /* * 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()". */ if (fcode.filter != NULL) free(fcode.filter); if (err == -2) /* Fatal error */ return -1; #endif /* SO_ATTACH_FILTER */ return 0; } static int pcap_setfilter_linux(pcap_t *handle, struct bpf_program *filter) { return pcap_setfilter_linux_common(handle, filter, 0); } /* * Set direction flag: Which packets do we accept on a forwarding * single device? IN, OUT or both? */ static int pcap_setdirection_linux(pcap_t *handle, pcap_direction_t d) { #ifdef HAVE_PF_PACKET_SOCKETS if (!handle->md.sock_packet) { handle->direction = d; return 0; } #endif /* * We're not using PF_PACKET sockets, so we can't determine * the direction of the packet. */ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Setting direction is not supported on SOCK_PACKET sockets"); return -1; } #ifdef HAVE_PF_PACKET_SOCKETS /* * Map the PACKET_ value to a LINUX_SLL_ value; we * want the same numerical value to be used in * the link-layer header even if the numerical values * for the PACKET_ #defines change, so that programs * that look at the packet type field will always be * able to handle DLT_LINUX_SLL captures. */ static short int map_packet_type_to_sll_type(short int sll_pkttype) { switch (sll_pkttype) { case PACKET_HOST: return htons(LINUX_SLL_HOST); case PACKET_BROADCAST: return htons(LINUX_SLL_BROADCAST); case PACKET_MULTICAST: return htons(LINUX_SLL_MULTICAST); case PACKET_OTHERHOST: return htons(LINUX_SLL_OTHERHOST); case PACKET_OUTGOING: return htons(LINUX_SLL_OUTGOING); default: return -1; } } #endif /* * Linux uses the ARP hardware type to identify the type of an * interface. pcap uses the DLT_xxx constants for this. This * 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.) * * If "cooked_ok" is non-zero, we can use DLT_LINUX_SLL and capture * in cooked mode; otherwise, we can't use cooked mode, so we have * to pick some type that works in raw mode, or fail. * * Sets the link type to -1 if unable to map the type. */ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, int cooked_ok) { switch (arptype) { case ARPHRD_ETHER: /* * This is (presumably) a real Ethernet capture; give it a * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so * that an application can let you choose it, in case you're * capturing DOCSIS traffic that a Cisco Cable Modem * Termination System is putting out onto an Ethernet (it * doesn't put an Ethernet header onto the wire, it puts raw * DOCSIS frames out on the wire inside the low-level * Ethernet framing). * * XXX - are there any sorts of "fake Ethernet" that have * ARPHRD_ETHER but that *shouldn't offer DLT_DOCSIS as * a Cisco CMTS won't put traffic onto it or get traffic * bridged onto it? ISDN is handled in "activate_new()", * as we fall back on cooked mode there; are there any * others? */ handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); /* * If that fails, just leave the list empty. */ if (handle->dlt_list != NULL) { handle->dlt_list[0] = DLT_EN10MB; handle->dlt_list[1] = DLT_DOCSIS; handle->dlt_count = 2; } /* FALLTHROUGH */ case ARPHRD_METRICOM: case ARPHRD_LOOPBACK: handle->linktype = DLT_EN10MB; handle->offset = 2; break; case ARPHRD_EETHER: handle->linktype = DLT_EN3MB; break; case ARPHRD_AX25: handle->linktype = DLT_AX25_KISS; break; case ARPHRD_PRONET: handle->linktype = DLT_PRONET; break; case ARPHRD_CHAOS: handle->linktype = DLT_CHAOS; break; #ifndef ARPHRD_CAN #define ARPHRD_CAN 280 #endif case ARPHRD_CAN: handle->linktype = DLT_CAN_SOCKETCAN; break; #ifndef ARPHRD_IEEE802_TR #define ARPHRD_IEEE802_TR 800 /* From Linux 2.4 */ #endif case ARPHRD_IEEE802_TR: case ARPHRD_IEEE802: handle->linktype = DLT_IEEE802; handle->offset = 2; break; case ARPHRD_ARCNET: handle->linktype = DLT_ARCNET_LINUX; break; #ifndef ARPHRD_FDDI /* From Linux 2.2.13 */ #define ARPHRD_FDDI 774 #endif 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: /* * 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, if we can. * Otherwise, we'll just fail. */ if (cooked_ok) handle->linktype = DLT_LINUX_SLL; else handle->linktype = -1; break; #ifndef ARPHRD_IEEE80211 /* From Linux 2.4.6 */ #define ARPHRD_IEEE80211 801 #endif case ARPHRD_IEEE80211: handle->linktype = DLT_IEEE802_11; break; #ifndef ARPHRD_IEEE80211_PRISM /* From Linux 2.4.18 */ #define ARPHRD_IEEE80211_PRISM 802 #endif case ARPHRD_IEEE80211_PRISM: handle->linktype = DLT_PRISM_HEADER; break; #ifndef ARPHRD_IEEE80211_RADIOTAP /* new */ #define ARPHRD_IEEE80211_RADIOTAP 803 #endif case ARPHRD_IEEE80211_RADIOTAP: handle->linktype = DLT_IEEE802_11_RADIO; 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, if we can; otherwise, we just treat * it as DLT_RAW, for now - if somebody needs to capture, * on a 2.0[.x] kernel, on PPP devices that supply a * link-layer header, they'll have to add code here to * map to the appropriate DLT_ type (possibly adding a * new DLT_ type, if necessary). */ if (cooked_ok) handle->linktype = DLT_LINUX_SLL; else { /* * XXX - handle ISDN types here? We can't fall * back on cooked sockets, so we'd have to * figure out from the device name what type of * link-layer encapsulation it's using, and map * that to an appropriate DLT_ value, meaning * we'd map "isdnN" devices to DLT_RAW (they * supply raw IP packets with no link-layer * header) and "isdY" devices to a new DLT_I4L_IP * type that has only an Ethernet packet type as * a link-layer header. * * But sometimes we seem to get random crap * in the link-layer header when capturing on * ISDN devices.... */ handle->linktype = DLT_RAW; } break; #ifndef ARPHRD_CISCO #define ARPHRD_CISCO 513 /* previously ARPHRD_HDLC */ #endif case ARPHRD_CISCO: handle->linktype = DLT_C_HDLC; break; /* Not sure if this is correct for all tunnels, but it * works for CIPE */ case ARPHRD_TUNNEL: #ifndef ARPHRD_SIT #define ARPHRD_SIT 776 /* From Linux 2.2.13 */ #endif case ARPHRD_SIT: case ARPHRD_CSLIP: case ARPHRD_SLIP6: case ARPHRD_CSLIP6: case ARPHRD_ADAPT: case ARPHRD_SLIP: #ifndef ARPHRD_RAWHDLC #define ARPHRD_RAWHDLC 518 #endif case ARPHRD_RAWHDLC: #ifndef ARPHRD_DLCI #define ARPHRD_DLCI 15 #endif case ARPHRD_DLCI: /* * 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; #ifndef ARPHRD_FRAD #define ARPHRD_FRAD 770 #endif case ARPHRD_FRAD: handle->linktype = DLT_FRELAY; break; case ARPHRD_LOCALTLK: handle->linktype = DLT_LTALK; break; #ifndef ARPHRD_FCPP #define ARPHRD_FCPP 784 #endif case ARPHRD_FCPP: #ifndef ARPHRD_FCAL #define ARPHRD_FCAL 785 #endif case ARPHRD_FCAL: #ifndef ARPHRD_FCPL #define ARPHRD_FCPL 786 #endif case ARPHRD_FCPL: #ifndef ARPHRD_FCFABRIC #define ARPHRD_FCFABRIC 787 #endif case ARPHRD_FCFABRIC: /* * We assume that those all mean RFC 2625 IP-over- * Fibre Channel, with the RFC 2625 header at * the beginning of the packet. */ handle->linktype = DLT_IP_OVER_FC; break; #ifndef ARPHRD_IRDA #define ARPHRD_IRDA 783 #endif case ARPHRD_IRDA: /* Don't expect IP packet out of this interfaces... */ handle->linktype = DLT_LINUX_IRDA; /* We need to save packet direction for IrDA decoding, * so let's use "Linux-cooked" mode. Jean II */ //handle->md.cooked = 1; break; /* ARPHRD_LAPD is unofficial and randomly allocated, if reallocation * is needed, please report it to */ #ifndef ARPHRD_LAPD #define ARPHRD_LAPD 8445 #endif case ARPHRD_LAPD: /* Don't expect IP packet out of this interfaces... */ handle->linktype = DLT_LINUX_LAPD; break; #ifndef ARPHRD_NONE #define ARPHRD_NONE 0xFFFE #endif case ARPHRD_NONE: /* * No link-layer header; packets are just IP * packets, so use DLT_RAW. */ handle->linktype = DLT_RAW; break; #ifndef ARPHRD_IEEE802154 #define ARPHRD_IEEE802154 804 #endif case ARPHRD_IEEE802154: handle->linktype = DLT_IEEE802_15_4_NOFCS; break; default: handle->linktype = -1; break; } } /* ===== Functions to interface to the newer kernels ================== */ /* * Try to open a packet socket using the new kernel PF_PACKET interface. * Returns 1 on success, 0 on an error that means the new interface isn't * present (so the old SOCK_PACKET interface should be tried), and a * PCAP_ERROR_ value on an error that means that the old mechanism won't * work either (so it shouldn't be tried). */ static int activate_new(pcap_t *handle) { #ifdef HAVE_PF_PACKET_SOCKETS const char *device = handle->opt.source; int is_any_device = (strcmp(device, "any") == 0); int sock_fd = -1, arptype; #ifdef HAVE_PACKET_AUXDATA int val; #endif int err = 0; struct packet_mreq mr; /* * Open a socket with protocol family packet. If the * "any" device was specified, we open a SOCK_DGRAM * socket for the cooked interface, otherwise we first * try a SOCK_RAW socket for the raw interface. */ sock_fd = is_any_device ? socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL)) : socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (sock_fd == -1) { if (errno == EINVAL || errno == EAFNOSUPPORT) { /* * We don't support PF_PACKET/SOCK_whatever * sockets; try the old mechanism. */ return 0; } snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "socket: %s", pcap_strerror(errno) ); if (errno == EPERM || errno == EACCES) { /* * You don't have permission to open the * socket. */ return PCAP_ERROR_PERM_DENIED; } else { /* * Other error. */ return PCAP_ERROR; } } /* It seems the kernel supports the new interface. */ handle->md.sock_packet = 0; /* * Get the interface index of the loopback device. * If the attempt fails, don't fail, just set the * "md.lo_ifindex" to -1. * * XXX - can there be more than one device that loops * packets back, i.e. devices other than "lo"? If so, * we'd need to find them all, and have an array of * indices for them, and check all of them in * "pcap_read_packet()". */ handle->md.lo_ifindex = iface_get_id(sock_fd, "lo", handle->errbuf); /* * 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 * or a type we know doesn't work well in raw mode. */ if (!is_any_device) { /* Assume for now we don't need cooked mode. */ handle->md.cooked = 0; if (handle->opt.rfmon) { /* * We were asked to turn on monitor mode. * Do so before we get the link-layer type, * because entering monitor mode could change * the link-layer type. */ err = enter_rfmon_mode(handle, sock_fd, device); if (err < 0) { /* Hard failure */ close(sock_fd); return err; } if (err == 0) { /* * Nothing worked for turning monitor mode * on. */ close(sock_fd); return PCAP_ERROR_RFMON_NOTSUP; } /* * Either monitor mode has been turned on for * the device, or we've been given a different * device to open for monitor mode. If we've * been given a different device, use it. */ if (handle->md.mondevice != NULL) device = handle->md.mondevice; } arptype = iface_get_arptype(sock_fd, device, handle->errbuf); if (arptype < 0) { close(sock_fd); return arptype; } map_arphrd_to_dlt(handle, arptype, 1); if (handle->linktype == -1 || handle->linktype == DLT_LINUX_SLL || handle->linktype == DLT_LINUX_IRDA || handle->linktype == DLT_LINUX_LAPD || (handle->linktype == DLT_EN10MB && (strncmp("isdn", device, 4) == 0 || strncmp("isdY", device, 4) == 0))) { /* * 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. */ if (close(sock_fd) == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "close: %s", pcap_strerror(errno)); return PCAP_ERROR; } sock_fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL)); if (sock_fd == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "socket: %s", pcap_strerror(errno)); if (errno == EPERM || errno == EACCES) { /* * You don't have permission to * open the socket. */ return PCAP_ERROR_PERM_DENIED; } else { /* * Other error. */ return PCAP_ERROR; } } handle->md.cooked = 1; /* * Get rid of any link-layer type list * we allocated - this only supports cooked * capture. */ if (handle->dlt_list != NULL) { free(handle->dlt_list); handle->dlt_list = NULL; handle->dlt_count = 0; } if (handle->linktype == -1) { /* * Warn that we're falling back on * cooked mode; we may want to * update "map_arphrd_to_dlt()" * to handle the new type. */ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "arptype %d not " "supported by libpcap - " "falling back to cooked " "socket", arptype); } /* * IrDA capture is not a real "cooked" capture, * it's IrLAP frames, not IP packets. The * same applies to LAPD capture. */ if (handle->linktype != DLT_LINUX_IRDA && handle->linktype != DLT_LINUX_LAPD) handle->linktype = DLT_LINUX_SLL; } handle->md.ifindex = iface_get_id(sock_fd, device, handle->errbuf); if (handle->md.ifindex == -1) { close(sock_fd); return PCAP_ERROR; } if ((err = iface_bind(sock_fd, handle->md.ifindex, handle->errbuf)) != 1) { close(sock_fd); if (err < 0) return err; else return 0; /* try old mechanism */ } } else { /* * The "any" device. */ if (handle->opt.rfmon) { /* * It doesn't support monitor mode. */ return PCAP_ERROR_RFMON_NOTSUP; } /* * It uses cooked mode. */ handle->md.cooked = 1; handle->linktype = DLT_LINUX_SLL; /* * We're not bound to a device. * For now, we're using this as an indication * that we can't transmit; stop doing that only * if we figure out how to transmit in cooked * mode. */ handle->md.ifindex = -1; } /* * Select promiscuous mode on if "promisc" is set. * * Do not turn allmulti mode on if we don't select * promiscuous mode - on some devices (e.g., Orinoco * wireless interfaces), allmulti mode isn't supported * and the driver implements it by turning promiscuous * mode on, and that screws up the operation of the * card as a normal networking interface, and on no * other platform I know of does starting a non- * promiscuous capture affect which multicast packets * are received by the interface. */ /* * Hmm, how can we set promiscuous mode on all interfaces? * I am not sure if that is possible at all. For now, we * silently ignore attempts to turn promiscuous mode on * for the "any" device (so you don't have to explicitly * disable it in programs such as tcpdump). */ if (!is_any_device && handle->opt.promisc) { memset(&mr, 0, sizeof(mr)); mr.mr_ifindex = handle->md.ifindex; mr.mr_type = PACKET_MR_PROMISC; if (setsockopt(sock_fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr)) == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "setsockopt: %s", pcap_strerror(errno)); close(sock_fd); return PCAP_ERROR; } } /* Enable auxillary data if supported and reserve room for * reconstructing VLAN headers. */ #ifdef HAVE_PACKET_AUXDATA val = 1; if (setsockopt(sock_fd, SOL_PACKET, PACKET_AUXDATA, &val, sizeof(val)) == -1 && errno != ENOPROTOOPT) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "setsockopt: %s", pcap_strerror(errno)); close(sock_fd); return PCAP_ERROR; } handle->offset += VLAN_TAG_LEN; #endif /* HAVE_PACKET_AUXDATA */ /* * This is a 2.2[.x] or later kernel (we know that * because we're not using a SOCK_PACKET socket - * PF_PACKET is supported only in 2.2 and later * kernels). * * We can safely pass "recvfrom()" a byte count * based on the snapshot length. * * If we're in cooked mode, make the snapshot length * large enough to hold a "cooked mode" header plus * 1 byte of packet data (so we don't pass a byte * count of 0 to "recvfrom()"). */ if (handle->md.cooked) { if (handle->snapshot < SLL_HDR_LEN + 1) handle->snapshot = SLL_HDR_LEN + 1; } handle->bufsize = handle->snapshot; + /* + * Set the offset at which to insert VLAN tags. + */ + switch (handle->linktype) { + + case DLT_EN10MB: + handle->md.vlan_offset = 2 * ETH_ALEN; + break; + + case DLT_LINUX_SLL: + handle->md.vlan_offset = 14; + break; + + default: + handle->md.vlan_offset = -1; /* unknown */ + break; + } + /* Save the socket FD in the pcap structure */ handle->fd = sock_fd; return 1; #else strncpy(ebuf, "New packet capturing interface not supported by build " "environment", PCAP_ERRBUF_SIZE); return 0; #endif } #ifdef HAVE_PACKET_RING /* * Attempt to activate with memory-mapped access. * * On success, returns 1, and sets *status to 0 if there are no warnings * or to a PCAP_WARNING_ code if there is a warning. * * On failure due to lack of support for memory-mapped capture, returns * 0. * * On error, returns -1, and sets *status to the appropriate error code; * if that is PCAP_ERROR, sets handle->errbuf to the appropriate message. */ static int activate_mmap(pcap_t *handle, int *status) { int ret; /* * Attempt to allocate a buffer to hold the contents of one * packet, for use by the oneshot callback. */ handle->md.oneshot_buffer = malloc(handle->snapshot); if (handle->md.oneshot_buffer == NULL) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "can't allocate oneshot buffer: %s", pcap_strerror(errno)); *status = PCAP_ERROR; return -1; } if (handle->opt.buffer_size == 0) { /* by default request 2M for the ring buffer */ handle->opt.buffer_size = 2*1024*1024; } ret = prepare_tpacket_socket(handle); if (ret == -1) { free(handle->md.oneshot_buffer); *status = PCAP_ERROR; return ret; } ret = create_ring(handle, status); if (ret == 0) { /* * We don't support memory-mapped capture; our caller * will fall back on reading from the socket. */ free(handle->md.oneshot_buffer); return 0; } if (ret == -1) { /* * Error attempting to enable memory-mapped capture; * fail. create_ring() has set *status. */ free(handle->md.oneshot_buffer); return -1; } /* * Success. *status has been set either to 0 if there are no * warnings or to a PCAP_WARNING_ value if there is a warning. * * Override some defaults and inherit the other fields from * activate_new. * handle->offset is used to get the current position into the rx ring. * handle->cc is used to store the ring size. */ handle->read_op = pcap_read_linux_mmap; handle->cleanup_op = pcap_cleanup_linux_mmap; handle->setfilter_op = pcap_setfilter_linux_mmap; handle->setnonblock_op = pcap_setnonblock_mmap; handle->getnonblock_op = pcap_getnonblock_mmap; handle->oneshot_callback = pcap_oneshot_mmap; handle->selectable_fd = handle->fd; return 1; } #else /* HAVE_PACKET_RING */ static int activate_mmap(pcap_t *handle _U_, int *status _U_) { return 0; } #endif /* HAVE_PACKET_RING */ #ifdef HAVE_PACKET_RING /* * Attempt to set the socket to version 2 of the memory-mapped header. * Return 1 if we succeed or if we fail because version 2 isn't * supported; return -1 on any other error, and set handle->errbuf. */ static int prepare_tpacket_socket(pcap_t *handle) { #ifdef HAVE_TPACKET2 socklen_t len; int val; #endif handle->md.tp_version = TPACKET_V1; handle->md.tp_hdrlen = sizeof(struct tpacket_hdr); #ifdef HAVE_TPACKET2 /* Probe whether kernel supports TPACKET_V2 */ val = TPACKET_V2; len = sizeof(val); if (getsockopt(handle->fd, SOL_PACKET, PACKET_HDRLEN, &val, &len) < 0) { if (errno == ENOPROTOOPT) return 1; /* no - just drive on */ /* Yes - treat as a failure. */ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "can't get TPACKET_V2 header len on packet socket: %s", pcap_strerror(errno)); return -1; } handle->md.tp_hdrlen = val; val = TPACKET_V2; if (setsockopt(handle->fd, SOL_PACKET, PACKET_VERSION, &val, sizeof(val)) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "can't activate TPACKET_V2 on packet socket: %s", pcap_strerror(errno)); return -1; } handle->md.tp_version = TPACKET_V2; /* Reserve space for VLAN tag reconstruction */ val = VLAN_TAG_LEN; if (setsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE, &val, sizeof(val)) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "can't set up reserve on packet socket: %s", pcap_strerror(errno)); return -1; } #endif /* HAVE_TPACKET2 */ return 1; } /* * Attempt to set up memory-mapped access. * * On success, returns 1, and sets *status to 0 if there are no warnings * or to a PCAP_WARNING_ code if there is a warning. * * On failure due to lack of support for memory-mapped capture, returns * 0. * * On error, returns -1, and sets *status to the appropriate error code; * if that is PCAP_ERROR, sets handle->errbuf to the appropriate message. */ static int create_ring(pcap_t *handle, int *status) { unsigned i, j, frames_per_block; struct tpacket_req req; socklen_t len; unsigned int sk_type, tp_reserve, maclen, tp_hdrlen, netoff, macoff; unsigned int frame_size; /* * Start out assuming no warnings or errors. */ *status = 0; /* Note that with large snapshot length (say 64K, which is the default * for recent versions of tcpdump, the value that "-s 0" has given * for a long time with tcpdump, and the default in Wireshark/TShark), * if we use the snapshot length to calculate the frame length, * only a few frames will be available in the ring even with pretty * large ring size (and a lot of memory will be unused). * * Ideally, we should choose a frame length based on the * minimum of the specified snapshot length and the maximum * packet size. That's not as easy as it sounds; consider, for * example, an 802.11 interface in monitor mode, where the * frame would include a radiotap header, where the maximum * radiotap header length is device-dependent. * * So, for now, we just do this for Ethernet devices, where * there's no metadata header, and the link-layer header is * fixed length. We can get the maximum packet size by * adding 18, the Ethernet header length plus the CRC length * (just in case we happen to get the CRC in the packet), to * the MTU of the interface; we fetch the MTU in the hopes * that it reflects support for jumbo frames. (Even if the * interface is just being used for passive snooping, the driver * might set the size of buffers in the receive ring based on * the MTU, so that the MTU limits the maximum size of packets * that we can receive.) * * We don't do that if segmentation/fragmentation or receive * offload are enabled, so we don't get rudely surprised by * "packets" bigger than the MTU. */ frame_size = handle->snapshot; if (handle->linktype == DLT_EN10MB) { int mtu; int offload; offload = iface_get_offload(handle); if (offload == -1) { *status = PCAP_ERROR; return -1; } if (!offload) { mtu = iface_get_mtu(handle->fd, handle->opt.source, handle->errbuf); if (mtu == -1) { *status = PCAP_ERROR; return -1; } if (frame_size > mtu + 18) frame_size = mtu + 18; } } /* NOTE: calculus matching those in tpacket_rcv() * in linux-2.6/net/packet/af_packet.c */ len = sizeof(sk_type); if (getsockopt(handle->fd, SOL_SOCKET, SO_TYPE, &sk_type, &len) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "getsockopt: %s", pcap_strerror(errno)); *status = PCAP_ERROR; return -1; } #ifdef PACKET_RESERVE len = sizeof(tp_reserve); if (getsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE, &tp_reserve, &len) < 0) { if (errno != ENOPROTOOPT) { /* * ENOPROTOOPT means "kernel doesn't support * PACKET_RESERVE", in which case we fall back * as best we can. */ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "getsockopt: %s", pcap_strerror(errno)); *status = PCAP_ERROR; return -1; } tp_reserve = 0; /* older kernel, reserve not supported */ } #else tp_reserve = 0; /* older kernel, reserve not supported */ #endif maclen = (sk_type == SOCK_DGRAM) ? 0 : MAX_LINKHEADER_SIZE; /* XXX: in the kernel maclen is calculated from * LL_ALLOCATED_SPACE(dev) and vnet_hdr.hdr_len * in: packet_snd() in linux-2.6/net/packet/af_packet.c * then packet_alloc_skb() in linux-2.6/net/packet/af_packet.c * then sock_alloc_send_pskb() in linux-2.6/net/core/sock.c * but I see no way to get those sizes in userspace, * like for instance with an ifreq ioctl(); * the best thing I've found so far is MAX_HEADER in the kernel * part of linux-2.6/include/linux/netdevice.h * which goes up to 128+48=176; since pcap-linux.c defines * a MAX_LINKHEADER_SIZE of 256 which is greater than that, * let's use it.. maybe is it even large enough to directly * replace macoff.. */ tp_hdrlen = TPACKET_ALIGN(handle->md.tp_hdrlen) + sizeof(struct sockaddr_ll) ; netoff = TPACKET_ALIGN(tp_hdrlen + (maclen < 16 ? 16 : maclen)) + tp_reserve; /* NOTE: AFAICS tp_reserve may break the TPACKET_ALIGN of * netoff, which contradicts * linux-2.6/Documentation/networking/packet_mmap.txt * documenting that: * "- Gap, chosen so that packet data (Start+tp_net) * aligns to TPACKET_ALIGNMENT=16" */ /* NOTE: in linux-2.6/include/linux/skbuff.h: * "CPUs often take a performance hit * when accessing unaligned memory locations" */ macoff = netoff - maclen; req.tp_frame_size = TPACKET_ALIGN(macoff + frame_size); req.tp_frame_nr = handle->opt.buffer_size/req.tp_frame_size; /* compute the minumum block size that will handle this frame. * The block has to be page size aligned. * The max block size allowed by the kernel is arch-dependent and * it's not explicitly checked here. */ req.tp_block_size = getpagesize(); while (req.tp_block_size < req.tp_frame_size) req.tp_block_size <<= 1; frames_per_block = req.tp_block_size/req.tp_frame_size; /* * PACKET_TIMESTAMP was added after linux/net_tstamp.h was, * so we check for PACKET_TIMESTAMP. We check for * linux/net_tstamp.h just in case a system somehow has * PACKET_TIMESTAMP but not linux/net_tstamp.h; that might * be unnecessary. * * SIOCSHWTSTAMP was introduced in the patch that introduced * linux/net_tstamp.h, so we don't bother checking whether * SIOCSHWTSTAMP is defined (if your Linux system has * linux/net_tstamp.h but doesn't define SIOCSHWTSTAMP, your * Linux system is badly broken). */ #if defined(HAVE_LINUX_NET_TSTAMP_H) && defined(PACKET_TIMESTAMP) /* * If we were told to do so, ask the kernel and the driver * to use hardware timestamps. * * Hardware timestamps are only supported with mmapped * captures. */ if (handle->opt.tstamp_type == PCAP_TSTAMP_ADAPTER || handle->opt.tstamp_type == PCAP_TSTAMP_ADAPTER_UNSYNCED) { struct hwtstamp_config hwconfig; struct ifreq ifr; int timesource; /* * Ask for hardware time stamps on all packets, * including transmitted packets. */ memset(&hwconfig, 0, sizeof(hwconfig)); hwconfig.tx_type = HWTSTAMP_TX_ON; hwconfig.rx_filter = HWTSTAMP_FILTER_ALL; memset(&ifr, 0, sizeof(ifr)); strcpy(ifr.ifr_name, handle->opt.source); ifr.ifr_data = (void *)&hwconfig; if (ioctl(handle->fd, SIOCSHWTSTAMP, &ifr) < 0) { switch (errno) { case EPERM: /* * Treat this as an error, as the * user should try to run this * with the appropriate privileges - * and, if they can't, shouldn't * try requesting hardware time stamps. */ *status = PCAP_ERROR_PERM_DENIED; return -1; case EOPNOTSUPP: /* * Treat this as a warning, as the * only way to fix the warning is to * get an adapter that supports hardware * time stamps. We'll just fall back * on the standard host time stamps. */ *status = PCAP_WARNING_TSTAMP_TYPE_NOTSUP; break; default: snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "SIOCSHWTSTAMP failed: %s", pcap_strerror(errno)); *status = PCAP_ERROR; return -1; } } else { /* * Well, that worked. Now specify the type of * hardware time stamp we want for this * socket. */ if (handle->opt.tstamp_type == PCAP_TSTAMP_ADAPTER) { /* * Hardware timestamp, synchronized * with the system clock. */ timesource = SOF_TIMESTAMPING_SYS_HARDWARE; } else { /* * PCAP_TSTAMP_ADAPTER_UNSYNCED - hardware * timestamp, not synchronized with the * system clock. */ timesource = SOF_TIMESTAMPING_RAW_HARDWARE; } if (setsockopt(handle->fd, SOL_PACKET, PACKET_TIMESTAMP, (void *)×ource, sizeof(timesource))) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "can't set PACKET_TIMESTAMP: %s", pcap_strerror(errno)); *status = PCAP_ERROR; return -1; } } } #endif /* HAVE_LINUX_NET_TSTAMP_H && PACKET_TIMESTAMP */ /* ask the kernel to create the ring */ retry: req.tp_block_nr = req.tp_frame_nr / frames_per_block; /* req.tp_frame_nr is requested to match frames_per_block*req.tp_block_nr */ req.tp_frame_nr = req.tp_block_nr * frames_per_block; if (setsockopt(handle->fd, SOL_PACKET, PACKET_RX_RING, (void *) &req, sizeof(req))) { if ((errno == ENOMEM) && (req.tp_block_nr > 1)) { /* * Memory failure; try to reduce the requested ring * size. * * We used to reduce this by half -- do 5% instead. * That may result in more iterations and a longer * startup, but the user will be much happier with * the resulting buffer size. */ if (req.tp_frame_nr < 20) req.tp_frame_nr -= 1; else req.tp_frame_nr -= req.tp_frame_nr/20; goto retry; } if (errno == ENOPROTOOPT) { /* * We don't have ring buffer support in this kernel. */ return 0; } snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "can't create rx ring on packet socket: %s", pcap_strerror(errno)); *status = PCAP_ERROR; return -1; } /* memory map the rx ring */ handle->md.mmapbuflen = req.tp_block_nr * req.tp_block_size; handle->md.mmapbuf = mmap(0, handle->md.mmapbuflen, PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0); if (handle->md.mmapbuf == MAP_FAILED) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "can't mmap rx ring: %s", pcap_strerror(errno)); /* clear the allocated ring on error*/ destroy_ring(handle); *status = PCAP_ERROR; return -1; } /* allocate a ring for each frame header pointer*/ handle->cc = req.tp_frame_nr; handle->buffer = malloc(handle->cc * sizeof(union thdr *)); if (!handle->buffer) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "can't allocate ring of frame headers: %s", pcap_strerror(errno)); destroy_ring(handle); *status = PCAP_ERROR; return -1; } /* fill the header ring with proper frame ptr*/ handle->offset = 0; for (i=0; imd.mmapbuf[i*req.tp_block_size]; for (j=0; joffset) { RING_GET_FRAME(handle) = base; base += req.tp_frame_size; } } handle->bufsize = req.tp_frame_size; handle->offset = 0; return 1; } /* free all ring related resources*/ static void destroy_ring(pcap_t *handle) { /* tell the kernel to destroy the ring*/ struct tpacket_req req; memset(&req, 0, sizeof(req)); setsockopt(handle->fd, SOL_PACKET, PACKET_RX_RING, (void *) &req, sizeof(req)); /* if ring is mapped, unmap it*/ if (handle->md.mmapbuf) { /* do not test for mmap failure, as we can't recover from any error */ munmap(handle->md.mmapbuf, handle->md.mmapbuflen); handle->md.mmapbuf = NULL; } } /* * Special one-shot callback, used for pcap_next() and pcap_next_ex(), * for Linux mmapped capture. * * The problem is that pcap_next() and pcap_next_ex() expect the packet * data handed to the callback to be valid after the callback returns, * but pcap_read_linux_mmap() has to release that packet as soon as * the callback returns (otherwise, the kernel thinks there's still * at least one unprocessed packet available in the ring, so a select() * will immediately return indicating that there's data to process), so, * in the callback, we have to make a copy of the packet. * * Yes, this means that, if the capture is using the ring buffer, using * pcap_next() or pcap_next_ex() requires more copies than using * pcap_loop() or pcap_dispatch(). If that bothers you, don't use * pcap_next() or pcap_next_ex(). */ static void pcap_oneshot_mmap(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes) { struct oneshot_userdata *sp = (struct oneshot_userdata *)user; *sp->hdr = *h; memcpy(sp->pd->md.oneshot_buffer, bytes, h->caplen); *sp->pkt = sp->pd->md.oneshot_buffer; } static void pcap_cleanup_linux_mmap( pcap_t *handle ) { destroy_ring(handle); if (handle->md.oneshot_buffer != NULL) { free(handle->md.oneshot_buffer); handle->md.oneshot_buffer = NULL; } pcap_cleanup_linux(handle); } static int pcap_getnonblock_mmap(pcap_t *p, char *errbuf) { /* use negative value of timeout to indicate non blocking ops */ return (p->md.timeout<0); } static int pcap_setnonblock_mmap(pcap_t *p, int nonblock, char *errbuf) { - /* map each value to the corresponding 2's complement, to - * preserve the timeout value provided with pcap_set_timeout */ + /* + * Map each value to their corresponding negation to + * preserve the timeout value provided with pcap_set_timeout. + */ if (nonblock) { if (p->md.timeout >= 0) { /* - * Timeout is non-negative, so we're not already - * in non-blocking mode; set it to the 2's - * complement, to make it negative, as an - * indication that we're in non-blocking mode. + * Indicate that we're switching to + * non-blocking mode. */ - p->md.timeout = p->md.timeout*-1 - 1; + p->md.timeout = ~p->md.timeout; } } else { if (p->md.timeout < 0) { - /* - * Timeout is negative, so we're not already - * in blocking mode; reverse the previous - * operation, to make the timeout non-negative - * again. - */ - p->md.timeout = (p->md.timeout+1)*-1; + p->md.timeout = ~p->md.timeout; } } return 0; } static inline union thdr * pcap_get_ring_frame(pcap_t *handle, int status) { union thdr h; h.raw = RING_GET_FRAME(handle); switch (handle->md.tp_version) { case TPACKET_V1: if (status != (h.h1->tp_status ? TP_STATUS_USER : TP_STATUS_KERNEL)) return NULL; break; #ifdef HAVE_TPACKET2 case TPACKET_V2: if (status != (h.h2->tp_status ? TP_STATUS_USER : TP_STATUS_KERNEL)) return NULL; break; #endif } return h.raw; } #ifndef POLLRDHUP #define POLLRDHUP 0 #endif static int pcap_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) { int timeout; int pkts = 0; char c; /* wait for frames availability.*/ if (!pcap_get_ring_frame(handle, TP_STATUS_USER)) { struct pollfd pollinfo; int ret; pollinfo.fd = handle->fd; pollinfo.events = POLLIN; if (handle->md.timeout == 0) timeout = -1; /* block forever */ else if (handle->md.timeout > 0) timeout = handle->md.timeout; /* block for that amount of time */ else timeout = 0; /* non-blocking mode - poll to pick up errors */ do { ret = poll(&pollinfo, 1, timeout); if (ret < 0 && errno != EINTR) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "can't poll on packet socket: %s", pcap_strerror(errno)); return PCAP_ERROR; } else if (ret > 0 && (pollinfo.revents & (POLLHUP|POLLRDHUP|POLLERR|POLLNVAL))) { /* * There's some indication other than * "you can read on this descriptor" on * the descriptor. */ if (pollinfo.revents & (POLLHUP | POLLRDHUP)) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Hangup on packet socket"); return PCAP_ERROR; } if (pollinfo.revents & POLLERR) { /* * A recv() will give us the * actual error code. * * XXX - make the socket non-blocking? */ if (recv(handle->fd, &c, sizeof c, MSG_PEEK) != -1) continue; /* what, no error? */ if (errno == ENETDOWN) { /* * The device on which we're * capturing went away. * * XXX - we should really return * PCAP_ERROR_IFACE_NOT_UP, * but pcap_dispatch() etc. * aren't defined to return * that. */ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "The interface went down"); } else { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Error condition on packet socket: %s", strerror(errno)); } return PCAP_ERROR; } if (pollinfo.revents & POLLNVAL) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Invalid polling request on packet socket"); return PCAP_ERROR; } } /* check for break loop condition on interrupted syscall*/ if (handle->break_loop) { handle->break_loop = 0; return PCAP_ERROR_BREAK; } } while (ret < 0); } /* non-positive values of max_packets are used to require all * packets currently available in the ring */ while ((pkts < max_packets) || (max_packets <= 0)) { int run_bpf; struct sockaddr_ll *sll; struct pcap_pkthdr pcaphdr; unsigned char *bp; union thdr h; unsigned int tp_len; unsigned int tp_mac; unsigned int tp_snaplen; unsigned int tp_sec; unsigned int tp_usec; h.raw = pcap_get_ring_frame(handle, TP_STATUS_USER); if (!h.raw) break; switch (handle->md.tp_version) { case TPACKET_V1: tp_len = h.h1->tp_len; tp_mac = h.h1->tp_mac; tp_snaplen = h.h1->tp_snaplen; tp_sec = h.h1->tp_sec; tp_usec = h.h1->tp_usec; break; #ifdef HAVE_TPACKET2 case TPACKET_V2: tp_len = h.h2->tp_len; tp_mac = h.h2->tp_mac; tp_snaplen = h.h2->tp_snaplen; tp_sec = h.h2->tp_sec; tp_usec = h.h2->tp_nsec / 1000; break; #endif default: snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "unsupported tpacket version %d", handle->md.tp_version); return -1; } /* perform sanity check on internal offset. */ if (tp_mac + tp_snaplen > handle->bufsize) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "corrupted frame on kernel ring mac " "offset %d + caplen %d > frame len %d", tp_mac, tp_snaplen, handle->bufsize); return -1; } /* run filter on received packet * If the kernel filtering is enabled we need to run the * filter until all the frames present into the ring * at filter creation time are processed. * In such case md.use_bpf is used as a counter for the * packet we need to filter. * Note: alternatively it could be possible to stop applying * the filter when the ring became empty, but it can possibly * happen a lot later... */ bp = (unsigned char*)h.raw + tp_mac; run_bpf = (!handle->md.use_bpf) || ((handle->md.use_bpf>1) && handle->md.use_bpf--); if (run_bpf && handle->fcode.bf_insns && (bpf_filter(handle->fcode.bf_insns, bp, tp_len, tp_snaplen) == 0)) goto skip; /* * Do checks based on packet direction. */ sll = (void *)h.raw + TPACKET_ALIGN(handle->md.tp_hdrlen); if (sll->sll_pkttype == PACKET_OUTGOING) { /* * Outgoing packet. * If this is from the loopback device, reject it; * we'll see the packet as an incoming packet as well, * and we don't want to see it twice. */ if (sll->sll_ifindex == handle->md.lo_ifindex) goto skip; /* * If the user only wants incoming packets, reject it. */ if (handle->direction == PCAP_D_IN) goto skip; } else { /* * Incoming packet. * If the user only wants outgoing packets, reject it. */ if (handle->direction == PCAP_D_OUT) goto skip; } /* get required packet info from ring header */ pcaphdr.ts.tv_sec = tp_sec; pcaphdr.ts.tv_usec = tp_usec; pcaphdr.caplen = tp_snaplen; pcaphdr.len = tp_len; /* if required build in place the sll header*/ if (handle->md.cooked) { struct sll_header *hdrp; /* * The kernel should have left us with enough * space for an sll header; back up the packet * data pointer into that space, as that'll be * the beginning of the packet we pass to the * callback. */ bp -= SLL_HDR_LEN; /* * Let's make sure that's past the end of * the tpacket header, i.e. >= * ((u_char *)thdr + TPACKET_HDRLEN), so we * don't step on the header when we construct * the sll header. */ if (bp < (u_char *)h.raw + TPACKET_ALIGN(handle->md.tp_hdrlen) + sizeof(struct sockaddr_ll)) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "cooked-mode frame doesn't have room for sll header"); return -1; } /* * OK, that worked; construct the sll header. */ hdrp = (struct sll_header *)bp; hdrp->sll_pkttype = map_packet_type_to_sll_type( sll->sll_pkttype); hdrp->sll_hatype = htons(sll->sll_hatype); hdrp->sll_halen = htons(sll->sll_halen); memcpy(hdrp->sll_addr, sll->sll_addr, SLL_ADDRLEN); hdrp->sll_protocol = sll->sll_protocol; /* update packet len */ pcaphdr.caplen += SLL_HDR_LEN; pcaphdr.len += SLL_HDR_LEN; } #ifdef HAVE_TPACKET2 - if (handle->md.tp_version == TPACKET_V2 && h.h2->tp_vlan_tci && - tp_snaplen >= 2 * ETH_ALEN) { + if ((handle->md.tp_version == TPACKET_V2) && +#if defined(TP_STATUS_VLAN_VALID) + (h.h2->tp_vlan_tci || (h.h2->tp_status & TP_STATUS_VLAN_VALID)) && +#else + h.h2->tp_vlan_tci && +#endif + handle->md.vlan_offset != -1 && + tp_snaplen >= (unsigned int) handle->md.vlan_offset) { struct vlan_tag *tag; bp -= VLAN_TAG_LEN; - memmove(bp, bp + VLAN_TAG_LEN, 2 * ETH_ALEN); + memmove(bp, bp + VLAN_TAG_LEN, handle->md.vlan_offset); - tag = (struct vlan_tag *)(bp + 2 * ETH_ALEN); + tag = (struct vlan_tag *)(bp + handle->md.vlan_offset); tag->vlan_tpid = htons(ETH_P_8021Q); tag->vlan_tci = htons(h.h2->tp_vlan_tci); pcaphdr.caplen += VLAN_TAG_LEN; pcaphdr.len += VLAN_TAG_LEN; } #endif /* * The only way to tell the kernel to cut off the * packet at a snapshot length is with a filter program; * if there's no filter program, the kernel won't cut * the packet off. * * Trim the snapshot length to be no longer than the * specified snapshot length. */ if (pcaphdr.caplen > handle->snapshot) pcaphdr.caplen = handle->snapshot; /* pass the packet to the user */ pkts++; callback(user, &pcaphdr, bp); handle->md.packets_read++; skip: /* next packet */ switch (handle->md.tp_version) { case TPACKET_V1: h.h1->tp_status = TP_STATUS_KERNEL; break; #ifdef HAVE_TPACKET2 case TPACKET_V2: h.h2->tp_status = TP_STATUS_KERNEL; break; #endif } if (++handle->offset >= handle->cc) handle->offset = 0; /* check for break loop condition*/ if (handle->break_loop) { handle->break_loop = 0; return PCAP_ERROR_BREAK; } } return pkts; } static int pcap_setfilter_linux_mmap(pcap_t *handle, struct bpf_program *filter) { int n, offset; int ret; /* * Don't rewrite "ret" instructions; we don't need to, as * we're not reading packets with recvmsg(), and we don't * want to, as, by not rewriting them, the kernel can avoid * copying extra data. */ ret = pcap_setfilter_linux_common(handle, filter, 1); if (ret < 0) return ret; /* if the kernel filter is enabled, we need to apply the filter on * all packets present into the ring. Get an upper bound of their number */ if (!handle->md.use_bpf) return ret; /* walk the ring backward and count the free slot */ offset = handle->offset; if (--handle->offset < 0) handle->offset = handle->cc - 1; for (n=0; n < handle->cc; ++n) { if (--handle->offset < 0) handle->offset = handle->cc - 1; if (!pcap_get_ring_frame(handle, TP_STATUS_KERNEL)) break; } /* be careful to not change current ring position */ handle->offset = offset; /* store the number of packets currently present in the ring */ handle->md.use_bpf = 1 + (handle->cc - n); return ret; } #endif /* HAVE_PACKET_RING */ #ifdef HAVE_PF_PACKET_SOCKETS /* * Return the index of the given device name. Fill ebuf and return * -1 on failure. */ static int iface_get_id(int fd, const char *device, char *ebuf) { struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCGIFINDEX: %s", pcap_strerror(errno)); return -1; } return ifr.ifr_ifindex; } /* * Bind the socket associated with FD to the given device. * Return 1 on success, 0 if we should try a SOCK_PACKET socket, * or a PCAP_ERROR_ value on a hard error. */ static int iface_bind(int fd, int ifindex, char *ebuf) { struct sockaddr_ll sll; int err; socklen_t errlen = sizeof(err); memset(&sll, 0, sizeof(sll)); sll.sll_family = AF_PACKET; sll.sll_ifindex = ifindex; sll.sll_protocol = htons(ETH_P_ALL); if (bind(fd, (struct sockaddr *) &sll, sizeof(sll)) == -1) { if (errno == ENETDOWN) { /* * Return a "network down" indication, so that * the application can report that rather than * saying we had a mysterious failure and * suggest that they report a problem to the * libpcap developers. */ return PCAP_ERROR_IFACE_NOT_UP; } else { snprintf(ebuf, PCAP_ERRBUF_SIZE, "bind: %s", pcap_strerror(errno)); return PCAP_ERROR; } } /* Any pending errors, e.g., network is down? */ if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "getsockopt: %s", pcap_strerror(errno)); return 0; } if (err == ENETDOWN) { /* * Return a "network down" indication, so that * the application can report that rather than * saying we had a mysterious failure and * suggest that they report a problem to the * libpcap developers. */ return PCAP_ERROR_IFACE_NOT_UP; } else if (err > 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "bind: %s", pcap_strerror(err)); return 0; } return 1; } #ifdef IW_MODE_MONITOR /* * Check whether the device supports the Wireless Extensions. * Returns 1 if it does, 0 if it doesn't, PCAP_ERROR_NO_SUCH_DEVICE * if the device doesn't even exist. */ static int has_wext(int sock_fd, const char *device, char *ebuf) { struct iwreq ireq; strncpy(ireq.ifr_ifrn.ifrn_name, device, sizeof ireq.ifr_ifrn.ifrn_name); ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0; if (ioctl(sock_fd, SIOCGIWNAME, &ireq) >= 0) return 1; /* yes */ snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: SIOCGIWPRIV: %s", device, pcap_strerror(errno)); if (errno == ENODEV) return PCAP_ERROR_NO_SUCH_DEVICE; return 0; } /* * Per me si va ne la citta dolente, * Per me si va ne l'etterno dolore, * ... * Lasciate ogne speranza, voi ch'intrate. * * XXX - airmon-ng does special stuff with the Orinoco driver and the * wlan-ng driver. */ typedef enum { MONITOR_WEXT, MONITOR_HOSTAP, MONITOR_PRISM, MONITOR_PRISM54, MONITOR_ACX100, MONITOR_RT2500, MONITOR_RT2570, MONITOR_RT73, MONITOR_RTL8XXX } monitor_type; /* * Use the Wireless Extensions, if we have them, to try to turn monitor mode * on if it's not already on. * * Returns 1 on success, 0 if we don't support the Wireless Extensions * on this device, or a PCAP_ERROR_ value if we do support them but * we weren't able to turn monitor mode on. */ static int enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device) { /* * XXX - at least some adapters require non-Wireless Extensions * mechanisms to turn monitor mode on. * * Atheros cards might require that a separate "monitor virtual access * point" be created, with later versions of the madwifi driver. * airmon-ng does "wlanconfig ath create wlandev {if} wlanmode * monitor -bssid", which apparently spits out a line "athN" * where "athN" is the monitor mode device. To leave monitor * mode, it destroys the monitor mode device. * * Some Intel Centrino adapters might require private ioctls to get * radio headers; the ipw2200 and ipw3945 drivers allow you to * configure a separate "rtapN" interface to capture in monitor * mode without preventing the adapter from operating normally. * (airmon-ng doesn't appear to use that, though.) * * It would be Truly Wonderful if mac80211 and nl80211 cleaned this * up, and if all drivers were converted to mac80211 drivers. * * If interface {if} is a mac80211 driver, the file * /sys/class/net/{if}/phy80211 is a symlink to * /sys/class/ieee80211/{phydev}, for some {phydev}. * * On Fedora 9, with a 2.6.26.3-29 kernel, my Zydas stick, at * least, has a "wmaster0" device and a "wlan0" device; the * latter is the one with the IP address. Both show up in * "tcpdump -D" output. Capturing on the wmaster0 device * captures with 802.11 headers. * * airmon-ng searches through /sys/class/net for devices named * monN, starting with mon0; as soon as one *doesn't* exist, * it chooses that as the monitor device name. If the "iw" * command exists, it does "iw dev {if} interface add {monif} * type monitor", where {monif} is the monitor device. It * then (sigh) sleeps .1 second, and then configures the * device up. Otherwise, if /sys/class/ieee80211/{phydev}/add_iface * is a file, it writes {mondev}, without a newline, to that file, * and again (sigh) sleeps .1 second, and then iwconfig's that * device into monitor mode and configures it up. Otherwise, * you can't do monitor mode. * * All these devices are "glued" together by having the * /sys/class/net/{device}/phy80211 links pointing to the same * place, so, given a wmaster, wlan, or mon device, you can * find the other devices by looking for devices with * the same phy80211 link. * * To turn monitor mode off, delete the monitor interface, * either with "iw dev {monif} interface del" or by sending * {monif}, with no NL, down /sys/class/ieee80211/{phydev}/remove_iface * * Note: if you try to create a monitor device named "monN", and * there's already a "monN" device, it fails, as least with * the netlink interface (which is what iw uses), with a return * value of -ENFILE. (Return values are negative errnos.) We * could probably use that to find an unused device. */ int err; struct iwreq ireq; struct iw_priv_args *priv; monitor_type montype; int i; __u32 cmd; struct ifreq ifr; int oldflags; int args[2]; int channel; /* * Does this device *support* the Wireless Extensions? */ err = has_wext(sock_fd, device, handle->errbuf); if (err <= 0) return err; /* either it doesn't or the device doesn't even exist */ /* * Start out assuming we have no private extensions to control * radio metadata. */ montype = MONITOR_WEXT; cmd = 0; /* * Try to get all the Wireless Extensions private ioctls * supported by this device. * * First, get the size of the buffer we need, by supplying no * buffer and a length of 0. If the device supports private * ioctls, it should return E2BIG, with ireq.u.data.length set * to the length we need. If it doesn't support them, it should * return EOPNOTSUPP. */ memset(&ireq, 0, sizeof ireq); strncpy(ireq.ifr_ifrn.ifrn_name, device, sizeof ireq.ifr_ifrn.ifrn_name); ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0; ireq.u.data.pointer = (void *)args; ireq.u.data.length = 0; ireq.u.data.flags = 0; if (ioctl(sock_fd, SIOCGIWPRIV, &ireq) != -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "%s: SIOCGIWPRIV with a zero-length buffer didn't fail!", device); return PCAP_ERROR; } if (errno != EOPNOTSUPP) { /* * OK, it's not as if there are no private ioctls. */ if (errno != E2BIG) { /* * Failed. */ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "%s: SIOCGIWPRIV: %s", device, pcap_strerror(errno)); return PCAP_ERROR; } /* * OK, try to get the list of private ioctls. */ priv = malloc(ireq.u.data.length * sizeof (struct iw_priv_args)); if (priv == NULL) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); return PCAP_ERROR; } ireq.u.data.pointer = (void *)priv; if (ioctl(sock_fd, SIOCGIWPRIV, &ireq) == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "%s: SIOCGIWPRIV: %s", device, pcap_strerror(errno)); free(priv); return PCAP_ERROR; } /* * Look for private ioctls to turn monitor mode on or, if * monitor mode is on, to set the header type. */ for (i = 0; i < ireq.u.data.length; i++) { if (strcmp(priv[i].name, "monitor_type") == 0) { /* * Hostap driver, use this one. * Set monitor mode first. * You can set it to 0 to get DLT_IEEE80211, * 1 to get DLT_PRISM, 2 to get * DLT_IEEE80211_RADIO_AVS, and, with more * recent versions of the driver, 3 to get * DLT_IEEE80211_RADIO. */ if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT) break; if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED)) break; if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 1) break; montype = MONITOR_HOSTAP; cmd = priv[i].cmd; break; } if (strcmp(priv[i].name, "set_prismhdr") == 0) { /* * Prism54 driver, use this one. * Set monitor mode first. * You can set it to 2 to get DLT_IEEE80211 * or 3 or get DLT_PRISM. */ if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT) break; if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED)) break; if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 1) break; montype = MONITOR_PRISM54; cmd = priv[i].cmd; break; } if (strcmp(priv[i].name, "forceprismheader") == 0) { /* * RT2570 driver, use this one. * Do this after turning monitor mode on. * You can set it to 1 to get DLT_PRISM or 2 * to get DLT_IEEE80211. */ if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT) break; if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED)) break; if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 1) break; montype = MONITOR_RT2570; cmd = priv[i].cmd; break; } if (strcmp(priv[i].name, "forceprism") == 0) { /* * RT73 driver, use this one. * Do this after turning monitor mode on. * Its argument is a *string*; you can * set it to "1" to get DLT_PRISM or "2" * to get DLT_IEEE80211. */ if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_CHAR) break; if (priv[i].set_args & IW_PRIV_SIZE_FIXED) break; montype = MONITOR_RT73; cmd = priv[i].cmd; break; } if (strcmp(priv[i].name, "prismhdr") == 0) { /* * One of the RTL8xxx drivers, use this one. * It can only be done after monitor mode * has been turned on. You can set it to 1 * to get DLT_PRISM or 0 to get DLT_IEEE80211. */ if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT) break; if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED)) break; if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 1) break; montype = MONITOR_RTL8XXX; cmd = priv[i].cmd; break; } if (strcmp(priv[i].name, "rfmontx") == 0) { /* * RT2500 or RT61 driver, use this one. * It has one one-byte parameter; set * u.data.length to 1 and u.data.pointer to * point to the parameter. * It doesn't itself turn monitor mode on. * You can set it to 1 to allow transmitting * in monitor mode(?) and get DLT_IEEE80211, * or set it to 0 to disallow transmitting in * monitor mode(?) and get DLT_PRISM. */ if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT) break; if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 2) break; montype = MONITOR_RT2500; cmd = priv[i].cmd; break; } if (strcmp(priv[i].name, "monitor") == 0) { /* * Either ACX100 or hostap, use this one. * It turns monitor mode on. * If it takes two arguments, it's ACX100; * the first argument is 1 for DLT_PRISM * or 2 for DLT_IEEE80211, and the second * argument is the channel on which to * run. If it takes one argument, it's * HostAP, and the argument is 2 for * DLT_IEEE80211 and 3 for DLT_PRISM. * * If we see this, we don't quit, as this * might be a version of the hostap driver * that also supports "monitor_type". */ if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT) break; if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED)) break; switch (priv[i].set_args & IW_PRIV_SIZE_MASK) { case 1: montype = MONITOR_PRISM; cmd = priv[i].cmd; break; case 2: montype = MONITOR_ACX100; cmd = priv[i].cmd; break; default: break; } } } free(priv); } /* * XXX - ipw3945? islism? */ /* * Get the old mode. */ strncpy(ireq.ifr_ifrn.ifrn_name, device, sizeof ireq.ifr_ifrn.ifrn_name); ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0; if (ioctl(sock_fd, SIOCGIWMODE, &ireq) == -1) { /* * We probably won't be able to set the mode, either. */ return PCAP_ERROR_RFMON_NOTSUP; } /* * Is it currently in monitor mode? */ if (ireq.u.mode == IW_MODE_MONITOR) { /* * Yes. Just leave things as they are. * We don't offer multiple link-layer types, as * changing the link-layer type out from under * somebody else capturing in monitor mode would * be considered rude. */ return 1; } /* * No. We have to put the adapter into rfmon mode. */ /* * If we haven't already done so, arrange to have * "pcap_close_all()" called when we exit. */ if (!pcap_do_addexit(handle)) { /* * "atexit()" failed; don't put the interface * in rfmon mode, just give up. */ return PCAP_ERROR_RFMON_NOTSUP; } /* * Save the old mode. */ handle->md.oldmode = ireq.u.mode; /* * Put the adapter in rfmon mode. How we do this depends * on whether we have a special private ioctl or not. */ if (montype == MONITOR_PRISM) { /* * We have the "monitor" private ioctl, but none of * the other private ioctls. Use this, and select * the Prism header. * * If it fails, just fall back on SIOCSIWMODE. */ memset(&ireq, 0, sizeof ireq); strncpy(ireq.ifr_ifrn.ifrn_name, device, sizeof ireq.ifr_ifrn.ifrn_name); ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0; ireq.u.data.length = 1; /* 1 argument */ args[0] = 3; /* request Prism header */ memcpy(ireq.u.name, args, IFNAMSIZ); if (ioctl(sock_fd, cmd, &ireq) != -1) { /* * Success. * Note that we have to put the old mode back * when we close the device. */ handle->md.must_do_on_close |= MUST_CLEAR_RFMON; /* * Add this to the list of pcaps to close * when we exit. */ pcap_add_to_pcaps_to_close(handle); return 1; } /* * Failure. Fall back on SIOCSIWMODE. */ } /* * First, take the interface down if it's up; otherwise, we * might get EBUSY. */ memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "%s: Can't get flags: %s", device, strerror(errno)); return PCAP_ERROR; } oldflags = 0; if (ifr.ifr_flags & IFF_UP) { oldflags = ifr.ifr_flags; ifr.ifr_flags &= ~IFF_UP; if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "%s: Can't set flags: %s", device, strerror(errno)); return PCAP_ERROR; } } /* * Then turn monitor mode on. */ strncpy(ireq.ifr_ifrn.ifrn_name, device, sizeof ireq.ifr_ifrn.ifrn_name); ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0; ireq.u.mode = IW_MODE_MONITOR; if (ioctl(sock_fd, SIOCSIWMODE, &ireq) == -1) { /* * Scientist, you've failed. * Bring the interface back up if we shut it down. */ ifr.ifr_flags = oldflags; if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "%s: Can't set flags: %s", device, strerror(errno)); return PCAP_ERROR; } return PCAP_ERROR_RFMON_NOTSUP; } /* * XXX - airmon-ng does "iwconfig {if} key off" after setting * monitor mode and setting the channel, and then does * "iwconfig up". */ /* * Now select the appropriate radio header. */ switch (montype) { case MONITOR_WEXT: /* * We don't have any private ioctl to set the header. */ break; case MONITOR_HOSTAP: /* * Try to select the radiotap header. */ memset(&ireq, 0, sizeof ireq); strncpy(ireq.ifr_ifrn.ifrn_name, device, sizeof ireq.ifr_ifrn.ifrn_name); ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0; args[0] = 3; /* request radiotap header */ memcpy(ireq.u.name, args, sizeof (int)); if (ioctl(sock_fd, cmd, &ireq) != -1) break; /* success */ /* * That failed. Try to select the AVS header. */ memset(&ireq, 0, sizeof ireq); strncpy(ireq.ifr_ifrn.ifrn_name, device, sizeof ireq.ifr_ifrn.ifrn_name); ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0; args[0] = 2; /* request AVS header */ memcpy(ireq.u.name, args, sizeof (int)); if (ioctl(sock_fd, cmd, &ireq) != -1) break; /* success */ /* * That failed. Try to select the Prism header. */ memset(&ireq, 0, sizeof ireq); strncpy(ireq.ifr_ifrn.ifrn_name, device, sizeof ireq.ifr_ifrn.ifrn_name); ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0; args[0] = 1; /* request Prism header */ memcpy(ireq.u.name, args, sizeof (int)); ioctl(sock_fd, cmd, &ireq); break; case MONITOR_PRISM: /* * The private ioctl failed. */ break; case MONITOR_PRISM54: /* * Select the Prism header. */ memset(&ireq, 0, sizeof ireq); strncpy(ireq.ifr_ifrn.ifrn_name, device, sizeof ireq.ifr_ifrn.ifrn_name); ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0; args[0] = 3; /* request Prism header */ memcpy(ireq.u.name, args, sizeof (int)); ioctl(sock_fd, cmd, &ireq); break; case MONITOR_ACX100: /* * Get the current channel. */ memset(&ireq, 0, sizeof ireq); strncpy(ireq.ifr_ifrn.ifrn_name, device, sizeof ireq.ifr_ifrn.ifrn_name); ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0; if (ioctl(sock_fd, SIOCGIWFREQ, &ireq) == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "%s: SIOCGIWFREQ: %s", device, pcap_strerror(errno)); return PCAP_ERROR; } channel = ireq.u.freq.m; /* * Select the Prism header, and set the channel to the * current value. */ memset(&ireq, 0, sizeof ireq); strncpy(ireq.ifr_ifrn.ifrn_name, device, sizeof ireq.ifr_ifrn.ifrn_name); ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0; args[0] = 1; /* request Prism header */ args[1] = channel; /* set channel */ memcpy(ireq.u.name, args, 2*sizeof (int)); ioctl(sock_fd, cmd, &ireq); break; case MONITOR_RT2500: /* * Disallow transmission - that turns on the * Prism header. */ memset(&ireq, 0, sizeof ireq); strncpy(ireq.ifr_ifrn.ifrn_name, device, sizeof ireq.ifr_ifrn.ifrn_name); ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0; args[0] = 0; /* disallow transmitting */ memcpy(ireq.u.name, args, sizeof (int)); ioctl(sock_fd, cmd, &ireq); break; case MONITOR_RT2570: /* * Force the Prism header. */ memset(&ireq, 0, sizeof ireq); strncpy(ireq.ifr_ifrn.ifrn_name, device, sizeof ireq.ifr_ifrn.ifrn_name); ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0; args[0] = 1; /* request Prism header */ memcpy(ireq.u.name, args, sizeof (int)); ioctl(sock_fd, cmd, &ireq); break; case MONITOR_RT73: /* * Force the Prism header. */ memset(&ireq, 0, sizeof ireq); strncpy(ireq.ifr_ifrn.ifrn_name, device, sizeof ireq.ifr_ifrn.ifrn_name); ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0; ireq.u.data.length = 1; /* 1 argument */ ireq.u.data.pointer = "1"; ireq.u.data.flags = 0; ioctl(sock_fd, cmd, &ireq); break; case MONITOR_RTL8XXX: /* * Force the Prism header. */ memset(&ireq, 0, sizeof ireq); strncpy(ireq.ifr_ifrn.ifrn_name, device, sizeof ireq.ifr_ifrn.ifrn_name); ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0; args[0] = 1; /* request Prism header */ memcpy(ireq.u.name, args, sizeof (int)); ioctl(sock_fd, cmd, &ireq); break; } /* * Now bring the interface back up if we brought it down. */ if (oldflags != 0) { ifr.ifr_flags = oldflags; if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "%s: Can't set flags: %s", device, strerror(errno)); /* * At least try to restore the old mode on the * interface. */ if (ioctl(handle->fd, SIOCSIWMODE, &ireq) == -1) { /* * Scientist, you've failed. */ fprintf(stderr, "Can't restore interface wireless mode (SIOCSIWMODE failed: %s).\n" "Please adjust manually.\n", strerror(errno)); } return PCAP_ERROR; } } /* * Note that we have to put the old mode back when we * close the device. */ handle->md.must_do_on_close |= MUST_CLEAR_RFMON; /* * Add this to the list of pcaps to close when we exit. */ pcap_add_to_pcaps_to_close(handle); return 1; } #endif /* IW_MODE_MONITOR */ /* * Try various mechanisms to enter monitor mode. */ static int enter_rfmon_mode(pcap_t *handle, int sock_fd, const char *device) { #if defined(HAVE_LIBNL) || defined(IW_MODE_MONITOR) int ret; #endif #ifdef HAVE_LIBNL ret = enter_rfmon_mode_mac80211(handle, sock_fd, device); if (ret < 0) return ret; /* error attempting to do so */ if (ret == 1) return 1; /* success */ #endif /* HAVE_LIBNL */ #ifdef IW_MODE_MONITOR ret = enter_rfmon_mode_wext(handle, sock_fd, device); if (ret < 0) return ret; /* error attempting to do so */ if (ret == 1) return 1; /* success */ #endif /* IW_MODE_MONITOR */ /* * Either none of the mechanisms we know about work or none * of those mechanisms are available, so we can't do monitor * mode. */ return 0; } /* * Find out if we have any form of fragmentation/reassembly offloading. * * We do so using SIOCETHTOOL checking for various types of offloading; * if SIOCETHTOOL isn't defined, or we don't have any #defines for any * of the types of offloading, there's nothing we can do to check, so * we just say "no, we don't". */ #if defined(SIOCETHTOOL) && (defined(ETHTOOL_GTSO) || defined(ETHTOOL_GUFO) || defined(ETHTOOL_GGSO) || defined(ETHTOOL_GFLAGS) || defined(ETHTOOL_GGRO)) static int iface_ethtool_ioctl(pcap_t *handle, int cmd, const char *cmdname) { struct ifreq ifr; struct ethtool_value eval; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, handle->opt.source, sizeof(ifr.ifr_name)); eval.cmd = cmd; ifr.ifr_data = (caddr_t)&eval; if (ioctl(handle->fd, SIOCETHTOOL, &ifr) == -1) { - if (errno == EOPNOTSUPP) { + if (errno == EOPNOTSUPP || errno == EINVAL) { /* * OK, let's just return 0, which, in our * case, either means "no, what we're asking * about is not enabled" or "all the flags * are clear (i.e., nothing is enabled)". */ return 0; } snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "%s: SIOETHTOOL(%s) ioctl failed: %s", handle->opt.source, cmdname, strerror(errno)); return -1; } return eval.data; } static int iface_get_offload(pcap_t *handle) { int ret; #ifdef ETHTOOL_GTSO ret = iface_ethtool_ioctl(handle, ETHTOOL_GTSO, "ETHTOOL_GTSO"); if (ret == -1) return -1; if (ret) return 1; /* TCP segmentation offloading on */ #endif #ifdef ETHTOOL_GUFO ret = iface_ethtool_ioctl(handle, ETHTOOL_GUFO, "ETHTOOL_GUFO"); if (ret == -1) return -1; if (ret) return 1; /* UDP fragmentation offloading on */ #endif #ifdef ETHTOOL_GGSO /* * XXX - will this cause large unsegmented packets to be * handed to PF_PACKET sockets on transmission? If not, * this need not be checked. */ ret = iface_ethtool_ioctl(handle, ETHTOOL_GGSO, "ETHTOOL_GGSO"); if (ret == -1) return -1; if (ret) return 1; /* generic segmentation offloading on */ #endif #ifdef ETHTOOL_GFLAGS ret = iface_ethtool_ioctl(handle, ETHTOOL_GFLAGS, "ETHTOOL_GFLAGS"); if (ret == -1) return -1; if (ret & ETH_FLAG_LRO) return 1; /* large receive offloading on */ #endif #ifdef ETHTOOL_GGRO /* * XXX - will this cause large reassembled packets to be * handed to PF_PACKET sockets on receipt? If not, * this need not be checked. */ ret = iface_ethtool_ioctl(handle, ETHTOOL_GGRO, "ETHTOOL_GGRO"); if (ret == -1) return -1; if (ret) return 1; /* generic (large) receive offloading on */ #endif return 0; } #else /* SIOCETHTOOL */ static int iface_get_offload(pcap_t *handle _U_) { /* * XXX - do we need to get this information if we don't * have the ethtool ioctls? If so, how do we do that? */ return 0; } #endif /* SIOCETHTOOL */ #endif /* HAVE_PF_PACKET_SOCKETS */ /* ===== Functions to interface to the older kernels ================== */ /* * Try to open a packet socket using the old kernel interface. * Returns 1 on success and a PCAP_ERROR_ value on an error. */ static int activate_old(pcap_t *handle) { int arptype; struct ifreq ifr; const char *device = handle->opt.source; struct utsname utsname; int mtu; /* Open the socket */ handle->fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL)); if (handle->fd == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "socket: %s", pcap_strerror(errno)); if (errno == EPERM || errno == EACCES) { /* * You don't have permission to open the * socket. */ return PCAP_ERROR_PERM_DENIED; } else { /* * Other error. */ return PCAP_ERROR; } } /* It worked - we are using the old interface */ handle->md.sock_packet = 1; /* ...which means we get the link-layer header. */ handle->md.cooked = 0; /* Bind to the given device */ if (strcmp(device, "any") == 0) { strncpy(handle->errbuf, "pcap_activate: The \"any\" device isn't supported on 2.0[.x]-kernel systems", PCAP_ERRBUF_SIZE); return PCAP_ERROR; } if (iface_bind_old(handle->fd, device, handle->errbuf) == -1) return PCAP_ERROR; /* * Try to get the link-layer type. */ arptype = iface_get_arptype(handle->fd, device, handle->errbuf); if (arptype < 0) return PCAP_ERROR; /* * Try to find the DLT_ type corresponding to that * link-layer type. */ map_arphrd_to_dlt(handle, arptype, 0); if (handle->linktype == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "unknown arptype %d", arptype); return PCAP_ERROR; } /* Go to promisc mode if requested */ if (handle->opt.promisc) { memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFFLAGS: %s", pcap_strerror(errno)); return PCAP_ERROR; } if ((ifr.ifr_flags & IFF_PROMISC) == 0) { /* * Promiscuous mode isn't currently on, * so turn it on, and remember that * we should turn it off when the * pcap_t is closed. */ /* * If we haven't already done so, arrange * to have "pcap_close_all()" called when * we exit. */ if (!pcap_do_addexit(handle)) { /* * "atexit()" failed; don't put * the interface in promiscuous * mode, just give up. */ return PCAP_ERROR; } ifr.ifr_flags |= IFF_PROMISC; if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "SIOCSIFFLAGS: %s", pcap_strerror(errno)); return PCAP_ERROR; } handle->md.must_do_on_close |= MUST_CLEAR_PROMISC; /* * Add this to the list of pcaps * to close when we exit. */ pcap_add_to_pcaps_to_close(handle); } } /* * Compute the buffer size. * * We're using SOCK_PACKET, so this might be a 2.0[.x] * kernel, and might require special handling - 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. * * 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, handle->errbuf); if (mtu == -1) return PCAP_ERROR; 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 can safely pass "recvfrom()" a byte count * based on the snapshot length. */ handle->bufsize = handle->snapshot; } /* * Default value for offset to align link-layer payload * on a 4-byte boundary. */ handle->offset = 0; + + /* + * SOCK_PACKET sockets don't supply information from + * stripped VLAN tags. + */ + handle->md.vlan_offset = -1; /* unknown */ return 1; } /* * Bind the socket associated with FD to the given device using the * interface of the old kernels. */ static int iface_bind_old(int fd, const char *device, char *ebuf) { struct sockaddr saddr; int err; socklen_t errlen = sizeof(err); memset(&saddr, 0, sizeof(saddr)); strncpy(saddr.sa_data, device, sizeof(saddr.sa_data)); if (bind(fd, &saddr, sizeof(saddr)) == -1) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "bind: %s", pcap_strerror(errno)); return -1; } /* Any pending errors, e.g., network is down? */ if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "getsockopt: %s", pcap_strerror(errno)); return -1; } if (err > 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "bind: %s", pcap_strerror(err)); return -1; } return 0; } /* ===== System calls available on all supported kernels ============== */ /* * Query the kernel for the MTU of the given interface. */ static int iface_get_mtu(int fd, const char *device, char *ebuf) { struct ifreq ifr; if (!device) return BIGGER_THAN_ALL_MTUS; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); if (ioctl(fd, SIOCGIFMTU, &ifr) == -1) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCGIFMTU: %s", pcap_strerror(errno)); return -1; } return ifr.ifr_mtu; } /* * Get the hardware type of the given interface as ARPHRD_xxx constant. */ static int iface_get_arptype(int fd, const char *device, char *ebuf) { struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCGIFHWADDR: %s", pcap_strerror(errno)); if (errno == ENODEV) { /* * No such device. */ return PCAP_ERROR_NO_SUCH_DEVICE; } return PCAP_ERROR; } return ifr.ifr_hwaddr.sa_family; } #ifdef SO_ATTACH_FILTER static int fix_program(pcap_t *handle, struct sock_fprog *fcode, int is_mmapped) { size_t prog_size; register int i; register struct bpf_insn *p; struct bpf_insn *f; int len; /* * Make a copy of the filter, and modify that copy if * necessary. */ prog_size = sizeof(*handle->fcode.bf_insns) * handle->fcode.bf_len; len = handle->fcode.bf_len; f = (struct bpf_insn *)malloc(prog_size); if (f == NULL) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); return -1; } memcpy(f, handle->fcode.bf_insns, prog_size); fcode->len = len; fcode->filter = (struct sock_filter *) f; for (i = 0; i < len; ++i) { p = &f[i]; /* * What type of instruction is this? */ switch (BPF_CLASS(p->code)) { case BPF_RET: /* * It's a return instruction; are we capturing * in memory-mapped mode? */ if (!is_mmapped) { /* * No; is the snapshot length a constant, * rather than the contents of the * accumulator? */ if (BPF_MODE(p->code) == BPF_K) { /* * Yes - if the value to be returned, * i.e. the snapshot length, is * anything other than 0, make it * 65535, so that the packet is * truncated by "recvfrom()", * not by the filter. * * XXX - there's nothing we can * easily do if it's getting the * value from the accumulator; we'd * have to insert code to force * non-zero values to be 65535. */ if (p->k != 0) p->k = 65535; } } break; case BPF_LD: case BPF_LDX: /* * It's a load instruction; is it loading * from the packet? */ switch (BPF_MODE(p->code)) { case BPF_ABS: case BPF_IND: case BPF_MSH: /* * Yes; are we in cooked mode? */ if (handle->md.cooked) { /* * Yes, so we need to fix this * instruction. */ if (fix_offset(p) < 0) { /* * We failed to do so. * Return 0, so our caller * knows to punt to userland. */ return 0; } } break; } break; } } return 1; /* we succeeded */ } static int fix_offset(struct bpf_insn *p) { /* * What's the offset? */ if (p->k >= SLL_HDR_LEN) { /* * It's within the link-layer payload; that starts at an * offset of 0, as far as the kernel packet filter is * concerned, so subtract the length of the link-layer * header. */ p->k -= SLL_HDR_LEN; } else if (p->k == 0) { /* * It's the packet type field; map it to the special magic * kernel offset for that field. */ p->k = SKF_AD_OFF + SKF_AD_PKTTYPE; } else if (p->k == 14) { /* * It's the protocol field; map it to the special magic * kernel offset for that field. */ p->k = SKF_AD_OFF + SKF_AD_PROTOCOL; } else if ((bpf_int32)(p->k) > 0) { /* * It's within the header, but it's not one of those * fields; we can't do that in the kernel, so punt * to userland. */ return -1; } 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 is normally 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) ; save_errno = errno; fcntl(handle->fd, F_SETFL, save_mode); if (save_errno != EAGAIN) { /* Fatal error */ reset_kernel_filter(handle); snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "recv: %s", pcap_strerror(save_errno)); return -2; } } } /* * 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. * valgrind whines unless the value is initialized, * as it has no idea that setsockopt() ignores its * parameter. */ int dummy = 0; return setsockopt(handle->fd, SOL_SOCKET, SO_DETACH_FILTER, &dummy, sizeof(dummy)); } #endif Index: stable/9/contrib/libpcap/pcap-netfilter-linux.c =================================================================== --- stable/9/contrib/libpcap/pcap-netfilter-linux.c (revision 252280) +++ stable/9/contrib/libpcap/pcap-netfilter-linux.c (revision 252281) @@ -1,468 +1,645 @@ /* * Copyright (c) 2011 Jakub Zawadzki * 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. The name of the author may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT * OWNER 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. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "pcap-int.h" #ifdef NEED_STRERROR_H #include "strerror.h" #endif #include #include #include #include #include #include #include #include #include #include #include +#include #include #include +#include +/* NOTE: if your program drops privilages after pcap_activate() it WON'T work with nfqueue. + * It took me quite some time to debug ;/ + * + * Sending any data to nfnetlink socket requires CAP_NET_ADMIN privilages, + * and in nfqueue we need to send verdict reply after recving packet. + * + * In tcpdump you can disable dropping privilages with -Z root + */ + #include "pcap-netfilter-linux.h" #define HDR_LENGTH (NLMSG_LENGTH(NLMSG_ALIGN(sizeof(struct nfgenmsg)))) #define NFLOG_IFACE "nflog" +#define NFQUEUE_IFACE "nfqueue" +typedef enum { OTHER = -1, NFLOG, NFQUEUE } nftype_t; + +static int nfqueue_send_verdict(const pcap_t *handle, u_int16_t group_id, u_int32_t id, u_int32_t verdict); + static int -nflog_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) +netfilter_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) { const unsigned char *buf; int count = 0; int len; /* ignore interrupt system call error */ do { len = recv(handle->fd, handle->buffer, handle->bufsize, 0); if (handle->break_loop) { handle->break_loop = 0; return -2; } } while ((len == -1) && (errno == EINTR)); if (len < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't receive packet %d:%s", errno, pcap_strerror(errno)); return -1; } buf = handle->buffer; while (len >= NLMSG_SPACE(0)) { const struct nlmsghdr *nlh = (const struct nlmsghdr *) buf; u_int32_t msg_len; + nftype_t type = OTHER; if (nlh->nlmsg_len < sizeof(struct nlmsghdr) || len < nlh->nlmsg_len) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Message truncated: (got: %d) (nlmsg_len: %u)", len, nlh->nlmsg_len); return -1; } if (NFNL_SUBSYS_ID(nlh->nlmsg_type) == NFNL_SUBSYS_ULOG && NFNL_MSG_TYPE(nlh->nlmsg_type) == NFULNL_MSG_PACKET) - { + type = NFLOG; + + if (NFNL_SUBSYS_ID(nlh->nlmsg_type) == NFNL_SUBSYS_QUEUE && + NFNL_MSG_TYPE(nlh->nlmsg_type) == NFQNL_MSG_PACKET) + type = NFQUEUE; + + if (type != OTHER) { const unsigned char *payload = NULL; struct pcap_pkthdr pkth; + const struct nfgenmsg *nfg; + int id = 0; + if (handle->linktype != DLT_NFLOG) { const struct nfattr *payload_attr = NULL; if (nlh->nlmsg_len < HDR_LENGTH) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Malformed message: (nlmsg_len: %u)", nlh->nlmsg_len); return -1; } + nfg = NLMSG_DATA(nlh); if (nlh->nlmsg_len > HDR_LENGTH) { - struct nfattr *attr = NFM_NFA(NLMSG_DATA(nlh)); + struct nfattr *attr = NFM_NFA(nfg); int attr_len = nlh->nlmsg_len - NLMSG_ALIGN(HDR_LENGTH); while (NFA_OK(attr, attr_len)) { - switch (NFA_TYPE(attr)) { - case NFULA_PAYLOAD: - payload_attr = attr; - break; + if (type == NFQUEUE) { + switch (NFA_TYPE(attr)) { + case NFQA_PACKET_HDR: + { + const struct nfqnl_msg_packet_hdr *pkt_hdr = (const struct nfqnl_msg_packet_hdr *) NFA_DATA(attr); + + id = ntohl(pkt_hdr->packet_id); + break; + } + case NFQA_PAYLOAD: + payload_attr = attr; + break; + } + + } else if (type == NFLOG) { + switch (NFA_TYPE(attr)) { + case NFULA_PAYLOAD: + payload_attr = attr; + break; + } } attr = NFA_NEXT(attr, attr_len); } } if (payload_attr) { payload = NFA_DATA(payload_attr); pkth.len = pkth.caplen = NFA_PAYLOAD(payload_attr); } } else { payload = NLMSG_DATA(nlh); pkth.caplen = pkth.len = nlh->nlmsg_len-NLMSG_ALIGN(sizeof(struct nlmsghdr)); } if (payload) { /* pkth.caplen = min (payload_len, handle->snapshot); */ gettimeofday(&pkth.ts, NULL); if (handle->fcode.bf_insns == NULL || bpf_filter(handle->fcode.bf_insns, payload, pkth.len, pkth.caplen)) { handle->md.packets_read++; callback(user, &pkth, payload); count++; } } + + if (type == NFQUEUE) { + /* XXX, possible responses: NF_DROP, NF_ACCEPT, NF_STOLEN, NF_QUEUE, NF_REPEAT, NF_STOP */ + nfqueue_send_verdict(handle, ntohs(nfg->res_id), id, NF_ACCEPT); + } } msg_len = NLMSG_ALIGN(nlh->nlmsg_len); if (msg_len > len) msg_len = len; len -= msg_len; buf += msg_len; } return count; } static int netfilter_set_datalink(pcap_t *handle, int dlt) { handle->linktype = dlt; return 0; } static int netfilter_stats_linux(pcap_t *handle, struct pcap_stat *stats) { stats->ps_recv = handle->md.packets_read; stats->ps_drop = 0; stats->ps_ifdrop = 0; return 0; } static int netfilter_inject_linux(pcap_t *handle, const void *buf, size_t size) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on netfilter devices"); return (-1); } struct my_nfattr { u_int16_t nfa_len; u_int16_t nfa_type; void *data; }; static int -nflog_send_config_msg(const pcap_t *handle, u_int8_t family, u_int16_t res_id, const struct my_nfattr *mynfa) +netfilter_send_config_msg(const pcap_t *handle, u_int16_t msg_type, int ack, u_int8_t family, u_int16_t res_id, const struct my_nfattr *mynfa) { char buf[1024] __attribute__ ((aligned)); struct nlmsghdr *nlh = (struct nlmsghdr *) buf; struct nfgenmsg *nfg = (struct nfgenmsg *) (buf + sizeof(struct nlmsghdr)); struct sockaddr_nl snl; static unsigned int seq_id; if (!seq_id) seq_id = time(NULL); ++seq_id; nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct nfgenmsg)); - nlh->nlmsg_type = (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_CONFIG; - nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + nlh->nlmsg_type = msg_type; + nlh->nlmsg_flags = NLM_F_REQUEST | (ack ? NLM_F_ACK : 0); nlh->nlmsg_pid = 0; /* to kernel */ nlh->nlmsg_seq = seq_id; nfg->nfgen_family = family; nfg->version = NFNETLINK_V0; nfg->res_id = htons(res_id); if (mynfa) { struct nfattr *nfa = (struct nfattr *) (buf + NLMSG_ALIGN(nlh->nlmsg_len)); nfa->nfa_type = mynfa->nfa_type; nfa->nfa_len = NFA_LENGTH(mynfa->nfa_len); memcpy(NFA_DATA(nfa), mynfa->data, mynfa->nfa_len); nlh->nlmsg_len = NLMSG_ALIGN(nlh->nlmsg_len) + NFA_ALIGN(nfa->nfa_len); } memset(&snl, 0, sizeof(snl)); snl.nl_family = AF_NETLINK; if (sendto(handle->fd, nlh, nlh->nlmsg_len, 0, (struct sockaddr *) &snl, sizeof(snl)) == -1) return -1; + if (!ack) + return 0; + /* waiting for reply loop */ do { socklen_t addrlen = sizeof(snl); int len; /* ignore interrupt system call error */ do { len = recvfrom(handle->fd, buf, sizeof(buf), 0, (struct sockaddr *) &snl, &addrlen); } while ((len == -1) && (errno == EINTR)); if (len <= 0) return len; if (addrlen != sizeof(snl) || snl.nl_family != AF_NETLINK) { errno = EINVAL; return -1; } nlh = (struct nlmsghdr *) buf; if (snl.nl_pid != 0 || seq_id != nlh->nlmsg_seq) /* if not from kernel or wrong sequence skip */ continue; while (len >= NLMSG_SPACE(0) && NLMSG_OK(nlh, len)) { if (nlh->nlmsg_type == NLMSG_ERROR || (nlh->nlmsg_type == NLMSG_DONE && nlh->nlmsg_flags & NLM_F_MULTI)) { if (nlh->nlmsg_len < NLMSG_ALIGN(sizeof(struct nlmsgerr))) { errno = EBADMSG; return -1; } errno = -(*((int *)NLMSG_DATA(nlh))); return (errno == 0) ? 0 : -1; } nlh = NLMSG_NEXT(nlh, len); } } while (1); return -1; /* never here */ } static int +nflog_send_config_msg(const pcap_t *handle, u_int8_t family, u_int16_t group_id, const struct my_nfattr *mynfa) +{ + return netfilter_send_config_msg(handle, (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_CONFIG, 1, family, group_id, mynfa); +} + +static int nflog_send_config_cmd(const pcap_t *handle, u_int16_t group_id, u_int8_t cmd, u_int8_t family) { struct nfulnl_msg_config_cmd msg; struct my_nfattr nfa; msg.command = cmd; nfa.data = &msg; nfa.nfa_type = NFULA_CFG_CMD; nfa.nfa_len = sizeof(msg); return nflog_send_config_msg(handle, family, group_id, &nfa); } static int nflog_send_config_mode(const pcap_t *handle, u_int16_t group_id, u_int8_t copy_mode, u_int32_t copy_range) { struct nfulnl_msg_config_mode msg; struct my_nfattr nfa; msg.copy_range = htonl(copy_range); msg.copy_mode = copy_mode; nfa.data = &msg; nfa.nfa_type = NFULA_CFG_MODE; nfa.nfa_len = sizeof(msg); return nflog_send_config_msg(handle, AF_UNSPEC, group_id, &nfa); } static int -nflog_activate(pcap_t* handle) +nfqueue_send_verdict(const pcap_t *handle, u_int16_t group_id, u_int32_t id, u_int32_t verdict) { + struct nfqnl_msg_verdict_hdr msg; + struct my_nfattr nfa; + + msg.id = htonl(id); + msg.verdict = htonl(verdict); + + nfa.data = &msg; + nfa.nfa_type = NFQA_VERDICT_HDR; + nfa.nfa_len = sizeof(msg); + + return netfilter_send_config_msg(handle, (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_VERDICT, 0, AF_UNSPEC, group_id, &nfa); +} + +static int +nfqueue_send_config_msg(const pcap_t *handle, u_int8_t family, u_int16_t group_id, const struct my_nfattr *mynfa) +{ + return netfilter_send_config_msg(handle, (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_CONFIG, 1, family, group_id, mynfa); +} + +static int +nfqueue_send_config_cmd(const pcap_t *handle, u_int16_t group_id, u_int8_t cmd, u_int16_t pf) +{ + struct nfqnl_msg_config_cmd msg; + struct my_nfattr nfa; + + msg.command = cmd; + msg.pf = htons(pf); + + nfa.data = &msg; + nfa.nfa_type = NFQA_CFG_CMD; + nfa.nfa_len = sizeof(msg); + + return nfqueue_send_config_msg(handle, AF_UNSPEC, group_id, &nfa); +} + +static int +nfqueue_send_config_mode(const pcap_t *handle, u_int16_t group_id, u_int8_t copy_mode, u_int32_t copy_range) +{ + struct nfqnl_msg_config_params msg; + struct my_nfattr nfa; + + msg.copy_range = htonl(copy_range); + msg.copy_mode = copy_mode; + + nfa.data = &msg; + nfa.nfa_type = NFQA_CFG_PARAMS; + nfa.nfa_len = sizeof(msg); + + return nfqueue_send_config_msg(handle, AF_UNSPEC, group_id, &nfa); +} + +static int +netfilter_activate(pcap_t* handle) +{ const char *dev = handle->opt.source; unsigned short groups[32]; int group_count = 0; + nftype_t type = OTHER; int i; - if (strncmp(dev, NFLOG_IFACE, strlen(NFLOG_IFACE)) == 0) { - dev += strlen(NFLOG_IFACE); + if (strncmp(dev, NFLOG_IFACE, strlen(NFLOG_IFACE)) == 0) { + dev += strlen(NFLOG_IFACE); + type = NFLOG; - /* nflog:30,33,42 looks nice, allow it */ - if (*dev == ':') - dev++; - + } else if (strncmp(dev, NFQUEUE_IFACE, strlen(NFQUEUE_IFACE)) == 0) { + dev += strlen(NFQUEUE_IFACE); + type = NFQUEUE; + } + + if (type != OTHER && *dev == ':') { + dev++; while (*dev) { long int group_id; char *end_dev; if (group_count == 32) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Maximum 32 netfilter groups! dev: %s", handle->opt.source); return PCAP_ERROR; } group_id = strtol(dev, &end_dev, 0); if (end_dev != dev) { if (group_id < 0 || group_id > 65535) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Netfilter group range from 0 to 65535 (got %ld)", group_id); return PCAP_ERROR; } groups[group_count++] = (unsigned short) group_id; dev = end_dev; } if (*dev != ',') break; dev++; } } - if (*dev) { + if (type == OTHER || *dev) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't get netfilter group(s) index from %s", handle->opt.source); return PCAP_ERROR; } /* if no groups, add default: 0 */ if (!group_count) { groups[0] = 0; group_count = 1; } /* Initialize some components of the pcap structure. */ handle->bufsize = 128 + handle->snapshot; handle->offset = 0; - handle->linktype = DLT_NFLOG; - handle->read_op = nflog_read_linux; + handle->read_op = netfilter_read_linux; handle->inject_op = netfilter_inject_linux; handle->setfilter_op = install_bpf_program; /* no kernel filtering */ handle->setdirection_op = NULL; handle->set_datalink_op = NULL; handle->set_datalink_op = netfilter_set_datalink; handle->getnonblock_op = pcap_getnonblock_fd; handle->setnonblock_op = pcap_setnonblock_fd; handle->stats_op = netfilter_stats_linux; /* Create netlink socket */ handle->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER); if (handle->fd < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't create raw socket %d:%s", errno, pcap_strerror(errno)); return PCAP_ERROR; } - handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); - if (handle->dlt_list != NULL) { - handle->dlt_list[0] = DLT_NFLOG; - handle->dlt_list[1] = DLT_IPV4; - handle->dlt_count = 2; - } + if (type == NFLOG) { + handle->linktype = DLT_NFLOG; + handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); + if (handle->dlt_list != NULL) { + handle->dlt_list[0] = DLT_NFLOG; + handle->dlt_list[1] = DLT_IPV4; + handle->dlt_count = 2; + } + } else + handle->linktype = DLT_IPV4; + handle->buffer = malloc(handle->bufsize); if (!handle->buffer) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate dump buffer: %s", pcap_strerror(errno)); goto close_fail; } - if (nflog_send_config_cmd(handle, 0, NFULNL_CFG_CMD_PF_UNBIND, AF_INET) < 0) { - snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFULNL_CFG_CMD_PF_UNBIND: %s", pcap_strerror(errno)); - goto close_fail; - } + if (type == NFLOG) { + if (nflog_send_config_cmd(handle, 0, NFULNL_CFG_CMD_PF_UNBIND, AF_INET) < 0) { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFULNL_CFG_CMD_PF_UNBIND: %s", pcap_strerror(errno)); + goto close_fail; + } - if (nflog_send_config_cmd(handle, 0, NFULNL_CFG_CMD_PF_BIND, AF_INET) < 0) { - snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFULNL_CFG_CMD_PF_BIND: %s", pcap_strerror(errno)); - goto close_fail; - } + if (nflog_send_config_cmd(handle, 0, NFULNL_CFG_CMD_PF_BIND, AF_INET) < 0) { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFULNL_CFG_CMD_PF_BIND: %s", pcap_strerror(errno)); + goto close_fail; + } - /* Bind socket to the nflog groups */ - for (i = 0; i < group_count; i++) { - if (nflog_send_config_cmd(handle, groups[i], NFULNL_CFG_CMD_BIND, AF_UNSPEC) < 0) { - snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't listen on group group index: %s", pcap_strerror(errno)); + /* Bind socket to the nflog groups */ + for (i = 0; i < group_count; i++) { + if (nflog_send_config_cmd(handle, groups[i], NFULNL_CFG_CMD_BIND, AF_UNSPEC) < 0) { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't listen on group group index: %s", pcap_strerror(errno)); + goto close_fail; + } + + if (nflog_send_config_mode(handle, groups[i], NFULNL_COPY_PACKET, handle->snapshot) < 0) { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFULNL_COPY_PACKET: %s", pcap_strerror(errno)); + goto close_fail; + } + } + + } else { + if (nfqueue_send_config_cmd(handle, 0, NFQNL_CFG_CMD_PF_UNBIND, AF_INET) < 0) { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFQNL_CFG_CMD_PF_UNBIND: %s", pcap_strerror(errno)); goto close_fail; } - if (nflog_send_config_mode(handle, groups[i], NFULNL_COPY_PACKET, handle->snapshot) < 0) { - snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFULNL_COPY_PACKET: %s", pcap_strerror(errno)); + if (nfqueue_send_config_cmd(handle, 0, NFQNL_CFG_CMD_PF_BIND, AF_INET) < 0) { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFQNL_CFG_CMD_PF_BIND: %s", pcap_strerror(errno)); goto close_fail; } + + /* Bind socket to the nfqueue groups */ + for (i = 0; i < group_count; i++) { + if (nfqueue_send_config_cmd(handle, groups[i], NFQNL_CFG_CMD_BIND, AF_UNSPEC) < 0) { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't listen on group group index: %s", pcap_strerror(errno)); + goto close_fail; + } + + if (nfqueue_send_config_mode(handle, groups[i], NFQNL_COPY_PACKET, handle->snapshot) < 0) { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFQNL_COPY_PACKET: %s", pcap_strerror(errno)); + goto close_fail; + } + } } if (handle->opt.rfmon) { /* * Monitor mode doesn't apply to netfilter devices. */ pcap_cleanup_live_common(handle); return PCAP_ERROR_RFMON_NOTSUP; } if (handle->opt.buffer_size != 0) { /* * Set the socket buffer size to the specified value. */ if (setsockopt(handle->fd, SOL_SOCKET, SO_RCVBUF, &handle->opt.buffer_size, sizeof(handle->opt.buffer_size)) == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "SO_RCVBUF: %s", pcap_strerror(errno)); goto close_fail; } } handle->selectable_fd = handle->fd; return 0; close_fail: pcap_cleanup_live_common(handle); return PCAP_ERROR; } pcap_t * -nflog_create(const char *device, char *ebuf) +netfilter_create(const char *device, char *ebuf, int *is_ours) { + const char *cp; pcap_t *p; + /* Does this look like an netfilter device? */ + cp = strrchr(device, '/'); + if (cp == NULL) + cp = device; + + /* Does it begin with NFLOG_IFACE or NFQUEUE_IFACE? */ + if (strncmp(cp, NFLOG_IFACE, sizeof NFLOG_IFACE - 1) == 0) + cp += sizeof NFLOG_IFACE - 1; + else if (strncmp(cp, NFQUEUE_IFACE, sizeof NFQUEUE_IFACE - 1) == 0) + cp += sizeof NFQUEUE_IFACE - 1; + else { + /* Nope, doesn't begin with NFLOG_IFACE nor NFQUEUE_IFACE */ + *is_ours = 0; + return NULL; + } + + /* + * Yes - is that either the end of the name, or is it followed + * by a colon? + */ + if (*cp != ':' && *cp != '\0') { + /* Nope */ + *is_ours = 0; + return NULL; + } + + /* OK, it's probably ours. */ + *is_ours = 1; + p = pcap_create_common(device, ebuf); if (p == NULL) return (NULL); - p->activate_op = nflog_activate; + p->activate_op = netfilter_activate; return (p); } int -netfilter_platform_finddevs(pcap_if_t **alldevsp, char *err_str) +netfilter_findalldevs(pcap_if_t **alldevsp, char *err_str) { pcap_if_t *found_dev = *alldevsp; int sock; sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER); if (sock < 0) { /* if netlink is not supported this is not fatal */ if (errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) return 0; snprintf(err_str, PCAP_ERRBUF_SIZE, "Can't open netlink socket %d:%s", errno, pcap_strerror(errno)); return -1; } close(sock); if (pcap_add_if(&found_dev, NFLOG_IFACE, 0, "Linux netfilter log (NFLOG) interface", err_str) < 0) return -1; + if (pcap_add_if(&found_dev, NFQUEUE_IFACE, 0, "Linux netfilter queue (NFQUEUE) interface", err_str) < 0) + return -1; return 0; } - Index: stable/9/contrib/libpcap/pcap-netfilter-linux.h =================================================================== --- stable/9/contrib/libpcap/pcap-netfilter-linux.h (revision 252280) +++ stable/9/contrib/libpcap/pcap-netfilter-linux.h (revision 252281) @@ -1,35 +1,35 @@ /* * Copyright (c) 2011 Jakub Zawadzki * 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. The name of the author may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT * OWNER 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. */ /* * Prototypes for netlink-related functions */ -int netfilter_platform_finddevs(pcap_if_t **alldevsp, char *err_str); -pcap_t *nflog_create(const char *device, char *ebuf); +int netfilter_findalldevs(pcap_if_t **alldevsp, char *err_str); +pcap_t *netfilter_create(const char *device, char *ebuf, int *is_ours); Index: stable/9/contrib/libpcap/pcap-nit.c =================================================================== --- stable/9/contrib/libpcap/pcap-nit.c (revision 252280) +++ stable/9/contrib/libpcap/pcap-nit.c (revision 252281) @@ -1,347 +1,347 @@ /* * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.62 2008-04-14 20:40:58 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pcap-int.h" #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif /* * The chunk size for NIT. This is the amount of buffering * done for read calls. */ #define CHUNKSIZE (2*1024) /* * The total buffer space used by NIT. */ #define BUFSPACE (4*CHUNKSIZE) /* Forwards */ static int nit_setflags(int, int, int, char *); static int pcap_stats_nit(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); } static int pcap_read_nit(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { register int cc, n; register u_char *bp, *cp, *ep; register struct nit_hdr *nh; register int caplen; cc = p->cc; if (cc == 0) { cc = read(p->fd, (char *)p->buffer, p->bufsize); if (cc < 0) { if (errno == EWOULDBLOCK) return (0); snprintf(p->errbuf, sizeof(p->errbuf), "pcap_read: %s", pcap_strerror(errno)); return (-1); } bp = p->buffer; } else bp = p->bp; /* * Loop through each packet. The increment expression * rounds up to the next int boundary past the end of * the previous packet. */ n = 0; ep = bp + cc; while (bp < ep) { /* * Has "pcap_breakloop()" been called? * If so, return immediately - if we haven't read any * packets, clear the flag and return -2 to indicate * that we were told to break out of the loop, otherwise * leave the flag set, so that the *next* call will break * out of the loop without having read any packets, and * return the number of packets we've processed so far. */ if (p->break_loop) { if (n == 0) { p->break_loop = 0; return (-2); } else { p->cc = ep - bp; p->bp = bp; return (n); } } nh = (struct nit_hdr *)bp; cp = bp + sizeof(*nh); switch (nh->nh_state) { case NIT_CATCH: break; case NIT_NOMBUF: case NIT_NOCLUSTER: case NIT_NOSPACE: p->md.stat.ps_drop = nh->nh_dropped; continue; case NIT_SEQNO: continue; default: snprintf(p->errbuf, sizeof(p->errbuf), "bad nit state %d", nh->nh_state); return (-1); } ++p->md.stat.ps_recv; bp += ((sizeof(struct nit_hdr) + nh->nh_datalen + sizeof(int) - 1) & ~(sizeof(int) - 1)); caplen = nh->nh_wirelen; if (caplen > p->snapshot) caplen = p->snapshot; if (bpf_filter(p->fcode.bf_insns, cp, nh->nh_wirelen, caplen)) { struct pcap_pkthdr h; h.ts = nh->nh_timestamp; h.len = nh->nh_wirelen; h.caplen = caplen; (*callback)(user, &h, cp); if (++n >= cnt && cnt > 0) { p->cc = ep - bp; p->bp = bp; return (n); } } } p->cc = 0; return (n); } static int pcap_inject_nit(pcap_t *p, const void *buf, size_t size) { struct sockaddr sa; int ret; memset(&sa, 0, sizeof(sa)); strncpy(sa.sa_data, device, sizeof(sa.sa_data)); ret = sendto(p->fd, buf, size, 0, &sa, sizeof(sa)); if (ret == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s", pcap_strerror(errno)); return (-1); } return (ret); } static int nit_setflags(int fd, int promisc, int to_ms, char *ebuf) { struct nit_ioc nioc; memset(&nioc, 0, sizeof(nioc)); nioc.nioc_bufspace = BUFSPACE; nioc.nioc_chunksize = CHUNKSIZE; nioc.nioc_typetomatch = NT_ALLTYPES; nioc.nioc_snaplen = p->snapshot; nioc.nioc_bufalign = sizeof(int); nioc.nioc_bufoffset = 0; if (to_ms != 0) { nioc.nioc_flags |= NF_TIMEOUT; nioc.nioc_timeout.tv_sec = to_ms / 1000; nioc.nioc_timeout.tv_usec = (to_ms * 1000) % 1000000; } if (promisc) nioc.nioc_flags |= NF_PROMISC; if (ioctl(fd, SIOCSNIT, &nioc) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCSNIT: %s", pcap_strerror(errno)); return (-1); } return (0); } static int pcap_activate_nit(pcap_t *p) { int fd; struct sockaddr_nit snit; if (p->opt.rfmon) { /* * No monitor mode on SunOS 3.x or earlier (no * Wi-Fi *devices* for the hardware that supported * them!). */ return (PCAP_ERROR_RFMON_NOTSUP); } if (p->snapshot < 96) /* * NIT requires a snapshot length of at least 96. */ p->snapshot = 96; memset(p, 0, sizeof(*p)); p->fd = fd = socket(AF_NIT, SOCK_RAW, NITPROTO_RAW); if (fd < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "socket: %s", pcap_strerror(errno)); goto bad; } snit.snit_family = AF_NIT; (void)strncpy(snit.snit_ifname, p->opt.source, NITIFSIZ); if (bind(fd, (struct sockaddr *)&snit, sizeof(snit))) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "bind: %s: %s", snit.snit_ifname, pcap_strerror(errno)); goto bad; } nit_setflags(p->fd, p->opt.promisc, p->md.timeout, p->errbuf); /* * NIT supports only ethernets. */ p->linktype = DLT_EN10MB; p->bufsize = BUFSPACE; p->buffer = (u_char *)malloc(p->bufsize); if (p->buffer == NULL) { strlcpy(p->errbuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); goto bad; } /* * "p->fd" is a socket, so "select()" should work on it. */ p->selectable_fd = p->fd; /* * This is (presumably) a real Ethernet capture; give it a * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so * that an application can let you choose it, in case you're * capturing DOCSIS traffic that a Cisco Cable Modem * Termination System is putting out onto an Ethernet (it * doesn't put an Ethernet header onto the wire, it puts raw * DOCSIS frames out on the wire inside the low-level * Ethernet framing). */ p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); /* * If that fails, just leave the list empty. */ if (p->dlt_list != NULL) { p->dlt_list[0] = DLT_EN10MB; p->dlt_list[1] = DLT_DOCSIS; p->dlt_count = 2; } p->read_op = pcap_read_nit; p->inject_op = pcap_inject_nit; p->setfilter_op = install_bpf_program; /* no kernel filtering */ p->setdirection_op = NULL; /* Not implemented. */ p->set_datalink_op = NULL; /* can't change data link type */ p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; p->stats_op = pcap_stats_nit; return (0); bad: pcap_cleanup_live_common(p); return (PCAP_ERROR); } pcap_t * -pcap_create(const char *device, char *ebuf) +pcap_create_interface(const char *device, char *ebuf) { pcap_t *p; p = pcap_create_common(device, ebuf); if (p == NULL) return (NULL); p->activate_op = pcap_activate_nit; return (p); } int pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) { return (0); } Index: stable/9/contrib/libpcap/pcap-null.c =================================================================== --- stable/9/contrib/libpcap/pcap-null.c (revision 252280) +++ stable/9/contrib/libpcap/pcap-null.c (revision 252281) @@ -1,53 +1,53 @@ /* * Copyright (c) 1994, 1995, 1996 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/pcap-null.c,v 1.22 2008-04-04 19:37:45 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include /* optionally get BSD define */ #include #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif #include "pcap-int.h" static char nosup[] = "live packet capture not supported on this system"; pcap_t * -pcap_create(const char *device, char *ebuf) +pcap_create_interface(const char *device, char *ebuf) { (void)strlcpy(ebuf, nosup, PCAP_ERRBUF_SIZE); return (NULL); } int pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) { return (0); } Index: stable/9/contrib/libpcap/pcap-pf.c =================================================================== --- stable/9/contrib/libpcap/pcap-pf.c (revision 252280) +++ stable/9/contrib/libpcap/pcap-pf.c (revision 252281) @@ -1,604 +1,604 @@ /* * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * packet filter subroutines for tcpdump * Extraction/creation by Jeffrey Mogul, DECWRL */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.97 2008-04-14 20:40:58 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include struct mbuf; struct rtentry; #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Make "pcap.h" not include "pcap/bpf.h"; we are going to include the * native OS version, as we need various BPF ioctls from it. */ #define PCAP_DONT_INCLUDE_PCAP_BPF_H #include #include "pcap-int.h" #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif static int pcap_setfilter_pf(pcap_t *, struct bpf_program *); /* * BUFSPACE is the size in bytes of the packet read buffer. Most tcpdump * applications aren't going to need more than 200 bytes of packet header * and the read shouldn't return more packets than packetfilter's internal * queue limit (bounded at 256). */ #define BUFSPACE (200 * 256) static int pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user) { register u_char *p, *bp; register int cc, n, buflen, inc; register struct enstamp *sp; #ifdef LBL_ALIGN struct enstamp stamp; #endif #ifdef PCAP_FDDIPAD register int pad; #endif again: cc = pc->cc; if (cc == 0) { cc = read(pc->fd, (char *)pc->buffer + pc->offset, pc->bufsize); if (cc < 0) { if (errno == EWOULDBLOCK) return (0); if (errno == EINVAL && lseek(pc->fd, 0L, SEEK_CUR) + pc->bufsize < 0) { /* * Due to a kernel bug, after 2^31 bytes, * the kernel file offset overflows and * read fails with EINVAL. The lseek() * to 0 will fix things. */ (void)lseek(pc->fd, 0L, SEEK_SET); goto again; } snprintf(pc->errbuf, sizeof(pc->errbuf), "pf read: %s", pcap_strerror(errno)); return (-1); } bp = pc->buffer + pc->offset; } else bp = pc->bp; /* * Loop through each packet. */ n = 0; #ifdef PCAP_FDDIPAD pad = pc->fddipad; #endif while (cc > 0) { /* * Has "pcap_breakloop()" been called? * If so, return immediately - if we haven't read any * packets, clear the flag and return -2 to indicate * that we were told to break out of the loop, otherwise * leave the flag set, so that the *next* call will break * out of the loop without having read any packets, and * return the number of packets we've processed so far. */ if (pc->break_loop) { if (n == 0) { pc->break_loop = 0; return (-2); } else { pc->cc = cc; pc->bp = bp; return (n); } } if (cc < sizeof(*sp)) { snprintf(pc->errbuf, sizeof(pc->errbuf), "pf short read (%d)", cc); return (-1); } #ifdef LBL_ALIGN if ((long)bp & 3) { sp = &stamp; memcpy((char *)sp, (char *)bp, sizeof(*sp)); } else #endif sp = (struct enstamp *)bp; if (sp->ens_stamplen != sizeof(*sp)) { snprintf(pc->errbuf, sizeof(pc->errbuf), "pf short stamplen (%d)", sp->ens_stamplen); return (-1); } p = bp + sp->ens_stamplen; buflen = sp->ens_count; if (buflen > pc->snapshot) buflen = pc->snapshot; /* Calculate inc before possible pad update */ inc = ENALIGN(buflen + sp->ens_stamplen); cc -= inc; bp += inc; pc->md.TotPkts++; pc->md.TotDrops += sp->ens_dropped; pc->md.TotMissed = sp->ens_ifoverflows; if (pc->md.OrigMissed < 0) pc->md.OrigMissed = pc->md.TotMissed; /* * Short-circuit evaluation: if using BPF filter * in kernel, no need to do it now - we already know * the packet passed the filter. * #ifdef PCAP_FDDIPAD * Note: the filter code was generated assuming * that pc->fddipad was the amount of padding * before the header, as that's what's required * in the kernel, so we run the filter before * skipping that padding. #endif */ if (pc->md.use_bpf || bpf_filter(pc->fcode.bf_insns, p, sp->ens_count, buflen)) { struct pcap_pkthdr h; pc->md.TotAccepted++; h.ts = sp->ens_tstamp; #ifdef PCAP_FDDIPAD h.len = sp->ens_count - pad; #else h.len = sp->ens_count; #endif #ifdef PCAP_FDDIPAD p += pad; buflen -= pad; #endif h.caplen = buflen; (*callback)(user, &h, p); if (++n >= cnt && cnt > 0) { pc->cc = cc; pc->bp = bp; return (n); } } } pc->cc = 0; return (n); } static int pcap_inject_pf(pcap_t *p, const void *buf, size_t size) { int ret; ret = write(p->fd, buf, size); if (ret == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s", pcap_strerror(errno)); return (-1); } return (ret); } static int pcap_stats_pf(pcap_t *p, struct pcap_stat *ps) { /* * 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; return (0); } /* * We include the OS's , not our "pcap/bpf.h", so we probably * don't get DLT_DOCSIS defined. */ #ifndef DLT_DOCSIS #define DLT_DOCSIS 143 #endif static int pcap_activate_pf(pcap_t *p) { short enmode; int backlog = -1; /* request the most */ struct enfilter Filter; struct endevp devparams; /* * Initially try a read/write open (to allow the inject * method to work). If that fails due to permission * issues, fall back to read-only. This allows a * non-root user to be granted specific access to pcap * capabilities via file permissions. * * XXX - we should have an API that has a flag that * controls whether to open read-only or read-write, * so that denial of permission to send (or inability * to send, if sending packets isn't supported on * the device in question) can be indicated at open * time. * * XXX - we assume here that "pfopen()" does not, in fact, modify * its argument, even though it takes a "char *" rather than a * "const char *" as its first argument. That appears to be * the case, at least on Digital UNIX 4.0. */ p->fd = pfopen(p->opt.source, O_RDWR); if (p->fd == -1 && errno == EACCES) p->fd = pfopen(p->opt.source, O_RDONLY); if (p->fd < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "pf open: %s: %s\n\ your system may not be properly configured; see the packetfilter(4) man page\n", p->opt.source, pcap_strerror(errno)); goto bad; } p->md.OrigMissed = -1; enmode = ENTSTAMP|ENBATCH|ENNONEXCL; if (p->opt.promisc) enmode |= ENPROMISC; if (ioctl(p->fd, EIOCMBIS, (caddr_t)&enmode) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCMBIS: %s", pcap_strerror(errno)); goto bad; } #ifdef ENCOPYALL /* Try to set COPYALL mode so that we see packets to ourself */ enmode = ENCOPYALL; (void)ioctl(p->fd, EIOCMBIS, (caddr_t)&enmode);/* OK if this fails */ #endif /* set the backlog */ if (ioctl(p->fd, EIOCSETW, (caddr_t)&backlog) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCSETW: %s", pcap_strerror(errno)); goto bad; } /* discover interface type */ if (ioctl(p->fd, EIOCDEVP, (caddr_t)&devparams) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCDEVP: %s", pcap_strerror(errno)); goto bad; } /* HACK: to compile prior to Ultrix 4.2 */ #ifndef ENDT_FDDI #define ENDT_FDDI 4 #endif switch (devparams.end_dev_type) { case ENDT_10MB: p->linktype = DLT_EN10MB; p->offset = 2; /* * This is (presumably) a real Ethernet capture; give it a * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so * that an application can let you choose it, in case you're * capturing DOCSIS traffic that a Cisco Cable Modem * Termination System is putting out onto an Ethernet (it * doesn't put an Ethernet header onto the wire, it puts raw * DOCSIS frames out on the wire inside the low-level * Ethernet framing). */ p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); /* * If that fails, just leave the list empty. */ if (p->dlt_list != NULL) { p->dlt_list[0] = DLT_EN10MB; p->dlt_list[1] = DLT_DOCSIS; p->dlt_count = 2; } break; case ENDT_FDDI: p->linktype = DLT_FDDI; break; #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(p->errbuf, PCAP_ERRBUF_SIZE, "unknown data-link type %u", devparams.end_dev_type); goto bad; } /* set truncation */ #ifdef PCAP_FDDIPAD if (p->linktype == DLT_FDDI) { p->fddipad = PCAP_FDDIPAD; /* packetfilter includes the padding in the snapshot */ p->snapshot += PCAP_FDDIPAD; } else p->fddipad = 0; #endif if (ioctl(p->fd, EIOCTRUNCATE, (caddr_t)&p->snapshot) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCTRUNCATE: %s", pcap_strerror(errno)); goto bad; } /* accept all packets */ memset(&Filter, 0, sizeof(Filter)); Filter.enf_Priority = 37; /* anything > 2 */ Filter.enf_FilterLen = 0; /* means "always true" */ if (ioctl(p->fd, EIOCSETF, (caddr_t)&Filter) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCSETF: %s", pcap_strerror(errno)); goto bad; } if (p->md.timeout != 0) { struct timeval timeout; timeout.tv_sec = p->md.timeout / 1000; timeout.tv_usec = (p->md.timeout * 1000) % 1000000; if (ioctl(p->fd, EIOCSRTIMEOUT, (caddr_t)&timeout) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCSRTIMEOUT: %s", pcap_strerror(errno)); goto bad; } } p->bufsize = BUFSPACE; p->buffer = (u_char*)malloc(p->bufsize + p->offset); if (p->buffer == NULL) { strlcpy(p->errbuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); goto bad; } /* * "select()" and "poll()" work on packetfilter devices. */ p->selectable_fd = p->fd; p->read_op = pcap_read_pf; p->inject_op = pcap_inject_pf; p->setfilter_op = pcap_setfilter_pf; p->setdirection_op = NULL; /* Not implemented. */ p->set_datalink_op = NULL; /* can't change data link type */ p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; p->stats_op = pcap_stats_pf; return (0); bad: pcap_cleanup_live_common(p); return (PCAP_ERROR); } pcap_t * -pcap_create(const char *device, char *ebuf) +pcap_create_interface(const char *device, char *ebuf) { pcap_t *p; p = pcap_create_common(device, ebuf); if (p == NULL) return (NULL); p->activate_op = pcap_activate_pf; return (p); } int pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) { return (0); } static int pcap_setfilter_pf(pcap_t *p, struct bpf_program *fp) { struct bpf_version bv; /* * See if BIOCVERSION works. If not, we assume the kernel doesn't * support BPF-style filters (it's not documented in the bpf(7) * or packetfiler(7) man pages, but the code used to fail if * BIOCSETF worked but BIOCVERSION didn't, and I've seen it do * kernel filtering in DU 4.0, so presumably BIOCVERSION works * there, at least). */ if (ioctl(p->fd, BIOCVERSION, (caddr_t)&bv) >= 0) { /* * OK, we have the version of the BPF interpreter; * is it the same major version as us, and the same * or better minor version? */ if (bv.bv_major == BPF_MAJOR_VERSION && bv.bv_minor >= BPF_MINOR_VERSION) { /* * Yes. Try to install the filter. */ if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) < 0) { snprintf(p->errbuf, sizeof(p->errbuf), "BIOCSETF: %s", pcap_strerror(errno)); return (-1); } /* * OK, that succeeded. We're doing filtering in * the kernel. (We assume we don't have a * userland filter installed - that'd require * a previous version check to have failed but * this one to succeed.) * * XXX - this message should be supplied to the * application as a warning of some sort, * except that if it's a GUI application, it's * not clear that it should be displayed in * a window to annoy the user. */ fprintf(stderr, "tcpdump: Using kernel BPF filter\n"); p->md.use_bpf = 1; /* * Discard any previously-received packets, * as they might have passed whatever filter * was formerly in effect, but might not pass * this filter (BIOCSETF discards packets buffered * in the kernel, so you can lose packets in any * case). */ p->cc = 0; return (0); } /* * We can't use the kernel's BPF interpreter; don't give * up, just log a message and be inefficient. * * XXX - this should really be supplied to the application * as a warning of some sort. */ fprintf(stderr, "tcpdump: Requires BPF language %d.%d or higher; kernel is %d.%d\n", BPF_MAJOR_VERSION, BPF_MINOR_VERSION, bv.bv_major, bv.bv_minor); } /* * We couldn't do filtering in the kernel; do it in userland. */ if (install_bpf_program(p, fp) < 0) return (-1); /* * XXX - this message should be supplied by the application as * a warning of some sort. */ fprintf(stderr, "tcpdump: Filtering in user process\n"); p->md.use_bpf = 0; return (0); } Index: stable/9/contrib/libpcap/pcap-septel.c =================================================================== --- stable/9/contrib/libpcap/pcap-septel.c (revision 252280) +++ stable/9/contrib/libpcap/pcap-septel.c (revision 252281) @@ -1,290 +1,295 @@ /* * pcap-septel.c: Packet capture interface for Intel/Septel card. * * The functionality of this code attempts to mimic that of pcap-linux as much * as possible. This code is compiled in several different ways depending on * whether SEPTEL_ONLY and HAVE_SEPTEL_API are defined. If HAVE_SEPTEL_API is * not defined it should not get compiled in, otherwise if SEPTEL_ONLY is * defined then the 'septel_' function calls are renamed to 'pcap_' * equivalents. If SEPTEL_ONLY is not defined then nothing is altered - the * septel_ functions will be called as required from their * pcap-linux/equivalents. * * Authors: Gilbert HOYEK (gil_hoyek@hotmail.com), Elias M. KHOURY * (+961 3 485243) */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/pcap-septel.c,v 1.4 2008-04-14 20:40:58 guy Exp $"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "pcap-int.h" #include #include #include #include #include #include -#ifdef HAVE_SEPTEL_API #include #include #include #include #include -#endif /* HAVE_SEPTEL_API */ -#ifdef SEPTEL_ONLY -/* This code is required when compiling for a Septel device only. */ #include "pcap-septel.h" -/* Replace septel function names with pcap equivalent. */ -#define septel_create pcap_create -#define septel_platform_finddevs pcap_platform_finddevs -#endif /* SEPTEL_ONLY */ - static int septel_setfilter(pcap_t *p, struct bpf_program *fp); static int septel_stats(pcap_t *p, struct pcap_stat *ps); static int septel_setnonblock(pcap_t *p, int nonblock, char *errbuf); /* * Read at most max_packets from the capture queue and call the callback * for each of them. Returns the number of packets handled, -1 if an * error occured, or -2 if we were told to break out of the loop. */ static int septel_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { HDR *h; MSG *m; int processed = 0 ; int t = 0 ; /* identifier for the message queue of the module(upe) from which we are capturing * packets.These IDs are defined in system.txt . By default it is set to 0x2d * so change it to 0xdd for technical reason and therefore the module id for upe becomes: * LOCAL 0xdd * upe - Example user part task */ unsigned int id = 0xdd; /* process the packets */ do { unsigned short packet_len = 0; int caplen = 0; int counter = 0; struct pcap_pkthdr pcap_header; u_char *dp ; /* * Has "pcap_breakloop()" been called? */ loop: if (p->break_loop) { /* * Yes - clear the flag that indicates that * it has, and return -2 to indicate that * we were told to break out of the loop. */ p->break_loop = 0; return -2; } /*repeat until a packet is read *a NULL message means : * when no packet is in queue or all packets in queue already read */ do { /* receive packet in non-blocking mode * GCT_grab is defined in the septel library software */ h = GCT_grab(id); m = (MSG*)h; /* a couter is added here to avoid an infinite loop * that will cause our capture program GUI to freeze while waiting * for a packet*/ counter++ ; } while ((m == NULL)&& (counter< 100)) ; if (m != NULL) { t = h->type ; /* catch only messages with type = 0xcf00 or 0x8f01 corrsponding to ss7 messages*/ /* XXX = why not use API_MSG_TX_REQ for 0xcf00 and API_MSG_RX_IND * for 0x8f01? */ if ((t != 0xcf00) && (t != 0x8f01)) { relm(h); goto loop ; } /* XXX - is API_MSG_RX_IND for an MTP2 or MTP3 message? */ dp = get_param(m);/* get pointer to MSG parameter area (m->param) */ packet_len = m->len; caplen = p->snapshot ; if (caplen > packet_len) { caplen = packet_len; } /* Run the packet filter if there is one. */ if ((p->fcode.bf_insns == NULL) || bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen)) { /* get a time stamp , consisting of : * * pcap_header.ts.tv_sec: * ---------------------- * a UNIX format time-in-seconds when he packet was captured, * i.e. the number of seconds since Epoch time (January 1,1970, 00:00:00 GMT) * * pcap_header.ts.tv_usec : * ------------------------ * the number of microseconds since that second * when the packet was captured */ (void)gettimeofday(&pcap_header.ts, NULL); /* Fill in our own header data */ pcap_header.caplen = caplen; pcap_header.len = packet_len; /* Count the packet. */ p->md.stat.ps_recv++; /* Call the user supplied callback function */ callback(user, &pcap_header, dp); processed++ ; } /* after being processed the packet must be *released in order to receive another one */ relm(h); }else processed++; } while (processed < cnt) ; return processed ; } static int septel_inject(pcap_t *handle, const void *buf _U_, size_t size _U_) { strlcpy(handle->errbuf, "Sending packets isn't supported on Septel cards", PCAP_ERRBUF_SIZE); return (-1); } /* * Activate a handle for a live capture from the given Septel device. Always pass a NULL device * The promisc flag is ignored because Septel cards have built-in tracing. * The timeout is also ignored as it is not supported in hardware. * * See also pcap(3). */ static pcap_t *septel_activate(pcap_t* handle) { /* Initialize some components of the pcap structure. */ handle->linktype = DLT_MTP2; handle->bufsize = 0; /* * "select()" and "poll()" don't work on Septel queues */ handle->selectable_fd = -1; handle->read_op = septel_read; handle->inject_op = septel_inject; handle->setfilter_op = septel_setfilter; handle->set_datalink_op = NULL; /* can't change data link type */ handle->getnonblock_op = pcap_getnonblock_fd; handle->setnonblock_op = septel_setnonblock; handle->stats_op = septel_stats; return 0; } -pcap_t *septel_create(const char *device, char *ebuf) { +pcap_t *septel_create(const char *device, char *ebuf, int *is_ours) { + const char *cp; pcap_t *p; + /* Does this look like the Septel device? */ + cp = strrchr(device, '/'); + if (cp == NULL) + cp = device; + if (strcmp(cp, "septel") != 0) { + /* Nope, it's not "septel" */ + *is_ours = 0; + return NULL; + } + + /* OK, it's probably ours. */ + *is_ours = 1; + p = pcap_create_common(device, ebuf); if (p == NULL) return NULL; p->activate_op = septel_activate; return p; } static int septel_stats(pcap_t *p, struct pcap_stat *ps) { /*p->md.stat.ps_recv = 0;*/ /*p->md.stat.ps_drop = 0;*/ *ps = p->md.stat; return 0; } int -septel_platform_finddevs(pcap_if_t **devlistp, char *errbuf) +septel_findalldevs(pcap_if_t **devlistp, char *errbuf) { unsigned char *p; const char description[512]= "Intel/Septel device"; char name[512]="septel" ; int ret = 0; pcap_add_if(devlistp,name,0,description,errbuf); return (ret); } /* * Installs the given bpf filter program in the given pcap structure. There is * no attempt to store the filter in kernel memory as that is not supported * with Septel cards. */ static int septel_setfilter(pcap_t *p, struct bpf_program *fp) { if (!p) return -1; if (!fp) { strncpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf)); return -1; } /* Make our private copy of the filter */ if (install_bpf_program(p, fp) < 0) { snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", pcap_strerror(errno)); return -1; } p->md.use_bpf = 0; return (0); } static int septel_setnonblock(pcap_t *p, int nonblock, char *errbuf) { return (0); } Index: stable/9/contrib/libpcap/pcap-septel.h =================================================================== --- stable/9/contrib/libpcap/pcap-septel.h (revision 252280) +++ stable/9/contrib/libpcap/pcap-septel.h (revision 252281) @@ -1,15 +1,15 @@ /* * pcap-septel.c: Packet capture interface for Intel Septel card * * The functionality of this code attempts to mimic that of pcap-linux as much * as possible. This code is only needed when compiling in the Intel/Septel * card code at the same time as another type of device. * * Authors: Gilbert HOYEK (gil_hoyek@hotmail.com), Elias M. KHOURY * (+961 3 485343); * * @(#) $Header: /tcpdump/master/libpcap/pcap-septel.h,v 1.2 2008-04-04 19:37:45 guy Exp $ */ -pcap_t *septel_create(const char *device, char *ebuf); - +pcap_t *septel_create(const char *device, char *ebuf, int *is_ours); +int septel_findalldevs(pcap_if_t **devlistp, char *errbuf); Index: stable/9/contrib/libpcap/pcap-sita.c =================================================================== --- stable/9/contrib/libpcap/pcap-sita.c (revision 252280) +++ stable/9/contrib/libpcap/pcap-sita.c (revision 252281) @@ -1,980 +1,1011 @@ /* * pcap-sita.c: Packet capture interface additions for SITA ACN devices * * Copyright (c) 2007 Fulko Hew, SITA INC Canada, Inc * * License: BSD * * 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. The names of the authors may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ /* $Id: pcap-sita.c */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include "pcap-int.h" #include "pcap-sita.h" /* non-configureable manifests follow */ #define IOP_SNIFFER_PORT 49152 /* TCP port on the IOP used for 'distributed pcap' usage */ #define MAX_LINE_SIZE 255 /* max size of a buffer/line in /etc/hosts we allow */ #define MAX_CHASSIS 8 /* number of chassis in an ACN site */ #define MAX_GEOSLOT 8 /* max number of access units in an ACN site */ #define FIND 0 #define LIVE 1 typedef struct iface { struct iface *next; /* a pointer to the next interface */ char *name; /* this interface's name on Wireshark */ char *IOPname; /* this interface's name on an IOP */ uint32_t iftype; /* the type of interface (DLT values) */ } iface_t; typedef struct unit { char *ip; /* this unit's IP address (as extracted from /etc/hosts) */ int fd; /* the connection to this unit (if it exists) */ int find_fd; /* a big kludge to avoid my programming limitations since I could have this unit open for findalldevs purposes */ int first_time; /* 0 = just opened via acn_open_live(), ie. the first time, NZ = nth time */ struct sockaddr_in *serv_addr; /* the address control block for comms to this unit */ int chassis; int geoslot; iface_t *iface; /* a pointer to a linked list of interface structures */ char *imsg; /* a pointer to an inbound message */ int len; /* the current size of the inbound message */ } unit_t; static char *errorString; static unit_t units[MAX_CHASSIS+1][MAX_GEOSLOT+1]; /* we use indexes of 1 through 8, but we reserve/waste index 0 */ static fd_set readfds; /* a place to store the file descriptors for the connections to the IOPs */ static fd_set working_set; static int max_fs; static char static_buf[32]; pcap_if_t *acn_if_list; /* pcap's list of available interfaces */ static void dump_interface_list(void) { pcap_if_t *iff; pcap_addr_t *addr; int longest_name_len = 0; char *n, *d, *f; int if_number = 0; iff = acn_if_list; while (iff) { if (iff->name && (strlen(iff->name) > longest_name_len)) longest_name_len = strlen(iff->name); iff = iff->next; } iff = acn_if_list; printf("Interface List:\n"); while (iff) { n = (iff->name) ? iff->name : ""; d = (iff->description) ? iff->description : ""; f = (iff->flags == PCAP_IF_LOOPBACK) ? "L" : ""; printf("%3d: %*s %s '%s'\n", if_number++, longest_name_len, n, f, d); addr = iff->addresses; while (addr) { printf("%*s ", (5 + longest_name_len), ""); /* add some indentation */ printf("%15s ", (addr->addr) ? inet_ntoa(((struct sockaddr_in *)addr->addr)->sin_addr) : ""); printf("%15s ", (addr->netmask) ? inet_ntoa(((struct sockaddr_in *)addr->netmask)->sin_addr) : ""); printf("%15s ", (addr->broadaddr) ? inet_ntoa(((struct sockaddr_in *)addr->broadaddr)->sin_addr) : ""); printf("%15s ", (addr->dstaddr) ? inet_ntoa(((struct sockaddr_in *)addr->dstaddr)->sin_addr) : ""); printf("\n"); addr = addr->next; } iff = iff->next; } } static void dump(unsigned char *ptr, int i, int indent) { fprintf(stderr, "%*s", indent, " "); for (; i > 0; i--) { fprintf(stderr, "%2.2x ", *ptr++); } fprintf(stderr, "\n"); } static void dump_interface_list_p(void) { pcap_if_t *iff; pcap_addr_t *addr; int if_number = 0; iff = acn_if_list; printf("Interface Pointer @ %p is %p:\n", &acn_if_list, iff); while (iff) { printf("%3d: %p %p next: %p\n", if_number++, iff->name, iff->description, iff->next); dump((unsigned char *)iff, sizeof(pcap_if_t), 5); addr = iff->addresses; while (addr) { printf(" %p %p %p %p, next: %p\n", addr->addr, addr->netmask, addr->broadaddr, addr->dstaddr, addr->next); dump((unsigned char *)addr, sizeof(pcap_addr_t), 10); addr = addr->next; } iff = iff->next; } } static void dump_unit_table(void) { int chassis, geoslot; iface_t *p; printf("%c:%c %s %s\n", 'C', 'S', "fd", "IP Address"); for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) { for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) { if (units[chassis][geoslot].ip != NULL) printf("%d:%d %2d %s\n", chassis, geoslot, units[chassis][geoslot].fd, units[chassis][geoslot].ip); p = units[chassis][geoslot].iface; while (p) { char *n = (p->name) ? p->name : ""; char *i = (p->IOPname) ? p->IOPname : ""; p = p->next; printf(" %12s -> %12s\n", i, n); } } } } static int find_unit_by_fd(int fd, int *chassis, int *geoslot, unit_t **unit_ptr) { int c, s; for (c = 0; c <= MAX_CHASSIS; c++) { for (s = 0; s <= MAX_GEOSLOT; s++) { if (units[c][s].fd == fd || units[c][s].find_fd == fd) { if (chassis) *chassis = c; if (geoslot) *geoslot = s; if (unit_ptr) *unit_ptr = &units[c][s]; return 1; } } } return 0; } static int read_client_nbytes(int fd, int count, unsigned char *buf) { unit_t *u; int chassis, geoslot; int len; find_unit_by_fd(fd, &chassis, &geoslot, &u); while (count) { if ((len = recv(fd, buf, count, 0)) <= 0) return -1; /* read in whatever data was sent to us */ count -= len; buf += len; } /* till we have everything we are looking for */ return 0; } static void empty_unit_iface(unit_t *u) { iface_t *p, *cur; cur = u->iface; while (cur) { /* loop over all the interface entries */ if (cur->name) free(cur->name); /* throwing away the contents if they exist */ if (cur->IOPname) free(cur->IOPname); p = cur->next; free(cur); /* then throw away the structure itself */ cur = p; } u->iface = 0; /* and finally remember that there are no remaining structure */ } static void empty_unit(int chassis, int geoslot) { unit_t *u = &units[chassis][geoslot]; empty_unit_iface(u); if (u->imsg) { /* then if an inbound message buffer exists */ u->imsg = (char *)realloc(u->imsg, 1); /* and re-allocate the old large buffer into a new small one */ + if (u->imsg == NULL) { /* oops, realloc call failed */ + fprintf(stderr, "Warning...call to realloc() failed, value of errno is %d\n", errno); + } } static void empty_unit_table(void) { int chassis, geoslot; for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) { for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) { if (units[chassis][geoslot].ip != NULL) { free(units[chassis][geoslot].ip); /* get rid of the malloc'ed space that holds the IP address */ units[chassis][geoslot].ip = 0; /* then set the pointer to NULL */ } empty_unit(chassis, geoslot); } } } static char *find_nth_interface_name(int n) { int chassis, geoslot; iface_t *p; char *last_name = 0; if (n < 0) n = 0; /* ensure we are working with a valid number */ for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) { /* scan the table... */ for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) { if (units[chassis][geoslot].ip != NULL) { p = units[chassis][geoslot].iface; while (p) { /* and all interfaces... */ if (p->IOPname) last_name = p->name; /* remembering the last name found */ if (n-- == 0) return last_name; /* and if we hit the instance requested */ p = p->next; } } } } /* if we couldn't fine the selected entry */ if (last_name) return last_name; /* ... but we did have at least one entry... return the last entry found */ return ""; /* ... but if there wasn't any entry... return an empty string instead */ } int acn_parse_hosts_file(char *errbuf) { /* returns: -1 = error, 0 = OK */ FILE *fp; char buf[MAX_LINE_SIZE]; char *ptr, *ptr2; int pos; int chassis, geoslot; unit_t *u; empty_unit_table(); if ((fp = fopen("/etc/hosts", "r")) == NULL) { /* try to open the hosts file and if it fails */ snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot open '/etc/hosts' for reading."); /* return the nohostsfile error response */ return -1; } while (fgets(buf, MAX_LINE_SIZE-1, fp)) { /* while looping over the file */ pos = strcspn(buf, "#\n\r"); /* find the first comment character or EOL */ *(buf + pos) = '\0'; /* and clobber it and anything that follows it */ pos = strspn(buf, " \t"); /* then find the first non-white space */ if (pos == strlen(buf)) /* if there is nothing but white space on the line */ continue; /* ignore that empty line */ ptr = buf + pos; /* and skip over any of that leading whitespace */ if ((ptr2 = strstr(ptr, "_I_")) == NULL) /* skip any lines that don't have names that look like they belong to IOPs */ continue; if (*(ptr2 + 4) != '_') /* and skip other lines that have names that don't look like ACN components */ continue; *(ptr + strcspn(ptr, " \t")) = '\0'; /* null terminate the IP address so its a standalone string */ chassis = *(ptr2 + 3) - '0'; /* extract the chassis number */ geoslot = *(ptr2 + 5) - '0'; /* and geo-slot number */ if (chassis < 1 || chassis > MAX_CHASSIS || geoslot < 1 || geoslot > MAX_GEOSLOT) { /* if the chassis and/or slot numbers appear to be bad... */ snprintf(errbuf, PCAP_ERRBUF_SIZE, "Invalid ACN name in '/etc/hosts'."); /* warn the user */ continue; /* and ignore the entry */ } if ((ptr2 = (char *)malloc(strlen(ptr) + 1)) == NULL) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); continue; } strcpy(ptr2, ptr); /* copy the IP address into our malloc'ed memory */ u = &units[chassis][geoslot]; u->ip = ptr2; /* and remember the whole shebang */ u->chassis = chassis; u->geoslot = geoslot; } fclose(fp); if (*errbuf) return -1; else return 0; } static int open_with_IOP(unit_t *u, int flag) { int sockfd; char *ip; if (u->serv_addr == NULL) { u->serv_addr = malloc(sizeof(struct sockaddr_in)); + + /* since we called malloc(), lets check to see if we actually got the memory */ + if (u->serv_addr == NULL) { /* oops, we didn't get the memory requested */ + fprintf(stderr, "malloc() request for u->serv_addr failed, value of errno is: %d\n", errno); + return 0; + } + } ip = u->ip; - bzero((char *)u->serv_addr, sizeof(struct sockaddr_in)); + /* bzero() is deprecated, replaced with memset() */ + memset((char *)u->serv_addr, 0, sizeof(struct sockaddr_in)); u->serv_addr->sin_family = AF_INET; u->serv_addr->sin_addr.s_addr = inet_addr(ip); u->serv_addr->sin_port = htons(IOP_SNIFFER_PORT); if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { fprintf(stderr, "pcap can't open a socket for connecting to IOP at %s\n", ip); return 0; } if (connect(sockfd, (struct sockaddr *)u->serv_addr, sizeof(struct sockaddr_in)) < 0) { fprintf(stderr, "pcap can't connect to IOP at %s\n", ip); return 0; } if (flag == LIVE) u->fd = sockfd; else u->find_fd = sockfd; u->first_time = 0; return sockfd; /* return the non-zero file descriptor as a 'success' indicator */ } static void close_with_IOP(int chassis, int geoslot, int flag) { int *id; if (flag == LIVE) id = &units[chassis][geoslot].fd; else id = &units[chassis][geoslot].find_fd; if (*id) { /* this was the last time, so... if we are connected... */ close(*id); /* disconnect us */ *id = 0; /* and forget that the descriptor exists because we are not open */ } } static void pcap_cleanup_acn(pcap_t *handle) { int chassis, geoslot; unit_t *u; if (find_unit_by_fd(handle->fd, &chassis, &geoslot, &u) == 0) return; close_with_IOP(chassis, geoslot, LIVE); if (u) u->first_time = 0; pcap_cleanup_live_common(handle); } static void send_to_fd(int fd, int len, unsigned char *str) { int nwritten; int chassis, geoslot; while (len > 0) { if ((nwritten = write(fd, str, len)) <= 0) { find_unit_by_fd(fd, &chassis, &geoslot, NULL); if (units[chassis][geoslot].fd == fd) close_with_IOP(chassis, geoslot, LIVE); else if (units[chassis][geoslot].find_fd == fd) close_with_IOP(chassis, geoslot, FIND); empty_unit(chassis, geoslot); return; } len -= nwritten; str += nwritten; } } static void acn_freealldevs(void) { pcap_if_t *iff, *next_iff; pcap_addr_t *addr, *next_addr; for (iff = acn_if_list; iff != NULL; iff = next_iff) { next_iff = iff->next; for (addr = iff->addresses; addr != NULL; addr = next_addr) { next_addr = addr->next; if (addr->addr) free(addr->addr); if (addr->netmask) free(addr->netmask); if (addr->broadaddr) free(addr->broadaddr); if (addr->dstaddr) free(addr->dstaddr); free(addr); } if (iff->name) free(iff->name); if (iff->description) free(iff->description); free(iff); } } static char *nonUnified_port_num(unit_t *u, int IOPportnum) { sprintf(static_buf, "%d_%d", u->chassis, u->geoslot); return static_buf; } static char *unified_port_num(unit_t *u, int IOPportnum) { int portnum; portnum = ((u->chassis - 1) * 64) + ((u->geoslot - 1) * 8) + IOPportnum + 1; sprintf(static_buf, "%d", portnum); return static_buf; } static char *translate_IOP_to_pcap_name(unit_t *u, char *IOPname, bpf_u_int32 iftype) { iface_t *iface_ptr, *iface; char *name; char buf[32]; char *proto; char *port; int IOPportnum = 0; iface = malloc(sizeof(iface_t)); /* get memory for a structure */ - bzero((char *)iface, sizeof(iface_t)); + if (iface == NULL) { /* oops, we didn't get the memory requested */ + fprintf(stderr, "Error...couldn't allocate memory for interface structure...value of errno is: %d\n", errno); + return NULL; + } + memset((char *)iface, 0, sizeof(iface_t)); /* bzero is deprecated(), replaced with memset() */ iface->iftype = iftype; /* remember the interface type of this interface */ name = malloc(strlen(IOPname) + 1); /* get memory for the IOP's name */ + if (name == NULL) { /* oops, we didn't get the memory requested */ + fprintf(stderr, "Error...couldn't allocate memory for IOPname...value of errno is: %d\n", errno); + return NULL; + } + strcpy(name, IOPname); /* and copy it in */ iface->IOPname = name; /* and stick it into the structure */ if (strncmp(IOPname, "lo", 2) == 0) { IOPportnum = atoi(&IOPname[2]); switch (iftype) { case DLT_EN10MB: proto = "lo"; port = nonUnified_port_num(u, IOPportnum); break; default: proto = "???"; port = unified_port_num(u, IOPportnum); break; } } else if (strncmp(IOPname, "eth", 3) == 0) { IOPportnum = atoi(&IOPname[3]); switch (iftype) { case DLT_EN10MB: proto = "eth"; port = nonUnified_port_num(u, IOPportnum); break; default: proto = "???"; port = unified_port_num(u, IOPportnum); break; } } else if (strncmp(IOPname, "wan", 3) == 0) { IOPportnum = atoi(&IOPname[3]); switch (iftype) { case DLT_SITA: proto = "wan"; port = unified_port_num(u, IOPportnum); break; default: proto = "???"; port = unified_port_num(u, IOPportnum); break; } } sprintf(buf, "%s_%s", proto, port); /* compose the user's name for that IOP port name */ name = malloc(strlen(buf) + 1); /* get memory for that name */ + if (name == NULL) { /* oops, we didn't get the memory requested */ + fprintf(stderr, "Error...couldn't allocate memory for IOP port name...value of errno is: %d\n", errno); + return NULL; + } + strcpy(name, buf); /* and copy it in */ iface->name = name; /* and stick it into the structure */ if (u->iface == 0) { /* if this is the first name */ u->iface = iface; /* stick this entry at the head of the list */ } else { iface_ptr = u->iface; while (iface_ptr->next) { /* othewise scan the list */ iface_ptr = iface_ptr->next; /* till we're at the last entry */ } iface_ptr->next = iface; /* then tack this entry on the end of the list */ } return iface->name; } static int if_sort(char *s1, char *s2) { char *s1_p2, *s2_p2; char str1[MAX_LINE_SIZE], str2[MAX_LINE_SIZE]; int s1_p1_len, s2_p1_len; int retval; if ((s1_p2 = strchr(s1, '_'))) { /* if an underscore is found... */ s1_p1_len = s1_p2 - s1; /* the prefix length is the difference in pointers */ s1_p2++; /* the suffix actually starts _after_ the underscore */ } else { /* otherwise... */ s1_p1_len = strlen(s1); /* the prefix length is the length of the string itself */ s1_p2 = 0; /* and there is no suffix */ } if ((s2_p2 = strchr(s2, '_'))) { /* now do the same for the second string */ s2_p1_len = s2_p2 - s2; s2_p2++; } else { s2_p1_len = strlen(s2); s2_p2 = 0; } strncpy(str1, s1, (s1_p1_len > sizeof(str1)) ? s1_p1_len : sizeof(str1)); *(str1 + s1_p1_len) = 0; strncpy(str2, s2, (s2_p1_len > sizeof(str2)) ? s2_p1_len : sizeof(str2)); *(str2 + s2_p1_len) = 0; retval = strcmp(str1, str2); if (retval != 0) return retval; /* if they are not identical, then we can quit now and return the indication */ return strcmp(s1_p2, s2_p2); /* otherwise we return the result of comparing the 2nd half of the string */ } static void sort_if_table(void) { pcap_if_t *p1, *p2, *prev, *temp; int has_swapped; if (!acn_if_list) return; /* nothing to do if the list is empty */ while (1) { p1 = acn_if_list; /* start at the head of the list */ prev = 0; has_swapped = 0; while ((p2 = p1->next)) { if (if_sort(p1->name, p2->name) > 0) { if (prev) { /* we are swapping things that are _not_ at the head of the list */ temp = p2->next; prev->next = p2; p2->next = p1; p1->next = temp; } else { /* special treatment if we are swapping with the head of the list */ temp = p2->next; acn_if_list= p2; p2->next = p1; p1->next = temp; } p1 = p2; prev = p1; has_swapped = 1; } prev = p1; p1 = p1->next; } if (has_swapped == 0) return; } return; } static int process_client_data (char *errbuf) { /* returns: -1 = error, 0 = OK */ int chassis, geoslot; unit_t *u; pcap_if_t *iff, *prev_iff; pcap_addr_t *addr, *prev_addr; char *ptr; int address_count; struct sockaddr_in *s; char *newname; bpf_u_int32 interfaceType; unsigned char flags; prev_iff = 0; for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) { for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) { /* now loop over all the devices */ u = &units[chassis][geoslot]; empty_unit_iface(u); ptr = u->imsg; /* point to the start of the msg for this IOP */ while (ptr < (u->imsg + u->len)) { if ((iff = malloc(sizeof(pcap_if_t))) == NULL) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); return -1; } - bzero((char *)iff, sizeof(pcap_if_t)); + memset((char *)iff, 0, sizeof(pcap_if_t)); /* bzero() is deprecated, replaced with memset() */ if (acn_if_list == 0) acn_if_list = iff; /* remember the head of the list */ if (prev_iff) prev_iff->next = iff; /* insert a forward link */ if (*ptr) { /* if there is a count for the name */ if ((iff->name = malloc(*ptr + 1)) == NULL) { /* get that amount of space */ snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); return -1; } memcpy(iff->name, (ptr + 1), *ptr); /* copy the name into the malloc'ed space */ *(iff->name + *ptr) = 0; /* and null terminate the string */ ptr += *ptr; /* now move the pointer forwards by the length of the count plus the length of the string */ } ptr++; if (*ptr) { /* if there is a count for the description */ if ((iff->description = malloc(*ptr + 1)) == NULL) { /* get that amount of space */ snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); return -1; } memcpy(iff->description, (ptr + 1), *ptr); /* copy the name into the malloc'ed space */ *(iff->description + *ptr) = 0; /* and null terminate the string */ ptr += *ptr; /* now move the pointer forwards by the length of the count plus the length of the string */ } ptr++; interfaceType = ntohl(*(bpf_u_int32 *)ptr); ptr += 4; /* skip over the interface type */ flags = *ptr++; if (flags) iff->flags = PCAP_IF_LOOPBACK; /* if this is a loopback style interface, lets mark it as such */ address_count = *ptr++; prev_addr = 0; while (address_count--) { if ((addr = malloc(sizeof(pcap_addr_t))) == NULL) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); return -1; } - bzero((char *)addr, sizeof(pcap_addr_t)); ++ memset((char *)addr, 0, sizeof(pcap_addr_t)); /* bzero() is deprecated, replaced with memset() */ if (iff->addresses == 0) iff->addresses = addr; if (prev_addr) prev_addr->next = addr; /* insert a forward link */ if (*ptr) { /* if there is a count for the address */ if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) { /* get that amount of space */ snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); return -1; } - bzero((char *)s, sizeof(struct sockaddr_in)); + memset((char *)s, 0, sizeof(struct sockaddr_in)); /* bzero() is deprecated, replaced with memset() */ addr->addr = (struct sockaddr *)s; s->sin_family = AF_INET; s->sin_addr.s_addr = *(bpf_u_int32 *)(ptr + 1); /* copy the address in */ ptr += *ptr; /* now move the pointer forwards according to the specified length of the address */ } ptr++; /* then forwards one more for the 'length of the address' field */ if (*ptr) { /* process any netmask */ if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); return -1; } - bzero((char *)s, sizeof(struct sockaddr_in)); + /* bzero() is deprecated, replaced with memset() */ + memset((char *)s, 0, sizeof(struct sockaddr_in)); + addr->netmask = (struct sockaddr *)s; s->sin_family = AF_INET; s->sin_addr.s_addr = *(bpf_u_int32*)(ptr + 1); ptr += *ptr; } ptr++; if (*ptr) { /* process any broadcast address */ if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); return -1; } - bzero((char *)s, sizeof(struct sockaddr_in)); + /* bzero() is deprecated, replaced with memset() */ + memset((char *)s, 0, sizeof(struct sockaddr_in)); + addr->broadaddr = (struct sockaddr *)s; s->sin_family = AF_INET; s->sin_addr.s_addr = *(bpf_u_int32*)(ptr + 1); ptr += *ptr; } ptr++; if (*ptr) { /* process any destination address */ if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); return -1; } - bzero((char *)s, sizeof(struct sockaddr_in)); + /* bzero() is deprecated, replaced with memset() */ + memset((char *)s, 0, sizeof(struct sockaddr_in)); + addr->dstaddr = (struct sockaddr *)s; s->sin_family = AF_INET; s->sin_addr.s_addr = *(bpf_u_int32*)(ptr + 1); ptr += *ptr; } ptr++; prev_addr = addr; } prev_iff = iff; newname = translate_IOP_to_pcap_name(u, iff->name, interfaceType); /* add a translation entry and get a point to the mangled name */ if ((iff->name = realloc(iff->name, strlen(newname) + 1)) == NULL) { /* we now re-write the name stored in the interface list */ snprintf(errbuf, PCAP_ERRBUF_SIZE, "realloc: %s", pcap_strerror(errno)); return -1; } strcpy(iff->name, newname); /* to this new name */ } } } return 0; } static int read_client_data (int fd) { unsigned char buf[256]; int chassis, geoslot; unit_t *u; int len; find_unit_by_fd(fd, &chassis, &geoslot, &u); if ((len = recv(fd, buf, sizeof(buf), 0)) <= 0) return 0; /* read in whatever data was sent to us */ if ((u->imsg = realloc(u->imsg, (u->len + len))) == NULL) /* extend the buffer for the new data */ return 0; memcpy((u->imsg + u->len), buf, len); /* append the new data */ u->len += len; return 1; } static void wait_for_all_answers(void) { int retval; struct timeval tv; int fd; int chassis, geoslot; tv.tv_sec = 2; tv.tv_usec = 0; while (1) { int flag = 0; for (fd = 0; fd <= max_fs; fd++) { /* scan the list of descriptors we may be listening to */ if (FD_ISSET(fd, &readfds)) flag = 1; /* and see if there are any still set */ } if (flag == 0) return; /* we are done, when they are all gone */ memcpy(&working_set, &readfds, sizeof(readfds)); /* otherwise, we still have to listen for more stuff, till we timeout */ retval = select(max_fs + 1, &working_set, NULL, NULL, &tv); if (retval == -1) { /* an error occured !!!!! */ return; } else if (retval == 0) { /* timeout occured, so process what we've got sofar and return */ printf("timeout\n"); return; } else { for (fd = 0; fd <= max_fs; fd++) { /* scan the list of things to do, and do them */ if (FD_ISSET(fd, &working_set)) { if (read_client_data(fd) == 0) { /* if the socket has closed */ FD_CLR(fd, &readfds); /* and descriptors we listen to for errors */ find_unit_by_fd(fd, &chassis, &geoslot, NULL); close_with_IOP(chassis, geoslot, FIND); /* and close out connection to him */ } } } } } } static char *get_error_response(int fd, char *errbuf) { /* return a pointer on error, NULL on no error */ char byte; int len = 0; while (1) { recv(fd, &byte, 1, 0); /* read another byte in */ if (errbuf && (len++ < PCAP_ERRBUF_SIZE)) { /* and if there is still room in the buffer */ *errbuf++ = byte; /* stick it in */ *errbuf = '\0'; /* ensure the string is null terminated just in case we might exceed the buffer's size */ } if (byte == '\0') { if (len > 1) { return errbuf; } else { return NULL; } } } } int acn_findalldevs(char *errbuf) { /* returns: -1 = error, 0 = OK */ int chassis, geoslot; unit_t *u; FD_ZERO(&readfds); max_fs = 0; for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) { for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) { u = &units[chassis][geoslot]; if (u->ip && (open_with_IOP(u, FIND))) { /* connect to the remote IOP */ send_to_fd(u->find_fd, 1, (unsigned char *)"\0"); if (get_error_response(u->find_fd, errbuf)) close_with_IOP(chassis, geoslot, FIND); else { if (u->find_fd > max_fs) max_fs = u->find_fd; /* remember the highest number currently in use */ FD_SET(u->find_fd, &readfds); /* we are going to want to read this guy's response to */ u->len = 0; send_to_fd(u->find_fd, 1, (unsigned char *)"Q"); /* this interface query request */ } } } } wait_for_all_answers(); if (process_client_data(errbuf)) return -1; sort_if_table(); return 0; } static int pcap_stats_acn(pcap_t *handle, struct pcap_stat *ps) { unsigned char buf[12]; send_to_fd(handle->fd, 1, (unsigned char *)"S"); /* send the get_stats command to the IOP */ if (read_client_nbytes(handle->fd, sizeof(buf), buf) == -1) return -1; /* try reading the required bytes */ ps->ps_recv = ntohl(*(uint32_t *)&buf[0]); /* break the buffer into its three 32 bit components */ ps->ps_drop = ntohl(*(uint32_t *)&buf[4]); ps->ps_ifdrop = ntohl(*(uint32_t *)&buf[8]); return 0; } static int acn_open_live(const char *name, char *errbuf, int *linktype) { /* returns 0 on error, else returns the file descriptor */ int chassis, geoslot; unit_t *u; iface_t *p; pcap_if_t *alldevsp; - pcap_findalldevs(&alldevsp, errbuf); + pcap_findalldevs_interfaces(&alldevsp, errbuf); for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) { /* scan the table... */ for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) { u = &units[chassis][geoslot]; if (u->ip != NULL) { p = u->iface; while (p) { /* and all interfaces... */ if (p->IOPname && p->name && (strcmp(p->name, name) == 0)) { /* and if we found the interface we want... */ *linktype = p->iftype; open_with_IOP(u, LIVE); /* start a connection with that IOP */ send_to_fd(u->fd, strlen(p->IOPname)+1, (unsigned char *)p->IOPname); /* send the IOP's interface name, and a terminating null */ if (get_error_response(u->fd, errbuf)) { return -1; } return u->fd; /* and return that open descriptor */ } p = p->next; } } } } return -1; /* if the interface wasn't found, return an error */ } static void acn_start_monitor(int fd, int snaplen, int timeout, int promiscuous, int direction) { unsigned char buf[8]; unit_t *u; //printf("acn_start_monitor()\n"); // fulko find_unit_by_fd(fd, NULL, NULL, &u); if (u->first_time == 0) { buf[0] = 'M'; *(uint32_t *)&buf[1] = htonl(snaplen); buf[5] = timeout; buf[6] = promiscuous; buf[7] = direction; //printf("acn_start_monitor() first time\n"); // fulko send_to_fd(fd, 8, buf); /* send the start monitor command with its parameters to the IOP */ u->first_time = 1; } //printf("acn_start_monitor() complete\n"); // fulko } static int pcap_inject_acn(pcap_t *p, const void *buf _U_, size_t size _U_) { strlcpy(p->errbuf, "Sending packets isn't supported on ACN adapters", PCAP_ERRBUF_SIZE); return (-1); } static int pcap_setfilter_acn(pcap_t *handle, struct bpf_program *bpf) { int fd = handle->fd; int count; struct bpf_insn *p; uint16_t shortInt; uint32_t longInt; send_to_fd(fd, 1, (unsigned char *)"F"); /* BPF filter follows command */ count = bpf->bf_len; longInt = htonl(count); send_to_fd(fd, 4, (unsigned char *)&longInt); /* send the instruction sequence count */ p = bpf->bf_insns; while (count--) { /* followed by the list of instructions */ shortInt = htons(p->code); longInt = htonl(p->k); send_to_fd(fd, 2, (unsigned char *)&shortInt); send_to_fd(fd, 1, (unsigned char *)&p->jt); send_to_fd(fd, 1, (unsigned char *)&p->jf); send_to_fd(fd, 4, (unsigned char *)&longInt); p++; } if (get_error_response(fd, NULL)) return -1; return 0; } static int pcap_setdirection_acn(pcap_t *handle, pcap_direction_t d) { snprintf(handle->errbuf, sizeof(handle->errbuf), "Setting direction is not supported on ACN adapters"); return -1; } static int acn_read_n_bytes_with_timeout(pcap_t *handle, int count) { struct timeval tv; int retval, fd; fd_set r_fds; fd_set w_fds; u_char *bp; int len = 0; int offset = 0; tv.tv_sec = 5; tv.tv_usec = 0; fd = handle->fd; FD_ZERO(&r_fds); FD_SET(fd, &r_fds); memcpy(&w_fds, &r_fds, sizeof(r_fds)); bp = handle->bp; while (count) { retval = select(fd + 1, &w_fds, NULL, NULL, &tv); if (retval == -1) { /* an error occured !!!!! */ // fprintf(stderr, "error during packet data read\n"); return -1; /* but we need to return a good indication to prevent unneccessary popups */ } else if (retval == 0) { /* timeout occured, so process what we've got sofar and return */ // fprintf(stderr, "timeout during packet data read\n"); return -1; } else { if ((len = recv(fd, (bp + offset), count, 0)) <= 0) { // fprintf(stderr, "premature exit during packet data rx\n"); return -1; } count -= len; offset += len; } } return 0; } static int pcap_read_acn(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) { #define HEADER_SIZE (4 * 4) unsigned char packet_header[HEADER_SIZE]; struct pcap_pkthdr pcap_header; //printf("pcap_read_acn()\n"); // fulko acn_start_monitor(handle->fd, handle->snapshot, handle->md.timeout, handle->md.clear_promisc, handle->direction); /* maybe tell him to start monitoring */ //printf("pcap_read_acn() after start monitor\n"); // fulko handle->bp = packet_header; if (acn_read_n_bytes_with_timeout(handle, HEADER_SIZE) == -1) return 0; /* try to read a packet header in so we can get the sizeof the packet data */ pcap_header.ts.tv_sec = ntohl(*(uint32_t *)&packet_header[0]); /* tv_sec */ pcap_header.ts.tv_usec = ntohl(*(uint32_t *)&packet_header[4]); /* tv_usec */ pcap_header.caplen = ntohl(*(uint32_t *)&packet_header[8]); /* caplen */ pcap_header.len = ntohl(*(uint32_t *)&packet_header[12]); /* len */ handle->bp = handle->buffer + handle->offset; /* start off the receive pointer at the right spot */ if (acn_read_n_bytes_with_timeout(handle, pcap_header.caplen) == -1) return 0; /* then try to read in the rest of the data */ callback(user, &pcap_header, handle->bp); /* call the user supplied callback function */ return 1; } static int pcap_activate_sita(pcap_t *handle) { int fd; if (handle->opt.rfmon) { /* * No monitor mode on SITA devices (they're not Wi-Fi * devices). */ return PCAP_ERROR_RFMON_NOTSUP; } /* Initialize some components of the pcap structure. */ handle->inject_op = pcap_inject_acn; handle->setfilter_op = pcap_setfilter_acn; handle->setdirection_op = pcap_setdirection_acn; handle->set_datalink_op = NULL; /* can't change data link type */ handle->getnonblock_op = pcap_getnonblock_fd; handle->setnonblock_op = pcap_setnonblock_fd; handle->cleanup_op = pcap_cleanup_acn; handle->read_op = pcap_read_acn; handle->stats_op = pcap_stats_acn; fd = acn_open_live(handle->opt.source, handle->errbuf, &handle->linktype); if (fd == -1) return PCAP_ERROR; handle->md.clear_promisc = handle->md.promisc; handle->fd = fd; handle->bufsize = handle->snapshot; /* Allocate the buffer */ handle->buffer = malloc(handle->bufsize + handle->offset); if (!handle->buffer) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); pcap_cleanup_acn(handle); return PCAP_ERROR; } /* * "handle->fd" is a socket, so "select()" and "poll()" * should work on it. */ handle->selectable_fd = handle->fd; return 0; } -pcap_t *pcap_create(const char *device, char *ebuf) { +pcap_t *pcap_create_interface(const char *device, char *ebuf) { pcap_t *p; p = pcap_create_common(device, ebuf); if (p == NULL) return (NULL); p->activate_op = pcap_activate_sita; return (p); } Index: stable/9/contrib/libpcap/pcap-snf.c =================================================================== --- stable/9/contrib/libpcap/pcap-snf.c (revision 252280) +++ stable/9/contrib/libpcap/pcap-snf.c (revision 252281) @@ -1,306 +1,313 @@ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include "snf.h" #include "pcap-int.h" -#ifdef SNF_ONLY -#define snf_create pcap_create -#define snf_platform_finddevs pcap_platform_finddevs -#endif - static int snf_set_datalink(pcap_t *p, int dlt) { p->linktype = dlt; return (0); } static int snf_pcap_stats(pcap_t *p, struct pcap_stat *ps) { struct snf_ring_stats stats; int rc; if ((rc = snf_ring_getstats(p->md.snf_ring, &stats))) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_get_stats: %s", pcap_strerror(rc)); return -1; } ps->ps_recv = stats.ring_pkt_recv + stats.ring_pkt_overflow; ps->ps_drop = stats.ring_pkt_overflow; ps->ps_ifdrop = stats.nic_pkt_overflow + stats.nic_pkt_bad; return 0; } static void snf_platform_cleanup(pcap_t *p) { if (p == NULL) return; snf_ring_close(p->md.snf_ring); snf_close(p->md.snf_handle); pcap_cleanup_live_common(p); } static int snf_getnonblock(pcap_t *p, char *errbuf) { return (p->md.snf_timeout == 0); } static int snf_setnonblock(pcap_t *p, int nonblock, char *errbuf) { if (nonblock) p->md.snf_timeout = 0; else { if (p->md.timeout <= 0) p->md.snf_timeout = -1; /* forever */ else p->md.snf_timeout = p->md.timeout; } return (0); } #define _NSEC_PER_SEC 1000000000 static inline struct timeval snf_timestamp_to_timeval(const int64_t ts_nanosec) { struct timeval tv; int32_t rem; if (ts_nanosec == 0) return (struct timeval) { 0, 0 }; tv.tv_sec = ts_nanosec / _NSEC_PER_SEC; tv.tv_usec = (ts_nanosec % _NSEC_PER_SEC) / 1000; return tv; } static int snf_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { struct pcap_pkthdr hdr; int i, flags, err, caplen, n; struct snf_recv_req req; if (!p || cnt == 0) return -1; n = 0; while (n < cnt || cnt < 0) { /* * Has "pcap_breakloop()" been called? */ if (p->break_loop) { if (n == 0) { p->break_loop = 0; return (-2); } else { return (n); } } err = snf_ring_recv(p->md.snf_ring, p->md.snf_timeout, &req); if (err) { if (err == EBUSY || err == EAGAIN) return (0); if (err == EINTR) continue; if (err != 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_read: %s", pcap_strerror(err)); return -1; } } caplen = req.length; if (caplen > p->snapshot) caplen = p->snapshot; if ((p->fcode.bf_insns == NULL) || bpf_filter(p->fcode.bf_insns, req.pkt_addr, req.length, caplen)) { hdr.ts = snf_timestamp_to_timeval(req.timestamp); hdr.caplen = caplen; hdr.len = req.length; callback(user, &hdr, req.pkt_addr); } n++; } return (n); } static int snf_setfilter(pcap_t *p, struct bpf_program *fp) { if (!p) return -1; if (!fp) { strncpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf)); return -1; } /* Make our private copy of the filter */ if (install_bpf_program(p, fp) < 0) return -1; p->md.use_bpf = 0; return (0); } static int snf_inject(pcap_t *p, const void *buf _U_, size_t size _U_) { strlcpy(p->errbuf, "Sending packets isn't supported with snf", PCAP_ERRBUF_SIZE); return (-1); } static int snf_activate(pcap_t* p) { char *device = p->opt.source; const char *nr = NULL; int err; int flags = 0; if (device == NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "device is NULL: %s", pcap_strerror(errno)); return -1; } /* In Libpcap, we set pshared by default if NUM_RINGS is set to > 1. * Since libpcap isn't thread-safe */ if ((nr = getenv("SNF_NUM_RINGS")) && *nr && atoi(nr) > 1) flags |= SNF_F_PSHARED; else nr = NULL; err = snf_open(p->md.snf_boardnum, 0, /* let SNF API parse SNF_NUM_RINGS, if set */ NULL, /* default RSS, or use SNF_RSS_FLAGS env */ 0, /* default to SNF_DATARING_SIZE from env */ flags, /* may want pshared */ &p->md.snf_handle); if (err != 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_open failed: %s", pcap_strerror(err)); return -1; } err = snf_ring_open(p->md.snf_handle, &p->md.snf_ring); if (err != 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_ring_open failed: %s", pcap_strerror(err)); return -1; } if (p->md.timeout <= 0) p->md.snf_timeout = -1; else p->md.snf_timeout = p->md.timeout; err = snf_start(p->md.snf_handle); if (err != 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_start failed: %s", pcap_strerror(err)); return -1; } /* * "select()" and "poll()" don't work on snf descriptors. */ p->selectable_fd = -1; p->linktype = DLT_EN10MB; p->read_op = snf_read; p->inject_op = snf_inject; p->setfilter_op = snf_setfilter; p->setdirection_op = NULL; /* Not implemented.*/ p->set_datalink_op = snf_set_datalink; p->getnonblock_op = snf_getnonblock; p->setnonblock_op = snf_setnonblock; p->stats_op = snf_pcap_stats; p->cleanup_op = snf_platform_cleanup; p->md.stat.ps_recv = 0; p->md.stat.ps_drop = 0; p->md.stat.ps_ifdrop = 0; return 0; } int -snf_platform_finddevs(pcap_if_t **devlistp, char *errbuf) +snf_findalldevs(pcap_if_t **devlistp, char *errbuf) { /* * There are no platform-specific devices since each device * exists as a regular Ethernet device. */ return 0; } pcap_t * -snf_create(const char *device, char *ebuf) +snf_create(const char *device, char *ebuf, int *is_ours) { pcap_t *p; int boardnum = -1; struct snf_ifaddrs *ifaddrs, *ifa; size_t devlen; - if (snf_init(SNF_VERSION_API)) + if (snf_init(SNF_VERSION_API)) { + /* Can't initialize the API, so no SNF devices */ + *is_ours = 0; return NULL; + } /* * Match a given interface name to our list of interface names, from * which we can obtain the intended board number */ - if (snf_getifaddrs(&ifaddrs) || ifaddrs == NULL) + if (snf_getifaddrs(&ifaddrs) || ifaddrs == NULL) { + /* Can't get SNF addresses */ + *is_ours = 0; return NULL; + } devlen = strlen(device) + 1; ifa = ifaddrs; while (ifa) { if (!strncmp(device, ifa->snf_ifa_name, devlen)) { boardnum = ifa->snf_ifa_boardnum; break; } ifa = ifa->snf_ifa_next; } snf_freeifaddrs(ifaddrs); if (ifa == NULL) { /* * If we can't find the device by name, support the name "snfX" * and "snf10gX" where X is the board number. */ if (sscanf(device, "snf10g%d", &boardnum) != 1 && - sscanf(device, "snf%d", &boardnum) != 1) + sscanf(device, "snf%d", &boardnum) != 1) { + /* Nope, not a supported name */ + *is_ours = 0; return NULL; + } } + + /* OK, it's probably ours. */ + *is_ours = 1; p = pcap_create_common(device, ebuf); if (p == NULL) return NULL; p->activate_op = snf_activate; p->md.snf_boardnum = boardnum; return p; } Index: stable/9/contrib/libpcap/pcap-snf.h =================================================================== --- stable/9/contrib/libpcap/pcap-snf.h (revision 252280) +++ stable/9/contrib/libpcap/pcap-snf.h (revision 252281) @@ -1,2 +1,2 @@ -pcap_t *snf_create(const char *, char *); -int snf_platform_finddevs(pcap_if_t **devlistp, char *errbuf); +pcap_t *snf_create(const char *, char *, int *); +int snf_findalldevs(pcap_if_t **devlistp, char *errbuf); Index: stable/9/contrib/libpcap/pcap-snit.c =================================================================== --- stable/9/contrib/libpcap/pcap-snit.c (revision 252280) +++ stable/9/contrib/libpcap/pcap-snit.c (revision 252281) @@ -1,426 +1,426 @@ /* * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Modifications made to accommodate the new SunOS4.0 NIT facility by * Micky Liu, micky@cunixc.cc.columbia.edu, Columbia University in May, 1989. * This module now handles the STREAMS based NIT. */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.77 2008-04-14 20:40:58 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pcap-int.h" #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif /* * The chunk size for NIT. This is the amount of buffering * done for read calls. */ #define CHUNKSIZE (2*1024) /* * The total buffer space used by NIT. */ #define BUFSPACE (4*CHUNKSIZE) /* Forwards */ static int nit_setflags(int, int, int, char *); static int pcap_stats_snit(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); } static int pcap_read_snit(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { register int cc, n; register u_char *bp, *cp, *ep; register struct nit_bufhdr *hdrp; register struct nit_iftime *ntp; register struct nit_iflen *nlp; register struct nit_ifdrops *ndp; register int caplen; cc = p->cc; if (cc == 0) { cc = read(p->fd, (char *)p->buffer, p->bufsize); if (cc < 0) { if (errno == EWOULDBLOCK) return (0); snprintf(p->errbuf, sizeof(p->errbuf), "pcap_read: %s", pcap_strerror(errno)); return (-1); } bp = p->buffer; } else bp = p->bp; /* * loop through each snapshot in the chunk */ n = 0; ep = bp + cc; while (bp < ep) { /* * Has "pcap_breakloop()" been called? * If so, return immediately - if we haven't read any * packets, clear the flag and return -2 to indicate * that we were told to break out of the loop, otherwise * leave the flag set, so that the *next* call will break * out of the loop without having read any packets, and * return the number of packets we've processed so far. */ if (p->break_loop) { if (n == 0) { p->break_loop = 0; return (-2); } else { p->bp = bp; p->cc = ep - bp; return (n); } } ++p->md.stat.ps_recv; cp = bp; /* get past NIT buffer */ hdrp = (struct nit_bufhdr *)cp; cp += sizeof(*hdrp); /* get past NIT timer */ ntp = (struct nit_iftime *)cp; cp += sizeof(*ntp); ndp = (struct nit_ifdrops *)cp; p->md.stat.ps_drop = ndp->nh_drops; cp += sizeof *ndp; /* get past packet len */ nlp = (struct nit_iflen *)cp; cp += sizeof(*nlp); /* next snapshot */ bp += hdrp->nhb_totlen; caplen = nlp->nh_pktlen; if (caplen > p->snapshot) caplen = p->snapshot; if (bpf_filter(p->fcode.bf_insns, cp, nlp->nh_pktlen, caplen)) { struct pcap_pkthdr h; h.ts = ntp->nh_timestamp; h.len = nlp->nh_pktlen; h.caplen = caplen; (*callback)(user, &h, cp); if (++n >= cnt && cnt > 0) { p->cc = ep - bp; p->bp = bp; return (n); } } } p->cc = 0; return (n); } static int pcap_inject_snit(pcap_t *p, const void *buf, size_t size) { struct strbuf ctl, data; /* * XXX - can we just do * ret = write(pd->f, buf, size); */ ctl.len = sizeof(*sa); /* XXX - what was this? */ ctl.buf = (char *)sa; data.buf = buf; data.len = size; ret = putmsg(p->fd, &ctl, &data); if (ret == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s", pcap_strerror(errno)); return (-1); } return (ret); } static int nit_setflags(int fd, int promisc, int to_ms, char *ebuf) { bpf_u_int32 flags; struct strioctl si; struct timeval timeout; si.ic_timout = INFTIM; if (to_ms != 0) { timeout.tv_sec = to_ms / 1000; timeout.tv_usec = (to_ms * 1000) % 1000000; si.ic_cmd = NIOCSTIME; si.ic_len = sizeof(timeout); si.ic_dp = (char *)&timeout; if (ioctl(fd, I_STR, (char *)&si) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "NIOCSTIME: %s", pcap_strerror(errno)); return (-1); } } flags = NI_TIMESTAMP | NI_LEN | NI_DROPS; if (promisc) flags |= NI_PROMISC; si.ic_cmd = NIOCSFLAGS; si.ic_len = sizeof(flags); si.ic_dp = (char *)&flags; if (ioctl(fd, I_STR, (char *)&si) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "NIOCSFLAGS: %s", pcap_strerror(errno)); return (-1); } return (0); } static int pcap_activate_snit(pcap_t *p) { struct strioctl si; /* struct for ioctl() */ struct ifreq ifr; /* interface request struct */ int chunksize = CHUNKSIZE; int fd; static char dev[] = "/dev/nit"; if (p->opt.rfmon) { /* * No monitor mode on SunOS 4.x (no Wi-Fi devices on * hardware supported by SunOS 4.x). */ return (PCAP_ERROR_RFMON_NOTSUP); } if (p->snapshot < 96) /* * NIT requires a snapshot length of at least 96. */ p->snapshot = 96; /* * Initially try a read/write open (to allow the inject * method to work). If that fails due to permission * issues, fall back to read-only. This allows a * non-root user to be granted specific access to pcap * capabilities via file permissions. * * XXX - we should have an API that has a flag that * controls whether to open read-only or read-write, * so that denial of permission to send (or inability * to send, if sending packets isn't supported on * the device in question) can be indicated at open * time. */ p->fd = fd = open(dev, O_RDWR); if (fd < 0 && errno == EACCES) p->fd = fd = open(dev, O_RDONLY); if (fd < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", dev, pcap_strerror(errno)); goto bad; } /* arrange to get discrete messages from the STREAM and use NIT_BUF */ if (ioctl(fd, I_SRDOPT, (char *)RMSGD) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "I_SRDOPT: %s", pcap_strerror(errno)); goto bad; } if (ioctl(fd, I_PUSH, "nbuf") < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "push nbuf: %s", pcap_strerror(errno)); goto bad; } /* set the chunksize */ si.ic_cmd = NIOCSCHUNK; si.ic_timout = INFTIM; si.ic_len = sizeof(chunksize); si.ic_dp = (char *)&chunksize; if (ioctl(fd, I_STR, (char *)&si) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSCHUNK: %s", pcap_strerror(errno)); goto bad; } /* request the interface */ strncpy(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name)); ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0'; si.ic_cmd = NIOCBIND; si.ic_len = sizeof(ifr); si.ic_dp = (char *)𝔦 if (ioctl(fd, I_STR, (char *)&si) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCBIND: %s: %s", ifr.ifr_name, pcap_strerror(errno)); goto bad; } /* set the snapshot length */ si.ic_cmd = NIOCSSNAP; si.ic_len = sizeof(p->snapshot); si.ic_dp = (char *)&p->snapshot; if (ioctl(fd, I_STR, (char *)&si) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSSNAP: %s", pcap_strerror(errno)); goto bad; } if (nit_setflags(p->fd, p->opt.promisc, p->md.timeout, p->errbuf) < 0) goto bad; (void)ioctl(fd, I_FLUSH, (char *)FLUSHR); /* * NIT supports only ethernets. */ p->linktype = DLT_EN10MB; p->bufsize = BUFSPACE; p->buffer = (u_char *)malloc(p->bufsize); if (p->buffer == NULL) { strlcpy(p->errbuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); goto bad; } /* * "p->fd" is an FD for a STREAMS device, so "select()" and * "poll()" should work on it. */ p->selectable_fd = p->fd; /* * This is (presumably) a real Ethernet capture; give it a * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so * that an application can let you choose it, in case you're * capturing DOCSIS traffic that a Cisco Cable Modem * Termination System is putting out onto an Ethernet (it * doesn't put an Ethernet header onto the wire, it puts raw * DOCSIS frames out on the wire inside the low-level * Ethernet framing). */ p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); /* * If that fails, just leave the list empty. */ if (p->dlt_list != NULL) { p->dlt_list[0] = DLT_EN10MB; p->dlt_list[1] = DLT_DOCSIS; p->dlt_count = 2; } p->read_op = pcap_read_snit; p->inject_op = pcap_inject_snit; p->setfilter_op = install_bpf_program; /* no kernel filtering */ p->setdirection_op = NULL; /* Not implemented. */ p->set_datalink_op = NULL; /* can't change data link type */ p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; p->stats_op = pcap_stats_snit; return (0); bad: pcap_cleanup_live_common(p); return (PCAP_ERROR); } pcap_t * -pcap_create(const char *device, char *ebuf) +pcap_create_interface(const char *device, char *ebuf) { pcap_t *p; p = pcap_create_common(device, ebuf); if (p == NULL) return (NULL); p->activate_op = pcap_activate_snit; return (p); } int pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) { return (0); } Index: stable/9/contrib/libpcap/pcap-snoop.c =================================================================== --- stable/9/contrib/libpcap/pcap-snoop.c (revision 252280) +++ stable/9/contrib/libpcap/pcap-snoop.c (revision 252281) @@ -1,413 +1,413 @@ /* * Copyright (c) 1993, 1994, 1995, 1996, 1997 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.59 2008-12-02 16:25:14 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pcap-int.h" #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif static int pcap_read_snoop(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { int cc; register struct snoopheader *sh; register u_int datalen; register u_int caplen; register u_char *cp; again: /* * Has "pcap_breakloop()" been called? */ if (p->break_loop) { /* * Yes - clear the flag that indicates that it * has, and return -2 to indicate that we were * told to break out of the loop. */ p->break_loop = 0; return (-2); } cc = read(p->fd, (char *)p->buffer, p->bufsize); if (cc < 0) { /* Don't choke when we get ptraced */ switch (errno) { case EINTR: goto again; case EWOULDBLOCK: return (0); /* XXX */ } snprintf(p->errbuf, sizeof(p->errbuf), "read: %s", pcap_strerror(errno)); return (-1); } sh = (struct snoopheader *)p->buffer; datalen = sh->snoop_packetlen; /* * XXX - Sigh, snoop_packetlen is a 16 bit quantity. If we * got a short length, but read a full sized snoop pakcet, * assume we overflowed and add back the 64K... */ if (cc == (p->snapshot + sizeof(struct snoopheader)) && (datalen < p->snapshot)) datalen += (64 * 1024); caplen = (datalen < p->snapshot) ? datalen : p->snapshot; cp = (u_char *)(sh + 1) + p->offset; /* XXX */ /* * XXX unfortunately snoop loopback isn't exactly like * BSD's. The address family is encoded in the first 2 * bytes rather than the first 4 bytes! Luckily the last * two snoop loopback bytes are zeroed. */ if (p->linktype == DLT_NULL && *((short *)(cp + 2)) == 0) { u_int *uip = (u_int *)cp; *uip >>= 16; } if (p->fcode.bf_insns == NULL || bpf_filter(p->fcode.bf_insns, cp, datalen, caplen)) { struct pcap_pkthdr h; ++p->md.stat.ps_recv; h.ts.tv_sec = sh->snoop_timestamp.tv_sec; h.ts.tv_usec = sh->snoop_timestamp.tv_usec; h.len = datalen; h.caplen = caplen; (*callback)(user, &h, cp); return (1); } return (0); } static int pcap_inject_snoop(pcap_t *p, const void *buf, size_t size) { int ret; /* * XXX - libnet overwrites the source address with what I * presume is the interface's address; is that required? */ ret = write(p->fd, buf, size); if (ret == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s", pcap_strerror(errno)); return (-1); } return (ret); } static int pcap_stats_snoop(pcap_t *p, struct pcap_stat *ps) { register struct rawstats *rs; struct rawstats rawstats; rs = &rawstats; memset(rs, 0, sizeof(*rs)); if (ioctl(p->fd, SIOCRAWSTATS, (char *)rs) < 0) { snprintf(p->errbuf, sizeof(p->errbuf), "SIOCRAWSTATS: %s", pcap_strerror(errno)); 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); } /* XXX can't disable promiscuous */ static int pcap_activate_snoop(pcap_t *p) { int fd; struct sockaddr_raw sr; struct snoopfilter sf; u_int v; int ll_hdrlen; int snooplen; struct ifreq ifr; fd = socket(PF_RAW, SOCK_RAW, RAWPROTO_SNOOP); if (fd < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snoop socket: %s", pcap_strerror(errno)); goto bad; } p->fd = fd; memset(&sr, 0, sizeof(sr)); sr.sr_family = AF_RAW; (void)strncpy(sr.sr_ifname, p->opt.source, sizeof(sr.sr_ifname)); if (bind(fd, (struct sockaddr *)&sr, sizeof(sr))) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snoop bind: %s", pcap_strerror(errno)); goto bad; } memset(&sf, 0, sizeof(sf)); if (ioctl(fd, SIOCADDSNOOP, &sf) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCADDSNOOP: %s", pcap_strerror(errno)); goto bad; } if (p->opt.buffer_size != 0) v = p->opt.buffer_size; else v = 64 * 1024; /* default to 64K buffer size */ (void)setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&v, sizeof(v)); /* * XXX hack - map device name to link layer type */ if (strncmp("et", p->opt.source, 2) == 0 || /* Challenge 10 Mbit */ strncmp("ec", p->opt.source, 2) == 0 || /* Indigo/Indy 10 Mbit, O2 10/100 */ strncmp("ef", p->opt.source, 2) == 0 || /* O200/2000 10/100 Mbit */ strncmp("eg", p->opt.source, 2) == 0 || /* Octane/O2xxx/O3xxx Gigabit */ strncmp("gfe", p->opt.source, 3) == 0 || /* GIO 100 Mbit */ strncmp("fxp", p->opt.source, 3) == 0 || /* Challenge VME Enet */ strncmp("ep", p->opt.source, 2) == 0 || /* Challenge 8x10 Mbit EPLEX */ strncmp("vfe", p->opt.source, 3) == 0 || /* Challenge VME 100Mbit */ strncmp("fa", p->opt.source, 2) == 0 || strncmp("qaa", p->opt.source, 3) == 0 || strncmp("cip", p->opt.source, 3) == 0 || strncmp("el", p->opt.source, 2) == 0) { p->linktype = DLT_EN10MB; p->offset = RAW_HDRPAD(sizeof(struct ether_header)); ll_hdrlen = sizeof(struct ether_header); /* * This is (presumably) a real Ethernet capture; give it a * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so * that an application can let you choose it, in case you're * capturing DOCSIS traffic that a Cisco Cable Modem * Termination System is putting out onto an Ethernet (it * doesn't put an Ethernet header onto the wire, it puts raw * DOCSIS frames out on the wire inside the low-level * Ethernet framing). * * XXX - are there any sorts of "fake Ethernet" that have * Ethernet link-layer headers but that *shouldn't offer * DLT_DOCSIS as a Cisco CMTS won't put traffic onto it * or get traffic bridged onto it? "el" is for ATM LANE * Ethernet devices, so that might be the case for them; * the same applies for "qaa" classical IP devices. If * "fa" devices are for FORE SPANS, that'd apply to them * as well; what are "cip" devices - some other ATM * Classical IP devices? */ p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); /* * If that fails, just leave the list empty. */ if (p->dlt_list != NULL) { p->dlt_list[0] = DLT_EN10MB; p->dlt_list[1] = DLT_DOCSIS; p->dlt_count = 2; } } else if (strncmp("ipg", p->opt.source, 3) == 0 || strncmp("rns", p->opt.source, 3) == 0 || /* O2/200/2000 FDDI */ strncmp("xpi", p->opt.source, 3) == 0) { p->linktype = DLT_FDDI; p->offset = 3; /* XXX yeah? */ ll_hdrlen = 13; } else if (strncmp("ppp", p->opt.source, 3) == 0) { p->linktype = DLT_RAW; ll_hdrlen = 0; /* DLT_RAW meaning "no PPP header, just the IP packet"? */ } else if (strncmp("qfa", p->opt.source, 3) == 0) { p->linktype = DLT_IP_OVER_FC; ll_hdrlen = 24; } else if (strncmp("pl", p->opt.source, 2) == 0) { p->linktype = DLT_RAW; ll_hdrlen = 0; /* Cray UNICOS/mp pseudo link */ } else if (strncmp("lo", p->opt.source, 2) == 0) { p->linktype = DLT_NULL; ll_hdrlen = 4; } else { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snoop: unknown physical layer type"); goto bad; } if (p->opt.rfmon) { /* * No monitor mode on Irix (no Wi-Fi devices on * hardware supported by Irix). */ return (PCAP_ERROR_RFMON_NOTSUP); } #ifdef SIOCGIFMTU /* * XXX - IRIX appears to give you an error if you try to set the * capture length to be greater than the MTU, so let's try to get * the MTU first and, if that succeeds, trim the snap length * to be no greater than the MTU. */ (void)strncpy(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name)); if (ioctl(fd, SIOCGIFMTU, (char *)&ifr) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFMTU: %s", pcap_strerror(errno)); goto bad; } /* * OK, we got it. * * XXX - some versions of IRIX 6.5 define "ifr_mtu" and have an * "ifru_metric" member of the "ifr_ifru" union in an "ifreq" * structure, others don't. * * I've no idea what's going on, so, if "ifr_mtu" isn't defined, * we define it as "ifr_metric", as using that field appears to * work on the versions that lack "ifr_mtu" (and, on those that * don't lack it, "ifru_metric" and "ifru_mtu" are both "int" * members of the "ifr_ifru" union, which suggests that they * may be interchangeable in this case). */ #ifndef ifr_mtu #define ifr_mtu ifr_metric #endif if (p->snapshot > ifr.ifr_mtu + ll_hdrlen) p->snapshot = ifr.ifr_mtu + ll_hdrlen; #endif /* * The argument to SIOCSNOOPLEN is the number of link-layer * payload bytes to capture - it doesn't count link-layer * header bytes. */ snooplen = p->snapshot - ll_hdrlen; if (snooplen < 0) snooplen = 0; if (ioctl(fd, SIOCSNOOPLEN, &snooplen) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPLEN: %s", pcap_strerror(errno)); goto bad; } v = 1; if (ioctl(fd, SIOCSNOOPING, &v) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPING: %s", pcap_strerror(errno)); goto bad; } p->bufsize = 4096; /* XXX */ p->buffer = (u_char *)malloc(p->bufsize); if (p->buffer == NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); goto bad; } /* * "p->fd" is a socket, so "select()" should work on it. */ p->selectable_fd = p->fd; p->read_op = pcap_read_snoop; p->inject_op = pcap_inject_snoop; p->setfilter_op = install_bpf_program; /* no kernel filtering */ p->setdirection_op = NULL; /* Not implemented. */ p->set_datalink_op = NULL; /* can't change data link type */ p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; p->stats_op = pcap_stats_snoop; return (0); bad: pcap_cleanup_live_common(p); return (PCAP_ERROR); } pcap_t * -pcap_create(const char *device, char *ebuf) +pcap_create_interface(const char *device, char *ebuf) { pcap_t *p; p = pcap_create_common(device, ebuf); if (p == NULL) return (NULL); p->activate_op = pcap_activate_snoop; return (p); } int pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) { return (0); } Index: stable/9/contrib/libpcap/pcap-usb-linux.c =================================================================== --- stable/9/contrib/libpcap/pcap-usb-linux.c (revision 252280) +++ stable/9/contrib/libpcap/pcap-usb-linux.c (revision 252281) @@ -1,883 +1,913 @@ /* * Copyright (c) 2006 Paolo Abeni (Italy) * 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. The name of the author may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT * OWNER 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. * * USB sniffing API implementation for Linux platform * By Paolo Abeni * Modifications: Kris Katterjohn * */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/pcap-usb-linux.c,v 1.33 2008-12-23 21:38:50 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "pcap-int.h" #include "pcap-usb-linux.h" #include "pcap/usb.h" #ifdef NEED_STRERROR_H #include "strerror.h" #endif #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_LINUX_USBDEVICE_FS_H /* * We might need to define __user for * . */ #ifdef HAVE_LINUX_COMPILER_H #include #endif /* HAVE_LINUX_COMPILER_H */ #include #endif /* HAVE_LINUX_USBDEVICE_FS_H */ #define USB_IFACE "usbmon" #define USB_TEXT_DIR_OLD "/sys/kernel/debug/usbmon" #define USB_TEXT_DIR "/sys/kernel/debug/usb/usbmon" #define SYS_USB_BUS_DIR "/sys/bus/usb/devices" #define PROC_USB_BUS_DIR "/proc/bus/usb" #define USB_LINE_LEN 4096 #if __BYTE_ORDER == __LITTLE_ENDIAN #define htols(s) s #define htoll(l) l #define htol64(ll) ll #else #define htols(s) bswap_16(s) #define htoll(l) bswap_32(l) #define htol64(ll) bswap_64(ll) #endif struct mon_bin_stats { u_int32_t queued; u_int32_t dropped; }; struct mon_bin_get { pcap_usb_header *hdr; void *data; size_t data_len; /* Length of data (can be zero) */ }; struct mon_bin_mfetch { int32_t *offvec; /* Vector of events fetched */ int32_t nfetch; /* Number of events to fetch (out: fetched) */ int32_t nflush; /* Number of events to flush */ }; #define MON_IOC_MAGIC 0x92 #define MON_IOCQ_URB_LEN _IO(MON_IOC_MAGIC, 1) #define MON_IOCX_URB _IOWR(MON_IOC_MAGIC, 2, struct mon_bin_hdr) #define MON_IOCG_STATS _IOR(MON_IOC_MAGIC, 3, struct mon_bin_stats) #define MON_IOCT_RING_SIZE _IO(MON_IOC_MAGIC, 4) #define MON_IOCQ_RING_SIZE _IO(MON_IOC_MAGIC, 5) #define MON_IOCX_GET _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get) #define MON_IOCX_MFETCH _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch) #define MON_IOCH_MFLUSH _IO(MON_IOC_MAGIC, 8) #define MON_BIN_SETUP 0x1 /* setup hdr is present*/ #define MON_BIN_SETUP_ZERO 0x2 /* setup buffer is not available */ #define MON_BIN_DATA_ZERO 0x4 /* data buffer is not available */ #define MON_BIN_ERROR 0x8 /* forward declaration */ static int usb_activate(pcap_t *); static int usb_stats_linux(pcap_t *, struct pcap_stat *); static int usb_stats_linux_bin(pcap_t *, struct pcap_stat *); static int usb_read_linux(pcap_t *, int , pcap_handler , u_char *); static int usb_read_linux_bin(pcap_t *, int , pcap_handler , u_char *); static int usb_read_linux_mmap(pcap_t *, int , pcap_handler , u_char *); static int usb_inject_linux(pcap_t *, const void *, size_t); static int usb_setdirection_linux(pcap_t *, pcap_direction_t); static void usb_cleanup_linux_mmap(pcap_t *); /* facility to add an USB device to the device list*/ static int usb_dev_add(pcap_if_t** alldevsp, int n, char *err_str) { char dev_name[10]; char dev_descr[30]; snprintf(dev_name, 10, USB_IFACE"%d", n); snprintf(dev_descr, 30, "USB bus number %d", n); if (pcap_add_if(alldevsp, dev_name, 0, dev_descr, err_str) < 0) return -1; return 0; } int -usb_platform_finddevs(pcap_if_t **alldevsp, char *err_str) +usb_findalldevs(pcap_if_t **alldevsp, char *err_str) { struct dirent* data; int ret = 0; DIR* dir; int n; char* name; size_t len; /* try scanning sysfs usb bus directory */ dir = opendir(SYS_USB_BUS_DIR); if (dir != NULL) { while ((ret == 0) && ((data = readdir(dir)) != 0)) { name = data->d_name; if (strncmp(name, "usb", 3) != 0) continue; if (sscanf(&name[3], "%d", &n) == 0) continue; ret = usb_dev_add(alldevsp, n, err_str); } closedir(dir); return ret; } /* that didn't work; try scanning procfs usb bus directory */ dir = opendir(PROC_USB_BUS_DIR); if (dir != NULL) { while ((ret == 0) && ((data = readdir(dir)) != 0)) { name = data->d_name; len = strlen(name); /* if this file name does not end with a number it's not of our interest */ if ((len < 1) || !isdigit(name[--len])) continue; while (isdigit(name[--len])); if (sscanf(&name[len+1], "%d", &n) != 1) continue; ret = usb_dev_add(alldevsp, n, err_str); } closedir(dir); return ret; } /* neither of them worked */ return 0; } static int usb_mmap(pcap_t* handle) { int len = ioctl(handle->fd, MON_IOCQ_RING_SIZE); if (len < 0) return 0; handle->md.mmapbuflen = len; handle->md.mmapbuf = mmap(0, handle->md.mmapbuflen, PROT_READ, MAP_SHARED, handle->fd, 0); return handle->md.mmapbuf != MAP_FAILED; } #define CTRL_TIMEOUT (5*1000) /* milliseconds */ #define USB_DIR_IN 0x80 #define USB_TYPE_STANDARD 0x00 #define USB_RECIP_DEVICE 0x00 #define USB_REQ_GET_DESCRIPTOR 6 #define USB_DT_DEVICE 1 /* probe the descriptors of the devices attached to the bus */ /* the descriptors will end up in the captured packet stream */ /* and be decoded by external apps like wireshark */ /* without these identifying probes packet data can't be fully decoded */ static void probe_devices(int bus) { struct usbdevfs_ctrltransfer ctrl; struct dirent* data; int ret = 0; char buf[40]; DIR* dir; /* scan usb bus directories for device nodes */ snprintf(buf, sizeof(buf), "/dev/bus/usb/%03d", bus); dir = opendir(buf); if (!dir) return; while ((ret >= 0) && ((data = readdir(dir)) != 0)) { int fd; char* name = data->d_name; if (name[0] == '.') continue; snprintf(buf, sizeof(buf), "/dev/bus/usb/%03d/%s", bus, data->d_name); fd = open(buf, O_RDWR); if (fd == -1) continue; /* * Sigh. Different kernels have different member names * for this structure. */ #ifdef HAVE_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE ctrl.bRequestType = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE; ctrl.bRequest = USB_REQ_GET_DESCRIPTOR; ctrl.wValue = USB_DT_DEVICE << 8; ctrl.wIndex = 0; ctrl.wLength = sizeof(buf); #else ctrl.requesttype = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE; ctrl.request = USB_REQ_GET_DESCRIPTOR; ctrl.value = USB_DT_DEVICE << 8; ctrl.index = 0; ctrl.length = sizeof(buf); #endif ctrl.data = buf; ctrl.timeout = CTRL_TIMEOUT; ret = ioctl(fd, USBDEVFS_CONTROL, &ctrl); close(fd); } closedir(dir); } pcap_t * -usb_create(const char *device, char *ebuf) +usb_create(const char *device, char *ebuf, int *is_ours) { + const char *cp; + char *cpend; + long devnum; pcap_t *p; + + /* Does this look like a USB monitoring device? */ + cp = strrchr(device, '/'); + if (cp == NULL) + cp = device; + /* Does it begin with USB_IFACE? */ + if (strncmp(cp, USB_IFACE, sizeof USB_IFACE - 1) != 0) { + /* Nope, doesn't begin with USB_IFACE */ + *is_ours = 0; + return NULL; + } + /* Yes - is USB_IFACE followed by a number? */ + cp += sizeof USB_IFACE - 1; + devnum = strtol(cp, &cpend, 10); + if (cpend == cp || *cpend != '\0') { + /* Not followed by a number. */ + *is_ours = 0; + return NULL; + } + if (devnum < 0) { + /* Followed by a non-valid number. */ + *is_ours = 0; + return NULL; + } + + /* OK, it's probably ours. */ + *is_ours = 1; p = pcap_create_common(device, ebuf); if (p == NULL) return (NULL); p->activate_op = usb_activate; return (p); } static int usb_activate(pcap_t* handle) { char full_path[USB_LINE_LEN]; /* Initialize some components of the pcap structure. */ handle->bufsize = handle->snapshot; handle->offset = 0; handle->linktype = DLT_USB_LINUX; handle->inject_op = usb_inject_linux; handle->setfilter_op = install_bpf_program; /* no kernel filtering */ handle->setdirection_op = usb_setdirection_linux; handle->set_datalink_op = NULL; /* can't change data link type */ handle->getnonblock_op = pcap_getnonblock_fd; handle->setnonblock_op = pcap_setnonblock_fd; /*get usb bus index from device name */ if (sscanf(handle->opt.source, USB_IFACE"%d", &handle->md.ifindex) != 1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't get USB bus index from %s", handle->opt.source); return PCAP_ERROR; } /*now select the read method: try to open binary interface */ snprintf(full_path, USB_LINE_LEN, LINUX_USB_MON_DEV"%d", handle->md.ifindex); handle->fd = open(full_path, O_RDONLY, 0); if (handle->fd >= 0) { if (handle->opt.rfmon) { /* * Monitor mode doesn't apply to USB devices. */ close(handle->fd); return PCAP_ERROR_RFMON_NOTSUP; } /* binary api is available, try to use fast mmap access */ if (usb_mmap(handle)) { handle->linktype = DLT_USB_LINUX_MMAPPED; handle->stats_op = usb_stats_linux_bin; handle->read_op = usb_read_linux_mmap; handle->cleanup_op = usb_cleanup_linux_mmap; probe_devices(handle->md.ifindex); /* * "handle->fd" is a real file, so "select()" and * "poll()" work on it. */ handle->selectable_fd = handle->fd; return 0; } /* can't mmap, use plain binary interface access */ handle->stats_op = usb_stats_linux_bin; handle->read_op = usb_read_linux_bin; probe_devices(handle->md.ifindex); } else { /*Binary interface not available, try open text interface */ snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR"/%dt", handle->md.ifindex); handle->fd = open(full_path, O_RDONLY, 0); if (handle->fd < 0) { if (errno == ENOENT) { /* * Not found at the new location; try * the old location. */ snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%dt", handle->md.ifindex); handle->fd = open(full_path, O_RDONLY, 0); } if (handle->fd < 0) { /* no more fallback, give it up*/ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't open USB bus file %s: %s", full_path, strerror(errno)); return PCAP_ERROR; } } if (handle->opt.rfmon) { /* * Monitor mode doesn't apply to USB devices. */ close(handle->fd); return PCAP_ERROR_RFMON_NOTSUP; } handle->stats_op = usb_stats_linux; handle->read_op = usb_read_linux; } /* * "handle->fd" is a real file, so "select()" and "poll()" * work on it. */ handle->selectable_fd = handle->fd; /* for plain binary access and text access we need to allocate the read * buffer */ handle->buffer = malloc(handle->bufsize); if (!handle->buffer) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); close(handle->fd); return PCAP_ERROR; } return 0; } static inline int ascii_to_int(char c) { return c < 'A' ? c- '0': ((c<'a') ? c - 'A' + 10: c-'a'+10); } /* * see /Documentation/usb/usbmon.txt and * /drivers/usb/mon/mon_text.c for urb string * format description */ static int usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) { /* see: * /usr/src/linux/Documentation/usb/usbmon.txt * for message format */ unsigned timestamp; int tag, cnt, ep_num, dev_addr, dummy, ret, urb_len, data_len; char etype, pipeid1, pipeid2, status[16], urb_tag, line[USB_LINE_LEN]; char *string = line; u_char * rawdata = handle->buffer; struct pcap_pkthdr pkth; pcap_usb_header* uhdr = (pcap_usb_header*)handle->buffer; u_char urb_transfer=0; int incoming=0; /* ignore interrupt system call errors */ do { ret = read(handle->fd, line, USB_LINE_LEN - 1); if (handle->break_loop) { handle->break_loop = 0; return -2; } } while ((ret == -1) && (errno == EINTR)); if (ret < 0) { if (errno == EAGAIN) return 0; /* no data there */ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't read from fd %d: %s", handle->fd, strerror(errno)); return -1; } /* read urb header; %n argument may increment return value, but it's * not mandatory, so does not count on it*/ string[ret] = 0; ret = sscanf(string, "%x %d %c %c%c:%d:%d %s%n", &tag, ×tamp, &etype, &pipeid1, &pipeid2, &dev_addr, &ep_num, status, &cnt); if (ret < 8) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't parse USB bus message '%s', too few tokens (expected 8 got %d)", string, ret); return -1; } uhdr->id = tag; uhdr->device_address = dev_addr; uhdr->bus_id = handle->md.ifindex; uhdr->status = 0; string += cnt; /* don't use usbmon provided timestamp, since it have low precision*/ if (gettimeofday(&pkth.ts, NULL) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't get timestamp for message '%s' %d:%s", string, errno, strerror(errno)); return -1; } uhdr->ts_sec = pkth.ts.tv_sec; uhdr->ts_usec = pkth.ts.tv_usec; /* parse endpoint information */ if (pipeid1 == 'C') urb_transfer = URB_CONTROL; else if (pipeid1 == 'Z') urb_transfer = URB_ISOCHRONOUS; else if (pipeid1 == 'I') urb_transfer = URB_INTERRUPT; else if (pipeid1 == 'B') urb_transfer = URB_BULK; if (pipeid2 == 'i') { ep_num |= URB_TRANSFER_IN; incoming = 1; } if (etype == 'C') incoming = !incoming; /* direction check*/ if (incoming) { if (handle->direction == PCAP_D_OUT) return 0; } else if (handle->direction == PCAP_D_IN) return 0; uhdr->event_type = etype; uhdr->transfer_type = urb_transfer; uhdr->endpoint_number = ep_num; pkth.caplen = sizeof(pcap_usb_header); rawdata += sizeof(pcap_usb_header); /* check if this is a setup packet */ ret = sscanf(status, "%d", &dummy); if (ret != 1) { /* this a setup packet, setup data can be filled with underscore if * usbmon has not been able to read them, so we must parse this fields as * strings */ pcap_usb_setup* shdr; char str1[3], str2[3], str3[5], str4[5], str5[5]; ret = sscanf(string, "%s %s %s %s %s%n", str1, str2, str3, str4, str5, &cnt); if (ret < 5) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't parse USB bus message '%s', too few tokens (expected 5 got %d)", string, ret); return -1; } string += cnt; /* try to convert to corresponding integer */ shdr = &uhdr->setup; shdr->bmRequestType = strtoul(str1, 0, 16); shdr->bRequest = strtoul(str2, 0, 16); shdr->wValue = htols(strtoul(str3, 0, 16)); shdr->wIndex = htols(strtoul(str4, 0, 16)); shdr->wLength = htols(strtoul(str5, 0, 16)); uhdr->setup_flag = 0; } else uhdr->setup_flag = 1; /* read urb data */ ret = sscanf(string, " %d%n", &urb_len, &cnt); if (ret < 1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't parse urb length from '%s'", string); return -1; } string += cnt; /* urb tag is not present if urb length is 0, so we can stop here * text parsing */ pkth.len = urb_len+pkth.caplen; uhdr->urb_len = urb_len; uhdr->data_flag = 1; data_len = 0; if (uhdr->urb_len == 0) goto got; /* check for data presence; data is present if and only if urb tag is '=' */ if (sscanf(string, " %c", &urb_tag) != 1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't parse urb tag from '%s'", string); return -1; } if (urb_tag != '=') goto got; /* skip urb tag and following space */ string += 3; /* if we reach this point we got some urb data*/ uhdr->data_flag = 0; /* read all urb data; if urb length is greater then the usbmon internal * buffer length used by the kernel to spool the URB, we get only * a partial information. * At least until linux 2.6.17 there is no way to set usbmon intenal buffer * length and default value is 130. */ while ((string[0] != 0) && (string[1] != 0) && (pkth.caplen < handle->snapshot)) { rawdata[0] = ascii_to_int(string[0]) * 16 + ascii_to_int(string[1]); rawdata++; string+=2; if (string[0] == ' ') string++; pkth.caplen++; data_len++; } got: uhdr->data_len = data_len; if (pkth.caplen > handle->snapshot) pkth.caplen = handle->snapshot; if (handle->fcode.bf_insns == NULL || bpf_filter(handle->fcode.bf_insns, handle->buffer, pkth.len, pkth.caplen)) { handle->md.packets_read++; callback(user, &pkth, handle->buffer); return 1; } return 0; /* didn't pass filter */ } static int usb_inject_linux(pcap_t *handle, const void *buf, size_t size) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on " "USB devices"); return (-1); } static int usb_stats_linux(pcap_t *handle, struct pcap_stat *stats) { int dummy, ret, consumed, cnt; char string[USB_LINE_LEN]; char token[USB_LINE_LEN]; char * ptr = string; int fd; snprintf(string, USB_LINE_LEN, USB_TEXT_DIR"/%ds", handle->md.ifindex); fd = open(string, O_RDONLY, 0); if (fd < 0) { if (errno == ENOENT) { /* * Not found at the new location; try the old * location. */ snprintf(string, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%ds", handle->md.ifindex); fd = open(string, O_RDONLY, 0); } if (fd < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't open USB stats file %s: %s", string, strerror(errno)); return -1; } } /* read stats line */ do { ret = read(fd, string, USB_LINE_LEN-1); } while ((ret == -1) && (errno == EINTR)); close(fd); if (ret < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't read stats from fd %d ", fd); return -1; } string[ret] = 0; /* extract info on dropped urbs */ for (consumed=0; consumed < ret; ) { /* from the sscanf man page: * The C standard says: "Execution of a %n directive does * not increment the assignment count returned at the completion * of execution" but the Corrigendum seems to contradict this. * Do not make any assumptions on the effect of %n conversions * on the return value and explicitly check for cnt assignmet*/ int ntok; cnt = -1; ntok = sscanf(ptr, "%s%n", token, &cnt); if ((ntok < 1) || (cnt < 0)) break; consumed += cnt; ptr += cnt; if (strcmp(token, "nreaders") == 0) ret = sscanf(ptr, "%d", &stats->ps_drop); else ret = sscanf(ptr, "%d", &dummy); if (ntok != 1) break; consumed += cnt; ptr += cnt; } stats->ps_recv = handle->md.packets_read; stats->ps_ifdrop = 0; return 0; } static int usb_setdirection_linux(pcap_t *p, pcap_direction_t d) { p->direction = d; return 0; } static int usb_stats_linux_bin(pcap_t *handle, struct pcap_stat *stats) { int ret; struct mon_bin_stats st; ret = ioctl(handle->fd, MON_IOCG_STATS, &st); if (ret < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't read stats from fd %d:%s ", handle->fd, strerror(errno)); return -1; } stats->ps_recv = handle->md.packets_read + st.queued; stats->ps_drop = st.dropped; stats->ps_ifdrop = 0; return 0; } /* * see /Documentation/usb/usbmon.txt and * /drivers/usb/mon/mon_bin.c binary ABI */ static int usb_read_linux_bin(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) { struct mon_bin_get info; int ret; struct pcap_pkthdr pkth; int clen = handle->snapshot - sizeof(pcap_usb_header); /* the usb header is going to be part of 'packet' data*/ info.hdr = (pcap_usb_header*) handle->buffer; info.data = handle->buffer + sizeof(pcap_usb_header); info.data_len = clen; /* ignore interrupt system call errors */ do { ret = ioctl(handle->fd, MON_IOCX_GET, &info); if (handle->break_loop) { handle->break_loop = 0; return -2; } } while ((ret == -1) && (errno == EINTR)); if (ret < 0) { if (errno == EAGAIN) return 0; /* no data there */ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't read from fd %d: %s", handle->fd, strerror(errno)); return -1; } /* we can get less that than really captured from kernel, depending on * snaplen, so adjust header accordingly */ if (info.hdr->data_len < clen) clen = info.hdr->data_len; info.hdr->data_len = clen; pkth.caplen = clen + sizeof(pcap_usb_header); pkth.len = info.hdr->data_len + sizeof(pcap_usb_header); pkth.ts.tv_sec = info.hdr->ts_sec; pkth.ts.tv_usec = info.hdr->ts_usec; if (handle->fcode.bf_insns == NULL || bpf_filter(handle->fcode.bf_insns, handle->buffer, pkth.len, pkth.caplen)) { handle->md.packets_read++; callback(user, &pkth, handle->buffer); return 1; } return 0; /* didn't pass filter */ } /* * see /Documentation/usb/usbmon.txt and * /drivers/usb/mon/mon_bin.c binary ABI */ #define VEC_SIZE 32 static int usb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) { struct mon_bin_mfetch fetch; int32_t vec[VEC_SIZE]; struct pcap_pkthdr pkth; pcap_usb_header* hdr; int nflush = 0; int packets = 0; int clen, max_clen; max_clen = handle->snapshot - sizeof(pcap_usb_header); for (;;) { int i, ret; int limit = max_packets - packets; if (limit <= 0) limit = VEC_SIZE; if (limit > VEC_SIZE) limit = VEC_SIZE; /* try to fetch as many events as possible*/ fetch.offvec = vec; fetch.nfetch = limit; fetch.nflush = nflush; /* ignore interrupt system call errors */ do { ret = ioctl(handle->fd, MON_IOCX_MFETCH, &fetch); if (handle->break_loop) { handle->break_loop = 0; return -2; } } while ((ret == -1) && (errno == EINTR)); if (ret < 0) { if (errno == EAGAIN) return 0; /* no data there */ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't mfetch fd %d: %s", handle->fd, strerror(errno)); return -1; } /* keep track of processed events, we will flush them later */ nflush = fetch.nfetch; for (i=0; imd.mmapbuf[vec[i]]; if (hdr->event_type == '@') continue; /* we can get less that than really captured from kernel, depending on * snaplen, so adjust header accordingly */ clen = max_clen; if (hdr->data_len < clen) clen = hdr->data_len; /* get packet info from header*/ pkth.caplen = clen + sizeof(pcap_usb_header_mmapped); pkth.len = hdr->data_len + sizeof(pcap_usb_header_mmapped); pkth.ts.tv_sec = hdr->ts_sec; pkth.ts.tv_usec = hdr->ts_usec; if (handle->fcode.bf_insns == NULL || bpf_filter(handle->fcode.bf_insns, (u_char*) hdr, pkth.len, pkth.caplen)) { handle->md.packets_read++; callback(user, &pkth, (u_char*) hdr); packets++; } } /* with max_packets <= 0 we stop afer the first chunk*/ if ((max_packets <= 0) || (packets == max_packets)) break; } /* flush pending events*/ ioctl(handle->fd, MON_IOCH_MFLUSH, nflush); return packets; } static void usb_cleanup_linux_mmap(pcap_t* handle) { /* if we have a memory-mapped buffer, unmap it */ if (handle->md.mmapbuf != NULL) { munmap(handle->md.mmapbuf, handle->md.mmapbuflen); handle->md.mmapbuf = NULL; } pcap_cleanup_live_common(handle); } Index: stable/9/contrib/libpcap/pcap-usb-linux.h =================================================================== --- stable/9/contrib/libpcap/pcap-usb-linux.h (revision 252280) +++ stable/9/contrib/libpcap/pcap-usb-linux.h (revision 252281) @@ -1,40 +1,40 @@ /* * Copyright (c) 2006 Paolo Abeni (Italy) * 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. The name of the author may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT * OWNER 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. * * USB sniffing API implementation for Linux platform * By Paolo Abeni * * @(#) $Header: /tcpdump/master/libpcap/pcap-usb-linux.h,v 1.5 2008-04-04 19:37:45 guy Exp $ (LBL) */ /* * Prototypes for USB-related functions */ -int usb_platform_finddevs(pcap_if_t **alldevsp, char *err_str); -pcap_t *usb_create(const char *device, char *ebuf); +int usb_findalldevs(pcap_if_t **alldevsp, char *err_str); +pcap_t *usb_create(const char *device, char *ebuf, int *is_ours); Index: stable/9/contrib/libpcap/pcap-win32.c =================================================================== --- stable/9/contrib/libpcap/pcap-win32.c (revision 252280) +++ stable/9/contrib/libpcap/pcap-win32.c (revision 252281) @@ -1,852 +1,852 @@ /* * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy) * Copyright (c) 2005 - 2008 CACE Technologies, Davis (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. Neither the name of the Politecnico di Torino, CACE Technologies * 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 COPYRIGHT HOLDERS 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 COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.42 2008-05-21 22:15:25 gianluca Exp $ (LBL)"; #endif #include #include #ifdef __MINGW32__ #ifdef __MINGW64__ #include #else /*__MINGW64__*/ #include #include #endif /*__MINGW64__*/ #else /*__MINGW32__*/ #include #endif /*__MINGW32__*/ #ifdef HAVE_DAG_API #include #include #endif /* HAVE_DAG_API */ #ifdef __MINGW32__ int* _errno(); #define errno (*_errno()) #endif /* __MINGW32__ */ static int pcap_setfilter_win32_npf(pcap_t *, struct bpf_program *); static int pcap_setfilter_win32_dag(pcap_t *, struct bpf_program *); static int pcap_getnonblock_win32(pcap_t *, char *); static int pcap_setnonblock_win32(pcap_t *, int, char *); /*dimension of the buffer in the pcap_t structure*/ #define WIN32_DEFAULT_USER_BUFFER_SIZE 256000 /*dimension of the buffer in the kernel driver NPF */ #define WIN32_DEFAULT_KERNEL_BUFFER_SIZE 1000000 /* Equivalent to ntohs(), but a lot faster under Windows */ #define SWAPS(_X) ((_X & 0xff) << 8) | (_X >> 8) /* * Header that the WinPcap driver associates to the packets. * Once was in bpf.h */ struct bpf_hdr { struct timeval bh_tstamp; /* time stamp */ bpf_u_int32 bh_caplen; /* length of captured portion */ bpf_u_int32 bh_datalen; /* original length of packet */ u_short bh_hdrlen; /* length of bpf header (this struct plus alignment padding) */ }; CRITICAL_SECTION g_PcapCompileCriticalSection; BOOL WINAPI DllMain( HANDLE hinstDLL, DWORD dwReason, LPVOID lpvReserved ) { if (dwReason == DLL_PROCESS_ATTACH) { InitializeCriticalSection(&g_PcapCompileCriticalSection); } return TRUE; } /* Start winsock */ int wsockinit() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 1, 1); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { return -1; } return 0; } static int pcap_stats_win32(pcap_t *p, struct pcap_stat *ps) { if(PacketGetStats(p->adapter, (struct bpf_stat*)ps) != TRUE){ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "PacketGetStats error: %s", pcap_win32strerror()); return -1; } return 0; } /* Set the dimension of the kernel-level capture buffer */ static int pcap_setbuff_win32(pcap_t *p, int dim) { if(PacketSetBuff(p->adapter,dim)==FALSE) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer"); return -1; } return 0; } /* Set the driver working mode */ static int pcap_setmode_win32(pcap_t *p, int mode) { if(PacketSetMode(p->adapter,mode)==FALSE) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized"); return -1; } return 0; } /*set the minimum amount of data that will release a read call*/ static int pcap_setmintocopy_win32(pcap_t *p, int size) { if(PacketSetMinToCopy(p->adapter, size)==FALSE) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size"); return -1; } return 0; } static int pcap_read_win32_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { int cc; int n = 0; register u_char *bp, *ep; cc = p->cc; if (p->cc == 0) { /* * Has "pcap_breakloop()" been called? */ if (p->break_loop) { /* * Yes - clear the flag that indicates that it * has, and return -2 to indicate that we were * told to break out of the loop. */ p->break_loop = 0; return (-2); } /* capture the packets */ if(PacketReceivePacket(p->adapter,p->Packet,TRUE)==FALSE){ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed"); return (-1); } cc = p->Packet->ulBytesReceived; bp = p->Packet->Buffer; } else bp = p->bp; /* * Loop through each packet. */ #define bhp ((struct bpf_hdr *)bp) ep = bp + cc; while (1) { register int caplen, hdrlen; /* * Has "pcap_breakloop()" been called? * If so, return immediately - if we haven't read any * packets, clear the flag and return -2 to indicate * that we were told to break out of the loop, otherwise * leave the flag set, so that the *next* call will break * out of the loop without having read any packets, and * return the number of packets we've processed so far. */ if (p->break_loop) { if (n == 0) { p->break_loop = 0; return (-2); } else { p->bp = bp; p->cc = ep - bp; return (n); } } if (bp >= ep) break; caplen = bhp->bh_caplen; hdrlen = bhp->bh_hdrlen; /* * XXX A bpf_hdr matches a pcap_pkthdr. */ (*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen); bp += Packet_WORDALIGN(caplen + hdrlen); if (++n >= cnt && cnt > 0) { p->bp = bp; p->cc = ep - bp; return (n); } } #undef bhp p->cc = 0; return (n); } #ifdef HAVE_DAG_API static int pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { u_char *dp = NULL; int packet_len = 0, caplen = 0; struct pcap_pkthdr pcap_header; u_char *endofbuf; int n = 0; dag_record_t *header; unsigned erf_record_len; ULONGLONG ts; int cc; unsigned swt; unsigned dfp = p->adapter->DagFastProcess; cc = p->cc; if (cc == 0) /* Get new packets only if we have processed all the ones of the previous read */ { /* Get new packets from the network */ if(PacketReceivePacket(p->adapter, p->Packet, TRUE)==FALSE){ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed"); return (-1); } cc = p->Packet->ulBytesReceived; if(cc == 0) /* The timeout has expired but we no packets arrived */ return 0; header = (dag_record_t*)p->adapter->DagBuffer; } else header = (dag_record_t*)p->bp; endofbuf = (char*)header + cc; /* * Cycle through the packets */ do { erf_record_len = SWAPS(header->rlen); if((char*)header + erf_record_len > endofbuf) break; /* Increase the number of captured packets */ p->md.stat.ps_recv++; /* Find the beginning of the packet */ dp = ((u_char *)header) + dag_record_size; /* Determine actual packet len */ switch(header->type) { case TYPE_ATM: packet_len = ATM_SNAPLEN; caplen = ATM_SNAPLEN; dp += 4; break; case TYPE_ETH: swt = SWAPS(header->wlen); packet_len = swt - (p->md.dag_fcs_bits); caplen = erf_record_len - dag_record_size - 2; if (caplen > packet_len) { caplen = packet_len; } dp += 2; break; case TYPE_HDLC_POS: swt = SWAPS(header->wlen); packet_len = swt - (p->md.dag_fcs_bits); caplen = erf_record_len - dag_record_size; if (caplen > packet_len) { caplen = packet_len; } break; } if(caplen > p->snapshot) caplen = p->snapshot; /* * Has "pcap_breakloop()" been called? * If so, return immediately - if we haven't read any * packets, clear the flag and return -2 to indicate * that we were told to break out of the loop, otherwise * leave the flag set, so that the *next* call will break * out of the loop without having read any packets, and * return the number of packets we've processed so far. */ if (p->break_loop) { if (n == 0) { p->break_loop = 0; return (-2); } else { p->bp = (char*)header; p->cc = endofbuf - (char*)header; return (n); } } if(!dfp) { /* convert between timestamp formats */ ts = header->ts; pcap_header.ts.tv_sec = (int)(ts >> 32); ts = (ts & 0xffffffffi64) * 1000000; ts += 0x80000000; /* rounding */ pcap_header.ts.tv_usec = (int)(ts >> 32); if (pcap_header.ts.tv_usec >= 1000000) { pcap_header.ts.tv_usec -= 1000000; pcap_header.ts.tv_sec++; } } /* No underlaying filtering system. We need to filter on our own */ if (p->fcode.bf_insns) { if (bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen) == 0) { /* Move to next packet */ header = (dag_record_t*)((char*)header + erf_record_len); continue; } } /* Fill the header for the user suppplied callback function */ pcap_header.caplen = caplen; pcap_header.len = packet_len; /* Call the callback function */ (*callback)(user, &pcap_header, dp); /* Move to next packet */ header = (dag_record_t*)((char*)header + erf_record_len); /* Stop if the number of packets requested by user has been reached*/ if (++n >= cnt && cnt > 0) { p->bp = (char*)header; p->cc = endofbuf - (char*)header; return (n); } } while((u_char*)header < endofbuf); return 1; } #endif /* HAVE_DAG_API */ /* Send a packet to the network */ static int pcap_inject_win32(pcap_t *p, const void *buf, size_t size){ LPPACKET PacketToSend; PacketToSend=PacketAllocatePacket(); if (PacketToSend == NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketAllocatePacket failed"); return -1; } PacketInitPacket(PacketToSend,(PVOID)buf,size); if(PacketSendPacket(p->adapter,PacketToSend,TRUE) == FALSE){ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketSendPacket failed"); PacketFreePacket(PacketToSend); return -1; } PacketFreePacket(PacketToSend); /* * We assume it all got sent if "PacketSendPacket()" succeeded. * "pcap_inject()" is expected to return the number of bytes * sent. */ return size; } static void pcap_cleanup_win32(pcap_t *p) { if (p->adapter != NULL) { PacketCloseAdapter(p->adapter); p->adapter = NULL; } if (p->Packet) { PacketFreePacket(p->Packet); p->Packet = NULL; } pcap_cleanup_live_common(p); } static int pcap_activate_win32(pcap_t *p) { NetType type; if (p->opt.rfmon) { /* * No monitor mode on Windows. It could be done on * Vista with drivers that support the native 802.11 * mechanism and monitor mode. */ return (PCAP_ERROR_RFMON_NOTSUP); } /* Init WinSock */ wsockinit(); p->adapter = PacketOpenAdapter(p->opt.source); if (p->adapter == NULL) { /* Adapter detected but we are not able to open it. Return failure. */ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error opening adapter: %s", pcap_win32strerror()); return PCAP_ERROR; } /*get network type*/ if(PacketGetNetType (p->adapter,&type) == FALSE) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Cannot determine the network type: %s", pcap_win32strerror()); goto bad; } /*Set the linktype*/ switch (type.LinkType) { case NdisMediumWan: p->linktype = DLT_EN10MB; break; case NdisMedium802_3: p->linktype = DLT_EN10MB; /* * This is (presumably) a real Ethernet capture; give it a * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so * that an application can let you choose it, in case you're * capturing DOCSIS traffic that a Cisco Cable Modem * Termination System is putting out onto an Ethernet (it * doesn't put an Ethernet header onto the wire, it puts raw * DOCSIS frames out on the wire inside the low-level * Ethernet framing). */ p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); /* * If that fails, just leave the list empty. */ if (p->dlt_list != NULL) { p->dlt_list[0] = DLT_EN10MB; p->dlt_list[1] = DLT_DOCSIS; p->dlt_count = 2; } break; case NdisMediumFddi: p->linktype = DLT_FDDI; break; case NdisMedium802_5: p->linktype = DLT_IEEE802; break; case NdisMediumArcnetRaw: p->linktype = DLT_ARCNET; break; case NdisMediumArcnet878_2: p->linktype = DLT_ARCNET; break; case NdisMediumAtm: p->linktype = DLT_ATM_RFC1483; break; case NdisMediumCHDLC: p->linktype = DLT_CHDLC; break; case NdisMediumPPPSerial: p->linktype = DLT_PPP_SERIAL; break; case NdisMediumNull: p->linktype = DLT_NULL; break; case NdisMediumBare80211: p->linktype = DLT_IEEE802_11; break; case NdisMediumRadio80211: p->linktype = DLT_IEEE802_11_RADIO; break; case NdisMediumPpi: p->linktype = DLT_PPI; break; default: p->linktype = DLT_EN10MB; /*an unknown adapter is assumed to be ethernet*/ break; } /* Set promiscuous mode */ if (p->opt.promisc) { if (PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_PROMISCUOUS) == FALSE) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to promiscuous mode"); goto bad; } } else { if (PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_ALL_LOCAL) == FALSE) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to non-promiscuous mode"); goto bad; } } /* Set the buffer size */ p->bufsize = WIN32_DEFAULT_USER_BUFFER_SIZE; /* allocate Packet structure used during the capture */ if((p->Packet = PacketAllocatePacket())==NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to allocate the PACKET structure"); goto bad; } if(!(p->adapter->Flags & INFO_FLAG_DAG_CARD)) { /* * Traditional Adapter */ /* * If the buffer size wasn't explicitly set, default to * WIN32_DEFAULT_USER_BUFFER_SIZE. */ if (p->opt.buffer_size == 0) p->opt.buffer_size = WIN32_DEFAULT_KERNEL_BUFFER_SIZE; if(PacketSetBuff(p->adapter,p->opt.buffer_size)==FALSE) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer"); goto bad; } p->buffer = (u_char *)malloc(p->bufsize); if (p->buffer == NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); goto bad; } PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize); /* tell the driver to copy the buffer only if it contains at least 16K */ if(PacketSetMinToCopy(p->adapter,16000)==FALSE) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s", pcap_win32strerror()); goto bad; } } else #ifdef HAVE_DAG_API { /* * Dag Card */ LONG status; HKEY dagkey; DWORD lptype; DWORD lpcbdata; int postype = 0; char keyname[512]; snprintf(keyname, sizeof(keyname), "%s\\CardParams\\%s", "SYSTEM\\CurrentControlSet\\Services\\DAG", strstr(_strlwr(p->opt.source), "dag")); do { status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &dagkey); if(status != ERROR_SUCCESS) break; status = RegQueryValueEx(dagkey, "PosType", NULL, &lptype, (char*)&postype, &lpcbdata); if(status != ERROR_SUCCESS) { postype = 0; } RegCloseKey(dagkey); } while(FALSE); p->snapshot = PacketSetSnapLen(p->adapter, snaplen); /* Set the length of the FCS associated to any packet. This value * will be subtracted to the packet length */ p->md.dag_fcs_bits = p->adapter->DagFcsLen; } #else goto bad; #endif /* HAVE_DAG_API */ PacketSetReadTimeout(p->adapter, p->md.timeout); #ifdef HAVE_DAG_API if(p->adapter->Flags & INFO_FLAG_DAG_CARD) { /* install dag specific handlers for read and setfilter */ p->read_op = pcap_read_win32_dag; p->setfilter_op = pcap_setfilter_win32_dag; } else { #endif /* HAVE_DAG_API */ /* install traditional npf handlers for read and setfilter */ p->read_op = pcap_read_win32_npf; p->setfilter_op = pcap_setfilter_win32_npf; #ifdef HAVE_DAG_API } #endif /* HAVE_DAG_API */ p->setdirection_op = NULL; /* Not implemented. */ /* XXX - can this be implemented on some versions of Windows? */ p->inject_op = pcap_inject_win32; p->set_datalink_op = NULL; /* can't change data link type */ p->getnonblock_op = pcap_getnonblock_win32; p->setnonblock_op = pcap_setnonblock_win32; p->stats_op = pcap_stats_win32; p->setbuff_op = pcap_setbuff_win32; p->setmode_op = pcap_setmode_win32; p->setmintocopy_op = pcap_setmintocopy_win32; p->cleanup_op = pcap_cleanup_win32; return (0); bad: pcap_cleanup_win32(p); return (PCAP_ERROR); } pcap_t * -pcap_create(const char *device, char *ebuf) +pcap_create_interface(const char *device, char *ebuf) { pcap_t *p; if (strlen(device) == 1) { /* * It's probably a unicode string * Convert to ascii and pass it to pcap_create_common * * This wonderful hack is needed because pcap_lookupdev still returns * unicode strings, and it's used by windump when no device is specified * in the command line */ size_t length; char* deviceAscii; length = wcslen((wchar_t*)device); deviceAscii = (char*)malloc(length + 1); if (deviceAscii == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "Malloc failed"); return NULL; } snprintf(deviceAscii, length + 1, "%ws", (wchar_t*)device); p = pcap_create_common(deviceAscii, ebuf); free(deviceAscii); } else { p = pcap_create_common(device, ebuf); } if (p == NULL) return (NULL); p->activate_op = pcap_activate_win32; return (p); } static int pcap_setfilter_win32_npf(pcap_t *p, struct bpf_program *fp) { if(PacketSetBpf(p->adapter,fp)==FALSE){ /* * Kernel filter not installed. * XXX - fall back on userland filtering, as is done * on other platforms? */ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Driver error: cannot set bpf filter: %s", pcap_win32strerror()); return (-1); } /* * Discard any previously-received packets, as they might have * passed whatever filter was formerly in effect, but might * not pass this filter (BIOCSETF discards packets buffered * in the kernel, so you can lose packets in any case). */ p->cc = 0; return (0); } /* * We filter at user level, since the kernel driver does't process the packets */ static int pcap_setfilter_win32_dag(pcap_t *p, struct bpf_program *fp) { if(!fp) { strncpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf)); return -1; } /* Install a user level filter */ if (install_bpf_program(p, fp) < 0) { snprintf(p->errbuf, sizeof(p->errbuf), "setfilter, unable to install the filter: %s", pcap_strerror(errno)); return -1; } p->md.use_bpf = 0; return (0); } static int pcap_getnonblock_win32(pcap_t *p, char *errbuf) { /* * XXX - if there were a PacketGetReadTimeout() call, we * would use it, and return 1 if the timeout is -1 * and 0 otherwise. */ return (p->nonblock); } static int pcap_setnonblock_win32(pcap_t *p, int nonblock, char *errbuf) { int newtimeout; if (nonblock) { /* * Set the read timeout to -1 for non-blocking mode. */ newtimeout = -1; } else { /* * Restore the timeout set when the device was opened. * (Note that this may be -1, in which case we're not * really leaving non-blocking mode.) */ newtimeout = p->md.timeout; } if (!PacketSetReadTimeout(p->adapter, newtimeout)) { - snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + snprintf(errbuf, PCAP_ERRBUF_SIZE, "PacketSetReadTimeout: %s", pcap_win32strerror()); return (-1); } p->nonblock = (newtimeout == -1); return (0); } /*platform-dependent routine to add devices other than NDIS interfaces*/ int pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) { return (0); } Index: stable/9/contrib/libpcap/pcap.c =================================================================== --- stable/9/contrib/libpcap/pcap.c (revision 252280) +++ stable/9/contrib/libpcap/pcap.c (revision 252281) @@ -1,1592 +1,1808 @@ /* * Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Computer Systems * Engineering Group at Lawrence Berkeley Laboratory. * 4. Neither the name of the University nor of the Laboratory may be used * to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.128 2008-12-23 20:13:29 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef WIN32 #include #else /* WIN32 */ #if HAVE_INTTYPES_H #include #elif HAVE_STDINT_H #include #endif #ifdef HAVE_SYS_BITYPES_H #include #endif #include #include #endif /* WIN32 */ #include #include #include #if !defined(_MSC_VER) && !defined(__BORLANDC__) && !defined(__MINGW32__) #include #endif #include #include #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif #ifdef MSDOS #include "pcap-dos.h" #endif #include "pcap-int.h" #ifdef HAVE_DAG_API -#include -#include +#include "pcap-dag.h" +#endif /* HAVE_DAG_API */ + +#ifdef HAVE_SEPTEL_API +#include "pcap-septel.h" +#endif /* HAVE_SEPTEL_API */ + +#ifdef HAVE_SNF_API +#include "pcap-snf.h" +#endif /* HAVE_SNF_API */ + +#ifdef PCAP_SUPPORT_USB +#include "pcap-usb-linux.h" #endif +#ifdef PCAP_SUPPORT_BT +#include "pcap-bt-linux.h" +#endif + +#ifdef PCAP_SUPPORT_CAN +#include "pcap-can-linux.h" +#endif + +#ifdef PCAP_SUPPORT_CANUSB +#include "pcap-canusb-linux.h" +#endif + +#ifdef PCAP_SUPPORT_NETFILTER +#include "pcap-netfilter-linux.h" +#endif + int pcap_not_initialized(pcap_t *pcap) { /* this means 'not initialized' */ return (PCAP_ERROR_NOT_ACTIVATED); } /* * Returns 1 if rfmon mode can be set on the pcap_t, 0 if it can't, * a PCAP_ERROR value on an error. */ int pcap_can_set_rfmon(pcap_t *p) { return (p->can_set_rfmon_op(p)); } /* * For systems where rfmon mode is never supported. */ static int pcap_cant_set_rfmon(pcap_t *p _U_) { return (0); } /* * Sets *tstamp_typesp to point to an array 1 or more supported time stamp * types; the return value is the number of supported time stamp types. * The list should be freed by a call to pcap_free_tstamp_types() when * you're done with it. * * A return value of 0 means "you don't get a choice of time stamp type", * in which case *tstamp_typesp is set to null. * * PCAP_ERROR is returned on error. */ int pcap_list_tstamp_types(pcap_t *p, int **tstamp_typesp) { if (p->tstamp_type_count == 0) { /* * We don't support multiple time stamp types. */ *tstamp_typesp = NULL; } else { *tstamp_typesp = (int*)calloc(sizeof(**tstamp_typesp), p->tstamp_type_count); if (*tstamp_typesp == NULL) { (void)snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", pcap_strerror(errno)); return (PCAP_ERROR); } (void)memcpy(*tstamp_typesp, p->tstamp_type_list, sizeof(**tstamp_typesp) * p->tstamp_type_count); } return (p->tstamp_type_count); } /* * In Windows, you might have a library built with one version of the * C runtime library and an application built with another version of * the C runtime library, which means that the library might use one * version of malloc() and free() and the application might use another * version of malloc() and free(). If so, that means something * allocated by the library cannot be freed by the application, so we * need to have a pcap_free_tstamp_types() routine to free up the list * allocated by pcap_list_tstamp_types(), even though it's just a wrapper * around free(). */ void pcap_free_tstamp_types(int *tstamp_type_list) { free(tstamp_type_list); } /* * Default one-shot callback; overridden for capture types where the * packet data cannot be guaranteed to be available after the callback * returns, so that a copy must be made. */ static void pcap_oneshot(u_char *user, const struct pcap_pkthdr *h, const u_char *pkt) { struct oneshot_userdata *sp = (struct oneshot_userdata *)user; *sp->hdr = *h; *sp->pkt = pkt; } const u_char * pcap_next(pcap_t *p, struct pcap_pkthdr *h) { struct oneshot_userdata s; const u_char *pkt; s.hdr = h; s.pkt = &pkt; s.pd = p; if (pcap_dispatch(p, 1, p->oneshot_callback, (u_char *)&s) <= 0) return (0); return (pkt); } int pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header, const u_char **pkt_data) { struct oneshot_userdata s; s.hdr = &p->pcap_header; s.pkt = pkt_data; s.pd = p; /* Saves a pointer to the packet headers */ *pkt_header= &p->pcap_header; if (p->sf.rfile != NULL) { int status; /* We are on an offline capture */ status = pcap_offline_read(p, 1, p->oneshot_callback, (u_char *)&s); /* * Return codes for pcap_offline_read() are: * - 0: EOF * - -1: error * - >1: OK * The first one ('0') conflicts with the return code of * 0 from pcap_read() meaning "no packets arrived before * the timeout expired", so we map it to -2 so you can * distinguish between an EOF from a savefile and a * "no packets arrived before the timeout expired, try * again" from a live capture. */ if (status == 0) return (-2); else return (status); } /* * Return codes for pcap_read() are: * - 0: timeout * - -1: error * - -2: loop was broken out of with pcap_breakloop() * - >1: OK * The first one ('0') conflicts with the return code of 0 from * pcap_offline_read() meaning "end of file". */ return (p->read_op(p, 1, p->oneshot_callback, (u_char *)&s)); } +#if defined(DAG_ONLY) +int +pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) +{ + return (dag_findalldevs(alldevsp, errbuf)); +} + +pcap_t * +pcap_create(const char *source, char *errbuf) +{ + return (dag_create(source, errbuf)); +} +#elif defined(SEPTEL_ONLY) +int +pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) +{ + return (septel_findalldevs(alldevsp, errbuf)); +} + +pcap_t * +pcap_create(const char *source, char *errbuf) +{ + return (septel_create(source, errbuf)); +} +#elif defined(SNF_ONLY) +int +pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) +{ + return (snf_findalldevs(alldevsp, errbuf)); +} + +pcap_t * +pcap_create(const char *source, char *errbuf) +{ + return (snf_create(source, errbuf)); +} +#else /* regular pcap */ +struct capture_source_type { + int (*findalldevs_op)(pcap_if_t **, char *); + pcap_t *(*create_op)(const char *, char *, int *); +} capture_source_types[] = { +#ifdef HAVE_DAG_API + { dag_findalldevs, dag_create }, +#endif +#ifdef HAVE_SEPTEL_API + { septel_findalldevs, septel_create }, +#endif +#ifdef HAVE_SNF_API + { snf_findalldevs, snf_create }, +#endif +#ifdef PCAP_SUPPORT_BT + { bt_findalldevs, bt_create }, +#endif +#if PCAP_SUPPORT_CANUSB + { canusb_findalldevs, canusb_create }, +#endif +#ifdef PCAP_SUPPORT_CAN + { can_findalldevs, can_create }, +#endif +#ifdef PCAP_SUPPORT_USB + { usb_findalldevs, usb_create }, +#endif +#ifdef PCAP_SUPPORT_NETFILTER + { netfilter_findalldevs, netfilter_create }, +#endif + { NULL, NULL } +}; + +/* + * Get a list of all capture sources 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. + */ +int +pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) +{ + size_t i; + + /* + * Get the list of regular interfaces first. + */ + if (pcap_findalldevs_interfaces(alldevsp, errbuf) == -1) + return (-1); /* failure */ + + /* + * Add any interfaces that need a platform-specific mechanism + * to find. + */ + if (pcap_platform_finddevs(alldevsp, errbuf) == -1) { + /* + * We had an error; free the list we've been + * constructing. + */ + if (*alldevsp != NULL) { + pcap_freealldevs(*alldevsp); + *alldevsp = NULL; + } + return (-1); + } + + /* + * Ask each of the non-local-network-interface capture + * source types what interfaces they have. + */ + for (i = 0; capture_source_types[i].findalldevs_op != NULL; i++) { + if (capture_source_types[i].findalldevs_op(alldevsp, errbuf) == -1) { + /* + * We had an error; free the list we've been + * constructing. + */ + if (*alldevsp != NULL) { + pcap_freealldevs(*alldevsp); + *alldevsp = NULL; + } + return (-1); + } + } + return (0); +} + +pcap_t * +pcap_create(const char *source, char *errbuf) +{ + size_t i; + int is_theirs; + pcap_t *p; + + /* + * A null source name is equivalent to the "any" device - + * which might not be supported on this platform, but + * this means that you'll get a "not supported" error + * rather than, say, a crash when we try to dereference + * the null pointer. + */ + if (source == NULL) + source = "any"; + + /* + * Try each of the non-local-network-interface capture + * source types until we find one that works for this + * device or run out of types. + */ + for (i = 0; capture_source_types[i].create_op != NULL; i++) { + is_theirs = 0; + p = capture_source_types[i].create_op(source, errbuf, &is_theirs); + if (is_theirs) { + /* + * The device name refers to a device of the + * type in question; either it succeeded, + * in which case p refers to a pcap_t to + * later activate for the device, or it + * failed, in which case p is null and we + * should return that to report the failure + * to create. + */ + return (p); + } + } + + /* + * OK, try it as a regular network interface. + */ + return (pcap_create_interface(source, errbuf)); +} +#endif + static void initialize_ops(pcap_t *p) { /* * Set operation pointers for operations that only work on * an activated pcap_t to point to a routine that returns * a "this isn't activated" error. */ p->read_op = (read_op_t)pcap_not_initialized; p->inject_op = (inject_op_t)pcap_not_initialized; p->setfilter_op = (setfilter_op_t)pcap_not_initialized; p->setdirection_op = (setdirection_op_t)pcap_not_initialized; p->set_datalink_op = (set_datalink_op_t)pcap_not_initialized; p->getnonblock_op = (getnonblock_op_t)pcap_not_initialized; p->setnonblock_op = (setnonblock_op_t)pcap_not_initialized; p->stats_op = (stats_op_t)pcap_not_initialized; #ifdef WIN32 p->setbuff_op = (setbuff_op_t)pcap_not_initialized; p->setmode_op = (setmode_op_t)pcap_not_initialized; p->setmintocopy_op = (setmintocopy_op_t)pcap_not_initialized; #endif /* * Default cleanup operation - implementations can override * this, but should call pcap_cleanup_live_common() after * doing their own additional cleanup. */ p->cleanup_op = pcap_cleanup_live_common; /* * In most cases, the standard one-short callback can * be used for pcap_next()/pcap_next_ex(). */ p->oneshot_callback = pcap_oneshot; } pcap_t * pcap_create_common(const char *source, char *ebuf) { pcap_t *p; p = malloc(sizeof(*p)); if (p == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); return (NULL); } memset(p, 0, sizeof(*p)); #ifndef WIN32 p->fd = -1; /* not opened yet */ p->selectable_fd = -1; p->send_fd = -1; #endif p->opt.source = strdup(source); if (p->opt.source == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); free(p); return (NULL); } /* * Default to "can't set rfmon mode"; if it's supported by * a platform, the create routine that called us can set * the op to its routine to check whether a particular * device supports it. */ p->can_set_rfmon_op = pcap_cant_set_rfmon; initialize_ops(p); /* put in some defaults*/ pcap_set_timeout(p, 0); pcap_set_snaplen(p, 65535); /* max packet size */ p->opt.promisc = 0; p->opt.buffer_size = 0; p->opt.tstamp_type = -1; /* default to not setting time stamp type */ return (p); } int pcap_check_activated(pcap_t *p) { if (p->activated) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't perform " " operation on activated capture"); return (-1); } return (0); } int pcap_set_snaplen(pcap_t *p, int snaplen) { if (pcap_check_activated(p)) return (PCAP_ERROR_ACTIVATED); p->snapshot = snaplen; return (0); } int pcap_set_promisc(pcap_t *p, int promisc) { if (pcap_check_activated(p)) return (PCAP_ERROR_ACTIVATED); p->opt.promisc = promisc; return (0); } int pcap_set_rfmon(pcap_t *p, int rfmon) { if (pcap_check_activated(p)) return (PCAP_ERROR_ACTIVATED); p->opt.rfmon = rfmon; return (0); } int pcap_set_timeout(pcap_t *p, int timeout_ms) { if (pcap_check_activated(p)) return (PCAP_ERROR_ACTIVATED); p->md.timeout = timeout_ms; return (0); } int pcap_set_tstamp_type(pcap_t *p, int tstamp_type) { int i; if (pcap_check_activated(p)) return (PCAP_ERROR_ACTIVATED); /* * If p->tstamp_type_count is 0, we don't support setting * the time stamp type at all. */ if (p->tstamp_type_count == 0) return (PCAP_ERROR_CANTSET_TSTAMP_TYPE); /* * Check whether we claim to support this type of time stamp. */ for (i = 0; i < p->tstamp_type_count; i++) { if (p->tstamp_type_list[i] == tstamp_type) { /* * Yes. */ p->opt.tstamp_type = tstamp_type; return (0); } } /* * No. We support setting the time stamp type, but not to this * particular value. */ return (PCAP_WARNING_TSTAMP_TYPE_NOTSUP); } int pcap_set_buffer_size(pcap_t *p, int buffer_size) { if (pcap_check_activated(p)) return (PCAP_ERROR_ACTIVATED); p->opt.buffer_size = buffer_size; return (0); } int pcap_activate(pcap_t *p) { int status; /* * Catch attempts to re-activate an already-activated * pcap_t; this should, for example, catch code that * calls pcap_open_live() followed by pcap_activate(), * as some code that showed up in a Stack Exchange * question did. */ if (pcap_check_activated(p)) return (PCAP_ERROR_ACTIVATED); status = p->activate_op(p); if (status >= 0) p->activated = 1; else { if (p->errbuf[0] == '\0') { /* * No error message supplied by the activate routine; * for the benefit of programs that don't specially * handle errors other than PCAP_ERROR, return the * error message corresponding to the status. */ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s", pcap_statustostr(status)); } /* * Undo any operation pointer setting, etc. done by * the activate operation. */ initialize_ops(p); } return (status); } pcap_t * pcap_open_live(const char *source, int snaplen, int promisc, int to_ms, char *errbuf) { pcap_t *p; int status; p = pcap_create(source, errbuf); if (p == NULL) return (NULL); status = pcap_set_snaplen(p, snaplen); if (status < 0) goto fail; status = pcap_set_promisc(p, promisc); if (status < 0) goto fail; status = pcap_set_timeout(p, to_ms); if (status < 0) goto fail; /* * Mark this as opened with pcap_open_live(), so that, for * example, we show the full list of DLT_ values, rather * than just the ones that are compatible with capturing * when not in monitor mode. That allows existing applications * to work the way they used to work, but allows new applications * that know about the new open API to, for example, find out the * DLT_ values that they can select without changing whether * the adapter is in monitor mode or not. */ p->oldstyle = 1; status = pcap_activate(p); if (status < 0) goto fail; return (p); fail: if (status == PCAP_ERROR) snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", source, p->errbuf); else if (status == PCAP_ERROR_NO_SUCH_DEVICE || status == PCAP_ERROR_PERM_DENIED || status == PCAP_ERROR_PROMISC_PERM_DENIED) snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%s)", source, pcap_statustostr(status), p->errbuf); else snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", source, pcap_statustostr(status)); pcap_close(p); return (NULL); } int pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { return (p->read_op(p, cnt, callback, user)); } /* * XXX - is this necessary? */ int pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { return (p->read_op(p, cnt, callback, user)); } int pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { register int n; for (;;) { if (p->sf.rfile != NULL) { /* * 0 means EOF, so don't loop if we get 0. */ n = pcap_offline_read(p, cnt, callback, user); } else { /* * XXX keep reading until we get something * (or an error occurs) */ do { n = p->read_op(p, cnt, callback, user); } while (n == 0); } if (n <= 0) return (n); if (cnt > 0) { cnt -= n; if (cnt <= 0) return (0); } } } /* * Force the loop in "pcap_read()" or "pcap_read_offline()" to terminate. */ void pcap_breakloop(pcap_t *p) { p->break_loop = 1; } int pcap_datalink(pcap_t *p) { return (p->linktype); } int pcap_datalink_ext(pcap_t *p) { return (p->linktype_ext); } int pcap_list_datalinks(pcap_t *p, int **dlt_buffer) { if (p->dlt_count == 0) { /* * We couldn't fetch the list of DLTs, which means * this platform doesn't support changing the * DLT for an interface. Return a list of DLTs * containing only the DLT this device supports. */ *dlt_buffer = (int*)malloc(sizeof(**dlt_buffer)); if (*dlt_buffer == NULL) { (void)snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", pcap_strerror(errno)); return (-1); } **dlt_buffer = p->linktype; return (1); } else { *dlt_buffer = (int*)calloc(sizeof(**dlt_buffer), p->dlt_count); if (*dlt_buffer == NULL) { (void)snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", pcap_strerror(errno)); return (-1); } (void)memcpy(*dlt_buffer, p->dlt_list, sizeof(**dlt_buffer) * p->dlt_count); return (p->dlt_count); } } /* * In Windows, you might have a library built with one version of the * C runtime library and an application built with another version of * the C runtime library, which means that the library might use one * version of malloc() and free() and the application might use another * version of malloc() and free(). If so, that means something * allocated by the library cannot be freed by the application, so we * need to have a pcap_free_datalinks() routine to free up the list * allocated by pcap_list_datalinks(), even though it's just a wrapper * around free(). */ void pcap_free_datalinks(int *dlt_list) { free(dlt_list); } int pcap_set_datalink(pcap_t *p, int dlt) { int i; const char *dlt_name; if (p->dlt_count == 0 || p->set_datalink_op == NULL) { /* * We couldn't fetch the list of DLTs, or we don't * have a "set datalink" operation, which means * this platform doesn't support changing the * DLT for an interface. Check whether the new * DLT is the one this interface supports. */ if (p->linktype != dlt) goto unsupported; /* * It is, so there's nothing we need to do here. */ return (0); } for (i = 0; i < p->dlt_count; i++) if (p->dlt_list[i] == dlt) break; if (i >= p->dlt_count) goto unsupported; if (p->dlt_count == 2 && p->dlt_list[0] == DLT_EN10MB && dlt == DLT_DOCSIS) { /* * This is presumably an Ethernet device, as the first * link-layer type it offers is DLT_EN10MB, and the only * other type it offers is DLT_DOCSIS. That means that * we can't tell the driver to supply DOCSIS link-layer * headers - we're just pretending that's what we're * getting, as, presumably, we're capturing on a dedicated * link to a Cisco Cable Modem Termination System, and * it's putting raw DOCSIS frames on the wire inside low-level * Ethernet framing. */ p->linktype = dlt; return (0); } if (p->set_datalink_op(p, dlt) == -1) return (-1); p->linktype = dlt; return (0); unsupported: dlt_name = pcap_datalink_val_to_name(dlt); if (dlt_name != NULL) { (void) snprintf(p->errbuf, sizeof(p->errbuf), "%s is not one of the DLTs supported by this device", dlt_name); } else { (void) snprintf(p->errbuf, sizeof(p->errbuf), "DLT %d is not one of the DLTs supported by this device", dlt); } return (-1); } /* * This array is designed for mapping upper and lower case letter * together for a case independent comparison. The mappings are * based upon ascii character sequences. */ static const u_char charmap[] = { (u_char)'\000', (u_char)'\001', (u_char)'\002', (u_char)'\003', (u_char)'\004', (u_char)'\005', (u_char)'\006', (u_char)'\007', (u_char)'\010', (u_char)'\011', (u_char)'\012', (u_char)'\013', (u_char)'\014', (u_char)'\015', (u_char)'\016', (u_char)'\017', (u_char)'\020', (u_char)'\021', (u_char)'\022', (u_char)'\023', (u_char)'\024', (u_char)'\025', (u_char)'\026', (u_char)'\027', (u_char)'\030', (u_char)'\031', (u_char)'\032', (u_char)'\033', (u_char)'\034', (u_char)'\035', (u_char)'\036', (u_char)'\037', (u_char)'\040', (u_char)'\041', (u_char)'\042', (u_char)'\043', (u_char)'\044', (u_char)'\045', (u_char)'\046', (u_char)'\047', (u_char)'\050', (u_char)'\051', (u_char)'\052', (u_char)'\053', (u_char)'\054', (u_char)'\055', (u_char)'\056', (u_char)'\057', (u_char)'\060', (u_char)'\061', (u_char)'\062', (u_char)'\063', (u_char)'\064', (u_char)'\065', (u_char)'\066', (u_char)'\067', (u_char)'\070', (u_char)'\071', (u_char)'\072', (u_char)'\073', (u_char)'\074', (u_char)'\075', (u_char)'\076', (u_char)'\077', (u_char)'\100', (u_char)'\141', (u_char)'\142', (u_char)'\143', (u_char)'\144', (u_char)'\145', (u_char)'\146', (u_char)'\147', (u_char)'\150', (u_char)'\151', (u_char)'\152', (u_char)'\153', (u_char)'\154', (u_char)'\155', (u_char)'\156', (u_char)'\157', (u_char)'\160', (u_char)'\161', (u_char)'\162', (u_char)'\163', (u_char)'\164', (u_char)'\165', (u_char)'\166', (u_char)'\167', (u_char)'\170', (u_char)'\171', (u_char)'\172', (u_char)'\133', (u_char)'\134', (u_char)'\135', (u_char)'\136', (u_char)'\137', (u_char)'\140', (u_char)'\141', (u_char)'\142', (u_char)'\143', (u_char)'\144', (u_char)'\145', (u_char)'\146', (u_char)'\147', (u_char)'\150', (u_char)'\151', (u_char)'\152', (u_char)'\153', (u_char)'\154', (u_char)'\155', (u_char)'\156', (u_char)'\157', (u_char)'\160', (u_char)'\161', (u_char)'\162', (u_char)'\163', (u_char)'\164', (u_char)'\165', (u_char)'\166', (u_char)'\167', (u_char)'\170', (u_char)'\171', (u_char)'\172', (u_char)'\173', (u_char)'\174', (u_char)'\175', (u_char)'\176', (u_char)'\177', (u_char)'\200', (u_char)'\201', (u_char)'\202', (u_char)'\203', (u_char)'\204', (u_char)'\205', (u_char)'\206', (u_char)'\207', (u_char)'\210', (u_char)'\211', (u_char)'\212', (u_char)'\213', (u_char)'\214', (u_char)'\215', (u_char)'\216', (u_char)'\217', (u_char)'\220', (u_char)'\221', (u_char)'\222', (u_char)'\223', (u_char)'\224', (u_char)'\225', (u_char)'\226', (u_char)'\227', (u_char)'\230', (u_char)'\231', (u_char)'\232', (u_char)'\233', (u_char)'\234', (u_char)'\235', (u_char)'\236', (u_char)'\237', (u_char)'\240', (u_char)'\241', (u_char)'\242', (u_char)'\243', (u_char)'\244', (u_char)'\245', (u_char)'\246', (u_char)'\247', (u_char)'\250', (u_char)'\251', (u_char)'\252', (u_char)'\253', (u_char)'\254', (u_char)'\255', (u_char)'\256', (u_char)'\257', (u_char)'\260', (u_char)'\261', (u_char)'\262', (u_char)'\263', (u_char)'\264', (u_char)'\265', (u_char)'\266', (u_char)'\267', (u_char)'\270', (u_char)'\271', (u_char)'\272', (u_char)'\273', (u_char)'\274', (u_char)'\275', (u_char)'\276', (u_char)'\277', (u_char)'\300', (u_char)'\341', (u_char)'\342', (u_char)'\343', (u_char)'\344', (u_char)'\345', (u_char)'\346', (u_char)'\347', (u_char)'\350', (u_char)'\351', (u_char)'\352', (u_char)'\353', (u_char)'\354', (u_char)'\355', (u_char)'\356', (u_char)'\357', (u_char)'\360', (u_char)'\361', (u_char)'\362', (u_char)'\363', (u_char)'\364', (u_char)'\365', (u_char)'\366', (u_char)'\367', (u_char)'\370', (u_char)'\371', (u_char)'\372', (u_char)'\333', (u_char)'\334', (u_char)'\335', (u_char)'\336', (u_char)'\337', (u_char)'\340', (u_char)'\341', (u_char)'\342', (u_char)'\343', (u_char)'\344', (u_char)'\345', (u_char)'\346', (u_char)'\347', (u_char)'\350', (u_char)'\351', (u_char)'\352', (u_char)'\353', (u_char)'\354', (u_char)'\355', (u_char)'\356', (u_char)'\357', (u_char)'\360', (u_char)'\361', (u_char)'\362', (u_char)'\363', (u_char)'\364', (u_char)'\365', (u_char)'\366', (u_char)'\367', (u_char)'\370', (u_char)'\371', (u_char)'\372', (u_char)'\373', (u_char)'\374', (u_char)'\375', (u_char)'\376', (u_char)'\377', }; int pcap_strcasecmp(const char *s1, const char *s2) { register const u_char *cm = charmap, *us1 = (const u_char *)s1, *us2 = (const u_char *)s2; while (cm[*us1] == cm[*us2++]) if (*us1++ == '\0') return(0); return (cm[*us1] - cm[*--us2]); } struct dlt_choice { const char *name; const char *description; int dlt; }; #define DLT_CHOICE(code, description) { #code, description, code } #define DLT_CHOICE_SENTINEL { NULL, NULL, 0 } static struct dlt_choice dlt_choices[] = { DLT_CHOICE(DLT_NULL, "BSD loopback"), DLT_CHOICE(DLT_EN10MB, "Ethernet"), DLT_CHOICE(DLT_IEEE802, "Token ring"), DLT_CHOICE(DLT_ARCNET, "BSD ARCNET"), DLT_CHOICE(DLT_SLIP, "SLIP"), DLT_CHOICE(DLT_PPP, "PPP"), DLT_CHOICE(DLT_FDDI, "FDDI"), DLT_CHOICE(DLT_ATM_RFC1483, "RFC 1483 LLC-encapsulated ATM"), DLT_CHOICE(DLT_RAW, "Raw IP"), DLT_CHOICE(DLT_SLIP_BSDOS, "BSD/OS SLIP"), DLT_CHOICE(DLT_PPP_BSDOS, "BSD/OS PPP"), DLT_CHOICE(DLT_ATM_CLIP, "Linux Classical IP-over-ATM"), DLT_CHOICE(DLT_PPP_SERIAL, "PPP over serial"), DLT_CHOICE(DLT_PPP_ETHER, "PPPoE"), DLT_CHOICE(DLT_SYMANTEC_FIREWALL, "Symantec Firewall"), DLT_CHOICE(DLT_C_HDLC, "Cisco HDLC"), DLT_CHOICE(DLT_IEEE802_11, "802.11"), DLT_CHOICE(DLT_FRELAY, "Frame Relay"), DLT_CHOICE(DLT_LOOP, "OpenBSD loopback"), DLT_CHOICE(DLT_ENC, "OpenBSD encapsulated IP"), DLT_CHOICE(DLT_LINUX_SLL, "Linux cooked"), DLT_CHOICE(DLT_LTALK, "Localtalk"), DLT_CHOICE(DLT_PFLOG, "OpenBSD pflog file"), DLT_CHOICE(DLT_PFSYNC, "Packet filter state syncing"), DLT_CHOICE(DLT_PRISM_HEADER, "802.11 plus Prism header"), DLT_CHOICE(DLT_IP_OVER_FC, "RFC 2625 IP-over-Fibre Channel"), DLT_CHOICE(DLT_SUNATM, "Sun raw ATM"), DLT_CHOICE(DLT_IEEE802_11_RADIO, "802.11 plus radiotap header"), DLT_CHOICE(DLT_ARCNET_LINUX, "Linux ARCNET"), DLT_CHOICE(DLT_JUNIPER_MLPPP, "Juniper Multi-Link PPP"), DLT_CHOICE(DLT_JUNIPER_MLFR, "Juniper Multi-Link Frame Relay"), DLT_CHOICE(DLT_JUNIPER_ES, "Juniper Encryption Services PIC"), DLT_CHOICE(DLT_JUNIPER_GGSN, "Juniper GGSN PIC"), DLT_CHOICE(DLT_JUNIPER_MFR, "Juniper FRF.16 Frame Relay"), DLT_CHOICE(DLT_JUNIPER_ATM2, "Juniper ATM2 PIC"), DLT_CHOICE(DLT_JUNIPER_SERVICES, "Juniper Advanced Services PIC"), DLT_CHOICE(DLT_JUNIPER_ATM1, "Juniper ATM1 PIC"), DLT_CHOICE(DLT_APPLE_IP_OVER_IEEE1394, "Apple IP-over-IEEE 1394"), DLT_CHOICE(DLT_MTP2_WITH_PHDR, "SS7 MTP2 with Pseudo-header"), DLT_CHOICE(DLT_MTP2, "SS7 MTP2"), DLT_CHOICE(DLT_MTP3, "SS7 MTP3"), DLT_CHOICE(DLT_SCCP, "SS7 SCCP"), DLT_CHOICE(DLT_DOCSIS, "DOCSIS"), DLT_CHOICE(DLT_LINUX_IRDA, "Linux IrDA"), DLT_CHOICE(DLT_IEEE802_11_RADIO_AVS, "802.11 plus AVS radio information header"), DLT_CHOICE(DLT_JUNIPER_MONITOR, "Juniper Passive Monitor PIC"), DLT_CHOICE(DLT_PPP_PPPD, "PPP for pppd, with direction flag"), DLT_CHOICE(DLT_JUNIPER_PPPOE, "Juniper PPPoE"), DLT_CHOICE(DLT_JUNIPER_PPPOE_ATM, "Juniper PPPoE/ATM"), DLT_CHOICE(DLT_GPRS_LLC, "GPRS LLC"), DLT_CHOICE(DLT_GPF_T, "GPF-T"), DLT_CHOICE(DLT_GPF_F, "GPF-F"), DLT_CHOICE(DLT_JUNIPER_PIC_PEER, "Juniper PIC Peer"), DLT_CHOICE(DLT_ERF_ETH, "Ethernet with Endace ERF header"), DLT_CHOICE(DLT_ERF_POS, "Packet-over-SONET with Endace ERF header"), DLT_CHOICE(DLT_LINUX_LAPD, "Linux vISDN LAPD"), DLT_CHOICE(DLT_JUNIPER_ETHER, "Juniper Ethernet"), DLT_CHOICE(DLT_JUNIPER_PPP, "Juniper PPP"), DLT_CHOICE(DLT_JUNIPER_FRELAY, "Juniper Frame Relay"), DLT_CHOICE(DLT_JUNIPER_CHDLC, "Juniper C-HDLC"), DLT_CHOICE(DLT_MFR, "FRF.16 Frame Relay"), DLT_CHOICE(DLT_JUNIPER_VP, "Juniper Voice PIC"), DLT_CHOICE(DLT_A429, "Arinc 429"), DLT_CHOICE(DLT_A653_ICM, "Arinc 653 Interpartition Communication"), DLT_CHOICE(DLT_USB, "USB"), DLT_CHOICE(DLT_BLUETOOTH_HCI_H4, "Bluetooth HCI UART transport layer"), DLT_CHOICE(DLT_IEEE802_16_MAC_CPS, "IEEE 802.16 MAC Common Part Sublayer"), DLT_CHOICE(DLT_USB_LINUX, "USB with Linux header"), DLT_CHOICE(DLT_CAN20B, "Controller Area Network (CAN) v. 2.0B"), DLT_CHOICE(DLT_IEEE802_15_4_LINUX, "IEEE 802.15.4 with Linux padding"), DLT_CHOICE(DLT_PPI, "Per-Packet Information"), DLT_CHOICE(DLT_IEEE802_16_MAC_CPS_RADIO, "IEEE 802.16 MAC Common Part Sublayer plus radiotap header"), DLT_CHOICE(DLT_JUNIPER_ISM, "Juniper Integrated Service Module"), DLT_CHOICE(DLT_IEEE802_15_4, "IEEE 802.15.4 with FCS"), DLT_CHOICE(DLT_SITA, "SITA pseudo-header"), DLT_CHOICE(DLT_ERF, "Endace ERF header"), DLT_CHOICE(DLT_RAIF1, "Ethernet with u10 Networks pseudo-header"), DLT_CHOICE(DLT_IPMB, "IPMB"), DLT_CHOICE(DLT_JUNIPER_ST, "Juniper Secure Tunnel"), DLT_CHOICE(DLT_BLUETOOTH_HCI_H4_WITH_PHDR, "Bluetooth HCI UART transport layer plus pseudo-header"), DLT_CHOICE(DLT_AX25_KISS, "AX.25 with KISS header"), DLT_CHOICE(DLT_IEEE802_15_4_NONASK_PHY, "IEEE 802.15.4 with non-ASK PHY data"), DLT_CHOICE(DLT_MPLS, "MPLS with label as link-layer header"), DLT_CHOICE(DLT_USB_LINUX_MMAPPED, "USB with padded Linux header"), DLT_CHOICE(DLT_DECT, "DECT"), DLT_CHOICE(DLT_AOS, "AOS Space Data Link protocol"), DLT_CHOICE(DLT_WIHART, "Wireless HART"), DLT_CHOICE(DLT_FC_2, "Fibre Channel FC-2"), DLT_CHOICE(DLT_FC_2_WITH_FRAME_DELIMS, "Fibre Channel FC-2 with frame delimiters"), DLT_CHOICE(DLT_IPNET, "Solaris ipnet"), DLT_CHOICE(DLT_CAN_SOCKETCAN, "CAN-bus with SocketCAN headers"), DLT_CHOICE(DLT_IPV4, "Raw IPv4"), DLT_CHOICE(DLT_IPV6, "Raw IPv6"), DLT_CHOICE(DLT_IEEE802_15_4_NOFCS, "IEEE 802.15.4 without FCS"), DLT_CHOICE(DLT_JUNIPER_VS, "Juniper Virtual Server"), DLT_CHOICE(DLT_JUNIPER_SRX_E2E, "Juniper SRX E2E"), DLT_CHOICE(DLT_JUNIPER_FIBRECHANNEL, "Juniper Fibre Channel"), DLT_CHOICE(DLT_DVB_CI, "DVB-CI"), DLT_CHOICE(DLT_JUNIPER_ATM_CEMIC, "Juniper ATM CEMIC"), DLT_CHOICE(DLT_NFLOG, "Linux netfilter log messages"), DLT_CHOICE(DLT_NETANALYZER, "Ethernet with Hilscher netANALYZER pseudo-header"), DLT_CHOICE(DLT_NETANALYZER_TRANSPARENT, "Ethernet with Hilscher netANALYZER pseudo-header and with preamble and SFD"), DLT_CHOICE(DLT_IPOIB, "RFC 4391 IP-over-Infiniband"), DLT_CHOICE_SENTINEL }; int pcap_datalink_name_to_val(const char *name) { int i; for (i = 0; dlt_choices[i].name != NULL; i++) { if (pcap_strcasecmp(dlt_choices[i].name + sizeof("DLT_") - 1, name) == 0) return (dlt_choices[i].dlt); } return (-1); } const char * pcap_datalink_val_to_name(int dlt) { int i; for (i = 0; dlt_choices[i].name != NULL; i++) { if (dlt_choices[i].dlt == dlt) return (dlt_choices[i].name + sizeof("DLT_") - 1); } return (NULL); } const char * pcap_datalink_val_to_description(int dlt) { int i; for (i = 0; dlt_choices[i].name != NULL; i++) { if (dlt_choices[i].dlt == dlt) return (dlt_choices[i].description); } return (NULL); } struct tstamp_type_choice { const char *name; const char *description; int type; }; static struct tstamp_type_choice tstamp_type_choices[] = { { "host", "Host", PCAP_TSTAMP_HOST }, { "host_lowprec", "Host, low precision", PCAP_TSTAMP_HOST_LOWPREC }, { "host_hiprec", "Host, high precision", PCAP_TSTAMP_HOST_HIPREC }, { "adapter", "Adapter", PCAP_TSTAMP_ADAPTER }, { "adapter_unsynced", "Adapter, not synced with system time", PCAP_TSTAMP_ADAPTER_UNSYNCED }, { NULL, NULL, 0 } }; int pcap_tstamp_type_name_to_val(const char *name) { int i; for (i = 0; tstamp_type_choices[i].name != NULL; i++) { if (pcap_strcasecmp(tstamp_type_choices[i].name, name) == 0) return (tstamp_type_choices[i].type); } return (PCAP_ERROR); } const char * pcap_tstamp_type_val_to_name(int tstamp_type) { int i; for (i = 0; tstamp_type_choices[i].name != NULL; i++) { if (tstamp_type_choices[i].type == tstamp_type) return (tstamp_type_choices[i].name); } return (NULL); } const char * pcap_tstamp_type_val_to_description(int tstamp_type) { int i; for (i = 0; tstamp_type_choices[i].name != NULL; i++) { if (tstamp_type_choices[i].type == tstamp_type) return (tstamp_type_choices[i].description); } return (NULL); } int pcap_snapshot(pcap_t *p) { return (p->snapshot); } int pcap_is_swapped(pcap_t *p) { return (p->sf.swapped); } int pcap_major_version(pcap_t *p) { return (p->sf.version_major); } int pcap_minor_version(pcap_t *p) { return (p->sf.version_minor); } FILE * pcap_file(pcap_t *p) { return (p->sf.rfile); } int pcap_fileno(pcap_t *p) { #ifndef WIN32 return (p->fd); #else if (p->adapter != NULL) return ((int)(DWORD)p->adapter->hFile); else return (-1); #endif } #if !defined(WIN32) && !defined(MSDOS) int pcap_get_selectable_fd(pcap_t *p) { return (p->selectable_fd); } #endif void pcap_perror(pcap_t *p, char *prefix) { fprintf(stderr, "%s: %s\n", prefix, p->errbuf); } char * pcap_geterr(pcap_t *p) { return (p->errbuf); } int pcap_getnonblock(pcap_t *p, char *errbuf) { - return (p->getnonblock_op(p, errbuf)); + int ret; + + ret = p->getnonblock_op(p, errbuf); + if (ret == -1) { + /* + * In case somebody depended on the bug wherein + * the error message was put into p->errbuf + * by pcap_getnonblock_fd(). + */ + strlcpy(p->errbuf, errbuf, PCAP_ERRBUF_SIZE); + } + return (ret); } /* * Get the current non-blocking mode setting, under the assumption that * it's just the standard POSIX non-blocking flag. * * We don't look at "p->nonblock", in case somebody tweaked the FD * directly. */ #if !defined(WIN32) && !defined(MSDOS) int pcap_getnonblock_fd(pcap_t *p, char *errbuf) { int fdflags; fdflags = fcntl(p->fd, F_GETFL, 0); if (fdflags == -1) { - snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s", + snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s", pcap_strerror(errno)); return (-1); } if (fdflags & O_NONBLOCK) return (1); else return (0); } #endif int pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf) { - return (p->setnonblock_op(p, nonblock, errbuf)); + int ret; + + ret = p->setnonblock_op(p, nonblock, errbuf); + if (ret == -1) { + /* + * In case somebody depended on the bug wherein + * the error message was put into p->errbuf + * by pcap_setnonblock_fd(). + */ + strlcpy(p->errbuf, errbuf, PCAP_ERRBUF_SIZE); + } + return (ret); } #if !defined(WIN32) && !defined(MSDOS) /* * Set non-blocking mode, under the assumption that it's just the * standard POSIX non-blocking flag. (This can be called by the * per-platform non-blocking-mode routine if that routine also * needs to do some additional work.) */ int pcap_setnonblock_fd(pcap_t *p, int nonblock, char *errbuf) { int fdflags; fdflags = fcntl(p->fd, F_GETFL, 0); if (fdflags == -1) { - snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s", + snprintf(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", + snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_SETFL: %s", pcap_strerror(errno)); return (-1); } return (0); } #endif #ifdef WIN32 /* * Generate a string for the last Win32-specific error (i.e. an error generated when * calling a Win32 API). * For errors occurred during standard C calls, we still use pcap_strerror() */ char * pcap_win32strerror(void) { DWORD error; static char errbuf[PCAP_ERRBUF_SIZE+1]; int errlen; char *p; error = GetLastError(); FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf, PCAP_ERRBUF_SIZE, NULL); /* * "FormatMessage()" "helpfully" sticks CR/LF at the end of the * message. Get rid of it. */ errlen = strlen(errbuf); if (errlen >= 2) { errbuf[errlen - 1] = '\0'; errbuf[errlen - 2] = '\0'; } p = strchr(errbuf, '\0'); snprintf (p, sizeof(errbuf)-(p-errbuf), " (%lu)", error); return (errbuf); } #endif /* * Generate error strings for PCAP_ERROR_ and PCAP_WARNING_ values. */ const char * pcap_statustostr(int errnum) { static char ebuf[15+10+1]; switch (errnum) { case PCAP_WARNING: return("Generic warning"); case PCAP_WARNING_TSTAMP_TYPE_NOTSUP: return ("That type of time stamp is not supported by that device"); case PCAP_WARNING_PROMISC_NOTSUP: return ("That device doesn't support promiscuous mode"); case PCAP_ERROR: return("Generic error"); case PCAP_ERROR_BREAK: return("Loop terminated by pcap_breakloop"); case PCAP_ERROR_NOT_ACTIVATED: return("The pcap_t has not been activated"); case PCAP_ERROR_ACTIVATED: return ("The setting can't be changed after the pcap_t is activated"); case PCAP_ERROR_NO_SUCH_DEVICE: return ("No such device exists"); case PCAP_ERROR_RFMON_NOTSUP: return ("That device doesn't support monitor mode"); case PCAP_ERROR_NOT_RFMON: return ("That operation is supported only in monitor mode"); case PCAP_ERROR_PERM_DENIED: return ("You don't have permission to capture on that device"); case PCAP_ERROR_IFACE_NOT_UP: return ("That device is not up"); case PCAP_ERROR_CANTSET_TSTAMP_TYPE: return ("That device doesn't support setting the time stamp type"); case PCAP_ERROR_PROMISC_PERM_DENIED: return ("You don't have permission to capture in promiscuous mode on that device"); } (void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum); return(ebuf); } /* * Not all systems have strerror(). */ const char * pcap_strerror(int errnum) { #ifdef HAVE_STRERROR return (strerror(errnum)); #else extern int sys_nerr; extern const char *const sys_errlist[]; static char ebuf[15+10+1]; if ((unsigned int)errnum < sys_nerr) return ((char *)sys_errlist[errnum]); (void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum); return(ebuf); #endif } int pcap_setfilter(pcap_t *p, struct bpf_program *fp) { return (p->setfilter_op(p, fp)); } /* * Set direction flag, which controls whether we accept only incoming * packets, only outgoing packets, or both. * Note that, depending on the platform, some or all direction arguments * might not be supported. */ int pcap_setdirection(pcap_t *p, pcap_direction_t d) { if (p->setdirection_op == NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Setting direction is not implemented on this platform"); return (-1); } else return (p->setdirection_op(p, d)); } int pcap_stats(pcap_t *p, struct pcap_stat *ps) { return (p->stats_op(p, ps)); } static int pcap_stats_dead(pcap_t *p, struct pcap_stat *ps _U_) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Statistics aren't available from a pcap_open_dead pcap_t"); return (-1); } #ifdef WIN32 int pcap_setbuff(pcap_t *p, int dim) { return (p->setbuff_op(p, dim)); } static int pcap_setbuff_dead(pcap_t *p, int dim) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "The kernel buffer size cannot be set on a pcap_open_dead pcap_t"); return (-1); } int pcap_setmode(pcap_t *p, int mode) { return (p->setmode_op(p, mode)); } static int pcap_setmode_dead(pcap_t *p, int mode) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "impossible to set mode on a pcap_open_dead pcap_t"); return (-1); } int pcap_setmintocopy(pcap_t *p, int size) { return (p->setmintocopy_op(p, size)); } static int pcap_setmintocopy_dead(pcap_t *p, int size) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "The mintocopy parameter cannot be set on a pcap_open_dead pcap_t"); return (-1); } #endif /* * On some platforms, we need to clean up promiscuous or monitor mode * when we close a device - and we want that to happen even if the * application just exits without explicitl closing devices. * On those platforms, we need to register a "close all the pcaps" * routine to be called when we exit, and need to maintain a list of * pcaps that need to be closed to clean up modes. * * XXX - not thread-safe. */ /* * List of pcaps on which we've done something that needs to be * cleaned up. * If there are any such pcaps, we arrange to call "pcap_close_all()" * when we exit, and have it close all of them. */ static struct pcap *pcaps_to_close; /* * TRUE if we've already called "atexit()" to cause "pcap_close_all()" to * be called on exit. */ static int did_atexit; static void pcap_close_all(void) { struct pcap *handle; while ((handle = pcaps_to_close) != NULL) pcap_close(handle); } int pcap_do_addexit(pcap_t *p) { /* * If we haven't already done so, arrange to have * "pcap_close_all()" called when we exit. */ if (!did_atexit) { if (atexit(pcap_close_all) == -1) { /* * "atexit()" failed; let our caller know. */ strncpy(p->errbuf, "atexit failed", PCAP_ERRBUF_SIZE); return (0); } did_atexit = 1; } return (1); } void pcap_add_to_pcaps_to_close(pcap_t *p) { p->md.next = pcaps_to_close; pcaps_to_close = p; } void pcap_remove_from_pcaps_to_close(pcap_t *p) { pcap_t *pc, *prevpc; for (pc = pcaps_to_close, prevpc = NULL; pc != NULL; prevpc = pc, pc = pc->md.next) { if (pc == p) { /* * Found it. Remove it from the list. */ if (prevpc == NULL) { /* * It was at the head of the list. */ pcaps_to_close = pc->md.next; } else { /* * It was in the middle of the list. */ prevpc->md.next = pc->md.next; } break; } } } void pcap_cleanup_live_common(pcap_t *p) { if (p->buffer != NULL) { free(p->buffer); p->buffer = NULL; } if (p->dlt_list != NULL) { free(p->dlt_list); p->dlt_list = NULL; p->dlt_count = 0; } if (p->tstamp_type_list != NULL) { free(p->tstamp_type_list); p->tstamp_type_list = NULL; p->tstamp_type_count = 0; } pcap_freecode(&p->fcode); #if !defined(WIN32) && !defined(MSDOS) if (p->fd >= 0) { close(p->fd); p->fd = -1; } p->selectable_fd = -1; p->send_fd = -1; #endif } static void pcap_cleanup_dead(pcap_t *p _U_) { /* Nothing to do. */ } pcap_t * pcap_open_dead(int linktype, int snaplen) { pcap_t *p; p = malloc(sizeof(*p)); if (p == NULL) return NULL; memset (p, 0, sizeof(*p)); p->snapshot = snaplen; p->linktype = linktype; p->stats_op = pcap_stats_dead; #ifdef WIN32 p->setbuff_op = pcap_setbuff_dead; p->setmode_op = pcap_setmode_dead; p->setmintocopy_op = pcap_setmintocopy_dead; #endif p->cleanup_op = pcap_cleanup_dead; p->activated = 1; return (p); } /* * API compatible with WinPcap's "send a packet" routine - returns -1 * on error, 0 otherwise. * * XXX - what if we get a short write? */ int pcap_sendpacket(pcap_t *p, const u_char *buf, int size) { if (p->inject_op(p, buf, size) == -1) return (-1); return (0); } /* * API compatible with OpenBSD's "send a packet" routine - returns -1 on * error, number of bytes written otherwise. */ int pcap_inject(pcap_t *p, const void *buf, size_t size) { return (p->inject_op(p, buf, size)); } void pcap_close(pcap_t *p) { if (p->opt.source != NULL) free(p->opt.source); p->cleanup_op(p); free(p); } /* * Given a BPF program, a pcap_pkthdr structure for a packet, and the raw * data for the packet, check whether the packet passes the filter. * Returns the return value of the filter program, which will be zero if * the packet doesn't pass and non-zero if the packet does pass. */ int -pcap_offline_filter(struct bpf_program *fp, const struct pcap_pkthdr *h, +pcap_offline_filter(const struct bpf_program *fp, const struct pcap_pkthdr *h, const u_char *pkt) { - struct bpf_insn *fcode = fp->bf_insns; + const struct bpf_insn *fcode = fp->bf_insns; if (fcode != NULL) return (bpf_filter(fcode, pkt, h->len, h->caplen)); else return (0); } /* * We make the version string static, and return a pointer to it, rather * than exporting the version string directly. On at least some UNIXes, * if you import data from a shared library into an program, the data is * bound into the program binary, so if the string in the version of the * library with which the program was linked isn't the same as the * string in the version of the library with which the program is being * run, various undesirable things may happen (warnings, the string * being the one from the version of the library with which the program * was linked, or even weirder things, such as the string being the one * from the library but being truncated). */ #ifdef HAVE_VERSION_H #include "version.h" #else static const char pcap_version_string[] = "libpcap version 1.x.y"; #endif #ifdef WIN32 /* * XXX - it'd be nice if we could somehow generate the WinPcap and libpcap * version numbers when building WinPcap. (It'd be nice to do so for * the packet.dll version number as well.) */ static const char wpcap_version_string[] = "4.0"; static const char pcap_version_string_fmt[] = "WinPcap version %s, based on %s"; static const char pcap_version_string_packet_dll_fmt[] = "WinPcap version %s (packet.dll version %s), based on %s"; static char *full_pcap_version_string; const char * pcap_lib_version(void) { char *packet_version_string; size_t full_pcap_version_string_len; if (full_pcap_version_string == NULL) { /* * Generate the version string. */ packet_version_string = PacketGetVersion(); if (strcmp(wpcap_version_string, packet_version_string) == 0) { /* * WinPcap version string and packet.dll version * string are the same; just report the WinPcap * version. */ full_pcap_version_string_len = (sizeof pcap_version_string_fmt - 4) + strlen(wpcap_version_string) + strlen(pcap_version_string); full_pcap_version_string = malloc(full_pcap_version_string_len); sprintf(full_pcap_version_string, pcap_version_string_fmt, wpcap_version_string, pcap_version_string); } else { /* * WinPcap version string and packet.dll version * string are different; that shouldn't be the * case (the two libraries should come from the * same version of WinPcap), so we report both * versions. */ full_pcap_version_string_len = (sizeof pcap_version_string_packet_dll_fmt - 6) + strlen(wpcap_version_string) + strlen(packet_version_string) + strlen(pcap_version_string); full_pcap_version_string = malloc(full_pcap_version_string_len); sprintf(full_pcap_version_string, pcap_version_string_packet_dll_fmt, wpcap_version_string, packet_version_string, pcap_version_string); } } return (full_pcap_version_string); } #elif defined(MSDOS) static char *full_pcap_version_string; const char * pcap_lib_version (void) { char *packet_version_string; size_t full_pcap_version_string_len; static char dospfx[] = "DOS-"; if (full_pcap_version_string == NULL) { /* * Generate the version string. */ full_pcap_version_string_len = sizeof dospfx + strlen(pcap_version_string); full_pcap_version_string = malloc(full_pcap_version_string_len); strcpy(full_pcap_version_string, dospfx); strcat(full_pcap_version_string, pcap_version_string); } return (full_pcap_version_string); } #else /* UN*X */ const char * pcap_lib_version(void) { return (pcap_version_string); } #endif Index: stable/9/contrib/libpcap/pcap_breakloop.3pcap =================================================================== --- stable/9/contrib/libpcap/pcap_breakloop.3pcap (revision 252280) +++ stable/9/contrib/libpcap/pcap_breakloop.3pcap (revision 252281) @@ -1,105 +1,100 @@ .\" @(#) $Header: /tcpdump/master/libpcap/pcap_breakloop.3pcap,v 1.3 2008-04-06 02:53:21 guy Exp $ .\" .\" Copyright (c) 1994, 1996, 1997 .\" The Regents of the University of California. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that: (1) source code distributions .\" retain the above copyright notice and this paragraph in its entirety, (2) .\" distributions including binary code include the above copyright notice and .\" this paragraph in its entirety in the documentation or other materials .\" provided with the distribution, and (3) all advertising materials mentioning .\" features or use of this software display the following acknowledgement: .\" ``This product includes software developed by the University of California, .\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of .\" the University nor the names of its contributors may be used to endorse .\" or promote products derived from this software without specific prior .\" written permission. .\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. .\" .TH PCAP_BREAKLOOP 3PCAP "5 April 2008" .SH NAME pcap_breakloop \- force a pcap_dispatch() or pcap_loop() call to return .SH SYNOPSIS .nf .ft B #include .ft .LP .ft B void pcap_breakloop(pcap_t *); .ft .fi .SH DESCRIPTION .B pcap_breakloop() sets a flag that will force .B pcap_dispatch() or .B pcap_loop() to return rather than looping; they will return the number of packets that have been processed so far, or \-2 if no packets have been processed so far. .PP This routine is safe to use inside a signal handler on UNIX or a console control handler on Windows, as it merely sets a flag that is checked within the loop. .PP The flag is checked in loops reading packets from the OS - a signal by itself will not necessarily terminate those loops - as well as in loops processing a set of packets returned by the OS. .ft B Note that if you are catching signals on UNIX systems that support restarting system calls after a signal, and calling pcap_breakloop() in the signal handler, you must specify, when catching those signals, that system calls should NOT be restarted by that signal. Otherwise, if the signal interrupted a call reading packets in a live capture, when your signal handler returns after calling pcap_breakloop(), the call will be restarted, and the loop will not terminate until more packets arrive and the call completes. +.ft R .PP +.ft B Note also that, in a multi-threaded application, if one thread is -blocked in -.BR pcap_dispatch() , -.BR pcap_loop() , -.BR pcap_next() , -or -.BR pcap_next_ex() , -a call to -.B pcap_breakloop() -in a different thread will not unblock that thread; you will need to use -whatever mechanism the OS provides for breaking a thread out of blocking -calls in order to unblock the thread, such as thread cancellation in -systems that support POSIX threads. +blocked in pcap_dispatch(), pcap_loop(), pcap_next(), or pcap_next_ex(), +a call to pcap_breakloop() in a different thread will not unblock that +thread; you will need to use whatever mechanism the OS provides for +breaking a thread out of blocking calls in order to unblock the thread, +such as thread cancellation in systems that support POSIX threads. .ft R .PP Note that .B pcap_next() and .B pcap_next_ex() will, on some platforms, loop reading packets from the OS; that loop will not necessarily be terminated by a signal, so .B pcap_breakloop() should be used to terminate packet processing even if .B pcap_next() or .B pcap_next_ex() is being used. .PP .B pcap_breakloop() does not guarantee that no further packets will be processed by .B pcap_dispatch() or .B pcap_loop() after it is called; at most one more packet might be processed. .PP If \-2 is returned from .B pcap_dispatch() or .BR pcap_loop() , the flag is cleared, so a subsequent call will resume reading packets. If a positive number is returned, the flag is not cleared, so a subsequent call will return \-2 and clear the flag. .SH SEE ALSO pcap(3PCAP), pcap_loop(3PCAP), pcap_next_ex(3PCAP) Index: stable/9/contrib/libpcap/pcap_loop.3pcap =================================================================== --- stable/9/contrib/libpcap/pcap_loop.3pcap (revision 252280) +++ stable/9/contrib/libpcap/pcap_loop.3pcap (revision 252281) @@ -1,157 +1,158 @@ .\" @(#) $Header: /tcpdump/master/libpcap/pcap_loop.3pcap,v 1.4 2008-12-25 02:01:32 guy Exp $ .\" .\" Copyright (c) 1994, 1996, 1997 .\" The Regents of the University of California. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that: (1) source code distributions .\" retain the above copyright notice and this paragraph in its entirety, (2) .\" distributions including binary code include the above copyright notice and .\" this paragraph in its entirety in the documentation or other materials .\" provided with the distribution, and (3) all advertising materials mentioning .\" features or use of this software display the following acknowledgement: .\" ``This product includes software developed by the University of California, .\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of .\" the University nor the names of its contributors may be used to endorse .\" or promote products derived from this software without specific prior .\" written permission. .\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. .\" .TH PCAP_LOOP 3PCAP "24 December 2008" .SH NAME pcap_loop, pcap_dispatch \- process packets from a live capture or savefile .SH SYNOPSIS .nf .ft B #include .ft .LP .ft B typedef void (*pcap_handler)(u_char *user, const struct pcap_pkthdr *h, .ti +8 const u_char *bytes); .ft .LP .ft B int pcap_loop(pcap_t *p, int cnt, .ti +8 pcap_handler callback, u_char *user); int pcap_dispatch(pcap_t *p, int cnt, .ti +8 pcap_handler callback, u_char *user); .ft .fi .SH DESCRIPTION .B pcap_loop() processes packets from a live capture or ``savefile'' until .I cnt packets are processed, the end of the ``savefile'' is reached when reading from a ``savefile'', .B pcap_breakloop() is called, or an error occurs. It does .B not return when live read timeouts occur. A value of \-1 or 0 for .I cnt is equivalent to infinity, so that packets are processed until another ending condition occurs. .PP .B pcap_dispatch() processes packets from a live capture or ``savefile'' until .I cnt packets are processed, the end of the current bufferful of packets is reached when doing a live capture, the end of the ``savefile'' is reached when reading from a ``savefile'', .B pcap_breakloop() is called, or an error occurs. Thus, when doing a live capture, .I cnt is the maximum number of packets to process before returning, but is not a minimum number; when reading a live capture, only one bufferful of packets is read at a time, so fewer than .I cnt packets may be processed. A value of \-1 or 0 for .I cnt causes all the packets received in one buffer to be processed when reading a live capture, and causes all the packets in the file to be processed when reading a ``savefile''. .PP .ft B (In older versions of libpcap, the behavior when \fIcnt\fP was 0 was undefined; different platforms and devices behaved differently, so code that must work with older versions of libpcap -should use \-1, nor 0, as the value of +should use \-1, not 0, as the value of \fIcnt\fP.) .ft R .PP .I callback specifies a .I pcap_handler routine to be called with three arguments: a .I u_char pointer which is passed in the .I user argument to .B pcap_loop() or .BR pcap_dispatch() , a .I const struct pcap_pkthdr pointer pointing to the packet time stamp and lengths, and a .I const u_char pointer to the first .B caplen (as given in the .I struct pcap_pkthdr a pointer to which is passed to the callback routine) bytes of data from the packet. The .I struct pcap_pkthdr and the packet data are not to be freed by the callback routine, and are not guaranteed to be valid after the callback routine returns; if the code needs them to be valid after the callback, it must make a copy of them. .SH RETURN VALUE .B pcap_loop() returns 0 if .I cnt -is exhausted, \-1 if an error occurs, or \-2 if the loop terminated due -to a call to +is exhausted or if, when reading from a ``savefile'', no more packets +are available. It returns \-1 if an error occurs or \-2 if the loop +terminated due to a call to .B pcap_breakloop() before any packets were processed. It does .B not return when live read timeouts occur; instead, it attempts to read more packets. .PP .B pcap_dispatch() returns the number of packets processed on success; this can be 0 if no packets were read from a live capture (if, for example, they were discarded because they didn't pass the packet filter, or if, on platforms that support a read timeout that starts before any packets arrive, the timeout expires before any packets arrive, or if the file descriptor for the capture device is in non-blocking mode and no packets were available to be read) or if no more packets are available in a ``savefile.'' It returns \-1 if an error occurs or \-2 if the loop terminated due to a call to .B pcap_breakloop() before any packets were processed. .ft B If your application uses pcap_breakloop(), make sure that you explicitly check for \-1 and \-2, rather than just checking for a return value < 0. .ft R .PP If \-1 is returned, .B pcap_geterr() or .B pcap_perror() may be called with .I p as an argument to fetch or display the error text. .SH SEE ALSO pcap(3PCAP), pcap_geterr(3PCAP), pcap_breakloop(3PCAP) Index: stable/9/contrib/libpcap/pcap_offline_filter.3pcap =================================================================== --- stable/9/contrib/libpcap/pcap_offline_filter.3pcap (revision 252280) +++ stable/9/contrib/libpcap/pcap_offline_filter.3pcap (revision 252281) @@ -1,57 +1,57 @@ .\" @(#) $Header: /tcpdump/master/libpcap/pcap_offline_filter.3pcap,v 1.1 2008-05-13 15:19:56 guy Exp $ .\" .\" Copyright (c) 1994, 1996, 1997 .\" The Regents of the University of California. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that: (1) source code distributions .\" retain the above copyright notice and this paragraph in its entirety, (2) .\" distributions including binary code include the above copyright notice and .\" this paragraph in its entirety in the documentation or other materials .\" provided with the distribution, and (3) all advertising materials mentioning .\" features or use of this software display the following acknowledgement: .\" ``This product includes software developed by the University of California, .\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of .\" the University nor the names of its contributors may be used to endorse .\" or promote products derived from this software without specific prior .\" written permission. .\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. .\" .TH PCAP_OFFLINE_FILTER 3PCAP "13 May 2008" .SH NAME pcap_offline_filter \- check whether a filter matches a packet .SH SYNOPSIS .nf .ft B #include .ft .LP .ft B -int pcap_offline_filter(struct bpf_program *fp, +int pcap_offline_filter(const struct bpf_program *fp, .ti +8 const struct pcap_pkthdr *h, const u_char *pkt) .ft .fi .SH DESCRIPTION .B pcap_offline_filter() checks whether a filter matches a packet. .I fp is a pointer to a .I bpf_program struct, usually the result of a call to .BR pcap_compile() . .I h points to the .I pcap_pkthdr structure for the packet, and .I pkt points to the data in the packet. .SH RETURN VALUE .B pcap_offline_filter() returns the return value of the filter program. This will be zero if the packet doesn't match the filter and non-zero if the packet matches the filter. .SH SEE ALSO pcap(3PCAP), pcap_compile(3PCAP) Index: stable/9/contrib/libpcap/scanner.l =================================================================== --- stable/9/contrib/libpcap/scanner.l (revision 252280) +++ stable/9/contrib/libpcap/scanner.l (revision 252281) @@ -1,467 +1,455 @@ %{ /* * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * $FreeBSD$ */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/scanner.l,v 1.112 2008-02-06 10:21:30 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef WIN32 #include #else /* WIN32 */ #if HAVE_INTTYPES_H #include #elif HAVE_STDINT_H #include #endif #ifdef HAVE_SYS_BITYPES_H #include #endif #include #endif /* WIN32 */ #include #include #include "pcap-int.h" #include "gencode.h" #ifdef INET6 #ifdef WIN32 #include #ifdef __MINGW32__ #include "ip6_misc.h" #endif #else /* WIN32 */ #include /* for "struct sockaddr" in "struct addrinfo" */ #include /* for "struct addrinfo" */ #endif /* WIN32 */ /* Workaround for AIX 4.3 */ #if !defined(AI_NUMERICHOST) #define AI_NUMERICHOST 0x04 #endif #endif /*INET6*/ #include #include "tokdefs.h" #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif static int stoi(char *); static inline int xdtoi(int); #ifdef FLEX_SCANNER #define YY_NO_INPUT #define YY_NO_UNPUT static YY_BUFFER_STATE in_buffer; #else static const char *in_buffer; #undef getc #define getc(fp) (*in_buffer == 0 ? EOF : *in_buffer++) #endif extern YYSTYPE yylval; %} N ([0-9]+|(0X|0x)[0-9A-Fa-f]+) B ([0-9A-Fa-f][0-9A-Fa-f]?) B2 ([0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f]) W ([0-9A-Fa-f][0-9A-Fa-f]?[0-9A-Fa-f]?[0-9A-Fa-f]?) %a 18400 %o 21500 %e 7600 %k 4550 %p 27600 %n 2000 V680 {W}:{W}:{W}:{W}:{W}:{W}:{W}:{W} V670 ::{W}:{W}:{W}:{W}:{W}:{W}:{W} V671 {W}::{W}:{W}:{W}:{W}:{W}:{W} V672 {W}:{W}::{W}:{W}:{W}:{W}:{W} V673 {W}:{W}:{W}::{W}:{W}:{W}:{W} V674 {W}:{W}:{W}:{W}::{W}:{W}:{W} V675 {W}:{W}:{W}:{W}:{W}::{W}:{W} V676 {W}:{W}:{W}:{W}:{W}:{W}::{W} V677 {W}:{W}:{W}:{W}:{W}:{W}:{W}:: V660 ::{W}:{W}:{W}:{W}:{W}:{W} V661 {W}::{W}:{W}:{W}:{W}:{W} V662 {W}:{W}::{W}:{W}:{W}:{W} V663 {W}:{W}:{W}::{W}:{W}:{W} V664 {W}:{W}:{W}:{W}::{W}:{W} V665 {W}:{W}:{W}:{W}:{W}::{W} V666 {W}:{W}:{W}:{W}:{W}:{W}:: V650 ::{W}:{W}:{W}:{W}:{W} V651 {W}::{W}:{W}:{W}:{W} V652 {W}:{W}::{W}:{W}:{W} V653 {W}:{W}:{W}::{W}:{W} V654 {W}:{W}:{W}:{W}::{W} V655 {W}:{W}:{W}:{W}:{W}:: V640 ::{W}:{W}:{W}:{W} V641 {W}::{W}:{W}:{W} V642 {W}:{W}::{W}:{W} V643 {W}:{W}:{W}::{W} V644 {W}:{W}:{W}:{W}:: V630 ::{W}:{W}:{W} V631 {W}::{W}:{W} V632 {W}:{W}::{W} V633 {W}:{W}:{W}:: V620 ::{W}:{W} V621 {W}::{W} V622 {W}:{W}:: V610 ::{W} V611 {W}:: V600 :: V6604 {W}:{W}:{W}:{W}:{W}:{W}:{N}\.{N}\.{N}\.{N} V6504 ::{W}:{W}:{W}:{W}:{W}:{N}\.{N}\.{N}\.{N} V6514 {W}::{W}:{W}:{W}:{W}:{N}\.{N}\.{N}\.{N} V6524 {W}:{W}::{W}:{W}:{W}:{N}\.{N}\.{N}\.{N} V6534 {W}:{W}:{W}::{W}:{W}:{N}\.{N}\.{N}\.{N} V6544 {W}:{W}:{W}:{W}::{W}:{N}\.{N}\.{N}\.{N} V6554 {W}:{W}:{W}:{W}:{W}::{N}\.{N}\.{N}\.{N} V6404 ::{W}:{W}:{W}:{W}:{N}\.{N}\.{N}\.{N} V6414 {W}::{W}:{W}:{W}:{N}\.{N}\.{N}\.{N} V6424 {W}:{W}::{W}:{W}:{N}\.{N}\.{N}\.{N} V6434 {W}:{W}:{W}::{W}:{N}\.{N}\.{N}\.{N} V6444 {W}:{W}:{W}:{W}::{N}\.{N}\.{N}\.{N} V6304 ::{W}:{W}:{W}:{N}\.{N}\.{N}\.{N} V6314 {W}::{W}:{W}:{N}\.{N}\.{N}\.{N} V6324 {W}:{W}::{W}:{N}\.{N}\.{N}\.{N} V6334 {W}:{W}:{W}::{N}\.{N}\.{N}\.{N} V6204 ::{W}:{W}:{N}\.{N}\.{N}\.{N} V6214 {W}::{W}:{N}\.{N}\.{N}\.{N} V6224 {W}:{W}::{N}\.{N}\.{N}\.{N} V6104 ::{W}:{N}\.{N}\.{N}\.{N} V6114 {W}::{N}\.{N}\.{N}\.{N} V6004 ::{N}\.{N}\.{N}\.{N} V6 ({V680}|{V670}|{V671}|{V672}|{V673}|{V674}|{V675}|{V676}|{V677}|{V660}|{V661}|{V662}|{V663}|{V664}|{V665}|{V666}|{V650}|{V651}|{V652}|{V653}|{V654}|{V655}|{V640}|{V641}|{V642}|{V643}|{V644}|{V630}|{V631}|{V632}|{V633}|{V620}|{V621}|{V622}|{V610}|{V611}|{V600}|{V6604}|{V6504}|{V6514}|{V6524}|{V6534}|{V6544}|{V6554}|{V6404}|{V6414}|{V6424}|{V6434}|{V6444}|{V6304}|{V6314}|{V6324}|{V6334}|{V6204}|{V6214}|{V6224}|{V6104}|{V6114}|{V6004}) MAC ({B}:{B}:{B}:{B}:{B}:{B}|{B}\-{B}\-{B}\-{B}\-{B}\-{B}|{B}\.{B}\.{B}\.{B}\.{B}\.{B}|{B2}\.{B2}\.{B2}|{B2}{3}) %% dst return DST; src return SRC; link|ether|ppp|slip return LINK; fddi|tr|wlan 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; carp return CARP; radio return RADIO; -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 - } +ip6 return IPV6; +icmp6 return ICMPV6; ah return AH; esp return ESP; atalk return ATALK; aarp return AARP; decnet return DECNET; lat return LAT; sca return SCA; moprc return MOPRC; mopdl return MOPDL; iso return ISO; esis return ESIS; es-is return ESIS; isis return ISIS; is-is return ISIS; l1 return L1; l2 return L2; iih return IIH; lsp return LSP; snp return SNP; csnp return CSNP; psnp return PSNP; clnp return CLNP; stp return STP; ipx return IPX; netbeui return NETBEUI; host return HOST; net return NET; mask return NETMASK; port return PORT; portrange return PORTRANGE; proto return PROTO; protochain { #ifdef NO_PROTOCHAIN bpf_error("%s not supported", yytext); #else return PROTOCHAIN; #endif } gateway return GATEWAY; type return TYPE; subtype return SUBTYPE; direction|dir return DIR; address1|addr1 return ADDR1; address2|addr2 return ADDR2; address3|addr3 return ADDR3; address4|addr4 return ADDR4; ra return RA; ta return TA; less return LESS; greater return GREATER; byte return CBYTE; broadcast return TK_BROADCAST; multicast return TK_MULTICAST; and|"&&" return AND; or|"||" return OR; not return '!'; len|length return LEN; inbound return INBOUND; outbound return OUTBOUND; vlan return VLAN; mpls return MPLS; pppoed return PPPOED; pppoes return PPPOES; lane return LANE; llc return LLC; metac return METAC; bcc return BCC; oam return OAM; oamf4 return OAMF4; oamf4ec return OAMF4EC; oamf4sc return OAMF4SC; sc return SC; ilmic return ILMIC; vpi return VPI; vci return VCI; connectmsg return CONNECTMSG; metaconnect return METACONNECT; on|ifname return PF_IFNAME; rset|ruleset return PF_RSET; rnr|rulenum return PF_RNR; srnr|subrulenum return PF_SRNR; reason return PF_REASON; action return PF_ACTION; fisu return FISU; lssu return LSSU; lsu return LSSU; msu return MSU; sio return SIO; opc return OPC; dpc return DPC; sls return SLS; [ \r\n\t] ; [+\-*/:\[\]!<>()&|=] return yytext[0]; ">=" return GEQ; "<=" return LEQ; "!=" return NEQ; "==" return '='; "<<" return LSH; ">>" return RSH; ${B} { yylval.e = pcap_ether_aton(((char *)yytext)+1); return AID; } {MAC} { yylval.e = pcap_ether_aton((char *)yytext); return EID; } {N} { yylval.i = stoi((char *)yytext); return NUM; } ({N}\.{N})|({N}\.{N}\.{N})|({N}\.{N}\.{N}\.{N}) { yylval.s = sdup((char *)yytext); return HID; } {V6} { #ifdef INET6 struct addrinfo hints, *res; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET6; hints.ai_flags = AI_NUMERICHOST; if (getaddrinfo(yytext, NULL, &hints, &res)) bpf_error("bogus IPv6 address %s", yytext); else { freeaddrinfo(res); yylval.s = sdup((char *)yytext); return HID6; } #else bpf_error("IPv6 address %s not supported", yytext); #endif /*INET6*/ } {B}:+({B}:+)+ { bpf_error("bogus ethernet address %s", yytext); } 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!<>()&|=]+ { bpf_error("illegal token: %s", yytext); } . { bpf_error("illegal char '%c'", *yytext); } %% void lex_init(buf) const char *buf; { #ifdef FLEX_SCANNER in_buffer = yy_scan_string(buf); #else in_buffer = buf; #endif } /* * Do any cleanup necessary after parsing. */ void lex_cleanup() { #ifdef FLEX_SCANNER if (in_buffer != NULL) yy_delete_buffer(in_buffer); in_buffer = NULL; #endif } /* * Also define a yywrap. Note that if we're using flex, it will * define a macro to map this identifier to pcap_wrap. */ int yywrap() { return 1; } /* Hex digit to integer. */ static inline int xdtoi(c) register int c; { if (isdigit(c)) return c - '0'; else if (islower(c)) return c - 'a' + 10; else return c - 'A' + 10; } /* * Convert string to integer. Just like atoi(), but checks for * preceding 0x or 0 and uses hex or octal instead of decimal. */ static int stoi(s) char *s; { int base = 10; int n = 0; if (*s == '0') { if (s[1] == 'x' || s[1] == 'X') { s += 2; base = 16; } else { base = 8; s += 1; } } while (*s) n = n * base + xdtoi(*s++); return n; } Index: stable/9/contrib/libpcap =================================================================== --- stable/9/contrib/libpcap (revision 252280) +++ stable/9/contrib/libpcap (revision 252281) Property changes on: stable/9/contrib/libpcap ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,2 ## Merged /vendor/libpcap/dist:r241201-251128 Merged /head/contrib/libpcap:r251129 Index: stable/9/lib/libpcap/config.h =================================================================== --- stable/9/lib/libpcap/config.h (revision 252280) +++ stable/9/lib/libpcap/config.h (revision 252281) @@ -1,320 +1,332 @@ /* $FreeBSD$ */ /* This is an edited copy of the config.h generated by configure. */ /* config.h. Generated from config.h.in by configure. */ /* config.h.in. Generated from configure.in by autoheader. */ /* Enable optimizer debugging */ /* #undef BDEBUG */ /* define if you have a cloning BPF device */ #define HAVE_CLONING_BPF 1 /* define if you have the DAG API */ /* #undef HAVE_DAG_API */ /* define if you have dag_get_erf_types() */ /* #undef HAVE_DAG_GET_ERF_TYPES */ /* define if you have dag_get_stream_erf_types() */ /* #undef HAVE_DAG_GET_STREAM_ERF_TYPES */ /* define if you have streams capable DAG API */ /* #undef HAVE_DAG_STREAMS_API */ /* define if you have vdag_set_device_info() */ /* #undef HAVE_DAG_VDAG */ /* Define to 1 if you have the declaration of `ether_hostton', and to 0 if you don't. */ #define HAVE_DECL_ETHER_HOSTTON 1 /* define if you have a /dev/dlpi */ /* #undef HAVE_DEV_DLPI */ /* if passive_req_t primitive exists */ /* #undef HAVE_DLPI_PASSIVE */ /* Define to 1 if you have the `ether_hostton' function. */ #define HAVE_ETHER_HOSTTON 1 /* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ #define HAVE_FSEEKO 1 /* on HP-UX 10.20 or later */ /* #undef HAVE_HPUX10_20_OR_LATER */ /* on HP-UX 9.x */ /* #undef HAVE_HPUX9 */ /* if ppa_info_t_dl_module_id exists */ /* #undef HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1 */ /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 /* if libdlpi exists */ /* #undef HAVE_LIBDLPI */ /* if libnl exists */ /* #undef HAVE_LIBNL */ /* if libnl exists and is version 2.x */ /* #undef HAVE_LIBNL_2_x */ +/* if libnl exists and is version 3.x */ +/* #undef HAVE_LIBNL_3_x */ + +/* libnl has NLE_FAILURE */ +/* #undef HAVE_LIBNL_NLE */ + +/* libnl has new-style socket api */ +/* #undef HAVE_LIBNL_SOCKETS */ + /* Define to 1 if you have the header file. */ #define HAVE_LIMITS_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_LINUX_COMPILER_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_LINUX_ETHTOOL_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_LINUX_IF_PACKET_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_LINUX_NET_TSTAMP_H */ /* if tp_vlan_tci exists */ /* #undef HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI */ /* Define to 1 if you have the header file. */ /* #undef HAVE_LINUX_TYPES_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_LINUX_USBDEVICE_FS_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_LINUX_WIRELESS_H */ /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_NETINET_ETHER_H */ /* Define to 1 if you have the header file. */ #define HAVE_NETINET_IF_ETHER_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_NETPACKET_IF_PACKET_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_NETPACKET_PACKET_H */ /* Define to 1 if you have the header file. */ #define HAVE_NET_IF_MEDIA_H 1 /* Define to 1 if you have the header file. */ /* See Makefile */ /* #undef HAVE_NET_PFVAR_H */ /* if there's an os_proto.h for this platform, to use additional prototypes */ /* #undef HAVE_OS_PROTO_H */ /* Define to 1 if you have the header file. */ #define HAVE_PATHS_H 1 /* define if net/pfvar.h defines PF_NAT through PF_NORDR */ #define HAVE_PF_NAT_THROUGH_PF_NORDR 1 /* define if you have a Septel API */ /* #undef HAVE_SEPTEL_API */ /* define if you have Myricom SNF API */ /* #undef HAVE_SNF_API */ /* Define to 1 if you have the `snprintf' function. */ #define HAVE_SNPRINTF 1 /* if struct sockaddr has the sa_len member */ #define HAVE_SOCKADDR_SA_LEN 1 /* if struct sockaddr_storage exists */ #define HAVE_SOCKADDR_STORAGE 1 /* define if socklen_t is defined */ #define HAVE_SOCKLEN_T 1 /* On solaris */ /* #undef HAVE_SOLARIS */ /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `strerror' function. */ #define HAVE_STRERROR 1 /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strlcpy' function. */ #define HAVE_STRLCPY 1 /* Define to 1 if the system has the type `struct BPF_TIMEVAL'. */ /* #undef HAVE_STRUCT_BPF_TIMEVAL */ /* Define to 1 if the system has the type `struct ether_addr'. */ /* #undef HAVE_STRUCT_ETHER_ADDR */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_BITYPES_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_BUFMOD_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_DLPI_EXT_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_IOCCOM_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_SOCKIO_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* if if_packet.h has tpacket_stats defined */ /* #undef HAVE_TPACKET_STATS */ /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* if struct usbdevfs_ctrltransfer has bRequestType */ /* #undef HAVE_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE */ /* define if version.h is generated in the build procedure */ #define HAVE_VERSION_H 1 /* Define to 1 if you have the `vsnprintf' function. */ #define HAVE_VSNPRINTF 1 /* define if the system supports zerocopy BPF */ #define HAVE_ZEROCOPY_BPF 1 /* define if your compiler has __attribute__ */ #define HAVE___ATTRIBUTE__ 1 /* IPv6 */ /* See Makefile */ /* #undef INET6 */ /* if unaligned access fails */ /* #undef LBL_ALIGN */ /* path for device for USB sniffing */ /* #undef LINUX_USB_MON_DEV */ +/* if we need a pcap_parse wrapper around yyparse */ +#define NEED_YYPARSE_WRAPPER + /* Define to 1 if netinet/ether.h declares `ether_hostton' */ /* #undef NETINET_ETHER_H_DECLARES_ETHER_HOSTTON */ /* Define to 1 if netinet/if_ether.h declares `ether_hostton' */ -#define NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON /**/ +#define NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON /* do not use protochain */ /* #undef NO_PROTOCHAIN */ /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "" /* Define to the full name of this package. */ #define PACKAGE_NAME "" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "" -/* Define to the home page for this package. */ -#define PACKAGE_URL "" - /* Define to the version of this package. */ #define PACKAGE_VERSION "" /* /dev/dlpi directory */ /* #undef PCAP_DEV_PREFIX */ /* target host supports Bluetooth sniffing */ /* #undef PCAP_SUPPORT_BT */ /* target host supports CAN sniffing */ /* #undef PCAP_SUPPORT_CAN */ /* target host supports canusb */ /* #undef PCAP_SUPPORT_CANUSB */ /* target host supports netfilter sniffing */ /* #undef PCAP_SUPPORT_NETFILTER */ /* target host supports USB sniffing */ /* #undef PCAP_SUPPORT_USB */ /* include ACN support */ /* #undef SITA */ + +/* if struct sockaddr_hci has hci_channel member */ +/* #undef SOCKADDR_HCI_HAS_HCI_CHANNEL */ /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Enable parser debugging */ /* #undef YYDEBUG */ /* Number of bits in a file offset, on hosts where this is settable. */ /* #undef _FILE_OFFSET_BITS */ /* needed on HP-UX */ /* #undef _HPUX_SOURCE */ /* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ /* #undef _LARGEFILE_SOURCE */ /* Define for large files, on AIX-style hosts. */ /* #undef _LARGE_FILES */ /* define on AIX to get certain functions */ /* #undef _SUN */ /* to handle Ultrix compilers that don't support const in prototypes */ /* #undef const */ /* Define as token for inline if inlining supported */ #define inline inline /* Define to `short' if int16_t not defined. */ /* #undef int16_t */ /* Define to `int' if int32_t not defined. */ /* #undef int32_t */ /* Define to `long long' if int64_t not defined. */ /* #undef int64_t */ /* Define to `signed char' if int8_t not defined. */ /* #undef int8_t */ /* on sinix */ /* #undef sinix */ /* Define to `unsigned short' if u_int16_t not defined. */ /* #undef u_int16_t */ /* Define to `unsigned int' if u_int32_t not defined. */ /* #undef u_int32_t */ /* Define to `unsigned long long' if u_int64_t not defined. */ /* #undef u_int64_t */ /* Define to `unsigned char' if u_int8_t not defined. */ /* #undef u_int8_t */ Index: stable/9/lib/libpcap =================================================================== --- stable/9/lib/libpcap (revision 252280) +++ stable/9/lib/libpcap (revision 252281) Property changes on: stable/9/lib/libpcap ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/lib/libpcap:r251129