diff --git a/CHANGELOG b/CHANGELOG index 487d76ded..46663a6fd 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,7 @@ # Nmap Changelog ($Id$); -*-text-*- +o Upgraded the included libpcap to 1.0.0. [David] + o Nmap now prefers to display the hostname supplied by the user instead of the reverse-DNS name in most places. If a reverse DNS record exists, and it differs from the user-supplied name, it is printed diff --git a/libpcap/CHANGES b/libpcap/CHANGES index a65654726..dc4e00699 100644 --- a/libpcap/CHANGES +++ b/libpcap/CHANGES @@ -1,21 +1,41 @@ -@(#) $Header: /tcpdump/master/libpcap/CHANGES,v 1.59.2.11 2007/07/24 02:27:32 mcr Exp $ (LBL) +@(#) $Header: /tcpdump/master/libpcap/CHANGES,v 1.67.2.4 2008-10-28 00:27:42 ken Exp $ (LBL) -Wed. July 23, 2007. mcr@xelerance.com. Summary for 0.9.7 libpcap release +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 zerocopy BPF on platforms that support it + 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/pbf* 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 - FIXED version file to be 0.9.7 instead of 0.9.5. - added flags/configuration for cloning bpf device. - added DLT_MTP2_WITH_PHDR support (PPI) - "fix" the "memory leak" in icode_to_fcode() -- documentation bug - Various link-layer types, with a pseudo-header, for SITA http://www.sita.aero/ - introduces support for the DAG ERF type TYPE_COLOR_MC_HDLC_POS. - Basic BPF filtering support for DLT_MTP2_WITH_PHDR is also added. - check for IPv4 and IPv6, even for DLT_RAW - add support for DLT_JUNIPER_ISM - Pick up changes from NetBSD: many from tron, christos, drochner - Allocate DLT_ for 802.15.4 without any header munging, for Mikko Saarnivala. - Header for 802.16 MAC Common Part Sublayer plus a radiotap radio header +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 +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 diff --git a/libpcap/CREDITS b/libpcap/CREDITS index d03dfb874..2cd7207d4 100644 --- a/libpcap/CREDITS +++ b/libpcap/CREDITS @@ -1,106 +1,126 @@ This file lists people who have contributed to libpcap: The current maintainers: - Bill Fenner - Fulvio Risso - Guy Harris - Hannes Gredler - Jun-ichiro itojun Hagino - Michael Richardson + Bill Fenner + Fulvio Risso + Guy Harris + Hannes Gredler + Michael Richardson Additional people who have contributed patches: - Alan Bawden - Alexey Kuznetsov - Albert Chin - Andrew Brown - Antti Kantee - Arkadiusz Miskiewicz - Armando L. Caro Jr. - Assar Westerlund - Brian Ginsbach - Charles M. Hannum - Chris G. Demetriou - Chris Lightfoot - Chris Pepper - Daniele Orlandi - Darren Reed - David Kaelbling - David Young - Dean Gaudet - Don Ebright - Dug Song - Eric Anderson - Erik de Castro Lopo - Florent Drouin - Franz Schaefer - Gianluca Varenni - Gilbert Hoyek - Gisle Vanem - Graeme Hewson - Greg Stark - Greg Troxel - Guillaume Pelat - Hyung Sik Yoon - Igor Khristophorov - Jan-Philip Velders - Jason R. Thorpe - Javier Achirica - Jean Tourrilhes - Jefferson Ogata - Jesper Peterson - John Bankier - Jon Lindgren - Juergen Schoenwaelder - Jung-uk Kim - Kazushi Sugyo - Klaus Klein - Koryn Grant - Krzysztof Halasa - Lorenzo Cavallaro - Loris Degioanni - Love Hörnquist-Åstrand - Maciej W. Rozycki - Marcus Felipe Pereira - Mark C. Brown - Mark Pizzolato - Martin Husemann - Matthew Luckie - Mike Kershaw - Mike Wiacek - Monroe Williams - Nicolas Dade - Octavian Cerna - Olaf Kirch - Ollie Wild - Onno van der Linden - Patrick Marie - Paul Mundt - Pavel Kankovsky - Pawel Pokrywka - Peter Fales - Peter Jeremy - Phil Wood - Rafal Maszkowski - Rick Jones - Scott Barron - Scott Gifford - Sebastian Krahmer - Shaun Clowes - Solomon Peachy - Stefan Hudson - Stephen Donnelly - Takashi Yamamoto - Tanaka Shin-ya - Tony Li - Torsten Landschoff - Uns Lider - Uwe Girlich - Xianjie Zhang + Alan Bawden + Alexander 'Leo' Bergolth + Alexey Kuznetsov + Albert Chin + Andrew Brown + Antti Kantee + Arien Vijn + Arkadiusz Miskiewicz + Armando L. Caro Jr. + Assar Westerlund + Brian Ginsbach + Charles M. Hannum + Chris G. Demetriou + Chris Lightfoot + Chris Pepper + Christian Peron + Daniele Orlandi + Darren Reed + David Kaelbling + David Young + Dean Gaudet + Don Ebright + Dug Song + Eric Anderson + Erik de Castro Lopo + Florent Drouin + Franz Schaefer + Fulko Hew + Gianluca Varenni + Gilbert Hoyek + Gisle Vanem + Gisle Vanem + Graeme Hewson + Greg Stark + Greg Troxel + Gregor Maier + Guillaume Pelat + Hagen Paul Pfeifer + Hyung Sik Yoon + Igor Khristophorov + Jan-Philip Velders + Jason R. Thorpe + Javier Achirica + Jean Tourrilhes + Jefferson Ogata + Jesper Peterson + Joerg Mayer + John Bankier + Jon Lindgren + Juergen Schoenwaelder + Jung-uk Kim + Kazushi Sugyo + Klaus Klein + Koryn Grant + Kris Katterjohn + Krzysztof Halasa + Lorenzo Cavallaro + Loris Degioanni + Love Hörnquist-Åstrand + Luis Martin Garcia + Maciej W. Rozycki + Marcus Felipe Pereira + Mark C. Brown + Mark Pizzolato + Martin Husemann + Matthew Luckie + Max Laier + Mike Frysinger + Mike Kershaw + Mike Wiacek + Monroe Williams + 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 + Phil Wood + Rafal Maszkowski + + Richard Stearn + Rick Jones + Sagun Shakya + Scott Barron + Scott Gifford + Sebastian Krahmer + Sepherosa Ziehau + Shaun Clowes + Solomon Peachy + Stefan Hudson + Stephen Donnelly + Takashi Yamamoto + Tanaka Shin-ya + Tony Li + Torsten Landschoff + Uns Lider + Uwe Girlich + Xianjie Zhang Yen Yen Lim - Yoann Vandoorselaere + Yoann Vandoorselaere The original LBL crew: Steve McCanne Craig Leres Van Jacobson + +Past maintainers: + Jun-ichiro itojun Hagino diff --git a/libpcap/FILES b/libpcap/FILES deleted file mode 100644 index 879d74b59..000000000 --- a/libpcap/FILES +++ /dev/null @@ -1,125 +0,0 @@ -CHANGES -ChmodBPF/ChmodBPF -ChmodBPF/StartupParameters.plist -CREDITS -FILES -INSTALL.txt -LICENSE -Makefile.in -README -README.aix -README.dag -README.hpux -README.linux -README.macosx -README.septel -README.tru64 -README.Win32 -SUNOS4/nit_if.o.sparc -SUNOS4/nit_if.o.sun3 -SUNOS4/nit_if.o.sun4c.4.0.3c -TODO -VERSION -acconfig.h -aclocal.m4 -arcnet.h -atmuni31.h -bpf/net/bpf_filter.c -bpf_dump.c -bpf_image.c -config.guess -config.h.in -config.sub -configure -configure.in -etherent.c -ethertype.h -fad-getad.c -fad-gifc.c -fad-glifc.c -fad-null.c -fad-win32.c -gencode.c -gencode.h -grammar.y -inet.c -install-sh -lbl/os-aix4.h -lbl/os-hpux11.h -lbl/os-osf4.h -lbl/os-osf5.h -lbl/os-solaris2.h -lbl/os-sunos4.h -lbl/os-ultrix4.h -llc.h -missing/snprintf.c -mkdep -msdos/bin2c.c -msdos/common.dj -msdos/makefile -msdos/makefile.dj -msdos/makefile.wc -msdos/ndis2.c -msdos/ndis2.h -msdos/ndis_0.asm -msdos/pkt_rx0.asm -msdos/pkt_rx1.s -msdos/pktdrvr.c -msdos/pktdrvr.h -msdos/readme.dos -nametoaddr.c -nlpid.h -optimize.c -packaging/pcap.spec -packaging/pcap.spec.in -pcap-bpf.c -pcap-bpf.h -pcap-dag.c -pcap-dag.h -pcap-dlpi.c -pcap-dos.c -pcap-dos.h -pcap-enet.c -pcap-int.h -pcap-linux.c -pcap-namedb.h -pcap-nit.c -pcap-nit.h -pcap-null.c -pcap-pf.c -pcap-pf.h -pcap-septel.c -pcap-septel.h -pcap-stdinc.h -pcap-snit.c -pcap-snoop.c -pcap-win32.c -pcap.3 -pcap.c -pcap.h -pf.h -ppp.h -savefile.c -scanner.l -sll.h -sunatmpos.h -Win32/Include/Gnuc.h -Win32/Include/addrinfo.h -Win32/Include/bittypes.h -Win32/Include/cdecl_ext.h -Win32/Include/inetprivate.h -Win32/Include/ip6_misc.h -Win32/Include/sockstorage.h -Win32/Include/arpa/nameser.h -Win32/Include/net/if.h -Win32/Include/net/netdb.h -Win32/Include/net/paths.h -Win32/Src/ffs.c -Win32/Src/getaddrinfo.c -Win32/Src/getnetbynm.c -Win32/Src/getnetent.c -Win32/Src/getopt.c -Win32/Src/getservent.c -Win32/Src/inet_aton.c -Win32/Src/inet_net.c -Win32/Src/inet_pton.c diff --git a/libpcap/INSTALL.txt b/libpcap/INSTALL.txt index d2c018066..c7cfd2261 100644 --- a/libpcap/INSTALL.txt +++ b/libpcap/INSTALL.txt @@ -1,4 +1,4 @@ -@(#) $Header: /tcpdump/master/libpcap/INSTALL.txt,v 1.12.2.1 2005/06/20 21:30:14 guy Exp $ (LBL) +@(#) $Header: /tcpdump/master/libpcap/INSTALL.txt,v 1.21.2.8 2008-06-12 20:25:38 guy Exp $ (LBL) To build libpcap, run "./configure" (a shell script). The configure script will determine your system attributes and generate an @@ -211,8 +211,7 @@ Read the README.aix file for information on installing libpcap and configuring your system to be able to support libpcap. If you use NeXTSTEP, you will not be able to build libpcap from this -release. We hope to support this operating system in some future -release of libpcap. +release. If you use SINIX, you should be able to build libpcap from this release. It is known to compile and run on SINIX-Y/N 5.42 with the C-DS @@ -229,22 +228,22 @@ Another workaround is to use flex and bison. If you use SCO, you might have trouble building libpcap from this release. We do not have a machine running SCO and have not had reports -of anyone successfully building on it. Since SCO apparently supports -DLPI, it's possible the current version works. Meanwhile, SCO provides -a tcpdump binary as part of their "Network/Security Tools" package: +of anyone successfully building on it; the current release of libpcap +does not compile on SCO OpenServer 5. Although SCO apparently supports +DLPI to some extent, the DLPI in OpenServer 5 is very non-standard, and +it appears that completely new code would need to be written to capture +network traffic. SCO do not appear to provide tcpdump binaries for +OpenServer 5 or OpenServer 6 as part of SCO Skunkware: - http://www.sco.com/technology/internet/goodies/#SECURITY + http://www.sco.com/skunkware/ -There is also a README that explains how to enable packet capture. - -If you use UnixWare, you will not be able to build libpcap from this -release. We hope to support this operating system in some future -release of libpcap. Meanwhile, there appears to be an UnixWare port of -libpcap 0.0 (and tcpdump 3.0) in: - - ftp://ftp1.freebird.org/pub/mirror/freebird/internet/systools/ - -UnixWare appears to use a hacked version of DLPI. +If you use UnixWare, you might be able to build libpcap from this +release, or you might not. We do not have a machine running UnixWare, +so we have not tested it; however, SCO provide packages for libpcap +0.6.2 and tcpdump 3.7.1 in the UnixWare 7/Open UNIX 8 part of SCO +Skunkware, and the source package for libpcap 0.6.2 is not changed from +the libpcap 0.6.2 source release, so this release of libpcap might also +build without changes on UnixWare 7. If linking tcpdump fails with "Undefined: _alloca" when using bison on a Sun4, your version of bison is broken. In any case version 1.16 or @@ -298,7 +297,6 @@ CHANGES - description of differences between releases ChmodBPF/* - Mac OS X startup item to set ownership and permissions on /dev/bpf* CREDITS - people that have helped libpcap along -FILES - list of files exported as part of the distribution INSTALL.txt - this file LICENSE - the license under which tcpdump is distributed Makefile.in - compilation rules (input to the configure script) @@ -309,6 +307,7 @@ README.hpux - notes on using libpcap on HP-UX README.linux - notes on using libpcap on Linux README.macosx - notes on using libpcap on Mac OS X README.septel - notes on using libpcap to capture on Intel/Septel devices +README.sita - notes on using libpcap to capture on SITA devices README.tru64 - notes on using libpcap on Digital/Tru64 UNIX README.Win32 - notes on using libpcap on Win32 systems (with WinPcap) SUNOS4 - pre-SunOS 4.1 replacement kernel nit modules @@ -326,16 +325,22 @@ config.h.in - autoconf input config.sub - autoconf support configure - configure script (run this first) configure.in - configure script source +dlpisubs.c - DLPI-related functions for pcap-dlpi.c and pcap-libdlpi.c +dlpisubs.h - DLPI-related function declarations etherent.c - /etc/ethers support routines ethertype.h - Ethernet protocol types and names definitions fad-getad.c - pcap_findalldevs() for systems with getifaddrs() fad-gifc.c - pcap_findalldevs() for systems with only SIOCGIFLIST fad-glifc.c - pcap_findalldevs() for systems with SIOCGLIFCONF fad-null.c - pcap_findalldevs() for systems without capture support +fad-sita.c - pcap_findalldevs() for systems with SITA support fad-win32.c - pcap_findalldevs() for WinPcap +filtertest.c - test program for BPF compiler +findalldevstest.c - test program for pcap_findalldevs() gencode.c - BPF code generation routines gencode.h - BPF code generation definitions grammar.y - filter string grammar +ieee80211.h - 802.11 definitions inet.c - network routines install-sh - BSD style install script lbl/os-*.h - OS-dependent defines and prototypes @@ -348,8 +353,16 @@ nlpid.h - OSI network layer protocol identifier definitions net - symlink to bpf/net optimize.c - BPF optimization routines packaging - packaging information for building libpcap RPMs +pcap/bluetooth.h - public definition of DLT_BLUETOOTH_HCI_H4_WITH_PHDR header +pcap/bpf.h - BPF definitions +pcap/namedb.h - public libpcap name database definitions +pcap/pcap.h - public libpcap definitions +pcap/sll.h - public definition of DLT_LINUX_SLL header +pcap/usb.h - public definition of DLT_USB header pcap-bpf.c - BSD Packet Filter support -pcap-bpf.h - BPF definitions +pcap-bpf.h - header for backwards compatibility +pcap-bt-linux.c - Bluetooth capture support for Linux +pcap-bt-linux.h - Bluetooth capture support for Linux pcap-dag.c - Endace DAG device capture support pcap-dag.h - Endace DAG device capture support pcap-dlpi.c - Data Link Provider Interface support @@ -357,27 +370,34 @@ pcap-dos.c - MS-DOS capture support pcap-dos.h - headers for MS-DOS capture support pcap-enet.c - enet support pcap-int.h - internal libpcap definitions +pcap-libdlpi.c - Data Link Provider Interface support for systems with libdlpi pcap-linux.c - Linux packet socket support -pcap-namedb.h - public libpcap name database definitions +pcap-namedb.h - header for backwards compatibility pcap-nit.c - SunOS Network Interface Tap support pcap-nit.h - SunOS Network Interface Tap definitions pcap-null.c - dummy monitor support (allows offline use of libpcap) pcap-pf.c - Ultrix and Digital/Tru64 UNIX Packet Filter support pcap-pf.h - Ultrix and Digital/Tru64 UNIX Packet Filter definitions -pcap-septel.c - INTEL/Septel device capture support -pcap-septel.h - INTEL/Septel device capture support +pcap-septel.c - Intel/Septel device capture support +pcap-septel.h - Intel/Septel device capture support +pcap-sita.c - SITA device capture support +pcap-sita.h - SITA device capture support +pcap-sita.html - SITA device capture documentation pcap-stdinc.h - includes and #defines for compiling on Win32 systems pcap-snit.c - SunOS 4.x STREAMS-based Network Interface Tap support pcap-snoop.c - IRIX Snoop network monitoring support +pcap-usb-linux.c - USB capture support for Linux +pcap-usb-linux.h - USB capture support for Linux pcap-win32.c - WinPcap capture support -pcap.3 - manual entry +pcap.3pcap - manual entry for the library pcap.c - pcap utility routines -pcap.h - public libpcap definitions -pf.h - OpenBSD DLT_PFLOG definitions +pcap.h - header for backwards compatibility +pcap_*.3pcap - manual entries for library functions +pcap-filter.4 - manual entry for filter syntax +pcap-linktype.4 - manual entry for link-layer header types ppp.h - Point to Point Protocol definitions -rawss7.h - information on DLT_ types for SS7 +runlex.sh - wrapper for Lex/Flex savefile.c - offline support scanner.l - filter string scanner -sll.h - definitions for Linux cooked mode fake link-layer header sunatmpos.h - definitions for SunATM capturing Win32 - headers and routines for building on Win32 systems diff --git a/libpcap/Makefile.in b/libpcap/Makefile.in index 6c90d7dfb..4d4356320 100644 --- a/libpcap/Makefile.in +++ b/libpcap/Makefile.in @@ -17,7 +17,7 @@ # WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. # -# @(#) $Header: /tcpdump/master/libpcap/Makefile.in,v 1.99.2.2 2007/07/24 02:35:15 mcr Exp $ (LBL) +# @(#) $Header: /tcpdump/master/libpcap/Makefile.in,v 1.108.2.28 2008-10-23 22:13:21 guy Exp $ (LBL) # # Various configurable paths (remember to edit Makefile.in, not Makefile) @@ -26,11 +26,14 @@ # Top level hierarchy prefix = @prefix@ exec_prefix = @exec_prefix@ +datarootdir = @datarootdir@ +# Pathname of directory to install the configure program +bindir = @bindir@ # Pathname of directory to install the include files includedir = @includedir@ # Pathname of directory to install the library libdir = @libdir@ -# Pathname of directory to install the man page +# Pathname of directory to install the man pages mandir = @mandir@ # VPATH @@ -47,11 +50,12 @@ INCLS = -I. @V_INCLS@ DEFS = @DEFS@ @V_DEFS@ LIBS = @V_LIBS@ DAGLIBS = @DAGLIBS@ +DEPLIBS = @DEPLIBS@ DYEXT = @DYEXT@ PROG=libpcap # Standard CFLAGS -CFLAGS = $(CCOPT) $(INCLS) $(DEFS) +CFLAGS = @CFLAGS@ $(CCOPT) $(INCLS) $(DEFS) INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ @@ -63,8 +67,8 @@ RANLIB = @RANLIB@ # used by the generated parser. This allows programs to use lex/yacc # and link against libpcap. If you don't have flex or bison, get them. # -LEX = flex -YACC = yacc +LEX = @V_LEX@ +YACC = @V_YACC@ # Explicitly define compilation rule since SunOS 4's make doesn't like gcc. # Also, gcc does not remove the .o before forking 'as', which can be a @@ -73,7 +77,7 @@ YACC = yacc @rm -f $@ $(CC) $(CFLAGS) -c $(srcdir)/$*.c -PSRC = pcap-@V_PCAP@.c +PSRC = pcap-@V_PCAP@.c @USB_SRC@ @BT_SRC@ FSRC = fad-@V_FINDALLDEVS@.c SSRC = @SSRC@ CSRC = pcap.c inet.c gencode.c optimize.c nametoaddr.c \ @@ -86,10 +90,31 @@ SRC = $(PSRC) $(FSRC) $(CSRC) $(SSRC) $(GENSRC) # We would like to say "OBJ = $(SRC:.c=.o)" but Ultrix's make cannot # hack the extra indirection OBJ = $(PSRC:.c=.o) $(FSRC:.c=.o) $(CSRC:.c=.o) $(SSRC:.c=.o) $(GENSRC:.c=.o) $(LIBOBJS) -HDR = pcap.h pcap-int.h pcap-namedb.h pcap-nit.h pcap-pf.h \ - ethertype.h gencode.h gnuc.h +HDR = \ + acconfig.h \ + arcnet.h \ + atmuni31.h \ + ethertype.h \ + gencode.h \ + ieee80211.h \ + llc.h \ + nlpid.h \ + pcap/bluetooth.h \ + pcap/bpf.h \ + pcap/namedb.h \ + pcap/pcap.h \ + pcap/sll.h \ + pcap/usb.h \ + pcap/vlan.h \ + pcap.h \ + pcap-int.h \ + pcap-namedb.h \ + pcap-stdinc.h \ + ppp.h \ + sunatmpos.h + GENHDR = \ - tokdefs.h version.h + scanner.h tokdefs.h version.h TAGHDR = \ pcap-bpf.h @@ -97,13 +122,200 @@ TAGHDR = \ TAGFILES = \ $(SRC) $(HDR) $(TAGHDR) -CLEANFILES = $(OBJ) libpcap.a version.c lex.yy.c +CLEANFILES = $(OBJ) libpcap.a $(GENSRC) $(GENHDR) lex.yy.c -all: libpcap.a +MAN1 = pcap-config.1 + +MAN3PCAP_EXPAND = \ + pcap.3pcap.in \ + pcap_compile.3pcap.in \ + pcap_datalink.3pcap.in \ + pcap_dump_open.3pcap.in \ + pcap_list_datalinks.3pcap.in \ + pcap_open_dead.3pcap.in \ + pcap_open_offline.3pcap.in + +MAN3PCAP_NOEXPAND = \ + pcap_activate.3pcap \ + pcap_breakloop.3pcap \ + pcap_can_set_rfmon.3pcap \ + pcap_close.3pcap \ + pcap_create.3pcap \ + pcap_datalink_name_to_val.3pcap \ + pcap_datalink_val_to_name.3pcap \ + pcap_dump.3pcap \ + pcap_dump_close.3pcap \ + pcap_dump_file.3pcap \ + pcap_dump_flush.3pcap \ + pcap_dump_ftell.3pcap \ + pcap_file.3pcap \ + pcap_fileno.3pcap \ + pcap_findalldevs.3pcap \ + pcap_freealldevs.3pcap \ + pcap_freecode.3pcap \ + pcap_free_datalinks.3pcap \ + pcap_get_selectable_fd.3pcap \ + pcap_geterr.3pcap \ + pcap_inject.3pcap \ + pcap_is_swapped.3pcap \ + pcap_lib_version.3pcap \ + pcap_lookupdev.3pcap \ + pcap_lookupnet.3pcap \ + pcap_loop.3pcap \ + pcap_major_version.3pcap \ + pcap_next_ex.3pcap \ + pcap_offline_filter.3pcap \ + pcap_open_live.3pcap \ + pcap_set_buffer_size.3pcap \ + pcap_set_datalink.3pcap \ + pcap_set_promisc.3pcap \ + pcap_set_rfmon.3pcap \ + pcap_set_snaplen.3pcap \ + pcap_set_timeout.3pcap \ + pcap_setdirection.3pcap \ + pcap_setfilter.3pcap \ + pcap_setnonblock.3pcap \ + pcap_snapshot.3pcap \ + pcap_stats.3pcap \ + pcap_statustostr.3pcap \ + pcap_strerror.3pcap + +MAN3PCAP = $(MAN3PCAP_NOEXPAND) $(MAN3PCAP_EXPAND:.in=) + +MANFILE = \ + pcap-savefile.manfile.in + +MANMISC = \ + pcap-filter.manmisc.in \ + pcap-linktype.manmisc.in + +EXTRA_DIST = \ + CHANGES \ + ChmodBPF/ChmodBPF \ + ChmodBPF/StartupParameters.plist \ + CREDITS \ + INSTALL.txt \ + LICENSE \ + Makefile.in \ + README \ + README.aix \ + README.dag \ + README.hpux \ + README.linux \ + README.macosx \ + README.septel \ + README.sita \ + README.tru64 \ + README.Win32 \ + SUNOS4/nit_if.o.sparc \ + SUNOS4/nit_if.o.sun3 \ + SUNOS4/nit_if.o.sun4c.4.0.3c \ + TODO \ + VERSION \ + aclocal.m4 \ + bpf/net/bpf_filter.c \ + chmod_bpf \ + config.guess \ + config.h.in \ + config.sub \ + configure \ + configure.in \ + dlpisubs.c \ + dlpisubs.h \ + fad-getad.c \ + fad-gifc.c \ + fad-glifc.c \ + fad-null.c \ + fad-sita.c \ + fad-win32.c \ + filtertest.c \ + findalldevstest.c \ + grammar.y \ + install-sh \ + lbl/os-aix4.h \ + lbl/os-hpux11.h \ + lbl/os-osf4.h \ + lbl/os-osf5.h \ + lbl/os-solaris2.h \ + lbl/os-sunos4.h \ + lbl/os-ultrix4.h \ + missing/snprintf.c \ + mkdep \ + msdos/bin2c.c \ + msdos/common.dj \ + msdos/makefile \ + msdos/makefile.dj \ + msdos/makefile.wc \ + msdos/ndis2.c \ + msdos/ndis2.h \ + msdos/ndis_0.asm \ + msdos/pkt_rx0.asm \ + msdos/pkt_rx1.s \ + msdos/pktdrvr.c \ + msdos/pktdrvr.h \ + msdos/readme.dos \ + net/bpf_filter.c \ + org.tcpdump.chmod_bpf.plist \ + packaging/pcap.spec.in \ + pcap-bpf.c \ + pcap-bpf.h \ + pcap-bt-linux.c \ + pcap-bt-linux.h \ + pcap-config.in \ + pcap-dag.c \ + pcap-dag.h \ + pcap-dlpi.c \ + pcap-dos.c \ + pcap-dos.h \ + pcap-enet.c \ + pcap-int.h \ + pcap-libdlpi.c \ + pcap-linux.c \ + pcap-namedb.h \ + pcap-nit.c \ + pcap-null.c \ + pcap-pf.c \ + pcap-septel.c \ + pcap-septel.h \ + pcap-sita.h \ + pcap-sita.c \ + pcap-sita.html \ + pcap-snit.c \ + pcap-snoop.c \ + pcap-usb-linux.c \ + pcap-usb-linux.h \ + pcap-win32.c \ + runlex.sh \ + scanner.l \ + Win32/Include/Gnuc.h \ + Win32/Include/addrinfo.h \ + Win32/Include/bittypes.h \ + Win32/Include/cdecl_ext.h \ + Win32/Include/inetprivate.h \ + Win32/Include/ip6_misc.h \ + Win32/Include/sockstorage.h \ + Win32/Include/arpa/nameser.h \ + Win32/Include/net/if.h \ + Win32/Include/net/netdb.h \ + Win32/Include/net/paths.h \ + Win32/Prj/libpcap.dsp \ + Win32/Prj/libpcap.dsw \ + Win32/Src/ffs.c \ + Win32/Src/gai_strerror.c \ + Win32/Src/getaddrinfo.c \ + Win32/Src/getnetbynm.c \ + Win32/Src/getnetent.c \ + Win32/Src/getopt.c \ + Win32/Src/getservent.c \ + Win32/Src/inet_aton.c \ + Win32/Src/inet_net.c \ + Win32/Src/inet_pton.c + +all: libpcap.a pcap-config libpcap.a: $(OBJ) @rm -f $@ - ar rc $@ $(OBJ) $(LIBS) + $(AR) rc $@ $(OBJ) $(LIBS) $(RANLIB) $@ shared: libpcap.$(DYEXT) @@ -114,19 +326,27 @@ shared: libpcap.$(DYEXT) # libpcap.so: $(OBJ) @rm -f $@ - $(CC) -shared -o $@.`cat VERSION` $(OBJ) $(DAGLIBS) + $(CC) -shared -Wl,-soname,$@.1 -o $@.`cat $(srcdir)/VERSION` $(OBJ) $(DAGLIBS) -# the following rule succeeds, but the result is untested. +# +# The following rule succeeds, but the result is untested. +# +# XXX - OS X installs the library as "libpcap.A.dylib", with that as the +# install_name, and sets the current version to 1 as well. VERSION +# might contain a not-purely-numeric version number, but +# -current_version requires a purely numeric version, so this won't +# work with top-of-tree builds. +# libpcap.dylib: $(OBJ) rm -f libpcap*.dylib - $(CC) -dynamiclib -undefined error -o libpcap.`cat VERSION`.dylib $(OBJ) \ - -install_name $(libdir)/libpcap.0.dylib -compatibility_version `cat VERSION` \ - -current_version `cat VERSION` - + $(CC) -dynamiclib -undefined error -o libpcap.`cat $(srcdir)/VERSION`.dylib $(OBJ) \ + -install_name $(libdir)/libpcap.A.dylib \ + -compatibility_version 1 \ + -current_version `sed 's/[^0-9.].*$$//' $(srcdir)/VERSION` scanner.c: $(srcdir)/scanner.l @rm -f $@ - $(LEX) -t $< > $$$$.$@; mv $$$$.$@ $@ + ./runlex.sh $(LEX) -o$@ $< scanner.o: scanner.c tokdefs.h $(CC) $(CFLAGS) -c scanner.c @@ -172,43 +392,135 @@ bpf_filter.c: $(srcdir)/bpf/net/bpf_filter.c bpf_filter.o: bpf_filter.c $(CC) $(CFLAGS) -c bpf_filter.c -install: libpcap.a +# +# Generate the pcap-config script. +# +pcap-config: pcap-config.in Makefile + @rm -f $@ $@.tmp + sed -e 's|@includedir[@]|$(includedir)|g' \ + -e 's|@libdir[@]|$(libdir)|g' \ + -e 's|@DEPLIBS[@]|$(DEPLIBS)|g' \ + pcap-config.in >$@.tmp + mv $@.tmp $@ + chmod a+x $@ + +# +# Test programs - not built by default, and not installed. +# +filtertest: filtertest.c libpcap.a + $(CC) $(CFLAGS) -I. -L. -o filtertest filtertest.c libpcap.a + +findalldevstest: findalldevstest.c libpcap.a + $(CC) $(CFLAGS) -I. -L. -o findalldevstest findalldevstest.c libpcap.a + +install: libpcap.a pcap-config [ -d $(DESTDIR)$(libdir) ] || \ (mkdir -p $(DESTDIR)$(libdir); chmod 755 $(DESTDIR)$(libdir)) $(INSTALL_DATA) libpcap.a $(DESTDIR)$(libdir)/libpcap.a $(RANLIB) $(DESTDIR)$(libdir)/libpcap.a [ -d $(DESTDIR)$(includedir) ] || \ (mkdir -p $(DESTDIR)$(includedir); chmod 755 $(DESTDIR)$(includedir)) + [ -d $(DESTDIR)$(includedir)/pcap ] || \ + (mkdir -p $(DESTDIR)$(includedir)/pcap; chmod 755 $(DESTDIR)$(includedir)/pcap) + [ -d $(DESTDIR)$(mandir)/man1 ] || \ + (mkdir -p $(DESTDIR)$(mandir)/man1; chmod 755 $(DESTDIR)$(mandir)/man1) + [ -d $(DESTDIR)$(mandir)/man3 ] || \ + (mkdir -p $(DESTDIR)$(mandir)/man3; chmod 755 $(DESTDIR)$(mandir)/man3) + [ -d $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@ ] || \ + (mkdir -p $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@; chmod 755 $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@) + [ -d $(DESTDIR)$(mandir)/man@MAN_MISC_INFO@ ] || \ + (mkdir -p $(DESTDIR)$(mandir)/man@MAN_MISC_INFO@; chmod 755 $(DESTDIR)$(mandir)/man@MAN_MISC_INFO@) + $(INSTALL_DATA) $(srcdir)/pcap/pcap.h \ + $(DESTDIR)$(includedir)/pcap/pcap.h + $(INSTALL_DATA) $(srcdir)/pcap/bpf.h \ + $(DESTDIR)$(includedir)/pcap/bpf.h + $(INSTALL_DATA) $(srcdir)/pcap/namedb.h \ + $(DESTDIR)$(includedir)/pcap/namedb.h + $(INSTALL_DATA) $(srcdir)/pcap/sll.h \ + $(DESTDIR)$(includedir)/pcap/sll.h + $(INSTALL_DATA) $(srcdir)/pcap/usb.h \ + $(DESTDIR)$(includedir)/pcap/usb.h $(INSTALL_DATA) $(srcdir)/pcap.h $(DESTDIR)$(includedir)/pcap.h $(INSTALL_DATA) $(srcdir)/pcap-bpf.h \ $(DESTDIR)$(includedir)/pcap-bpf.h $(INSTALL_DATA) $(srcdir)/pcap-namedb.h \ $(DESTDIR)$(includedir)/pcap-namedb.h - [ -d $(DESTDIR)$(mandir)/man3 ] || \ - (mkdir -p $(DESTDIR)$(mandir)/man3; chmod 755 $(DESTDIR)$(mandir)/man3) - $(INSTALL_DATA) $(srcdir)/pcap.3 \ - $(DESTDIR)$(mandir)/man3/pcap.3 + $(INSTALL_PROGRAM) pcap-config $(DESTDIR)$(bindir)/pcap-config + for i in $(MAN1); do \ + $(INSTALL_DATA) $(srcdir)/$$i \ + $(DESTDIR)$(mandir)/man1/$$i; done + for i in $(MAN3PCAP); do \ + $(INSTALL_DATA) $(srcdir)/$$i \ + $(DESTDIR)$(mandir)/man3/$$i; done + ln $(DESTDIR)$(mandir)/man3/pcap_datalink_val_to_name.3pcap \ + $(DESTDIR)$(mandir)/man3/pcap_datalink_val_to_description.3pcap + ln $(DESTDIR)$(mandir)/man3/pcap_dump_open.3pcap \ + $(DESTDIR)$(mandir)/man3/pcap_dump_fopen.3pcap + ln $(DESTDIR)$(mandir)/man3/pcap_geterr.3pcap \ + $(DESTDIR)$(mandir)/man3/pcap_perror.3pcap + ln $(DESTDIR)$(mandir)/man3/pcap_inject.3pcap \ + $(DESTDIR)$(mandir)/man3/pcap_sendpacket.3pcap + ln $(DESTDIR)$(mandir)/man3/pcap_loop.3pcap \ + $(DESTDIR)$(mandir)/man3/pcap_dispatch.3pcap + ln $(DESTDIR)$(mandir)/man3/pcap_major_version.3pcap \ + $(DESTDIR)$(mandir)/man3/pcap_minor_version.3pcap + ln $(DESTDIR)$(mandir)/man3/pcap_next_ex.3pcap \ + $(DESTDIR)$(mandir)/man3/pcap_next.3pcap + ln $(DESTDIR)$(mandir)/man3/pcap_open_offline.3pcap \ + $(DESTDIR)$(mandir)/man3/pcap_fopen_offline.3pcap + ln $(DESTDIR)$(mandir)/man3/pcap_setnonblock.3pcap \ + $(DESTDIR)$(mandir)/man3/pcap_getnonblock.3pcap + for i in $(MANFILE); do \ + $(INSTALL_DATA) $(srcdir)/`echo $$i | sed 's/.manfile.in/.manfile/'` \ + $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@/`echo $$i | sed 's/.manfile.in/.@MAN_FILE_FORMATS@/'`; done + for i in $(MANMISC); do \ + $(INSTALL_DATA) $(srcdir)/`echo $$i | sed 's/.manmisc.in/.manmisc/'` \ + $(DESTDIR)$(mandir)/man@MAN_MISC_INFO@/`echo $$i | sed 's/.manmisc.in/.@MAN_MISC_INFO@/'`; done install-shared: install-shared-$(DYEXT) install-shared-so: libpcap.so $(INSTALL_PROGRAM) libpcap.so.`cat VERSION` $(DESTDIR)$(libdir)/libpcap.so.`cat VERSION` install-shared-dylib: libpcap.dylib $(INSTALL_PROGRAM) libpcap.`cat VERSION`.dylib $(DESTDIR)$(libdir)/libpcap.`cat VERSION`.dylib - VER=`cat VERSION`; cd $(DESTDIR)$(libdir) && ln -sf libpcap.$$VER.dylib libpcap.0.dylib; ln -sf libpcap.0.dylib libpcap.dylib + VER=`cat VERSION`; cd $(DESTDIR)$(libdir) && ln -sf libpcap.$$VER.dylib libpcap.A.dylib; ln -sf libpcap.A.dylib libpcap.dylib uninstall: rm -f $(DESTDIR)$(libdir)/libpcap.a + rm -f $(DESTDIR)$(includedir)/pcap/pcap.h + rm -f $(DESTDIR)$(includedir)/pcap/bpf.h + rm -f $(DESTDIR)$(includedir)/pcap/namedb.h + rm -f $(DESTDIR)$(includedir)/pcap/sll.h + rm -f $(DESTDIR)$(includedir)/pcap/usb.h + -rmdir $(DESTDIR)$(includedir)/pcap rm -f $(DESTDIR)$(includedir)/pcap.h rm -f $(DESTDIR)$(includedir)/pcap-bpf.h rm -f $(DESTDIR)$(includedir)/pcap-namedb.h - rm -f $(DESTDIR)$(mandir)/man3/pcap.3 + for i in $(MAN1); do \ + rm -f $(DESTDIR)$(mandir)/man1/$$i; done + for i in $(MAN3PCAP); do \ + rm -f $(DESTDIR)$(mandir)/man3/$$i; done + rm -f $(DESTDIR)$(mandir)/man3/pcap_datalink_val_to_description.3pcap + rm -f $(DESTDIR)$(mandir)/man3/pcap_dump_fopen.3pcap + rm -f $(DESTDIR)$(mandir)/man3/pcap_perror.3pcap + rm -f $(DESTDIR)$(mandir)/man3/pcap_sendpacket.3pcap + rm -f $(DESTDIR)$(mandir)/man3/pcap_dispatch.3pcap + rm -f $(DESTDIR)$(mandir)/man3/pcap_minor_version.3pcap + rm -f $(DESTDIR)$(mandir)/man3/pcap_next.3pcap + rm -f $(DESTDIR)$(mandir)/man3/pcap_fopen_offline.3pcap + rm -f $(DESTDIR)$(mandir)/man3/pcap_getnonblock.3pcap + for i in $(MANFILE); do \ + rm -f $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@/`echo $$i | sed 's/.manfile.in/.@MAN_FILE_FORMATS@/'`; done + for i in $(MANMISC); do \ + rm -f $(DESTDIR)$(mandir)/man@MAN_MISC_INFO@/`echo $$i | sed 's/.manmisc.in/.@MAN_MISC_INFO@/'`; done clean: rm -f $(CLEANFILES) libpcap*.dylib libpcap.so* distclean: clean rm -f Makefile config.cache config.log config.status \ - config.h gnuc.h os-proto.h bpf_filter.c stamp-h stamp-h.in + config.h gnuc.h os-proto.h bpf_filter.c pcap-config \ + stamp-h stamp-h.in + rm -f $(MAN3PCAP_EXPAND:.in=) $(MANFILE:.in=) $(MANMISC:.in=) rm -rf autom4te.cache tags: $(TAGFILES) @@ -220,8 +532,12 @@ packaging/pcap.spec: packaging/pcap.spec.in VERSION releasetar: @cwd=`pwd` ; dir=`basename $$cwd` ; name=$(PROG)-`cat VERSION` ; \ - list="" ; make distclean; cd ..; mkdir -p n; cd n; ln -s ../$$dir $$name; \ - tar -c -z -f $$name.tar.gz $$name/. ; + mkdir $$name; \ + tar cf - $(CSRC) $(HDR) $(MAN1) $(MAN3PCAP_EXPAND) \ + $(MAN3PCAP_NOEXPAND) $(MANFILE) $(MANMISC) $(EXTRA_DIST) | \ + (cd $$name; tar xf -); \ + tar -c -z -f $$name.tar.gz $$name; \ + rm -rf $$name depend: $(GENSRC) $(GENHDR) bpf_filter.c ./mkdep -c $(CC) $(DEFS) $(INCLS) $(SRC) diff --git a/libpcap/NMAP_MODIFICATIONS b/libpcap/NMAP_MODIFICATIONS index 417a43adc..e7fb97e37 100644 --- a/libpcap/NMAP_MODIFICATIONS +++ b/libpcap/NMAP_MODIFICATIONS @@ -1,197 +1,47 @@ -Nmap currently includes a modified version of the tcpdump.org release -of libpcap version 0.9.7 (released July 23, 2007). The modifications -are as follows: +o Included this file, renamed directory from libpcap-1.0.0 to libpcap. -o Included this file, renamed directory from libpcap-0.9.7 to - libpcap. +o Removed these files and directories: + packaging/ + config.guess + config.sub + install-sh + Win32 + msdos -o Renamed configure.in to configure.ac, which is the name now - recommended by the autoconf project. +o Added @CFLAGS@ to the CFLAGS definition in Makefile.in to pick up -g + if configure determines that it is supported: -o Removed the .cvsignore file, all 'CVS' directories, the 'packaging' - directory, (pcap spec file conflicts w/Nmap spec file when I - rpmbuild from tarball) and the install-sh script. +--- Makefile.in.orig 2009-10-27 13:17:52.000000000 -0600 ++++ Makefile.in 2009-10-27 13:14:42.000000000 -0600 +@@ -55,7 +55,7 @@ + PROG=libpcap -o Removed libpcap-0.9, CHANGES~, gencode.c.orig, gencode.c.rej, - wlan_filtering.patch, .#CHANGES.1.59 and .#Makefile.in.1.99.2.1 - -o Updated config.sub and config.guess (in the distribution file they - are just symlinks to the corresponding files in the nmap dir) - -o Removed the Win32 and msdos directories as Nmap doesn't use them - -o Added the gcc debugging flag (-g) to aclocal.m4 if gcc is being used: - ---- libpcap-0.9.7/aclocal.m4 2005-04-20 22:42:09.000000000 -0500 -+++ libpcap/aclocal.m4 2007-08-25 17:11:22.000000000 -0500 -@@ -76,7 +76,7 @@ AC_DEFUN(AC_LBL_C_INIT, - if test "$GCC" = yes ; then - if test "$SHLICC2" = yes ; then - ac_cv_lbl_gcc_vers=2 -- $1="-O2" -+ $1="-g -O2" - else - AC_MSG_CHECKING(gcc version) - AC_CACHE_VAL(ac_cv_lbl_gcc_vers, -@@ -87,7 +87,7 @@ AC_DEFUN(AC_LBL_C_INIT, - -e 's/\..*//'`) - AC_MSG_RESULT($ac_cv_lbl_gcc_vers) - if test $ac_cv_lbl_gcc_vers -gt 1 ; then -- $1="-O2" -+ $1="-g -O2" - fi - fi - else - -o Used to change pcap-linux.c by adding a select() call guarding - recvfrom() to insure that it returns after the timeout period - specified in pcap_open_live() rather than blocking forever. But now - we use the new get_selectable_fd() API instead (thanks to Doug Hoyte - for the patch). - -o Eliminated Lex/Yacc requirement (I now ship the generated .c files). - This involved: - - o Changes to Makefile.in: - ---- libpcap-0.9.7/Makefile.in 2007-07-23 21:35:15.000000000 -0500 -+++ libpcap/Makefile.in 2007-08-25 17:37:07.000000000 -0500 -@@ -63,8 +63,8 @@ RANLIB = @RANLIB@ - # used by the generated parser. This allows programs to use lex/yacc - # and link against libpcap. If you don't have flex or bison, get them. - # --LEX = @V_LEX@ --YACC = @V_YACC@ -+LEX = flex -+YACC = yacc - - # Explicitly define compilation rule since SunOS 4's make doesn't like gcc. - # Also, gcc does not remove the .o before forking 'as', which can be a -@@ -97,7 +97,7 @@ TAGHDR = \ - TAGFILES = \ - $(SRC) $(HDR) $(TAGHDR) - --CLEANFILES = $(OBJ) libpcap.a $(GENSRC) $(GENHDR) lex.yy.c -+CLEANFILES = $(OBJ) libpcap.a version.c lex.yy.c - - all: libpcap.a - - o Ripped LEX/YACC detection code from configure.ac: - ---- libpcap-0.9.7/configure.in 2007-07-05 08:56:00.000000000 -0500 -+++ libpcap/configure.ac 2007-08-25 17:37:22.000000000 -0500 -@@ -703,24 +703,6 @@ if test "$V_PCAP" = septel -a "$ac_cv_lb - 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 -- - DYEXT="so" - case "$host_os" in - -@@ -803,11 +818,9 @@ AC_SUBST(V_CCOPT) - AC_SUBST(V_DEFS) - AC_SUBST(V_INCLS) - AC_SUBST(V_LIBS) --AC_SUBST(V_LEX) - AC_SUBST(V_PCAP) - AC_SUBST(V_FINDALLDEVS) - AC_SUBST(V_RANLIB) --AC_SUBST(V_YACC) - AC_SUBST(SSRC) - AC_SUBST(DYEXT) - AC_SUBST(DAGLIBS) + # Standard CFLAGS + # -CFLAGS = $(CCOPT) $(INCLS) $(DEFS) + # +CFLAGS = @CFLAGS@ $(CCOPT) $(INCLS) $(DEFS) + # + # INSTALL = @INSTALL@ + # INSTALL_PROGRAM = @INSTALL_PROGRAM@ o The following patch removes some code that apparently causes libpcap on Solaris to wait for 64K chunks before returning in some cases, regardless of the timeout values. Problem report and original patch came from Ben Harris (bjh21(a)cam.ac.uk) ---- libpcap-0.9.7/pcap-dlpi.c 2006-09-19 14:26:25.000000000 -0500 -+++ libpcap/pcap-dlpi.c 2007-08-25 17:10:28.000000000 -0500 -@@ -902,17 +902,6 @@ pcap_open_live(const char *device, int s - goto bad; - } - } +--- dlpisubs.c.orig 2009-10-27 10:24:45.000000000 -0600 ++++ dlpisubs.c 2009-10-27 10:24:49.000000000 -0600 +@@ -291,14 +291,6 @@ + } + } + +- /* Set the chunk length. */ +- chunksize = CHUNKSIZE; +- if (strioctl(p->fd, SBIOCSCHUNK, sizeof(chunksize), (char *)&chunksize) +- != 0) { +- pcap_stream_err("SBIOCSCHUNKP", errno, p->errbuf); +- retv = -1; +- } - -- /* -- ** Set the chunk length. -- */ -- chunksize = CHUNKSIZE; -- if (strioctl(p->fd, SBIOCSCHUNK, sizeof(chunksize), (char *)&chunksize) -- != 0) { -- snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCSCHUNKP: %s", -- pcap_strerror(errno)); -- goto bad; -- } - #endif - - /* - -o Changed the configure.ac to enable -fno-strict-aliasing when GCC 4+ -is in use. Here is that patch: - ---- libpcap-0.9.7/configure.in 2007-07-05 08:56:00.000000000 -0500 -+++ libpcap/configure.ac 2007-08-25 17:12:49.000000000 -0500 -@@ -790,6 +790,39 @@ AC_LBL_HP_PPA_INFO_T_DL_MODULE_ID_1 - - AC_LBL_UNALIGNED_ACCESS - -+pcap_gcc_major_version=0 -+AC_MSG_CHECKING([whether the compiler is gcc 4 or greater]) -+if test x"$GCC" = xno; then -+ AC_MSG_RESULT([no]) -+else -+ # new major versions must be added here -+ case `$CC --version | sed -e 's,\..*,.,' -e q` in -+ *4.) -+ pcap_gcc_major_version=4 -+ ;; -+ *3.) -+ pcap_gcc_major_version=3 -+ ;; -+ *2.) -+ pcap_gcc_major_version=2 -+ ;; -+ *1.) -+ pcap_gcc_major_version=1 -+ ;; -+ esac -+ if test "$pcap_gcc_major_version" -ge 4; then -+ AC_MSG_RESULT([yes]) -+ else -+ AC_MSG_RESULT([no - $pcap_gcc_major_version ; $CC ; $GCC]) -+ fi -+fi -+ -+# Remember that all following tests will run with this CXXFLAGS by default -+if test "$pcap_gcc_major_version" -ge 4; then -+ V_CCOPT="$V_CCOPT -fno-strict-aliasing" -+fi -+ -+ - # - # Makefile.in includes rules to generate version.h, so we assume - # that it will be generated if autoconf is used. - -o Ran autoconf to regenerate configure (I ship those with the Nmap - tarball rather than generating them at build time). - -o Removed config.sub, config.guess, and install-sh. These files are found in - the parent (i.e., Nmap's) directory. + return (retv); + } + #endif /* HAVE_SYS_BUFMOD_H */ diff --git a/libpcap/README b/libpcap/README index 90571a150..ee1a14186 100644 --- a/libpcap/README +++ b/libpcap/README @@ -1,20 +1,22 @@ -@(#) $Header: /tcpdump/master/libpcap/README,v 1.30 2004/10/12 02:02:28 guy Exp $ (LBL) +@(#) $Header: /tcpdump/master/libpcap/README,v 1.30.4.3 2008-10-17 10:39:20 ken Exp $ (LBL) -LIBPCAP 0.9 -Now maintained by "The Tcpdump Group" -See www.tcpdump.org +LIBPCAP 1.0.0 -Please send inquiries/comments/reports to tcpdump-workers@tcpdump.org +www.tcpdump.org + +Please send inquiries/comments/reports to: + tcpdump-workers@lists.tcpdump.org Anonymous CVS is available via: cvs -d :pserver:tcpdump@cvs.tcpdump.org:/tcpdump/master login (password "anoncvs") cvs -d :pserver:tcpdump@cvs.tcpdump.org:/tcpdump/master checkout libpcap -Version 0.9 of LIBPCAP can be retrieved with the CVS tag "libpcap_0_9rel1": - cvs -d :pserver:tcpdump@cvs.tcpdump.org:/tcpdump/master checkout -r libpcap_0_9rel1 libpcap +Version 1.0.0 of LIBPCAP can be retrieved with the CVS tag "libpcap_1_0": + cvs -d :pserver:tcpdump@cvs.tcpdump.org:/tcpdump/master checkout -r libpcap_1_0 libpcap -Please send patches against the master copy to patches@tcpdump.org. +Please submit patches against the master copy to the libpcap project on +sourceforge.net. formerly from Lawrence Berkeley National Laboratory Network Research Group @@ -30,8 +32,6 @@ 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. -Note well: this interface is new and is likely to change. - 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 @@ -77,16 +77,28 @@ 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 (and OS X). + +It sets the soname of the library to "libpcap.so.1"; this is what it +should be, *NOT* libpcap.so.1.0 or libpcap.so.1.0.0 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@tcpdump.org". Bugs, support requests, -and feature requests may also be submitted on the SourceForge site for -libpcap at +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 http://sourceforge.net/projects/libpcap/ Source code contributions, etc. should be sent to the email address -"patches@tcpdump.org", or submitted as patches on the SourceForge site -for libpcap. +submitted as patches on the SourceForge site for libpcap. Current versions can be found at www.tcpdump.org, or the SourceForge site for libpcap. diff --git a/libpcap/README.aix b/libpcap/README.aix index dcddb6156..b32fa5868 100644 --- a/libpcap/README.aix +++ b/libpcap/README.aix @@ -13,14 +13,17 @@ Using BPF: (2) If libpcap doesn't compile on your machine when configured to use BPF, or if the workarounds fail to make it work correctly, you - should send to tcpdump-workers@tcpdump.org a detailed bug report (if - the compile fails, send us the compile error messages; if it - compiles but fails to work correctly, send us as detailed as + should send to tcpdump-workers@lists.tcpdump.org a detailed bug + report (if the compile fails, send us the compile error messages; + if it compiles but fails to work correctly, send us as detailed as possible a description of the symptoms, including indications of the network link-layer type being wrong or time stamps being wrong). - If you fix the problems yourself, please send to patches@tcpdump.org - a patch, so we can incorporate them into the next release. + If you fix the problems yourself, please submit a patch to + + http://sourceforge.net/projects/libpcap/ + + so we can incorporate them into the next release. If you don't fix the problems yourself, you can, as a workaround, make libpcap use DLPI instead of BPF. diff --git a/libpcap/README.macosx b/libpcap/README.macosx index 25794d885..cfda4b867 100644 --- a/libpcap/README.macosx +++ b/libpcap/README.macosx @@ -17,12 +17,17 @@ devfs is based on an older (non-default) FreeBSD devfs, and that version of devfs cannot be configured to set the permissions and/or ownership of those devices. -Therefore, we supply a "startup item" for OS X that will change the -ownership of the BPF devices so that the "admin" group owns them, and -will change the permission of the BPF devices to rw-rw----, so that all -users in the "admin" group - i.e., all users with "Allow user to -administer this computer" turned on - have both read and write access to -them. +Therefore, we supply: + + a "startup item" for older versions of Mac OS X; + + a launchd daemon for Tiger and later versions of Mac OS X; + +Both of them will change the ownership of the BPF devices so that the +"admin" group owns them, and will change the permission of the BPF +devices to rw-rw----, so that all users in the "admin" group - i.e., all +users with "Allow user to administer this computer" turned on - have +both read and write access to them. The startup item is in the ChmodBPF directory in the source tree. A /Library/StartupItems directory should be created if it doesn't already @@ -30,7 +35,28 @@ exist, and the ChmodBPF directory should be copied to the /Library/StartupItems directory (copy the entire directory, so that there's a /Library/StartupItems/ChmodBPF directory, containing all the files in the source tree's ChmodBPF directory; don't copy the individual -items in that directory to /Library/StartupItems). +items in that directory to /Library/StartupItems). The ChmodBPF +directory, and all files under it, must be owned by root. Installing +the files won't immediately cause the startup item to be executed; it +will be executed on the next reboot. To change the permissions before +the reboot, run + + sudo SystemStarter start ChmodBPF + +The launchd daemon is the chmod_bpf script, plus the +org.tcpdump.chmod_bpf.plist launchd plist file. chmod_bpf should be +installed in /usr/local/bin/chmod_bpf, and org.tcpdump.chmod_bpf.plist +should be installed in /Library/LaunchDaemons. chmod_bpf, and +org.tcpdump.chmod_bpf.plist, must be owned by root. Installing the +script and plist file won't immediately cause the script to be executed; +it will be executed on the next reboot. To change the permissions +before the reboot, run + + sudo /usr/local/bin/chmod_bpf + +or + + sudo launchctl load /Library/LaunchDaemons/org.tcpdump.chmod_bpf.plist If you want to give a particular user permission to access the BPF devices, rather than giving all administrative users permission to diff --git a/libpcap/README.sita b/libpcap/README.sita new file mode 100644 index 000000000..ee7a42684 --- /dev/null +++ b/libpcap/README.sita @@ -0,0 +1,64 @@ +The following instructions apply if you have a Linux platform and want +libpcap to support the 'ACN' WAN/LAN router product from from SITA +(http://www.sita.aero) + +This might also work on non-Linux Unix-compatible platforms, but that +has not been tested. + +See also the libpcap INSTALL.txt file for further libpcap configuration +options. + +These additions/extensions have been made to PCAP to allow it to +capture packets from a SITA ACN device (and potentially others). + +To enable its support you need to ensure that the distribution has +a correct configure.in file; that can be created if neccessay by +using the normal autoconf procedure of: + +aclocal +autoconf +autoheader +automake + +Then run configure with the 'sita' option: + +./configure --with-sita + +Applications built with libpcap configured in this way will only detect SITA +ACN interfaces and will not capture from the native OS packet stream. + +The SITA extension provides a remote datascope operation for capturing +both WAN and LAN protocols. It effectively splits the operation of +PCAP into two halves. The top layer performs the majority of the +work, but interfaces via a TCP session to remote agents that +provide the lower layer functionality of actual sniffing and +filtering. More detailed information regarding the functions and +inter-device protocol and naming conventions are described in detail +in 'pcap-sita.html'. + +pcap_findalldevs() reads the local system's /etc/hosts file looking +for host names that match the format of IOP type devices. ie. aaa_I_x_y +and then queries each associated IP address for a list of its WAN and +LAN devices. The local system the aggregates the lists obtained from +each IOP, sorts it, and provides it (to Wireshark et.al) as the +list of monitorable interfaces. + +Once a valid interface has been selected, pcap_open() is called +which opens a TCP session (to a well known port) on the target IOP +and tells it to start monitoring. + +All captured packets are then forwarded across that TCP session +back to the local 'top layer' for forwarding to the actual +sniffing program (wireshark...) + +Note that the DLT_SITA link-layer type includes a proprietary header +that is documented as part of the SITA dissector of Wireshark and is +also described in 'pcap-sita.html' for posterity sake. + +That header provides: +- Packet direction (in/out) (1 octet) +- Link layer hardware signal status (1 octet) +- Transmit/Receive error status (2 octets) +- Encapsulated WAN protocol ID (1 octet) + + diff --git a/libpcap/VERSION b/libpcap/VERSION index c81aa44af..3eefcb9dd 100644 --- a/libpcap/VERSION +++ b/libpcap/VERSION @@ -1 +1 @@ -0.9.7 +1.0.0 diff --git a/libpcap/aclocal.m4 b/libpcap/aclocal.m4 index 16e1d558b..5ceb076c9 100644 --- a/libpcap/aclocal.m4 +++ b/libpcap/aclocal.m4 @@ -1,4 +1,4 @@ -dnl @(#) $Header: /tcpdump/master/libpcap/aclocal.m4,v 1.85.2.1 2005/04/21 03:42:09 guy Exp $ (LBL) +dnl @(#) $Header: /tcpdump/master/libpcap/aclocal.m4,v 1.86.2.6 2008-09-28 17:13:37 guy Exp $ (LBL) dnl dnl Copyright (c) 1995, 1996, 1997, 1998 dnl The Regents of the University of California. All rights reserved. @@ -57,7 +57,7 @@ AC_DEFUN(AC_LBL_C_INIT, LBL_CFLAGS="$CFLAGS" fi if test -z "$CC" ; then - case "$target_os" in + case "$host_os" in bsdi*) AC_CHECK_PROG(SHLICC2, shlicc2, yes, no) @@ -76,7 +76,7 @@ AC_DEFUN(AC_LBL_C_INIT, if test "$GCC" = yes ; then if test "$SHLICC2" = yes ; then ac_cv_lbl_gcc_vers=2 - $1="-g -O2" + $1="-O2" else AC_MSG_CHECKING(gcc version) AC_CACHE_VAL(ac_cv_lbl_gcc_vers, @@ -87,7 +87,7 @@ AC_DEFUN(AC_LBL_C_INIT, -e 's/\..*//'`) AC_MSG_RESULT($ac_cv_lbl_gcc_vers) if test $ac_cv_lbl_gcc_vers -gt 1 ; then - $1="-g -O2" + $1="-O2" fi fi else @@ -100,7 +100,7 @@ AC_DEFUN(AC_LBL_C_INIT, ac_cv_lbl_cc_ansi_prototypes=no)) AC_MSG_RESULT($ac_cv_lbl_cc_ansi_prototypes) if test $ac_cv_lbl_cc_ansi_prototypes = no ; then - case "$target_os" in + case "$host_os" in hpux*) AC_MSG_CHECKING(for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE)) @@ -129,7 +129,7 @@ AC_DEFUN(AC_LBL_C_INIT, $2="$$2 -I/usr/local/include" LDFLAGS="$LDFLAGS -L/usr/local/lib" - case "$target_os" in + case "$host_os" in irix*) V_CCOPT="$V_CCOPT -xansi -signed -g3" @@ -269,7 +269,7 @@ AC_DEFUN(AC_LBL_LIBPCAP, AC_MSG_RESULT($libpcap) fi LIBS="$libpcap $LIBS" - case "$target_os" in + case "$host_os" in aix*) pseexe="/lib/pse.exp" @@ -301,7 +301,7 @@ AC_DEFUN(AC_LBL_TYPE_SIGNAL, else AC_DEFINE(RETSIGVAL,(0),[return value of signal handlers]) fi - case "$target_os" in + case "$host_os" in irix*) AC_DEFINE(_BSD_SIGNALS,1,[get BSD semantics on Irix]) @@ -627,7 +627,7 @@ AC_DEFUN(AC_LBL_UNALIGNED_ACCESS, # know it does work, and have the script just fail on other # cpu types and update it when such a failure occurs. # - alpha*|arm*|hp*|mips*|sh*|sparc*|ia64|nv1) + alpha*|arm*|bfin*|hp*|mips*|sh*|sparc*|ia64|nv1) ac_cv_lbl_unaligned_fail=yes ;; @@ -682,7 +682,7 @@ EOF dnl dnl If using gcc and the file .devel exists: dnl Compile with -g (if supported) and -Wall -dnl If using gcc 2, do extra prototype checking +dnl If using gcc 2 or later, do extra prototype checking dnl If an os prototype include exists, symlink os-proto.h to it dnl dnl usage: @@ -712,7 +712,7 @@ AC_DEFUN(AC_LBL_DEVEL, fi fi else - case "$target_os" in + case "$host_os" in irix6*) V_CCOPT="$V_CCOPT -n32" @@ -722,7 +722,7 @@ AC_DEFUN(AC_LBL_DEVEL, ;; esac fi - os=`echo $target_os | sed -e 's/\([[0-9]][[0-9]]*\)[[^0-9]].*$/\1/'` + 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 @@ -746,6 +746,11 @@ dnl results: dnl dnl LIBS dnl +dnl XXX - "AC_LBL_LIBRARY_NET" was redone to use "AC_SEARCH_LIBS" +dnl rather than "AC_LBL_CHECK_LIB", so this isn't used any more. +dnl We keep it around for reference purposes in case it's ever +dnl useful in the future. +dnl define(AC_LBL_CHECK_LIB, [AC_MSG_CHECKING([for $2 in -l$1]) @@ -898,3 +903,59 @@ AC_DEFUN(AC_LBL_TPACKET_STATS, if test $ac_cv_lbl_tpacket_stats = yes; then AC_DEFINE(HAVE_TPACKET_STATS,1,[if if_packet.h has tpacket_stats defined]) fi]) + +dnl +dnl Checks to see if the tpacket_auxdata struct has a tp_vlan_tci member. +dnl +dnl usage: +dnl +dnl AC_LBL_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI +dnl +dnl results: +dnl +dnl HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI (defined) +dnl +dnl NOTE: any compile failure means we conclude that it doesn't have +dnl that member, so if we don't have tpacket_auxdata, we conclude it +dnl doesn't have that member (which is OK, as either we won't be using +dnl code that would use that member, or we wouldn't compile in any case). +dnl +AC_DEFUN(AC_LBL_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI, + [AC_MSG_CHECKING(if tpacket_auxdata struct has tp_vlan_tci member) + AC_CACHE_VAL(ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1, + AC_TRY_COMPILE([ +# include ], + [u_int i = sizeof(((struct tpacket_auxdata *)0)->tp_vlan_tci)], + ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci=yes, + ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci=no)) + AC_MSG_RESULT($ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci) + if test $ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci = yes ; then + AC_DEFINE(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI,1,[if tp_vlan_tci exists]) + fi]) + +dnl +dnl Checks to see if Solaris has the dl_passive_req_t struct defined +dnl in . +dnl +dnl usage: +dnl +dnl AC_LBL_DL_PASSIVE_REQ_T +dnl +dnl results: +dnl +dnl HAVE_DLPI_PASSIVE (defined) +dnl +AC_DEFUN(AC_LBL_DL_PASSIVE_REQ_T, + [AC_MSG_CHECKING(if dl_passive_req_t struct exists) + AC_CACHE_VAL(ac_cv_lbl_has_dl_passive_req_t, + AC_TRY_COMPILE([ +# include +# include ], + [u_int i = sizeof(dl_passive_req_t)], + ac_cv_lbl_has_dl_passive_req_t=yes, + ac_cv_lbl_has_dl_passive_req_t=no)) + AC_MSG_RESULT($ac_cv_lbl_has_dl_passive_req_t) + if test $ac_cv_lbl_has_dl_passive_req_t = yes ; then + AC_DEFINE(HAVE_DLPI_PASSIVE,1,[if passive_req_t primitive + exists]) + fi]) diff --git a/libpcap/atmuni31.h b/libpcap/atmuni31.h index 877ed6879..11242b8bf 100644 --- a/libpcap/atmuni31.h +++ b/libpcap/atmuni31.h @@ -29,18 +29,18 @@ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * - * @(#) $Header: /tcpdump/master/libpcap/atmuni31.h,v 1.1 2002/07/11 09:06:32 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/atmuni31.h,v 1.1.6.2 2007/10/22 19:30:14 guy Exp $ (LBL) */ /* Based on UNI3.1 standard by ATM Forum */ /* ATM traffic types based on VPI=0 and (the following VCI */ -#define PPC 0x05 /* Point-to-point signal msg */ -#define BCC 0x02 /* Broadcast signal msg */ -#define OAMF4SC 0x03 /* Segment OAM F4 flow cell */ -#define OAMF4EC 0x04 /* End-to-end OAM F4 flow cell */ -#define METAC 0x01 /* Meta signal msg */ -#define ILMIC 0x10 /* ILMI msg */ +#define VCI_PPC 0x05 /* Point-to-point signal msg */ +#define VCI_BCC 0x02 /* Broadcast signal msg */ +#define VCI_OAMF4SC 0x03 /* Segment OAM F4 flow cell */ +#define VCI_OAMF4EC 0x04 /* End-to-end OAM F4 flow cell */ +#define VCI_METAC 0x01 /* Meta signal msg */ +#define VCI_ILMIC 0x10 /* ILMI msg */ /* Q.2931 signalling messages */ #define CALL_PROCEED 0x02 /* call proceeding */ diff --git a/libpcap/bpf/net/bpf_filter.c b/libpcap/bpf/net/bpf_filter.c index 40df32a8b..a2733d1b1 100644 --- a/libpcap/bpf/net/bpf_filter.c +++ b/libpcap/bpf/net/bpf_filter.c @@ -40,7 +40,7 @@ #if !(defined(lint) || defined(KERNEL) || defined(_KERNEL)) static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/bpf/net/bpf_filter.c,v 1.44 2003/11/15 23:24:07 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/bpf/net/bpf_filter.c,v 1.45.2.1 2008/01/02 04:22:16 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -71,7 +71,7 @@ static const char rcsid[] _U_ = #endif /* WIN32 */ -#include +#include #if !defined(KERNEL) && !defined(_KERNEL) #include @@ -200,8 +200,8 @@ m_xhalf(m, k, err) */ u_int bpf_filter(pc, p, wirelen, buflen) - register struct bpf_insn *pc; - register u_char *p; + register const struct bpf_insn *pc; + register const u_char *p; u_int wirelen; register u_int buflen; { @@ -512,54 +512,155 @@ bpf_filter(pc, p, wirelen, buflen) } } - /* * Return true if the 'fcode' is a valid filter program. * The constraints are that each jump be forward and to a valid - * code. The code must terminate with either an accept or reject. - * 'valid' is an array for use by the routine (it must be at least - * 'len' bytes long). + * code, that memory accesses are within valid ranges (to the + * extent that this can be checked statically; loads of packet + * data have to be, and are, also checked at run time), and that + * the code terminates with either an accept or reject. * * The kernel needs to be able to verify an application's filter code. * Otherwise, a bogus program could easily crash the system. */ int bpf_validate(f, len) - struct bpf_insn *f; + const struct bpf_insn *f; int len; { - register int i; - register struct bpf_insn *p; + u_int i, from; + const struct bpf_insn *p; + + if (len < 1) + return 0; + /* + * There's no maximum program length in userland. + */ +#if defined(KERNEL) || defined(_KERNEL) + if (len > BPF_MAXINSNS) + return 0; +#endif for (i = 0; i < len; ++i) { - /* - * Check that that jumps are forward, and within - * the code block. - */ p = &f[i]; - if (BPF_CLASS(p->code) == BPF_JMP) { - register int from = i + 1; - - if (BPF_OP(p->code) == BPF_JA) { - if (from + p->k >= (unsigned)len) - return 0; - } - else if (from + p->jt >= len || from + p->jf >= len) - return 0; - } + switch (BPF_CLASS(p->code)) { /* * Check that memory operations use valid addresses. */ - if ((BPF_CLASS(p->code) == BPF_ST || - (BPF_CLASS(p->code) == BPF_LD && - (p->code & 0xe0) == BPF_MEM)) && - (p->k >= BPF_MEMWORDS || p->k < 0)) - return 0; - /* - * Check for constant division by 0. - */ - if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0) + case BPF_LD: + case BPF_LDX: + switch (BPF_MODE(p->code)) { + case BPF_IMM: + break; + case BPF_ABS: + case BPF_IND: + case BPF_MSH: + /* + * There's no maximum packet data size + * in userland. The runtime packet length + * check suffices. + */ +#if defined(KERNEL) || defined(_KERNEL) + /* + * More strict check with actual packet length + * is done runtime. + */ + if (p->k >= bpf_maxbufsize) + return 0; +#endif + break; + case BPF_MEM: + if (p->k >= BPF_MEMWORDS) + return 0; + break; + case BPF_LEN: + break; + default: + return 0; + } + break; + case BPF_ST: + case BPF_STX: + if (p->k >= BPF_MEMWORDS) + return 0; + break; + case BPF_ALU: + switch (BPF_OP(p->code)) { + case BPF_ADD: + case BPF_SUB: + case BPF_MUL: + case BPF_OR: + case BPF_AND: + case BPF_LSH: + case BPF_RSH: + case BPF_NEG: + break; + case BPF_DIV: + /* + * Check for constant division by 0. + */ + if (BPF_RVAL(p->code) == BPF_K && p->k == 0) + return 0; + break; + default: + return 0; + } + break; + case BPF_JMP: + /* + * Check that jumps are within the code block, + * and that unconditional branches don't go + * backwards as a result of an overflow. + * Unconditional branches have a 32-bit offset, + * so they could overflow; we check to make + * sure they don't. Conditional branches have + * an 8-bit offset, and the from address is <= + * BPF_MAXINSNS, and we assume that BPF_MAXINSNS + * is sufficiently small that adding 255 to it + * won't overflow. + * + * We know that len is <= BPF_MAXINSNS, and we + * assume that BPF_MAXINSNS is < the maximum size + * of a u_int, so that i + 1 doesn't overflow. + * + * For userland, we don't know that the from + * or len are <= BPF_MAXINSNS, but we know that + * from <= len, and, except on a 64-bit system, + * it's unlikely that len, if it truly reflects + * the size of the program we've been handed, + * will be anywhere near the maximum size of + * a u_int. We also don't check for backward + * branches, as we currently support them in + * userland for the protochain operation. + */ + from = i + 1; + switch (BPF_OP(p->code)) { + case BPF_JA: +#if defined(KERNEL) || defined(_KERNEL) + if (from + p->k < from || from + p->k >= len) +#else + if (from + p->k >= len) +#endif + return 0; + break; + case BPF_JEQ: + case BPF_JGT: + case BPF_JGE: + case BPF_JSET: + if (from + p->jt >= len || from + p->jf >= len) + return 0; + break; + default: + return 0; + } + break; + case BPF_RET: + break; + case BPF_MISC: + break; + default: return 0; + } } return BPF_CLASS(f[len - 1].code) == BPF_RET; } diff --git a/libpcap/bpf_dump.c b/libpcap/bpf_dump.c index 303602e20..5c0033dc5 100644 --- a/libpcap/bpf_dump.c +++ b/libpcap/bpf_dump.c @@ -20,7 +20,7 @@ */ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/bpf_dump.c,v 1.14 2003/11/15 23:23:57 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/bpf_dump.c,v 1.14.4.1 2008/01/02 04:22:16 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -31,9 +31,9 @@ static const char rcsid[] _U_ = #include void -bpf_dump(struct bpf_program *p, int option) +bpf_dump(const struct bpf_program *p, int option) { - struct bpf_insn *insn; + const struct bpf_insn *insn; int i; int n = p->bf_len; diff --git a/libpcap/bpf_image.c b/libpcap/bpf_image.c index 2e761289f..91f7cef43 100644 --- a/libpcap/bpf_image.c +++ b/libpcap/bpf_image.c @@ -21,7 +21,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/bpf_image.c,v 1.26.2.1 2007/06/11 09:52:04 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/bpf_image.c,v 1.27.2.1 2008/01/02 04:22:16 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -39,7 +39,7 @@ static const char rcsid[] _U_ = char * bpf_image(p, n) - struct bpf_insn *p; + const struct bpf_insn *p; int n; { int v; diff --git a/libpcap/chmod_bpf b/libpcap/chmod_bpf new file mode 100755 index 000000000..0a30d9930 --- /dev/null +++ b/libpcap/chmod_bpf @@ -0,0 +1,19 @@ +#! /bin/sh + +# +# Unfortunately, Mac OS X's devfs is based on the old FreeBSD +# one, not the current one, so there's no way to configure it +# to create BPF devices with particular owners or groups. +# This startup item will make it owned by the admin group, +# with permissions rw-rw----, so that anybody in the admin +# group can use programs that capture or send raw packets. +# +# Change this as appropriate for your site, e.g. to make +# it owned by a particular user without changing the permissions, +# so only that user and the super-user can capture or send raw +# packets, or give it the permissions rw-r-----, so that +# only the super-user can send raw packets but anybody in the +# admin group can capture packets. +# +chgrp admin /dev/bpf* +chmod g+rw /dev/bpf* diff --git a/libpcap/config.h.in b/libpcap/config.h.in index 0bc48dcab..403cbfa7b 100644 --- a/libpcap/config.h.in +++ b/libpcap/config.h.in @@ -19,6 +19,9 @@ /* 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 @@ -29,9 +32,15 @@ /* 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 @@ -44,9 +53,18 @@ /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H +/* if libdlpi exists */ +#undef HAVE_LIBDLPI + /* Define to 1 if you have the header file. */ #undef HAVE_LIMITS_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_WIRELESS_H + /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H @@ -56,12 +74,21 @@ /* 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_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 */ #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 /proc/net/dev */ #undef HAVE_PROC_NET_DEV @@ -77,6 +104,9 @@ /* if struct sockaddr_storage exists */ #undef HAVE_SOCKADDR_STORAGE +/* define if socklen_t is defined */ +#undef HAVE_SOCKLEN_T + /* On solaris */ #undef HAVE_SOLARIS @@ -131,6 +161,9 @@ /* 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__ @@ -140,6 +173,9 @@ /* if unaligned access fails */ #undef LBL_ALIGN +/* path for device for USB sniffing */ +#undef LINUX_USB_MON_DEV + /* Define to 1 if netinet/ether.h declares `ether_hostton' */ #undef NETINET_ETHER_H_DECLARES_ETHER_HOSTTON @@ -167,15 +203,33 @@ /* /dev/dlpi directory */ #undef PCAP_DEV_PREFIX +/* target host supports Bluetooth sniffing */ +#undef PCAP_SUPPORT_BT + +/* target host supports USB sniffing */ +#undef PCAP_SUPPORT_USB + +/* include ACN support */ +#undef SITA + /* 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 @@ -191,5 +245,8 @@ /* if we have u_int32_t */ #undef u_int32_t +/* if we have u_int64_t */ +#undef u_int64_t + /* if we have u_int8_t */ #undef u_int8_t diff --git a/libpcap/configure b/libpcap/configure index b648adcde..bd8da0bfd 100755 --- a/libpcap/configure +++ b/libpcap/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.ac Revision: 1.120.2.12 . +# From configure.in Revision: 1.138.2.22 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61. # @@ -675,6 +675,8 @@ CPP GREP EGREP LIBOBJS +V_LEX +V_YACC RANLIB V_CCOPT V_DEFS @@ -682,10 +684,16 @@ V_INCLS V_LIBS V_PCAP V_FINDALLDEVS -V_RANLIB SSRC DYEXT DAGLIBS +DEPLIBS +MAN_FILE_FORMATS +MAN_MISC_INFO +PCAP_SUPPORT_USB +USB_SRC +PCAP_SUPPORT_BT +BT_SRC INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA @@ -1273,8 +1281,9 @@ if test -n "$ac_init_help"; then Optional Features: --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 + --enable-ipv6 build IPv6-capable version [default=yes, if getaddrinfo available] --enable-optimizer-dbg build optimizer debugging code --enable-yydebug build parser debugging code @@ -1282,11 +1291,14 @@ 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 --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 + --without-flex don't use flex + --without-bison don't use bison Some influential environment variables: CC C compiler command @@ -1898,7 +1910,7 @@ fi LBL_CFLAGS="$CFLAGS" fi if test -z "$CC" ; then - case "$target_os" in + case "$host_os" in bsdi*) # Extract the first word of "shlicc2", so it can be a program name with args. @@ -2872,7 +2884,7 @@ 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="-g -O2" + V_CCOPT="-O2" else { echo "$as_me:$LINENO: checking gcc version" >&5 echo $ECHO_N "checking gcc version... $ECHO_C" >&6; } @@ -2889,7 +2901,7 @@ fi { 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="-g -O2" + V_CCOPT="-O2" fi fi else @@ -2945,7 +2957,7 @@ fi { 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 "$target_os" in + case "$host_os" in hpux*) { echo "$as_me:$LINENO: checking for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE)" >&5 @@ -3024,7 +3036,7 @@ echo "$as_me: error: see the INSTALL doc for more info" >&2;} V_INCLS="$V_INCLS -I/usr/local/include" LDFLAGS="$LDFLAGS -L/usr/local/lib" - case "$target_os" in + case "$host_os" in irix*) V_CCOPT="$V_CCOPT -xansi -signed -g3" @@ -3446,6 +3458,543 @@ cat >>confdefs.h <<\_ACEOF _ACEOF fi +{ echo "$as_me:$LINENO: checking for u_int64_t using $CC" >&5 +echo $ECHO_N "checking for u_int64_t using $CC... $ECHO_C" >&6; } + if test "${ac_cv_lbl_have_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. */ + +# include "confdefs.h" +# include +# if STDC_HEADERS +# include +# include +# endif +int +main () +{ +u_int64_t i + ; + 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_have_u_int64_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lbl_have_u_int64_t=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + + { echo "$as_me:$LINENO: result: $ac_cv_lbl_have_u_int64_t" >&5 +echo "${ECHO_T}$ac_cv_lbl_have_u_int64_t" >&6; } + if test $ac_cv_lbl_have_u_int64_t = no ; then + +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 + enableval=$enable_largefile; +fi + +if test "$enable_largefile" != no; then + + { 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 >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 + 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" + 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 +{ 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 + + { 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 >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 +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 >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 +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 +{ 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 -f conftest* + if test $ac_cv_sys_file_offset_bits = unknown; then + { 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 >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 +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 >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 +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 +{ 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 -f conftest* + fi +fi + +{ 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 >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +return fseeko (stdin, 0, 0) && (fseeko) (stdin, 0, 0); + ; + 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_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_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 +int +main () +{ +return fseeko (stdin, 0, 0) && (fseeko) (stdin, 0, 0); + ; + 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_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_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext + ac_cv_sys_largefile_source=unknown + break +done +fi +{ 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 -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 + +cat >>confdefs.h <<\_ACEOF +#define HAVE_FSEEKO 1 +_ACEOF + +fi + ac_ext=c ac_cpp='$CPP $CPPFLAGS' @@ -4227,6 +4776,126 @@ fi done +for ac_header in net/pfvar.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 + +#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 `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. + # + { 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 +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 + + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + +cat >>confdefs.h <<\_ACEOF +#define HAVE_PF_NAT_THROUGH_PF_NORDR 1 +_ACEOF + + +else + 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 as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` @@ -5558,6 +6227,26 @@ fi { 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 + withval=$with_sita; + +cat >>confdefs.h <<\_ACEOF +#define SITA 1 +_ACEOF + + { echo "$as_me:$LINENO: Enabling SITA ACN support" >&5 +echo "$as_me: Enabling SITA ACN support" >&6;} + V_PCAP=sita + V_FINDALLDEVS=sita + +else + if test -z "$with_pcap" && test "$cross_compiling" = yes; then { { 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;} @@ -5618,6 +6307,829 @@ fi { 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" + { 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 >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 +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 + 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_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ 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 + +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. + # + { 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 >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 +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 + 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 + + { 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 + { { 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. + # + { 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 + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DEV_DLPI 1 +_ACEOF + + else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + dir="/dev/dlpi" + { echo "$as_me:$LINENO: checking for $dir directory" >&5 +echo $ECHO_N "checking for $dir directory... $ECHO_C" >&6; } + if test -d $dir ; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + +cat >>confdefs.h <<_ACEOF +#define PCAP_DEV_PREFIX "$dir" +_ACEOF + + else + { 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. + # + { 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 >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 +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 + 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 + + { 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 + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DLPI_PASSIVE 1 +_ACEOF + + fi + ;; + +linux) + { echo "$as_me:$LINENO: checking Linux kernel version" >&5 +echo $ECHO_N "checking Linux kernel version... $ECHO_C" >&6; } + if test "$cross_compiling" = yes; then + if test "${ac_cv_linux_vers+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_linux_vers=unknown +fi + + else + if test "${ac_cv_linux_vers+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_linux_vers=`uname -r 2>&1 | \ + sed -n -e '$s/.* //' -e '$s/\..*//p'` +fi + + fi + { echo "$as_me:$LINENO: result: $ac_cv_linux_vers" >&5 +echo "${ECHO_T}$ac_cv_linux_vers" >&6; } + if test $ac_cv_linux_vers = unknown ; then + { { echo "$as_me:$LINENO: error: cannot determine linux version when cross-compiling" >&5 +echo "$as_me: error: cannot determine linux version when cross-compiling" >&2;} + { (exit 1); exit 1; }; } + fi + if test $ac_cv_linux_vers -lt 2 ; then + { { echo "$as_me:$LINENO: error: version 2 or higher required; see the INSTALL doc for more info" >&5 +echo "$as_me: error: version 2 or higher required; see the INSTALL doc for more info" >&2;} + { (exit 1); exit 1; }; } + fi + +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 + + +#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 `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + for ac_header in +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 `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + { 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 >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 +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 + 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 + + { 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 + +cat >>confdefs.h <<\_ACEOF +#define HAVE_TPACKET_STATS 1 +_ACEOF + + fi + { 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_dl_hp_ppa_info_t_has_dl_module_id_1+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 +int +main () +{ +u_int i = sizeof(((struct tpacket_auxdata *)0)->tp_vlan_tci) + ; + 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_linux_tpacket_auxdata_tp_vlan_tci=yes +else + 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 + + { 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 + +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 +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 `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + { 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 +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 + + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + +cat >>confdefs.h <<\_ACEOF +#define HAVE_ZEROCOPY_BPF 1 +_ACEOF + + +else + 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 + ;; + +dag) + V_DEFS="$V_DEFS -DDAG_ONLY" + ;; + +septel) + V_DEFS="$V_DEFS -DSEPTEL_ONLY" + ;; + +null) + { 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 # @@ -5876,142 +7388,7 @@ else # case "$V_PCAP" in - dlpi) - # - # This might be Solaris 8 or later, with - # SIOCGLIFCONF, or it might be some other OS - # or some older version of Solaris, with - # just SIOCGIFCONF. - # - { echo "$as_me:$LINENO: checking whether we have SIOCGLIFCONF" >&5 -echo $ECHO_N "checking whether we have SIOCGLIFCONF... $ECHO_C" >&6; } - if test "${ac_cv_lbl_have_siocglifconf+set}" = set; then - 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 - #include -int -main () -{ -ioctl(0, SIOCGLIFCONF, (char *)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_lbl_have_siocglifconf=yes -else - 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 - - { 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 - ;; - - *) - # - # 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 - -{ echo "$as_me:$LINENO: checking if --enable-ipv6 option is specified" >&5 -echo $ECHO_N "checking if --enable-ipv6 option is specified... $ECHO_C" >&6; } -# Check whether --enable-ipv6 was given. -if test "${enable_ipv6+set}" = set; then - enableval=$enable_ipv6; -fi - -if test "$enable_ipv6" = "yes"; then - -cat >>confdefs.h <<\_ACEOF -#define INET6 1 -_ACEOF - -fi -{ echo "$as_me:$LINENO: result: ${enable_ipv6-no}" >&5 -echo "${ECHO_T}${enable_ipv6-no}" >&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 - enableval=$enable_optimizer_dbg; -fi - -if test "$enable_optimizer_dbg" = "yes"; then - -cat >>confdefs.h <<\_ACEOF -#define BDEBUG 1 -_ACEOF - -fi -{ echo "$as_me:$LINENO: result: ${enable_optimizer_dbg-no}" >&5 -echo "${ECHO_T}${enable_optimizer_dbg-no}" >&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 - enableval=$enable_yydebug; -fi - -if test "$enable_yydebug" = "yes"; then - -cat >>confdefs.h <<\_ACEOF -#define YYDEBUG 1 -_ACEOF - -fi -{ echo "$as_me:$LINENO: result: ${enable_yydebug-no}" >&5 -echo "${ECHO_T}${enable_yydebug-no}" >&6; } - -case "$V_PCAP" in - -dlpi) + dlpi|libdlpi) for ac_header in sys/bufmod.h sys/dlpi_ext.h @@ -6153,71 +7530,15 @@ fi done - { 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 - { echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6; } - -cat >>confdefs.h <<\_ACEOF -#define HAVE_DEV_DLPI 1 -_ACEOF - - else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } - dir="/dev/dlpi" - { echo "$as_me:$LINENO: checking for $dir directory" >&5 -echo $ECHO_N "checking for $dir directory... $ECHO_C" >&6; } - if test -d $dir ; then - { echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6; } - -cat >>confdefs.h <<_ACEOF -#define PCAP_DEV_PREFIX "$dir" -_ACEOF - - else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } - fi - fi - ;; - -linux) - { echo "$as_me:$LINENO: checking Linux kernel version" >&5 -echo $ECHO_N "checking Linux kernel version... $ECHO_C" >&6; } - if test "$cross_compiling" = yes; then - if test "${ac_cv_linux_vers+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_linux_vers=unknown -fi - - else - if test "${ac_cv_linux_vers+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_linux_vers=`uname -r 2>&1 | \ - sed -n -e '$s/.* //' -e '$s/\..*//p'` -fi - - fi - { echo "$as_me:$LINENO: result: $ac_cv_linux_vers" >&5 -echo "${ECHO_T}$ac_cv_linux_vers" >&6; } - if test $ac_cv_linux_vers = unknown ; then - { { echo "$as_me:$LINENO: error: cannot determine linux version when cross-compiling" >&5 -echo "$as_me: error: cannot determine linux version when cross-compiling" >&2;} - { (exit 1); exit 1; }; } - fi - if test $ac_cv_linux_vers -lt 2 ; then - { { echo "$as_me:$LINENO: error: version 2 or higher required; see the INSTALL doc for more info" >&5 -echo "$as_me: error: version 2 or higher required; see the INSTALL doc for more info" >&2;} - { (exit 1); exit 1; }; } - fi - { 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 + # + # This might be Solaris 8 or later, with + # SIOCGLIFCONF, or it might be some other OS + # or some older version of Solaris, with + # just SIOCGIFCONF. + # + { echo "$as_me:$LINENO: checking whether we have SIOCGLIFCONF" >&5 +echo $ECHO_N "checking whether we have SIOCGLIFCONF... $ECHO_C" >&6; } + if test "${ac_cv_lbl_have_siocglifconf+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF @@ -6226,12 +7547,15 @@ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ - -# include +#include + #include + #include + #include + #include int main () { -struct tpacket_stats stats +ioctl(0, SIOCGLIFCONF, (char *)0); ; return 0; } @@ -6253,44 +7577,247 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then - ac_cv_lbl_tpacket_stats=yes + ac_cv_lbl_have_siocglifconf=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 - ac_cv_lbl_tpacket_stats=no + ac_cv_lbl_have_siocglifconf=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - { 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 + { 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 + + +{ 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 +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 + 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 cat >>confdefs.h <<\_ACEOF -#define HAVE_TPACKET_STATS 1 +#define HAVE_SOCKLEN_T 1 _ACEOF - fi - ;; +fi +{ echo "$as_me:$LINENO: result: $have_socklen_t" >&5 +echo "${ECHO_T}$have_socklen_t" >&6; } -dag) - V_DEFS="$V_DEFS -DDAG_ONLY" - ;; +# Check whether --enable-ipv6 was given. +if test "${enable_ipv6+set}" = set; then + enableval=$enable_ipv6; +else + enable_ipv6=ifavailable +fi -septel) - V_DEFS="$V_DEFS -DSEPTEL_ONLY" - ;; +if test "$enable_ipv6" != "no"; 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 -null) - { 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;} - ;; +/* 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. */ +#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 + { { 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 + +{ 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 + enableval=$enable_optimizer_dbg; +fi + +if test "$enable_optimizer_dbg" = "yes"; then + +cat >>confdefs.h <<\_ACEOF +#define BDEBUG 1 +_ACEOF + +fi +{ echo "$as_me:$LINENO: result: ${enable_optimizer_dbg-no}" >&5 +echo "${ECHO_T}${enable_optimizer_dbg-no}" >&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 + enableval=$enable_yydebug; +fi + +if test "$enable_yydebug" = "yes"; then + +cat >>confdefs.h <<\_ACEOF +#define YYDEBUG 1 +_ACEOF + +fi +{ echo "$as_me:$LINENO: result: ${enable_yydebug-no}" >&5 +echo "${ECHO_T}${enable_yydebug-no}" >&6; } { echo "$as_me:$LINENO: checking whether we have /proc/net/dev" >&5 echo $ECHO_N "checking whether we have /proc/net/dev... $ECHO_C" >&6; } @@ -6427,11 +7954,11 @@ echo $ECHO_N "checking dagapi.o... $ECHO_C" >&6; } dagapi_obj=$dag_lib_dir/dagapi.o elif test -r $dag_lib_dir/libdag.a; then # 2.5.x. - ar x $dag_lib_dir/libdag.a dagapi.o + ar x $dag_lib_dir/libdag.a dagapi.o 2>/dev/null if test -r ./dagapi.o; then dagapi_obj=./dagapi.o else - ar x $dag_lib_dir/libdag.a libdag_la-dagapi.o + ar x $dag_lib_dir/libdag.a libdag_la-dagapi.o 2>/dev/null if test -r ./libdag_la-dagapi.o; then dagapi_obj=./libdag_la-dagapi.o fi @@ -6461,11 +7988,11 @@ echo $ECHO_N "checking dagopts.o... $ECHO_C" >&6; } dagopts_obj=$dag_lib_dir/dagopts.o elif test -r $dag_lib_dir/libdag.a; then # 2.5.x. - ar x $dag_lib_dir/libdag.a dagopts.o + ar x $dag_lib_dir/libdag.a dagopts.o 2>/dev/null if test -r ./dagopts.o; then dagopts_obj=./dagopts.o else - ar x $dag_lib_dir/libdag.a libdag_la-dagopts.o + ar x $dag_lib_dir/libdag.a libdag_la-dagopts.o 2>/dev/null if test -r ./libdag_la-dagopts.o; then dagopts_obj=./libdag_la-dagopts.o fi @@ -6493,11 +8020,11 @@ echo $ECHO_N "checking dagreg.o... $ECHO_C" >&6; } dagreg_obj=$dag_lib_dir/dagreg.o elif test -r $dag_lib_dir/libdag.a; then # Extract from libdag.a. - ar x $dag_lib_dir/libdag.a dagreg.o + ar x $dag_lib_dir/libdag.a dagreg.o 2>/dev/null if test -r ./dagreg.o; then dagreg_obj=./dagreg.o else - ar x $dag_lib_dir/libdag.a libdag_la-dagreg.o + ar x $dag_lib_dir/libdag.a libdag_la-dagreg.o 2>/dev/null if test -r ./libdag_la-dagreg.o; then dagreg_obj=./libdag_la-dagreg.o fi @@ -6589,9 +8116,9 @@ fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dag_dag_attach_stream" >&5 echo "${ECHO_T}$ac_cv_lib_dag_dag_attach_stream" >&6; } if test $ac_cv_lib_dag_dag_attach_stream = yes; then - dag_version="2.5.x" + dag_streams="1" else - dag_version="2.4.x" + dag_streams="0" fi { echo "$as_me:$LINENO: checking for dag_get_erf_types in -ldag" >&5 @@ -6662,12 +8189,81 @@ cat >>confdefs.h <<\_ACEOF #define HAVE_DAG_GET_ERF_TYPES 1 _ACEOF +fi + + { 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 >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 +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 + 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_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ 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 + + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DAG_GET_STREAM_ERF_TYPES 1 +_ACEOF fi LDFLAGS=$saved_ldflags - if test "$dag_version" = 2.5.x; then + if test "$dag_streams" = 1; then cat >>confdefs.h <<\_ACEOF #define HAVE_DAG_STREAMS_API 1 @@ -6676,14 +8272,6 @@ _ACEOF DAGLIBS="-ldag" fi - # See if we can find a specific version string. - { echo "$as_me:$LINENO: checking the DAG API version" >&5 -echo $ECHO_N "checking the DAG API version... $ECHO_C" >&6; } - if test -r "$dag_root/VERSION"; then - dag_version="`cat $dag_root/VERSION`" - fi - { echo "$as_me:$LINENO: result: $dag_version" >&5 -echo "${ECHO_T}$dag_version" >&6; } cat >>confdefs.h <<\_ACEOF #define HAVE_DAG_API 1 @@ -6691,7 +8279,12 @@ _ACEOF fi +{ 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 + { 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. { { echo "$as_me:$LINENO: error: DAG API requested, but not found at $dag_root: use --without-dag" >&5 @@ -6706,6 +8299,9 @@ echo "$as_me: error: DAG API requested, but not found at $dag_root: use --withou 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 + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } fi @@ -6809,7 +8405,185 @@ echo "$as_me: error: Specifying the capture type as 'septel' requires the Septel fi + +# Check whether --with-flex was given. +if test "${with_flex+set}" = set; then + withval=$with_flex; +fi + + +# Check whether --with-bison was given. +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 +{ 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 + 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" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +V_LEX=$ac_cv_prog_V_LEX +if test -n "$V_LEX"; then + { echo "$as_me:$LINENO: result: $V_LEX" >&5 +echo "${ECHO_T}$V_LEX" >&6; } +else + { 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 + { 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 + + { 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" + { 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 +{ 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 + 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" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +V_YACC=$ac_cv_prog_V_YACC +if test -n "$V_YACC"; then + { echo "$as_me:$LINENO: result: $V_YACC" >&5 +echo "${ECHO_T}$V_YACC" >&6; } +else + { 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 + { 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_" + 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. + { 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 +{ 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 + { { 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 ." >&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 a.out/ELF convention for shared library names (".so"), and +# V7/BSD convention for man pages (file formats in section 5, +# miscellaneous info in section 7). +# DYEXT="so" +MAN_FILE_FORMATS=5 +MAN_MISC_INFO=7 case "$host_os" in aix*) @@ -6818,6 +8592,15 @@ cat >>confdefs.h <<\_ACEOF #define _SUN 1 _ACEOF + + # We need "-lodm" and "-lcfg", as libpcap requires them on + # AIX. + DEPLIBS="-lodm -lcfg" + ;; + +darwin*) + DYEXT="dylib" + V_CCOPT="$V_CCOPT -fno-common" ;; hpux9*) @@ -6826,12 +8609,30 @@ 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*) @@ -6840,6 +8641,32 @@ cat >>confdefs.h <<\_ACEOF #define HAVE_HPUX10_20_OR_LATER 1 _ACEOF + + # + # 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*) + V_CCOPT="$V_CCOPT -fPIC" + ;; + +osf*) + # + # Use System V conventions for man pages. + # + MAN_FILE_FORMATS=4 + MAN_MISC_INFO=5 ;; sinix*) @@ -6908,17 +8735,13 @@ cat >>confdefs.h <<\_ACEOF #define HAVE_SOLARIS 1 _ACEOF - ;; -darwin*) - DYEXT="dylib" - V_CCOPT="$V_CCOPT -fno-common" + # + # Use System V conventions for man pages. + # + MAN_FILE_FORMATS=4 + MAN_MISC_INFO=5 ;; - -linux*) - V_CCOPT="$V_CCOPT -fPIC" - ;; - esac if test -n "$ac_tool_prefix"; then @@ -7034,7 +8857,7 @@ rm -f os-proto.h fi fi else - case "$target_os" in + case "$host_os" in irix6*) V_CCOPT="$V_CCOPT -n32" @@ -7044,7 +8867,7 @@ rm -f os-proto.h ;; esac fi - os=`echo $target_os | sed -e 's/\([0-9][0-9]*\)[^0-9].*$/\1/'` + 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 @@ -7279,7 +9102,7 @@ else # know it does work, and have the script just fail on other # cpu types and update it when such a failure occurs. # - alpha*|arm*|hp*|mips*|sh*|sparc*|ia64|nv1) + alpha*|arm*|bfin*|hp*|mips*|sh*|sparc*|ia64|nv1) ac_cv_lbl_unaligned_fail=yes ;; @@ -7337,43 +9160,6 @@ _ACEOF fi -pcap_gcc_major_version=0 -{ echo "$as_me:$LINENO: checking whether the compiler is gcc 4 or greater" >&5 -echo $ECHO_N "checking whether the compiler is gcc 4 or greater... $ECHO_C" >&6; } -if test x"$GCC" = xno; then - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -else - # new major versions must be added here - case `$CC --version | sed -e 's,\..*,.,' -e q` in - *4.) - pcap_gcc_major_version=4 - ;; - *3.) - pcap_gcc_major_version=3 - ;; - *2.) - pcap_gcc_major_version=2 - ;; - *1.) - pcap_gcc_major_version=1 - ;; - esac - if test "$pcap_gcc_major_version" -ge 4; then - { echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6; } - else - { echo "$as_me:$LINENO: result: no - $pcap_gcc_major_version ; $CC ; $GCC" >&5 -echo "${ECHO_T}no - $pcap_gcc_major_version ; $CC ; $GCC" >&6; } - fi -fi - -# Remember that all following tests will run with this CXXFLAGS by default -if test "$pcap_gcc_major_version" -ge 4; then - V_CCOPT="$V_CCOPT -fno-strict-aliasing" -fi - - # # Makefile.in includes rules to generate version.h, so we assume # that it will be generated if autoconf is used. @@ -7398,6 +9184,196 @@ ln -s ${srcdir}/bpf/net net + + + + +{ 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*) + +cat >>confdefs.h <<\_ACEOF +#define PCAP_SUPPORT_USB 1 +_ACEOF + + USB_SRC=pcap-usb-linux.c + { 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 + + { 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;} + ;; +*) + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + ;; +esac + + + +case "$host_os" in +linux*) + 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 + +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 + { echo "$as_me:$LINENO: Bluetooth sniffing is supported" >&5 +echo "$as_me: Bluetooth sniffing is supported" >&6;} + +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 + + + ;; +*) + { echo "$as_me:$LINENO: no Bluetooth sniffing support" >&5 +echo "$as_me: no Bluetooth sniffing support" >&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: @@ -7482,7 +9458,7 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' ac_config_headers="$ac_config_headers config.h" -ac_config_files="$ac_config_files Makefile" +ac_config_files="$ac_config_files Makefile pcap-filter.manmisc pcap-linktype.manmisc pcap-savefile.manfile pcap.3pcap pcap_compile.3pcap pcap_datalink.3pcap pcap_dump_open.3pcap pcap_list_datalinks.3pcap pcap_open_dead.3pcap pcap_open_offline.3pcap" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -8039,6 +10015,16 @@ 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-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_open_dead.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_open_dead.3pcap" ;; + "pcap_open_offline.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_open_offline.3pcap" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} @@ -8161,6 +10147,8 @@ CPP!$CPP$ac_delim GREP!$GREP$ac_delim EGREP!$EGREP$ac_delim LIBOBJS!$LIBOBJS$ac_delim +V_LEX!$V_LEX$ac_delim +V_YACC!$V_YACC$ac_delim RANLIB!$RANLIB$ac_delim V_CCOPT!$V_CCOPT$ac_delim V_DEFS!$V_DEFS$ac_delim @@ -8168,17 +10156,23 @@ V_INCLS!$V_INCLS$ac_delim V_LIBS!$V_LIBS$ac_delim V_PCAP!$V_PCAP$ac_delim V_FINDALLDEVS!$V_FINDALLDEVS$ac_delim -V_RANLIB!$V_RANLIB$ac_delim SSRC!$SSRC$ac_delim DYEXT!$DYEXT$ac_delim DAGLIBS!$DAGLIBS$ac_delim +DEPLIBS!$DEPLIBS$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_BT!$PCAP_SUPPORT_BT$ac_delim +BT_SRC!$BT_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 - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 76; then + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 84; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 diff --git a/libpcap/configure.ac b/libpcap/configure.in similarity index 71% rename from libpcap/configure.ac rename to libpcap/configure.in index 82cfa4574..7d1230913 100644 --- a/libpcap/configure.ac +++ b/libpcap/configure.in @@ -1,4 +1,4 @@ -dnl @(#) $Header: /tcpdump/master/libpcap/configure.in,v 1.120.2.12 2007/06/15 17:57:26 guy Exp $ (LBL) +dnl @(#) $Header: /tcpdump/master/libpcap/configure.in,v 1.138.2.22 2008-10-24 07:30:18 guy Exp $ (LBL) dnl dnl Copyright (c) 1994, 1995, 1996, 1997 dnl The Regents of the University of California. All rights reserved. @@ -6,7 +6,7 @@ dnl dnl Process this file with autoconf to produce a configure script. dnl -AC_REVISION($Revision: 1.120.2.12 $) +AC_REVISION($Revision: 1.138.2.22 $) AC_PREREQ(2.50) AC_INIT(pcap.c) @@ -19,6 +19,13 @@ AC_C___ATTRIBUTE__ AC_LBL_CHECK_TYPE(u_int8_t, u_char) AC_LBL_CHECK_TYPE(u_int16_t, u_short) AC_LBL_CHECK_TYPE(u_int32_t, u_int) +AC_LBL_CHECK_TYPE(u_int64_t, unsigned long long) + +# +# Try to arrange for large file support. +# +AC_SYS_LARGEFILE +AC_FUNC_FSEEKO dnl dnl libpcap doesn't itself use ; however, the test program @@ -27,6 +34,27 @@ dnl test for it and set "HAVE_SYS_IOCCOM_H" if we have it, otherwise dnl "AC_LBL_FIXINCLUDES" won't work on some platforms such as Solaris. dnl AC_CHECK_HEADERS(sys/ioccom.h sys/sockio.h limits.h paths.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 @@ -169,6 +197,18 @@ if test "$enable_protochain" = "disabled"; then fi AC_MSG_RESULT(${enable_protochain}) +# +# SITA support is mutually exclusive with native capture support; +# "--with-sita" selects SITA support. +# +AC_ARG_WITH(sita, [ --with-sita include SITA support], +[ + AC_DEFINE(SITA,1,[include ACN support]) + AC_MSG_NOTICE(Enabling SITA ACN support) + V_PCAP=sita + V_FINDALLDEVS=sita +], +[ 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 @@ -224,6 +264,140 @@ else 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) + AC_MSG_CHECKING(Linux kernel version) + if test "$cross_compiling" = yes; then + AC_CACHE_VAL(ac_cv_linux_vers, + ac_cv_linux_vers=unknown) + else + AC_CACHE_VAL(ac_cv_linux_vers, + ac_cv_linux_vers=`uname -r 2>&1 | \ + sed -n -e '$s/.* //' -e '$s/\..*//p'`) + fi + AC_MSG_RESULT($ac_cv_linux_vers) + if test $ac_cv_linux_vers = unknown ; then + AC_MSG_ERROR(cannot determine linux version when cross-compiling) + fi + if test $ac_cv_linux_vers -lt 2 ; then + AC_MSG_ERROR(version 2 or higher required; see the INSTALL doc for more info) + fi + AC_CHECK_HEADERS(linux/wireless.h, [], [], + [ +#include +#include +#include + ]) + AC_CHECK_HEADERS() + 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)) + ;; + +dag) + V_DEFS="$V_DEFS -DDAG_ONLY" + ;; + +septel) + V_DEFS="$V_DEFS -DSEPTEL_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 @@ -270,7 +444,8 @@ else # case "$V_PCAP" in - dlpi) + 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 @@ -294,6 +469,10 @@ else else V_FINDALLDEVS=gifc fi + # + # Needed for common functions used by pcap-[dlpi,libdlpi].c + # + SSRC="dlpisubs.c" ;; *) @@ -307,13 +486,35 @@ else ;; esac]) fi +]) -AC_MSG_CHECKING(if --enable-ipv6 option is specified) -AC_ARG_ENABLE(ipv6, [ --enable-ipv6 build IPv6-capable version]) -if test "$enable_ipv6" = "yes"; then - AC_DEFINE(INET6,1,[IPv6]) +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, [ --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_RESULT(${enable_ipv6-no}) AC_MSG_CHECKING(whether to build optimizer debugging code) AC_ARG_ENABLE(optimizer-dbg, [ --enable-optimizer-dbg build optimizer debugging code]) @@ -329,62 +530,6 @@ if test "$enable_yydebug" = "yes"; then fi AC_MSG_RESULT(${enable_yydebug-no}) -case "$V_PCAP" in - -dlpi) - AC_CHECK_HEADERS(sys/bufmod.h sys/dlpi_ext.h) - 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 - ;; - -linux) - AC_MSG_CHECKING(Linux kernel version) - if test "$cross_compiling" = yes; then - AC_CACHE_VAL(ac_cv_linux_vers, - ac_cv_linux_vers=unknown) - else - AC_CACHE_VAL(ac_cv_linux_vers, - ac_cv_linux_vers=`uname -r 2>&1 | \ - sed -n -e '$s/.* //' -e '$s/\..*//p'`) - fi - AC_MSG_RESULT($ac_cv_linux_vers) - if test $ac_cv_linux_vers = unknown ; then - AC_MSG_ERROR(cannot determine linux version when cross-compiling) - fi - if test $ac_cv_linux_vers -lt 2 ; then - AC_MSG_ERROR(version 2 or higher required; see the INSTALL doc for more info) - fi - AC_LBL_TPACKET_STATS - ;; - -dag) - V_DEFS="$V_DEFS -DDAG_ONLY" - ;; - -septel) - V_DEFS="$V_DEFS -DSEPTEL_ONLY" - ;; - -null) - AC_MSG_WARN(cannot determine packet capture interface) - AC_MSG_WARN((see the INSTALL doc for more info)) - ;; - -esac - AC_MSG_CHECKING(whether we have /proc/net/dev) if test -r /proc/net/dev ; then ac_cv_lbl_proc_net_dev=yes @@ -495,11 +640,11 @@ if test $ac_cv_lbl_dag_api = yes; then dagapi_obj=$dag_lib_dir/dagapi.o elif test -r $dag_lib_dir/libdag.a; then # 2.5.x. - ar x $dag_lib_dir/libdag.a dagapi.o + ar x $dag_lib_dir/libdag.a dagapi.o 2>/dev/null if test -r ./dagapi.o; then dagapi_obj=./dagapi.o else - ar x $dag_lib_dir/libdag.a libdag_la-dagapi.o + ar x $dag_lib_dir/libdag.a libdag_la-dagapi.o 2>/dev/null if test -r ./libdag_la-dagapi.o; then dagapi_obj=./libdag_la-dagapi.o fi @@ -526,11 +671,11 @@ if test $ac_cv_lbl_dag_api = yes; then dagopts_obj=$dag_lib_dir/dagopts.o elif test -r $dag_lib_dir/libdag.a; then # 2.5.x. - ar x $dag_lib_dir/libdag.a dagopts.o + ar x $dag_lib_dir/libdag.a dagopts.o 2>/dev/null if test -r ./dagopts.o; then dagopts_obj=./dagopts.o else - ar x $dag_lib_dir/libdag.a libdag_la-dagopts.o + ar x $dag_lib_dir/libdag.a libdag_la-dagopts.o 2>/dev/null if test -r ./libdag_la-dagopts.o; then dagopts_obj=./libdag_la-dagopts.o fi @@ -555,11 +700,11 @@ if test $ac_cv_lbl_dag_api = yes; then dagreg_obj=$dag_lib_dir/dagreg.o elif test -r $dag_lib_dir/libdag.a; then # Extract from libdag.a. - ar x $dag_lib_dir/libdag.a dagreg.o + ar x $dag_lib_dir/libdag.a dagreg.o 2>/dev/null if test -r ./dagreg.o; then dagreg_obj=./dagreg.o else - ar x $dag_lib_dir/libdag.a libdag_la-dagreg.o + ar x $dag_lib_dir/libdag.a libdag_la-dagreg.o 2>/dev/null if test -r ./libdag_la-dagreg.o; then dagreg_obj=./libdag_la-dagreg.o fi @@ -587,27 +732,25 @@ if test $ac_cv_lbl_dag_api = yes; then # included if there's a found-action (arg 3). saved_ldflags=$LDFLAGS LDFLAGS="-L$dag_lib_dir" - AC_CHECK_LIB([dag], [dag_attach_stream], [dag_version="2.5.x"], [dag_version="2.4.x"]) + 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_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_version" = 2.5.x; then + if test "$dag_streams" = 1; then AC_DEFINE(HAVE_DAG_STREAMS_API, 1, [define if you have streams capable DAG API]) DAGLIBS="-ldag" fi - # See if we can find a specific version string. - AC_MSG_CHECKING([the DAG API version]) - if test -r "$dag_root/VERSION"; then - dag_version="`cat $dag_root/VERSION`" - fi - AC_MSG_RESULT([$dag_version]) AC_DEFINE(HAVE_DAG_API, 1, [define if you have the DAG API]) fi +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]) @@ -618,6 +761,8 @@ if test $ac_cv_lbl_dag_api = no; then # 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, [ --with-septel[[=DIR]] include Septel support (located in directory DIR, if supplied). [default=yes, on Linux, if present]], @@ -703,22 +848,74 @@ if test "$V_PCAP" = septel -a "$ac_cv_lbl_septel_api" = no; then 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 a.out/ELF convention for shared library names (".so"), and +# V7/BSD convention for man pages (file formats in section 5, +# miscellaneous info in section 7). +# DYEXT="so" +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]) + + # We need "-lodm" and "-lcfg", as libpcap requires them on + # AIX. + DEPLIBS="-lodm -lcfg" + ;; + +darwin*) + DYEXT="dylib" + V_CCOPT="$V_CCOPT -fno-common" ;; 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*) @@ -729,6 +926,32 @@ hpux*) 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]) + + # + # 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*) + V_CCOPT="$V_CCOPT -fPIC" + ;; + +osf*) + # + # Use System V conventions for man pages. + # + MAN_FILE_FORMATS=4 + MAN_MISC_INFO=5 ;; sinix*) @@ -747,17 +970,13 @@ sinix*) solaris*) AC_DEFINE(HAVE_SOLARIS,1,[On solaris]) - ;; -darwin*) - DYEXT="dylib" - V_CCOPT="$V_CCOPT -fno-common" + # + # Use System V conventions for man pages. + # + MAN_FILE_FORMATS=4 + MAN_MISC_INFO=5 ;; - -linux*) - V_CCOPT="$V_CCOPT -fPIC" - ;; - esac AC_PROG_RANLIB @@ -772,39 +991,6 @@ AC_LBL_HP_PPA_INFO_T_DL_MODULE_ID_1 AC_LBL_UNALIGNED_ACCESS -pcap_gcc_major_version=0 -AC_MSG_CHECKING([whether the compiler is gcc 4 or greater]) -if test x"$GCC" = xno; then - AC_MSG_RESULT([no]) -else - # new major versions must be added here - case `$CC --version | sed -e 's,\..*,.,' -e q` in - *4.) - pcap_gcc_major_version=4 - ;; - *3.) - pcap_gcc_major_version=3 - ;; - *2.) - pcap_gcc_major_version=2 - ;; - *1.) - pcap_gcc_major_version=1 - ;; - esac - if test "$pcap_gcc_major_version" -ge 4; then - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no - $pcap_gcc_major_version ; $CC ; $GCC]) - fi -fi - -# Remember that all following tests will run with this CXXFLAGS by default -if test "$pcap_gcc_major_version" -ge 4; then - V_CCOPT="$V_CCOPT -fno-strict-aliasing" -fi - - # # Makefile.in includes rules to generate version.h, so we assume # that it will be generated if autoconf is used. @@ -818,18 +1004,66 @@ AC_SUBST(V_CCOPT) AC_SUBST(V_DEFS) AC_SUBST(V_INCLS) AC_SUBST(V_LIBS) +AC_SUBST(V_LEX) AC_SUBST(V_PCAP) AC_SUBST(V_FINDALLDEVS) -AC_SUBST(V_RANLIB) +AC_SUBST(V_YACC) AC_SUBST(SSRC) AC_SUBST(DYEXT) AC_SUBST(DAGLIBS) +AC_SUBST(DEPLIBS) +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) + ;; +*) + AC_MSG_RESULT(no) + ;; +esac +AC_SUBST(PCAP_SUPPORT_USB) +AC_SUBST(USB_SRC) + +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) + ], + AC_MSG_NOTICE(Bluetooth sniffing is not supported; install bluez-lib devel to enable it) + ) + ;; +*) + AC_MSG_NOTICE(no Bluetooth sniffing support) + ;; +esac +AC_SUBST(PCAP_SUPPORT_BT) +AC_SUBST(BT_SRC) AC_PROG_INSTALL AC_CONFIG_HEADER(config.h) -AC_OUTPUT(Makefile) +AC_OUTPUT(Makefile pcap-filter.manmisc pcap-linktype.manmisc + pcap-savefile.manfile pcap.3pcap pcap_compile.3pcap + pcap_datalink.3pcap pcap_dump_open.3pcap + pcap_list_datalinks.3pcap pcap_open_dead.3pcap + pcap_open_offline.3pcap) if test -f .devel ; then make depend diff --git a/libpcap/dlpisubs.c b/libpcap/dlpisubs.c new file mode 100644 index 000000000..05ea4dd95 --- /dev/null +++ b/libpcap/dlpisubs.c @@ -0,0 +1,341 @@ +/* + * This code is derived from code formerly in pcap-dlpi.c, originally + * 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 . + */ + +/* + * This file contains dlpi/libdlpi related common functions used + * by pcap-[dlpi,libdlpi].c. + */ +#ifndef lint +static const char rcsid[] _U_ = + "@(#) $Header: /tcpdump/master/libpcap/dlpisubs.c,v 1.1.2.2 2008-04-04 19:39:05 guy Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_SYS_BUFMOD_H + /* + * Size of a bufmod chunk to pass upstream; that appears to be the + * biggest value to which you can set it, and setting it to that value + * (which is bigger than what appears to be the Solaris default of 8192) + * reduces the number of packet drops. + */ +#define CHUNKSIZE 65536 + + /* + * Size of the buffer to allocate for packet data we read; it must be + * large enough to hold a chunk. + */ +#define PKTBUFSIZE CHUNKSIZE + +#else /* HAVE_SYS_BUFMOD_H */ + + /* + * Size of the buffer to allocate for packet data we read; this is + * what the value used to be - there's no particular reason why it + * should be tied to MAXDLBUF, but we'll leave it as this for now. + */ +#define PKTBUFSIZE (MAXDLBUF * sizeof(bpf_u_int32)) + +#endif + +#include +#include +#ifdef HAVE_SYS_BUFMOD_H +#include +#endif +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "pcap-int.h" +#include "dlpisubs.h" + +static void pcap_stream_err(const char *, int, char *); + +/* + * Get the packet statistics. + */ +int +pcap_stats_dlpi(pcap_t *p, struct pcap_stat *ps) +{ + + /* + * "ps_recv" counts packets handed to the filter, not packets + * that passed the filter. As filtering is done in userland, + * this would not include packets dropped because we ran out + * of buffer space; in order to make this more like other + * platforms (Linux 2.4 and later, BSDs with BPF), where the + * "packets received" count includes packets received but dropped + * due to running out of buffer space, and to keep from confusing + * applications that, for example, compute packet drop percentages, + * we also make it count packets dropped by "bufmod" (otherwise we + * might run the risk of the packet drop count being bigger than + * the received-packet count). + * + * "ps_drop" counts packets dropped by "bufmod" because of + * flow control requirements or resource exhaustion; it doesn't + * count packets dropped by the interface driver, or packets + * dropped upstream. As filtering is done in userland, it counts + * packets regardless of whether they would've passed the filter. + * + * These statistics don't include packets not yet read from + * the kernel by libpcap, but they may include packets not + * yet read from libpcap by the application. + */ + *ps = p->md.stat; + + /* + * Add in the drop count, as per the above comment. + */ + ps->ps_recv += ps->ps_drop; + return (0); +} + +/* + * Loop through the packets and call the callback for each packet. + * Return the number of packets read. + */ +int +pcap_process_pkts(pcap_t *p, pcap_handler callback, u_char *user, + int count, u_char *bufp, int len) +{ + int n, caplen, origlen; + u_char *ep, *pk; + struct pcap_pkthdr pkthdr; +#ifdef HAVE_SYS_BUFMOD_H + struct sb_hdr *sbp; +#ifdef LBL_ALIGN + struct sb_hdr sbhdr; +#endif +#endif + + /* Loop through packets */ + ep = bufp + len; + n = 0; + +#ifdef HAVE_SYS_BUFMOD_H + while (bufp < 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 = bufp; + p->cc = ep - bufp; + return (n); + } + } +#ifdef LBL_ALIGN + if ((long)bufp & 3) { + sbp = &sbhdr; + memcpy(sbp, bufp, sizeof(*sbp)); + } else +#endif + sbp = (struct sb_hdr *)bufp; + p->md.stat.ps_drop = sbp->sbh_drops; + pk = bufp + sizeof(*sbp); + bufp += sbp->sbh_totlen; + origlen = sbp->sbh_origlen; + caplen = sbp->sbh_msglen; +#else + origlen = len; + caplen = min(p->snapshot, len); + pk = bufp; + bufp += caplen; +#endif + ++p->md.stat.ps_recv; + if (bpf_filter(p->fcode.bf_insns, pk, origlen, caplen)) { +#ifdef HAVE_SYS_BUFMOD_H + pkthdr.ts.tv_sec = sbp->sbh_timestamp.tv_sec; + pkthdr.ts.tv_usec = sbp->sbh_timestamp.tv_usec; +#else + (void) gettimeofday(&pkthdr.ts, NULL); +#endif + pkthdr.len = origlen; + pkthdr.caplen = caplen; + /* Insure caplen does not exceed snapshot */ + if (pkthdr.caplen > p->snapshot) + pkthdr.caplen = p->snapshot; + (*callback)(user, &pkthdr, pk); + if (++n >= count && count >= 0) { + p->cc = ep - bufp; + p->bp = bufp; + return (n); + } + } +#ifdef HAVE_SYS_BUFMOD_H + } +#endif + p->cc = 0; + return (n); +} + +/* + * Process the mac type. Returns -1 if no matching mac type found, otherwise 0. + */ +int +pcap_process_mactype(pcap_t *p, u_int mactype) +{ + int retv = 0; + + switch (mactype) { + + case DL_CSMACD: + case DL_ETHER: + p->linktype = DLT_EN10MB; + p->offset = 2; + /* + * This is (presumably) a real Ethernet capture; give it a + * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so + * that an application can let you choose it, in case you're + * capturing DOCSIS traffic that a Cisco Cable Modem + * Termination System is putting out onto an Ethernet (it + * doesn't put an Ethernet header onto the wire, it puts raw + * DOCSIS frames out on the wire inside the low-level + * Ethernet framing). + */ + p->dlt_list = (u_int *)malloc(sizeof(u_int) * 2); + /* + * If that fails, just leave the list empty. + */ + if (p->dlt_list != NULL) { + p->dlt_list[0] = DLT_EN10MB; + p->dlt_list[1] = DLT_DOCSIS; + p->dlt_count = 2; + } + break; + + case DL_FDDI: + p->linktype = DLT_FDDI; + p->offset = 3; + break; + + case DL_TPR: + /* XXX - what about DL_TPB? Is that Token Bus? */ + p->linktype = DLT_IEEE802; + p->offset = 2; + break; + +#ifdef HAVE_SOLARIS + case DL_IPATM: + p->linktype = DLT_SUNATM; + p->offset = 0; /* works for LANE and LLC encapsulation */ + break; +#endif + + default: + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "unknown mactype %u", + mactype); + retv = -1; + } + + return (retv); +} + +#ifdef HAVE_SYS_BUFMOD_H +/* + * Push and configure the buffer module. Returns -1 for error, otherwise 0. + */ +int +pcap_conf_bufmod(pcap_t *p, int snaplen, int timeout) +{ + int retv = 0; + + bpf_u_int32 ss, chunksize; + + /* Non-standard call to get the data nicely buffered. */ + if (ioctl(p->fd, I_PUSH, "bufmod") != 0) { + pcap_stream_err("I_PUSH bufmod", errno, p->errbuf); + retv = -1; + } + + ss = snaplen; + if (ss > 0 && + strioctl(p->fd, SBIOCSSNAP, sizeof(ss), (char *)&ss) != 0) { + pcap_stream_err("SBIOCSSNAP", errno, p->errbuf); + retv = -1; + } + + /* Set up the bufmod timeout. */ + if (timeout != 0) { + struct timeval to; + + to.tv_sec = timeout / 1000; + to.tv_usec = (timeout * 1000) % 1000000; + if (strioctl(p->fd, SBIOCSTIME, sizeof(to), (char *)&to) != 0) { + pcap_stream_err("SBIOCSTIME", errno, p->errbuf); + retv = -1; + } + } + + return (retv); +} +#endif /* HAVE_SYS_BUFMOD_H */ + +/* + * Allocate data buffer. Returns -1 if memory allocation fails, else 0. + */ +int +pcap_alloc_databuf(pcap_t *p) +{ + p->bufsize = PKTBUFSIZE; + p->buffer = (u_char *)malloc(p->bufsize + p->offset); + if (p->buffer == NULL) { + strlcpy(p->errbuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); + return (-1); + } + + return (0); +} + +/* + * Issue a STREAMS I_STR ioctl. Returns -1 on error, otherwise + * length of returned data on success. + */ +int +strioctl(int fd, int cmd, int len, char *dp) +{ + struct strioctl str; + int retv; + + str.ic_cmd = cmd; + str.ic_timout = -1; + str.ic_len = len; + str.ic_dp = dp; + if ((retv = ioctl(fd, I_STR, &str)) < 0) + return (retv); + + return (str.ic_len); +} + +/* + * Write stream error message to errbuf. + */ +static void +pcap_stream_err(const char *func, int err, char *errbuf) +{ + snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", func, pcap_strerror(err)); +} diff --git a/libpcap/dlpisubs.h b/libpcap/dlpisubs.h new file mode 100644 index 000000000..67acd292f --- /dev/null +++ b/libpcap/dlpisubs.h @@ -0,0 +1,28 @@ +/* + * @(#) $Header: /tcpdump/master/libpcap/dlpisubs.h,v 1.1.2.2 2008-04-04 19:39:05 guy Exp $ + */ + +#ifndef dlpisubs_h +#define dlpisubs_h + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Functions used by dlpisubs.c. + */ +int pcap_stats_dlpi(pcap_t *, struct pcap_stat *); +int pcap_process_pkts(pcap_t *, pcap_handler, u_char *, int, u_char *, int); +int pcap_process_mactype(pcap_t *, u_int); +#ifdef HAVE_SYS_BUFMOD_H +int pcap_conf_bufmod(pcap_t *, int, int); +#endif +int pcap_alloc_databuf(pcap_t *); +int strioctl(int, int, int, char *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libpcap/doc/pcap.html b/libpcap/doc/pcap.html deleted file mode 100644 index 94e351400..000000000 --- a/libpcap/doc/pcap.html +++ /dev/null @@ -1,997 +0,0 @@ - -PCAP New Generation Dump File Format - - - - - - -
 TOC 
-
- - - - -
Network Working GroupL. Degioanni
Internet-DraftF. Risso
Expires: August 30, 2004Politecnico di Torino
 March 2004
-

PCAP New Generation Dump File Format
-

pcap
- -

Status of this Memo

-

-This document is an Internet-Draft and is -in full conformance with all provisions of Section 10 of RFC2026.

-

-Internet-Drafts are working documents of the Internet Engineering -Task Force (IETF), its areas, and its working groups. -Note that other groups may also distribute working documents as -Internet-Drafts.

-

-Internet-Drafts are draft documents valid for a maximum of six months -and may be updated, replaced, or obsoleted by other documents at any time. -It is inappropriate to use Internet-Drafts as reference material or to cite -them other than as "work in progress."

-

-The list of current Internet-Drafts can be accessed at -http://www.ietf.org/ietf/1id-abstracts.txt.

-

-The list of Internet-Draft Shadow Directories can be accessed at -http://www.ietf.org/shadow.html.

-

-This Internet-Draft will expire on August 30, 2004.

- -

Copyright Notice

-

-Copyright (C) The Internet Society (2004). All Rights Reserved.

- -

Abstract

- -

This document describes a format to dump captured packets on a file. This format is extensible and it is currently proposed for implementation in the libpcap/WinPcap packet capture library. -



-

Table of Contents

-

-1.  -Objectives
-2.  -General File Structure
-2.1  -General Block Structure
-2.2  -Block Types
-2.3  -Block Hierarchy and Precedence
-2.4  -Data format
-3.  -Block Definition
-3.1  -Section Header Block (mandatory)
-3.2  -Interface Description Block (mandatory)
-3.3  -Packet Block (optional)
-3.4  -Simple Packet Block (optional)
-3.5  -Name Resolution Block (optional)
-3.6  -Interface Statistics Block (optional)
-4.  -Options
-5.  -Experimental Blocks (deserved to a further investigation)
-5.1  -Other Packet Blocks (experimental)
-5.2  -Compression Block (experimental)
-5.3  -Encryption Block (experimental)
-5.4  -Fixed Length Block (experimental)
-5.5  -Directory Block (experimental)
-5.6  -Traffic Statistics and Monitoring Blocks (experimental)
-5.7  -Event/Security Block (experimental)
-6.  -Conclusions
-7.  -Most important open issues
-§  -Intellectual Property and Copyright Statements
-

-
- -

-
 TOC 
-

1. Objectives

- -

The problem of exchanging packet traces becomes more and more critical every day; unfortunately, no standard solutions exist for this task right now. One of the most accepted packet interchange formats is the one defined by libpcap, which is rather old and does not fit for some of the nowadays applications especially in terms of extensibility. -

-

This document proposes a new format for dumping packet traces. The following goals are being pursued: -

-
    -
  • Extensibility: aside of some common functionalities, third parties should be able to enrich the information embedded in the file with proprietary extensions, which will be ignored by tools that are not able to understand them. -
  • -
  • Portability: a capture trace must contain all the information needed to read data independently from network, hardware and operating system of the machine that made the capture. -
  • -
  • Merge/Append data: it should be possible to add data at the end of a given file, and the resulting file must still be readable. -
  • -
-

-
 TOC 
-

2. General File Structure

- -

2.1 General Block Structure

- -

A capture file is organized in blocks, that are appended one to another to form the file. All the blocks share a common format, which is shown in Figure 1. -



- -
-    0                   1                   2                   3   
-    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |                          Block Type                           |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |                      Block Total Length                       |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   /                          Block Body                           /
-   /          /* variable length, aligned to 32 bits */            /
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |                      Block Total Length                       |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
-
 Basic block structure. 

- -

The fields have the following meaning: -

-
    -
  • Block Type (32 bits): unique value that identifies the block. Values whose Most Significant Bit (MSB) is equal to 1 are reserved for local use. They allow to save private data to the file and to extend the file format. -
  • -
  • Block Total Length: total size of this block, in bytes. For instance, a block that does not have a body has a length of 12 bytes. -
  • -
  • Block Body: content of the block. -
  • -
  • Block Total Length: total size of this block, in bytes. This field is duplicated for permitting backward file navigation. -
  • -
-

This structure, shared among all blocks, makes easy to process a file and to skip unneeded or unknown blocks. Blocks can be nested one inside the others (NOTE: needed?). Some of the blocks are mandatory, i.e. a dump file is not valid if they are not present, other are optional. -

-

The structure of the blocks allows to define other blocks if needed. A parser that does non understand them can simply ignore their content. -

-

2.2 Block Types

- -

The currently defined blocks are the following: -

-
    -
  1. Section Header Block: it defines the most important characteristics of the capture file. -
  2. -
  3. Interface Description Block: it defines the most important characteristics of the interface(s) used for capturing traffic. -
  4. -
  5. Packet Block: it contains a single captured packet, or a portion of it. -
  6. -
  7. Simple Packet Block: it contains a single captured packet, or a portion of it, with only a minimal set of information about it. -
  8. -
  9. Name Resolution Block: it defines the mapping from numeric addresses present in the packet dump and the canonical name counterpart. -
  10. -
  11. Capture Statistics Block: it defines how to store some statistical data (e.g. packet dropped, etc) which can be useful to undestand the conditions in which the capture has been made. -
  12. -
  13. Compression Marker Block: TODO -
  14. -
  15. Encryption Marker Block: TODO -
  16. -
  17. Fixed Length Marker Block: TODO -
  18. -
-

The following blocks instead are considered interesting but the authors believe that they deserve more in-depth discussion before being defined: -

-
    -
  1. Further Packet Blocks -
  2. -
  3. Directory Block -
  4. -
  5. Traffic Statistics and Monitoring Blocks -
  6. -
  7. Alert and Security Blocks -
  8. -
-

TODO Currently standardized Block Type codes are specified in Appendix 1. -

-

2.3 Block Hierarchy and Precedence

- -

The file must begin with a Section Header Block. However, more than one Section Header Block can be present on the dump, each one covering the data following it till the next one (or the end of file). A Section includes the data delimited by two Section Header Blocks (or by a Section Header Block and the end of the file), including the first Section Header Block. -

-

In case an application cannot read a Section because of different version number, it must skip everything until the next Section Header Block. Note that, in order to properly skip the blocks until the next section, all blocks must have the fields Type and Length at the beginning. This is a mandatory requirement that must be maintained in future versions of the block format. -

-

Figure 2 shows two valid files: the first has a typical configuration, with a single Section Header that covers the whole file. The second one contains three headers, and is normally the result of file concatenation. An application that understands only version 1.0 of the file format skips the intermediate section and restart processing the packets after the third Section Header. -



- -
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   | SHB v1.0  |                      Data                         |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   Typical configuration with a single Section Header Block 
-
-
-   |--   1st Section   --|--   2nd Section   --|--  3rd Section  --|
-   |                                                               |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   | SHB v1.0  |  Data   | SHB V1.1  |  Data   | SHB V1.0  |  Data |  
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   Configuration with three different Section Header Blocks
-
-
 File structure example: the Section Header Block. 

- -

NOTE: TO BE COMPLETED with some examples of other blocks -

-

2.4 Data format

- -

Data contained in each section will always be saved according to the characteristics (little endian / big endian) of the dumping machine. This refers to all fields that are saved as numbers and that span over two or more bytes. -

-

The approach of having each section saved in the native format of the generating host is more efficient because it avoids translation of data when reading / writing on the host itself, which is the most common case when generating/processing capture dumps. -

-

TODO Probably we have to specify something more here. Is what we're saying enough to avoid any kind of ambiguity?. -

-

-
 TOC 
-

3. Block Definition

- -

This section details the format of the body of the blocks currently defined. -

-

3.1 Section Header Block (mandatory)

- -

The Section Header Block is mandatory. It identifies the beginning of a section of the capture dump file. Its format is shown in Figure 3. -



- -
-    0                   1                   2                   3   
-    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |                            Magic                              |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |              Major            |             Minor             |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   /                                                               / 
-   /                      Options (variable)                       / 
-   /                                                               / 
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
-
 Section Header Block format. 

- -

The meaning of the fields is: -

-
    -
  • Magic: magic number, whose value is the hexadecimal number 0x1A2B3C4D. This number can be used to distinguish section that have been saved on little-endian machines from the one saved on big-endian machines. -
  • -
  • Major: number of the current mayor version of the format. Current value is 1. -
  • -
  • Minor: number of the current minor version of the format. Current value is 0. -
  • -
  • Options: optionally, a list of options (formatted according to the rules defined in Section 4) can be present. -
  • -
-

Aside form the options defined in Section 4, the following options are valid within this block: -

- - - - - - - - - - - - - - - - - - - - - - - - - -
NameCodeLengthDescription
Hardware2variableAn ascii string containing the description of the hardware used to create this section.
Operating System3variableAn ascii string containing the name of the operating system used to create this section.
User Application3variableAn ascii string containing the name of the application used to create this section.
- -

The Section Header Block does not contain data but it rather identifies a list of blocks (interfaces, packets) that are logically correlated. This block does not contain any reference to the size of the section it is currently delimiting, therefore the reader cannot skip a whole section at once. In case a section must be skipped, the user has to repeatedly skip all the blocks contained within it; this makes the parsing of the file slower but it permits to append several capture dumps at the same file. -

-

3.2 Interface Description Block (mandatory)

- -

The Interface Description Block is mandatory. This block is needed to specify the characteristics of the network interface on which the capture has been made. In order to properly associate the captured data to the corresponding interface, the Interface Description Block must be defined before any other block that uses it; therefore, this block is usually placed immediately after the Section Header Block. -

-

An Interface Description Block is valid only inside the section which it belongs to. The structure of a Interface Description Block is shown in Figure 4. -



- -
-    0                   1                   2                   3   
-    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |          Interface ID         |           LinkType            |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |                            SnapLen                            |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   /                                                               / 
-   /                      Options (variable)                       / 
-   /                                                               / 
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- 
-
 Interface Description Block format. 

- -

The meaning of the fields is: -

-
    -
  • Interface ID: a progressive number that identifies uniquely any interface inside current section. Two Interface Description Blocks can have the same Interface ID only if they are in different sections of the file. The Interface ID is referenced by the packet blocks. -
  • -
  • LinkType: a value that defines the link layer type of this interface. -
  • -
  • SnapLen: maximum number of bytes dumped from each packet. The portion of each packet that exceeds this value will not be stored in the file. -
  • -
  • Options: optionally, a list of options (formatted according to the rules defined in Section 4) can be present. -
  • -
-

In addition to the options defined in Section 4, the following options are valid within this block: -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameCodeLengthDescription
if_name2VariableName of the device used to capture data.
if_IPv4addr38Interface network address and netmask.
if_IPv6addr417Interface network address and prefix length (stored in the last byte).
if_MACaddr56Interface Hardware MAC address (48 bits).
if_EUIaddr68Interface Hardware EUI address (64 bits), if available.
if_speed78Interface speed (in bps).
if_tsaccur81Precision of timestamps. If the Most Significant Bit is equal to zero, the remaining bits indicates the accuracy as as a negative power of 10 (e.g. 6 means microsecond accuracy). If the Most Significant Bit is equal to zero, the remaining bits indicates the accuracy as as negative power of 2 (e.g. 10 means 1/1024 of second). If this option is not present, a precision of 10^-6 is assumed.
if_tzone94Time zone for GMT support (TODO: specify better).
if_flags104Interface flags. (TODO: specify better. Possible flags: promiscuous, inbound/outbound, traffic filtered during capture).
if_filter11variableThe filter (e.g. "capture only TCP traffic") used to capture traffic. The first byte of the Option Data keeps a code of the filter used (e.g. if this is a libpcap string, or BPF bytecode, and more). More details about this format will be presented in Appendix XXX (TODO).
if_opersystem12variableAn ascii string containing the name of the operating system of the machine that hosts this interface. This can be different from the same information that can be contained by the Section Header Block (Section 3.1) because the capture can have been done on a remote machine.
- -

3.3 Packet Block (optional)

- -

A Packet Block is the standard container for storing the packets coming from the network. The Packet Block is optional because packets can be stored either by means of this block or the Simple Packet Block, which can be used to speed up dump generation. The format of a packet block is shown in Figure 5. -



- -
-    0                   1                   2                   3   
-    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |         Interface ID          |          Drops Count          |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |                        Timestamp (High)                       |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |                        Timestamp (Low)                        |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |                         Captured Len                          |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |                          Packet Len                           |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |                                                               |
-   |                          Packet Data                          |
-   |                                                               |
-   |              /* variable length, byte-aligned */              |
-   |                                                               |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   /                                                               / 
-   /                      Options (variable)                       / 
-   /                                                               / 
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
-
 Packet Block format. 

- -

The Packet Block has the following fields: -

-
    -
  • Interface ID: Specifies the interface this packet comes from, and corresponds to the ID of one of the Interface Description Blocks present in this section of the file (see Figure 4). -
  • -
  • Drops Count: a local drop counter. It specified the number of packets lost (by the interface and the operating system) between this packet and the preceding one. The value xFFFF (in hexadecimal) is reserved for those systems in which this information is not available. -
  • -
  • Timestamp (High): the most significative part of the timestamp. in standard Unix format, i.e. from 1/1/1970. -
  • -
  • Timestamp (Low): the less significative part of the timestamp. The way to interpret this field is specified by the 'ts_accur' option (see Figure 4) of the Interface Description block referenced by this packet. If the Interface Description block does not contain a 'ts_accur' option, then this field is expressed in microseconds. -
  • -
  • Captured Len: number of bytes captured from the packet (i.e. the length of the Packet Data field). It will be the minimum value among the actual Packet Length and the snapshot length (defined in Figure 4). -
  • -
  • Packet Len: actual length of the packet when it was transmitted on the network. Can be different from Captured Len if the user wants only a snapshot of the packet. -
  • -
  • Packet Data: the data coming from the network, including link-layer headers. The length of this field is Captured Len. The format of the link-layer headers depends on the LinkType field specified in the Interface Description Block (see Section 3.2) and it is specified in Appendix XXX (TODO). -
  • -
  • Options: optionally, a list of options (formatted according to the rules defined in Section 4) can be present. -
  • -
-

-

-

3.4 Simple Packet Block (optional)

- -

The Simple Packet Block is a lightweight container for storing the packets coming from the network. Its presence is optional. -

-

A Simple Packet Block is similar to a Packet Block (see Section 3.3), but it is smaller, simpler to process and contains only a minimal set of information. This block is preferred to the standard Packet Block when performance or space occupation are critical factors, such as in sustained traffic dump applications. A capture file can contain both Packet Blocks and Simple Packet Blocks: for example, a capture tool could switch from Packet Blocks to Simple Packet Blocks when the hardware resources become critical. -

-

The Simple Packet Block does not contain the Interface ID field. Therefore, it must be assumed that all the Simple Packet Blocks have been captured on the interface previously specified in the Interface Description Block. -

-

Figure 6 shows the format of the Simple Packet Block. -



- -
-    0                   1                   2                   3   
-    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |                          Packet Len                           |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |                                                               |
-   |                          Packet Data                          |
-   |                                                               |
-   |              /* variable length, byte-aligned */              |
-   |                                                               |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- 
-
 Simple Packet Block format. 

- -

The Packet Block has the following fields: -

-
    -
  • Packet Len: actual length of the packet when it was transmitted on the network. Can be different from captured len if the packet has been truncated. -
  • -
  • Packet data: the data coming from the network, including link-layers headers. The length of this field can be derived from the field Block Total Length, present in the Block Header. -
  • -
-

The Simple Packet Block does not contain the timestamp because this is one of the most costly operations on PCs. Additionally, there are applications that do not require it; e.g. an Intrusion Detection System is interested in packets, not in their timestamp. -

-

The Simple Packet Block is very efficient in term of disk space: a snapshot of length 100 bytes requires only 16 bytes of overhead, which corresponds to an efficiency of more than 86%. -

-

3.5 Name Resolution Block (optional)

- -

The Name Resolution Block is used to support the correlation of numeric addresses (present in the captured packets) and their corresponding canonical names and it is optional. Having the literal names saved in the file, this prevents the need of a name resolution in a delayed time, when the association between names and addresses can be different from the one in use at capture time. Moreover, The Name Resolution Block avoids the need of issuing a lot of DNS requests every time the trace capture is opened, and allows to have name resolution also when reading the capture with a machine not connected to the network. -

-

The format of the Name Resolution Block is shown in Figure 7. -



- -
-    0                   1                   2                   3   
-    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |      Record Type              |         Record Length         | 
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |                       Record Value                            |
-   |              /* variable length, byte-aligned */              |
-   |               + + + + + + + + + + + + + + + + + + + + + + + + +
-   |               |               |               |               |
-   +-+-+-+-+-+-+-+-+ + + + + + + + + + + + + + + + + + + + + + + + +
-             . . . other records . . .
-   |  Record Type == end_of_recs   |  Record Length == 00          |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   /                                                               / 
-   /                      Options (variable)                       / 
-   /                                                               / 
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- 
-
 Name Resolution Block format. 

- -

A Name Resolution Block is a zero-terminated list of records (in the TLV format), each of which contains an association between a network address and a name. There are three possible types of records: -

- - - - - - - - - - - - - - - - - - - - - - - - - -
NameCodeLengthDescription
end_of_recs00End of records
ip4_rec1VariableSpecifies an IPv4 address (contained in the first 4 bytes), followed by one or more zero-terminated strings containing the DNS entries for that address.
ip6_rec1VariableSpecifies an IPv6 address (contained in the first 16 bytes), followed by one or more zero-terminated strings containing the DNS entries for that address.
- -

After the list or Name Resolution Records, optionally, a list of options (formatted according to the rules defined in Section 4) can be present. -

-

A Name Resolution Block is normally placed at the beginning of the file, but no assumptions can be taken about its position. Name Resolution Blocks can be added in a second time by tools that process the file, like network analyzers. -

-

In addiction to the options defined in Section 4, the following options are valid within this block: -

- - - - - - - - - - - - -
NameCodeLengthDescription
ns_dnsname2VariableAn ascii string containing the name of the machine (DNS server) used to perform the name resolution.
- -

3.6 Interface Statistics Block (optional)

- -

The Interface Statistics Block contains the capture statistics for a given interface and it is optional. The statistics are referred to the interface defined in the current Section identified by the Interface ID field. -

-

The format of the Interface Statistics Block is shown in Figure 8. -



- -
-    0                   1                   2                   3   
-    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |                         IfRecv                                |
-   |                          (high + low)                         |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |                         IfDrop                                |
-   |                          (high + low)                         |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |                         FilterAccept                          |
-   |                          (high + low)                         |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |                         OSDrop                                |
-   |                          (high + low)                         |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |                         UsrDelivered                          |
-   |                          (high + low)                         |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |          Interface ID         |           Reserved            |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   /                                                               / 
-   /                      Options (variable)                       / 
-   /                                                               / 
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- 
-
 Interface Statistics Block format. 

- -

The fields have the following meaning: -

-
    -
  • IfRecv: number of packets received from the interface during the capture. This number is reported as a 64 bits value, in which the most significat bits are located in the first four bytes of the field. -
  • -
  • IfDrop: number of packets dropped by the interface during the capture due to lack of resources. -
  • -
  • FilterAccept: number of packets accepeted by filter during current capture. -
  • -
  • OSDrop: number of packets dropped by the operating system during the capture. -
  • -
  • UsrDelivered: number of packets delivered to the user. UsrDelivered can be different from the value 'FilterAccept - OSDropped' because some packets could still lay in the OS buffers when the capture ended. -
  • -
  • Interface ID: reference to an Interface Description Block. -
  • -
  • Reserved: Reserved to future use. -
  • -
  • Options: optionally, a list of options (formatted according to the rules defined in Section 4) can be present. -
  • -
-

In addiction to the options defined in Section 4, the following options are valid within this block: -

- - - - - - - - - - - - - - - - - - -
NameCodeLengthDescription
isb_starttime28Time in which the capture started; time will be stored in two blocks of four bytes each, containing the timestamp in seconds and nanoseconds.
isb_endtime38Time in which the capture started; time will be stored in two blocks of four bytes each, containing the timestamp in seconds and nanoseconds.
- -

-
 TOC 
-

4. Options

- -

Almost all blocks have the possibility to embed optional fields. Optional fields can be used to insert some information that may be useful when reading data, but that it is not really needed for packet processing. Therefore, each tool can be either read the content of the optional fields (if any), or skip them at once. -

-

Skipping all the optional fields at once is straightforward because most of the blocks have a fixed length, therefore the field Block Length (present in the General Block Structure, see Section 2.1) can be used to skip everything till the next block. -

-

Options are a list of Type - Length - Value fields, each one containing a single value: -

-
    -
  • Option Type (2 bytes): it contains the code that specifies the type of the current TLV record. Option types whose Most Significant Bit is equal to one are reserved for local use; therefore, there is no guarantee that the code used is unique among all capture files (generated by other applications). In case of vendor-specific extensions that have to be identified uniquely, vendors must request an Option Code whose MSB is equal to zero. -
  • -
  • Option Length (2 bytes): it contains the length of the following 'Option Value' field. -
  • -
  • Option Value (variable length): it contains the value of the given option. The length of this field as been specified by the Option Length field. -
  • -
-

Options may be repeated several times (e.g. an interface that has several IP addresses associated to it). The option list is terminated by a special code which is the 'End of Option'. -

-

The format of the optional fields is shown in Figure 9. -



- -
-    0                   1                   2                   3   
-    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |      Option Code              |         Option Length         | 
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |                       Option Value                            |
-   |              /* variable length, byte-aligned */              |
-   |               + + + + + + + + + + + + + + + + + + + + + + + + +
-   |               /               /               /               |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   /                                                               /
-   /                 . . . other options . . .                     /
-   /                                                               /
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |   Option Code == opt_endofopt  |  Option Length == 0          |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- 
-
 Options format. 

- -

The following codes can always be present in any optional field: -

- - - - - - - - - - - - - - - - - - -
NameCodeLengthDescription
opt_endofopt00End of options: it is used to delimit the end of the optional fields. This block cannot be repeated within a given list of options.
opt_comment1variableComment: it is an ascii string containing a comment that is associated to the current block.
- -

-
 TOC 
-

5. Experimental Blocks (deserved to a further investigation)

- -

5.1 Other Packet Blocks (experimental)

- -

Can some other packet blocks (besides the two described in the previous paragraphs) be useful? -

-

5.2 Compression Block (experimental)

- -

The Compression Block is optional. A file can contain an arbitrary number of these blocks. A Compression Block, as the name says, is used to store compressed data. Its format is shown in Figure 10. -



- -
-    0                   1                   2                   3   
-    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |  Compr. Type  |                                               |
-   +-+-+-+-+-+-+-+-+                                               |
-   |                                                               |
-   |                       Compressed Data                         |
-   |                                                               |
-   |              /* variable length, byte-aligned */              |
-   |                                                               |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- 
-
 Compression Block format. 

- -

The fields have the following meaning: -

-
    -
  • Compression Type: specifies the compression algorithm. Possible values for this field are 0 (uncompressed), 1 (Lempel Ziv), 2 (Gzip), other?? Probably some kind of dumb and fast compression algorithm could be effective with some types of traffic (for example web), but which? -
  • -
  • Compressed Data: data of this block. Once decompressed, it is made of other blocks. -
  • -
-

5.3 Encryption Block (experimental)

- -

The Encryption Block is optional. A file can contain an arbitrary number of these blocks. An Encryption Block is used to sotre encrypted data. Its format is shown in Figure 11. -



- -
-    0                   1                   2                   3   
-    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |   Encr. Type  |                                               |
-   +-+-+-+-+-+-+-+-+                                               |
-   |                                                               |
-   |                       Compressed Data                         |
-   |                                                               |
-   |              /* variable length, byte-aligned */              |
-   |                                                               |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- 
-
 Encryption Block format. 

- -

The fields have the following meaning: -

-
    -
  • Compression Type: specifies the encryption algorithm. Possible values for this field are ??? NOTE: this block should probably contain other fields, depending on the encryption algorithm. To be define precisely. -
  • -
  • Encrypted Data: data of this block. Once decripted, it consists of other blocks. -
  • -
-

5.4 Fixed Length Block (experimental)

- -

The Fixed Length Block is optional. A file can contain an arbitrary number of these blocks. A Fixed Length Block can be used to optimize the access to the file. Its format is shown in Figure 12. -A Fixed Length Block stores records with constant size. It contains a set of Blocks (normally Packet Blocks or Simple Packet Blocks), of wihich it specifies the size. Knowing this size a priori helps to scan the file and to load some portions of it without truncating a block, and is particularly useful with cell-based networks like ATM. -



- -
-    0                   1                   2                   3   
-    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |          Cell Size            |                               |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
-   |                                                               |
-   |                        Fixed Size Data                        |
-   |                                                               |
-   |              /* variable length, byte-aligned */              |
-   |                                                               |
-   |                                                               |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- 
-
 Fixed Length Block format. 

- -

The fields have the following meaning: -

-
    -
  • Cell size: the size of the blocks contained in the data field. -
  • -
  • Fixed Size Data: data of this block. -
  • -
-

5.5 Directory Block (experimental)

- -

If present, this block contains the following information: -

-
    -
  • number of indexed packets (N) -
  • -
  • table with position and length of any indexed packet (N entries) -
  • -
-

A directory block must be followed by at least N packets, otherwise it must be considered invalid. It can be used to efficiently load portions of the file to memory and to support operations on memory mapped files. This block can be added by tools like network analyzers as a consequence of file processing. -

-

5.6 Traffic Statistics and Monitoring Blocks (experimental)

- -

One or more blocks could be defined to contain network statistics or traffic monitoring information. They could be use to store data collected from RMON or Netflow probes, or from other network monitoring tools. -

-

5.7 Event/Security Block (experimental)

- -

This block could be used to store events. Events could contain generic information (for example network load over 50%, server down...) or security alerts. An event could be: -

-
    -
  • skipped, if the application doesn't know how to do with it -
  • -
  • processed independently by the packets. In other words, the applications skips the packets and processes only the alerts -
  • -
  • processed in relation to packets: for example, a security tool could load only the packets of the file that are near a security alert; a monitorg tool could skip the packets captured while the server was down. -
  • -
-

-
 TOC 
-

6. Conclusions

- -

The file format proposed in this document should be very versatile and satisfy a wide range of applications. -In the simplest case, it can contain a raw dump of the network data, made of a series of Simple Packet Blocks. -In the most complex case, it can be used as a repository for heterogeneous information. -In every case, the file remains easy to parse and an application can always skip the data it is not interested in; at the same time, different applications can share the file, and each of them can benfit of the information produced by the others. -Two or more files can be concatenated obtaining another valid file. -

-

-
 TOC 
-

7. Most important open issues

- -
    -
  • Data, in the file, must be byte or word aligned? Currently, the structure of this document is not consistent with respect to this point. -
  • -


-
 TOC 
-

Intellectual Property Statement

- - -

Full Copyright Statement

- - - - -

Acknowledgment

- - diff --git a/libpcap/doc/pcap.txt b/libpcap/doc/pcap.txt deleted file mode 100644 index cfa6645fc..000000000 --- a/libpcap/doc/pcap.txt +++ /dev/null @@ -1,1680 +0,0 @@ - - -Network Working Group L. Degioanni -Internet-Draft F. Risso -Expires: August 30, 2004 Politecnico di Torino - March 2004 - - - PCAP New Generation Dump File Format - pcap - -Status of this Memo - - This document is an Internet-Draft and is in full conformance with - all provisions of Section 10 of RFC2026. - - Internet-Drafts are working documents of the Internet Engineering - Task Force (IETF), its areas, and its working groups. Note that other - groups may also distribute working documents as Internet-Drafts. - - Internet-Drafts are draft documents valid for a maximum of six months - and may be updated, replaced, or obsoleted by other documents at any - time. It is inappropriate to use Internet-Drafts as reference - material or to cite them other than as "work in progress." - - The list of current Internet-Drafts can be accessed at http:// - www.ietf.org/ietf/1id-abstracts.txt. - - The list of Internet-Draft Shadow Directories can be accessed at - http://www.ietf.org/shadow.html. - - This Internet-Draft will expire on August 30, 2004. - -Copyright Notice - - Copyright (C) The Internet Society (2004). All Rights Reserved. - -Abstract - - This document describes a format to dump captured packets on a file. - This format is extensible and it is currently proposed for - implementation in the libpcap/WinPcap packet capture library. - - - - - - - - - - - - -Degioanni & Risso Expires August 30, 2004 [Page 1] - -Internet-Draft PCAP New Generation Dump File Format March 2004 - - -Table of Contents - - 1. Objectives . . . . . . . . . . . . . . . . . . . . . . . . . . 3 - 2. General File Structure . . . . . . . . . . . . . . . . . . . . 4 - 2.1 General Block Structure . . . . . . . . . . . . . . . . . . . 4 - 2.2 Block Types . . . . . . . . . . . . . . . . . . . . . . . . . 5 - 2.3 Block Hierarchy and Precedence . . . . . . . . . . . . . . . . 5 - 2.4 Data format . . . . . . . . . . . . . . . . . . . . . . . . . 6 - 3. Block Definition . . . . . . . . . . . . . . . . . . . . . . . 8 - 3.1 Section Header Block (mandatory) . . . . . . . . . . . . . . . 8 - 3.2 Interface Description Block (mandatory) . . . . . . . . . . . 9 - 3.3 Packet Block (optional) . . . . . . . . . . . . . . . . . . . 13 - 3.4 Simple Packet Block (optional) . . . . . . . . . . . . . . . . 15 - 3.5 Name Resolution Block (optional) . . . . . . . . . . . . . . . 16 - 3.6 Interface Statistics Block (optional) . . . . . . . . . . . . 18 - 4. Options . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 - 5. Experimental Blocks (deserved to a further investigation) . . 23 - 5.1 Other Packet Blocks (experimental) . . . . . . . . . . . . . . 23 - 5.2 Compression Block (experimental) . . . . . . . . . . . . . . . 23 - 5.3 Encryption Block (experimental) . . . . . . . . . . . . . . . 23 - 5.4 Fixed Length Block (experimental) . . . . . . . . . . . . . . 24 - 5.5 Directory Block (experimental) . . . . . . . . . . . . . . . . 25 - 5.6 Traffic Statistics and Monitoring Blocks (experimental) . . . 25 - 5.7 Event/Security Block (experimental) . . . . . . . . . . . . . 25 - 6. Conclusions . . . . . . . . . . . . . . . . . . . . . . . . . 27 - 7. Most important open issues . . . . . . . . . . . . . . . . . . 28 - Intellectual Property and Copyright Statements . . . . . . . . 29 - - - - - - - - - - - - - - - - - - - - - - - - -Degioanni & Risso Expires August 30, 2004 [Page 2] - -Internet-Draft PCAP New Generation Dump File Format March 2004 - - -1. Objectives - - The problem of exchanging packet traces becomes more and more - critical every day; unfortunately, no standard solutions exist for - this task right now. One of the most accepted packet interchange - formats is the one defined by libpcap, which is rather old and does - not fit for some of the nowadays applications especially in terms of - extensibility. - - This document proposes a new format for dumping packet traces. The - following goals are being pursued: - - o Extensibility: aside of some common functionalities, third parties - should be able to enrich the information embedded in the file with - proprietary extensions, which will be ignored by tools that are - not able to understand them. - - o Portability: a capture trace must contain all the information - needed to read data independently from network, hardware and - operating system of the machine that made the capture. - - o Merge/Append data: it should be possible to add data at the end of - a given file, and the resulting file must still be readable. - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Degioanni & Risso Expires August 30, 2004 [Page 3] - -Internet-Draft PCAP New Generation Dump File Format March 2004 - - -2. General File Structure - -2.1 General Block Structure - - A capture file is organized in blocks, that are appended one to - another to form the file. All the blocks share a common format, which - is shown in Figure 1. - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Block Type | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Block Total Length | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - / Block Body / - / /* variable length, aligned to 32 bits */ / - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Block Total Length | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - Figure 1: Basic block structure. - - The fields have the following meaning: - - o Block Type (32 bits): unique value that identifies the block. - Values whose Most Significant Bit (MSB) is equal to 1 are reserved - for local use. They allow to save private data to the file and to - extend the file format. - - o Block Total Length: total size of this block, in bytes. For - instance, a block that does not have a body has a length of 12 - bytes. - - o Block Body: content of the block. - - o Block Total Length: total size of this block, in bytes. This field - is duplicated for permitting backward file navigation. - - This structure, shared among all blocks, makes easy to process a file - and to skip unneeded or unknown blocks. Blocks can be nested one - inside the others (NOTE: needed?). Some of the blocks are mandatory, - i.e. a dump file is not valid if they are not present, other are - optional. - - The structure of the blocks allows to define other blocks if needed. - A parser that does non understand them can simply ignore their - content. - - - -Degioanni & Risso Expires August 30, 2004 [Page 4] - -Internet-Draft PCAP New Generation Dump File Format March 2004 - - -2.2 Block Types - - The currently defined blocks are the following: - - 1. Section Header Block: it defines the most important - characteristics of the capture file. - - 2. Interface Description Block: it defines the most important - characteristics of the interface(s) used for capturing traffic. - - 3. Packet Block: it contains a single captured packet, or a portion - of it. - - 4. Simple Packet Block: it contains a single captured packet, or a - portion of it, with only a minimal set of information about it. - - 5. Name Resolution Block: it defines the mapping from numeric - addresses present in the packet dump and the canonical name - counterpart. - - 6. Capture Statistics Block: it defines how to store some - statistical data (e.g. packet dropped, etc) which can be useful - to undestand the conditions in which the capture has been made. - - 7. Compression Marker Block: TODO - - 8. Encryption Marker Block: TODO - - 9. Fixed Length Marker Block: TODO - - The following blocks instead are considered interesting but the - authors believe that they deserve more in-depth discussion before - being defined: - - 1. Further Packet Blocks - - 2. Directory Block - - 3. Traffic Statistics and Monitoring Blocks - - 4. Alert and Security Blocks - - TODO Currently standardized Block Type codes are specified in - Appendix 1. - -2.3 Block Hierarchy and Precedence - - The file must begin with a Section Header Block. However, more than - - - -Degioanni & Risso Expires August 30, 2004 [Page 5] - -Internet-Draft PCAP New Generation Dump File Format March 2004 - - - one Section Header Block can be present on the dump, each one - covering the data following it till the next one (or the end of - file). A Section includes the data delimited by two Section Header - Blocks (or by a Section Header Block and the end of the file), - including the first Section Header Block. - - In case an application cannot read a Section because of different - version number, it must skip everything until the next Section Header - Block. Note that, in order to properly skip the blocks until the next - section, all blocks must have the fields Type and Length at the - beginning. This is a mandatory requirement that must be maintained in - future versions of the block format. - - Figure 2 shows two valid files: the first has a typical - configuration, with a single Section Header that covers the whole - file. The second one contains three headers, and is normally the - result of file concatenation. An application that understands only - version 1.0 of the file format skips the intermediate section and - restart processing the packets after the third Section Header. - - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | SHB v1.0 | Data | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - Typical configuration with a single Section Header Block - - - |-- 1st Section --|-- 2nd Section --|-- 3rd Section --| - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | SHB v1.0 | Data | SHB V1.1 | Data | SHB V1.0 | Data | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - Configuration with three different Section Header Blocks - - Figure 2: File structure example: the Section Header Block. - - NOTE: TO BE COMPLETED with some examples of other blocks - -2.4 Data format - - Data contained in each section will always be saved according to the - characteristics (little endian / big endian) of the dumping machine. - This refers to all fields that are saved as numbers and that span - over two or more bytes. - - The approach of having each section saved in the native format of the - generating host is more efficient because it avoids translation of - data when reading / writing on the host itself, which is the most - common case when generating/processing capture dumps. - - - -Degioanni & Risso Expires August 30, 2004 [Page 6] - -Internet-Draft PCAP New Generation Dump File Format March 2004 - - - TODO Probably we have to specify something more here. Is what we're - saying enough to avoid any kind of ambiguity?. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Degioanni & Risso Expires August 30, 2004 [Page 7] - -Internet-Draft PCAP New Generation Dump File Format March 2004 - - -3. Block Definition - - This section details the format of the body of the blocks currently - defined. - -3.1 Section Header Block (mandatory) - - The Section Header Block is mandatory. It identifies the beginning of - a section of the capture dump file. Its format is shown in Figure 3. - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Magic | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Major | Minor | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - / / - / Options (variable) / - / / - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - Figure 3: Section Header Block format. - - The meaning of the fields is: - - o Magic: magic number, whose value is the hexadecimal number - 0x1A2B3C4D. This number can be used to distinguish section that - have been saved on little-endian machines from the one saved on - big-endian machines. - - o Major: number of the current mayor version of the format. Current - value is 1. - - o Minor: number of the current minor version of the format. Current - value is 0. - - o Options: optionally, a list of options (formatted according to the - rules defined in Section 4) can be present. - - Aside form the options defined in Section 4, the following options - are valid within this block: - - +----------------+----------------+----------------+----------------+ - | Name | Code | Length | Description | - +----------------+----------------+----------------+----------------+ - | Hardware | 2 | variable | An ascii | - | | | | string | - - - -Degioanni & Risso Expires August 30, 2004 [Page 8] - -Internet-Draft PCAP New Generation Dump File Format March 2004 - - - | | | | containing the | - | | | | description of | - | | | | the hardware | - | | | | used to create | - | | | | this section. | - | | | | | - | Operating | 3 | variable | An ascii | - | System | | | string | - | | | | containing the | - | | | | name of the | - | | | | operating | - | | | | system used to | - | | | | create this | - | | | | section. | - | | | | | - | User | 3 | variable | An ascii | - | Application | | | string | - | | | | containing the | - | | | | name of the | - | | | | application | - | | | | used to create | - | | | | this section. | - +----------------+----------------+----------------+----------------+ - - Table 1 - - The Section Header Block does not contain data but it rather - identifies a list of blocks (interfaces, packets) that are logically - correlated. This block does not contain any reference to the size of - the section it is currently delimiting, therefore the reader cannot - skip a whole section at once. In case a section must be skipped, the - user has to repeatedly skip all the blocks contained within it; this - makes the parsing of the file slower but it permits to append several - capture dumps at the same file. - -3.2 Interface Description Block (mandatory) - - The Interface Description Block is mandatory. This block is needed to - specify the characteristics of the network interface on which the - capture has been made. In order to properly associate the captured - data to the corresponding interface, the Interface Description Block - must be defined before any other block that uses it; therefore, this - block is usually placed immediately after the Section Header Block. - - An Interface Description Block is valid only inside the section which - it belongs to. The structure of a Interface Description Block is - shown in Figure 4. - - - - -Degioanni & Risso Expires August 30, 2004 [Page 9] - -Internet-Draft PCAP New Generation Dump File Format March 2004 - - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Interface ID | LinkType | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | SnapLen | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - / / - / Options (variable) / - / / - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - Figure 4: Interface Description Block format. - - The meaning of the fields is: - - o Interface ID: a progressive number that identifies uniquely any - interface inside current section. Two Interface Description Blocks - can have the same Interface ID only if they are in different - sections of the file. The Interface ID is referenced by the packet - blocks. - - o LinkType: a value that defines the link layer type of this - interface. - - o SnapLen: maximum number of bytes dumped from each packet. The - portion of each packet that exceeds this value will not be stored - in the file. - - o Options: optionally, a list of options (formatted according to the - rules defined in Section 4) can be present. - - In addition to the options defined in Section 4, the following - options are valid within this block: - - +----------------+----------------+----------------+----------------+ - | Name | Code | Length | Description | - +----------------+----------------+----------------+----------------+ - | if_name | 2 | Variable | Name of the | - | | | | device used to | - | | | | capture data. | - | | | | | - | if_IPv4addr | 3 | 8 | Interface | - | | | | network | - | | | | address and | - | | | | netmask. | - | | | | | - | if_IPv6addr | 4 | 17 | Interface | - - - -Degioanni & Risso Expires August 30, 2004 [Page 10] - -Internet-Draft PCAP New Generation Dump File Format March 2004 - - - | | | | network | - | | | | address and | - | | | | prefix length | - | | | | (stored in the | - | | | | last byte). | - | | | | | - | if_MACaddr | 5 | 6 | Interface | - | | | | Hardware MAC | - | | | | address (48 | - | | | | bits). | - | | | | | - | if_EUIaddr | 6 | 8 | Interface | - | | | | Hardware EUI | - | | | | address (64 | - | | | | bits), if | - | | | | available. | - | | | | | - | if_speed | 7 | 8 | Interface | - | | | | speed (in | - | | | | bps). | - | | | | | - | if_tsaccur | 8 | 1 | Precision of | - | | | | timestamps. If | - | | | | the Most | - | | | | Significant | - | | | | Bit is equal | - | | | | to zero, the | - | | | | remaining bits | - | | | | indicates the | - | | | | accuracy as as | - | | | | a negative | - | | | | power of 10 | - | | | | (e.g. 6 means | - | | | | microsecond | - | | | | accuracy). If | - | | | | the Most | - | | | | Significant | - | | | | Bit is equal | - | | | | to zero, the | - | | | | remaining bits | - | | | | indicates the | - | | | | accuracy as as | - | | | | negative power | - | | | | of 2 (e.g. 10 | - | | | | means 1/1024 | - | | | | of second). If | - | | | | this option is | - | | | | not present, a | - - - -Degioanni & Risso Expires August 30, 2004 [Page 11] - -Internet-Draft PCAP New Generation Dump File Format March 2004 - - - | | | | precision of | - | | | | 10^-6 is | - | | | | assumed. | - | | | | | - | if_tzone | 9 | 4 | Time zone for | - | | | | GMT support | - | | | | (TODO: specify | - | | | | better). | - | | | | | - | if_flags | 10 | 4 | Interface | - | | | | flags. (TODO: | - | | | | specify | - | | | | better. | - | | | | Possible | - | | | | flags: | - | | | | promiscuous, | - | | | | inbound/outbou | - | | | | nd, traffic | - | | | | filtered | - | | | | during | - | | | | capture). | - | | | | | - | if_filter | 11 | variable | The filter | - | | | | (e.g. "capture | - | | | | only TCP | - | | | | traffic") used | - | | | | to capture | - | | | | traffic. The | - | | | | first byte of | - | | | | the Option | - | | | | Data keeps a | - | | | | code of the | - | | | | filter used | - | | | | (e.g. if this | - | | | | is a libpcap | - | | | | string, or BPF | - | | | | bytecode, and | - | | | | more). More | - | | | | details about | - | | | | this format | - | | | | will be | - | | | | presented in | - | | | | Appendix XXX | - | | | | (TODO). | - | | | | | - | if_opersystem | 12 | variable | An ascii | - | | | | string | - | | | | containing the | - - - -Degioanni & Risso Expires August 30, 2004 [Page 12] - -Internet-Draft PCAP New Generation Dump File Format March 2004 - - - | | | | name of the | - | | | | operating | - | | | | system of the | - | | | | machine that | - | | | | hosts this | - | | | | interface. | - | | | | This can be | - | | | | different from | - | | | | the same | - | | | | information | - | | | | that can be | - | | | | contained by | - | | | | the Section | - | | | | Header Block | - | | | | (Section 3.1) | - | | | | because the | - | | | | capture can | - | | | | have been done | - | | | | on a remote | - | | | | machine. | - +----------------+----------------+----------------+----------------+ - - Table 2 - - -3.3 Packet Block (optional) - - A Packet Block is the standard container for storing the packets - coming from the network. The Packet Block is optional because packets - can be stored either by means of this block or the Simple Packet - Block, which can be used to speed up dump generation. The format of a - packet block is shown in Figure 5. - - - - - - - - - - - - - - - - - - - -Degioanni & Risso Expires August 30, 2004 [Page 13] - -Internet-Draft PCAP New Generation Dump File Format March 2004 - - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Interface ID | Drops Count | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Timestamp (High) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Timestamp (Low) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Captured Len | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Packet Len | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - | Packet Data | - | | - | /* variable length, byte-aligned */ | - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - / / - / Options (variable) / - / / - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - Figure 5: Packet Block format. - - The Packet Block has the following fields: - - o Interface ID: Specifies the interface this packet comes from, and - corresponds to the ID of one of the Interface Description Blocks - present in this section of the file (see Figure 4). - - o Drops Count: a local drop counter. It specified the number of - packets lost (by the interface and the operating system) between - this packet and the preceding one. The value xFFFF (in - hexadecimal) is reserved for those systems in which this - information is not available. - - o Timestamp (High): the most significative part of the timestamp. in - standard Unix format, i.e. from 1/1/1970. - - o Timestamp (Low): the less significative part of the timestamp. The - way to interpret this field is specified by the 'ts_accur' option - (see Figure 4) of the Interface Description block referenced by - this packet. If the Interface Description block does not contain a - 'ts_accur' option, then this field is expressed in microseconds. - - o Captured Len: number of bytes captured from the packet (i.e. the - - - -Degioanni & Risso Expires August 30, 2004 [Page 14] - -Internet-Draft PCAP New Generation Dump File Format March 2004 - - - length of the Packet Data field). It will be the minimum value - among the actual Packet Length and the snapshot length (defined in - Figure 4). - - o Packet Len: actual length of the packet when it was transmitted on - the network. Can be different from Captured Len if the user wants - only a snapshot of the packet. - - o Packet Data: the data coming from the network, including - link-layer headers. The length of this field is Captured Len. The - format of the link-layer headers depends on the LinkType field - specified in the Interface Description Block (see Section 3.2) and - it is specified in Appendix XXX (TODO). - - o Options: optionally, a list of options (formatted according to the - rules defined in Section 4) can be present. - - -3.4 Simple Packet Block (optional) - - The Simple Packet Block is a lightweight container for storing the - packets coming from the network. Its presence is optional. - - A Simple Packet Block is similar to a Packet Block (see Section 3.3), - but it is smaller, simpler to process and contains only a minimal set - of information. This block is preferred to the standard Packet Block - when performance or space occupation are critical factors, such as in - sustained traffic dump applications. A capture file can contain both - Packet Blocks and Simple Packet Blocks: for example, a capture tool - could switch from Packet Blocks to Simple Packet Blocks when the - hardware resources become critical. - - The Simple Packet Block does not contain the Interface ID field. - Therefore, it must be assumed that all the Simple Packet Blocks have - been captured on the interface previously specified in the Interface - Description Block. - - Figure 6 shows the format of the Simple Packet Block. - - - - - - - - - - - - - -Degioanni & Risso Expires August 30, 2004 [Page 15] - -Internet-Draft PCAP New Generation Dump File Format March 2004 - - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Packet Len | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - | Packet Data | - | | - | /* variable length, byte-aligned */ | - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - Figure 6: Simple Packet Block format. - - The Packet Block has the following fields: - - o Packet Len: actual length of the packet when it was transmitted on - the network. Can be different from captured len if the packet has - been truncated. - - o Packet data: the data coming from the network, including - link-layers headers. The length of this field can be derived from - the field Block Total Length, present in the Block Header. - - The Simple Packet Block does not contain the timestamp because this - is one of the most costly operations on PCs. Additionally, there are - applications that do not require it; e.g. an Intrusion Detection - System is interested in packets, not in their timestamp. - - The Simple Packet Block is very efficient in term of disk space: a - snapshot of length 100 bytes requires only 16 bytes of overhead, - which corresponds to an efficiency of more than 86%. - -3.5 Name Resolution Block (optional) - - The Name Resolution Block is used to support the correlation of - numeric addresses (present in the captured packets) and their - corresponding canonical names and it is optional. Having the literal - names saved in the file, this prevents the need of a name resolution - in a delayed time, when the association between names and addresses - can be different from the one in use at capture time. Moreover, The - Name Resolution Block avoids the need of issuing a lot of DNS - requests every time the trace capture is opened, and allows to have - name resolution also when reading the capture with a machine not - connected to the network. - - The format of the Name Resolution Block is shown in Figure 7. - - - - -Degioanni & Risso Expires August 30, 2004 [Page 16] - -Internet-Draft PCAP New Generation Dump File Format March 2004 - - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Record Type | Record Length | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Record Value | - | /* variable length, byte-aligned */ | - | + + + + + + + + + + + + + + + + + + + + + + + + + - | | | | | - +-+-+-+-+-+-+-+-+ + + + + + + + + + + + + + + + + + + + + + + + + - . . . other records . . . - | Record Type == end_of_recs | Record Length == 00 | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - / / - / Options (variable) / - / / - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - Figure 7: Name Resolution Block format. - - A Name Resolution Block is a zero-terminated list of records (in the - TLV format), each of which contains an association between a network - address and a name. There are three possible types of records: - - +----------------+----------------+----------------+----------------+ - | Name | Code | Length | Description | - +----------------+----------------+----------------+----------------+ - | end_of_recs | 0 | 0 | End of records | - | | | | | - | ip4_rec | 1 | Variable | Specifies an | - | | | | IPv4 address | - | | | | (contained in | - | | | | the first 4 | - | | | | bytes), | - | | | | followed by | - | | | | one or more | - | | | | zero-terminate | - | | | | d strings | - | | | | containing the | - | | | | DNS entries | - | | | | for that | - | | | | address. | - | | | | | - | ip6_rec | 1 | Variable | Specifies an | - | | | | IPv6 address | - | | | | (contained in | - | | | | the first 16 | - | | | | bytes), | - - - -Degioanni & Risso Expires August 30, 2004 [Page 17] - -Internet-Draft PCAP New Generation Dump File Format March 2004 - - - | | | | followed by | - | | | | one or more | - | | | | zero-terminate | - | | | | d strings | - | | | | containing the | - | | | | DNS entries | - | | | | for that | - | | | | address. | - +----------------+----------------+----------------+----------------+ - - Table 3 - - After the list or Name Resolution Records, optionally, a list of - options (formatted according to the rules defined in Section 4) can - be present. - - A Name Resolution Block is normally placed at the beginning of the - file, but no assumptions can be taken about its position. Name - Resolution Blocks can be added in a second time by tools that process - the file, like network analyzers. - - In addiction to the options defined in Section 4, the following - options are valid within this block: - - +----------------+----------------+----------------+----------------+ - | Name | Code | Length | Description | - +----------------+----------------+----------------+----------------+ - | ns_dnsname | 2 | Variable | An ascii | - | | | | string | - | | | | containing the | - | | | | name of the | - | | | | machine (DNS | - | | | | server) used | - | | | | to perform the | - | | | | name | - | | | | resolution. | - +----------------+----------------+----------------+----------------+ - - -3.6 Interface Statistics Block (optional) - - The Interface Statistics Block contains the capture statistics for a - given interface and it is optional. The statistics are referred to - the interface defined in the current Section identified by the - Interface ID field. - - The format of the Interface Statistics Block is shown in Figure 8. - - - - -Degioanni & Risso Expires August 30, 2004 [Page 18] - -Internet-Draft PCAP New Generation Dump File Format March 2004 - - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | IfRecv | - | (high + low) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | IfDrop | - | (high + low) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | FilterAccept | - | (high + low) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | OSDrop | - | (high + low) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | UsrDelivered | - | (high + low) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Interface ID | Reserved | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - / / - / Options (variable) / - / / - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - Figure 8: Interface Statistics Block format. - - The fields have the following meaning: - - o IfRecv: number of packets received from the interface during the - capture. This number is reported as a 64 bits value, in which the - most significat bits are located in the first four bytes of the - field. - - o IfDrop: number of packets dropped by the interface during the - capture due to lack of resources. - - o FilterAccept: number of packets accepeted by filter during current - capture. - - o OSDrop: number of packets dropped by the operating system during - the capture. - - o UsrDelivered: number of packets delivered to the user. - UsrDelivered can be different from the value 'FilterAccept - - OSDropped' because some packets could still lay in the OS buffers - when the capture ended. - - - - -Degioanni & Risso Expires August 30, 2004 [Page 19] - -Internet-Draft PCAP New Generation Dump File Format March 2004 - - - o Interface ID: reference to an Interface Description Block. - - o Reserved: Reserved to future use. - - o Options: optionally, a list of options (formatted according to the - rules defined in Section 4) can be present. - - In addiction to the options defined in Section 4, the following - options are valid within this block: - - +----------------+----------------+----------------+----------------+ - | Name | Code | Length | Description | - +----------------+----------------+----------------+----------------+ - | isb_starttime | 2 | 8 | Time in which | - | | | | the capture | - | | | | started; time | - | | | | will be stored | - | | | | in two blocks | - | | | | of four bytes | - | | | | each, | - | | | | containing the | - | | | | timestamp in | - | | | | seconds and | - | | | | nanoseconds. | - | | | | | - | isb_endtime | 3 | 8 | Time in which | - | | | | the capture | - | | | | started; time | - | | | | will be stored | - | | | | in two blocks | - | | | | of four bytes | - | | | | each, | - | | | | containing the | - | | | | timestamp in | - | | | | seconds and | - | | | | nanoseconds. | - +----------------+----------------+----------------+----------------+ - - - - - - - - - - - - - - -Degioanni & Risso Expires August 30, 2004 [Page 20] - -Internet-Draft PCAP New Generation Dump File Format March 2004 - - -4. Options - - Almost all blocks have the possibility to embed optional fields. - Optional fields can be used to insert some information that may be - useful when reading data, but that it is not really needed for packet - processing. Therefore, each tool can be either read the content of - the optional fields (if any), or skip them at once. - - Skipping all the optional fields at once is straightforward because - most of the blocks have a fixed length, therefore the field Block - Length (present in the General Block Structure, see Section 2.1) can - be used to skip everything till the next block. - - Options are a list of Type - Length - Value fields, each one - containing a single value: - - o Option Type (2 bytes): it contains the code that specifies the - type of the current TLV record. Option types whose Most - Significant Bit is equal to one are reserved for local use; - therefore, there is no guarantee that the code used is unique - among all capture files (generated by other applications). In case - of vendor-specific extensions that have to be identified uniquely, - vendors must request an Option Code whose MSB is equal to zero. - - o Option Length (2 bytes): it contains the length of the following - 'Option Value' field. - - o Option Value (variable length): it contains the value of the given - option. The length of this field as been specified by the Option - Length field. - - Options may be repeated several times (e.g. an interface that has - several IP addresses associated to it). The option list is terminated - by a special code which is the 'End of Option'. - - The format of the optional fields is shown in Figure 9. - - - - - - - - - - - - - - - -Degioanni & Risso Expires August 30, 2004 [Page 21] - -Internet-Draft PCAP New Generation Dump File Format March 2004 - - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Option Code | Option Length | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Option Value | - | /* variable length, byte-aligned */ | - | + + + + + + + + + + + + + + + + + + + + + + + + + - | / / / | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - / / - / . . . other options . . . / - / / - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Option Code == opt_endofopt | Option Length == 0 | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - Figure 9: Options format. - - The following codes can always be present in any optional field: - - +----------------+----------------+----------------+----------------+ - | Name | Code | Length | Description | - +----------------+----------------+----------------+----------------+ - | opt_endofopt | 0 | 0 | End of | - | | | | options: it is | - | | | | used to | - | | | | delimit the | - | | | | end of the | - | | | | optional | - | | | | fields. This | - | | | | block cannot | - | | | | be repeated | - | | | | within a given | - | | | | list of | - | | | | options. | - | | | | | - | opt_comment | 1 | variable | Comment: it is | - | | | | an ascii | - | | | | string | - | | | | containing a | - | | | | comment that | - | | | | is associated | - | | | | to the current | - | | | | block. | - +----------------+----------------+----------------+----------------+ - - - - - -Degioanni & Risso Expires August 30, 2004 [Page 22] - -Internet-Draft PCAP New Generation Dump File Format March 2004 - - -5. Experimental Blocks (deserved to a further investigation) - -5.1 Other Packet Blocks (experimental) - - Can some other packet blocks (besides the two described in the - previous paragraphs) be useful? - -5.2 Compression Block (experimental) - - The Compression Block is optional. A file can contain an arbitrary - number of these blocks. A Compression Block, as the name says, is - used to store compressed data. Its format is shown in Figure 10. - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Compr. Type | | - +-+-+-+-+-+-+-+-+ | - | | - | Compressed Data | - | | - | /* variable length, byte-aligned */ | - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - Figure 10: Compression Block format. - - The fields have the following meaning: - - o Compression Type: specifies the compression algorithm. Possible - values for this field are 0 (uncompressed), 1 (Lempel Ziv), 2 - (Gzip), other?? Probably some kind of dumb and fast compression - algorithm could be effective with some types of traffic (for - example web), but which? - - o Compressed Data: data of this block. Once decompressed, it is made - of other blocks. - - -5.3 Encryption Block (experimental) - - The Encryption Block is optional. A file can contain an arbitrary - number of these blocks. An Encryption Block is used to sotre - encrypted data. Its format is shown in Figure 11. - - - - - - - -Degioanni & Risso Expires August 30, 2004 [Page 23] - -Internet-Draft PCAP New Generation Dump File Format March 2004 - - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Encr. Type | | - +-+-+-+-+-+-+-+-+ | - | | - | Compressed Data | - | | - | /* variable length, byte-aligned */ | - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - Figure 11: Encryption Block format. - - The fields have the following meaning: - - o Compression Type: specifies the encryption algorithm. Possible - values for this field are ??? NOTE: this block should probably - contain other fields, depending on the encryption algorithm. To be - define precisely. - - o Encrypted Data: data of this block. Once decripted, it consists of - other blocks. - - -5.4 Fixed Length Block (experimental) - - The Fixed Length Block is optional. A file can contain an arbitrary - number of these blocks. A Fixed Length Block can be used to optimize - the access to the file. Its format is shown in Figure 12. A Fixed - Length Block stores records with constant size. It contains a set of - Blocks (normally Packet Blocks or Simple Packet Blocks), of wihich it - specifies the size. Knowing this size a priori helps to scan the file - and to load some portions of it without truncating a block, and is - particularly useful with cell-based networks like ATM. - - - - - - - - - - - - - - - - -Degioanni & Risso Expires August 30, 2004 [Page 24] - -Internet-Draft PCAP New Generation Dump File Format March 2004 - - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Cell Size | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | - | | - | Fixed Size Data | - | | - | /* variable length, byte-aligned */ | - | | - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - Figure 12: Fixed Length Block format. - - The fields have the following meaning: - - o Cell size: the size of the blocks contained in the data field. - - o Fixed Size Data: data of this block. - - -5.5 Directory Block (experimental) - - If present, this block contains the following information: - - o number of indexed packets (N) - - o table with position and length of any indexed packet (N entries) - - A directory block must be followed by at least N packets, otherwise - it must be considered invalid. It can be used to efficiently load - portions of the file to memory and to support operations on memory - mapped files. This block can be added by tools like network analyzers - as a consequence of file processing. - -5.6 Traffic Statistics and Monitoring Blocks (experimental) - - One or more blocks could be defined to contain network statistics or - traffic monitoring information. They could be use to store data - collected from RMON or Netflow probes, or from other network - monitoring tools. - -5.7 Event/Security Block (experimental) - - This block could be used to store events. Events could contain - generic information (for example network load over 50%, server - down...) or security alerts. An event could be: - - - -Degioanni & Risso Expires August 30, 2004 [Page 25] - -Internet-Draft PCAP New Generation Dump File Format March 2004 - - - o skipped, if the application doesn't know how to do with it - - o processed independently by the packets. In other words, the - applications skips the packets and processes only the alerts - - o processed in relation to packets: for example, a security tool - could load only the packets of the file that are near a security - alert; a monitorg tool could skip the packets captured while the - server was down. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Degioanni & Risso Expires August 30, 2004 [Page 26] - -Internet-Draft PCAP New Generation Dump File Format March 2004 - - -6. Conclusions - - The file format proposed in this document should be very versatile - and satisfy a wide range of applications. In the simplest case, it - can contain a raw dump of the network data, made of a series of - Simple Packet Blocks. In the most complex case, it can be used as a - repository for heterogeneous information. In every case, the file - remains easy to parse and an application can always skip the data it - is not interested in; at the same time, different applications can - share the file, and each of them can benfit of the information - produced by the others. Two or more files can be concatenated - obtaining another valid file. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Degioanni & Risso Expires August 30, 2004 [Page 27] - -Internet-Draft PCAP New Generation Dump File Format March 2004 - - -7. Most important open issues - - o Data, in the file, must be byte or word aligned? Currently, the - structure of this document is not consistent with respect to this - point. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Degioanni & Risso Expires August 30, 2004 [Page 28] - -Internet-Draft PCAP New Generation Dump File Format March 2004 - - -Intellectual Property Statement - - The IETF takes no position regarding the validity or scope of any - intellectual property or other rights that might be claimed to - pertain to the implementation or use of the technology described in - this document or the extent to which any license under such rights - might or might not be available; neither does it represent that it - has made any effort to identify any such rights. Information on the - IETF's procedures with respect to rights in standards-track and - standards-related documentation can be found in BCP-11. Copies of - claims of rights made available for publication and any assurances of - licenses to be made available, or the result of an attempt made to - obtain a general license or permission for the use of such - proprietary rights by implementors or users of this specification can - be obtained from the IETF Secretariat. - - The IETF invites any interested party to bring to its attention any - copyrights, patents or patent applications, or other proprietary - rights which may cover technology that may be required to practice - this standard. Please address the information to the IETF Executive - Director. - - -Full Copyright Statement - - Copyright (C) The Internet Society (2004). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assignees. - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - - - -Degioanni & Risso Expires August 30, 2004 [Page 29] - -Internet-Draft PCAP New Generation Dump File Format March 2004 - - - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - - -Acknowledgment - - Funding for the RFC Editor function is currently provided by the - Internet Society. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Degioanni & Risso Expires August 30, 2004 [Page 30] - diff --git a/libpcap/doc/pcap.xml b/libpcap/doc/pcap.xml deleted file mode 100644 index ebbf3217f..000000000 --- a/libpcap/doc/pcap.xml +++ /dev/null @@ -1,746 +0,0 @@ - - - - - - - - PCAP New Generation Dump File Format - - Politecnico di Torino -
- - Corso Duca degli Abruzzi, 24 - Torino - 10129 - Italy - - +39 011 564 7008 - loris.degioanni@polito.it - http://netgroup.polito.it/loris/ -
-
- - Politecnico di Torino -
- - Corso Duca degli Abruzzi, 24 - Torino - 10129 - Italy - - +39 011 564 7008 - fulvio.risso@polito.it - http://netgroup.polito.it/fulvio.risso/ -
-
- - - - - General - - Internet-Draft - Libpcap, dump file format - -This document describes a format to dump captured packets on a file. This format is extensible and it is currently proposed for implementation in the libpcap/WinPcap packet capture library. - - -
- - -
-The problem of exchanging packet traces becomes more and more critical every day; unfortunately, no standard solutions exist for this task right now. One of the most accepted packet interchange formats is the one defined by libpcap, which is rather old and does not fit for some of the nowadays applications especially in terms of extensibility. -This document proposes a new format for dumping packet traces. The following goals are being pursued: - -Extensibility: aside of some common functionalities, third parties should be able to enrich the information embedded in the file with proprietary extensions, which will be ignored by tools that are not able to understand them. -Portability: a capture trace must contain all the information needed to read data independently from network, hardware and operating system of the machine that made the capture. -Merge/Append data: it should be possible to add data at the end of a given file, and the resulting file must still be readable. - - -
- - -
- -
-A capture file is organized in blocks, that are appended one to another to form the file. All the blocks share a common format, which is shown in . - -
- - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Block Type | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Block Total Length | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - / Block Body / - / /* variable length, aligned to 32 bits */ / - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Block Total Length | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -
- -The fields have the following meaning: - - -Block Type (32 bits): unique value that identifies the block. Values whose Most Significant Bit (MSB) is equal to 1 are reserved for local use. They allow to save private data to the file and to extend the file format. -Block Total Length: total size of this block, in bytes. For instance, a block that does not have a body has a length of 12 bytes. -Block Body: content of the block. -Block Total Length: total size of this block, in bytes. This field is duplicated for permitting backward file navigation. - - -This structure, shared among all blocks, makes easy to process a file and to skip unneeded or unknown blocks. Blocks can be nested one inside the others (NOTE: needed?). Some of the blocks are mandatory, i.e. a dump file is not valid if they are not present, other are optional. -The structure of the blocks allows to define other blocks if needed. A parser that does non understand them can simply ignore their content. -
- -
-The currently defined blocks are the following: - -Section Header Block: it defines the most important characteristics of the capture file. -Interface Description Block: it defines the most important characteristics of the interface(s) used for capturing traffic. -Packet Block: it contains a single captured packet, or a portion of it. -Simple Packet Block: it contains a single captured packet, or a portion of it, with only a minimal set of information about it. -Name Resolution Block: it defines the mapping from numeric addresses present in the packet dump and the canonical name counterpart. -Capture Statistics Block: it defines how to store some statistical data (e.g. packet dropped, etc) which can be useful to undestand the conditions in which the capture has been made. -Compression Marker Block: TODO -Encryption Marker Block: TODO -Fixed Length Marker Block: TODO - - -The following blocks instead are considered interesting but the authors believe that they deserve more in-depth discussion before being defined: - -Further Packet Blocks -Directory Block -Traffic Statistics and Monitoring Blocks -Alert and Security Blocks - - -TODO Currently standardized Block Type codes are specified in Appendix 1. - -
- -
-The file must begin with a Section Header Block. However, more than one Section Header Block can be present on the dump, each one covering the data following it till the next one (or the end of file). A Section includes the data delimited by two Section Header Blocks (or by a Section Header Block and the end of the file), including the first Section Header Block. -In case an application cannot read a Section because of different version number, it must skip everything until the next Section Header Block. Note that, in order to properly skip the blocks until the next section, all blocks must have the fields Type and Length at the beginning. This is a mandatory requirement that must be maintained in future versions of the block format. - shows two valid files: the first has a typical configuration, with a single Section Header that covers the whole file. The second one contains three headers, and is normally the result of file concatenation. An application that understands only version 1.0 of the file format skips the intermediate section and restart processing the packets after the third Section Header. - -
- - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | SHB v1.0 | Data | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - Typical configuration with a single Section Header Block - - - |-- 1st Section --|-- 2nd Section --|-- 3rd Section --| - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | SHB v1.0 | Data | SHB V1.1 | Data | SHB V1.0 | Data | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - Configuration with three different Section Header Blocks - -
- -NOTE: TO BE COMPLETED with some examples of other blocks - -
- -
-Data contained in each section will always be saved according to the characteristics (little endian / big endian) of the dumping machine. This refers to all fields that are saved as numbers and that span over two or more bytes. -The approach of having each section saved in the native format of the generating host is more efficient because it avoids translation of data when reading / writing on the host itself, which is the most common case when generating/processing capture dumps. -TODO Probably we have to specify something more here. Is what we're saying enough to avoid any kind of ambiguity?. -
- -
- - - - -
-This section details the format of the body of the blocks currently defined. - -
-The Section Header Block is mandatory. It identifies the beginning of a section of the capture dump file. Its format is shown in . -
- - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Magic | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Major | Minor | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - / / - / Options (variable) / - / / - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -
- -The meaning of the fields is: - -Magic: magic number, whose value is the hexadecimal number 0x1A2B3C4D. This number can be used to distinguish section that have been saved on little-endian machines from the one saved on big-endian machines. -Major: number of the current mayor version of the format. Current value is 1. -Minor: number of the current minor version of the format. Current value is 0. -Options: optionally, a list of options (formatted according to the rules defined in ) can be present. - - -Aside form the options defined in , the following options are valid within this block: - - - Name - Code - Length - Description - - Hardware - 2 - variable - An ascii string containing the description of the hardware used to create this section. - - Operating System - 3 - variable - An ascii string containing the name of the operating system used to create this section. - - User Application - 3 - variable - An ascii string containing the name of the application used to create this section. - - - -The Section Header Block does not contain data but it rather identifies a list of blocks (interfaces, packets) that are logically correlated. This block does not contain any reference to the size of the section it is currently delimiting, therefore the reader cannot skip a whole section at once. In case a section must be skipped, the user has to repeatedly skip all the blocks contained within it; this makes the parsing of the file slower but it permits to append several capture dumps at the same file. -
- -
-The Interface Description Block is mandatory. This block is needed to specify the characteristics of the network interface on which the capture has been made. In order to properly associate the captured data to the corresponding interface, the Interface Description Block must be defined before any other block that uses it; therefore, this block is usually placed immediately after the Section Header Block. - -An Interface Description Block is valid only inside the section which it belongs to. The structure of a Interface Description Block is shown in . - -
- - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Interface ID | LinkType | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | SnapLen | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - / / - / Options (variable) / - / / - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -
- -The meaning of the fields is: - -Interface ID: a progressive number that identifies uniquely any interface inside current section. Two Interface Description Blocks can have the same Interface ID only if they are in different sections of the file. The Interface ID is referenced by the packet blocks. -LinkType: a value that defines the link layer type of this interface. -SnapLen: maximum number of bytes dumped from each packet. The portion of each packet that exceeds this value will not be stored in the file. -Options: optionally, a list of options (formatted according to the rules defined in ) can be present. - - -In addition to the options defined in , the following options are valid within this block: - - - Name - Code - Length - Description - - if_name - 2 - Variable - Name of the device used to capture data. - - if_IPv4addr - 3 - 8 - Interface network address and netmask. - - if_IPv6addr - 4 - 17 - Interface network address and prefix length (stored in the last byte). - - if_MACaddr - 5 - 6 - Interface Hardware MAC address (48 bits). - - if_EUIaddr - 6 - 8 - Interface Hardware EUI address (64 bits), if available. - - if_speed - 7 - 8 - Interface speed (in bps). - - if_tsaccur - 8 - 1 - Precision of timestamps. If the Most Significant Bit is equal to zero, the remaining bits indicates the accuracy as as a negative power of 10 (e.g. 6 means microsecond accuracy). If the Most Significant Bit is equal to zero, the remaining bits indicates the accuracy as as negative power of 2 (e.g. 10 means 1/1024 of second). If this option is not present, a precision of 10^-6 is assumed. - - if_tzone - 9 - 4 - Time zone for GMT support (TODO: specify better). - - if_flags - 10 - 4 - Interface flags. (TODO: specify better. Possible flags: promiscuous, inbound/outbound, traffic filtered during capture). - - if_filter - 11 - variable - The filter (e.g. "capture only TCP traffic") used to capture traffic. The first byte of the Option Data keeps a code of the filter used (e.g. if this is a libpcap string, or BPF bytecode, and more). More details about this format will be presented in Appendix XXX (TODO). - - if_opersystem - 12 - variable - An ascii string containing the name of the operating system of the machine that hosts this interface. This can be different from the same information that can be contained by the Section Header Block () because the capture can have been done on a remote machine. - - - -
- - - -
-A Packet Block is the standard container for storing the packets coming from the network. The Packet Block is optional because packets can be stored either by means of this block or the Simple Packet Block, which can be used to speed up dump generation. The format of a packet block is shown in . - -
- - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Interface ID | Drops Count | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Timestamp (High) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Timestamp (Low) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Captured Len | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Packet Len | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - | Packet Data | - | | - | /* variable length, byte-aligned */ | - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - / / - / Options (variable) / - / / - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -
- -The Packet Block has the following fields: - - -Interface ID: Specifies the interface this packet comes from, and corresponds to the ID of one of the Interface Description Blocks present in this section of the file (see ). -Drops Count: a local drop counter. It specified the number of packets lost (by the interface and the operating system) between this packet and the preceding one. The value xFFFF (in hexadecimal) is reserved for those systems in which this information is not available. -Timestamp (High): the most significative part of the timestamp. in standard Unix format, i.e. from 1/1/1970. -Timestamp (Low): the less significative part of the timestamp. The way to interpret this field is specified by the 'ts_accur' option (see ) of the Interface Description block referenced by this packet. If the Interface Description block does not contain a 'ts_accur' option, then this field is expressed in microseconds. -Captured Len: number of bytes captured from the packet (i.e. the length of the Packet Data field). It will be the minimum value among the actual Packet Length and the snapshot length (defined in ). -Packet Len: actual length of the packet when it was transmitted on the network. Can be different from Captured Len if the user wants only a snapshot of the packet. -Packet Data: the data coming from the network, including link-layer headers. The length of this field is Captured Len. The format of the link-layer headers depends on the LinkType field specified in the Interface Description Block (see ) and it is specified in Appendix XXX (TODO). -Options: optionally, a list of options (formatted according to the rules defined in ) can be present. - - - -
- - -
-The Simple Packet Block is a lightweight container for storing the packets coming from the network. Its presence is optional. -A Simple Packet Block is similar to a Packet Block (see ), but it is smaller, simpler to process and contains only a minimal set of information. This block is preferred to the standard Packet Block when performance or space occupation are critical factors, such as in sustained traffic dump applications. A capture file can contain both Packet Blocks and Simple Packet Blocks: for example, a capture tool could switch from Packet Blocks to Simple Packet Blocks when the hardware resources become critical. -The Simple Packet Block does not contain the Interface ID field. Therefore, it must be assumed that all the Simple Packet Blocks have been captured on the interface previously specified in the Interface Description Block. - shows the format of the Simple Packet Block. - -
- - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Packet Len | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - | Packet Data | - | | - | /* variable length, byte-aligned */ | - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -
- -The Packet Block has the following fields: - -Packet Len: actual length of the packet when it was transmitted on the network. Can be different from captured len if the packet has been truncated. -Packet data: the data coming from the network, including link-layers headers. The length of this field can be derived from the field Block Total Length, present in the Block Header. - - -The Simple Packet Block does not contain the timestamp because this is one of the most costly operations on PCs. Additionally, there are applications that do not require it; e.g. an Intrusion Detection System is interested in packets, not in their timestamp. - -The Simple Packet Block is very efficient in term of disk space: a snapshot of length 100 bytes requires only 16 bytes of overhead, which corresponds to an efficiency of more than 86%. - -
- - - -
-The Name Resolution Block is used to support the correlation of numeric addresses (present in the captured packets) and their corresponding canonical names and it is optional. Having the literal names saved in the file, this prevents the need of a name resolution in a delayed time, when the association between names and addresses can be different from the one in use at capture time. Moreover, The Name Resolution Block avoids the need of issuing a lot of DNS requests every time the trace capture is opened, and allows to have name resolution also when reading the capture with a machine not connected to the network. -The format of the Name Resolution Block is shown in . - -
- - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Record Type | Record Length | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Record Value | - | /* variable length, byte-aligned */ | - | + + + + + + + + + + + + + + + + + + + + + + + + + - | | | | | - +-+-+-+-+-+-+-+-+ + + + + + + + + + + + + + + + + + + + + + + + + - . . . other records . . . - | Record Type == end_of_recs | Record Length == 00 | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - / / - / Options (variable) / - / / - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -
- -A Name Resolution Block is a zero-terminated list of records (in the TLV format), each of which contains an association between a network address and a name. There are three possible types of records: - - - Name - Code - Length - Description - - end_of_recs - 0 - 0 - End of records - - ip4_rec - 1 - Variable - Specifies an IPv4 address (contained in the first 4 bytes), followed by one or more zero-terminated strings containing the DNS entries for that address. - - ip6_rec - 1 - Variable - Specifies an IPv6 address (contained in the first 16 bytes), followed by one or more zero-terminated strings containing the DNS entries for that address. - - -After the list or Name Resolution Records, optionally, a list of options (formatted according to the rules defined in ) can be present. - -A Name Resolution Block is normally placed at the beginning of the file, but no assumptions can be taken about its position. Name Resolution Blocks can be added in a second time by tools that process the file, like network analyzers. - -In addiction to the options defined in , the following options are valid within this block: - - - Name - Code - Length - Description - - ns_dnsname - 2 - Variable - An ascii string containing the name of the machine (DNS server) used to perform the name resolution. - - -
- - -
-The Interface Statistics Block contains the capture statistics for a given interface and it is optional. The statistics are referred to the interface defined in the current Section identified by the Interface ID field. -The format of the Interface Statistics Block is shown in . - -
- - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | IfRecv | - | (high + low) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | IfDrop | - | (high + low) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | FilterAccept | - | (high + low) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | OSDrop | - | (high + low) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | UsrDelivered | - | (high + low) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Interface ID | Reserved | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - / / - / Options (variable) / - / / - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -
- -The fields have the following meaning: - - -IfRecv: number of packets received from the interface during the capture. This number is reported as a 64 bits value, in which the most significat bits are located in the first four bytes of the field. -IfDrop: number of packets dropped by the interface during the capture due to lack of resources. -FilterAccept: number of packets accepeted by filter during current capture. -OSDrop: number of packets dropped by the operating system during the capture. -UsrDelivered: number of packets delivered to the user. UsrDelivered can be different from the value 'FilterAccept - OSDropped' because some packets could still lay in the OS buffers when the capture ended. -Interface ID: reference to an Interface Description Block. -Reserved: Reserved to future use. -Options: optionally, a list of options (formatted according to the rules defined in ) can be present. - - -In addiction to the options defined in , the following options are valid within this block: - - - Name - Code - Length - Description - - isb_starttime - 2 - 8 - Time in which the capture started; time will be stored in two blocks of four bytes each, containing the timestamp in seconds and nanoseconds. - - isb_endtime - 3 - 8 - Time in which the capture started; time will be stored in two blocks of four bytes each, containing the timestamp in seconds and nanoseconds. - - -
-
- - - -
-Almost all blocks have the possibility to embed optional fields. Optional fields can be used to insert some information that may be useful when reading data, but that it is not really needed for packet processing. Therefore, each tool can be either read the content of the optional fields (if any), or skip them at once. -Skipping all the optional fields at once is straightforward because most of the blocks have a fixed length, therefore the field Block Length (present in the General Block Structure, see ) can be used to skip everything till the next block. - -Options are a list of Type - Length - Value fields, each one containing a single value: - - -Option Type (2 bytes): it contains the code that specifies the type of the current TLV record. Option types whose Most Significant Bit is equal to one are reserved for local use; therefore, there is no guarantee that the code used is unique among all capture files (generated by other applications). In case of vendor-specific extensions that have to be identified uniquely, vendors must request an Option Code whose MSB is equal to zero. -Option Length (2 bytes): it contains the length of the following 'Option Value' field. -Option Value (variable length): it contains the value of the given option. The length of this field as been specified by the Option Length field. - - -Options may be repeated several times (e.g. an interface that has several IP addresses associated to it). The option list is terminated by a special code which is the 'End of Option'. - -The format of the optional fields is shown in . - -
- - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Option Code | Option Length | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Option Value | - | /* variable length, byte-aligned */ | - | + + + + + + + + + + + + + + + + + + + + + + + + + - | / / / | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - / / - / . . . other options . . . / - / / - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Option Code == opt_endofopt | Option Length == 0 | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -
- -The following codes can always be present in any optional field: - - - Name - Code - Length - Description - - opt_endofopt - 0 - 0 - End of options: it is used to delimit the end of the optional fields. This block cannot be repeated within a given list of options. - - opt_comment - 1 - variable - Comment: it is an ascii string containing a comment that is associated to the current block. - - -
- - - - -
- -
-Can some other packet blocks (besides the two described in the previous paragraphs) be useful? -
- -
-The Compression Block is optional. A file can contain an arbitrary number of these blocks. A Compression Block, as the name says, is used to store compressed data. Its format is shown in . - -
- - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Compr. Type | | - +-+-+-+-+-+-+-+-+ | - | | - | Compressed Data | - | | - | /* variable length, byte-aligned */ | - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -
- -The fields have the following meaning: - - -Compression Type: specifies the compression algorithm. Possible values for this field are 0 (uncompressed), 1 (Lempel Ziv), 2 (Gzip), other?? Probably some kind of dumb and fast compression algorithm could be effective with some types of traffic (for example web), but which? -Compressed Data: data of this block. Once decompressed, it is made of other blocks. - - -
- - -
-The Encryption Block is optional. A file can contain an arbitrary number of these blocks. An Encryption Block is used to sotre encrypted data. Its format is shown in . - -
- - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Encr. Type | | - +-+-+-+-+-+-+-+-+ | - | | - | Compressed Data | - | | - | /* variable length, byte-aligned */ | - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -
- -The fields have the following meaning: - -Compression Type: specifies the encryption algorithm. Possible values for this field are ??? NOTE: this block should probably contain other fields, depending on the encryption algorithm. To be define precisely. -Encrypted Data: data of this block. Once decripted, it consists of other blocks. - - -
- - -
-The Fixed Length Block is optional. A file can contain an arbitrary number of these blocks. A Fixed Length Block can be used to optimize the access to the file. Its format is shown in . -A Fixed Length Block stores records with constant size. It contains a set of Blocks (normally Packet Blocks or Simple Packet Blocks), of wihich it specifies the size. Knowing this size a priori helps to scan the file and to load some portions of it without truncating a block, and is particularly useful with cell-based networks like ATM. - -
- - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Cell Size | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | - | | - | Fixed Size Data | - | | - | /* variable length, byte-aligned */ | - | | - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -
- -The fields have the following meaning: - -Cell size: the size of the blocks contained in the data field. -Fixed Size Data: data of this block. - - -
- -
-If present, this block contains the following information: - -number of indexed packets (N) -table with position and length of any indexed packet (N entries) - - -A directory block must be followed by at least N packets, otherwise it must be considered invalid. It can be used to efficiently load portions of the file to memory and to support operations on memory mapped files. This block can be added by tools like network analyzers as a consequence of file processing. -
- -
-One or more blocks could be defined to contain network statistics or traffic monitoring information. They could be use to store data collected from RMON or Netflow probes, or from other network monitoring tools. -
- -
-This block could be used to store events. Events could contain generic information (for example network load over 50%, server down...) or security alerts. An event could be: - - -skipped, if the application doesn't know how to do with it -processed independently by the packets. In other words, the applications skips the packets and processes only the alerts -processed in relation to packets: for example, a security tool could load only the packets of the file that are near a security alert; a monitorg tool could skip the packets captured while the server was down. - - -
- -
- - - - -
-The file format proposed in this document should be very versatile and satisfy a wide range of applications. -In the simplest case, it can contain a raw dump of the network data, made of a series of Simple Packet Blocks. -In the most complex case, it can be used as a repository for heterogeneous information. -In every case, the file remains easy to parse and an application can always skip the data it is not interested in; at the same time, different applications can share the file, and each of them can benfit of the information produced by the others. -Two or more files can be concatenated obtaining another valid file. -
- - -
- -Data, in the file, must be byte or word aligned? Currently, the structure of this document is not consistent with respect to this point. - -
- -
- -
diff --git a/libpcap/etherent.c b/libpcap/etherent.c index 9d299557f..27e55024e 100644 --- a/libpcap/etherent.c +++ b/libpcap/etherent.c @@ -21,7 +21,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/etherent.c,v 1.22 2003/11/15 23:23:57 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/etherent.c,v 1.23 2006/10/04 18:09:22 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -37,7 +37,7 @@ static const char rcsid[] _U_ = #include "pcap-int.h" -#include +#include #ifdef HAVE_OS_PROTO_H #include "os-proto.h" diff --git a/libpcap/ethertype.h b/libpcap/ethertype.h index 2d21c6d9c..867d33eae 100644 --- a/libpcap/ethertype.h +++ b/libpcap/ethertype.h @@ -18,7 +18,7 @@ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * @(#) $Header: /tcpdump/master/libpcap/ethertype.h,v 1.13.2.1 2005/09/05 09:08:03 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/ethertype.h,v 1.14 2005/09/05 09:06:58 guy Exp $ (LBL) */ /* diff --git a/libpcap/fad-getad.c b/libpcap/fad-getad.c index 58305d565..2ce6d7009 100644 --- a/libpcap/fad-getad.c +++ b/libpcap/fad-getad.c @@ -34,7 +34,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/fad-getad.c,v 1.10.2.1 2005/04/10 18:04:49 hannes Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/fad-getad.c,v 1.12 2007/09/14 00:44:55 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -61,7 +61,11 @@ static const char rcsid[] _U_ = #endif #ifdef AF_PACKET -# include +# ifdef __Lynx__ +# include /* LynxOS */ +# else +# include /* Linux */ +# endif #endif /* diff --git a/libpcap/fad-gifc.c b/libpcap/fad-gifc.c index 985d2c0ba..ef04bd903 100644 --- a/libpcap/fad-gifc.c +++ b/libpcap/fad-gifc.c @@ -34,7 +34,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/fad-gifc.c,v 1.8.2.2 2005/06/29 06:43:31 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/fad-gifc.c,v 1.11.2.1 2008-08-06 07:35:01 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -42,7 +42,6 @@ static const char rcsid[] _U_ = #endif #include -#include #include #include #ifdef HAVE_SYS_SOCKIO_H diff --git a/libpcap/fad-glifc.c b/libpcap/fad-glifc.c index 8a86a3d2e..9e92bc359 100644 --- a/libpcap/fad-glifc.c +++ b/libpcap/fad-glifc.c @@ -34,7 +34,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/fad-glifc.c,v 1.5.2.1 2005/04/19 00:54:16 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/fad-glifc.c,v 1.6.2.1 2008/01/30 09:36:09 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -75,9 +75,9 @@ struct rtentry; /* declarations in */ * 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 SIOCLGIFCONF + * This is the implementation used on platforms that have SIOCGLIFCONF * but don't have "getifaddrs()". (Solaris 8 and later; we use - * SIOCLGIFCONF rather than SIOCGIFCONF in order to get IPv6 addresses.) + * SIOCGLIFCONF rather than SIOCGIFCONF in order to get IPv6 addresses.) */ int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) diff --git a/libpcap/fad-sita.c b/libpcap/fad-sita.c new file mode 100644 index 000000000..261904567 --- /dev/null +++ b/libpcap/fad-sita.c @@ -0,0 +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) { + + //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; +} diff --git a/libpcap/fad-win32.c b/libpcap/fad-win32.c index 4d2c01ede..19839c869 100644 --- a/libpcap/fad-win32.c +++ b/libpcap/fad-win32.c @@ -33,7 +33,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/fad-win32.c,v 1.11.2.3 2006/02/22 17:09:32 gianluca Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/fad-win32.c,v 1.15 2007/09/25 20:34:36 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -301,6 +301,15 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) name += strlen(name) + 1; desc += strlen(desc) + 1; } + + 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) { /* diff --git a/libpcap/filtertest.c b/libpcap/filtertest.c new file mode 100644 index 000000000..cfa69eab4 --- /dev/null +++ b/libpcap/filtertest.c @@ -0,0 +1,254 @@ +/* + * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000 + * 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 copyright[] _U_ = + "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\ +The Regents of the University of California. All rights reserved.\n"; +static const char rcsid[] _U_ = + "@(#) $Header: /tcpdump/master/libpcap/filtertest.c,v 1.2 2005/08/08 17:50:13 guy Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef HAVE___ATTRIBUTE__ +#define __attribute__(x) +#endif + +static char *program_name; + +/* Forwards */ +static void usage(void) __attribute__((noreturn)); +static void error(const char *, ...) + __attribute__((noreturn, format (printf, 1, 2))); + +extern int optind; +extern int opterr; +extern char *optarg; + +/* + * On Windows, we need to open the file in binary mode, so that + * we get all the bytes specified by the size we get from "fstat()". + * On UNIX, that's not necessary. O_BINARY is defined on Windows; + * we define it as 0 if it's not defined, so it does nothing. + */ +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +static char * +read_infile(char *fname) +{ + register int i, fd, cc; + register char *cp; + struct stat buf; + + fd = open(fname, O_RDONLY|O_BINARY); + if (fd < 0) + error("can't open %s: %s", fname, pcap_strerror(errno)); + + if (fstat(fd, &buf) < 0) + error("can't stat %s: %s", fname, pcap_strerror(errno)); + + cp = malloc((u_int)buf.st_size + 1); + if (cp == NULL) + error("malloc(%d) for %s: %s", (u_int)buf.st_size + 1, + fname, pcap_strerror(errno)); + cc = read(fd, cp, (u_int)buf.st_size); + if (cc < 0) + error("read %s: %s", fname, pcap_strerror(errno)); + if (cc != buf.st_size) + error("short read %s (%d != %d)", fname, cc, (int)buf.st_size); + + close(fd); + /* replace "# comment" with spaces */ + for (i = 0; i < cc; i++) { + if (cp[i] == '#') + while (i < cc && cp[i] != '\n') + cp[i++] = ' '; + } + cp[cc] = '\0'; + return (cp); +} + +/* VARARGS */ +static void +error(const char *fmt, ...) +{ + va_list ap; + + (void)fprintf(stderr, "%s: ", program_name); + va_start(ap, fmt); + (void)vfprintf(stderr, fmt, ap); + va_end(ap); + if (*fmt) { + fmt += strlen(fmt); + if (fmt[-1] != '\n') + (void)fputc('\n', stderr); + } + exit(1); + /* NOTREACHED */ +} + +/* + * Copy arg vector into a new buffer, concatenating arguments with spaces. + */ +static char * +copy_argv(register char **argv) +{ + register char **p; + register u_int len = 0; + char *buf; + char *src, *dst; + + p = argv; + if (*p == 0) + return 0; + + while (*p) + len += strlen(*p++) + 1; + + buf = (char *)malloc(len); + if (buf == NULL) + error("copy_argv: malloc"); + + p = argv; + dst = buf; + while ((src = *p++) != NULL) { + while ((*dst++ = *src++) != '\0') + ; + dst[-1] = ' '; + } + dst[-1] = '\0'; + + return buf; +} + +int +main(int argc, char **argv) +{ + char *cp; + int op; + int dflag; + char *infile; + int Oflag; + long snaplen; + int dlt; + char *cmdbuf; + pcap_t *pd; + struct bpf_program fcode; + +#ifdef WIN32 + if(wsockinit() != 0) return 1; +#endif /* WIN32 */ + + dflag = 1; + infile = NULL; + Oflag = 1; + snaplen = 68; + + if ((cp = strrchr(argv[0], '/')) != NULL) + program_name = cp + 1; + else + program_name = argv[0]; + + opterr = 0; + while ((op = getopt(argc, argv, "dF:Os:")) != -1) { + switch (op) { + + case 'd': + ++dflag; + break; + + case 'F': + infile = optarg; + break; + + case 'O': + Oflag = 0; + break; + + case 's': { + char *end; + + snaplen = strtol(optarg, &end, 0); + if (optarg == end || *end != '\0' + || snaplen < 0 || snaplen > 65535) + error("invalid snaplen %s", optarg); + else if (snaplen == 0) + snaplen = 65535; + break; + } + + default: + usage(); + /* NOTREACHED */ + } + } + + if (optind >= argc) { + usage(); + /* NOTREACHED */ + } + + dlt = pcap_datalink_name_to_val(argv[optind]); + if (dlt < 0) + error("invalid data link type %s", argv[optind]); + + if (infile) + cmdbuf = read_infile(infile); + else + cmdbuf = copy_argv(&argv[optind+1]); + + pd = pcap_open_dead(dlt, snaplen); + if (pd == NULL) + error("Can't open fake pcap_t"); + + if (pcap_compile(pd, &fcode, cmdbuf, Oflag, 0) < 0) + error("%s", pcap_geterr(pd)); + bpf_dump(&fcode, dflag); + pcap_close(pd); + exit(0); +} + +static void +usage(void) +{ + (void)fprintf(stderr, "%s, with %s\n", program_name, + pcap_lib_version()); + (void)fprintf(stderr, + "Usage: %s [-dO] [ -F file ] [ -s snaplen ] dlt [ expression ]\n", + program_name); + exit(1); +} diff --git a/libpcap/findalldevstest.c b/libpcap/findalldevstest.c new file mode 100644 index 000000000..ec7c95015 --- /dev/null +++ b/libpcap/findalldevstest.c @@ -0,0 +1,131 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include + +#include + +static void ifprint(pcap_if_t *d); +static char *iptos(bpf_u_int32 in); + +int main(int argc, char **argv) +{ + pcap_if_t *alldevs; + pcap_if_t *d; + char *s; + bpf_u_int32 net, mask; + + char errbuf[PCAP_ERRBUF_SIZE+1]; + if (pcap_findalldevs(&alldevs, errbuf) == -1) + { + fprintf(stderr,"Error in pcap_findalldevs: %s\n",errbuf); + exit(1); + } + for(d=alldevs;d;d=d->next) + { + ifprint(d); + } + + if ( (s = pcap_lookupdev(errbuf)) == NULL) + { + fprintf(stderr,"Error in pcap_lookupdev: %s\n",errbuf); + } + else + { + printf("Preferred device name: %s\n",s); + } + + if (pcap_lookupnet(s, &net, &mask, errbuf) < 0) + { + fprintf(stderr,"Error in pcap_lookupnet: %s\n",errbuf); + } + else + { + printf("Preferred device is on network: %s/%s\n",iptos(net), iptos(mask)); + } + + exit(0); +} + +static void ifprint(pcap_if_t *d) +{ + pcap_addr_t *a; +#ifdef INET6 + char ntop_buf[INET6_ADDRSTRLEN]; +#endif + + printf("%s\n",d->name); + if (d->description) + printf("\tDescription: %s\n",d->description); + printf("\tLoopback: %s\n",(d->flags & PCAP_IF_LOOPBACK)?"yes":"no"); + + for(a=d->addresses;a;a=a->next) { + switch(a->addr->sa_family) + { + case AF_INET: + printf("\tAddress Family: AF_INET\n"); + if (a->addr) + printf("\t\tAddress: %s\n", + inet_ntoa(((struct sockaddr_in *)(a->addr))->sin_addr)); + if (a->netmask) + printf("\t\tNetmask: %s\n", + inet_ntoa(((struct sockaddr_in *)(a->netmask))->sin_addr)); + if (a->broadaddr) + printf("\t\tBroadcast Address: %s\n", + inet_ntoa(((struct sockaddr_in *)(a->broadaddr))->sin_addr)); + if (a->dstaddr) + printf("\t\tDestination Address: %s\n", + inet_ntoa(((struct sockaddr_in *)(a->dstaddr))->sin_addr)); + break; +#ifdef INET6 + case AF_INET6: + printf("\tAddress Family: AF_INET6\n"); + if (a->addr) + printf("\t\tAddress: %s\n", + inet_ntop(AF_INET6, + ((struct sockaddr_in6 *)(a->addr))->sin6_addr.s6_addr, + ntop_buf, sizeof ntop_buf)); + if (a->netmask) + printf("\t\tNetmask: %s\n", + inet_ntop(AF_INET6, + ((struct sockaddr_in6 *)(a->netmask))->sin6_addr.s6_addr, + ntop_buf, sizeof ntop_buf)); + if (a->broadaddr) + printf("\t\tBroadcast Address: %s\n", + inet_ntop(AF_INET6, + ((struct sockaddr_in6 *)(a->broadaddr))->sin6_addr.s6_addr, + ntop_buf, sizeof ntop_buf)); + if (a->dstaddr) + printf("\t\tDestination Address: %s\n", + inet_ntop(AF_INET6, + ((struct sockaddr_in6 *)(a->dstaddr))->sin6_addr.s6_addr, + ntop_buf, sizeof ntop_buf)); + break; +#endif + default: + printf("\tAddress Family: Unknown (%d)\n", a->addr->sa_family); + break; + } + } + printf("\n"); +} + +/* From tcptraceroute */ +#define IPTOSBUFFERS 12 +static char *iptos(bpf_u_int32 in) +{ + static char output[IPTOSBUFFERS][3*4+3+1]; + static short which; + u_char *p; + + p = (u_char *)∈ + which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1); + sprintf(output[which], "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); + return output[which]; +} diff --git a/libpcap/gencode.c b/libpcap/gencode.c index 5067abc6d..41057ba8c 100644 --- a/libpcap/gencode.c +++ b/libpcap/gencode.c @@ -21,7 +21,7 @@ */ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221.2.52 2007/06/22 06:43:58 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.290.2.16 2008-09-22 20:16:01 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -68,12 +68,18 @@ static const char rcsid[] _U_ = #include "nlpid.h" #include "llc.h" #include "gencode.h" +#include "ieee80211.h" #include "atmuni31.h" #include "sunatmpos.h" #include "ppp.h" -#include "sll.h" +#include "pcap/sll.h" #include "arcnet.h" -#include "pf.h" +#ifdef HAVE_NET_PFVAR_H +#include +#include +#include +#include +#endif #ifndef offsetof #define offsetof(s, e) ((size_t)&((s *)0)->e) #endif @@ -82,7 +88,7 @@ static const char rcsid[] _U_ = #include /* for "struct addrinfo" */ #endif /* WIN32 */ #endif /*INET6*/ -#include +#include #define ETHERMTU 1500 @@ -100,8 +106,8 @@ static const char rcsid[] _U_ = static jmp_buf top_ctx; static pcap_t *bpf_pcap; -#ifdef WIN32 /* 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; @@ -129,6 +135,7 @@ bpf_error(const char *fmt, ...) static void init_linktype(pcap_t *); +static void init_regs(void); static int alloc_reg(void); static void free_reg(int); @@ -140,7 +147,8 @@ static struct block *root; */ enum e_offrel { OR_PACKET, /* relative to the beginning of the packet */ - OR_LINK, /* relative to the link-layer header */ + 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 */ @@ -185,6 +193,7 @@ 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); @@ -192,12 +201,16 @@ static inline struct block *gen_true(void); static inline struct block *gen_false(void); static struct block *gen_ether_linktype(int); static struct block *gen_linux_sll_linktype(int); -static void insert_radiotap_load_llprefixlen(struct block *); -static void insert_ppi_load_llprefixlen(struct block *); -static void insert_load_llprefixlen(struct block *); +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, u_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 @@ -242,6 +255,7 @@ 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); @@ -364,6 +378,7 @@ pcap_compile(pcap_t *p, struct bpf_program *program, n_errors = 0; root = NULL; bpf_pcap = p; + init_regs(); if (setjmp(top_ctx)) { lex_cleanup(); freechunks(); @@ -479,24 +494,11 @@ merge(b0, b1) *p = b1; } - void finish_parse(p) struct block *p; { struct block *ppi_dlt_check; - - 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; /* * Insert before the statements of the first (root) block any @@ -507,14 +509,30 @@ finish_parse(p) * 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, as we're currently only - * handling variable-length radiotap headers, and as all - * filtering expressions other than raw link[M:N] tests - * require the length of that header, doing more for that - * header length isn't really worth the effort. + * 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); - insert_load_llprefixlen(root); + backpatch(p, gen_retblk(snaplen)); + p->sense = !p->sense; + backpatch(p, gen_retblk(0)); + root = p->head; } void @@ -677,13 +695,7 @@ gen_ncmp(offrel, offset, size, mask, jtype, reverse, v) * 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. - * - * If the link layer has variable_length headers, the offsets are offsets - * from the end of the link-link-layer header, and "reg_ll_size" is - * the register number for a register containing the length of the - * link-layer header. Otherwise, "reg_ll_size" is -1. */ -static int reg_ll_size; /* * This is the offset of the beginning of the link-layer header from @@ -696,12 +708,48 @@ static int reg_ll_size; static u_int off_ll; /* - * This is the offset of the beginning of the MAC-layer header. + * 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. */ 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 @@ -724,6 +772,13 @@ static u_int off_mac; */ 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. */ @@ -763,8 +818,8 @@ static u_int off_payload; /* * These are offsets to the beginning of the network-layer header. - * They are relative to the beginning of the link-layer header (i.e., - * they don't include off_ll). + * 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: * @@ -810,6 +865,11 @@ init_linktype(p) off_proto = -1; off_payload = -1; + /* + * And that we're not doing PPPoE. + */ + is_pppoes = 0; + /* * And assume we're not doing SS7. */ @@ -820,34 +880,40 @@ init_linktype(p) off_sls = -1; /* - * Also assume it's not 802.11 with a fixed-length radio header. + * 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_ll_size = -1; + reg_off_ll = -1; + reg_off_macpl = -1; switch (linktype) { case DLT_ARCNET: off_linktype = 2; - off_nl = 6; /* XXX in reality, variable! */ - off_nl_nosnap = 6; /* no 802.2 LLC */ + 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_nl = 8; /* XXX in reality, variable! */ - off_nl_nosnap = 8; /* no 802.2 LLC */ + 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_nl = 14; /* Ethernet II */ - off_nl_nosnap = 17; /* 802.3+802.2 */ + off_macpl = 14; /* Ethernet header length */ + off_nl = 0; /* Ethernet II */ + off_nl_nosnap = 3; /* 802.3+802.2 */ return; case DLT_SLIP: @@ -856,29 +922,33 @@ init_linktype(p) * header is hacked into our SLIP driver. */ off_linktype = -1; - off_nl = 16; - off_nl_nosnap = 16; /* no 802.2 LLC */ + 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_nl = 24; - off_nl_nosnap = 24; /* no 802.2 LLC */ + 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_nl = 4; - off_nl_nosnap = 4; /* no 802.2 LLC */ + off_macpl = 4; + off_nl = 0; + off_nl_nosnap = 0; /* no 802.2 LLC */ return; case DLT_ENC: off_linktype = 0; - off_nl = 12; - off_nl_nosnap = 12; /* no 802.2 LLC */ + off_macpl = 12; + off_nl = 0; + off_nl_nosnap = 0; /* no 802.2 LLC */ return; case DLT_PPP: @@ -886,8 +956,9 @@ init_linktype(p) case DLT_C_HDLC: /* BSD/OS Cisco HDLC */ case DLT_PPP_SERIAL: /* NetBSD sync/async serial PPP */ off_linktype = 2; - off_nl = 4; - off_nl_nosnap = 4; /* no 802.2 LLC */ + off_macpl = 4; + off_nl = 0; + off_nl_nosnap = 0; /* no 802.2 LLC */ return; case DLT_PPP_ETHER: @@ -896,14 +967,16 @@ init_linktype(p) * only covers session state. */ off_linktype = 6; - off_nl = 8; - off_nl_nosnap = 8; /* no 802.2 LLC */ + off_macpl = 8; + off_nl = 0; + off_nl_nosnap = 0; /* no 802.2 LLC */ return; case DLT_PPP_BSDOS: off_linktype = 5; - off_nl = 24; - off_nl_nosnap = 24; /* no 802.2 LLC */ + off_macpl = 24; + off_nl = 0; + off_nl_nosnap = 0; /* no 802.2 LLC */ return; case DLT_FDDI: @@ -919,12 +992,12 @@ init_linktype(p) #ifdef PCAP_FDDIPAD off_linktype += pcap_fddipad; #endif - off_nl = 21; /* FDDI+802.2+SNAP */ - off_nl_nosnap = 16; /* FDDI+802.2 */ + off_macpl = 13; /* FDDI MAC header length */ #ifdef PCAP_FDDIPAD - off_nl += pcap_fddipad; - off_nl_nosnap += pcap_fddipad; + off_macpl += pcap_fddipad; #endif + off_nl = 8; /* 802.2+SNAP */ + off_nl_nosnap = 3; /* 802.2 */ return; case DLT_IEEE802: @@ -952,11 +1025,15 @@ init_linktype(p) * 8 - figure out which byte that is). */ off_linktype = 14; - off_nl = 22; /* Token Ring+802.2+SNAP */ - off_nl_nosnap = 17; /* Token Ring+802.2 */ + 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. @@ -965,90 +1042,37 @@ init_linktype(p) * is being used and pick out the encapsulated Ethernet type. * XXX - should we generate code to check for SNAP? * - * XXX - the header is actually variable-length. We - * assume a 24-byte link-layer header, as appears in - * data frames in networks with no bridges. If the - * fromds and tods 802.11 header bits are both set, - * it's actually supposed to be 30 bytes. + * 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_nl = 32; /* 802.11+802.2+SNAP */ - off_nl_nosnap = 27; /* 802.11+802.2 */ + 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_PRISM_HEADER: - /* - * Same as 802.11, but with an additional header before - * the 802.11 header, containing a bunch of additional - * information including radio-level information. - * - * The header is 144 bytes long. - * - * XXX - same variable-length header problem; at least - * the Prism header is fixed-length. - */ - off_ll = 144; - off_linktype = 24; - off_nl = 32; /* Prism+802.11+802.2+SNAP */ - off_nl_nosnap = 27; /* Prism+802.11+802.2 */ - return; - - case DLT_IEEE802_11_RADIO_AVS: - /* - * Same as 802.11, but with an additional header before - * the 802.11 header, containing a bunch of additional - * information including radio-level information. - * - * The header is 64 bytes long, at least in its - * current incarnation. - * - * XXX - same variable-length header problem, only - * more so; this header is also variable-length, - * with the length being the 32-bit big-endian - * number at an offset of 4 from the beginning - * of the radio header. We should handle that the - * same way we handle the length at the beginning - * of the radiotap header. - * - * XXX - in Linux, do any drivers that supply an AVS - * header supply a link-layer type other than - * ARPHRD_IEEE80211_PRISM? If so, we should map that - * to DLT_IEEE802_11_RADIO_AVS; if not, or if there are - * any drivers that supply an AVS header but supply - * an ARPHRD value of ARPHRD_IEEE80211_PRISM, we'll - * have to check the header in the generated code to - * determine whether it's Prism or AVS. - */ - off_ll = 64; - off_linktype = 24; - off_nl = 32; /* Radio+802.11+802.2+SNAP */ - off_nl_nosnap = 27; /* Radio+802.11+802.2 */ - return; - - - /* - * 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. - */ case DLT_PPI: - case DLT_IEEE802_11_RADIO: - /* - * Same as 802.11, but with an additional header before - * the 802.11 header, containing a bunch of additional - * information including radio-level information. - * - * The radiotap header is variable length, and we - * generate code to compute its length and store it - * in a register. These offsets are relative to the - * beginning of the 802.11 header. + /* + * 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_nl = 32; /* 802.11+802.2+SNAP */ - off_nl_nosnap = 27; /* 802.11+802.2 */ + 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: @@ -1065,6 +1089,7 @@ init_linktype(p) * 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; @@ -1078,23 +1103,26 @@ init_linktype(p) off_vpi = SUNATM_VPI_POS; off_vci = SUNATM_VCI_POS; off_proto = PROTO_POS; - off_mac = -1; /* LLC-encapsulated, so no MAC-layer header */ + off_mac = -1; /* assume LLC-encapsulated, so no MAC-layer header */ off_payload = SUNATM_PKT_BEGIN_POS; off_linktype = off_payload; - off_nl = off_payload+8; /* 802.2+SNAP */ - off_nl_nosnap = off_payload+3; /* 802.2 */ + off_macpl = off_payload; /* if LLC-encapsulated */ + off_nl = 8; /* 802.2+SNAP */ + off_nl_nosnap = 3; /* 802.2 */ return; case DLT_RAW: 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_nl = 16; - off_nl_nosnap = 16; /* no 802.2 LLC */ + off_macpl = 16; + off_nl = 0; + off_nl_nosnap = 0; /* no 802.2 LLC */ return; case DLT_LTALK: @@ -1104,6 +1132,7 @@ init_linktype(p) * "long" DDP packet following. */ off_linktype = -1; + off_macpl = 0; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ return; @@ -1120,8 +1149,9 @@ init_linktype(p) * 2625 says SNAP should be used. */ off_linktype = 16; - off_nl = 24; /* IPFC+802.2+SNAP */ - off_nl_nosnap = 19; /* IPFC+802.2 */ + off_macpl = 16; + off_nl = 8; /* 802.2+SNAP */ + off_nl_nosnap = 3; /* 802.2 */ return; case DLT_FRELAY: @@ -1130,6 +1160,7 @@ init_linktype(p) * frames (NLPID of 0x80). */ off_linktype = -1; + off_macpl = 0; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ return; @@ -1141,14 +1172,16 @@ init_linktype(p) */ 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_nl = 18; - off_nl_nosnap = 18; /* no 802.2 LLC */ + off_macpl = 18; + off_nl = 0; + off_nl_nosnap = 0; /* no 802.2 LLC */ return; case DLT_LINUX_IRDA: @@ -1156,6 +1189,7 @@ init_linktype(p) * Currently, only raw "link[N:M]" filtering is supported. */ off_linktype = -1; + off_macpl = -1; off_nl = -1; off_nl_nosnap = -1; return; @@ -1165,22 +1199,26 @@ init_linktype(p) * Currently, only raw "link[N:M]" filtering is supported. */ off_linktype = -1; + off_macpl = -1; off_nl = -1; off_nl_nosnap = -1; return; case DLT_SYMANTEC_FIREWALL: off_linktype = 6; - off_nl = 44; /* Ethernet II */ - off_nl_nosnap = 44; /* XXX - what does it do with 802.3 packets? */ + 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; - /* XXX read this from pf.h? */ - off_nl = PFLOG_HDRLEN; - off_nl_nosnap = PFLOG_HDRLEN; /* no 802.2 LLC */ + 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: @@ -1189,26 +1227,30 @@ init_linktype(p) case DLT_JUNIPER_CHDLC: case DLT_JUNIPER_FRELAY: off_linktype = 4; - off_nl = 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_nl = 4; - off_nl_nosnap = 14; + 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_nl = 8; - off_nl_nosnap = 18; + 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 */ @@ -1216,36 +1258,56 @@ init_linktype(p) case DLT_JUNIPER_PPPOE_ATM: off_linktype = 4; - off_nl = 6; - off_nl_nosnap = -1; /* no 802.2 LLC */ + off_macpl = 6; + off_nl = 0; + off_nl_nosnap = -1; /* no 802.2 LLC */ return; case DLT_JUNIPER_GGSN: off_linktype = 6; - off_nl = 12; - off_nl_nosnap = -1; /* no 802.2 LLC */ + off_macpl = 12; + off_nl = 0; + off_nl_nosnap = -1; /* no 802.2 LLC */ return; case DLT_JUNIPER_ES: off_linktype = 6; - off_nl = -1; /* not really a network layer but raw IP adresses */ + 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_nl = 12; /* raw IP/IP6 header */ + 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; @@ -1257,6 +1319,7 @@ init_linktype(p) off_dpc = 4; off_sls = 7; off_linktype = -1; + off_macpl = -1; off_nl = -1; off_nl_nosnap = -1; return; @@ -1268,6 +1331,19 @@ init_linktype(p) 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; @@ -1275,8 +1351,9 @@ init_linktype(p) #ifdef DLT_PFSYNC case DLT_PFSYNC: off_linktype = -1; - off_nl = 4; - off_nl_nosnap = 4; + off_macpl = 4; + off_nl = 0; + off_nl_nosnap = 0; return; #endif @@ -1285,6 +1362,7 @@ init_linktype(p) * Currently, only raw "link[N:M]" filtering is supported. */ off_linktype = -1; + off_macpl = -1; off_nl = -1; off_nl_nosnap = -1; return; @@ -1294,6 +1372,7 @@ init_linktype(p) * Currently, only raw "link[N:M]" filtering is supported. */ off_linktype = -1; + off_macpl = -1; off_nl = -1; off_nl_nosnap = -1; return; @@ -1303,6 +1382,118 @@ init_linktype(p) * Currently, only raw "link[N:M]" filtering is supported. */ off_linktype = -1; + off_macpl = -1; + off_nl = -1; + off_nl_nosnap = -1; + return; + + case DLT_USB_LINUX: + /* + * Currently, only raw "link[N:M]" filtering is supported. + */ + off_linktype = -1; + off_macpl = -1; + off_nl = -1; + off_nl_nosnap = -1; + return; + + case DLT_CAN20B: + /* + * Currently, only raw "link[N:M]" filtering is supported. + */ + off_linktype = -1; + off_macpl = -1; + off_nl = -1; + off_nl_nosnap = -1; + return; + + case DLT_IEEE802_15_4_LINUX: + /* + * Currently, only raw "link[N:M]" filtering is supported. + */ + off_linktype = -1; + off_macpl = -1; + off_nl = -1; + off_nl_nosnap = -1; + return; + + case DLT_IEEE802_16_MAC_CPS_RADIO: + /* + * Currently, only raw "link[N:M]" filtering is supported. + */ + off_linktype = -1; + off_macpl = -1; + off_nl = -1; + off_nl_nosnap = -1; + return; + + case DLT_IEEE802_15_4: + /* + * Currently, only raw "link[N:M]" filtering is supported. + */ + off_linktype = -1; + off_macpl = -1; + off_nl = -1; + off_nl_nosnap = -1; + return; + + case DLT_SITA: + /* + * Currently, only raw "link[N:M]" filtering is supported. + */ + off_linktype = -1; + off_macpl = -1; + off_nl = -1; + off_nl_nosnap = -1; + return; + + case DLT_RAIF1: + /* + * Currently, only raw "link[N:M]" filtering is supported. + */ + off_linktype = -1; + off_macpl = -1; + off_nl = -1; + off_nl_nosnap = -1; + return; + + case DLT_IPMB: + /* + * Currently, only raw "link[N:M]" filtering is supported. + */ + off_linktype = -1; + off_macpl = -1; + off_nl = -1; + off_nl_nosnap = -1; + return; + + case DLT_BLUETOOTH_HCI_H4_WITH_PHDR: + /* + * Currently, only raw "link[N:M]" filtering is supported. + */ + off_linktype = -1; + off_macpl = -1; + off_nl = -1; + off_nl_nosnap = -1; + 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_IEEE802_15_4_NONASK_PHY: + /* + * Currently, only raw "link[N:M]" filtering is supported. + */ + off_linktype = -1; + off_macpl = -1; off_nl = -1; off_nl_nosnap = -1; return; @@ -1356,6 +1547,45 @@ gen_load_llrel(offset, size) 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. @@ -1378,12 +1608,16 @@ gen_load_a(offrel, offset, size) s = gen_load_llrel(offset, size); break; + case OR_MACPL: + s = gen_load_macplrel(offset, size); + break; + case OR_NET: - s = gen_load_llrel(off_nl + offset, size); + s = gen_load_macplrel(off_nl + offset, size); break; case OR_NET_NOSNAP: - s = gen_load_llrel(off_nl_nosnap + offset, size); + s = gen_load_macplrel(off_nl_nosnap + offset, size); break; case OR_TRAN_IPV4: @@ -1396,21 +1630,22 @@ gen_load_a(offrel, offset, size) s = gen_loadx_iphdrlen(); /* - * Load the item at {offset of the link-layer header} + - * {offset, relative to the start of the link-layer - * header, of the IPv4 header} + {length of the IPv4 header} + + * 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 link-layer is variable-length, it's included - * in the value in the X register, and off_ll is 0.) + * (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_ll + off_nl + offset; + s2->s.k = off_macpl + off_nl + offset; sappend(s, s2); break; case OR_TRAN_IPV6: - s = gen_load_llrel(off_nl + 40 + offset, size); + s = gen_load_macplrel(off_nl + 40 + offset, size); break; default: @@ -1430,12 +1665,15 @@ gen_loadx_iphdrlen() { struct slist *s, *s2; - s = gen_llprefixlen(); + s = gen_off_macpl(); 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. + * 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 @@ -1453,22 +1691,24 @@ gen_loadx_iphdrlen() /* * The A register now contains the length of the - * IP header. We need to add to it the length - * of the prefix preceding the link-layer - * header, which is still in the X register, and - * move the result into the X register. + * 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; add in off_ll, which, if there's - * a fixed-length header preceding the link-layer header, - * is the length of that header. + * 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_ll + off_nl; + s->s.k = off_macpl + off_nl; } return s; } @@ -1542,7 +1782,7 @@ gen_ether_linktype(proto) */ b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU); gen_not(b0); - b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_H, (bpf_int32) + b1 = gen_cmp(OR_MACPL, 0, BPF_H, (bpf_int32) ((proto << 8) | proto)); gen_and(b0, b1); return b1; @@ -1580,17 +1820,15 @@ gen_ether_linktype(proto) * This generates code to check both for the * IPX LSAP (Ethernet_802.2) and for Ethernet_802.3. */ - b0 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B, - (bpf_int32)LLCSAP_IPX); - b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_H, - (bpf_int32)0xFFFF); + 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, 14); + b0 = gen_snap(0x000000, ETHERTYPE_IPX); gen_or(b0, b1); /* @@ -1645,9 +1883,9 @@ gen_ether_linktype(proto) * type of ETHERTYPE_AARP (Appletalk ARP). */ if (proto == ETHERTYPE_ATALK) - b1 = gen_snap(0x080007, ETHERTYPE_ATALK, 14); + b1 = gen_snap(0x080007, ETHERTYPE_ATALK); else /* proto == ETHERTYPE_AARP */ - b1 = gen_snap(0x000000, ETHERTYPE_AARP, 14); + b1 = gen_snap(0x000000, ETHERTYPE_AARP); gen_and(b0, b1); /* @@ -1724,7 +1962,7 @@ gen_linux_sll_linktype(proto) * (i.e., other SAP values)? */ b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2); - b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_H, (bpf_int32) + b1 = gen_cmp(OR_MACPL, 0, BPF_H, (bpf_int32) ((proto << 8) | proto)); gen_and(b0, b1); return b1; @@ -1755,10 +1993,8 @@ gen_linux_sll_linktype(proto) * then put a check for LINUX_SLL_P_802_2 frames * before it. */ - b0 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B, - (bpf_int32)LLCSAP_IPX); - b1 = gen_snap(0x000000, ETHERTYPE_IPX, - off_linktype + 2); + 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); @@ -1806,11 +2042,9 @@ gen_linux_sll_linktype(proto) * type of ETHERTYPE_AARP (Appletalk ARP). */ if (proto == ETHERTYPE_ATALK) - b1 = gen_snap(0x080007, ETHERTYPE_ATALK, - off_linktype + 2); + b1 = gen_snap(0x080007, ETHERTYPE_ATALK); else /* proto == ETHERTYPE_AARP */ - b1 = gen_snap(0x000000, ETHERTYPE_AARP, - off_linktype + 2); + b1 = gen_snap(0x000000, ETHERTYPE_AARP); gen_and(b0, b1); /* @@ -1834,7 +2068,7 @@ gen_linux_sll_linktype(proto) */ b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2); - b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B, + b1 = gen_cmp(OR_LINK, off_macpl, BPF_B, (bpf_int32)proto); gen_and(b0, b1); return b1; @@ -1854,18 +2088,169 @@ gen_linux_sll_linktype(proto) } } -static void -insert_radiotap_load_llprefixlen(b) - struct block *b; +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; /* - * Prepend to the statements in this block code to load the - * length of the radiotap header into the register assigned - * to hold that length, if one has been assigned. + * 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_ll_size != -1) { + 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 @@ -1900,7 +2285,7 @@ insert_radiotap_load_llprefixlen(b) * it. */ s2 = new_stmt(BPF_ST); - s2->s.k = reg_ll_size; + s2->s.k = reg_off_ll; sappend(s1, s2); /* @@ -1909,13 +2294,9 @@ insert_radiotap_load_llprefixlen(b) s2 = new_stmt(BPF_MISC|BPF_TAX); sappend(s1, s2); - /* - * Now append all the existing statements in this - * block to these statements. - */ - sappend(s1, b->stmts); - b->stmts = s1; - } + return (s1); + } else + return (NULL); } /* @@ -1924,21 +2305,21 @@ insert_radiotap_load_llprefixlen(b) * 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. + * DLT_IEEE802_11) we generate code to check for this too; + * that's done in finish_parse(). */ -static void -insert_ppi_load_llprefixlen(b) - struct block *b; +static struct slist * +gen_load_ppi_llprefixlen() { struct slist *s1, *s2; /* - * Prepend to the statements in this block code to load the - * length of the radiotap header into the register assigned - * to hold that length, if one has been assigned. + * 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_ll_size != -1) { - /* + 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 @@ -1972,7 +2353,7 @@ insert_ppi_load_llprefixlen(b) * it. */ s2 = new_stmt(BPF_ST); - s2->s.k = reg_ll_size; + s2->s.k = reg_off_ll; sappend(s1, s2); /* @@ -1981,16 +2362,295 @@ insert_ppi_load_llprefixlen(b) s2 = new_stmt(BPF_MISC|BPF_TAX); sappend(s1, s2); - /* - * Now append all the existing statements in this - * block to these statements. - */ - sappend(s1, b->stmts); - b->stmts = s1; + 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) { @@ -2017,42 +2677,61 @@ gen_ppi_dlt_check(void) return b; } -static void -insert_load_llprefixlen(b) - struct block *b; +static struct slist * +gen_prism_llprefixlen(void) { - switch (linktype) { + struct slist *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. - */ - case DLT_PPI: - insert_ppi_load_llprefixlen(b); - break; - - case DLT_IEEE802_11_RADIO: - insert_radiotap_load_llprefixlen(b); - break; + 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_ll_size == -1) { + if (reg_off_ll == -1) { /* * We haven't yet assigned a register for the length * of the radiotap header; allocate one. */ - reg_ll_size = alloc_reg(); + reg_off_ll = alloc_reg(); } /* @@ -2060,7 +2739,7 @@ gen_radiotap_llprefixlen(void) * into the X register. */ s = new_stmt(BPF_LDX|BPF_MEM); - s->s.k = reg_ll_size; + s->s.k = reg_off_ll; return s; } @@ -2077,25 +2756,23 @@ gen_ppi_llprefixlen(void) { struct slist *s; - if (reg_ll_size == -1) { + if (reg_off_ll == -1) { /* * We haven't yet assigned a register for the length * of the radiotap header; allocate one. */ - reg_ll_size = alloc_reg(); + reg_off_ll = alloc_reg(); } /* - * Load the register containing the radiotap length + * Load the register containing the PPI length * into the X register. */ s = new_stmt(BPF_LDX|BPF_MEM); - s->s.k = reg_ll_size; + 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 @@ -2107,18 +2784,109 @@ gen_llprefixlen(void) { switch (linktype) { - case DLT_PPI: - return gen_ppi_llprefixlen(); + 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. @@ -2137,12 +2905,12 @@ gen_linktype(proto) switch (proto) { case ETHERTYPE_IP: case PPP_IP: - /* FIXME add other L3 proto IDs */ + /* FIXME add other L3 proto IDs */ return gen_mpls_linktype(Q_IP); case ETHERTYPE_IPV6: case PPP_IPV6: - /* FIXME add other L3 proto IDs */ + /* FIXME add other L3 proto IDs */ return gen_mpls_linktype(Q_IPV6); default: @@ -2151,6 +2919,25 @@ gen_linktype(proto) } } + /* + * 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: @@ -2173,13 +2960,41 @@ gen_linktype(proto) } break; - case DLT_PPI: - case DLT_FDDI: - case DLT_IEEE802: case DLT_IEEE802_11: + case DLT_PRISM_HEADER: case DLT_IEEE802_11_RADIO_AVS: case DLT_IEEE802_11_RADIO: - case DLT_PRISM_HEADER: + 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: @@ -2264,47 +3079,9 @@ gen_linktype(proto) * We use Ethernet protocol types inside libpcap; * map them to the corresponding PPP protocol types. */ - 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; - } + proto = ethertype_to_ppptype(proto); + return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); + /*NOTREACHED*/ break; case DLT_PPP_BSDOS: @@ -2315,6 +3092,10 @@ gen_linktype(proto) 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); @@ -2322,42 +3103,12 @@ gen_linktype(proto) gen_or(b1, b0); return b0; -#ifdef INET6 - case ETHERTYPE_IPV6: - proto = PPP_IPV6; - /* more to go? */ - 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; + default: + proto = ethertype_to_ppptype(proto); + return gen_cmp(OR_LINK, off_linktype, BPF_H, + (bpf_int32)proto); } + /*NOTREACHED*/ break; case DLT_NULL: @@ -2426,6 +3177,7 @@ gen_linktype(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 @@ -2443,6 +3195,7 @@ gen_linktype(proto) return gen_false(); /*NOTREACHED*/ break; +#endif /* HAVE_NET_PFVAR_H */ case DLT_ARCNET: case DLT_ARCNET_LINUX: @@ -2544,6 +3297,9 @@ gen_linktype(proto) /*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: @@ -2560,6 +3316,8 @@ gen_linktype(proto) case DLT_JUNIPER_FRELAY: case DLT_JUNIPER_CHDLC: case DLT_JUNIPER_VP: + case DLT_JUNIPER_ST: + case DLT_JUNIPER_ISM: /* 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 @@ -2575,8 +3333,51 @@ gen_linktype(proto) 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"); + +#ifdef DLT_PFSYNC + case DLT_PFSYNC: + bpf_error("PFSYNC link-layer type filtering not implemented"); +#endif + case DLT_LINUX_LAPD: bpf_error("LAPD link-layer type filtering not implemented"); + + case DLT_USB: + case DLT_USB_LINUX: + 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: + bpf_error("CAN20B link-layer type filtering not implemented"); + + case DLT_IEEE802_15_4: + case DLT_IEEE802_15_4_LINUX: + case DLT_IEEE802_15_4_NONASK_PHY: + 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"); } /* @@ -2594,12 +3395,7 @@ gen_linktype(proto) /* * Any type not handled above should always have an Ethernet - * type at an offset of "off_linktype". (PPP is partially - * handled above - the protocol type is mapped from the - * Ethernet and LLC types we use internally to the corresponding - * PPP type - but the PPP type is always specified by a value - * at "off_linktype", so we don't have to do the code generation - * above.) + * type at an offset of "off_linktype". */ return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); } @@ -2612,10 +3408,9 @@ gen_linktype(proto) * code and protocol type in the SNAP header. */ static struct block * -gen_snap(orgcode, ptype, offset) +gen_snap(orgcode, ptype) bpf_u_int32 orgcode; bpf_u_int32 ptype; - u_int offset; { u_char snapblock[8]; @@ -2627,7 +3422,7 @@ gen_snap(orgcode, ptype, offset) 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_LINK, offset, 8, snapblock); + return gen_bcmp(OR_MACPL, 0, 8, snapblock); } /* @@ -2660,7 +3455,7 @@ gen_llc_linktype(proto) * DSAP, as we do for other types <= ETHERMTU * (i.e., other SAP values)? */ - return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_u_int32) + return gen_cmp(OR_MACPL, 0, BPF_H, (bpf_u_int32) ((proto << 8) | proto)); case LLCSAP_IPX: @@ -2668,7 +3463,7 @@ gen_llc_linktype(proto) * XXX - are there ever SNAP frames for IPX on * non-Ethernet 802.x networks? */ - return gen_cmp(OR_LINK, off_linktype, BPF_B, + return gen_cmp(OR_MACPL, 0, BPF_B, (bpf_int32)LLCSAP_IPX); case ETHERTYPE_ATALK: @@ -2681,7 +3476,7 @@ gen_llc_linktype(proto) * XXX - check for an organization code of * encapsulated Ethernet as well? */ - return gen_snap(0x080007, ETHERTYPE_ATALK, off_linktype); + return gen_snap(0x080007, ETHERTYPE_ATALK); default: /* @@ -2693,8 +3488,7 @@ gen_llc_linktype(proto) * This is an LLC SAP value, so check * the DSAP. */ - return gen_cmp(OR_LINK, off_linktype, BPF_B, - (bpf_int32)proto); + return gen_cmp(OR_MACPL, 0, BPF_B, (bpf_int32)proto); } else { /* * This is an Ethernet type; we assume that it's @@ -2709,15 +3503,13 @@ gen_llc_linktype(proto) * organization code of 0x000000 (encapsulated * Ethernet), we'd do * - * return gen_snap(0x000000, proto, - * off_linktype); + * 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_LINK, off_linktype+6, BPF_H, - (bpf_int32)proto); + return gen_cmp(OR_MACPL, 6, BPF_H, (bpf_int32)proto); } } } @@ -2926,7 +3718,8 @@ gen_thostop(eaddr, dir) } /* - * Like gen_ehostop, but for DLT_IEEE802_11 (802.11 wireless LAN) + * 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) @@ -2936,6 +3729,16 @@ gen_wlanhostop(eaddr, 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: /* @@ -3033,7 +3836,7 @@ gen_wlanhostop(eaddr, dir) * Now check for a data frame. * I.e, check "link[0] & 0x08". */ - gen_load_a(OR_LINK, 0, BPF_B); + s = gen_load_a(OR_LINK, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x08; b1->stmts = s; @@ -3202,6 +4005,55 @@ gen_wlanhostop(eaddr, dir) gen_and(b1, b0); return b0; + /* + * XXX - add RA, TA, and BSSID keywords? + */ + 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); @@ -3644,48 +4496,48 @@ gen_gateway(eaddr, alist, proto, dir) case Q_IP: case Q_ARP: case Q_RARP: - switch (linktype) { - case DLT_EN10MB: - 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_IEEE802_11_RADIO_AVS: - case DLT_PPI: - case DLT_IEEE802_11_RADIO: - case DLT_PRISM_HEADER: - b0 = gen_wlanhostop(eaddr, Q_OR); - break; - 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. - */ + switch (linktype) { + case DLT_EN10MB: b0 = gen_ehostop(eaddr, Q_OR); - gen_and(b1, b0); - } - break; + 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) { + /* + * 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( + b0 = gen_ipfchostop(eaddr, Q_OR); + break; + default: + bpf_error( "'gateway' supported only on ethernet/FDDI/token ring/802.11/Fibre Channel"); - } + } b1 = gen_host(**alist++, 0xffffffff, proto, Q_OR, Q_HOST); while (*alist) { tmp = gen_host(**alist++, 0xffffffff, proto, Q_OR, @@ -4450,7 +5302,8 @@ gen_protochain(v, proto, dir) } /* - * We don't handle variable-length radiotap here headers yet. + * 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 @@ -4459,11 +5312,15 @@ gen_protochain(v, proto, dir) * branches, and backward branch support is unlikely to appear * in kernel BPF engines.) */ - if (linktype == DLT_IEEE802_11_RADIO) - bpf_error("'protochain' not supported with radiotap headers"); + switch (linktype) { - if (linktype == DLT_PPI) - bpf_error("'protochain' not supported with PPI headers"); + 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 */ @@ -4482,11 +5339,11 @@ gen_protochain(v, proto, dir) /* A = ip->ip_p */ s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B); - s[i]->s.k = off_ll + off_nl + 9; + 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_ll + off_nl; + s[i]->s.k = off_macpl + off_nl; i++; break; #ifdef INET6 @@ -4495,7 +5352,7 @@ gen_protochain(v, proto, dir) /* A = ip6->ip_nxt */ s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B); - s[i]->s.k = off_ll + off_nl + 6; + s[i]->s.k = off_macpl + off_nl + 6; i++; /* X = sizeof(struct ip6_hdr) */ s[i] = new_stmt(BPF_LDX|BPF_IMM); @@ -4575,7 +5432,7 @@ gen_protochain(v, proto, dir) i++; /* A = P[X + packet head] */ s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B); - s[i]->s.k = off_ll + off_nl; + s[i]->s.k = off_macpl + off_nl; i++; /* MEM[reg2] = A */ s[i] = new_stmt(BPF_ST); @@ -4593,7 +5450,7 @@ gen_protochain(v, proto, dir) i++; /* A = P[X + packet head]; */ s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B); - s[i]->s.k = off_ll + off_nl; + s[i]->s.k = off_macpl + off_nl; i++; /* A += 1 */ s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); @@ -4652,7 +5509,7 @@ gen_protochain(v, proto, dir) i++; /* A = P[X + packet head]; */ s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B); - s[i]->s.k = off_ll + off_nl; + s[i]->s.k = off_macpl + off_nl; i++; /* MEM[reg2] = A */ s[i] = new_stmt(BPF_ST); @@ -4670,7 +5527,7 @@ gen_protochain(v, proto, dir) i++; /* A = P[X + packet head] */ s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B); - s[i]->s.k = off_ll + off_nl; + s[i]->s.k = off_macpl + off_nl; i++; /* A += 2 */ s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); @@ -4724,6 +5581,31 @@ gen_protochain(v, proto, dir) #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 @@ -5011,9 +5893,9 @@ gen_scode(name, q) return b; case DLT_IEEE802_11: + case DLT_PRISM_HEADER: case DLT_IEEE802_11_RADIO_AVS: case DLT_IEEE802_11_RADIO: - case DLT_PRISM_HEADER: case DLT_PPI: eaddr = pcap_ether_hostton(name); if (eaddr == NULL) @@ -5242,7 +6124,6 @@ gen_scode(name, q) else bpf_error("unknown protocol: %s", name); - case Q_UNDEF: syntax(); /* NOTREACHED */ @@ -5479,44 +6360,44 @@ gen_ecode(eaddr, q) struct block *b, *tmp; if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) { - switch (linktype) { - case DLT_EN10MB: - 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_IEEE802_11_RADIO_AVS: - case DLT_IEEE802_11_RADIO: - case DLT_PRISM_HEADER: - 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); + switch (linktype) { + case DLT_EN10MB: + 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; - } + /* + * 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 */ @@ -5683,14 +6564,14 @@ gen_load(proto, inst, size) * XXX - are there any cases where we want * off_nl_nosnap? */ - s = gen_llprefixlen(); + s = gen_off_macpl(); /* * 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 + * 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 specifed * by "index". */ @@ -5704,13 +6585,17 @@ gen_load(proto, inst, size) /* * 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, 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). + * 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_ll + off_nl; + tmp->s.k = off_macpl + off_nl; sappend(s, tmp); sappend(inst->s, s); @@ -5751,22 +6636,24 @@ gen_load(proto, inst, size) /* * The X register now contains the sum of the length * of any variable-length header preceding the link-layer - * header and the length of the network-layer header. + * 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 link-layer header plus the length of any - * fixed-length header preceding the link-layer - * header. + * 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_ll + off_nl; + tmp->s.k = off_macpl + off_nl; sappend(inst->s, s); /* @@ -5932,6 +6819,16 @@ gen_arth(code, a0, a1) 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. */ @@ -6063,46 +6960,46 @@ gen_broadcast(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: - 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_IEEE802_11_RADIO_AVS: - case DLT_IEEE802_11_RADIO: - case DLT_PPI: - case DLT_PRISM_HEADER: - 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); + switch (linktype) { + case DLT_ARCNET: + case DLT_ARCNET_LINUX: + return gen_ahostop(abroadcast, Q_DST); + case DLT_EN10MB: + 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"); - } + /* + * 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: @@ -6150,167 +7047,167 @@ gen_multicast(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: - /* 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_IEEE802_11_RADIO_AVS: - case DLT_PPI: - case DLT_IEEE802_11_RADIO: - case DLT_PRISM_HEADER: - /* - * 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) { + 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: + /* ether[0] & 1 != 0 */ + return gen_mac_multicast(0); + case DLT_FDDI: /* - * Check that the packet doesn't begin with an - * LE Control marker. (We've already generated - * a test for LANE.) + * XXX TEST THIS: MIGHT NOT PORT PROPERLY XXX + * + * XXX - was that referring to bit-order issues? */ - b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, - 0xFF00); + /* 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); - /* ether[off_mac] & 1 != 0 */ - b0 = gen_mac_multicast(off_mac); + /* + * AND that with the checks for data and management + * frames. + */ gen_and(b1, b0); return b0; - } - break; - default: - break; - } - /* Link not known to support multicasts */ - break; + 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); @@ -6374,10 +7271,12 @@ gen_inbound(dir) } 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) { @@ -6405,6 +7304,8 @@ gen_inbound(dir) case DLT_JUNIPER_FRELAY: case DLT_JUNIPER_CHDLC: case DLT_JUNIPER_VP: + case DLT_JUNIPER_ST: + case DLT_JUNIPER_ISM: /* juniper flags (including direction) are stored * the byte after the 3-byte magic number */ if (dir) { @@ -6414,7 +7315,7 @@ gen_inbound(dir) /* match incoming packets */ b0 = gen_mcmp(OR_LINK, 3, BPF_B, 1, 0x01); } - break; + break; default: bpf_error("inbound/outbound not supported on linktype %d", @@ -6425,6 +7326,7 @@ gen_inbound(dir) return (b0); } +#ifdef HAVE_NET_PFVAR_H /* PF firewall log matched interface */ struct block * gen_pf_ifname(const char *ifname) @@ -6432,13 +7334,12 @@ gen_pf_ifname(const char *ifname) struct block *b0; u_int len, off; - if (linktype == DLT_PFLOG) { - len = sizeof(((struct pfloghdr *)0)->ifname); - off = offsetof(struct pfloghdr, ifname); - } else { - bpf_error("ifname not supported on linktype 0x%x", linktype); + 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); @@ -6455,14 +7356,16 @@ gen_pf_ruleset(char *ruleset) struct block *b0; if (linktype != DLT_PFLOG) { - bpf_error("ruleset not supported on linktype 0x%x", linktype); + 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); @@ -6474,14 +7377,13 @@ gen_pf_rnr(int rnr) { struct block *b0; - if (linktype == DLT_PFLOG) { - b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, rulenr), BPF_W, - (bpf_int32)rnr); - } else { - bpf_error("rnr not supported on linktype 0x%x", linktype); + 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); } @@ -6492,7 +7394,7 @@ gen_pf_srnr(int srnr) struct block *b0; if (linktype != DLT_PFLOG) { - bpf_error("srnr not supported on linktype 0x%x", linktype); + bpf_error("srnr supported only on PF linktype"); /* NOTREACHED */ } @@ -6507,14 +7409,13 @@ gen_pf_reason(int reason) { struct block *b0; - if (linktype == DLT_PFLOG) { - b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, reason), BPF_B, - (bpf_int32)reason); - } else { - bpf_error("reason not supported on linktype 0x%x", linktype); + 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); } @@ -6524,14 +7425,110 @@ gen_pf_action(int action) { struct block *b0; - if (linktype == DLT_PFLOG) { - b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, action), BPF_B, - (bpf_int32)action); - } else { - bpf_error("action not supported on linktype 0x%x", linktype); + 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); } @@ -6540,9 +7537,22 @@ gen_acode(eaddr, q) register const u_char *eaddr; struct qual q; { - if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) { - if (linktype == DLT_ARCNET || linktype == DLT_ARCNET_LINUX) - return gen_ahostop(eaddr, (int)q.dir); + 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 */ @@ -6595,10 +7605,11 @@ gen_vlan(vlan_num) bpf_error("no VLAN match after MPLS"); /* - * 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. + * 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 @@ -6624,15 +7635,29 @@ gen_vlan(vlan_num) * be done assuming a VLAN, even though the "or" could be viewed * as meaning "or, if this isn't a VLAN packet...". */ - orig_linktype = off_linktype; /* save original values */ orig_nl = off_nl; switch (linktype) { case DLT_EN10MB: + /* check for VLAN */ + b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, + (bpf_int32)ETHERTYPE_8021Q); + + /* 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: @@ -6641,17 +7666,6 @@ gen_vlan(vlan_num) /*NOTREACHED*/ } - /* check for VLAN */ - b0 = gen_cmp(OR_LINK, orig_linktype, BPF_H, (bpf_int32)ETHERTYPE_8021Q); - - /* If a specific VLAN is requested, check VLAN id */ - if (vlan_num >= 0) { - b1 = gen_mcmp(OR_LINK, orig_nl, BPF_H, (bpf_int32)vlan_num, - 0x0fff); - gen_and(b0, b1); - b0 = b1; - } - return (b0); } @@ -6677,7 +7691,7 @@ gen_mpls(label_num) if (label_stack_depth > 0) { /* just match the bottom-of-stack bit clear */ - b0 = gen_mcmp(OR_LINK, orig_nl-2, BPF_B, 0, 0x01); + b0 = gen_mcmp(OR_MACPL, orig_nl-2, BPF_B, 0, 0x01); } else { /* * Indicate that we're checking MPLS-encapsulated headers, @@ -6712,7 +7726,7 @@ gen_mpls(label_num) /* 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_LINK, orig_nl, BPF_W, (bpf_int32)label_num, + 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; @@ -6746,7 +7760,8 @@ gen_pppoes() /* * Change the offsets to point to the type and data fields within - * the PPP packet. + * 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 @@ -6774,24 +7789,28 @@ gen_pppoes() */ 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 PPP payload, so we set the - * offsets to the network layer offset plus 6 bytes for - * the PPPoE header plus the values appropriate for PPP when - * encapsulated in Ethernet (which means there's no HDLC - * encapsulation). + * 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 = orig_nl + 6; - off_nl = orig_nl + 6 + 2; - off_nl_nosnap = orig_nl + 6 + 2; + off_linktype = off_nl + 6; /* - * Set the link-layer type to PPP, as all subsequent tests will - * be on the encapsulated PPP header. + * 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. */ - linktype = DLT_PPP; + off_nl = 6+2; + off_nl_nosnap = 6+2; return b0; } @@ -6937,8 +7956,9 @@ gen_atmtype_abbrev(type) is_lane = 1; off_mac = off_payload + 2; /* MAC header */ off_linktype = off_mac + 12; - off_nl = off_mac + 14; /* Ethernet II */ - off_nl_nosnap = off_mac + 17; /* 802.3+802.2 */ + off_macpl = off_mac + 14; /* Ethernet */ + off_nl = 0; /* Ethernet II */ + off_nl_nosnap = 3; /* 802.3+802.2 */ break; case A_LLC: @@ -6971,6 +7991,7 @@ gen_mtp2type_abbrev(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) */ @@ -6979,6 +8000,7 @@ gen_mtp2type_abbrev(type) 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); @@ -6988,6 +8010,7 @@ gen_mtp2type_abbrev(type) 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); diff --git a/libpcap/gencode.h b/libpcap/gencode.h index f4c5cf750..39b1eea54 100644 --- a/libpcap/gencode.h +++ b/libpcap/gencode.h @@ -18,7 +18,7 @@ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * @(#) $Header: /tcpdump/master/libpcap/gencode.h,v 1.60.2.11 2007/06/11 09:52:04 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/gencode.h,v 1.70.2.1 2007/11/18 02:04:55 guy Exp $ (LBL) */ /* @@ -132,6 +132,10 @@ #define Q_DST 2 #define Q_OR 3 #define Q_AND 4 +#define Q_ADDR1 5 +#define Q_ADDR2 6 +#define Q_ADDR3 7 +#define Q_ADDR4 8 #define Q_DEFAULT 0 #define Q_UNDEF 255 @@ -312,6 +316,9 @@ struct block *gen_pf_reason(int); struct block *gen_pf_action(int); struct block *gen_pf_dir(int); +struct block *gen_p80211_type(int, int); +struct block *gen_p80211_fcdir(int); + void bpf_optimize(struct block **); void bpf_error(const char *, ...) __attribute__((noreturn, format (printf, 1, 2))); diff --git a/libpcap/grammar.c b/libpcap/grammar.c deleted file mode 100644 index b7cf38468..000000000 --- a/libpcap/grammar.c +++ /dev/null @@ -1,3117 +0,0 @@ -/* A Bison parser, made by GNU Bison 2.3. */ - -/* Skeleton implementation for Bison's Yacc-like parsers in C - - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 - Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - -/* C LALR(1) parser skeleton written by Richard Stallman, by - simplifying the original so-called "semantic" parser. */ - -/* All symbols defined below should begin with yy or YY, to avoid - infringing on user name space. This should be done even for local - variables, as they might otherwise be expanded by user macros. - There are some unavoidable exceptions within include files to - define necessary library symbols; they are noted "INFRINGES ON - USER NAME SPACE" below. */ - -/* Identify Bison output. */ -#define YYBISON 1 - -/* Bison version. */ -#define YYBISON_VERSION "2.3" - -/* Skeleton name. */ -#define YYSKELETON_NAME "yacc.c" - -/* Pure parsers. */ -#define YYPURE 0 - -/* Using locations. */ -#define YYLSP_NEEDED 0 - -/* Substitute the variable and function names. */ -#define yyparse pcap_parse -#define yylex pcap_lex -#define yyerror pcap_error -#define yylval pcap_lval -#define yychar pcap_char -#define yydebug pcap_debug -#define yynerrs pcap_nerrs - - -/* Tokens. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - enum yytokentype { - DST = 258, - SRC = 259, - HOST = 260, - GATEWAY = 261, - NET = 262, - NETMASK = 263, - PORT = 264, - PORTRANGE = 265, - LESS = 266, - GREATER = 267, - PROTO = 268, - PROTOCHAIN = 269, - CBYTE = 270, - ARP = 271, - RARP = 272, - IP = 273, - SCTP = 274, - TCP = 275, - UDP = 276, - ICMP = 277, - IGMP = 278, - IGRP = 279, - PIM = 280, - VRRP = 281, - ATALK = 282, - AARP = 283, - DECNET = 284, - LAT = 285, - SCA = 286, - MOPRC = 287, - MOPDL = 288, - TK_BROADCAST = 289, - TK_MULTICAST = 290, - NUM = 291, - INBOUND = 292, - OUTBOUND = 293, - PF_IFNAME = 294, - PF_RSET = 295, - PF_RNR = 296, - PF_SRNR = 297, - PF_REASON = 298, - PF_ACTION = 299, - LINK = 300, - GEQ = 301, - LEQ = 302, - NEQ = 303, - ID = 304, - EID = 305, - HID = 306, - HID6 = 307, - AID = 308, - LSH = 309, - RSH = 310, - LEN = 311, - IPV6 = 312, - ICMPV6 = 313, - AH = 314, - ESP = 315, - VLAN = 316, - MPLS = 317, - PPPOED = 318, - PPPOES = 319, - ISO = 320, - ESIS = 321, - CLNP = 322, - ISIS = 323, - L1 = 324, - L2 = 325, - IIH = 326, - LSP = 327, - SNP = 328, - CSNP = 329, - PSNP = 330, - STP = 331, - IPX = 332, - NETBEUI = 333, - LANE = 334, - LLC = 335, - METAC = 336, - BCC = 337, - SC = 338, - ILMIC = 339, - OAMF4EC = 340, - OAMF4SC = 341, - OAM = 342, - OAMF4 = 343, - CONNECTMSG = 344, - METACONNECT = 345, - VPI = 346, - VCI = 347, - RADIO = 348, - FISU = 349, - LSSU = 350, - MSU = 351, - SIO = 352, - OPC = 353, - DPC = 354, - SLS = 355, - AND = 356, - OR = 357, - UMINUS = 358 - }; -#endif -/* Tokens. */ -#define DST 258 -#define SRC 259 -#define HOST 260 -#define GATEWAY 261 -#define NET 262 -#define NETMASK 263 -#define PORT 264 -#define PORTRANGE 265 -#define LESS 266 -#define GREATER 267 -#define PROTO 268 -#define PROTOCHAIN 269 -#define CBYTE 270 -#define ARP 271 -#define RARP 272 -#define IP 273 -#define SCTP 274 -#define TCP 275 -#define UDP 276 -#define ICMP 277 -#define IGMP 278 -#define IGRP 279 -#define PIM 280 -#define VRRP 281 -#define ATALK 282 -#define AARP 283 -#define DECNET 284 -#define LAT 285 -#define SCA 286 -#define MOPRC 287 -#define MOPDL 288 -#define TK_BROADCAST 289 -#define TK_MULTICAST 290 -#define NUM 291 -#define INBOUND 292 -#define OUTBOUND 293 -#define PF_IFNAME 294 -#define PF_RSET 295 -#define PF_RNR 296 -#define PF_SRNR 297 -#define PF_REASON 298 -#define PF_ACTION 299 -#define LINK 300 -#define GEQ 301 -#define LEQ 302 -#define NEQ 303 -#define ID 304 -#define EID 305 -#define HID 306 -#define HID6 307 -#define AID 308 -#define LSH 309 -#define RSH 310 -#define LEN 311 -#define IPV6 312 -#define ICMPV6 313 -#define AH 314 -#define ESP 315 -#define VLAN 316 -#define MPLS 317 -#define PPPOED 318 -#define PPPOES 319 -#define ISO 320 -#define ESIS 321 -#define CLNP 322 -#define ISIS 323 -#define L1 324 -#define L2 325 -#define IIH 326 -#define LSP 327 -#define SNP 328 -#define CSNP 329 -#define PSNP 330 -#define STP 331 -#define IPX 332 -#define NETBEUI 333 -#define LANE 334 -#define LLC 335 -#define METAC 336 -#define BCC 337 -#define SC 338 -#define ILMIC 339 -#define OAMF4EC 340 -#define OAMF4SC 341 -#define OAM 342 -#define OAMF4 343 -#define CONNECTMSG 344 -#define METACONNECT 345 -#define VPI 346 -#define VCI 347 -#define RADIO 348 -#define FISU 349 -#define LSSU 350 -#define MSU 351 -#define SIO 352 -#define OPC 353 -#define DPC 354 -#define SLS 355 -#define AND 356 -#define OR 357 -#define UMINUS 358 - - - - -/* Copy the first part of user declarations. */ -#line 1 "grammar.y" - -/* - * 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. - * - */ -#ifndef lint -static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/grammar.y,v 1.86.2.8 2007/06/11 09:52:04 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 -#endif /* WIN32 */ - -#include - -#include "pcap-int.h" - -#include "gencode.h" -#include "pf.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) - -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 -int yyparse(void); - -int -pcap_parse() -{ - return (yyparse()); -} -#endif - - - -/* Enabling traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif - -/* Enabling verbose error messages. */ -#ifdef YYERROR_VERBOSE -# undef YYERROR_VERBOSE -# define YYERROR_VERBOSE 1 -#else -# define YYERROR_VERBOSE 0 -#endif - -/* Enabling the token table. */ -#ifndef YYTOKEN_TABLE -# define YYTOKEN_TABLE 0 -#endif - -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -typedef union YYSTYPE -#line 90 "grammar.y" -{ - 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; -} -/* Line 187 of yacc.c. */ -#line 415 "y.tab.c" - YYSTYPE; -# define yystype YYSTYPE /* obsolescent; will be withdrawn */ -# define YYSTYPE_IS_DECLARED 1 -# define YYSTYPE_IS_TRIVIAL 1 -#endif - - - -/* Copy the second part of user declarations. */ - - -/* Line 216 of yacc.c. */ -#line 428 "y.tab.c" - -#ifdef short -# undef short -#endif - -#ifdef YYTYPE_UINT8 -typedef YYTYPE_UINT8 yytype_uint8; -#else -typedef unsigned char yytype_uint8; -#endif - -#ifdef YYTYPE_INT8 -typedef YYTYPE_INT8 yytype_int8; -#elif (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -typedef signed char yytype_int8; -#else -typedef short int yytype_int8; -#endif - -#ifdef YYTYPE_UINT16 -typedef YYTYPE_UINT16 yytype_uint16; -#else -typedef unsigned short int yytype_uint16; -#endif - -#ifdef YYTYPE_INT16 -typedef YYTYPE_INT16 yytype_int16; -#else -typedef short int yytype_int16; -#endif - -#ifndef YYSIZE_T -# ifdef __SIZE_TYPE__ -# define YYSIZE_T __SIZE_TYPE__ -# elif defined size_t -# define YYSIZE_T size_t -# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -# include /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t -# else -# define YYSIZE_T unsigned int -# endif -#endif - -#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) - -#ifndef YY_ -# if YYENABLE_NLS -# if ENABLE_NLS -# include /* INFRINGES ON USER NAME SPACE */ -# define YY_(msgid) dgettext ("bison-runtime", msgid) -# endif -# endif -# ifndef YY_ -# define YY_(msgid) msgid -# endif -#endif - -/* Suppress unused-variable warnings by "using" E. */ -#if ! defined lint || defined __GNUC__ -# define YYUSE(e) ((void) (e)) -#else -# define YYUSE(e) /* empty */ -#endif - -/* Identity function, used to suppress warnings about constant conditions. */ -#ifndef lint -# define YYID(n) (n) -#else -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static int -YYID (int i) -#else -static int -YYID (i) - int i; -#endif -{ - return i; -} -#endif - -#if ! defined yyoverflow || YYERROR_VERBOSE - -/* The parser invokes alloca or malloc; define the necessary symbols. */ - -# ifdef YYSTACK_USE_ALLOCA -# if YYSTACK_USE_ALLOCA -# ifdef __GNUC__ -# define YYSTACK_ALLOC __builtin_alloca -# elif defined __BUILTIN_VA_ARG_INCR -# include /* INFRINGES ON USER NAME SPACE */ -# elif defined _AIX -# define YYSTACK_ALLOC __alloca -# elif defined _MSC_VER -# include /* INFRINGES ON USER NAME SPACE */ -# define alloca _alloca -# else -# define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -# include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 -# endif -# endif -# endif -# endif -# endif - -# ifdef YYSTACK_ALLOC - /* Pacify GCC's `empty if-body' warning. */ -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) -# ifndef YYSTACK_ALLOC_MAXIMUM - /* The OS might guarantee only one guard page at the bottom of the stack, - and a page size can be as small as 4096 bytes. So we cannot safely - invoke alloca (N) if N exceeds 4096. Use a slightly smaller number - to allow for a few compiler-allocated temporary stack slots. */ -# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ -# endif -# else -# define YYSTACK_ALLOC YYMALLOC -# define YYSTACK_FREE YYFREE -# ifndef YYSTACK_ALLOC_MAXIMUM -# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM -# endif -# if (defined __cplusplus && ! defined _STDLIB_H \ - && ! ((defined YYMALLOC || defined malloc) \ - && (defined YYFREE || defined free))) -# include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 -# endif -# endif -# ifndef YYMALLOC -# define YYMALLOC malloc -# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# ifndef YYFREE -# define YYFREE free -# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -void free (void *); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# endif -#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ - - -#if (! defined yyoverflow \ - && (! defined __cplusplus \ - || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) - -/* A type that is properly aligned for any stack member. */ -union yyalloc -{ - yytype_int16 yyss; - YYSTYPE yyvs; - }; - -/* The size of the maximum gap between one aligned stack and the next. */ -# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) - -/* The size of an array large to enough to hold all stacks, each with - N elements. */ -# define YYSTACK_BYTES(N) \ - ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ - + YYSTACK_GAP_MAXIMUM) - -/* Copy COUNT objects from FROM to TO. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) -# else -# define YYCOPY(To, From, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ - } \ - while (YYID (0)) -# endif -# endif - -/* Relocate STACK from its old location to the new one. The - local variables YYSIZE and YYSTACKSIZE give the old and new number of - elements in the stack, and YYPTR gives the new location of the - stack. Advance YYPTR to a properly aligned location for the next - stack. */ -# define YYSTACK_RELOCATE(Stack) \ - do \ - { \ - YYSIZE_T yynewbytes; \ - YYCOPY (&yyptr->Stack, Stack, yysize); \ - Stack = &yyptr->Stack; \ - yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ - yyptr += yynewbytes / sizeof (*yyptr); \ - } \ - while (YYID (0)) - -#endif - -/* YYFINAL -- State number of the termination state. */ -#define YYFINAL 3 -/* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 605 - -/* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 119 -/* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 41 -/* YYNRULES -- Number of rules. */ -#define YYNRULES 186 -/* YYNRULES -- Number of states. */ -#define YYNSTATES 254 - -/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ -#define YYUNDEFTOK 2 -#define YYMAXUTOK 358 - -#define YYTRANSLATE(YYX) \ - ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) - -/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ -static const yytype_uint8 yytranslate[] = -{ - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 103, 2, 2, 2, 2, 105, 2, - 112, 111, 108, 106, 2, 107, 2, 109, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 118, 2, - 115, 114, 113, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 116, 2, 117, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 104, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - 95, 96, 97, 98, 99, 100, 101, 102, 110 -}; - -#if YYDEBUG -/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in - YYRHS. */ -static const yytype_uint16 yyprhs[] = -{ - 0, 0, 3, 6, 8, 9, 11, 15, 19, 23, - 27, 29, 31, 33, 35, 39, 41, 45, 49, 51, - 55, 57, 59, 61, 64, 66, 68, 70, 74, 78, - 80, 82, 84, 87, 91, 94, 97, 100, 103, 106, - 109, 113, 115, 119, 123, 125, 127, 129, 132, 134, - 137, 139, 140, 142, 144, 148, 152, 156, 160, 162, - 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, - 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, - 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, - 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, - 244, 246, 249, 252, 255, 258, 263, 265, 267, 270, - 272, 275, 277, 279, 281, 283, 286, 289, 292, 295, - 298, 301, 303, 305, 307, 309, 311, 313, 315, 317, - 319, 321, 323, 328, 335, 339, 343, 347, 351, 355, - 359, 363, 367, 370, 374, 376, 378, 380, 382, 384, - 386, 388, 392, 394, 396, 398, 400, 402, 404, 406, - 408, 410, 412, 414, 416, 418, 420, 422, 425, 428, - 432, 434, 436, 440, 442, 444, 446, 448, 450, 452, - 454, 456, 459, 462, 466, 468, 470 -}; - -/* YYRHS -- A `-1'-separated list of the rules' RHS. */ -static const yytype_int16 yyrhs[] = -{ - 120, 0, -1, 121, 122, -1, 121, -1, -1, 131, - -1, 122, 123, 131, -1, 122, 123, 125, -1, 122, - 124, 131, -1, 122, 124, 125, -1, 101, -1, 102, - -1, 126, -1, 148, -1, 128, 129, 111, -1, 49, - -1, 51, 109, 36, -1, 51, 8, 51, -1, 51, - -1, 52, 109, 36, -1, 52, -1, 50, -1, 53, - -1, 127, 125, -1, 103, -1, 112, -1, 126, -1, - 130, 123, 125, -1, 130, 124, 125, -1, 148, -1, - 129, -1, 133, -1, 127, 131, -1, 134, 135, 136, - -1, 134, 135, -1, 134, 136, -1, 134, 13, -1, - 134, 14, -1, 134, 137, -1, 132, 125, -1, 128, - 122, 111, -1, 138, -1, 145, 143, 145, -1, 145, - 144, 145, -1, 139, -1, 149, -1, 150, -1, 151, - 152, -1, 155, -1, 156, 157, -1, 138, -1, -1, - 4, -1, 3, -1, 4, 102, 3, -1, 3, 102, - 4, -1, 4, 101, 3, -1, 3, 101, 4, -1, - 5, -1, 7, -1, 9, -1, 10, -1, 6, -1, - 45, -1, 18, -1, 16, -1, 17, -1, 19, -1, - 20, -1, 21, -1, 22, -1, 23, -1, 24, -1, - 25, -1, 26, -1, 27, -1, 28, -1, 29, -1, - 30, -1, 31, -1, 33, -1, 32, -1, 57, -1, - 58, -1, 59, -1, 60, -1, 65, -1, 66, -1, - 68, -1, 69, -1, 70, -1, 71, -1, 72, -1, - 73, -1, 75, -1, 74, -1, 67, -1, 76, -1, - 77, -1, 78, -1, 93, -1, 134, 34, -1, 134, - 35, -1, 11, 36, -1, 12, 36, -1, 15, 36, - 147, 36, -1, 37, -1, 38, -1, 61, 148, -1, - 61, -1, 62, 148, -1, 62, -1, 63, -1, 64, - -1, 140, -1, 39, 49, -1, 40, 49, -1, 41, - 36, -1, 42, 36, -1, 43, 141, -1, 44, 142, - -1, 36, -1, 49, -1, 49, -1, 113, -1, 46, - -1, 114, -1, 47, -1, 115, -1, 48, -1, 148, - -1, 146, -1, 138, 116, 145, 117, -1, 138, 116, - 145, 118, 36, 117, -1, 145, 106, 145, -1, 145, - 107, 145, -1, 145, 108, 145, -1, 145, 109, 145, - -1, 145, 105, 145, -1, 145, 104, 145, -1, 145, - 54, 145, -1, 145, 55, 145, -1, 107, 145, -1, - 128, 146, 111, -1, 56, -1, 105, -1, 104, -1, - 115, -1, 113, -1, 114, -1, 36, -1, 128, 148, - 111, -1, 79, -1, 80, -1, 81, -1, 82, -1, - 85, -1, 86, -1, 83, -1, 84, -1, 87, -1, - 88, -1, 89, -1, 90, -1, 91, -1, 92, -1, - 153, -1, 143, 36, -1, 144, 36, -1, 128, 154, - 111, -1, 36, -1, 153, -1, 154, 124, 153, -1, - 94, -1, 95, -1, 96, -1, 97, -1, 98, -1, - 99, -1, 100, -1, 158, -1, 143, 36, -1, 144, - 36, -1, 128, 159, 111, -1, 36, -1, 158, -1, - 159, 124, 158, -1 -}; - -/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ -static const yytype_uint16 yyrline[] = -{ - 0, 162, 162, 166, 168, 170, 171, 172, 173, 174, - 176, 178, 180, 181, 183, 185, 186, 188, 190, 195, - 204, 213, 222, 231, 233, 235, 237, 238, 239, 241, - 243, 245, 246, 248, 249, 250, 251, 252, 253, 255, - 256, 257, 258, 260, 262, 263, 264, 265, 266, 267, - 270, 271, 274, 275, 276, 277, 278, 279, 282, 283, - 284, 285, 288, 290, 291, 292, 293, 294, 295, 296, - 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, - 327, 329, 330, 331, 332, 333, 334, 335, 336, 337, - 338, 339, 340, 341, 342, 345, 346, 347, 348, 349, - 350, 353, 354, 367, 378, 379, 380, 382, 383, 384, - 386, 387, 389, 390, 391, 392, 393, 394, 395, 396, - 397, 398, 399, 400, 401, 403, 404, 405, 406, 407, - 409, 410, 412, 413, 414, 415, 416, 417, 418, 419, - 421, 422, 423, 424, 427, 428, 430, 431, 432, 433, - 435, 442, 443, 446, 447, 448, 451, 452, 453, 454, - 456, 457, 458, 459, 461, 470, 471 -}; -#endif - -#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE -/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. - First, the terminals, then, starting at YYNTOKENS, nonterminals. */ -static const char *const yytname[] = -{ - "$end", "error", "$undefined", "DST", "SRC", "HOST", "GATEWAY", "NET", - "NETMASK", "PORT", "PORTRANGE", "LESS", "GREATER", "PROTO", "PROTOCHAIN", - "CBYTE", "ARP", "RARP", "IP", "SCTP", "TCP", "UDP", "ICMP", "IGMP", - "IGRP", "PIM", "VRRP", "ATALK", "AARP", "DECNET", "LAT", "SCA", "MOPRC", - "MOPDL", "TK_BROADCAST", "TK_MULTICAST", "NUM", "INBOUND", "OUTBOUND", - "PF_IFNAME", "PF_RSET", "PF_RNR", "PF_SRNR", "PF_REASON", "PF_ACTION", - "LINK", "GEQ", "LEQ", "NEQ", "ID", "EID", "HID", "HID6", "AID", "LSH", - "RSH", "LEN", "IPV6", "ICMPV6", "AH", "ESP", "VLAN", "MPLS", "PPPOED", - "PPPOES", "ISO", "ESIS", "CLNP", "ISIS", "L1", "L2", "IIH", "LSP", "SNP", - "CSNP", "PSNP", "STP", "IPX", "NETBEUI", "LANE", "LLC", "METAC", "BCC", - "SC", "ILMIC", "OAMF4EC", "OAMF4SC", "OAM", "OAMF4", "CONNECTMSG", - "METACONNECT", "VPI", "VCI", "RADIO", "FISU", "LSSU", "MSU", "SIO", - "OPC", "DPC", "SLS", "AND", "OR", "'!'", "'|'", "'&'", "'+'", "'-'", - "'*'", "'/'", "UMINUS", "')'", "'('", "'>'", "'='", "'<'", "'['", "']'", - "':'", "$accept", "prog", "null", "expr", "and", "or", "id", "nid", - "not", "paren", "pid", "qid", "term", "head", "rterm", "pqual", "dqual", - "aqual", "ndaqual", "pname", "other", "pfvar", "reason", "action", - "relop", "irelop", "arth", "narth", "byteop", "pnum", "atmtype", - "atmmultitype", "atmfield", "atmvalue", "atmfieldvalue", "atmlistvalue", - "mtp2type", "mtp3field", "mtp3value", "mtp3fieldvalue", "mtp3listvalue", 0 -}; -#endif - -# ifdef YYPRINT -/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to - token YYLEX-NUM. */ -static const yytype_uint16 yytoknum[] = -{ - 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, - 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, - 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 33, 124, 38, 43, 45, 42, 47, - 358, 41, 40, 62, 61, 60, 91, 93, 58 -}; -# endif - -/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const yytype_uint8 yyr1[] = -{ - 0, 119, 120, 120, 121, 122, 122, 122, 122, 122, - 123, 124, 125, 125, 125, 126, 126, 126, 126, 126, - 126, 126, 126, 126, 127, 128, 129, 129, 129, 130, - 130, 131, 131, 132, 132, 132, 132, 132, 132, 133, - 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, - 134, 134, 135, 135, 135, 135, 135, 135, 136, 136, - 136, 136, 137, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, - 138, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 140, 140, 140, 140, 140, - 140, 141, 141, 142, 143, 143, 143, 144, 144, 144, - 145, 145, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 147, 147, 147, 147, 147, - 148, 148, 149, 149, 149, 149, 149, 149, 149, 149, - 150, 150, 150, 150, 151, 151, 152, 152, 152, 152, - 153, 154, 154, 155, 155, 155, 156, 156, 156, 156, - 157, 157, 157, 157, 158, 159, 159 -}; - -/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ -static const yytype_uint8 yyr2[] = -{ - 0, 2, 2, 1, 0, 1, 3, 3, 3, 3, - 1, 1, 1, 1, 3, 1, 3, 3, 1, 3, - 1, 1, 1, 2, 1, 1, 1, 3, 3, 1, - 1, 1, 2, 3, 2, 2, 2, 2, 2, 2, - 3, 1, 3, 3, 1, 1, 1, 2, 1, 2, - 1, 0, 1, 1, 3, 3, 3, 3, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 2, 2, 2, 4, 1, 1, 2, 1, - 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, - 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 4, 6, 3, 3, 3, 3, 3, 3, - 3, 3, 2, 3, 1, 1, 1, 1, 1, 1, - 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, - 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 2, 3, 1, 1, 3 -}; - -/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state - STATE-NUM when YYTABLE doesn't specify something else to do. Zero - means the default is an error. */ -static const yytype_uint8 yydefact[] = -{ - 4, 0, 51, 1, 0, 0, 0, 65, 66, 64, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 81, 80, 150, 106, 107, 0, 0, - 0, 0, 0, 0, 63, 144, 82, 83, 84, 85, - 109, 111, 112, 113, 86, 87, 96, 88, 89, 90, - 91, 92, 93, 95, 94, 97, 98, 99, 152, 153, - 154, 155, 158, 159, 156, 157, 160, 161, 162, 163, - 164, 165, 100, 173, 174, 175, 176, 177, 178, 179, - 24, 0, 25, 2, 51, 51, 5, 0, 31, 0, - 50, 44, 114, 0, 131, 130, 45, 46, 0, 48, - 0, 103, 104, 0, 115, 116, 117, 118, 121, 122, - 119, 123, 120, 0, 108, 110, 0, 0, 142, 10, - 11, 51, 51, 32, 0, 131, 130, 15, 21, 18, - 20, 22, 39, 12, 0, 0, 13, 53, 52, 58, - 62, 59, 60, 61, 36, 37, 101, 102, 34, 35, - 38, 0, 125, 127, 129, 0, 0, 0, 0, 0, - 0, 0, 0, 124, 126, 128, 0, 0, 170, 0, - 0, 0, 47, 166, 184, 0, 0, 0, 49, 180, - 146, 145, 148, 149, 147, 0, 0, 0, 7, 51, - 51, 6, 130, 9, 8, 40, 143, 151, 0, 0, - 0, 23, 26, 30, 0, 29, 0, 0, 0, 0, - 33, 0, 140, 141, 139, 138, 134, 135, 136, 137, - 42, 43, 171, 0, 167, 168, 185, 0, 181, 182, - 105, 130, 17, 16, 19, 14, 0, 0, 57, 55, - 56, 54, 132, 0, 169, 0, 183, 0, 27, 28, - 0, 172, 186, 133 -}; - -/* YYDEFGOTO[NTERM-NUM]. */ -static const yytype_int16 yydefgoto[] = -{ - -1, 1, 2, 124, 121, 122, 201, 133, 134, 116, - 203, 204, 86, 87, 88, 89, 148, 149, 150, 117, - 91, 92, 110, 112, 166, 167, 93, 94, 185, 95, - 96, 97, 98, 172, 173, 223, 99, 100, 178, 179, - 227 -}; - -/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing - STATE-NUM. */ -#define YYPACT_NINF -181 -static const yytype_int16 yypact[] = -{ - -181, 19, 200, -181, -3, 1, 15, -181, -181, -181, - -181, -181, -181, -181, -181, -181, -181, -181, -181, -181, - -181, -181, -181, -181, -181, -181, -181, -181, 13, 20, - 18, 44, -26, 35, -181, -181, -181, -181, -181, -181, - -19, -19, -181, -181, -181, -181, -181, -181, -181, -181, - -181, -181, -181, -181, -181, -181, -181, -181, -181, -181, - -181, -181, -181, -181, -181, -181, -181, -181, -181, -181, - -181, -181, -181, -181, -181, -181, -181, -181, -181, -181, - -181, 493, -181, 41, 396, 396, -181, -24, -181, 155, - 2, -181, -181, 488, -181, -181, -181, -181, 9, -181, - 134, -181, -181, 62, -181, -181, -181, -181, -181, -181, - -181, -181, -181, -19, -181, -181, 493, -9, -181, -181, - -181, 298, 298, -181, -53, -14, -1, -181, -181, 0, - 3, -181, -181, -181, -24, -24, -181, 77, 82, -181, - -181, -181, -181, -181, -181, -181, -181, -181, 437, -181, - -181, 493, -181, -181, -181, 493, 493, 493, 493, 493, - 493, 493, 493, -181, -181, -181, 493, 493, -181, 78, - 81, 89, -181, -181, -181, 95, 108, 113, -181, -181, - -181, -181, -181, -181, -181, 120, -1, -34, -181, 298, - 298, -181, 4, -181, -181, -181, -181, -181, 112, 149, - 150, -181, -181, 80, 41, -1, 188, 189, 205, 206, - -181, -41, 65, 65, 98, 144, -93, -93, -181, -181, - -34, -34, -181, -80, -181, -181, -181, -58, -181, -181, - -181, 46, -181, -181, -181, -181, -24, -24, -181, -181, - -181, -181, -181, 174, -181, 78, -181, 95, -181, -181, - 96, -181, -181, -181 -}; - -/* YYPGOTO[NTERM-NUM]. */ -static const yytype_int16 yypgoto[] = -{ - -181, -181, -181, 212, 50, -180, -86, -89, 5, -2, - -181, -181, -81, -181, -181, -181, -181, 107, -181, 7, - -181, -181, -181, -181, -66, -39, -21, -74, -181, -35, - -181, -181, -181, -181, -151, -181, -181, -181, -181, -145, - -181 -}; - -/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule which - number is the opposite. If zero, do what YYDEFACT says. - If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -42 -static const yytype_int16 yytable[] = -{ - 85, 132, -41, 123, -13, 114, 115, 84, 198, 90, - 108, 125, 25, 155, 156, 161, 162, 25, 222, 3, - 155, 156, 120, 109, 237, 127, 128, 129, 130, 131, - 226, 244, 170, 101, 176, 188, 193, 102, 113, 113, - 191, 194, 125, 245, 120, 168, 202, 247, 119, 120, - 126, 103, 136, 246, 106, 152, 153, 154, 195, 171, - 118, 177, 104, 157, 158, 159, 160, 161, 162, 105, - 157, 158, 159, 160, 161, 162, 242, 243, 186, 80, - 107, 126, 85, 85, 111, 135, 192, 192, 82, 84, - 84, 90, 90, 82, 251, 187, 169, 196, 175, 136, - 205, 202, 252, -41, -41, -13, -13, 151, 123, 199, - 197, 113, 200, -41, 168, -13, 125, 224, 151, 190, - 190, 82, 163, 164, 165, 225, 189, 189, 90, 90, - 211, 174, 135, 113, 212, 213, 214, 215, 216, 217, - 218, 219, 119, 120, 228, 220, 221, -29, -29, 229, - 248, 249, 155, 156, 192, 231, 230, 197, 137, 138, - 139, 140, 141, 232, 142, 143, 180, 181, 144, 145, - 174, 159, 160, 161, 162, 182, 183, 184, 206, 207, - 152, 153, 154, 208, 209, 233, 234, 190, 85, 146, - 147, 235, 238, 239, 189, 189, 90, 90, 155, 156, - -3, 136, 136, 158, 159, 160, 161, 162, 240, 241, - 250, 4, 5, 253, 83, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 135, 135, 25, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 82, 163, 164, 165, - 159, 160, 161, 162, 236, 210, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - 79, 0, 0, 80, 0, 0, 0, 81, 0, 4, - 5, 0, 82, 6, 7, 8, 9, 10, 11, 12, - 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, - 23, 24, 0, 0, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, 0, 0, 0, 127, 128, 129, - 130, 131, 0, 0, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, - 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - 71, 72, 73, 74, 75, 76, 77, 78, 79, 0, - 0, 80, 0, 0, 0, 81, 0, 4, 5, 0, - 82, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 0, 0, 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 139, 0, 141, 0, 142, 143, 0, 0, - 0, 0, 35, 36, 37, 38, 39, 40, 41, 42, - 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, - 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, - 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, - 73, 74, 75, 76, 77, 78, 79, 0, 0, 80, - 0, 0, 0, 81, 0, 0, 0, 0, 82, 7, - 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 0, 0, 25, - 0, 0, 0, 0, 152, 153, 154, 0, 34, 0, - 0, 0, 155, 156, 0, 0, 0, 0, 0, 35, - 36, 37, 38, 39, 0, 0, 0, 0, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, - 0, 0, 157, 158, 159, 160, 161, 162, 0, 0, - 81, 163, 164, 165, 0, 82 -}; - -static const yytype_int16 yycheck[] = -{ - 2, 87, 0, 84, 0, 40, 41, 2, 8, 2, - 36, 85, 36, 54, 55, 108, 109, 36, 169, 0, - 54, 55, 102, 49, 204, 49, 50, 51, 52, 53, - 175, 111, 98, 36, 100, 121, 122, 36, 40, 41, - 121, 122, 116, 223, 102, 36, 135, 227, 101, 102, - 85, 36, 87, 111, 36, 46, 47, 48, 111, 98, - 81, 100, 49, 104, 105, 106, 107, 108, 109, 49, - 104, 105, 106, 107, 108, 109, 117, 118, 113, 103, - 36, 116, 84, 85, 49, 87, 121, 122, 112, 84, - 85, 84, 85, 112, 245, 116, 98, 111, 100, 134, - 135, 190, 247, 101, 102, 101, 102, 116, 189, 109, - 111, 113, 109, 111, 36, 111, 190, 36, 116, 121, - 122, 112, 113, 114, 115, 36, 121, 122, 121, 122, - 151, 36, 134, 135, 155, 156, 157, 158, 159, 160, - 161, 162, 101, 102, 36, 166, 167, 101, 102, 36, - 236, 237, 54, 55, 189, 190, 36, 111, 3, 4, - 5, 6, 7, 51, 9, 10, 104, 105, 13, 14, - 36, 106, 107, 108, 109, 113, 114, 115, 101, 102, - 46, 47, 48, 101, 102, 36, 36, 189, 190, 34, - 35, 111, 4, 4, 189, 190, 189, 190, 54, 55, - 0, 236, 237, 105, 106, 107, 108, 109, 3, 3, - 36, 11, 12, 117, 2, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 236, 237, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 112, 113, 114, 115, - 106, 107, 108, 109, 204, 148, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, - 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, - 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, - 100, -1, -1, 103, -1, -1, -1, 107, -1, 11, - 12, -1, 112, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, -1, -1, 36, 37, 38, 39, 40, 41, - 42, 43, 44, 45, -1, -1, -1, 49, 50, 51, - 52, 53, -1, -1, 56, 57, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - 92, 93, 94, 95, 96, 97, 98, 99, 100, -1, - -1, 103, -1, -1, -1, 107, -1, 11, 12, -1, - 112, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, - -1, -1, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 5, -1, 7, -1, 9, 10, -1, -1, - -1, -1, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - 94, 95, 96, 97, 98, 99, 100, -1, -1, 103, - -1, -1, -1, 107, -1, -1, -1, -1, 112, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, -1, -1, 36, - -1, -1, -1, -1, 46, 47, 48, -1, 45, -1, - -1, -1, 54, 55, -1, -1, -1, -1, -1, 56, - 57, 58, 59, 60, -1, -1, -1, -1, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 93, -1, -1, -1, - -1, -1, 104, 105, 106, 107, 108, 109, -1, -1, - 107, 113, 114, 115, -1, 112 -}; - -/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing - symbol of state STATE-NUM. */ -static const yytype_uint8 yystos[] = -{ - 0, 120, 121, 0, 11, 12, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, - 29, 30, 31, 32, 33, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 56, 57, 58, 59, 60, - 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, - 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, - 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, - 103, 107, 112, 122, 127, 128, 131, 132, 133, 134, - 138, 139, 140, 145, 146, 148, 149, 150, 151, 155, - 156, 36, 36, 36, 49, 49, 36, 36, 36, 49, - 141, 49, 142, 128, 148, 148, 128, 138, 145, 101, - 102, 123, 124, 131, 122, 146, 148, 49, 50, 51, - 52, 53, 125, 126, 127, 128, 148, 3, 4, 5, - 6, 7, 9, 10, 13, 14, 34, 35, 135, 136, - 137, 116, 46, 47, 48, 54, 55, 104, 105, 106, - 107, 108, 109, 113, 114, 115, 143, 144, 36, 128, - 143, 144, 152, 153, 36, 128, 143, 144, 157, 158, - 104, 105, 113, 114, 115, 147, 148, 145, 125, 127, - 128, 131, 148, 125, 131, 111, 111, 111, 8, 109, - 109, 125, 126, 129, 130, 148, 101, 102, 101, 102, - 136, 145, 145, 145, 145, 145, 145, 145, 145, 145, - 145, 145, 153, 154, 36, 36, 158, 159, 36, 36, - 36, 148, 51, 36, 36, 111, 123, 124, 4, 4, - 3, 3, 117, 118, 111, 124, 111, 124, 125, 125, - 36, 153, 158, 117 -}; - -#define yyerrok (yyerrstatus = 0) -#define yyclearin (yychar = YYEMPTY) -#define YYEMPTY (-2) -#define YYEOF 0 - -#define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab -#define YYERROR goto yyerrorlab - - -/* Like YYERROR except do call yyerror. This remains here temporarily - to ease the transition to the new meaning of YYERROR, for GCC. - Once GCC version 2 has supplanted version 1, this can go. */ - -#define YYFAIL goto yyerrlab - -#define YYRECOVERING() (!!yyerrstatus) - -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY && yylen == 1) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - yytoken = YYTRANSLATE (yychar); \ - YYPOPSTACK (1); \ - goto yybackup; \ - } \ - else \ - { \ - yyerror (YY_("syntax error: cannot back up")); \ - YYERROR; \ - } \ -while (YYID (0)) - - -#define YYTERROR 1 -#define YYERRCODE 256 - - -/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. - If N is 0, then set CURRENT to the empty location which ends - the previous symbol: RHS[0] (always defined). */ - -#define YYRHSLOC(Rhs, K) ((Rhs)[K]) -#ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - do \ - if (YYID (N)) \ - { \ - (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ - (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ - (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ - (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ - } \ - else \ - { \ - (Current).first_line = (Current).last_line = \ - YYRHSLOC (Rhs, 0).last_line; \ - (Current).first_column = (Current).last_column = \ - YYRHSLOC (Rhs, 0).last_column; \ - } \ - while (YYID (0)) -#endif - - -/* YY_LOCATION_PRINT -- Print the location on the stream. - This macro was not mandated originally: define only if we know - we won't break user code: when these are the locations we know. */ - -#ifndef YY_LOCATION_PRINT -# if YYLTYPE_IS_TRIVIAL -# define YY_LOCATION_PRINT(File, Loc) \ - fprintf (File, "%d.%d-%d.%d", \ - (Loc).first_line, (Loc).first_column, \ - (Loc).last_line, (Loc).last_column) -# else -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -# endif -#endif - - -/* YYLEX -- calling `yylex' with the right arguments. */ - -#ifdef YYLEX_PARAM -# define YYLEX yylex (YYLEX_PARAM) -#else -# define YYLEX yylex () -#endif - -/* Enable debugging if requested. */ -#if YYDEBUG - -# ifndef YYFPRINTF -# include /* INFRINGES ON USER NAME SPACE */ -# define YYFPRINTF fprintf -# endif - -# define YYDPRINTF(Args) \ -do { \ - if (yydebug) \ - YYFPRINTF Args; \ -} while (YYID (0)) - -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ -do { \ - if (yydebug) \ - { \ - YYFPRINTF (stderr, "%s ", Title); \ - yy_symbol_print (stderr, \ - Type, Value); \ - YYFPRINTF (stderr, "\n"); \ - } \ -} while (YYID (0)) - - -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ - -/*ARGSUSED*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) -#else -static void -yy_symbol_value_print (yyoutput, yytype, yyvaluep) - FILE *yyoutput; - int yytype; - YYSTYPE const * const yyvaluep; -#endif -{ - if (!yyvaluep) - return; -# ifdef YYPRINT - if (yytype < YYNTOKENS) - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); -# else - YYUSE (yyoutput); -# endif - switch (yytype) - { - default: - break; - } -} - - -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ - -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) -#else -static void -yy_symbol_print (yyoutput, yytype, yyvaluep) - FILE *yyoutput; - int yytype; - YYSTYPE const * const yyvaluep; -#endif -{ - if (yytype < YYNTOKENS) - YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); - else - YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); - - yy_symbol_value_print (yyoutput, yytype, yyvaluep); - YYFPRINTF (yyoutput, ")"); -} - -/*------------------------------------------------------------------. -| yy_stack_print -- Print the state stack from its BOTTOM up to its | -| TOP (included). | -`------------------------------------------------------------------*/ - -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) -#else -static void -yy_stack_print (bottom, top) - yytype_int16 *bottom; - yytype_int16 *top; -#endif -{ - YYFPRINTF (stderr, "Stack now"); - for (; bottom <= top; ++bottom) - YYFPRINTF (stderr, " %d", *bottom); - YYFPRINTF (stderr, "\n"); -} - -# define YY_STACK_PRINT(Bottom, Top) \ -do { \ - if (yydebug) \ - yy_stack_print ((Bottom), (Top)); \ -} while (YYID (0)) - - -/*------------------------------------------------. -| Report that the YYRULE is going to be reduced. | -`------------------------------------------------*/ - -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_reduce_print (YYSTYPE *yyvsp, int yyrule) -#else -static void -yy_reduce_print (yyvsp, yyrule) - YYSTYPE *yyvsp; - int yyrule; -#endif -{ - int yynrhs = yyr2[yyrule]; - int yyi; - unsigned long int yylno = yyrline[yyrule]; - YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", - yyrule - 1, yylno); - /* The symbols being reduced. */ - for (yyi = 0; yyi < yynrhs; yyi++) - { - fprintf (stderr, " $%d = ", yyi + 1); - yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], - &(yyvsp[(yyi + 1) - (yynrhs)]) - ); - fprintf (stderr, "\n"); - } -} - -# define YY_REDUCE_PRINT(Rule) \ -do { \ - if (yydebug) \ - yy_reduce_print (yyvsp, Rule); \ -} while (YYID (0)) - -/* Nonzero means print parse trace. It is left uninitialized so that - multiple parsers can coexist. */ -int yydebug; -#else /* !YYDEBUG */ -# define YYDPRINTF(Args) -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) -# define YY_STACK_PRINT(Bottom, Top) -# define YY_REDUCE_PRINT(Rule) -#endif /* !YYDEBUG */ - - -/* YYINITDEPTH -- initial size of the parser's stacks. */ -#ifndef YYINITDEPTH -# define YYINITDEPTH 200 -#endif - -/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only - if the built-in stack extension method is used). - - Do not make this value too large; the results are undefined if - YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) - evaluated with infinite-precision integer arithmetic. */ - -#ifndef YYMAXDEPTH -# define YYMAXDEPTH 10000 -#endif - - - -#if YYERROR_VERBOSE - -# ifndef yystrlen -# if defined __GLIBC__ && defined _STRING_H -# define yystrlen strlen -# else -/* Return the length of YYSTR. */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static YYSIZE_T -yystrlen (const char *yystr) -#else -static YYSIZE_T -yystrlen (yystr) - const char *yystr; -#endif -{ - YYSIZE_T yylen; - for (yylen = 0; yystr[yylen]; yylen++) - continue; - return yylen; -} -# endif -# endif - -# ifndef yystpcpy -# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE -# define yystpcpy stpcpy -# else -/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in - YYDEST. */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static char * -yystpcpy (char *yydest, const char *yysrc) -#else -static char * -yystpcpy (yydest, yysrc) - char *yydest; - const char *yysrc; -#endif -{ - char *yyd = yydest; - const char *yys = yysrc; - - while ((*yyd++ = *yys++) != '\0') - continue; - - return yyd - 1; -} -# endif -# endif - -# ifndef yytnamerr -/* Copy to YYRES the contents of YYSTR after stripping away unnecessary - quotes and backslashes, so that it's suitable for yyerror. The - heuristic is that double-quoting is unnecessary unless the string - contains an apostrophe, a comma, or backslash (other than - backslash-backslash). YYSTR is taken from yytname. If YYRES is - null, do not copy; instead, return the length of what the result - would have been. */ -static YYSIZE_T -yytnamerr (char *yyres, const char *yystr) -{ - if (*yystr == '"') - { - YYSIZE_T yyn = 0; - char const *yyp = yystr; - - for (;;) - switch (*++yyp) - { - case '\'': - case ',': - goto do_not_strip_quotes; - - case '\\': - if (*++yyp != '\\') - goto do_not_strip_quotes; - /* Fall through. */ - default: - if (yyres) - yyres[yyn] = *yyp; - yyn++; - break; - - case '"': - if (yyres) - yyres[yyn] = '\0'; - return yyn; - } - do_not_strip_quotes: ; - } - - if (! yyres) - return yystrlen (yystr); - - return yystpcpy (yyres, yystr) - yyres; -} -# endif - -/* Copy into YYRESULT an error message about the unexpected token - YYCHAR while in state YYSTATE. Return the number of bytes copied, - including the terminating null byte. If YYRESULT is null, do not - copy anything; just return the number of bytes that would be - copied. As a special case, return 0 if an ordinary "syntax error" - message will do. Return YYSIZE_MAXIMUM if overflow occurs during - size calculation. */ -static YYSIZE_T -yysyntax_error (char *yyresult, int yystate, int yychar) -{ - int yyn = yypact[yystate]; - - if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) - return 0; - else - { - int yytype = YYTRANSLATE (yychar); - YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); - YYSIZE_T yysize = yysize0; - YYSIZE_T yysize1; - int yysize_overflow = 0; - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - int yyx; - -# if 0 - /* This is so xgettext sees the translatable formats that are - constructed on the fly. */ - YY_("syntax error, unexpected %s"); - YY_("syntax error, unexpected %s, expecting %s"); - YY_("syntax error, unexpected %s, expecting %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); -# endif - char *yyfmt; - char const *yyf; - static char const yyunexpected[] = "syntax error, unexpected %s"; - static char const yyexpecting[] = ", expecting %s"; - static char const yyor[] = " or %s"; - char yyformat[sizeof yyunexpected - + sizeof yyexpecting - 1 - + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) - * (sizeof yyor - 1))]; - char const *yyprefix = yyexpecting; - - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yycount = 1; - - yyarg[0] = yytname[yytype]; - yyfmt = yystpcpy (yyformat, yyunexpected); - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) - { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - yyformat[sizeof yyunexpected - 1] = '\0'; - break; - } - yyarg[yycount++] = yytname[yyx]; - yysize1 = yysize + yytnamerr (0, yytname[yyx]); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - yyfmt = yystpcpy (yyfmt, yyprefix); - yyprefix = yyor; - } - - yyf = YY_(yyformat); - yysize1 = yysize + yystrlen (yyf); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - - if (yysize_overflow) - return YYSIZE_MAXIMUM; - - if (yyresult) - { - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - char *yyp = yyresult; - int yyi = 0; - while ((*yyp = *yyf) != '\0') - { - if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyf += 2; - } - else - { - yyp++; - yyf++; - } - } - } - return yysize; - } -} -#endif /* YYERROR_VERBOSE */ - - -/*-----------------------------------------------. -| Release the memory associated to this symbol. | -`-----------------------------------------------*/ - -/*ARGSUSED*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) -#else -static void -yydestruct (yymsg, yytype, yyvaluep) - const char *yymsg; - int yytype; - YYSTYPE *yyvaluep; -#endif -{ - YYUSE (yyvaluep); - - if (!yymsg) - yymsg = "Deleting"; - YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); - - switch (yytype) - { - - default: - break; - } -} - - -/* Prevent warnings from -Wmissing-prototypes. */ - -#ifdef YYPARSE_PARAM -#if defined __STDC__ || defined __cplusplus -int yyparse (void *YYPARSE_PARAM); -#else -int yyparse (); -#endif -#else /* ! YYPARSE_PARAM */ -#if defined __STDC__ || defined __cplusplus -int yyparse (void); -#else -int yyparse (); -#endif -#endif /* ! YYPARSE_PARAM */ - - - -/* The look-ahead symbol. */ -int yychar; - -/* The semantic value of the look-ahead symbol. */ -YYSTYPE yylval; - -/* Number of syntax errors so far. */ -int yynerrs; - - - -/*----------. -| yyparse. | -`----------*/ - -#ifdef YYPARSE_PARAM -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -int -yyparse (void *YYPARSE_PARAM) -#else -int -yyparse (YYPARSE_PARAM) - void *YYPARSE_PARAM; -#endif -#else /* ! YYPARSE_PARAM */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -int -yyparse (void) -#else -int -yyparse () - -#endif -#endif -{ - - int yystate; - int yyn; - int yyresult; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; - /* Look-ahead token as an internal (translated) token number. */ - int yytoken = 0; -#if YYERROR_VERBOSE - /* Buffer for error messages, and its allocated size. */ - char yymsgbuf[128]; - char *yymsg = yymsgbuf; - YYSIZE_T yymsg_alloc = sizeof yymsgbuf; -#endif - - /* Three stacks and their tools: - `yyss': related to states, - `yyvs': related to semantic values, - `yyls': related to locations. - - Refer to the stacks thru separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ - - /* The state stack. */ - yytype_int16 yyssa[YYINITDEPTH]; - yytype_int16 *yyss = yyssa; - yytype_int16 *yyssp; - - /* The semantic value stack. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs = yyvsa; - YYSTYPE *yyvsp; - - - -#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) - - YYSIZE_T yystacksize = YYINITDEPTH; - - /* The variables used to return semantic value and location from the - action routines. */ - YYSTYPE yyval; - - - /* The number of symbols on the RHS of the reduced rule. - Keep to zero when no symbol should be popped. */ - int yylen = 0; - - YYDPRINTF ((stderr, "Starting parse\n")); - - yystate = 0; - yyerrstatus = 0; - yynerrs = 0; - yychar = YYEMPTY; /* Cause a token to be read. */ - - /* Initialize stack pointers. - Waste one element of value and location stack - so that they stay on the same level as the state stack. - The wasted elements are never initialized. */ - - yyssp = yyss; - yyvsp = yyvs; - - goto yysetstate; - -/*------------------------------------------------------------. -| yynewstate -- Push a new state, which is found in yystate. | -`------------------------------------------------------------*/ - yynewstate: - /* In all cases, when you get here, the value and location stacks - have just been pushed. So pushing a state here evens the stacks. */ - yyssp++; - - yysetstate: - *yyssp = yystate; - - if (yyss + yystacksize - 1 <= yyssp) - { - /* Get the current used size of the three stacks, in elements. */ - YYSIZE_T yysize = yyssp - yyss + 1; - -#ifdef yyoverflow - { - /* Give user a chance to reallocate the stack. Use copies of - these so that the &'s don't force the real ones into - memory. */ - YYSTYPE *yyvs1 = yyvs; - yytype_int16 *yyss1 = yyss; - - - /* Each stack pointer address is followed by the size of the - data in use in that stack, in bytes. This used to be a - conditional around just the two extra args, but that might - be undefined if yyoverflow is a macro. */ - yyoverflow (YY_("memory exhausted"), - &yyss1, yysize * sizeof (*yyssp), - &yyvs1, yysize * sizeof (*yyvsp), - - &yystacksize); - - yyss = yyss1; - yyvs = yyvs1; - } -#else /* no yyoverflow */ -# ifndef YYSTACK_RELOCATE - goto yyexhaustedlab; -# else - /* Extend the stack our own way. */ - if (YYMAXDEPTH <= yystacksize) - goto yyexhaustedlab; - yystacksize *= 2; - if (YYMAXDEPTH < yystacksize) - yystacksize = YYMAXDEPTH; - - { - yytype_int16 *yyss1 = yyss; - union yyalloc *yyptr = - (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); - if (! yyptr) - goto yyexhaustedlab; - YYSTACK_RELOCATE (yyss); - YYSTACK_RELOCATE (yyvs); - -# undef YYSTACK_RELOCATE - if (yyss1 != yyssa) - YYSTACK_FREE (yyss1); - } -# endif -#endif /* no yyoverflow */ - - yyssp = yyss + yysize - 1; - yyvsp = yyvs + yysize - 1; - - - YYDPRINTF ((stderr, "Stack size increased to %lu\n", - (unsigned long int) yystacksize)); - - if (yyss + yystacksize - 1 <= yyssp) - YYABORT; - } - - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); - - goto yybackup; - -/*-----------. -| yybackup. | -`-----------*/ -yybackup: - - /* Do appropriate processing given the current state. Read a - look-ahead token if we need one and don't already have one. */ - - /* First try to decide what to do without reference to look-ahead token. */ - yyn = yypact[yystate]; - if (yyn == YYPACT_NINF) - goto yydefault; - - /* Not known => get a look-ahead token if don't already have one. */ - - /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ - if (yychar == YYEMPTY) - { - YYDPRINTF ((stderr, "Reading a token: ")); - yychar = YYLEX; - } - - if (yychar <= YYEOF) - { - yychar = yytoken = YYEOF; - YYDPRINTF ((stderr, "Now at end of input.\n")); - } - else - { - yytoken = YYTRANSLATE (yychar); - YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); - } - - /* If the proper action on seeing token YYTOKEN is to reduce or to - detect an error, take that action. */ - yyn += yytoken; - if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) - goto yydefault; - yyn = yytable[yyn]; - if (yyn <= 0) - { - if (yyn == 0 || yyn == YYTABLE_NINF) - goto yyerrlab; - yyn = -yyn; - goto yyreduce; - } - - if (yyn == YYFINAL) - YYACCEPT; - - /* Count tokens shifted since error; after three, turn off error - status. */ - if (yyerrstatus) - yyerrstatus--; - - /* Shift the look-ahead token. */ - YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - - /* Discard the shifted token unless it is eof. */ - if (yychar != YYEOF) - yychar = YYEMPTY; - - yystate = yyn; - *++yyvsp = yylval; - - goto yynewstate; - - -/*-----------------------------------------------------------. -| yydefault -- do the default action for the current state. | -`-----------------------------------------------------------*/ -yydefault: - yyn = yydefact[yystate]; - if (yyn == 0) - goto yyerrlab; - goto yyreduce; - - -/*-----------------------------. -| yyreduce -- Do a reduction. | -`-----------------------------*/ -yyreduce: - /* yyn is the number of a rule to reduce with. */ - yylen = yyr2[yyn]; - - /* If YYLEN is nonzero, implement the default value of the action: - `$$ = $1'. - - Otherwise, the following line sets YYVAL to garbage. - This behavior is undocumented and Bison - users should not rely upon it. Assigning to YYVAL - unconditionally makes the parser a bit smaller, and it avoids a - GCC warning that YYVAL may be used uninitialized. */ - yyval = yyvsp[1-yylen]; - - - YY_REDUCE_PRINT (yyn); - switch (yyn) - { - case 2: -#line 163 "grammar.y" - { - finish_parse((yyvsp[(2) - (2)].blk).b); -} - break; - - case 4: -#line 168 "grammar.y" - { (yyval.blk).q = qerr; } - break; - - case 6: -#line 171 "grammar.y" - { gen_and((yyvsp[(1) - (3)].blk).b, (yyvsp[(3) - (3)].blk).b); (yyval.blk) = (yyvsp[(3) - (3)].blk); } - break; - - case 7: -#line 172 "grammar.y" - { gen_and((yyvsp[(1) - (3)].blk).b, (yyvsp[(3) - (3)].blk).b); (yyval.blk) = (yyvsp[(3) - (3)].blk); } - break; - - case 8: -#line 173 "grammar.y" - { gen_or((yyvsp[(1) - (3)].blk).b, (yyvsp[(3) - (3)].blk).b); (yyval.blk) = (yyvsp[(3) - (3)].blk); } - break; - - case 9: -#line 174 "grammar.y" - { gen_or((yyvsp[(1) - (3)].blk).b, (yyvsp[(3) - (3)].blk).b); (yyval.blk) = (yyvsp[(3) - (3)].blk); } - break; - - case 10: -#line 176 "grammar.y" - { (yyval.blk) = (yyvsp[(0) - (1)].blk); } - break; - - case 11: -#line 178 "grammar.y" - { (yyval.blk) = (yyvsp[(0) - (1)].blk); } - break; - - case 13: -#line 181 "grammar.y" - { (yyval.blk).b = gen_ncode(NULL, (bpf_u_int32)(yyvsp[(1) - (1)].i), - (yyval.blk).q = (yyvsp[(0) - (1)].blk).q); } - break; - - case 14: -#line 183 "grammar.y" - { (yyval.blk) = (yyvsp[(2) - (3)].blk); } - break; - - case 15: -#line 185 "grammar.y" - { (yyval.blk).b = gen_scode((yyvsp[(1) - (1)].s), (yyval.blk).q = (yyvsp[(0) - (1)].blk).q); } - break; - - case 16: -#line 186 "grammar.y" - { (yyval.blk).b = gen_mcode((yyvsp[(1) - (3)].s), NULL, (yyvsp[(3) - (3)].i), - (yyval.blk).q = (yyvsp[(0) - (3)].blk).q); } - break; - - case 17: -#line 188 "grammar.y" - { (yyval.blk).b = gen_mcode((yyvsp[(1) - (3)].s), (yyvsp[(3) - (3)].s), 0, - (yyval.blk).q = (yyvsp[(0) - (3)].blk).q); } - break; - - case 18: -#line 190 "grammar.y" - { - /* Decide how to parse HID based on proto */ - (yyval.blk).q = (yyvsp[(0) - (1)].blk).q; - (yyval.blk).b = gen_ncode((yyvsp[(1) - (1)].s), 0, (yyval.blk).q); - } - break; - - case 19: -#line 195 "grammar.y" - { -#ifdef INET6 - (yyval.blk).b = gen_mcode6((yyvsp[(1) - (3)].s), NULL, (yyvsp[(3) - (3)].i), - (yyval.blk).q = (yyvsp[(0) - (3)].blk).q); -#else - bpf_error("'ip6addr/prefixlen' not supported " - "in this configuration"); -#endif /*INET6*/ - } - break; - - case 20: -#line 204 "grammar.y" - { -#ifdef INET6 - (yyval.blk).b = gen_mcode6((yyvsp[(1) - (1)].s), 0, 128, - (yyval.blk).q = (yyvsp[(0) - (1)].blk).q); -#else - bpf_error("'ip6addr' not supported " - "in this configuration"); -#endif /*INET6*/ - } - break; - - case 21: -#line 213 "grammar.y" - { - (yyval.blk).b = gen_ecode((yyvsp[(1) - (1)].e), (yyval.blk).q = (yyvsp[(0) - (1)].blk).q); - /* - * $1 was allocated by "pcap_ether_aton()", - * so we must free it now that we're done - * with it. - */ - free((yyvsp[(1) - (1)].e)); - } - break; - - case 22: -#line 222 "grammar.y" - { - (yyval.blk).b = gen_acode((yyvsp[(1) - (1)].e), (yyval.blk).q = (yyvsp[(0) - (1)].blk).q); - /* - * $1 was allocated by "pcap_ether_aton()", - * so we must free it now that we're done - * with it. - */ - free((yyvsp[(1) - (1)].e)); - } - break; - - case 23: -#line 231 "grammar.y" - { gen_not((yyvsp[(2) - (2)].blk).b); (yyval.blk) = (yyvsp[(2) - (2)].blk); } - break; - - case 24: -#line 233 "grammar.y" - { (yyval.blk) = (yyvsp[(0) - (1)].blk); } - break; - - case 25: -#line 235 "grammar.y" - { (yyval.blk) = (yyvsp[(0) - (1)].blk); } - break; - - case 27: -#line 238 "grammar.y" - { gen_and((yyvsp[(1) - (3)].blk).b, (yyvsp[(3) - (3)].blk).b); (yyval.blk) = (yyvsp[(3) - (3)].blk); } - break; - - case 28: -#line 239 "grammar.y" - { gen_or((yyvsp[(1) - (3)].blk).b, (yyvsp[(3) - (3)].blk).b); (yyval.blk) = (yyvsp[(3) - (3)].blk); } - break; - - case 29: -#line 241 "grammar.y" - { (yyval.blk).b = gen_ncode(NULL, (bpf_u_int32)(yyvsp[(1) - (1)].i), - (yyval.blk).q = (yyvsp[(0) - (1)].blk).q); } - break; - - case 32: -#line 246 "grammar.y" - { gen_not((yyvsp[(2) - (2)].blk).b); (yyval.blk) = (yyvsp[(2) - (2)].blk); } - break; - - case 33: -#line 248 "grammar.y" - { QSET((yyval.blk).q, (yyvsp[(1) - (3)].i), (yyvsp[(2) - (3)].i), (yyvsp[(3) - (3)].i)); } - break; - - case 34: -#line 249 "grammar.y" - { QSET((yyval.blk).q, (yyvsp[(1) - (2)].i), (yyvsp[(2) - (2)].i), Q_DEFAULT); } - break; - - case 35: -#line 250 "grammar.y" - { QSET((yyval.blk).q, (yyvsp[(1) - (2)].i), Q_DEFAULT, (yyvsp[(2) - (2)].i)); } - break; - - case 36: -#line 251 "grammar.y" - { QSET((yyval.blk).q, (yyvsp[(1) - (2)].i), Q_DEFAULT, Q_PROTO); } - break; - - case 37: -#line 252 "grammar.y" - { QSET((yyval.blk).q, (yyvsp[(1) - (2)].i), Q_DEFAULT, Q_PROTOCHAIN); } - break; - - case 38: -#line 253 "grammar.y" - { QSET((yyval.blk).q, (yyvsp[(1) - (2)].i), Q_DEFAULT, (yyvsp[(2) - (2)].i)); } - break; - - case 39: -#line 255 "grammar.y" - { (yyval.blk) = (yyvsp[(2) - (2)].blk); } - break; - - case 40: -#line 256 "grammar.y" - { (yyval.blk).b = (yyvsp[(2) - (3)].blk).b; (yyval.blk).q = (yyvsp[(1) - (3)].blk).q; } - break; - - case 41: -#line 257 "grammar.y" - { (yyval.blk).b = gen_proto_abbrev((yyvsp[(1) - (1)].i)); (yyval.blk).q = qerr; } - break; - - case 42: -#line 258 "grammar.y" - { (yyval.blk).b = gen_relation((yyvsp[(2) - (3)].i), (yyvsp[(1) - (3)].a), (yyvsp[(3) - (3)].a), 0); - (yyval.blk).q = qerr; } - break; - - case 43: -#line 260 "grammar.y" - { (yyval.blk).b = gen_relation((yyvsp[(2) - (3)].i), (yyvsp[(1) - (3)].a), (yyvsp[(3) - (3)].a), 1); - (yyval.blk).q = qerr; } - break; - - case 44: -#line 262 "grammar.y" - { (yyval.blk).b = (yyvsp[(1) - (1)].rblk); (yyval.blk).q = qerr; } - break; - - case 45: -#line 263 "grammar.y" - { (yyval.blk).b = gen_atmtype_abbrev((yyvsp[(1) - (1)].i)); (yyval.blk).q = qerr; } - break; - - case 46: -#line 264 "grammar.y" - { (yyval.blk).b = gen_atmmulti_abbrev((yyvsp[(1) - (1)].i)); (yyval.blk).q = qerr; } - break; - - case 47: -#line 265 "grammar.y" - { (yyval.blk).b = (yyvsp[(2) - (2)].blk).b; (yyval.blk).q = qerr; } - break; - - case 48: -#line 266 "grammar.y" - { (yyval.blk).b = gen_mtp2type_abbrev((yyvsp[(1) - (1)].i)); (yyval.blk).q = qerr; } - break; - - case 49: -#line 267 "grammar.y" - { (yyval.blk).b = (yyvsp[(2) - (2)].blk).b; (yyval.blk).q = qerr; } - break; - - case 51: -#line 271 "grammar.y" - { (yyval.i) = Q_DEFAULT; } - break; - - case 52: -#line 274 "grammar.y" - { (yyval.i) = Q_SRC; } - break; - - case 53: -#line 275 "grammar.y" - { (yyval.i) = Q_DST; } - break; - - case 54: -#line 276 "grammar.y" - { (yyval.i) = Q_OR; } - break; - - case 55: -#line 277 "grammar.y" - { (yyval.i) = Q_OR; } - break; - - case 56: -#line 278 "grammar.y" - { (yyval.i) = Q_AND; } - break; - - case 57: -#line 279 "grammar.y" - { (yyval.i) = Q_AND; } - break; - - case 58: -#line 282 "grammar.y" - { (yyval.i) = Q_HOST; } - break; - - case 59: -#line 283 "grammar.y" - { (yyval.i) = Q_NET; } - break; - - case 60: -#line 284 "grammar.y" - { (yyval.i) = Q_PORT; } - break; - - case 61: -#line 285 "grammar.y" - { (yyval.i) = Q_PORTRANGE; } - break; - - case 62: -#line 288 "grammar.y" - { (yyval.i) = Q_GATEWAY; } - break; - - case 63: -#line 290 "grammar.y" - { (yyval.i) = Q_LINK; } - break; - - case 64: -#line 291 "grammar.y" - { (yyval.i) = Q_IP; } - break; - - case 65: -#line 292 "grammar.y" - { (yyval.i) = Q_ARP; } - break; - - case 66: -#line 293 "grammar.y" - { (yyval.i) = Q_RARP; } - break; - - case 67: -#line 294 "grammar.y" - { (yyval.i) = Q_SCTP; } - break; - - case 68: -#line 295 "grammar.y" - { (yyval.i) = Q_TCP; } - break; - - case 69: -#line 296 "grammar.y" - { (yyval.i) = Q_UDP; } - break; - - case 70: -#line 297 "grammar.y" - { (yyval.i) = Q_ICMP; } - break; - - case 71: -#line 298 "grammar.y" - { (yyval.i) = Q_IGMP; } - break; - - case 72: -#line 299 "grammar.y" - { (yyval.i) = Q_IGRP; } - break; - - case 73: -#line 300 "grammar.y" - { (yyval.i) = Q_PIM; } - break; - - case 74: -#line 301 "grammar.y" - { (yyval.i) = Q_VRRP; } - break; - - case 75: -#line 302 "grammar.y" - { (yyval.i) = Q_ATALK; } - break; - - case 76: -#line 303 "grammar.y" - { (yyval.i) = Q_AARP; } - break; - - case 77: -#line 304 "grammar.y" - { (yyval.i) = Q_DECNET; } - break; - - case 78: -#line 305 "grammar.y" - { (yyval.i) = Q_LAT; } - break; - - case 79: -#line 306 "grammar.y" - { (yyval.i) = Q_SCA; } - break; - - case 80: -#line 307 "grammar.y" - { (yyval.i) = Q_MOPDL; } - break; - - case 81: -#line 308 "grammar.y" - { (yyval.i) = Q_MOPRC; } - break; - - case 82: -#line 309 "grammar.y" - { (yyval.i) = Q_IPV6; } - break; - - case 83: -#line 310 "grammar.y" - { (yyval.i) = Q_ICMPV6; } - break; - - case 84: -#line 311 "grammar.y" - { (yyval.i) = Q_AH; } - break; - - case 85: -#line 312 "grammar.y" - { (yyval.i) = Q_ESP; } - break; - - case 86: -#line 313 "grammar.y" - { (yyval.i) = Q_ISO; } - break; - - case 87: -#line 314 "grammar.y" - { (yyval.i) = Q_ESIS; } - break; - - case 88: -#line 315 "grammar.y" - { (yyval.i) = Q_ISIS; } - break; - - case 89: -#line 316 "grammar.y" - { (yyval.i) = Q_ISIS_L1; } - break; - - case 90: -#line 317 "grammar.y" - { (yyval.i) = Q_ISIS_L2; } - break; - - case 91: -#line 318 "grammar.y" - { (yyval.i) = Q_ISIS_IIH; } - break; - - case 92: -#line 319 "grammar.y" - { (yyval.i) = Q_ISIS_LSP; } - break; - - case 93: -#line 320 "grammar.y" - { (yyval.i) = Q_ISIS_SNP; } - break; - - case 94: -#line 321 "grammar.y" - { (yyval.i) = Q_ISIS_PSNP; } - break; - - case 95: -#line 322 "grammar.y" - { (yyval.i) = Q_ISIS_CSNP; } - break; - - case 96: -#line 323 "grammar.y" - { (yyval.i) = Q_CLNP; } - break; - - case 97: -#line 324 "grammar.y" - { (yyval.i) = Q_STP; } - break; - - case 98: -#line 325 "grammar.y" - { (yyval.i) = Q_IPX; } - break; - - case 99: -#line 326 "grammar.y" - { (yyval.i) = Q_NETBEUI; } - break; - - case 100: -#line 327 "grammar.y" - { (yyval.i) = Q_RADIO; } - break; - - case 101: -#line 329 "grammar.y" - { (yyval.rblk) = gen_broadcast((yyvsp[(1) - (2)].i)); } - break; - - case 102: -#line 330 "grammar.y" - { (yyval.rblk) = gen_multicast((yyvsp[(1) - (2)].i)); } - break; - - case 103: -#line 331 "grammar.y" - { (yyval.rblk) = gen_less((yyvsp[(2) - (2)].i)); } - break; - - case 104: -#line 332 "grammar.y" - { (yyval.rblk) = gen_greater((yyvsp[(2) - (2)].i)); } - break; - - case 105: -#line 333 "grammar.y" - { (yyval.rblk) = gen_byteop((yyvsp[(3) - (4)].i), (yyvsp[(2) - (4)].i), (yyvsp[(4) - (4)].i)); } - break; - - case 106: -#line 334 "grammar.y" - { (yyval.rblk) = gen_inbound(0); } - break; - - case 107: -#line 335 "grammar.y" - { (yyval.rblk) = gen_inbound(1); } - break; - - case 108: -#line 336 "grammar.y" - { (yyval.rblk) = gen_vlan((yyvsp[(2) - (2)].i)); } - break; - - case 109: -#line 337 "grammar.y" - { (yyval.rblk) = gen_vlan(-1); } - break; - - case 110: -#line 338 "grammar.y" - { (yyval.rblk) = gen_mpls((yyvsp[(2) - (2)].i)); } - break; - - case 111: -#line 339 "grammar.y" - { (yyval.rblk) = gen_mpls(-1); } - break; - - case 112: -#line 340 "grammar.y" - { (yyval.rblk) = gen_pppoed(); } - break; - - case 113: -#line 341 "grammar.y" - { (yyval.rblk) = gen_pppoes(); } - break; - - case 114: -#line 342 "grammar.y" - { (yyval.rblk) = (yyvsp[(1) - (1)].rblk); } - break; - - case 115: -#line 345 "grammar.y" - { (yyval.rblk) = gen_pf_ifname((yyvsp[(2) - (2)].s)); } - break; - - case 116: -#line 346 "grammar.y" - { (yyval.rblk) = gen_pf_ruleset((yyvsp[(2) - (2)].s)); } - break; - - case 117: -#line 347 "grammar.y" - { (yyval.rblk) = gen_pf_rnr((yyvsp[(2) - (2)].i)); } - break; - - case 118: -#line 348 "grammar.y" - { (yyval.rblk) = gen_pf_srnr((yyvsp[(2) - (2)].i)); } - break; - - case 119: -#line 349 "grammar.y" - { (yyval.rblk) = gen_pf_reason((yyvsp[(2) - (2)].i)); } - break; - - case 120: -#line 350 "grammar.y" - { (yyval.rblk) = gen_pf_action((yyvsp[(2) - (2)].i)); } - break; - - case 121: -#line 353 "grammar.y" - { (yyval.i) = (yyvsp[(1) - (1)].i); } - break; - - case 122: -#line 354 "grammar.y" - { const char *reasons[] = PFRES_NAMES; - int i; - for (i = 0; reasons[i]; i++) { - if (pcap_strcasecmp((yyvsp[(1) - (1)].s), reasons[i]) == 0) { - (yyval.i) = i; - break; - } - } - if (reasons[i] == NULL) - bpf_error("unknown PF reason"); - } - break; - - case 123: -#line 367 "grammar.y" - { if (pcap_strcasecmp((yyvsp[(1) - (1)].s), "pass") == 0 || - pcap_strcasecmp((yyvsp[(1) - (1)].s), "accept") == 0) - (yyval.i) = PF_PASS; - else if (pcap_strcasecmp((yyvsp[(1) - (1)].s), "drop") == 0 || - pcap_strcasecmp((yyvsp[(1) - (1)].s), "block") == 0) - (yyval.i) = PF_DROP; - else - bpf_error("unknown PF action"); - } - break; - - case 124: -#line 378 "grammar.y" - { (yyval.i) = BPF_JGT; } - break; - - case 125: -#line 379 "grammar.y" - { (yyval.i) = BPF_JGE; } - break; - - case 126: -#line 380 "grammar.y" - { (yyval.i) = BPF_JEQ; } - break; - - case 127: -#line 382 "grammar.y" - { (yyval.i) = BPF_JGT; } - break; - - case 128: -#line 383 "grammar.y" - { (yyval.i) = BPF_JGE; } - break; - - case 129: -#line 384 "grammar.y" - { (yyval.i) = BPF_JEQ; } - break; - - case 130: -#line 386 "grammar.y" - { (yyval.a) = gen_loadi((yyvsp[(1) - (1)].i)); } - break; - - case 132: -#line 389 "grammar.y" - { (yyval.a) = gen_load((yyvsp[(1) - (4)].i), (yyvsp[(3) - (4)].a), 1); } - break; - - case 133: -#line 390 "grammar.y" - { (yyval.a) = gen_load((yyvsp[(1) - (6)].i), (yyvsp[(3) - (6)].a), (yyvsp[(5) - (6)].i)); } - break; - - case 134: -#line 391 "grammar.y" - { (yyval.a) = gen_arth(BPF_ADD, (yyvsp[(1) - (3)].a), (yyvsp[(3) - (3)].a)); } - break; - - case 135: -#line 392 "grammar.y" - { (yyval.a) = gen_arth(BPF_SUB, (yyvsp[(1) - (3)].a), (yyvsp[(3) - (3)].a)); } - break; - - case 136: -#line 393 "grammar.y" - { (yyval.a) = gen_arth(BPF_MUL, (yyvsp[(1) - (3)].a), (yyvsp[(3) - (3)].a)); } - break; - - case 137: -#line 394 "grammar.y" - { (yyval.a) = gen_arth(BPF_DIV, (yyvsp[(1) - (3)].a), (yyvsp[(3) - (3)].a)); } - break; - - case 138: -#line 395 "grammar.y" - { (yyval.a) = gen_arth(BPF_AND, (yyvsp[(1) - (3)].a), (yyvsp[(3) - (3)].a)); } - break; - - case 139: -#line 396 "grammar.y" - { (yyval.a) = gen_arth(BPF_OR, (yyvsp[(1) - (3)].a), (yyvsp[(3) - (3)].a)); } - break; - - case 140: -#line 397 "grammar.y" - { (yyval.a) = gen_arth(BPF_LSH, (yyvsp[(1) - (3)].a), (yyvsp[(3) - (3)].a)); } - break; - - case 141: -#line 398 "grammar.y" - { (yyval.a) = gen_arth(BPF_RSH, (yyvsp[(1) - (3)].a), (yyvsp[(3) - (3)].a)); } - break; - - case 142: -#line 399 "grammar.y" - { (yyval.a) = gen_neg((yyvsp[(2) - (2)].a)); } - break; - - case 143: -#line 400 "grammar.y" - { (yyval.a) = (yyvsp[(2) - (3)].a); } - break; - - case 144: -#line 401 "grammar.y" - { (yyval.a) = gen_loadlen(); } - break; - - case 145: -#line 403 "grammar.y" - { (yyval.i) = '&'; } - break; - - case 146: -#line 404 "grammar.y" - { (yyval.i) = '|'; } - break; - - case 147: -#line 405 "grammar.y" - { (yyval.i) = '<'; } - break; - - case 148: -#line 406 "grammar.y" - { (yyval.i) = '>'; } - break; - - case 149: -#line 407 "grammar.y" - { (yyval.i) = '='; } - break; - - case 151: -#line 410 "grammar.y" - { (yyval.i) = (yyvsp[(2) - (3)].i); } - break; - - case 152: -#line 412 "grammar.y" - { (yyval.i) = A_LANE; } - break; - - case 153: -#line 413 "grammar.y" - { (yyval.i) = A_LLC; } - break; - - case 154: -#line 414 "grammar.y" - { (yyval.i) = A_METAC; } - break; - - case 155: -#line 415 "grammar.y" - { (yyval.i) = A_BCC; } - break; - - case 156: -#line 416 "grammar.y" - { (yyval.i) = A_OAMF4EC; } - break; - - case 157: -#line 417 "grammar.y" - { (yyval.i) = A_OAMF4SC; } - break; - - case 158: -#line 418 "grammar.y" - { (yyval.i) = A_SC; } - break; - - case 159: -#line 419 "grammar.y" - { (yyval.i) = A_ILMIC; } - break; - - case 160: -#line 421 "grammar.y" - { (yyval.i) = A_OAM; } - break; - - case 161: -#line 422 "grammar.y" - { (yyval.i) = A_OAMF4; } - break; - - case 162: -#line 423 "grammar.y" - { (yyval.i) = A_CONNECTMSG; } - break; - - case 163: -#line 424 "grammar.y" - { (yyval.i) = A_METACONNECT; } - break; - - case 164: -#line 427 "grammar.y" - { (yyval.blk).atmfieldtype = A_VPI; } - break; - - case 165: -#line 428 "grammar.y" - { (yyval.blk).atmfieldtype = A_VCI; } - break; - - case 167: -#line 431 "grammar.y" - { (yyval.blk).b = gen_atmfield_code((yyvsp[(0) - (2)].blk).atmfieldtype, (bpf_int32)(yyvsp[(2) - (2)].i), (bpf_u_int32)(yyvsp[(1) - (2)].i), 0); } - break; - - case 168: -#line 432 "grammar.y" - { (yyval.blk).b = gen_atmfield_code((yyvsp[(0) - (2)].blk).atmfieldtype, (bpf_int32)(yyvsp[(2) - (2)].i), (bpf_u_int32)(yyvsp[(1) - (2)].i), 1); } - break; - - case 169: -#line 433 "grammar.y" - { (yyval.blk).b = (yyvsp[(2) - (3)].blk).b; (yyval.blk).q = qerr; } - break; - - case 170: -#line 435 "grammar.y" - { - (yyval.blk).atmfieldtype = (yyvsp[(0) - (1)].blk).atmfieldtype; - if ((yyval.blk).atmfieldtype == A_VPI || - (yyval.blk).atmfieldtype == A_VCI) - (yyval.blk).b = gen_atmfield_code((yyval.blk).atmfieldtype, (bpf_int32) (yyvsp[(1) - (1)].i), BPF_JEQ, 0); - } - break; - - case 172: -#line 443 "grammar.y" - { gen_or((yyvsp[(1) - (3)].blk).b, (yyvsp[(3) - (3)].blk).b); (yyval.blk) = (yyvsp[(3) - (3)].blk); } - break; - - case 173: -#line 446 "grammar.y" - { (yyval.i) = M_FISU; } - break; - - case 174: -#line 447 "grammar.y" - { (yyval.i) = M_LSSU; } - break; - - case 175: -#line 448 "grammar.y" - { (yyval.i) = M_MSU; } - break; - - case 176: -#line 451 "grammar.y" - { (yyval.blk).mtp3fieldtype = M_SIO; } - break; - - case 177: -#line 452 "grammar.y" - { (yyval.blk).mtp3fieldtype = M_OPC; } - break; - - case 178: -#line 453 "grammar.y" - { (yyval.blk).mtp3fieldtype = M_DPC; } - break; - - case 179: -#line 454 "grammar.y" - { (yyval.blk).mtp3fieldtype = M_SLS; } - break; - - case 181: -#line 457 "grammar.y" - { (yyval.blk).b = gen_mtp3field_code((yyvsp[(0) - (2)].blk).mtp3fieldtype, (u_int)(yyvsp[(2) - (2)].i), (u_int)(yyvsp[(1) - (2)].i), 0); } - break; - - case 182: -#line 458 "grammar.y" - { (yyval.blk).b = gen_mtp3field_code((yyvsp[(0) - (2)].blk).mtp3fieldtype, (u_int)(yyvsp[(2) - (2)].i), (u_int)(yyvsp[(1) - (2)].i), 1); } - break; - - case 183: -#line 459 "grammar.y" - { (yyval.blk).b = (yyvsp[(2) - (3)].blk).b; (yyval.blk).q = qerr; } - break; - - case 184: -#line 461 "grammar.y" - { - (yyval.blk).mtp3fieldtype = (yyvsp[(0) - (1)].blk).mtp3fieldtype; - if ((yyval.blk).mtp3fieldtype == M_SIO || - (yyval.blk).mtp3fieldtype == M_OPC || - (yyval.blk).mtp3fieldtype == M_DPC || - (yyval.blk).mtp3fieldtype == M_SLS ) - (yyval.blk).b = gen_mtp3field_code((yyval.blk).mtp3fieldtype, (u_int) (yyvsp[(1) - (1)].i), BPF_JEQ, 0); - } - break; - - case 186: -#line 471 "grammar.y" - { gen_or((yyvsp[(1) - (3)].blk).b, (yyvsp[(3) - (3)].blk).b); (yyval.blk) = (yyvsp[(3) - (3)].blk); } - break; - - -/* Line 1267 of yacc.c. */ -#line 2902 "y.tab.c" - default: break; - } - YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); - - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); - - *++yyvsp = yyval; - - - /* Now `shift' the result of the reduction. Determine what state - that goes to, based on the state we popped back to and the rule - number reduced by. */ - - yyn = yyr1[yyn]; - - yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; - if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) - yystate = yytable[yystate]; - else - yystate = yydefgoto[yyn - YYNTOKENS]; - - goto yynewstate; - - -/*------------------------------------. -| yyerrlab -- here on detecting error | -`------------------------------------*/ -yyerrlab: - /* If not already recovering from an error, report this error. */ - if (!yyerrstatus) - { - ++yynerrs; -#if ! YYERROR_VERBOSE - yyerror (YY_("syntax error")); -#else - { - YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); - if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) - { - YYSIZE_T yyalloc = 2 * yysize; - if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) - yyalloc = YYSTACK_ALLOC_MAXIMUM; - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yyalloc); - if (yymsg) - yymsg_alloc = yyalloc; - else - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - } - } - - if (0 < yysize && yysize <= yymsg_alloc) - { - (void) yysyntax_error (yymsg, yystate, yychar); - yyerror (yymsg); - } - else - { - yyerror (YY_("syntax error")); - if (yysize != 0) - goto yyexhaustedlab; - } - } -#endif - } - - - - if (yyerrstatus == 3) - { - /* If just tried and failed to reuse look-ahead token after an - error, discard it. */ - - if (yychar <= YYEOF) - { - /* Return failure if at end of input. */ - if (yychar == YYEOF) - YYABORT; - } - else - { - yydestruct ("Error: discarding", - yytoken, &yylval); - yychar = YYEMPTY; - } - } - - /* Else will try to reuse look-ahead token after shifting the error - token. */ - goto yyerrlab1; - - -/*---------------------------------------------------. -| yyerrorlab -- error raised explicitly by YYERROR. | -`---------------------------------------------------*/ -yyerrorlab: - - /* Pacify compilers like GCC when the user code never invokes - YYERROR and the label yyerrorlab therefore never appears in user - code. */ - if (/*CONSTCOND*/ 0) - goto yyerrorlab; - - /* Do not reclaim the symbols of the rule which action triggered - this YYERROR. */ - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); - yystate = *yyssp; - goto yyerrlab1; - - -/*-------------------------------------------------------------. -| yyerrlab1 -- common code for both syntax error and YYERROR. | -`-------------------------------------------------------------*/ -yyerrlab1: - yyerrstatus = 3; /* Each real token shifted decrements this. */ - - for (;;) - { - yyn = yypact[yystate]; - if (yyn != YYPACT_NINF) - { - yyn += YYTERROR; - if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) - { - yyn = yytable[yyn]; - if (0 < yyn) - break; - } - } - - /* Pop the current state because it cannot handle the error token. */ - if (yyssp == yyss) - YYABORT; - - - yydestruct ("Error: popping", - yystos[yystate], yyvsp); - YYPOPSTACK (1); - yystate = *yyssp; - YY_STACK_PRINT (yyss, yyssp); - } - - if (yyn == YYFINAL) - YYACCEPT; - - *++yyvsp = yylval; - - - /* Shift the error token. */ - YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); - - yystate = yyn; - goto yynewstate; - - -/*-------------------------------------. -| yyacceptlab -- YYACCEPT comes here. | -`-------------------------------------*/ -yyacceptlab: - yyresult = 0; - goto yyreturn; - -/*-----------------------------------. -| yyabortlab -- YYABORT comes here. | -`-----------------------------------*/ -yyabortlab: - yyresult = 1; - goto yyreturn; - -#ifndef yyoverflow -/*-------------------------------------------------. -| yyexhaustedlab -- memory exhaustion comes here. | -`-------------------------------------------------*/ -yyexhaustedlab: - yyerror (YY_("memory exhausted")); - yyresult = 2; - /* Fall through. */ -#endif - -yyreturn: - if (yychar != YYEOF && yychar != YYEMPTY) - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval); - /* Do not reclaim the symbols of the rule which action triggered - this YYABORT or YYACCEPT. */ - YYPOPSTACK (yylen); - YY_STACK_PRINT (yyss, yyssp); - while (yyssp != yyss) - { - yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp); - YYPOPSTACK (1); - } -#ifndef yyoverflow - if (yyss != yyssa) - YYSTACK_FREE (yyss); -#endif -#if YYERROR_VERBOSE - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); -#endif - /* Make sure YYID is used. */ - return YYID (yyresult); -} - - -#line 473 "grammar.y" - - diff --git a/libpcap/grammar.y b/libpcap/grammar.y index eedd63051..7076c87bc 100644 --- a/libpcap/grammar.y +++ b/libpcap/grammar.y @@ -22,7 +22,7 @@ */ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/grammar.y,v 1.86.2.8 2007/06/11 09:52:04 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/grammar.y,v 1.99.2.2 2007/11/18 02:04:55 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -52,8 +52,13 @@ struct rtentry; #include "pcap-int.h" #include "gencode.h" -#include "pf.h" -#include +#ifdef HAVE_NET_PFVAR_H +#include +#include +#include +#endif +#include "ieee80211.h" +#include #ifdef HAVE_OS_PROTO_H #include "os-proto.h" @@ -63,6 +68,92 @@ struct rtentry; (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 }; @@ -85,6 +176,66 @@ pcap_parse() } #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 { @@ -109,7 +260,7 @@ pcap_parse() %type arth narth %type byteop pname pnum relop irelop %type and or paren not null prog -%type other pfvar +%type other pfvar p80211 %type atmtype atmmultitype %type atmfield %type atmfieldvalue atmvalue atmlistvalue @@ -125,6 +276,7 @@ pcap_parse() %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 %token LINK %token GEQ LEQ NEQ %token ID EID HID HID6 AID @@ -148,7 +300,7 @@ pcap_parse() %type EID %type AID %type HID HID6 -%type NUM action reason +%type NUM action reason type subtype type_subtype dir %left OR AND %nonassoc '!' @@ -190,6 +342,14 @@ nid: ID { $$.b = gen_scode($1, $$.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 { @@ -277,6 +437,10 @@ dqual: SRC { $$ = Q_SRC; } | 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; } ; /* address type qualifiers */ aqual: HOST { $$ = Q_HOST; } @@ -340,6 +504,7 @@ other: pqual TK_BROADCAST { $$ = gen_broadcast($1); } | PPPOED { $$ = gen_pppoed(); } | PPPOES { $$ = gen_pppoes(); } | pfvar { $$ = $1; } + | pqual p80211 { $$ = $2; } ; pfvar: PF_IFNAME ID { $$ = gen_pf_ifname($2); } @@ -350,31 +515,86 @@ pfvar: PF_IFNAME ID { $$ = gen_pf_ifname($2); } | PF_ACTION action { $$ = gen_pf_action($2); } ; -reason: NUM { $$ = $1; } - | ID { const char *reasons[] = PFRES_NAMES; - int i; - for (i = 0; reasons[i]; i++) { - if (pcap_strcasecmp($1, reasons[i]) == 0) { - $$ = i; - break; - } - } - if (reasons[i] == NULL) - bpf_error("unknown PF reason"); +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"); } ; -action: ID { if (pcap_strcasecmp($1, "pass") == 0 || - pcap_strcasecmp($1, "accept") == 0) - $$ = PF_PASS; - else if (pcap_strcasecmp($1, "drop") == 0 || - pcap_strcasecmp($1, "block") == 0) - $$ = PF_DROP; - else - bpf_error("unknown PF action"); +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; } diff --git a/libpcap/ieee80211.h b/libpcap/ieee80211.h new file mode 100644 index 000000000..473803d8a --- /dev/null +++ b/libpcap/ieee80211.h @@ -0,0 +1,146 @@ +/*- + * Copyright (c) 2001 Atsushi Onoe + * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting + * 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. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * 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. + * + * $FreeBSD: src/sys/net80211/ieee80211.h,v 1.10 2005/07/22 16:55:27 sam Exp $ + */ +#ifndef _NET80211_IEEE80211_H_ +#define _NET80211_IEEE80211_H_ + +/* + * 802.11 protocol definitions. + */ + +#define IEEE80211_FC0_VERSION_MASK 0x03 +#define IEEE80211_FC0_VERSION_SHIFT 0 +#define IEEE80211_FC0_VERSION_0 0x00 +#define IEEE80211_FC0_TYPE_MASK 0x0c +#define IEEE80211_FC0_TYPE_SHIFT 2 +#define IEEE80211_FC0_TYPE_MGT 0x00 +#define IEEE80211_FC0_TYPE_CTL 0x04 +#define IEEE80211_FC0_TYPE_DATA 0x08 + +#define IEEE80211_FC0_SUBTYPE_MASK 0xf0 +#define IEEE80211_FC0_SUBTYPE_SHIFT 4 +/* for TYPE_MGT */ +#define IEEE80211_FC0_SUBTYPE_ASSOC_REQ 0x00 +#define IEEE80211_FC0_SUBTYPE_ASSOC_RESP 0x10 +#define IEEE80211_FC0_SUBTYPE_REASSOC_REQ 0x20 +#define IEEE80211_FC0_SUBTYPE_REASSOC_RESP 0x30 +#define IEEE80211_FC0_SUBTYPE_PROBE_REQ 0x40 +#define IEEE80211_FC0_SUBTYPE_PROBE_RESP 0x50 +#define IEEE80211_FC0_SUBTYPE_BEACON 0x80 +#define IEEE80211_FC0_SUBTYPE_ATIM 0x90 +#define IEEE80211_FC0_SUBTYPE_DISASSOC 0xa0 +#define IEEE80211_FC0_SUBTYPE_AUTH 0xb0 +#define IEEE80211_FC0_SUBTYPE_DEAUTH 0xc0 +/* for TYPE_CTL */ +#define IEEE80211_FC0_SUBTYPE_PS_POLL 0xa0 +#define IEEE80211_FC0_SUBTYPE_RTS 0xb0 +#define IEEE80211_FC0_SUBTYPE_CTS 0xc0 +#define IEEE80211_FC0_SUBTYPE_ACK 0xd0 +#define IEEE80211_FC0_SUBTYPE_CF_END 0xe0 +#define IEEE80211_FC0_SUBTYPE_CF_END_ACK 0xf0 +/* for TYPE_DATA (bit combination) */ +#define IEEE80211_FC0_SUBTYPE_DATA 0x00 +#define IEEE80211_FC0_SUBTYPE_CF_ACK 0x10 +#define IEEE80211_FC0_SUBTYPE_CF_POLL 0x20 +#define IEEE80211_FC0_SUBTYPE_CF_ACPL 0x30 +#define IEEE80211_FC0_SUBTYPE_NODATA 0x40 +#define IEEE80211_FC0_SUBTYPE_NODATA_CF_ACK 0x50 +#define IEEE80211_FC0_SUBTYPE_NODATA_CF_POLL 0x60 +#define IEEE80211_FC0_SUBTYPE_NODATA_CF_ACPL 0x70 +#define IEEE80211_FC0_SUBTYPE_QOS 0x80 +#define IEEE80211_FC0_SUBTYPE_QOS_NULL 0xc0 + +#define IEEE80211_FC1_DIR_MASK 0x03 +#define IEEE80211_FC1_DIR_NODS 0x00 /* STA->STA */ +#define IEEE80211_FC1_DIR_TODS 0x01 /* STA->AP */ +#define IEEE80211_FC1_DIR_FROMDS 0x02 /* AP ->STA */ +#define IEEE80211_FC1_DIR_DSTODS 0x03 /* AP ->AP */ + +#define IEEE80211_FC1_MORE_FRAG 0x04 +#define IEEE80211_FC1_RETRY 0x08 +#define IEEE80211_FC1_PWR_MGT 0x10 +#define IEEE80211_FC1_MORE_DATA 0x20 +#define IEEE80211_FC1_WEP 0x40 +#define IEEE80211_FC1_ORDER 0x80 + +#define IEEE80211_SEQ_FRAG_MASK 0x000f +#define IEEE80211_SEQ_FRAG_SHIFT 0 +#define IEEE80211_SEQ_SEQ_MASK 0xfff0 +#define IEEE80211_SEQ_SEQ_SHIFT 4 + +#define IEEE80211_NWID_LEN 32 + +#define IEEE80211_QOS_TXOP 0x00ff +/* bit 8 is reserved */ +#define IEEE80211_QOS_ACKPOLICY 0x60 +#define IEEE80211_QOS_ACKPOLICY_S 5 +#define IEEE80211_QOS_ESOP 0x10 +#define IEEE80211_QOS_ESOP_S 4 +#define IEEE80211_QOS_TID 0x0f + +#define IEEE80211_MGT_SUBTYPE_NAMES { \ + "assoc-req", "assoc-resp", \ + "reassoc-req", "reassoc-resp", \ + "probe-req", "probe-resp", \ + "reserved#6", "reserved#7", \ + "beacon", "atim", \ + "disassoc", "auth", \ + "deauth", "reserved#13", \ + "reserved#14", "reserved#15" \ +} + +#define IEEE80211_CTL_SUBTYPE_NAMES { \ + "reserved#0", "reserved#1", \ + "reserved#2", "reserved#3", \ + "reserved#3", "reserved#5", \ + "reserved#6", "reserved#7", \ + "reserved#8", "reserved#9", \ + "ps-poll", "rts", \ + "cts", "ack", \ + "cf-end", "cf-end-ack" \ +} + +#define IEEE80211_DATA_SUBTYPE_NAMES { \ + "data", "data-cf-ack", \ + "data-cf-poll", "data-cf-ack-poll", \ + "null", "cf-ack", \ + "cf-poll", "cf-ack-poll", \ + "qos-data", "qos-data-cf-ack", \ + "qos-data-cf-poll", "qos-data-cf-ack-poll", \ + "qos", "reserved#13", \ + "qos-cf-poll", "qos-cf-ack-poll" \ +} + +#define IEEE80211_TYPE_NAMES { "mgt", "ctl", "data", "reserved#4" } + +#endif /* _NET80211_IEEE80211_H_ */ diff --git a/libpcap/inet.c b/libpcap/inet.c index 8a44728b3..aad87963e 100644 --- a/libpcap/inet.c +++ b/libpcap/inet.c @@ -34,7 +34,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.66.2.6 2007/06/11 09:52:04 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.75.2.4 2008-04-20 18:19:24 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -356,6 +356,40 @@ add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name, return (0); } +/* + * XXX - on FreeBSDs that support it, should it get the sysctl named + * "dev.{adapter family name}.{adapter unit}.%desc" to get a description + * of the adapter? Note that "dev.an.0.%desc" is "Aironet PC4500/PC4800" + * with my Cisco 350 card, so the name isn't entirely descriptive. The + * "dev.an.0.%pnpinfo" has a better description, although one might argue + * that the problem is really a driver bug - if it can find out that it's + * a Cisco 340 or 350, rather than an old Aironet card, it should use + * that in the description. + * + * Do NetBSD, DragonflyBSD, or OpenBSD support this as well? OpenBSD + * lets you get a description, but it's not generated by the OS, it's + * set with another ioctl that ifconfig supports; we use that to get + * the description in OpenBSD. + * + * In OS X, the System Configuration framework can apparently return + * names in 10.4 and later; it also appears that freedesktop.org's HAL + * offers an "info.product" string, but the HAL specification says + * it "should not be used in any UI" and "subsystem/capability + * specific properties" should be used instead. Using that would + * require that libpcap applications be linked with the frameworks/ + * libraries in question, which would be a bit of a pain unless we + * offer, for example, a pkg-config: + * + * http://pkg-config.freedesktop.org/wiki/ + * + * script, so applications can just use that script to find out what + * libraries you need to link with when linking with libpcap. + * pkg-config is GPLed; I don't know whether that would prevent its + * use with a BSD-licensed library such as libpcap. + * + * Do any other UN*Xes, or desktop environments support getting a + * description? + */ int add_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags, struct sockaddr *addr, size_t addr_size, @@ -365,9 +399,32 @@ add_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags, char *errbuf) { pcap_if_t *curdev; + char *description = NULL; pcap_addr_t *curaddr, *prevaddr, *nextaddr; +#ifdef SIOCGIFDESCR + struct ifreq ifrdesc; + char ifdescr[IFDESCRSIZE]; + int s; +#endif - if (add_or_find_if(&curdev, alldevs, name, flags, NULL, errbuf) == -1) { +#ifdef SIOCGIFDESCR + /* + * Get the description for the interface. + */ + memset(&ifrdesc, 0, sizeof ifrdesc); + strlcpy(ifrdesc.ifr_name, name, sizeof ifrdesc.ifr_name); + ifrdesc.ifr_data = (caddr_t)&ifdescr; + s = socket(AF_INET, SOCK_DGRAM, 0); + if (s >= 0) { + if (ioctl(s, SIOCGIFDESCR, &ifrdesc) == 0 && + strlen(ifrdesc.ifr_data) != 0) + description = ifrdesc.ifr_data; + close(s); + } +#endif + + if (add_or_find_if(&curdev, alldevs, name, flags, description, + errbuf) == -1) { /* * Error - give up. */ @@ -607,6 +664,12 @@ pcap_lookupnet(device, netp, maskp, errbuf) #endif #ifdef HAVE_SEPTEL_API || strstr(device, "septel") != NULL +#endif +#ifdef PCAP_SUPPORT_BT + || strstr(device, "bluetooth") != NULL +#endif +#ifdef PCAP_SUPPORT_USB + || strstr(device, "usb") != NULL #endif ) { *netp = *maskp = 0; diff --git a/libpcap/mkdep b/libpcap/mkdep index 2a9c221b1..b41a00e1d 100755 --- a/libpcap/mkdep +++ b/libpcap/mkdep @@ -13,7 +13,7 @@ # @(#)mkdep.sh 5.11 (Berkeley) 5/5/88 # -PATH=/bin:/usr/bin:/usr/ucb:/usr/local:/usr/local/bin +PATH=/bin:/usr/bin:/usr/ucb:/usr/local:/usr/local/bin:/usr/sfw/bin export PATH MAKE=Makefile # default makefile name is "Makefile" diff --git a/libpcap/nametoaddr.c b/libpcap/nametoaddr.c index d60e93d5c..c21e7849c 100644 --- a/libpcap/nametoaddr.c +++ b/libpcap/nametoaddr.c @@ -24,7 +24,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/nametoaddr.c,v 1.77.2.4 2007/06/11 09:52:05 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/nametoaddr.c,v 1.82.2.1 2008/02/06 10:21:47 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -80,7 +80,7 @@ struct rtentry; /* declarations in */ #include "pcap-int.h" #include "gencode.h" -#include +#include #ifdef HAVE_OS_PROTO_H #include "os-proto.h" @@ -398,7 +398,15 @@ __pcap_atodn(const char *s, bpf_u_int32 *addr) } /* - * Convert 's' which has the form "xx:xx:xx:xx:xx:xx" into a new + * 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 * @@ -410,7 +418,7 @@ pcap_ether_aton(const char *s) e = ep = (u_char *)malloc(6); while (*s) { - if (*s == ':') + if (*s == ':' || *s == '.' || *s == '-') s += 1; d = xdtoi(*s++); if (isxdigit((unsigned char)*s)) { diff --git a/libpcap/optimize.c b/libpcap/optimize.c index 1502ab15e..475313f26 100644 --- a/libpcap/optimize.c +++ b/libpcap/optimize.c @@ -22,7 +22,7 @@ */ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/optimize.c,v 1.85.2.2 2007/07/15 19:55:04 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/optimize.c,v 1.90.2.1 2008/01/02 04:22:16 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -53,6 +53,10 @@ 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. */ @@ -905,6 +909,17 @@ opt_peep(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. @@ -1972,7 +1987,7 @@ opt_init(root) */ unMarkAll(); n = count_blocks(root); - blocks = (struct block **)malloc(n * sizeof(*blocks)); + blocks = (struct block **)calloc(n, sizeof(*blocks)); if (blocks == NULL) bpf_error("malloc"); unMarkAll(); @@ -1980,14 +1995,14 @@ opt_init(root) number_blks_r(root); n_edges = 2 * n_blocks; - edges = (struct edge **)malloc(n_edges * sizeof(*edges)); + 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 **)malloc(n_blocks * sizeof(*levels)); + levels = (struct block **)calloc(n_blocks, sizeof(*levels)); if (levels == NULL) bpf_error("malloc"); @@ -2034,8 +2049,8 @@ opt_init(root) * we'll need. */ maxval = 3 * max_stmts; - vmap = (struct vmapinfo *)malloc(maxval * sizeof(*vmap)); - vnode_base = (struct valnode *)malloc(maxval * sizeof(*vnode_base)); + 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"); } @@ -2276,6 +2291,15 @@ 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. */ diff --git a/libpcap/org.tcpdump.chmod_bpf.plist b/libpcap/org.tcpdump.chmod_bpf.plist new file mode 100644 index 000000000..8ad685261 --- /dev/null +++ b/libpcap/org.tcpdump.chmod_bpf.plist @@ -0,0 +1,16 @@ + + + + + Label + org.tcpdump.chmod_bpf + RunAtLoad + + Program + /usr/local/bin/chmod_bpf + ProgramArguments + + /usr/local/bin/chmod_bpf + + + diff --git a/libpcap/pcap-bpf.c b/libpcap/pcap-bpf.c index 027913e7f..6ec6515fb 100644 --- a/libpcap/pcap-bpf.c +++ b/libpcap/pcap-bpf.c @@ -20,7 +20,7 @@ */ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.86.2.12 2007/06/15 17:57:27 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.99.2.17 2008-09-16 18:43:02 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -28,6 +28,9 @@ static const char rcsid[] _U_ = #endif #include /* optionally get BSD define */ +#ifdef HAVE_ZEROCOPY_BPF +#include +#endif #include #include #include @@ -35,12 +38,16 @@ static const char rcsid[] _U_ = #include #include +#ifdef HAVE_ZEROCOPY_BPF +#include +#endif + #include #ifdef _AIX /* - * Make "pcap.h" not include "pcap-bpf.h"; we are going to include the + * 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 @@ -92,6 +99,10 @@ static int odmlockid = 0; #include #include +#ifdef HAVE_NET_IF_MEDIA_H +# include +#endif + #include "pcap-int.h" #ifdef HAVE_DAG_API @@ -102,12 +113,579 @@ static int odmlockid = 0; #include "os-proto.h" #endif -#include "gencode.h" /* for "no_optimize" */ +#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 */ + +/* + * 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); +#ifdef HAVE_ZEROCOPY_BPF +/* + * For zerocopy bpf, we need to override the setnonblock/getnonblock routines + * 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_zbuf(pcap_t *p, char *errbuf) +{ + /* + * Use a negative value for the timeout to represent that the + * pcap handle is in non-blocking mode. + */ + return (p->md.timeout < 0); +} + +static int +pcap_setnonblock_zbuf(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. + * (from pcap-linux.c). + */ + if (nonblock) { + if (p->md.timeout > 0) + p->md.timeout = p->md.timeout * -1 - 1; + } else + if (p->md.timeout < 0) + p->md.timeout = (p->md.timeout + 1) * -1; + return (0); +} + +/* + * Zero-copy specific close method. Un-map the shared buffers then call + * pcap_cleanup_live_common. + */ +static void +pcap_cleanup_zbuf(pcap_t *p) +{ + /* + * 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; + pcap_cleanup_live_common(p); +} + +/* + * 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 + +pcap_t * +pcap_create(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 */ + + 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); +} + +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) { + if (errno == EACCES) + fd = PCAP_ERROR_PERM_DENIED; + else + fd = PCAP_ERROR; + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "(no devices found) %s: %s", + device, pcap_strerror(errno)); + } +#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). + */ + if (v == DLT_EN10MB) { + is_ethernet = 1; + for (i = 0; i < bdlp->bfl_len; i++) { + if (bdlp->bfl_list[i] != DLT_EN10MB) { + 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); + + /* + * 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) { + 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. + */ + close(fd); + return (PCAP_ERROR_IFACE_NOT_UP); + } else { + 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) { @@ -129,7 +707,7 @@ pcap_stats_bpf(pcap_t *p, struct pcap_stat *ps) if (ioctl(p->fd, BIOCGSTATS, (caddr_t)&s) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGSTATS: %s", pcap_strerror(errno)); - return (-1); + return (PCAP_ERROR); } ps->ps_recv = s.bs_recv; @@ -144,12 +722,13 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) int n = 0; register u_char *bp, *ep; u_char *datap; - struct bpf_insn *fcode; #ifdef PCAP_FDDIPAD register int pad; #endif +#ifdef HAVE_ZEROCOPY_BPF + int i; +#endif - fcode = p->md.use_bpf ? NULL : p->fcode.bf_insns; again: /* * Has "pcap_breakloop()" been called? @@ -157,15 +736,36 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 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. + * has, and return PCAP_ERROR_BREAK to indicate + * that we were told to break out of the loop. */ p->break_loop = 0; - return (-2); + return (PCAP_ERROR_BREAK); } cc = p->cc; if (p->cc == 0) { - cc = read(p->fd, (char *)p->buffer, p->bufsize); + /* + * 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) { @@ -180,16 +780,16 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) * * For some unknown reason the uiomove() * operation in the bpf kernel extension - * used to copy the buffer into user + * 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. + * 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 + * 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 @@ -197,8 +797,8 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) * we just ignore EFAULT and keep reading. */ goto again; -#endif - +#endif + case EWOULDBLOCK: return (0); #if defined(sun) && !defined(BSD) @@ -218,7 +818,7 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) } snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read: %s", pcap_strerror(errno)); - return (-1); + return (PCAP_ERROR); } bp = p->buffer; } else @@ -238,16 +838,17 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) /* * 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. + * 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) { if (n == 0) { p->break_loop = 0; - return (-2); + return (PCAP_ERROR_BREAK); } else { p->bp = bp; p->cc = ep - bp; @@ -260,7 +861,8 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) datap = bp + hdrlen; /* * Short-circuit evaluation: if using BPF filter - * in kernel, no need to do it now. + * 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 @@ -270,8 +872,8 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) * skipping that padding. #endif */ - if (fcode == NULL || - bpf_filter(fcode, datap, bhp->bh_datalen, caplen)) { + 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; @@ -349,7 +951,7 @@ pcap_inject_bpf(pcap_t *p, const void *buf, size_t size) (void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: can't turn off BIOCSHDRCMPLT: %s", pcap_strerror(errno)); - return (-1); + return (PCAP_ERROR); } /* @@ -361,13 +963,13 @@ pcap_inject_bpf(pcap_t *p, const void *buf, size_t size) if (ret == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s", pcap_strerror(errno)); - return (-1); + return (PCAP_ERROR); } return (ret); } #ifdef _AIX -static int +static int bpf_odminit(char *errbuf) { char *errstr; @@ -378,7 +980,7 @@ bpf_odminit(char *errbuf) snprintf(errbuf, PCAP_ERRBUF_SIZE, "bpf_load: odm_initialize failed: %s", errstr); - return (-1); + return (PCAP_ERROR); } if ((odmlockid = odm_lock("/etc/objrepos/config_lock", ODM_WAIT)) == -1) { @@ -387,13 +989,13 @@ bpf_odminit(char *errbuf) snprintf(errbuf, PCAP_ERRBUF_SIZE, "bpf_load: odm_lock of /etc/objrepos/config_lock failed: %s", errstr); - return (-1); + return (PCAP_ERROR); } return (0); } -static int +static int bpf_odmcleanup(char *errbuf) { char *errstr; @@ -404,7 +1006,7 @@ bpf_odmcleanup(char *errbuf) snprintf(errbuf, PCAP_ERRBUF_SIZE, "bpf_load: odm_unlock failed: %s", errstr); - return (-1); + return (PCAP_ERROR); } if (odm_terminate() == -1) { @@ -413,7 +1015,7 @@ bpf_odmcleanup(char *errbuf) snprintf(errbuf, PCAP_ERRBUF_SIZE, "bpf_load: odm_terminate failed: %s", errstr); - return (-1); + return (PCAP_ERROR); } return (0); @@ -438,14 +1040,14 @@ bpf_load(char *errbuf) if (bpfloadedflag) return (0); - if (bpf_odminit(errbuf) != 0) - return (-1); + 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)); - return (-1); + return (PCAP_ERROR); } minors = getminor(major, &numminors, BPF_NAME); @@ -455,19 +1057,19 @@ bpf_load(char *errbuf) snprintf(errbuf, PCAP_ERRBUF_SIZE, "bpf_load: genminor failed: %s", pcap_strerror(errno)); - return (-1); + return (PCAP_ERROR); } } - if (bpf_odmcleanup(errbuf)) - return (-1); + 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 (-1); + return (PCAP_ERROR); } if (rc == -1 || getmajor(sbuf.st_rdev) != major) { @@ -478,7 +1080,7 @@ bpf_load(char *errbuf) snprintf(errbuf, PCAP_ERRBUF_SIZE, "bpf_load: can't mknod %s: %s", buf, pcap_strerror(errno)); - return (-1); + return (PCAP_ERROR); } } } @@ -494,7 +1096,7 @@ bpf_load(char *errbuf) snprintf(errbuf, PCAP_ERRBUF_SIZE, "bpf_load: could not load driver: %s", strerror(errno)); - return (-1); + return (PCAP_ERROR); } } @@ -502,190 +1104,507 @@ bpf_load(char *errbuf) cfg_km.cmd = CFG_INIT; cfg_km.kmid = cfg_ld.kmid; cfg_km.mdilen = sizeof(cfg_bpf); - cfg_km.mdiptr = (void *)&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 (-1); + return (PCAP_ERROR); } } - + bpfloadedflag = 1; return (0); } #endif -static inline int -bpf_open(pcap_t *p, char *errbuf) +/* + * Turn off rfmon mode if necessary. + */ +static void +pcap_cleanup_bpf(pcap_t *p) { - int fd; -#ifdef HAVE_CLONING_BPF - static const char device[] = "/dev/bpf"; -#else - int n = 0; - char device[sizeof "/dev/bpf0000000000"]; +#ifdef HAVE_BSD_IEEE80211 + int sock; + struct ifmediareq req; + struct ifreq ifr; #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(errbuf) == -1) - return (-1); -#endif - -#ifdef HAVE_CLONING_BPF - if ((fd = open(device, O_RDWR)) == -1 && - (errno != EACCES || (fd = open(device, O_RDONLY)) == -1)) - snprintf(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++); + if (p->md.must_clear != 0) { /* - * 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. + * There's something we have to do when closing this + * pcap_t. */ - fd = open(device, O_RDWR); - if (fd == -1 && errno == EACCES) - fd = open(device, O_RDONLY); - } while (fd < 0 && errno == EBUSY); +#ifdef HAVE_BSD_IEEE80211 + if (p->md.must_clear & 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_clear = 0; + } + +#ifdef HAVE_ZEROCOPY_BPF /* - * XXX better message for all minors used + * In zero-copy mode, p->buffer is just a pointer into one of the two + * memory-mapped buffers, so no need to free it. */ - if (fd < 0) - snprintf(errbuf, PCAP_ERRBUF_SIZE, "(no devices found) %s: %s", - device, pcap_strerror(errno)); + if (p->md.zerocopy) { + if (p->md.zbuf1 != MAP_FAILED && p->md.zbuf1 != NULL) + munmap(p->md.zbuf1, p->md.zbufsize); + if (p->md.zbuf2 != MAP_FAILED && p->md.zbuf2 != NULL) + munmap(p->md.zbuf2, p->md.zbufsize); + } #endif - - return (fd); + if (p->md.device != NULL) { + free(p->md.device); + p->md.device = NULL; + } + pcap_cleanup_live_common(p); } -/* - * 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 +static int +check_setif_failure(pcap_t *p, int error) +{ +#ifdef __APPLE__ + int fd; + struct ifreq ifr; + int err; #endif -pcap_t * -pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, - char *ebuf) + 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; + strcpy(p->errbuf, ""); + } 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; + strcpy(p->errbuf, ""); + } + return (err); + } +#endif + /* + * No such device. + */ + strcpy(p->errbuf, ""); + 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); + } +} + +static int +pcap_activate_bpf(pcap_t *p) { + int status = 0; int fd; struct ifreq ifr; 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; - pcap_t *p; 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 - p = (pcap_t *)malloc(sizeof(*p)); - if (p == NULL) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", - pcap_strerror(errno)); - return (NULL); - } - memset(p, 0, sizeof(*p)); - fd = bpf_open(p, ebuf); - if (fd < 0) + fd = bpf_open(p); + if (fd < 0) { + status = fd; goto bad; + } p->fd = fd; - p->snapshot = snaplen; if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCVERSION: %s", + 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(ebuf, PCAP_ERRBUF_SIZE, + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "kernel bpf filter out of date"); + status = PCAP_ERROR; + goto bad; + } + + 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 ((ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) || v < 32768) - v = 32768; - 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); + if (uname(&osinfo) == 0) + have_osinfo = 1; - (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); - if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) >= 0) - break; /* that size worked; we're done */ - - if (errno != ENOBUFS) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCSETIF: %s: %s", - device, pcap_strerror(errno)); - goto bad; +#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(ifr.ifr_name, + p->opt.source, + sizeof(ifr.ifr_name)); + if (ioctl(sockfd, SIOCGIFFLAGS, + (char *)&ifr) < 0) { + /* + * We assume this + * failed because + * the underlying + * device doesn't + * exist. + */ + status = PCAP_ERROR_NO_SUCH_DEVICE; + strcpy(p->errbuf, ""); + } 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; + strcpy(p->errbuf, ""); + } + 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; - if (v == 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, - "BIOCSBLEN: %s: No buffer size worked", device); - goto bad; + /* + * Set the cleanup and set/get nonblocking mode ops + * as appropriate for zero-copy mode. + */ + p->cleanup_op = pcap_cleanup_zbuf; + p->setnonblock_op = pcap_setnonblock_zbuf; + p->getnonblock_op = pcap_getnonblock_zbuf; + + /* + * 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 < 32768) + v = 32768; + } +#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)); + 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(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name)); + 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(ifr.ifr_name, p->opt.source, + sizeof(ifr.ifr_name)); + if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) { + status = check_setif_failure(p, errno); + goto bad; + } + } else { + /* + * No buffer size was explicitly specified. + * + * 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. + */ + if ((ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) || + v < 32768) + v = 32768; + 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(ifr.ifr_name, p->opt.source, + sizeof(ifr.ifr_name)); + if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) >= 0) + 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; + } + } } /* Get the data link layer type. */ if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGDLT: %s", + 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. @@ -713,8 +1632,9 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, /* * We don't know what to map this to yet. */ - snprintf(ebuf, PCAP_ERRBUF_SIZE, "unknown interface type %u", + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "unknown interface type %u", v); + status = PCAP_ERROR; goto bad; } #endif @@ -739,13 +1659,6 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, break; } #endif -#ifdef PCAP_FDDIPAD - if (v == DLT_FDDI) - p->fddipad = PCAP_FDDIPAD; - else - p->fddipad = 0; -#endif - p->linktype = v; #ifdef BIOCGDLTLIST /* @@ -753,68 +1666,144 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, * this interface supports. If this fails with EINVAL, it's * not fatal; we just don't get to use the feature later. */ - if (ioctl(fd, BIOCGDLTLIST, (caddr_t)&bdl) == 0) { - u_int i; - int is_ethernet; + 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; - bdl.bfl_list = (u_int *) malloc(sizeof(u_int) * (bdl.bfl_len + 1)); - if (bdl.bfl_list == NULL) { - (void)snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", - pcap_strerror(errno)); - goto bad; +#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; + } + } } - - if (ioctl(fd, BIOCGDLTLIST, (caddr_t)&bdl) < 0) { - (void)snprintf(ebuf, PCAP_ERRBUF_SIZE, - "BIOCGDLTLIST: %s", pcap_strerror(errno)); - free(bdl.bfl_list); + } +#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; } /* - * 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). + * 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. */ - if (p->linktype == DLT_EN10MB) { - is_ethernet = 1; - for (i = 0; i < bdl.bfl_len; i++) { - if (bdl.bfl_list[i] != DLT_EN10MB) { - is_ethernet = 0; - break; + 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; } } - if (is_ethernet) { - /* - * We reserved one more slot at the end of - * the list. - */ - bdl.bfl_list[bdl.bfl_len] = DLT_DOCSIS; - bdl.bfl_len++; - } - } - p->dlt_count = bdl.bfl_len; - p->dlt_list = bdl.bfl_list; - } else { - if (errno != EINVAL) { - (void)snprintf(ebuf, PCAP_ERRBUF_SIZE, - "BIOCGDLTLIST: %s", pcap_strerror(errno)); - goto bad; } } -#endif +#endif /* various platforms */ +#endif /* BIOCGDLTLIST */ /* * If this is an Ethernet device, and we don't have a DLT_ list, @@ -824,7 +1813,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, * some other way of determining whether it's an Ethernet or 802.11 * device.) */ - if (p->linktype == DLT_EN10MB && p->dlt_count == 0) { + 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. @@ -835,7 +1824,14 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, 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 @@ -847,24 +1843,30 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, * BSDs - check CVS log for "bpf.c"? */ if (ioctl(fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1) { - (void)snprintf(ebuf, PCAP_ERRBUF_SIZE, + (void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSHDRCMPLT: %s", pcap_strerror(errno)); + status = PCAP_ERROR; goto bad; } #endif /* set timeout */ - if (to_ms != 0) { +#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.) */ struct timeval to; - to.tv_sec = to_ms / 1000; - to.tv_usec = (to_ms * 1000) % 1000000; + 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(ebuf, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT: %s", + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT: %s", pcap_strerror(errno)); + status = PCAP_ERROR; goto bad; } } @@ -919,38 +1921,48 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, */ v = 1; if (ioctl(p->fd, BIOCIMMEDIATE, &v) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCIMMEDIATE: %s", + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCIMMEDIATE: %s", pcap_strerror(errno)); + status = PCAP_ERROR; goto bad; } #endif /* BIOCIMMEDIATE */ #endif /* _AIX */ - if (promisc) { - /* set promiscuous mode, okay if it fails */ + if (p->opt.promisc) { + /* set promiscuous mode, just warn if it fails */ if (ioctl(p->fd, BIOCPROMISC, NULL) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCPROMISC: %s", + 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(ebuf, PCAP_ERRBUF_SIZE, "BIOCGBLEN: %s", + 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(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", + 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 + /* 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 @@ -964,13 +1976,14 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, total_insn.code = (u_short)(BPF_RET | BPF_K); total_insn.jt = 0; total_insn.jf = 0; - total_insn.k = snaplen; + 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(ebuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s", + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s", pcap_strerror(errno)); + status = PCAP_ERROR; goto bad; } @@ -1011,7 +2024,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, * XXX - what about AIX? */ p->selectable_fd = p->fd; /* assume select() works until we know otherwise */ - if (uname(&osinfo) == 0) { + if (have_osinfo) { /* * We can check what OS this is. */ @@ -1030,15 +2043,12 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; p->stats_op = pcap_stats_bpf; - p->close_op = pcap_close_common; + p->cleanup_op = pcap_cleanup_bpf; - return (p); + return (status); bad: - (void)close(fd); - if (p->dlt_list != NULL) - free(p->dlt_list); - free(p); - return (NULL); + pcap_cleanup_bpf(p); + return (status); } int @@ -1052,24 +2062,313 @@ pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) 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. + */ + if (errno == EINVAL) { + /* + * Interface doesn't support SIOC{G,S}IFMEDIA. + */ + close(sock); + return (PCAP_ERROR_RFMON_NOTSUP); + } + 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_clear |= 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. + */ +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 DLT_EN10MB from the list of DLT_ values, and look for the + * best 802.11 link-layer type in that list and return it. + * Radiotap is better than anything else; 802.11 with any other radio + * header is better than 802.11 with no radio header. + */ +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) { - /* - * It looks that BPF code generated by gen_protochain() is not - * compatible with some of kernel BPF code (for example BSD/OS 3.1). - * Take a safer side for now. - */ - if (no_optimize) { - /* - * 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); - } - /* * Free any user-mode filter we might happen to have installed. */ @@ -1078,20 +2377,51 @@ pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp) /* * Try to install the kernel filter. */ - if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) < 0) { + 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); } - 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). + * install_bpf_program() validates the program. + * + * XXX - what if we already have a filter in the kernel? */ - p->cc = 0; + if (install_bpf_program(p, fp) < 0) + return (-1); + p->md.use_bpf = 0; /* filtering in userland */ return (0); } diff --git a/libpcap/pcap-bpf.h b/libpcap/pcap-bpf.h index aae7b5652..5fe129dbb 100644 --- a/libpcap/pcap-bpf.h +++ b/libpcap/pcap-bpf.h @@ -35,766 +35,13 @@ * 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.50 2007/04/01 21:43:55 guy Exp $ (LBL) + */ + +/* + * For backwards compatibility. * - * @(#) $Header: /tcpdump/master/libpcap/pcap-bpf.h,v 1.34.2.20 2007/07/19 06:20:53 guy Exp $ (LBL) + * Note to OS vendors: do NOT get rid of this file! Some applications + * might expect to be able to include . */ - -/* - * 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. - * - * XXX - should this all just be moved to "pcap.h"? - */ - -#ifndef BPF_MAJOR_VERSION - -#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. - */ -#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)) - -#define BPF_MAXINSNS 512 -#define BPF_MAXBUFSIZE 0x8000 -#define BPF_MINBUFSIZE 32 - -/* - * Structure for "pcap_compile()", "pcap_setfilter()", etc.. - */ -struct bpf_program { - u_int bf_len; - struct bpf_insn *bf_insns; -}; - -/* - * Struct return by BIOCVERSION. This represents the version number of - * the filter language described by the instruction encodings below. - * bpf understands a program iff kernel_major == filter_major && - * kernel_minor >= filter_minor, that is, if the value returned by the - * running kernel has the same major number and a minor number equal - * equal to or less than the filter being downloaded. Otherwise, the - * results are undefined, meaning an error may be returned or packets - * may be accepted haphazardly. - * It has nothing to do with the source code version. - */ -struct bpf_version { - u_short bv_major; - u_short bv_minor; -}; -/* Current version number of filter architecture. */ -#define BPF_MAJOR_VERSION 1 -#define BPF_MINOR_VERSION 1 - -/* - * Data-link level type codes. - * - * Do *NOT* add new values to this list without asking - * "tcpdump-workers@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). - */ - -/* - * 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 /* IEEE 802 Networks */ -#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 is used for DLT_OLD_PFLOG in OpenBSD; - * OBSOLETE: DLT_PFLOG is 117 in OpenBSD now as well. See below. - * 18 is used for DLT_PFSYNC in OpenBSD; don't use it for anything else. - */ - -#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 types corresponding to DLT_ types that differ - * between platforms; don't use those values for new DLT_ new types. - */ - -/* - * This value was defined by libpcap 0.5; platforms that have defined - * 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; DLT_PFLOG is 17 in OpenBSD, but that's DLT_LANE8023 - * in SuSE 6.3, so we can't use 17 for it in capture-file headers. - * - * XXX: is there a conflict with DLT_PFSYNC 18 as well? - */ -#ifdef __OpenBSD__ -#define DLT_OLD_PFLOG 17 -#define DLT_PFSYNC 18 -#endif -#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 - -/* - * Reserved for Siemens HiPath HDLC. - */ -#define DLT_HHDLC 121 - -/* - * 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@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 - -/* - * Reserved for BACnet MS/TP. - */ -#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 . - */ -#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 - - -/* - * 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_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(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 +#include diff --git a/libpcap/pcap-bt-linux.c b/libpcap/pcap-bt-linux.c new file mode 100644 index 000000000..2c619ff9f --- /dev/null +++ b/libpcap/pcap-bt-linux.c @@ -0,0 +1,372 @@ +/* + * 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.9.2.6 2008-07-01 07:06:37 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_setfilter_linux(pcap_t *, struct bpf_program *); +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) +{ + 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 %d:%s", + errno, 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 %d:%s", + errno, 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) +{ + pcap_t *p; + + 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 = bt_setfilter_linux; + 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 %d:%s", + errno, 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 %d:%s", + errno, 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 %d:%s", + errno, 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 %d:%s", + errno, strerror(errno)); + goto close_fail; + } + + + /* Bind socket to the HCI device */ + addr.hci_family = AF_BLUETOOTH; + addr.hci_dev = 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)); + 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; + 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 { + 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; + } + + /* get direction and timestamp*/ + cmsg = CMSG_FIRSTHDR(&msg); + int in=0; + while (cmsg) { + switch (cmsg->cmsg_type) { + case HCI_CMSG_DIR: + in = *((int *) CMSG_DATA(cmsg)); + break; + case HCI_CMSG_TSTAMP: + pkth.ts = *((struct timeval *) CMSG_DATA(cmsg)); + 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; + callback(user, &pkth, &handle->buffer[handle->offset]); + return 1; +} + +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; + + /* ingnore 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 get stats" + " via ioctl %d:%s", errno, 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_setfilter_linux(pcap_t *p, struct bpf_program *fp) +{ + return 0; +} + + +static int +bt_setdirection_linux(pcap_t *p, pcap_direction_t d) +{ + p->direction = d; + return 0; +} diff --git a/libpcap/pcap-bt-linux.h b/libpcap/pcap-bt-linux.h new file mode 100644 index 000000000..87d22a6e1 --- /dev/null +++ b/libpcap/pcap-bt-linux.h @@ -0,0 +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.4.2.1 2008-04-04 19:39:05 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); diff --git a/libpcap/pcap-config.1 b/libpcap/pcap-config.1 new file mode 100644 index 000000000..a99b37912 --- /dev/null +++ b/libpcap/pcap-config.1 @@ -0,0 +1,54 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap-config.1,v 1.1.2.2 2008-09-23 18:06: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-CONFIG 1 "23 September 2008" +.SH NAME +pcap-config \- write libpcap compiler and linker flags to standard output +.SH SYNOPSIS +.na +.B pcap-config +[ +.B \-\-cflags | \-\-libs +] +.ad +.SH DESCRIPTION +.LP +When run with the +.B \-\-cflags +option, +.I pcap-config +writes to the standard output the +.B \-I +compiler flags required to include libpcap's header files. +When run with the +.B \-\-libs +option, +.I pcap-config +writes to the standard output the +.B \-L +and +.B \-l +linker required to link with libpcap, including +.B \-l +flags for libraries required by libpcap. +.SH "SEE ALSO" +pcap(3PCAP) diff --git a/libpcap/pcap-config.in b/libpcap/pcap-config.in new file mode 100644 index 000000000..19f21141d --- /dev/null +++ b/libpcap/pcap-config.in @@ -0,0 +1,16 @@ +#! /bin/sh + +# +# Script to give the appropriate compiler flags and linker flags +# to use when building code that uses libpcap. +# +case "$1" in + +--cflags) + echo "-I @includedir@" + ;; + +--libs) + echo "-L @libdir@ -lpcap @DEPLIBS@" + ;; +esac diff --git a/libpcap/pcap-dag.c b/libpcap/pcap-dag.c index 3ef250843..039d92601 100644 --- a/libpcap/pcap-dag.c +++ b/libpcap/pcap-dag.c @@ -17,7 +17,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.21.2.7 2007/06/22 06:43:58 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.31.2.8 2008-04-14 20:41:51 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -46,6 +46,8 @@ struct rtentry; /* declarations in */ #include "dagnew.h" #include "dagapi.h" +#include "pcap-dag.h" + #define ATM_CELL_SIZE 52 #define ATM_HDR_SIZE 4 @@ -83,10 +85,9 @@ static const unsigned short endian_test_word = 0x0100; #ifdef DAG_ONLY /* This code is required when compiling for a DAG device only. */ -#include "pcap-dag.h" /* Replace dag function names with pcap equivalent. */ -#define dag_open_live pcap_open_live +#define dag_create pcap_create #define dag_platform_finddevs pcap_platform_finddevs #endif /* DAG_ONLY */ @@ -124,7 +125,7 @@ delete_pcap_dag(pcap_t *p) */ static void -dag_platform_close(pcap_t *p) +dag_platform_cleanup(pcap_t *p) { if (p != NULL) { @@ -138,10 +139,14 @@ dag_platform_close(pcap_t *p) if(dag_stop(p->fd) < 0) fprintf(stderr,"dag_stop: %s\n", strerror(errno)); #endif /* HAVE_DAG_STREAMS_API */ - if(dag_close(p->fd) < 0) - fprintf(stderr,"dag_close: %s\n", strerror(errno)); + 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); } - delete_pcap_dag(p); /* Note: don't need to call close(p->fd) here as dag_close(p->fd) does this. */ } @@ -150,7 +155,7 @@ atexit_handler(void) { while (pcap_dags != NULL) { if (pcap_dags->pid == getpid()) { - dag_platform_close(pcap_dags->p); + dag_platform_cleanup(pcap_dags->p); } else { delete_pcap_dag(pcap_dags->p); } @@ -180,6 +185,38 @@ new_pcap_dag(pcap_t *p) 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 @@ -191,6 +228,7 @@ 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) { @@ -220,7 +258,9 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) * If non-block is specified it will return immediately. The user * is then responsible for efficiency. */ - p->md.dag_mem_top = dag_advance_stream(p->fd, p->md.dag_stream, &(p->md.dag_mem_bottom)); + 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); @@ -244,18 +284,18 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) /* 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; + u_char *dp = ((u_char *)header); /* + dag_record_size; */ unsigned short rlen; /* @@ -279,146 +319,17 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) } p->md.dag_mem_bottom += rlen; - switch(header->type) { - case TYPE_ATM: -#ifdef TYPE_AAL5 - case TYPE_AAL5: - if (header->type == TYPE_AAL5) { - packet_len = ntohs(header->wlen); - caplen = rlen - dag_record_size; - } -#endif -#ifdef TYPE_MC_ATM - case TYPE_MC_ATM: - if (header->type == TYPE_MC_ATM) { - caplen = packet_len = ATM_CELL_SIZE; - dp+=4; - } -#endif -#ifdef TYPE_MC_AAL5 - case TYPE_MC_AAL5: - if (header->type == TYPE_MC_AAL5) { - packet_len = ntohs(header->wlen); - caplen = rlen - dag_record_size - 4; - dp+=4; - } -#endif - 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; - -#ifdef TYPE_DSM_COLOR_ETH - case TYPE_DSM_COLOR_ETH: -#endif -#ifdef TYPE_COLOR_ETH - case TYPE_COLOR_ETH: -#endif - 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; -#ifdef TYPE_DSM_COLOR_HDLC_POS - case TYPE_DSM_COLOR_HDLC_POS: -#endif -#ifdef TYPE_COLOR_HDLC_POS - case TYPE_COLOR_HDLC_POS: -#endif - 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; -#ifdef TYPE_COLOR_MC_HDLC_POS - case TYPE_COLOR_MC_HDLC_POS: -#endif -#ifdef TYPE_MC_HDLC - 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; - 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; - } - break; -#endif - default: - /* Unhandled ERF type. - * Ignore rather than generating error - */ - continue; - } - - if (caplen > p->snapshot) - caplen = p->snapshot; - /* Count lost packets. */ - switch(header->type) { -#ifdef TYPE_COLOR_HDLC_POS - /* in this type the color value overwrites the lctr */ + switch((header->type & 0x7f)) { + /* in these types the color value overwrites the lctr */ case TYPE_COLOR_HDLC_POS: - break; -#endif -#ifdef TYPE_COLOR_ETH - /* in this type the color value overwrites the lctr */ case TYPE_COLOR_ETH: - break; -#endif -#ifdef TYPE_DSM_COLOR_HDLC_POS - /* in this type the color value overwrites the lctr */ case TYPE_DSM_COLOR_HDLC_POS: - break; -#endif -#ifdef TYPE_DSM_COLOR_ETH - /* in this type the color value overwrites the lctr */ case TYPE_DSM_COLOR_ETH: - break; -#endif -#ifdef TYPE_COLOR_MC_HDLC_POS case TYPE_COLOR_MC_HDLC_POS: + case TYPE_COLOR_HASH_ETH: + case TYPE_COLOR_HASH_POS: break; -#endif default: if (header->lctr) { @@ -429,10 +340,178 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) } } } + + 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: + 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: + packet_len = ntohs(header->wlen); + caplen = rlen - dag_record_size; + if (caplen > packet_len) { + caplen = packet_len; + } + break; + + 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; @@ -463,7 +542,7 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) /* Only count packets that pass the filter, for consistency with standard Linux behaviour. */ processed++; - if (processed == cnt) + if (processed == cnt && cnt > 0) { /* Reached the user-specified limit. */ return cnt; @@ -485,23 +564,24 @@ dag_inject(pcap_t *p, const void *buf _U_, size_t size _U_) /* * 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 also ignored as it is - * not supported in hardware. + * 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_open_live(). + * slen with approprite DAG tool BEFORE pcap_activate(). * * See also pcap(3). */ -pcap_t * -dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf) +static int dag_activate(pcap_t* handle) { +#if 0 char conf[30]; /* dag configure string */ - pcap_t *handle; +#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; @@ -509,44 +589,35 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu #endif if (device == NULL) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "device is NULL: %s", pcap_strerror(errno)); - return NULL; + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "device is NULL: %s", pcap_strerror(errno)); + return -1; } - /* Allocate a handle for this session. */ - handle = malloc(sizeof(*handle)); - if (handle == NULL) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc %s: %s", device, pcap_strerror(errno)); - return NULL; - } - /* Initialize some components of the pcap structure. */ - - memset(handle, 0, sizeof(*handle)); #ifdef HAVE_DAG_STREAMS_API newDev = (char *)malloc(strlen(device) + 16); if (newDev == NULL) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s\n", pcap_strerror(errno)); + 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(ebuf, PCAP_ERRBUF_SIZE, "dag_parse_name: %s\n", pcap_strerror(errno)); + 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(ebuf, PCAP_ERRBUF_SIZE, "dag_parse_name: tx (even numbered) streams not supported for capture\n"); + 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(ebuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s\n", pcap_strerror(errno)); + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s\n", pcap_strerror(errno)); goto fail; } strcpy(newDev, "/dev/"); @@ -557,14 +628,14 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu /* setup device parameters */ if((handle->fd = dag_open((char *)device)) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_open %s: %s", device, pcap_strerror(errno)); + 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(ebuf, PCAP_ERRBUF_SIZE, "dag_attach_stream: %s\n", pcap_strerror(errno)); + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_attach_stream: %s\n", pcap_strerror(errno)); goto failclose; } @@ -573,7 +644,7 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu */ if (dag_get_stream_poll(handle->fd, handle->md.dag_stream, &mindata, &maxwait, &poll) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno)); + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno)); goto faildetach; } @@ -583,21 +654,21 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu */ mindata = 65536; - /* Obey to_ms if supplied. This is a good idea! + /* 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 = to_ms/1000; - maxwait.tv_usec = (to_ms%1000) * 1000; + 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(ebuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno)); + 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(ebuf, PCAP_ERRBUF_SIZE,"dag_mmap %s: %s\n", device, pcap_strerror(errno)); + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,"dag_mmap %s: %s\n", device, pcap_strerror(errno)); goto failclose; } @@ -611,28 +682,28 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu /* 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 (snaplen == 0 || snaplen > MAX_DAG_SNAPLEN) { - snaplen = MAX_DAG_SNAPLEN; + if (handle->snapshot == 0 || handle->snapshot > MAX_DAG_SNAPLEN) { + handle->snapshot = MAX_DAG_SNAPLEN; } else if (snaplen < MIN_DAG_SNAPLEN) { - 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(ebuf, PCAP_ERRBUF_SIZE,"dag_configure %s: %s\n", device, pcap_strerror(errno)); + 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(ebuf, PCAP_ERRBUF_SIZE, "dag_start_stream %s: %s\n", device, pcap_strerror(errno)); + 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(ebuf, PCAP_ERRBUF_SIZE, "dag_start %s: %s\n", device, pcap_strerror(errno)); + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_start %s: %s\n", device, pcap_strerror(errno)); goto failclose; } #endif /* HAVE_DAG_STREAMS_API */ @@ -644,40 +715,58 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu */ handle->md.dag_mem_bottom = 0; handle->md.dag_mem_top = 0; - handle->md.dag_fcs_bits = 32; - /* Query the card first for special cases. */ + /* + * 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)) - { + if ((0x4200 == daginf->device_code) || (0x4230 == daginf->device_code)) { /* DAG 4.2S and 4.23S already strip the FCS. Stripping the final word again truncates the packet. */ handle->md.dag_fcs_bits = 0; - } - /* Then allow an environment variable to override. */ - if ((s = getenv("ERF_FCS_BITS")) != NULL) { - if ((n = atoi(s)) == 0 || n == 16|| n == 32) { - handle->md.dag_fcs_bits = n; - } else { - snprintf(ebuf, PCAP_ERRBUF_SIZE, - "pcap_open_live %s: bad ERF_FCS_BITS value (%d) in environment\n", device, n); - goto failstop; + /* 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->snapshot = snaplen; - handle->md.dag_timeout = to_ms; + handle->md.dag_timeout = handle->md.timeout; handle->linktype = -1; - if (dag_get_datalink(handle) < 0) { - strcpy(ebuf, handle->errbuf); + if (dag_get_datalink(handle) < 0) goto failstop; - } handle->bufsize = 0; if (new_pcap_dag(handle) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "new_pcap_dag %s: %s\n", device, pcap_strerror(errno)); + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "new_pcap_dag %s: %s\n", device, pcap_strerror(errno)); goto failstop; } @@ -698,54 +787,50 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu handle->getnonblock_op = pcap_getnonblock_fd; handle->setnonblock_op = dag_setnonblock; handle->stats_op = dag_stats; - handle->close_op = dag_platform_close; + handle->cleanup_op = dag_platform_cleanup; handle->md.stat.ps_drop = 0; handle->md.stat.ps_recv = 0; - return handle; + return 0; #ifdef HAVE_DAG_STREAMS_API failstop: - if (handle != NULL) { - if (dag_stop_stream(handle->fd, handle->md.dag_stream) < 0) - fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno)); + if (dag_stop_stream(handle->fd, handle->md.dag_stream) < 0) { + fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno)); } faildetach: - if (handle != NULL) { - if (dag_detach_stream(handle->fd, handle->md.dag_stream) < 0) - fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno)); - } -#else + if (dag_detach_stream(handle->fd, handle->md.dag_stream) < 0) + fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno)); +#else failstop: - if (handle != NULL) { - if (dag_stop(p->fd) < 0) - fprintf(stderr,"dag_stop: %s\n", strerror(errno)); - } + if (dag_stop(handle->fd) < 0) + fprintf(stderr,"dag_stop: %s\n", strerror(errno)); #endif /* HAVE_DAG_STREAMS_API */ failclose: - if (handle != NULL) { - if (dag_close(handle->fd) < 0) - fprintf(stderr,"dag_close: %s\n", strerror(errno)); - } - if (handle != NULL) - delete_pcap_dag(handle); - + 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); } - if (handle != NULL) { - /* - * Get rid of any link-layer type list we allocated. - */ - if (handle->dlt_list != NULL) { - free(handle->dlt_list); - } - free(handle); - } - return NULL; + return PCAP_ERROR; +} + +pcap_t *dag_create(const char *device, char *ebuf) +{ + pcap_t *p; + + p = pcap_create_common(device, ebuf); + if (p == NULL) + return NULL; + + p->activate_op = dag_activate; + return p; } static int @@ -762,10 +847,13 @@ dag_stats(pcap_t *p, struct pcap_stat *ps) { } /* - * Simply submit all possible dag names as candidates. - * pcap_add_if() internally tests each candidate with pcap_open_live(), - * so any non-existent devices are dropped. - * For 2.5 try all rx stream names as well. + * 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) @@ -773,30 +861,46 @@ dag_platform_finddevs(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-9 */ for (c = 0; c < 9; c++) { snprintf(name, 12, "dag%d", c); - if (pcap_add_if(devlistp, name, 0, NULL, errbuf) == -1) { - /* - * Failure. - */ - ret = -1; - } -#ifdef HAVE_DAG_STREAMS_API + if (-1 == dag_parse_name(name, dagname, DAGNAME_BUFSIZE, &dagstream)) { - int stream; - for(stream=0;stream<16;stream+=2) { - snprintf(name, 10, "dag%d:%d", c, stream); - if (pcap_add_if(devlistp, name, 0, NULL, errbuf) == -1) { - /* - * Failure. - */ - ret = -1; - } - } + 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;stream<16;stream+=2) { + if (0 == dag_attach_stream(dagfd, stream, 0, 0)) { + dag_detach_stream(dagfd, stream); + + snprintf(name, 10, "dag%d:%d", c, stream); + if (pcap_add_if(devlistp, name, 0, NULL, errbuf) == -1) { + /* + * Failure. + */ + ret = -1; + } + } + } + } #endif /* HAVE_DAG_STREAMS_API */ + dag_close(dagfd); + } + } return (ret); } @@ -885,7 +989,7 @@ dag_setnonblock(pcap_t *p, int nonblock, char *errbuf) static int dag_get_datalink(pcap_t *p) { - int index=0; + int index=0, dlt_index=0; uint8_t types[255]; memset(types, 0, 255); @@ -897,7 +1001,16 @@ dag_get_datalink(pcap_t *p) p->linktype = 0; -#ifdef HAVE_DAG_GET_ERF_TYPES +#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)); @@ -911,31 +1024,26 @@ dag_get_datalink(pcap_t *p) { #endif - switch(types[index]) { + switch((types[index] & 0x7f)) { case TYPE_HDLC_POS: -#ifdef TYPE_COLOR_HDLC_POS case TYPE_COLOR_HDLC_POS: -#endif -#ifdef TYPE_DSM_COLOR_HDLC_POS case TYPE_DSM_COLOR_HDLC_POS: -#endif + case TYPE_COLOR_HASH_POS: + if (p->dlt_list != NULL) { - p->dlt_list[index++] = DLT_CHDLC; - p->dlt_list[index++] = DLT_PPP_SERIAL; - p->dlt_list[index++] = DLT_FRELAY; + 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: -#ifdef TYPE_COLOR_ETH case TYPE_COLOR_ETH: -#endif -#ifdef TYPE_DSM_COLOR_ETH case TYPE_DSM_COLOR_ETH: -#endif + 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 @@ -947,61 +1055,66 @@ dag_get_datalink(pcap_t *p) * Ethernet framing). */ if (p->dlt_list != NULL) { - p->dlt_list[index++] = DLT_EN10MB; - p->dlt_list[index++] = DLT_DOCSIS; + 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: -#ifdef TYPE_AAL5 case TYPE_AAL5: -#endif -#ifdef TYPE_MC_ATM case TYPE_MC_ATM: -#endif -#ifdef TYPE_MC_AAL5 case TYPE_MC_AAL5: -#endif if (p->dlt_list != NULL) { - p->dlt_list[index++] = DLT_ATM_RFC1483; - p->dlt_list[index++] = DLT_SUNATM; + p->dlt_list[dlt_index++] = DLT_ATM_RFC1483; + p->dlt_list[dlt_index++] = DLT_SUNATM; } if(!p->linktype) p->linktype = DLT_ATM_RFC1483; break; -#ifdef TYPE_COLOR_MC_HDLC_POS case TYPE_COLOR_MC_HDLC_POS: -#endif -#ifdef TYPE_MC_HDLC case TYPE_MC_HDLC: if (p->dlt_list != NULL) { - p->dlt_list[index++] = DLT_CHDLC; - p->dlt_list[index++] = DLT_PPP_SERIAL; - p->dlt_list[index++] = DLT_FRELAY; - p->dlt_list[index++] = DLT_MTP2; - p->dlt_list[index++] = DLT_MTP2_WITH_PHDR; + 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; -#endif - case TYPE_LEGACY: + case TYPE_IPV4: if(!p->linktype) - p->linktype = DLT_NULL; + 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_IPV6: default: - snprintf(p->errbuf, sizeof(p->errbuf), "unknown DAG linktype %d", types[index]); - return (-1); + /* Libpcap cannot deal with these types yet */ + /* Add no DLTs, but still covered by DLT_ERF */ + break; } /* switch */ + index++; } - p->dlt_count = index; + p->dlt_list[dlt_index++] = DLT_ERF; + + p->dlt_count = dlt_index; + + if(!p->linktype) + p->linktype = DLT_ERF; return p->linktype; } diff --git a/libpcap/pcap-dag.h b/libpcap/pcap-dag.h index eff01d666..7ba272bec 100644 --- a/libpcap/pcap-dag.h +++ b/libpcap/pcap-dag.h @@ -7,8 +7,94 @@ * * Author: Richard Littin, Sean Irvine ({richard,sean}@reeltwo.com) * - * @(#) $Header: /tcpdump/master/libpcap/pcap-dag.h,v 1.3.4.1 2005/07/07 06:56:04 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/pcap-dag.h,v 1.4.2.3 2008-04-04 19:39:06 guy Exp $ (LBL) */ -pcap_t *dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf); +pcap_t *dag_create(const char *, char *); int dag_platform_finddevs(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_PAD +#define TYPE_PAD 48 +#endif diff --git a/libpcap/pcap-dlpi.c b/libpcap/pcap-dlpi.c index c29532a32..695e48ad3 100644 --- a/libpcap/pcap-dlpi.c +++ b/libpcap/pcap-dlpi.c @@ -22,7 +22,7 @@ * University College London, and subsequently modified by * Guy Harris (guy@alum.mit.edu), Mark Pizzolato * , - * and Mark C. Brown (mbrown@hp.com). + * Mark C. Brown (mbrown@hp.com), and Sagun Shakya . */ /* @@ -70,7 +70,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.108.2.7 2006/04/04 05:33:02 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.116.2.11 2008-04-14 20:41:51 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -121,6 +121,7 @@ static const char rcsid[] _U_ = #endif #include "pcap-int.h" +#include "dlpisubs.h" #ifdef HAVE_OS_PROTO_H #include "os-proto.h" @@ -136,33 +137,6 @@ static const char rcsid[] _U_ = #define MAXDLBUF 8192 -#ifdef HAVE_SYS_BUFMOD_H - -/* - * Size of a bufmod chunk to pass upstream; that appears to be the biggest - * value to which you can set it, and setting it to that value (which - * is bigger than what appears to be the Solaris default of 8192) - * reduces the number of packet drops. - */ -#define CHUNKSIZE 65536 - -/* - * Size of the buffer to allocate for packet data we read; it must be - * large enough to hold a chunk. - */ -#define PKTBUFSIZE CHUNKSIZE - -#else /* HAVE_SYS_BUFMOD_H */ - -/* - * Size of the buffer to allocate for packet data we read; this is - * what the value used to be - there's no particular reason why it - * should be tied to MAXDLBUF, but we'll leave it as this for now. - */ -#define PKTBUFSIZE (MAXDLBUF * sizeof(bpf_u_int32)) - -#endif - /* Forwards */ static char *split_dname(char *, int *, char *); static int dl_doattach(int, int, char *); @@ -176,6 +150,11 @@ static int dlpromisconreq(int, bpf_u_int32, char *); static int dlokack(int, const char *, char *, char *); static int dlinforeq(int, char *); static int dlinfoack(int, char *, char *); + +#ifdef HAVE_DLPI_PASSIVE +static void dlpassive(int, char *); +#endif + #ifdef DL_HP_RAWDLS static int dlrawdatareq(int, const u_char *, int); #endif @@ -186,9 +165,6 @@ static char *dlprim(bpf_u_int32); 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_SYS_BUFMOD_H -static int strioctl(int, int, int, char *); -#endif #ifdef HAVE_HPUX9 static int dlpi_kread(int, off_t, void *, u_int, char *); #endif @@ -196,42 +172,6 @@ static int dlpi_kread(int, off_t, void *, u_int, char *); static int get_dlpi_ppa(int, const char *, int, char *); #endif -static int -pcap_stats_dlpi(pcap_t *p, struct pcap_stat *ps) -{ - - /* - * "ps_recv" counts packets handed to the filter, not packets - * that passed the filter. As filtering is done in userland, - * this would not include packets dropped because we ran out - * of buffer space; in order to make this more like other - * platforms (Linux 2.4 and later, BSDs with BPF), where the - * "packets received" count includes packets received but dropped - * due to running out of buffer space, and to keep from confusing - * applications that, for example, compute packet drop percentages, - * we also make it count packets dropped by "bufmod" (otherwise we - * might run the risk of the packet drop count being bigger than - * the received-packet count). - * - * "ps_drop" counts packets dropped by "bufmod" because of - * flow control requirements or resource exhaustion; it doesn't - * count packets dropped by the interface driver, or packets - * dropped upstream. As filtering is done in userland, it counts - * packets regardless of whether they would've passed the filter. - * - * These statistics don't include packets not yet read from - * the kernel by libpcap, but they may include packets not - * yet read from libpcap by the application. - */ - *ps = p->md.stat; - - /* - * Add in the drop count, as per the above comment. - */ - ps->ps_recv += ps->ps_drop; - return (0); -} - /* XXX Needed by HP-UX (at least) */ static bpf_u_int32 ctlbuf[MAXDLBUF]; static struct strbuf ctl = { @@ -243,18 +183,10 @@ static struct strbuf ctl = { static int pcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { - register int cc, n, caplen, origlen; - register u_char *bp, *ep, *pk; - register struct bpf_insn *fcode; -#ifdef HAVE_SYS_BUFMOD_H - register struct sb_hdr *sbp; -#ifdef LBL_ALIGN - struct sb_hdr sbhdr; -#endif -#endif + int cc; + u_char *bp; int flags; struct strbuf data; - struct pcap_pkthdr pkthdr; flags = 0; cc = p->cc; @@ -302,74 +234,7 @@ pcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user) } else bp = p->bp; - /* Loop through packets */ - fcode = p->fcode.bf_insns; - ep = bp + cc; - n = 0; -#ifdef HAVE_SYS_BUFMOD_H - 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); - } - } -#ifdef LBL_ALIGN - if ((long)bp & 3) { - sbp = &sbhdr; - memcpy(sbp, bp, sizeof(*sbp)); - } else -#endif - sbp = (struct sb_hdr *)bp; - p->md.stat.ps_drop = sbp->sbh_drops; - pk = bp + sizeof(*sbp); - bp += sbp->sbh_totlen; - origlen = sbp->sbh_origlen; - caplen = sbp->sbh_msglen; -#else - origlen = cc; - caplen = min(p->snapshot, cc); - pk = bp; - bp += caplen; -#endif - ++p->md.stat.ps_recv; - if (bpf_filter(fcode, pk, origlen, caplen)) { -#ifdef HAVE_SYS_BUFMOD_H - pkthdr.ts.tv_sec = sbp->sbh_timestamp.tv_sec; - pkthdr.ts.tv_usec = sbp->sbh_timestamp.tv_usec; -#else - (void)gettimeofday(&pkthdr.ts, NULL); -#endif - pkthdr.len = origlen; - pkthdr.caplen = caplen; - /* Insure caplen does not exceed snapshot */ - if (pkthdr.caplen > p->snapshot) - pkthdr.caplen = p->snapshot; - (*callback)(user, &pkthdr, pk); - if (++n >= cnt && cnt >= 0) { - p->cc = ep - bp; - p->bp = bp; - return (n); - } - } -#ifdef HAVE_SYS_BUFMOD_H - } -#endif - p->cc = 0; - return (n); + return (pcap_process_pkts(p, callback, user, cnt, bp, cc)); } static int @@ -449,26 +314,26 @@ pcap_inject_dlpi(pcap_t *p, const void *buf, size_t size) #endif /* HAVE_SOLARIS */ static void -pcap_close_dlpi(pcap_t *p) +pcap_cleanup_dlpi(pcap_t *p) { - pcap_close_common(p); - if (p->send_fd >= 0) + if (p->send_fd >= 0) { close(p->send_fd); + p->send_fd = -1; + } + pcap_cleanup_live_common(p); } -pcap_t * -pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, - char *ebuf) +static int +pcap_activate_dlpi(pcap_t *p) { register char *cp; - register pcap_t *p; int ppa; #ifdef HAVE_SOLARIS int isatm = 0; #endif register dl_info_ack_t *infop; #ifdef HAVE_SYS_BUFMOD_H - bpf_u_int32 ss, chunksize; + bpf_u_int32 ss; #ifdef HAVE_SOLARIS register char *release; bpf_u_int32 osmajor, osminor, osmicro; @@ -479,23 +344,15 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, #ifndef HAVE_DEV_DLPI char dname2[100]; #endif - - p = (pcap_t *)malloc(sizeof(*p)); - if (p == NULL) { - strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); - return (NULL); - } - memset(p, 0, sizeof(*p)); - p->fd = -1; /* indicate that it hasn't been opened yet */ - p->send_fd = -1; + int status = PCAP_ERROR; #ifdef HAVE_DEV_DLPI /* ** Remove any "/dev/" on the front of the device. */ - cp = strrchr(device, '/'); + cp = strrchr(p->opt.source, '/'); if (cp == NULL) - strlcpy(dname, device, sizeof(dname)); + strlcpy(dname, p->opt.source, sizeof(dname)); else strlcpy(dname, cp + 1, sizeof(dname)); @@ -503,9 +360,11 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, * 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, ebuf); - if (cp == NULL) + cp = split_dname(dname, &ppa, p->errbuf); + if (cp == NULL) { + status = PCAP_ERROR_NO_SUCH_DEVICE; goto bad; + } *cp = '\0'; /* @@ -521,7 +380,9 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, */ cp = "/dev/dlpi"; if ((p->fd = open(cp, O_RDWR)) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, + if (errno == EPERM || errno == EACCES) + status = PCAP_ERROR_PERM_DENIED; + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", cp, pcap_strerror(errno)); goto bad; } @@ -545,9 +406,11 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, * 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, ebuf); - if (ppa < 0) + 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 @@ -555,19 +418,21 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, * otherwise, concatenate the device directory name and the * device name. */ - if (*device == '/') - strlcpy(dname, device, sizeof(dname)); + if (*p->opt.source == '/') + strlcpy(dname, p->opt.source, sizeof(dname)); else snprintf(dname, sizeof(dname), "%s/%s", PCAP_DEV_PREFIX, - device); + p->opt.source); /* * Get the unit number, and a pointer to the end of the device * type name. */ - cp = split_dname(dname, &ppa, ebuf); - if (cp == NULL) + 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 @@ -579,7 +444,9 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, /* Try device without unit number */ if ((p->fd = open(dname, O_RDWR)) < 0) { if (errno != ENOENT) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s", dname, + if (errno == EACCES) + status = PCAP_ERROR_PERM_DENIED; + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", dname, pcap_strerror(errno)); goto bad; } @@ -587,10 +454,18 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, /* Try again with unit number */ if ((p->fd = open(dname2, O_RDWR)) < 0) { if (errno == ENOENT) { + status = PCAP_ERROR_NO_SUCH_DEVICE; + /* - * We just report "No DLPI device found" - * with the device name, so people don't - * get confused and think, for example, + * 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 @@ -602,10 +477,12 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, * for the loopback interface is just a * symptom of that inability. */ - snprintf(ebuf, PCAP_ERRBUF_SIZE, - "%s: No DLPI device found", device); + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "%s: No DLPI device found", p->opt.source); } else { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s", + if (errno == EACCES) + status = PCAP_ERROR_PERM_DENIED; + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", dname2, pcap_strerror(errno)); } goto bad; @@ -615,13 +492,11 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, } #endif - p->snapshot = snaplen; - /* ** Attach if "style 2" provider */ - if (dlinforeq(p->fd, ebuf) < 0 || - dlinfoack(p->fd, (char *)buf, ebuf) < 0) + if (dlinforeq(p->fd, p->errbuf) < 0 || + dlinfoack(p->fd, (char *)buf, p->errbuf) < 0) goto bad; infop = &((union DL_primitives *)buf)->info_ack; #ifdef HAVE_SOLARIS @@ -629,16 +504,33 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, isatm = 1; #endif if (infop->dl_provider_style == DL_STYLE2) { - if (dl_doattach(p->fd, ppa, ebuf) < 0) + 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, ebuf) < 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) @@ -663,15 +555,15 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, ** assume the SAP value in a DLPI bind is an LLC SAP for network ** types that use 802.2 LLC). */ - if ((dlbindreq(p->fd, 1537, ebuf) < 0 && - dlbindreq(p->fd, 2, ebuf) < 0) || - dlbindack(p->fd, (char *)buf, ebuf, NULL) < 0) + 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, ebuf) < 0) + if (dl_dohpuxbind(p->fd, p->errbuf) < 0) goto bad; if (p->send_fd >= 0) { /* @@ -679,7 +571,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, ** set it to -1, so that you can't send but can ** still receive? */ - if (dl_dohpuxbind(p->send_fd, ebuf) < 0) + if (dl_dohpuxbind(p->send_fd, p->errbuf) < 0) goto bad; } #else /* neither AIX nor HP-UX */ @@ -687,8 +579,8 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, ** Not Sinix, and neither AIX nor HP-UX - Solaris, and any other ** OS using DLPI. **/ - if (dlbindreq(p->fd, 0, ebuf) < 0 || - dlbindack(p->fd, (char *)buf, ebuf, NULL) < 0) + 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 */ @@ -702,18 +594,18 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, ** help, and may break things. */ if (strioctl(p->fd, A_PROMISCON_REQ, 0, NULL) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "A_PROMISCON_REQ: %s", - pcap_strerror(errno)); + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "A_PROMISCON_REQ: %s", pcap_strerror(errno)); goto bad; } } else #endif - if (promisc) { + if (p->opt.promisc) { /* ** Enable promiscuous (not necessary on send FD) */ - if (dlpromisconreq(p->fd, DL_PROMISC_PHYS, ebuf) < 0 || - dlokack(p->fd, "promisc_phys", (char *)buf, ebuf) < 0) + if (dlpromisconreq(p->fd, DL_PROMISC_PHYS, p->errbuf) < 0 || + dlokack(p->fd, "promisc_phys", (char *)buf, p->errbuf) < 0) goto bad; /* @@ -722,10 +614,9 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, ** HP-UX or SINIX) (Not necessary on send FD) */ #if !defined(__hpux) && !defined(sinix) - if (dlpromisconreq(p->fd, DL_PROMISC_MULTI, ebuf) < 0 || - dlokack(p->fd, "promisc_multi", (char *)buf, ebuf) < 0) - fprintf(stderr, - "WARNING: DL_PROMISC_MULTI failed (%s)\n", ebuf); + if (dlpromisconreq(p->fd, DL_PROMISC_MULTI, p->errbuf) < 0 || + dlokack(p->fd, "promisc_multi", (char *)buf, p->errbuf) < 0) + status = PCAP_WARNING; #endif } /* @@ -736,17 +627,16 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, #ifndef sinix if ( #ifdef __hpux - !promisc && + !p->opt.promisc && #endif #ifdef HAVE_SOLARIS !isatm && #endif - (dlpromisconreq(p->fd, DL_PROMISC_SAP, ebuf) < 0 || - dlokack(p->fd, "promisc_sap", (char *)buf, ebuf) < 0)) { + (dlpromisconreq(p->fd, DL_PROMISC_SAP, p->errbuf) < 0 || + dlokack(p->fd, "promisc_sap", (char *)buf, p->errbuf) < 0)) { /* Not fatal if promisc since the DL_PROMISC_PHYS worked */ - if (promisc) - fprintf(stderr, - "WARNING: DL_PROMISC_SAP failed (%s)\n", ebuf); + if (p->opt.promisc) + status = PCAP_WARNING; else goto bad; } @@ -757,7 +647,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, ** promiscuous options. */ #if defined(HAVE_HPUX9) || defined(HAVE_HPUX10_20_OR_LATER) - if (dl_dohpuxbind(p->fd, ebuf) < 0) + if (dl_dohpuxbind(p->fd, p->errbuf) < 0) goto bad; /* ** We don't set promiscuous mode on the send FD, but we'll defer @@ -770,7 +660,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, ** set it to -1, so that you can't send but can ** still receive? */ - if (dl_dohpuxbind(p->send_fd, ebuf) < 0) + if (dl_dohpuxbind(p->send_fd, p->errbuf) < 0) goto bad; } #endif @@ -780,63 +670,13 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, ** XXX - get SAP length and address length as well, for use ** when sending packets. */ - if (dlinforeq(p->fd, ebuf) < 0 || - dlinfoack(p->fd, (char *)buf, ebuf) < 0) + if (dlinforeq(p->fd, p->errbuf) < 0 || + dlinfoack(p->fd, (char *)buf, p->errbuf) < 0) goto bad; infop = &((union DL_primitives *)buf)->info_ack; - switch (infop->dl_mac_type) { - - case DL_CSMACD: - case DL_ETHER: - p->linktype = DLT_EN10MB; - p->offset = 2; - /* - * This is (presumably) a real Ethernet capture; give it a - * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so - * that an application can let you choose it, in case you're - * capturing DOCSIS traffic that a Cisco Cable Modem - * Termination System is putting out onto an Ethernet (it - * doesn't put an Ethernet header onto the wire, it puts raw - * DOCSIS frames out on the wire inside the low-level - * Ethernet framing). - */ - p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); - /* - * If that fails, just leave the list empty. - */ - if (p->dlt_list != NULL) { - p->dlt_list[0] = DLT_EN10MB; - p->dlt_list[1] = DLT_DOCSIS; - p->dlt_count = 2; - } - break; - - case DL_FDDI: - p->linktype = DLT_FDDI; - p->offset = 3; - break; - - case DL_TPR: - /* - * XXX - what about DL_TPB? Is that Token Bus? - */ - p->linktype = DLT_IEEE802; - p->offset = 2; - break; - -#ifdef HAVE_SOLARIS - case DL_IPATM: - p->linktype = DLT_SUNATM; - p->offset = 0; /* works for LANE and LLC encapsulation */ - break; -#endif - - default: - snprintf(ebuf, PCAP_ERRBUF_SIZE, "unknown mac type %lu", - (unsigned long)infop->dl_mac_type); + if (pcap_process_mactype(p, infop->dl_mac_type) != 0) goto bad; - } #ifdef DLIOCRAW /* @@ -844,82 +684,56 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, ** header. */ if (strioctl(p->fd, DLIOCRAW, 0, NULL) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "DLIOCRAW: %s", + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "DLIOCRAW: %s", pcap_strerror(errno)); goto bad; } #endif -#ifdef HAVE_SYS_BUFMOD_H - /* - ** Another non standard call to get the data nicely buffered - */ - if (ioctl(p->fd, I_PUSH, "bufmod") != 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "I_PUSH bufmod: %s", - pcap_strerror(errno)); - goto bad; - } + ss = p->snapshot; /* - ** Now that the bufmod is pushed lets configure it. - ** ** 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 supposed to be fixed in 5.3.2. Also, there is a - ** patch available. Ask for bugid 1149065. + ** This bug is fixed in 5.3.2. Also, there is a patch available. + ** Ask for bugid 1149065. */ - ss = snaplen; #ifdef HAVE_SOLARIS release = get_release(&osmajor, &osminor, &osmicro); if (osmajor == 5 && (osminor <= 2 || (osminor == 3 && osmicro < 2)) && getenv("BUFMOD_FIXED") == NULL) { - fprintf(stderr, - "WARNING: bufmod is broken in SunOS %s; ignoring snaplen.\n", + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "WARNING: bufmod is broken in SunOS %s; ignoring snaplen.", release); ss = 0; + status = PCAP_WARNING; } #endif - if (ss > 0 && - strioctl(p->fd, SBIOCSSNAP, sizeof(ss), (char *)&ss) != 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCSSNAP: %s", - pcap_strerror(errno)); + +#ifdef HAVE_SYS_BUFMOD_H + /* Push and configure bufmod. */ + if (pcap_conf_bufmod(p, ss, p->md.timeout) != 0) goto bad; - } - - /* - ** Set up the bufmod timeout - */ - if (to_ms != 0) { - struct timeval to; - - to.tv_sec = to_ms / 1000; - to.tv_usec = (to_ms * 1000) % 1000000; - if (strioctl(p->fd, SBIOCSTIME, sizeof(to), (char *)&to) != 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCSTIME: %s", - pcap_strerror(errno)); - goto bad; - } - } #endif /* ** As the last operation flush the read side. */ if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s", + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s", pcap_strerror(errno)); goto bad; } - /* Allocate data buffer */ - p->bufsize = PKTBUFSIZE; - p->buffer = (u_char *)malloc(p->bufsize + p->offset); - if (p->buffer == NULL) { - strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); + /* 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 @@ -935,21 +749,12 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; p->stats_op = pcap_stats_dlpi; - p->close_op = pcap_close_dlpi; + p->cleanup_op = pcap_cleanup_dlpi; - return (p); + return (status); bad: - if (p->fd >= 0) - close(p->fd); - if (p->send_fd >= 0) - close(p->send_fd); - /* - * Get rid of any link-layer type list we allocated. - */ - if (p->dlt_list != NULL) - free(p->dlt_list); - free(p); - return (NULL); + pcap_cleanup_dlpi(p); + return (status); } /* @@ -1005,10 +810,13 @@ static int dl_doattach(int fd, int ppa, char *ebuf) { bpf_u_int32 buf[MAXDLBUF]; + int err; - if (dlattachreq(fd, ppa, ebuf) < 0 || - dlokack(fd, "attach", (char *)buf, ebuf) < 0) - return (-1); + if (dlattachreq(fd, ppa, ebuf) < 0) + return (PCAP_ERROR); + err = dlokack(fd, "attach", (char *)buf, ebuf); + if (err < 0) + return (err); return (0); } @@ -1148,7 +956,7 @@ recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf, int *uerror if (getmsg(fd, &ctl, (struct strbuf*)NULL, &flags) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s getmsg: %s", what, pcap_strerror(errno)); - return (-1); + return (PCAP_ERROR); } dlp = (union DL_primitives *) ctl.buf; @@ -1172,27 +980,33 @@ recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf, int *uerror 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 == 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 (-1); + return (PCAP_ERROR); default: snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: Unexpected primitive ack %s", what, dlprim(dlp->dl_primitive)); - return (-1); + 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 (-1); + return (PCAP_ERROR); } return (ctl.len); } @@ -1475,6 +1289,24 @@ 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. @@ -1511,26 +1343,6 @@ dlrawdatareq(int fd, const u_char *datap, int datalen) } #endif /* DL_HP_RAWDLS */ -#ifdef HAVE_SYS_BUFMOD_H -static int -strioctl(int fd, int cmd, int len, char *dp) -{ - struct strioctl str; - int rc; - - str.ic_cmd = cmd; - str.ic_timout = -1; - str.ic_len = len; - str.ic_dp = dp; - rc = ioctl(fd, I_STR, &str); - - if (rc < 0) - return (rc); - else - return (str.ic_len); -} -#endif - #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) @@ -1620,7 +1432,7 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit, memset((char *)buf, 0, sizeof(buf)); if (send_request(fd, (char *)&req, sizeof(req), "hpppa", ebuf) < 0) - return (-1); + return (PCAP_ERROR); ctl.maxlen = DL_HP_PPA_ACK_SIZE; ctl.len = 0; @@ -1643,7 +1455,7 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit, if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno)); - return (-1); + return (PCAP_ERROR); } dlp = (dl_hp_ppa_ack_t *)ctl.buf; @@ -1651,21 +1463,21 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit, snprintf(ebuf, PCAP_ERRBUF_SIZE, "get_dlpi_ppa: hpppa unexpected primitive ack 0x%x", (bpf_u_int32)dlp->dl_primitive); - return (-1); + 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 (-1); + 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 (-1); + return (PCAP_ERROR); } ctl.maxlen = dlp->dl_length; ctl.len = 0; @@ -1675,14 +1487,14 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit, snprintf(ebuf, PCAP_ERRBUF_SIZE, "get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno)); free(ppa_data_buf); - return (-1); + return (PCAP_ERROR); } if (ctl.len < dlp->dl_length) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "get_dlpi_ppa: hpppa ack too small (%d < %d)", ctl.len, dlp->dl_length); free(ppa_data_buf); - return (-1); + return (PCAP_ERROR); } ap = (dl_hp_ppa_ack_t *)buf; @@ -1739,7 +1551,7 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit, if (stat(dname, &statbuf) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "stat: %s: %s", dname, pcap_strerror(errno)); - return (-1); + return (PCAP_ERROR); } majdev = major(statbuf.st_rdev); @@ -1756,13 +1568,13 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit, if (i == ap->dl_count) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "can't find /dev/dlpi PPA for %s%d", device, unit); - return (-1); + 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 (-1); + return (PCAP_ERROR); } ppa = ip->dl_ppa; free(ppa_data_buf); @@ -1860,3 +1672,18 @@ dlpi_kread(register int fd, register off_t addr, return (cc); } #endif + +pcap_t * +pcap_create(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); +} diff --git a/libpcap/pcap-dos.c b/libpcap/pcap-dos.c index 0700d6b1c..7b3c4bda7 100644 --- a/libpcap/pcap-dos.c +++ b/libpcap/pcap-dos.c @@ -1,11 +1,11 @@ /* * This file is part of DOS-libpcap - * Ported to DOS/DOSX by G. Vanem + * Ported to DOS/DOSX by G. Vanem * * pcap-dos.c: Interface to PKTDRVR, NDIS2 and 32-bit pmode * network drivers. * - * @(#) $Header: /tcpdump/master/libpcap/pcap-dos.c,v 1.1.2.1 2005/05/03 18:54:35 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/pcap-dos.c,v 1.2.2.5 2008-04-22 17:16:49 guy Exp $ (LBL) */ #include @@ -97,9 +97,10 @@ static volatile BOOL exc_occured = 0; static struct device *handle_to_device [20]; +static int pcap_activate_dos (pcap_t *p); static int pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback, u_char *data); -static void pcap_close_dos (pcap_t *p); +static void pcap_cleanup_dos (pcap_t *p); static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps); static int pcap_sendpacket_dos (pcap_t *p, const void *buf, size_t len); static int pcap_setfilter_dos (pcap_t *p, struct bpf_program *fp); @@ -142,59 +143,64 @@ static struct device *get_device (int fd) return handle_to_device [fd-1]; } +pcap_t *pcap_create (const char *device, char *ebuf) +{ + pcap_t *p; + + p = pcap_create_common(device, ebuf); + if (p == NULL) + return (NULL); + + p->activate_op = pcap_activate_dos; + return (p); +} + /* * Open MAC-driver with name 'device_name' for live capture of * network packets. */ -pcap_t *pcap_open_live (const char *device_name, int snaplen, int promisc, - int timeout_ms, char *errbuf) +static int pcap_activate_dos (pcap_t *pcap) { - struct pcap *pcap; - - if (snaplen < ETH_MIN) - snaplen = ETH_MIN; - - if (snaplen > ETH_MAX) /* silently accept and truncate large MTUs */ - snaplen = ETH_MAX; - - pcap = calloc (sizeof(*pcap), 1); - if (!pcap) - { - strcpy (errbuf, "Not enough memory (pcap)"); - return (NULL); + if (pcap->opt.rfmon) { + /* + * No monitor mode on DOS. + */ + return (PCAP_ERROR_RFMON_NOTSUP); } - pcap->snapshot = max (ETH_MIN+8, snaplen); + if (pcap->snapshot < ETH_MIN+8) + pcap->snapshot = ETH_MIN+8; + + if (pcap->snapshot > ETH_MAX) /* silently accept and truncate large MTUs */ + pcap->snapshot = ETH_MAX; + pcap->linktype = DLT_EN10MB; /* !! */ - pcap->inter_packet_wait = timeout_ms; - pcap->close_op = pcap_close_dos; + pcap->cleanup_op = pcap_cleanup_dos; pcap->read_op = pcap_read_dos; pcap->stats_op = pcap_stats_dos; pcap->inject_op = pcap_sendpacket_dos; pcap->setfilter_op = pcap_setfilter_dos; - pcap->setdirection_op = NULL; /* Not implemented.*/ + pcap->setdirection_op = NULL; /* Not implemented.*/ pcap->fd = ++ref_count; if (pcap->fd == 1) /* first time we're called */ { - if (!init_watt32(pcap, device_name, errbuf) || - !first_init(device_name, errbuf, promisc)) + if (!init_watt32(pcap, pcap->opt.source, pcap->errbuf) || + !first_init(pcap->opt.source, pcap->errbuf, pcap->opt.promisc)) { - free (pcap); - return (NULL); + return (PCAP_ERROR); } atexit (close_driver); } - else if (stricmp(active_dev->name,device_name)) + else if (stricmp(active_dev->name,pcap->opt.source)) { - snprintf (errbuf, PCAP_ERRBUF_SIZE, + snprintf (pcap->errbuf, PCAP_ERRBUF_SIZE, "Cannot use different devices simultaneously " - "(`%s' vs. `%s')", active_dev->name, device_name); - free (pcap); - pcap = NULL; + "(`%s' vs. `%s')", active_dev->name, pcap->opt.source); + return (PCAP_ERROR); } handle_to_device [pcap->fd-1] = active_dev; - return (pcap); + return (0); } /* @@ -205,15 +211,14 @@ static int pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data) { struct pcap_pkthdr pcap; - struct bpf_insn *fcode = p->fcode.bf_insns; struct timeval now, expiry; BYTE *rx_buf; int rx_len = 0; - if (p->inter_packet_wait > 0) + if (p->md.timeout > 0) { gettimeofday2 (&now, NULL); - expiry.tv_usec = now.tv_usec + 1000UL * p->inter_packet_wait; + expiry.tv_usec = now.tv_usec + 1000UL * p->md.timeout; expiry.tv_sec = now.tv_sec; while (expiry.tv_usec >= 1000000L) { @@ -258,7 +263,7 @@ pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data) pcap.len = rx_len; if (callback && - (!fcode || bpf_filter(fcode, rx_buf, pcap.len, pcap.caplen))) + (!p->fcode.bf_insns || bpf_filter(p->fcode.bf_insns, rx_buf, pcap.len, pcap.caplen))) { filter_count++; @@ -285,7 +290,7 @@ pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data) /* If not to wait for a packet or pcap_close() called from * e.g. SIGINT handler, exit loop now. */ - if (p->inter_packet_wait <= 0 || (volatile int)p->fd <= 0) + if (p->md.timeout <= 0 || (volatile int)p->fd <= 0) break; gettimeofday2 (&now, NULL); @@ -421,7 +426,7 @@ u_long pcap_filter_packets (void) /* * Close pcap device. Not called for offline captures. */ -static void pcap_close_dos (pcap_t *p) +static void pcap_cleanup_dos (pcap_t *p) { if (p && !exc_occured) { @@ -477,7 +482,7 @@ int pcap_lookupnet (const char *device, bpf_u_int32 *localnet, { if (!_watt_is_init) { - strcpy (errbuf, "pcap_open_offline() or pcap_open_live() must be " + strcpy (errbuf, "pcap_open_offline() or pcap_activate() must be " "called first"); return (-1); } @@ -588,7 +593,7 @@ void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait) if (p) { p->wait_proc = yield; - p->inter_packet_wait = wait; + p->md.timeout = wait; } } @@ -734,13 +739,13 @@ static void exc_handler (int sig) fprintf (stderr, "Catching signal %d.\n", sig); } exc_occured = 1; - pcap_close_dos (NULL); + pcap_cleanup_dos (NULL); } #endif /* __DJGPP__ */ /* - * Open the pcap device for the first client calling pcap_open_live() + * Open the pcap device for the first client calling pcap_activate() */ static int first_init (const char *name, char *ebuf, int promisc) { @@ -991,7 +996,7 @@ int EISA_bus = 0; /* Where is natural place for this? */ * Application config hooks to set various driver parameters. */ -static struct config_table debug_tab[] = { +static const struct config_table debug_tab[] = { { "PKT.DEBUG", ARG_ATOI, &pcap_pkt_debug }, { "PKT.VECTOR", ARG_ATOX_W, NULL }, { "NDIS.DEBUG", ARG_ATOI, NULL }, diff --git a/libpcap/pcap-enet.c b/libpcap/pcap-enet.c index a48420718..e5ea9aa17 100644 --- a/libpcap/pcap-enet.c +++ b/libpcap/pcap-enet.c @@ -8,7 +8,7 @@ */ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-enet.c,v 1.8 2003/11/15 23:24:02 guy Exp $"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-enet.c,v 1.9 2006/10/04 18:09:22 guy Exp $"; #endif #ifdef HAVE_CONFIG_H @@ -22,7 +22,7 @@ static const char rcsid[] _U_ = #include #include -#include +#include #include #include diff --git a/libpcap/pcap-filter.manmisc.in b/libpcap/pcap-filter.manmisc.in new file mode 100644 index 000000000..3beec5802 --- /dev/null +++ b/libpcap/pcap-filter.manmisc.in @@ -0,0 +1,949 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap-filter.manmisc.in,v 1.1.2.2 2008-10-21 07:44:56 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 +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 +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 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 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 +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 +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 +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 +True if the Ethernet source address is \fIehost\fP. +.IP "\fBether host \fIehost\fP +True if either the Ethernet source or destination address is \fIehost\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 "\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 "\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 "\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 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, \fInetbeui\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 +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 +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. diff --git a/libpcap/pcap-int.h b/libpcap/pcap-int.h index 3071c77f5..080470e93 100644 --- a/libpcap/pcap-int.h +++ b/libpcap/pcap-int.h @@ -30,17 +30,21 @@ * 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.68.2.11 2007/06/22 06:43:58 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.85.2.9 2008-09-16 00:21:08 guy Exp $ (LBL) */ #ifndef pcap_int_h -#define pcap_int_h +#define pcap_int_h + +#include #ifdef __cplusplus extern "C" { #endif -#include +#ifdef HAVE_LIBDLPI +#include +#endif #ifdef WIN32 #include @@ -51,6 +55,23 @@ extern "C" { #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. @@ -64,6 +85,8 @@ extern "C" { ((ull & 0x000000000000ff00LL) << 40) | \ ((ull & 0x00000000000000ffLL) << 56) +#endif /* _MSC_VER */ + /* * Savefile */ @@ -73,16 +96,22 @@ typedef enum { MAYBE_SWAPPED } swapped_type_t; +/* + * Used when reading a savefile. + */ struct pcap_sf { FILE *rfile; int swapped; - int hdrsize; + size_t hdrsize; swapped_type_t lengths_swapped; int version_major; int version_minor; u_char *base; }; +/* + * Used when doing a live capture. + */ struct pcap_md { struct pcap_stat stat; /*XXX*/ @@ -93,22 +122,25 @@ struct pcap_md { 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_clear; /* stuff we must clear 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 timeout; /* timeout specified to pcap_open_live */ - int clear_promisc; /* must clear promiscuous mode when we close */ int cooked; /* using SOCK_DGRAM rather than SOCK_RAW */ int ifindex; /* interface index of device we're bound to */ int lo_ifindex; /* interface index of the loopback device */ - struct pcap *next; /* list of open promiscuous sock_packet pcaps */ u_int packets_read; /* count of packets read with recvfrom() */ -#endif + bpf_u_int32 oldmode; /* mode to restore when turning monitor mode off */ + u_int tp_version; /* version of tpacket_hdr for mmaped ring */ + u_int tp_hdrlen; /* hdrlen of tpacket_hdr for mmaped ring */ +#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 +#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 */ @@ -120,6 +152,41 @@ struct pcap_md { * Same as in linux above, introduce * generally? */ #endif /* HAVE_DAG_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 clear when we close. + */ +#define MUST_CLEAR_PROMISC 0x00000001 /* promiscuous mode */ +#define MUST_CLEAR_RFMON 0x00000002 /* rfmon (monitor) mode */ + +struct pcap_opt { + int buffer_size; + char *source; + int promisc; + int rfmon; }; /* @@ -135,21 +202,44 @@ struct pcap_md { #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 timeout; 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; + 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 */ @@ -158,12 +248,12 @@ struct pcap { #endif #ifdef MSDOS - int inter_packet_wait; /* offline: wait between packets */ void (*wait_proc)(void); /* call proc while waiting */ #endif struct pcap_sf sf; struct pcap_md md; + struct pcap_opt opt; /* * Read buffer. @@ -184,15 +274,27 @@ struct pcap { /* * Methods. */ - int (*read_op)(pcap_t *, int cnt, pcap_handler, u_char *); - int (*inject_op)(pcap_t *, const void *, size_t); - int (*setfilter_op)(pcap_t *, struct bpf_program *); - int (*setdirection_op)(pcap_t *, pcap_direction_t); - int (*set_datalink_op)(pcap_t *, int); - int (*getnonblock_op)(pcap_t *, char *); - int (*setnonblock_op)(pcap_t *, int, char *); - int (*stats_op)(pcap_t *, struct pcap_stat *); - void (*close_op)(pcap_t *); + 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; + +#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. @@ -231,8 +333,8 @@ struct pcap_timeval { * * introduce a new structure for the new format; * - * send mail to "tcpdump-workers@tcpdump.org", requesting a new - * magic number for your new capture file format, and, when + * 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 @@ -242,9 +344,12 @@ struct pcap_timeval { * 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 to "patches@tcpdump.org", so that future - * versions of libpcap and programs that use it (such as tcpdump) will - * be able to read your new capture file format. + * Then supply the changes as a patch at + * + * http://sourceforge.net/projects/libpcap/ + * + * 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 { @@ -309,7 +414,13 @@ int pcap_getnonblock_fd(pcap_t *, char *); int pcap_setnonblock_fd(pcap_t *p, int, char *); #endif -void pcap_close_common(pcap_t *); +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()". diff --git a/libpcap/pcap-libdlpi.c b/libpcap/pcap-libdlpi.c new file mode 100644 index 000000000..b61e8ecd4 --- /dev/null +++ b/libpcap/pcap-libdlpi.c @@ -0,0 +1,370 @@ +/* + * 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.1.2.6 2008-04-14 20:41:52 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 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 *); + +/* + * 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 == DLPI_SYSERR && 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) { + retv = dlpi_promiscon(p->dlpi_hd, DL_PROMISC_PHYS); + if (retv != DLPI_SUCCESS) { + pcap_libdlpi_err(p->opt.source, + "dlpi_promisc(PHYSICAL)", retv, p->errbuf); + goto bad; + } + } else { + /* Try to enable multicast. */ + retv = dlpi_promiscon(p->dlpi_hd, DL_PROMISC_MULTI); + if (retv != DLPI_SUCCESS) { + pcap_libdlpi_err(p->opt.source, "dlpi_promisc(MULTI)", + retv, p->errbuf); + goto bad; + } + } + + /* Try to enable SAP promiscuity. */ + if ((retv = dlpi_promiscon(p->dlpi_hd, DL_PROMISC_SAP)) != DLPI_SUCCESS) { + if (!promisc) { + pcap_libdlpi_err(p->opt.source, "dlpi_promisc(SAP)", + retv, p->errbuf); + goto bad; + } + + /* Not fatal, since the DL_PROMISC_PHYS mode worked. */ + fprintf(stderr, "WARNING: dlpi_promisc(SAP) failed on" + " %s:(%s)\n", p->opt.source, dlpi_strerror(retv)); + } + + /* 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, snaplen, 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); +} + +/* + * 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_t *p; + + p = pcap_create_common(device, ebuf); + if (p == NULL) + return (NULL); + + p->activate_op = pcap_activate_libdlpi; + return (p); +} diff --git a/libpcap/pcap-linktype.manmisc.in b/libpcap/pcap-linktype.manmisc.in new file mode 100644 index 000000000..7d33b7f88 --- /dev/null +++ b/libpcap/pcap-linktype.manmisc.in @@ -0,0 +1,282 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap-linktype.manmisc.in,v 1.1.2.4 2008-10-27 22:52:05 guy Exp $ +.\" +.\" 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-LINKTYPE @MAN_MISC_INFO@ "23 October 2008" +.SH NAME +pcap-linktype \- link-layer header types supported by libpcap +.SH DESCRIPTION +For a live capture or ``savefile'', libpcap supplies, as the return +value of the +.BR pcap_datalink (3PCAP) +routine, a value that indicates the type of link-layer header at the +beginning of the packets it provides. This is not necessarily the type +of link-layer header that the packets being captured have on the network +from which they're being captured; for example, packets from an IEEE +802.11 network might be provided by libpcap with Ethernet headers that +the network adapter or the network adapter driver generates from the +802.11 headers. The names for those values begin with +.BR DLT_ , +so they are sometimes called "DLT_ values". +.PP +The values stored in the link-layer header type field in the savefile +header are, in most but not all cases, the same as the values returned +by +.BR pcap_datalink() . +The names for those values begin with +.BR LINKTYPE_ . +.PP +The link-layer header types supported by libpcap are listed here. The +value corresponding to +.B LINKTYPE_ +names are given; the value corresponding to +.B DLT_ +values are, in some cases, platform dependent, and are not given; +applications should check for particular +.B DLT_ +values by name. +.RS 5 +.TP 5 +.BR DLT_NULL "; " LINKTYPE_NULL = 0 +BSD loopback encapsulation; the link layer header is a 4-byte field, in +.I host +byte order, containing a PF_ value from +.B socket.h +for the network-layer protocol of the packet. +.IP +Note that ``host byte order'' is the byte order of the machine on which +the packets are captured, and the PF_ values are for the OS of the +machine on which the packets are captured; if a live capture is being +done, ``host byte order'' is the byte order of the machine capturing the +packets, and the PF_ values are those of the OS of the machine capturing +the packets, but if a ``savefile'' is being read, the byte order and PF_ +values are +.I not +necessarily those of the machine reading the capture file. +.TP 5 +.BR DLT_EN10MB "; " LINKTYPE_ETHERNET = 1 +Ethernet (10Mb, 100Mb, 1000Mb, and up); the +.B 10MB +in the +.B DLT_ +name is historical. +.TP 5 +.BR DLT_IEEE802 "; " LINKTYPE_TOKEN_RING = 6 +IEEE 802.5 Token Ring; the +.B IEEE802 +in the +.B DLT_ +name is historical. +.TP 5 +.BR DLT_ARCNET "; " LINKTYPE_ARCNET = 7 +ARCNET +.TP 5 +.BR DLT_SLIP "; " LINKTYPE_SLIP = 8 +SLIP; the link layer header contains, in order: +.RS 10 +.LP +a 1-byte flag, which is 0 for packets received by the machine and 1 for +packets sent by the machine; +.LP +a 1-byte field, the upper 4 bits of which indicate the type of packet, +as per RFC 1144: +.RS 5 +.TP 5 +0x40 +an unmodified IP datagram (TYPE_IP); +.TP 5 +0x70 +an uncompressed-TCP IP datagram (UNCOMPRESSED_TCP), with that byte being +the first byte of the raw IP header on the wire, containing the +connection number in the protocol field; +.TP 5 +0x80 +a compressed-TCP IP datagram (COMPRESSED_TCP), with that byte being the +first byte of the compressed TCP/IP datagram header; +.RE +.LP +for UNCOMPRESSED_TCP, the rest of the modified IP header, and for +COMPRESSED_TCP, the compressed TCP/IP datagram header; +.RE +.RS 5 +.LP +for a total of 16 bytes; the uncompressed IP datagram follows the header. +.RE +.TP 5 +.BR DLT_PPP "; " LINKTYPE_PPP = 9 +PPP; if the first 2 bytes are 0xff and 0x03, it's PPP in HDLC-like +framing, with the PPP header following those two bytes, otherwise it's +PPP without framing, and the packet begins with the PPP header. +.TP 5 +.BR DLT_FDDI "; " LINKTYPE_FDDI = 10 +FDDI +.TP 5 +.BR DLT_ATM_RFC1483 "; " LINKTYPE_ATM_RFC1483 = 100 +RFC 1483 LLC/SNAP-encapsulated ATM; the packet begins with an IEEE 802.2 +LLC header. +.TP 5 +.BR DLT_RAW "; " LINKTYPE_RAW = 101 +raw IP; the packet begins with an IP header. +.TP 5 +.BR DLT_PPP_SERIAL "; " LINKTYPE_PPP_HDLC = 50 +PPP in HDLC-like framing, as per RFC 1662, or Cisco PPP with HDLC +framing, as per section 4.3.1 of RFC 1547; the first byte will be 0xFF +for PPP in HDLC-like framing, and will be 0x0F or 0x8F for Cisco PPP +with HDLC framing. +.TP 5 +.BR DLT_PPP_ETHER "; " LINKTYPE_PPP_ETHER = 51 +PPPoE; the packet begins with a PPPoE header, as per RFC 2516. +.TP 5 +.BR DLT_C_HDLC "; " LINKTYPE_C_HDLC = 104 +Cisco PPP with HDLC framing, as per section 4.3.1 of RFC 1547. +.TP 5 +.BR DLT_IEEE802_11 "; " LINKTYPE_IEEE802_11 = 105 +IEEE 802.11 wireless LAN +.TP 5 +.BR DLT_FRELAY "; " LINKTYPE_FRELAY = 107 +Frame Relay +.TP 5 +.BR DLT_LOOP "; " LINKTYPE_LOOP = 108 +OpenBSD loopback encapsulation; the link layer header is a 4-byte field, in +.I network +byte order, containing a PF_ value from OpenBSD's +.B socket.h +for the network-layer protocol of the packet. +.IP +Note that, if a ``savefile'' is being read, those PF_ values are +.I not +necessarily those of the machine reading the capture file. +.TP 5 +.BR DLT_LINUX_SLL "; " LINKTYPE_LINUX_SLL = 113 +Linux "cooked" capture encapsulation; the link layer header contains, in +order: +.RS 10 +.LP +a 2-byte "packet type", in network byte order, which is one of: +.RS 5 +.TP 5 +0 +packet was sent to us by somebody else +.TP 5 +1 +packet was broadcast by somebody else +.TP 5 +2 +packet was multicast, but not broadcast, by somebody else +.TP 5 +3 +packet was sent by somebody else to somebody else +.TP 5 +4 +packet was sent by us +.RE +.LP +a 2-byte field, in network byte order, containing a Linux ARPHRD_ value +for the link layer device type; +.LP +a 2-byte field, in network byte order, containing the length of the +link layer address of the sender of the packet (which could be 0); +.LP +an 8-byte field containing that number of bytes of the link layer header +(if there are more than 8 bytes, only the first 8 are present); +.LP +a 2-byte field containing an Ethernet protocol type, in network byte +order, or containing 1 for Novell 802.3 frames without an 802.2 LLC +header or 4 for frames beginning with an 802.2 LLC header. +.RE +.TP 5 +.BR DLT_LTALK "; " LINKTYPE_LTALK = 104 +Apple LocalTalk; the packet begins with an AppleTalk LLAP header. +.TP 5 +.BR DLT_PFLOG "; " LINKTYPE_PFLOG = 117 +OpenBSD pflog; the link layer header contains a +.B "struct pfloghdr" +structure, as defined by the host on which the file was saved. (This +differs from operating system to operating system and release to +release; there is nothing in the file to indicate what the layout of +that structure is.) +.TP 5 +.BR DLT_PRISM_HEADER "; " LINKTYPE_PRISM_HEADER = 119 +Prism monitor mode information followed by an 802.11 header. +.TP 5 +.BR DLT_IP_OVER_FC "; " LINKTYPE_IP_OVER_FC = 122 +RFC 2625 IP-over-Fibre Channel, with the link-layer header being the +Network_Header as described in that RFC. +.TP 5 +.BR DLT_SUNATM "; " LINKTYPE_SUNATM = 123 +SunATM devices; the link layer header contains, in order: +.RS 10 +.LP +a 1-byte flag field, containing a direction flag in the uppermost bit, +which is set for packets transmitted by the machine and clear for +packets received by the machine, and a 4-byte traffic type in the +low-order 4 bits, which is one of: +.RS 5 +.TP 5 +0 +raw traffic +.TP 5 +1 +LANE traffic +.TP 5 +2 +LLC-encapsulated traffic +.TP 5 +3 +MARS traffic +.TP 5 +4 +IFMP traffic +.TP 5 +5 +ILMI traffic +.TP 5 +6 +Q.2931 traffic +.RE +.LP +a 1-byte VPI value; +.LP +a 2-byte VCI field, in network byte order. +.RE +.TP 5 +.BR DLT_IEEE802_11_RADIO "; " LINKTYPE_IEEE802_11_RADIO = 127 +link-layer information followed by an 802.11 header - see +http://www.shaftnet.org/~pizza/software/capturefrm.txt for a description +of the link-layer information. +.TP 5 +.BR DLT_ARCNET_LINUX "; " LINKTYPE_ARCNET_LINUX = 129 +ARCNET, with no exception frames, reassembled packets rather than raw +frames, and an extra 16-bit offset field between the destination host +and type bytes. +.TP 5 +.BR DLT_LINUX_IRDA "; " LINKTYPE_LINUX_IRDA = 144 +Linux-IrDA packets, with a +.B DLT_LINUX_SLL +header followed by the IrLAP header. +.TP 5 +.BR DLT_LINUX_LAPD "; " LINKTYPE_LINUX_LAPD = 177 +LAPD (Q.921) frames, with a +.B DLT_LINUX_SLL +header captured via vISDN. +.RE +.SH SEE ALSO +pcap_datalink(3PCAP) diff --git a/libpcap/pcap-linux.c b/libpcap/pcap-linux.c index e9db010d3..8161af019 100644 --- a/libpcap/pcap-linux.c +++ b/libpcap/pcap-linux.c @@ -23,11 +23,18 @@ * 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 */ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.110.2.14 2006/10/12 17:26:58 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.129.2.29 2008-10-28 00:50:39 guy Exp $ (LBL)"; #endif /* @@ -77,17 +84,6 @@ static const char rcsid[] _U_ = #include "config.h" #endif -#include "pcap-int.h" -#include "sll.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 */ - #include #include #include @@ -96,10 +92,39 @@ static const char rcsid[] _U_ = #include #include #include +#include #include #include #include #include +#include + +/* + * Got Wireless Extensions? + */ +#ifdef HAVE_LINUX_WIRELESS_H +#include +#endif + +#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 PCAP_SUPPORT_USB +#include "pcap-usb-linux.h" +#endif + +#ifdef PCAP_SUPPORT_BT +#include "pcap-bt-linux.h" +#endif /* * If PF_PACKET is defined, we can use {SOCK_RAW,SOCK_DGRAM}/PF_PACKET @@ -141,7 +166,23 @@ static const char rcsid[] _U_ = */ # 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 @@ -149,7 +190,7 @@ static const char rcsid[] _U_ = #include #endif -#ifndef __GLIBC__ +#ifndef HAVE_SOCKLEN_T typedef int socklen_t; #endif @@ -185,18 +226,43 @@ typedef int socklen_t; #define BIGGER_THAN_ALL_MTUS (64*1024) /* - * Prototypes for internal functions + * Prototypes for internal functions and methods. */ static void map_arphrd_to_dlt(pcap_t *, int, int); -static int live_open_old(pcap_t *, const char *, int, int, char *); -static int live_open_new(pcap_t *, const char *, int, int, char *); +#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 *); +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_close_linux(pcap_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); +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); +#endif /* * Wrap some ioctl calls @@ -208,6 +274,9 @@ 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); +static int has_wext(int sock_fd, const char *device, char *ebuf); +static int enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, + const char *device); #endif static int iface_bind_old(int fd, const char *device, char *ebuf); @@ -223,6 +292,204 @@ static struct sock_fprog total_fcode = { 1, &total_insn }; #endif +pcap_t * +pcap_create(const char *device, char *ebuf) +{ + pcap_t *handle; + +#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 PCAP_SUPPORT_BT + if (strstr(device, "bluetooth")) { + return bt_create(device, ebuf); + } +#endif + +#ifdef PCAP_SUPPORT_USB + if (strstr(device, "usb")) { + return usb_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; + return handle; +} + +static int +pcap_can_set_rfmon_linux(pcap_t *p) +{ +#ifdef IW_MODE_MONITOR + int sock_fd; + struct iwreq ireq; +#endif + + if (p->opt.source == NULL) { + /* + * This is equivalent to the "any" device, and we don't + * support monitor mode on it. + */ + return 0; + } + +#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(p->errbuf, PCAP_ERRBUF_SIZE, + "socket: %s", pcap_strerror(errno)); + return PCAP_ERROR; + } + + /* + * Attempt to get the current mode. + */ + strncpy(ireq.ifr_ifrn.ifrn_name, p->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. */ + close(sock_fd); + return PCAP_ERROR_NO_SUCH_DEVICE; + } + close(sock_fd); +#endif + return 0; +} + +/* + * 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 IW_MODE_MONITOR + struct iwreq ireq; +#endif + + if (handle->md.must_clear != 0) { + /* + * There's something we have to do when closing this + * pcap_t. + */ + if (handle->md.must_clear & 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 flags (SIOCGIFFLAGS failed: %s).\n" + "Please adjust manually.\n" + "Hint: This can't happen with Linux >= 2.2.0.\n", + 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 flags (SIOCSIFFLAGS failed: %s).\n" + "Please adjust manually.\n" + "Hint: This can't happen with Linux >= 2.2.0.\n", + strerror(errno)); + } + } + } + } + +#ifdef IW_MODE_MONITOR + if (handle->md.must_clear & 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. + */ + 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 wireless mode (SIOCSIWMODE failed: %s).\n" + "Please adjust manually.\n", + strerror(errno)); + } + } +#endif + + /* + * 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.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 @@ -230,45 +497,25 @@ static struct sock_fprog total_fcode * 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). - * - * See also pcap(3). */ -pcap_t * -pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, - char *ebuf) +static int +pcap_activate_linux(pcap_t *handle) { - pcap_t *handle; - int mtu; - int err; - int live_open_ok = 0; - struct utsname utsname; + const char *device; + int status = 0; + int activate_ok = 0; -#ifdef HAVE_DAG_API - if (strstr(device, "dag")) { - return dag_open_live(device, snaplen, promisc, to_ms, ebuf); - } -#endif /* HAVE_DAG_API */ + device = handle->opt.source; -#ifdef HAVE_SEPTEL_API - if (strstr(device, "septel")) { - return septel_open_live(device, snaplen, promisc, to_ms, ebuf); - } -#endif /* HAVE_SEPTEL_API */ - - /* Allocate a handle for this session. */ - - handle = malloc(sizeof(*handle)); - if (handle == NULL) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", - pcap_strerror(errno)); - return NULL; - } - - /* Initialize some components of the pcap structure. */ - - memset(handle, 0, sizeof(*handle)); - handle->snapshot = snaplen; - handle->md.timeout = to_ms; + 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; /* * NULL and "any" are special devices which give us the hint to @@ -277,21 +524,21 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, if (!device || strcmp(device, "any") == 0) { device = NULL; handle->md.device = strdup("any"); - if (promisc) { - promisc = 0; + if (handle->opt.promisc) { + handle->opt.promisc = 0; /* Just a warning. */ - snprintf(ebuf, PCAP_ERRBUF_SIZE, + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Promiscuous mode not supported on the \"any\" device"); + status = PCAP_WARNING_PROMISC_NOTSUP; } } else handle->md.device = strdup(device); if (handle->md.device == NULL) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "strdup: %s", + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s", pcap_strerror(errno) ); - free(handle); - return NULL; + return PCAP_ERROR; } /* @@ -304,118 +551,50 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, * trying both methods with the newer method preferred. */ - if ((err = live_open_new(handle, device, promisc, to_ms, ebuf)) == 1) - live_open_ok = 1; - else if (err == 0) { - /* Non-fatal error; try old way */ - if (live_open_old(handle, device, promisc, to_ms, ebuf)) - live_open_ok = 1; + if ((status = activate_new(handle)) == 1) { + activate_ok = 1; + /* + * Try to use memory-mapped access. + */ + if (activate_mmap(handle) == 1) + return 0; /* we succeeded; nothing more to do */ } - if (!live_open_ok) { + else if (status == 0) { + /* Non-fatal error; try old way */ + if ((status = activate_old(handle)) == 1) + activate_ok = 1; + } + if (!activate_ok) { /* * Both methods to open the packet socket failed. Tidy * up and report our failure (ebuf is expected to be * set by the functions above). */ - - if (handle->md.device != NULL) - free(handle->md.device); - free(handle); - return NULL; + goto fail; } - /* - * Compute the buffer size. - * - * If we're using SOCK_PACKET, this might be a 2.0[.x] kernel, - * and might require special handling - check. - */ - if (handle->md.sock_packet && (uname(&utsname) < 0 || - strncmp(utsname.release, "2.0", 3) == 0)) { + if (handle->opt.buffer_size != 0) { /* - * We're using a SOCK_PACKET structure, and either - * we couldn't find out what kernel release this is, - * or it's a 2.0[.x] kernel. - * - * In the 2.0[.x] kernel, a "recvfrom()" on - * a SOCK_PACKET socket, with MSG_TRUNC set, will - * return the number of bytes read, so if we pass - * a length based on the snapshot length, it'll - * return the number of bytes from the packet - * copied to userland, not the actual length - * of the packet. - * - * This means that, for example, the IP dissector - * in tcpdump will get handed a packet length less - * than the length in the IP header, and will - * complain about "truncated-ip". - * - * So we don't bother trying to copy from the - * kernel only the bytes in which we're interested, - * but instead copy them all, just as the older - * versions of libpcap for Linux did. - * - * The buffer therefore needs to be big enough to - * hold the largest packet we can get from this - * device. Unfortunately, we can't get the MRU - * of the network; we can only get the MTU. The - * MTU may be too small, in which case a packet larger - * than the buffer size will be truncated *and* we - * won't get the actual packet size. - * - * However, if the snapshot length is larger than - * the buffer size based on the MTU, we use the - * snapshot length as the buffer size, instead; - * this means that with a sufficiently large snapshot - * length we won't artificially truncate packets - * to the MTU-based size. - * - * This mess just one of many problems with packet - * capture on 2.0[.x] kernels; you really want a - * 2.2[.x] or later kernel if you want packet capture - * to work well. + * Set the socket buffer size to the specified value. */ - mtu = iface_get_mtu(handle->fd, device, ebuf); - if (mtu == -1) { - pcap_close_linux(handle); - free(handle); - return NULL; + 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; } - handle->bufsize = MAX_LINKHEADER_SIZE + mtu; - if (handle->bufsize < handle->snapshot) - handle->bufsize = handle->snapshot; - } else { - /* - * This is a 2.2[.x] or later kernel (we know that - * either because we're not using a SOCK_PACKET - * socket - PF_PACKET is supported only in 2.2 - * and later kernels - or because we checked the - * kernel version). - * - * We can safely pass "recvfrom()" a byte count - * based on the snapshot length. - * - * 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; } /* Allocate the buffer */ handle->buffer = malloc(handle->bufsize + handle->offset); if (!handle->buffer) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); - pcap_close_linux(handle); - free(handle); - return NULL; + status = PCAP_ERROR; + goto fail; } /* @@ -424,17 +603,11 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, */ handle->selectable_fd = handle->fd; - handle->read_op = pcap_read_linux; - handle->inject_op = pcap_inject_linux; - handle->setfilter_op = pcap_setfilter_linux; - handle->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->stats_op = pcap_stats_linux; - handle->close_op = pcap_close_linux; + return status; - return handle; +fail: + pcap_cleanup_linux(handle); + return status; } /* @@ -468,7 +641,17 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) #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; @@ -489,9 +672,36 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) offset = 0; #endif - /* Receive a single packet from the kernel */ - + /* + * 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? @@ -505,12 +715,17 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) handle->break_loop = 0; return -2; } + +#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); - } while (packet_len == -1 && errno == EINTR); +#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */ + } while (packet_len == -1 && (errno == EINTR || errno == ENETDOWN)); /* Check if an error occured */ @@ -518,7 +733,7 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) if (errno == EAGAIN) return 0; /* no packet there */ else { - snprintf(handle->errbuf, sizeof(handle->errbuf), + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "recvfrom: %s", pcap_strerror(errno)); return -1; } @@ -586,42 +801,7 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) packet_len += SLL_HDR_LEN; hdrp = (struct sll_header *)bp; - - /* - * 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. - */ - switch (from.sll_pkttype) { - - case PACKET_HOST: - hdrp->sll_pkttype = htons(LINUX_SLL_HOST); - break; - - case PACKET_BROADCAST: - hdrp->sll_pkttype = htons(LINUX_SLL_BROADCAST); - break; - - case PACKET_MULTICAST: - hdrp->sll_pkttype = htons(LINUX_SLL_MULTICAST); - break; - - case PACKET_OTHERHOST: - hdrp->sll_pkttype = htons(LINUX_SLL_OTHERHOST); - break; - - case PACKET_OUTGOING: - hdrp->sll_pkttype = htons(LINUX_SLL_OUTGOING); - break; - - default: - hdrp->sll_pkttype = -1; - break; - } - + 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, @@ -630,7 +810,37 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) from.sll_halen); hdrp->sll_protocol = from.sll_protocol; } -#endif + +#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 (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; + + len = packet_len > iov.iov_len ? iov.iov_len : packet_len; + if (len < 2 * ETH_ALEN) + break; + + bp -= VLAN_TAG_LEN; + memmove(bp, bp + VLAN_TAG_LEN, 2 * ETH_ALEN); + + tag = (struct vlan_tag *)(bp + 2 * ETH_ALEN); + tag->vlan_tpid = htons(ETH_P_8021Q); + tag->vlan_tci = htons(aux->tp_vlan_tci); + + 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 @@ -681,7 +891,7 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) /* Fill in our own header data */ if (ioctl(handle->fd, SIOCGSTAMP, &pcap_header.ts) == -1) { - snprintf(handle->errbuf, sizeof(handle->errbuf), + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "SIOCGSTAMP: %s", pcap_strerror(errno)); return -1; } @@ -915,6 +1125,16 @@ pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) return (-1); #endif /* HAVE_SEPTEL_API */ +#ifdef PCAP_SUPPORT_BT + if (bt_platform_finddevs(alldevsp, errbuf) < 0) + return (-1); +#endif + +#ifdef PCAP_SUPPORT_USB + if (usb_platform_finddevs(alldevsp, errbuf) < 0) + return (-1); +#endif + return (0); } @@ -934,7 +1154,7 @@ pcap_setfilter_linux(pcap_t *handle, struct bpf_program *filter) return -1; if (!filter) { strncpy(handle->errbuf, "setfilter: No filter specified", - sizeof(handle->errbuf)); + PCAP_ERRBUF_SIZE); return -1; } @@ -1072,11 +1292,47 @@ pcap_setdirection_linux(pcap_t *handle, pcap_direction_t d) * We're not using PF_PACKET sockets, so we can't determine * the direction of the packet. */ - snprintf(handle->errbuf, sizeof(handle->errbuf), + 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 @@ -1113,7 +1369,7 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, int cooked_ok) * XXX - are there any sorts of "fake Ethernet" that have * ARPHRD_ETHER but that *shouldn't offer DLT_DOCSIS as * a Cisco CMTS won't put traffic onto it or get traffic - * bridged onto it? ISDN is handled in "live_open_new()", + * bridged onto it? ISDN is handled in "activate_new()", * as we fall back on cooked mode there; are there any * others? */ @@ -1139,7 +1395,7 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, int cooked_ok) break; case ARPHRD_AX25: - handle->linktype = DLT_AX25; + handle->linktype = DLT_AX25_KISS; break; case ARPHRD_PRONET: @@ -1371,6 +1627,17 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, int cooked_ok) 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; + default: handle->linktype = -1; break; @@ -1380,218 +1647,265 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, int cooked_ok) /* ===== Functions to interface to the newer kernels ================== */ /* - * Try to open a packet socket using the new kernel interface. - * Returns 0 on failure. - * FIXME: 0 uses to mean success (Sebastian) + * 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 -live_open_new(pcap_t *handle, const char *device, int promisc, - int to_ms, char *ebuf) +activate_new(pcap_t *handle) { #ifdef HAVE_PF_PACKET_SOCKETS - int sock_fd = -1, arptype; - int err; - int fatal_err = 0; + int sock_fd = -1, arptype, val; + int err = 0; struct packet_mreq mr; + const char* device = handle->opt.source; - /* One shot loop used for error handling - bail out with break */ + /* + * Open a socket with protocol family packet. If a device is + * given we try to open it in raw mode otherwise we use + * the cooked interface. + */ + sock_fd = device ? + socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)) + : socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL)); - do { - /* - * Open a socket with protocol family packet. If a device is - * given we try to open it in raw mode otherwise we use - * the cooked interface. - */ - sock_fd = device ? - socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)) - : socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL)); + if (sock_fd == -1) { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "socket: %s", + pcap_strerror(errno) ); + return 0; /* try old mechanism */ + } - if (sock_fd == -1) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "socket: %s", - pcap_strerror(errno) ); - break; - } + /* It seems the kernel supports the new interface. */ + handle->md.sock_packet = 0; - /* 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); - /* - * 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", ebuf); + /* + * Default value for offset to align link-layer payload + * on a 4-byte boundary. + */ + handle->offset = 0; - /* - * 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 (device) { + /* Assume for now we don't need cooked mode. */ + handle->md.cooked = 0; - /* - * What kind of frames do we have to deal with? Fall back - * to cooked mode if we have an unknown interface type. - */ - - if (device) { - /* Assume for now we don't need cooked mode. */ - handle->md.cooked = 0; - - arptype = iface_get_arptype(sock_fd, device, ebuf); - if (arptype == -1) { - fatal_err = 1; - break; - } - 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(ebuf, PCAP_ERRBUF_SIZE, - "close: %s", pcap_strerror(errno)); - break; - } - sock_fd = socket(PF_PACKET, SOCK_DGRAM, - htons(ETH_P_ALL)); - if (sock_fd == -1) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, - "socket: %s", pcap_strerror(errno)); - break; - } - 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(ebuf, 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. */ - 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, ebuf); - if (handle->md.ifindex == -1) - break; - - if ((err = iface_bind(sock_fd, handle->md.ifindex, - ebuf)) < 0) { - if (err == -2) - fatal_err = 1; - break; - } - } else { + if (handle->opt.rfmon) { /* - * This is cooked mode. + * 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_wext(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; + } + } + 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)); + return PCAP_ERROR; + } handle->md.cooked = 1; - handle->linktype = DLT_LINUX_SLL; /* - * We're not bound to a device. - * XXX - true? Or true only if we're using - * the "any" device? - * For now, we're using this as an indication - * that we can't transmit; stop doing that only - * if we figure out how to transmit in cooked - * mode. + * Get rid of any link-layer type list + * we allocated - this only supports cooked + * capture. */ - 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. - */ - - if (device && 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(ebuf, PCAP_ERRBUF_SIZE, - "setsockopt: %s", pcap_strerror(errno)); - break; + 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; } - /* Save the socket FD in the pcap structure */ + handle->md.ifindex = iface_get_id(sock_fd, device, + handle->errbuf); + if (handle->md.ifindex == -1) { + close(sock_fd); + return PCAP_ERROR; + } - handle->fd = sock_fd; - - return 1; - - } while(0); - - if (sock_fd != -1) - close(sock_fd); - - if (fatal_err) { + 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 { /* - * Get rid of any link-layer type list we allocated. + * This is cooked mode. */ - if (handle->dlt_list != NULL) - free(handle->dlt_list); - return -2; - } else - return 0; + handle->md.cooked = 1; + handle->linktype = DLT_LINUX_SLL; + + /* + * We're not bound to a device. + * XXX - true? Or true only if we're using + * the "any" device? + * For now, we're using this as an indication + * that we can't transmit; stop doing that only + * if we figure out how to transmit in cooked + * mode. + */ + 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. + */ + + if (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; + + /* 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 " @@ -1600,6 +1914,488 @@ live_open_new(pcap_t *handle, const char *device, int promisc, #endif } +static int +activate_mmap(pcap_t *handle) +{ +#ifdef HAVE_PACKET_RING + int ret; + + 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 == 0) + return ret; + ret = create_ring(handle); + if (ret == 0) + return ret; + + /* 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->selectable_fd = handle->fd; + return 1; +#else /* HAVE_PACKET_RING */ + return 0; +#endif /* HAVE_PACKET_RING */ +} + +#ifdef HAVE_PACKET_RING +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; + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, + "can't get TPACKET_V2 header len on socket %d: %d-%s", + handle->fd, errno, pcap_strerror(errno)); + return 0; + } + 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 socket %d: %d-%s", + handle->fd, errno, pcap_strerror(errno)); + return 0; + } + 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 socket %d: %d-%s", + handle->fd, errno, pcap_strerror(errno)); + return 0; + } + +#endif /* HAVE_TPACKET2 */ + return 1; +} + +static void +compute_ring_block(int frame_size, unsigned *block_size, unsigned *frames_per_block) +{ + /* 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. */ + *block_size = getpagesize(); + while (*block_size < frame_size) + *block_size <<= 1; + + *frames_per_block = *block_size/frame_size; +} + +static int +create_ring(pcap_t *handle) +{ + unsigned i, j, ringsize, frames_per_block; + struct tpacket_req req; + + /* Note that with large snapshot (say 64K) only a few frames + * will be available in the ring even with pretty large ring size + * (and a lot of memory will be unused). + * The snap len should be carefully chosen to achive best + * performance */ + req.tp_frame_size = TPACKET_ALIGN(handle->snapshot + + TPACKET_ALIGN(handle->md.tp_hdrlen) + + sizeof(struct sockaddr_ll)); + req.tp_frame_nr = handle->opt.buffer_size/req.tp_frame_size; + compute_ring_block(req.tp_frame_size, &req.tp_block_size, &frames_per_block); + 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; + + /* ask the kernel to create the ring */ +retry: + if (setsockopt(handle->fd, SOL_PACKET, PACKET_RX_RING, + (void *) &req, sizeof(req))) { + /* try to reduce requested ring size to prevent memory failure */ + if ((errno == ENOMEM) && (req.tp_block_nr > 1)) { + req.tp_frame_nr >>= 1; + req.tp_block_nr = req.tp_frame_nr/frames_per_block; + goto retry; + } + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "can't create rx ring on " + "packet socket %d: %d-%s", handle->fd, errno, + pcap_strerror(errno)); + return 0; + } + + /* memory map the rx ring */ + ringsize = req.tp_block_nr * req.tp_block_size; + handle->bp = mmap(0, ringsize, PROT_READ| PROT_WRITE, MAP_SHARED, + handle->fd, 0); + if (handle->bp == MAP_FAILED) { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "can't mmap rx ring: %d-%s", + errno, pcap_strerror(errno)); + + /* clear the allocated ring on error*/ + destroy_ring(handle); + return 0; + } + + /* 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) { + destroy_ring(handle); + return 0; + } + + /* fill the header ring with proper frame ptr*/ + handle->offset = 0; + for (i=0; ibp[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->bp) { + /* need to re-compute the ring size */ + unsigned frames_per_block, block_size; + compute_ring_block(handle->bufsize, &block_size, &frames_per_block); + + /* do not perform sanity check here: we can't recover any error */ + munmap(handle->bp, block_size * handle->cc / frames_per_block); + handle->bp = 0; + } +} + +static void +pcap_cleanup_linux_mmap( pcap_t *handle ) +{ + destroy_ring(handle); + 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 */ + if (nonblock) { + if (p->md.timeout > 0) + p->md.timeout = p->md.timeout*-1 - 1; + } else + if (p->md.timeout < 0) + p->md.timeout = (p->md.timeout+1)*-1; + 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; +} + +static int +pcap_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, + u_char *user) +{ + int pkts = 0; + + /* wait for frames availability.*/ + if ((handle->md.timeout >= 0) && + !pcap_get_ring_frame(handle, TP_STATUS_USER)) { + struct pollfd pollinfo; + int ret; + + pollinfo.fd = handle->fd; + pollinfo.events = POLLIN; + + do { + /* poll() requires a negative timeout to wait forever */ + ret = poll(&pollinfo, 1, (handle->md.timeout > 0)? + handle->md.timeout: -1); + if ((ret < 0) && (errno != EINTR)) { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, + "can't poll on packet socket fd %d: %d-%s", + handle->fd, errno, pcap_strerror(errno)); + return -1; + } + /* check for break loop condition on interrupted syscall*/ + if (handle->break_loop) { + handle->break_loop = 0; + return -2; + } + } 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; + + /* check direction and interface index */ + sll = (void *)h.raw + TPACKET_ALIGN(handle->md.tp_hdrlen); + if ((sll->sll_ifindex == handle->md.lo_ifindex) && + (sll->sll_pkttype == PACKET_OUTGOING)) + 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) { + struct vlan_tag *tag; + + bp -= VLAN_TAG_LEN; + memmove(bp, bp + VLAN_TAG_LEN, 2 * ETH_ALEN); + + tag = (struct vlan_tag *)(bp + 2 * ETH_ALEN); + 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 + + /* 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 -2; + } + } + return pkts; +} + +static int +pcap_setfilter_linux_mmap(pcap_t *handle, struct bpf_program *filter) +{ + int n, offset; + int ret = pcap_setfilter_linux(handle, filter); + 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 @@ -1624,6 +2420,8 @@ iface_get_id(int fd, const char *device, char *ebuf) /* * 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) @@ -1638,9 +2436,20 @@ iface_bind(int fd, int ifindex, char *ebuf) sll.sll_protocol = htons(ETH_P_ALL); if (bind(fd, (struct sockaddr *) &sll, sizeof(sll)) == -1) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, - "bind: %s", pcap_strerror(errno)); - return -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? */ @@ -1648,251 +2457,815 @@ iface_bind(int fd, int ifindex, char *ebuf) if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "getsockopt: %s", pcap_strerror(errno)); - return -2; + return 0; } - if (err > 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 -2; + return 0; } + return 1; +} + +/* + * 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) +{ +#ifdef IW_MODE_MONITOR + 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; +#endif return 0; } -#endif +/* + * 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) +{ +#ifdef IW_MODE_MONITOR + /* + * 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; + 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 */ + /* + * 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 = 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) { + /* + * No private ioctls, so we assume that there's only one + * DLT_ for monitor mode. + */ + return 0; + } + if (errno != E2BIG) { + /* + * Failed. + */ + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, + "%s: SIOCGIWPRIV: %s", device, pcap_strerror(errno)); + return PCAP_ERROR; + } + 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 = 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. + */ + montype = MONITOR_WEXT; + cmd = 0; + 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, or 2 to get + * DLT_IEEE80211_RADIO_AVS. + */ + 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_clear |= 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, 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. + */ + 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: + /* + * Select the AVS header if we can, otherwise + * 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] = 2; /* request AVS header */ + memcpy(ireq.u.name, args, sizeof (int)); + if (ioctl(sock_fd, cmd, &ireq) == -1) { + /* + * Failure - try 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; + } + + /* + * Note that we have to put the old mode back when we + * close the device. + */ + handle->md.must_clear |= MUST_CLEAR_RFMON; + + /* + * Add this to the list of pcaps to close when we exit. + */ + pcap_add_to_pcaps_to_close(handle); + + return 1; +#else + /* + * We don't have the Wireless Extensions available, so we can't + * do monitor mode. + */ + return 0; +#endif +} + +#endif /* HAVE_PF_PACKET_SOCKETS */ /* ===== Functions to interface to the older kernels ================== */ /* - * 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. - */ - -/* - * List of pcaps for which we turned promiscuous mode on by hand. - * If there are any such pcaps, we arrange to call "pcap_close_all()" - * when we exit, and have it close all of them to turn promiscuous mode - * off. - */ -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); -} - -static void pcap_close_linux( pcap_t *handle ) -{ - struct pcap *p, *prevp; - struct ifreq ifr; - - if (handle->md.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 flags (SIOCGIFFLAGS failed: %s).\n" - "Please adjust manually.\n" - "Hint: This can't happen with Linux >= 2.2.0.\n", - 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 flags (SIOCSIFFLAGS failed: %s).\n" - "Please adjust manually.\n" - "Hint: This can't happen with Linux >= 2.2.0.\n", - strerror(errno)); - } - } - } - - /* - * Take this pcap out of the list of pcaps for which we - * have to take the interface out of promiscuous mode. - */ - for (p = pcaps_to_close, prevp = NULL; p != NULL; - prevp = p, p = p->md.next) { - if (p == handle) { - /* - * Found it. Remove it from the list. - */ - if (prevp == NULL) { - /* - * It was at the head of the list. - */ - pcaps_to_close = p->md.next; - } else { - /* - * It was in the middle of the list. - */ - prevp->md.next = p->md.next; - } - break; - } - } - } - - if (handle->md.device != NULL) - free(handle->md.device); - handle->md.device = NULL; - pcap_close_common(handle); -} - -/* - * Try to open a packet socket using the old kernel interface. - * Returns 0 on failure. - * FIXME: 0 uses to mean success (Sebastian) + * 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 -live_open_old(pcap_t *handle, const char *device, int promisc, - int to_ms, char *ebuf) +activate_old(pcap_t *handle) { int arptype; struct ifreq ifr; + const char *device = handle->opt.source; + struct utsname utsname; + int mtu; - do { - /* Open the socket */ + /* Open the socket */ - handle->fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL)); - if (handle->fd == -1) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, - "socket: %s", pcap_strerror(errno)); - break; + 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)); + return PCAP_ERROR_PERM_DENIED; + } + + /* 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 (!device) { + 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. + */ - /* 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 (!device) { - strncpy(ebuf, "pcap_open_live: The \"any\" device isn't supported on 2.0[.x]-kernel systems", - PCAP_ERRBUF_SIZE); - break; - } - if (iface_bind_old(handle->fd, device, ebuf) == -1) - break; - - /* - * Try to get the link-layer type. - */ - arptype = iface_get_arptype(handle->fd, device, ebuf); - if (arptype == -1) - break; - - /* - * Try to find the DLT_ type corresponding to that - * link-layer type. - */ - map_arphrd_to_dlt(handle, arptype, 0); - if (handle->linktype == -1) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, - "unknown arptype %d", arptype); - break; - } - - /* Go to promisc mode if requested */ - - if (promisc) { - memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); - if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, - "SIOCGIFFLAGS: %s", pcap_strerror(errno)); - break; + /* + * 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; } - 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 (!did_atexit) { - if (atexit(pcap_close_all) == -1) { - /* - * "atexit()" failed; don't - * put the interface in - * promiscuous mode, just - * give up. - */ - strncpy(ebuf, "atexit failed", - PCAP_ERRBUF_SIZE); - break; - } - did_atexit = 1; - } - - ifr.ifr_flags |= IFF_PROMISC; - if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, - "SIOCSIFFLAGS: %s", - pcap_strerror(errno)); - break; - } - handle->md.clear_promisc = 1; - - /* - * Add this to the list of pcaps - * to close when we exit. - */ - handle->md.next = pcaps_to_close; - pcaps_to_close = handle; + 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_clear |= 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) { /* - * Default value for offset to align link-layer payload - * on a 4-byte boundary. + * 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. */ - handle->offset = 0; + 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; + } - return 1; + /* + * Default value for offset to align link-layer payload + * on a 4-byte boundary. + */ + handle->offset = 0; - } while (0); - - pcap_close_linux(handle); - return 0; + return 1; } /* @@ -1971,7 +3344,13 @@ iface_get_arptype(int fd, const char *device, char *ebuf) if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCGIFHWADDR: %s", pcap_strerror(errno)); - return -1; + if (errno == ENODEV) { + /* + * No such device. + */ + return PCAP_ERROR_NO_SUCH_DEVICE; + } + return PCAP_ERROR; } return ifr.ifr_hwaddr.sa_family; @@ -1995,7 +3374,7 @@ fix_program(pcap_t *handle, struct sock_fprog *fcode) len = handle->fcode.bf_len; f = (struct bpf_insn *)malloc(prog_size); if (f == NULL) { - snprintf(handle->errbuf, sizeof(handle->errbuf), + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); return -1; } @@ -2167,7 +3546,7 @@ set_kernel_filter(pcap_t *handle, struct sock_fprog *fcode) if (save_errno != EAGAIN) { /* Fatal error */ reset_kernel_filter(handle); - snprintf(handle->errbuf, sizeof(handle->errbuf), + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "recv: %s", pcap_strerror(save_errno)); return -2; } diff --git a/libpcap/pcap-namedb.h b/libpcap/pcap-namedb.h index acaabd963..80a2f0040 100644 --- a/libpcap/pcap-namedb.h +++ b/libpcap/pcap-namedb.h @@ -30,60 +30,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#) $Header: /tcpdump/master/libpcap/pcap-namedb.h,v 1.10.2.1 2005/04/19 04:26:08 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/pcap-namedb.h,v 1.13 2006/10/04 18:13:32 guy Exp $ (LBL) */ -#ifndef lib_pcap_namedb_h -#define lib_pcap_namedb_h - -#ifdef __cplusplus -extern "C" { -#endif - /* - * As returned by the pcap_next_etherent() - * XXX this stuff doesn't belong in this interface, but this - * library already must do name to address translation, so - * on systems that don't have support for /etc/ethers, we - * export these hooks since they'll + * For backwards compatibility. + * + * Note to OS vendors: do NOT get rid of this file! Some applications + * might expect to be able to include . */ -struct pcap_etherent { - u_char addr[6]; - char name[122]; -}; -#ifndef PCAP_ETHERS_FILE -#define PCAP_ETHERS_FILE "/etc/ethers" -#endif -struct pcap_etherent *pcap_next_etherent(FILE *); -u_char *pcap_ether_hostton(const char*); -u_char *pcap_ether_aton(const char *); - -bpf_u_int32 **pcap_nametoaddr(const char *); -#ifdef INET6 -struct addrinfo *pcap_nametoaddrinfo(const char *); -#endif -bpf_u_int32 pcap_nametonetaddr(const char *); - -int pcap_nametoport(const char *, int *, int *); -int pcap_nametoportrange(const char *, int *, int *, int *); -int pcap_nametoproto(const char *); -int pcap_nametoeproto(const char *); -int pcap_nametollc(const char *); -/* - * If a protocol is unknown, PROTO_UNDEF is returned. - * Also, pcap_nametoport() returns the protocol along with the port number. - * If there are ambiguous entried in /etc/services (i.e. domain - * can be either tcp or udp) PROTO_UNDEF is returned. - */ -#define PROTO_UNDEF -1 - -/* XXX move these to pcap-int.h? */ -int __pcap_atodn(const char *, bpf_u_int32 *); -int __pcap_atoin(const char *, bpf_u_int32 *); -u_short __pcap_nametodnaddr(const char *); - -#ifdef __cplusplus -} -#endif - -#endif +#include diff --git a/libpcap/pcap-nit.c b/libpcap/pcap-nit.c index 94c452884..ed042089a 100644 --- a/libpcap/pcap-nit.c +++ b/libpcap/pcap-nit.c @@ -20,7 +20,7 @@ */ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.57.2.1 2005/05/03 18:54:37 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.58.2.4 2008-04-14 20:41:52 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -99,7 +99,6 @@ static int pcap_read_nit(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { register int cc, n; - register struct bpf_insn *fcode = p->fcode.bf_insns; register u_char *bp, *cp, *ep; register struct nit_hdr *nh; register int caplen; @@ -175,13 +174,13 @@ pcap_read_nit(pcap_t *p, int cnt, pcap_handler callback, u_char *user) caplen = nh->nh_wirelen; if (caplen > p->snapshot) caplen = p->snapshot; - if (bpf_filter(fcode, cp, nh->nh_wirelen, caplen)) { + 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) { + if (++n >= cnt && cnt > 0) { p->cc = ep - bp; p->bp = bp; return (n); @@ -238,51 +237,43 @@ nit_setflags(int fd, int promisc, int to_ms, char *ebuf) return (0); } -static void -pcap_close_nit(pcap_t *p) -{ - pcap_close_common(p); - if (p->device != NULL) - free(p->device); -} - -pcap_t * -pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, - char *ebuf) +static int +pcap_activate_nit(pcap_t *p) { int fd; struct sockaddr_nit snit; - register pcap_t *p; - p = (pcap_t *)malloc(sizeof(*p)); - if (p == NULL) { - strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); - return (NULL); + 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 (snaplen < 96) + if (p->snapshot < 96) /* * NIT requires a snapshot length of at least 96. */ - snaplen = 96; + p->snapshot = 96; memset(p, 0, sizeof(*p)); p->fd = fd = socket(AF_NIT, SOCK_RAW, NITPROTO_RAW); if (fd < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "socket: %s", pcap_strerror(errno)); goto bad; } snit.snit_family = AF_NIT; - (void)strncpy(snit.snit_ifname, device, NITIFSIZ); + (void)strncpy(snit.snit_ifname, p->opt.source, NITIFSIZ); if (bind(fd, (struct sockaddr *)&snit, sizeof(snit))) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "bind: %s: %s", snit.snit_ifname, pcap_strerror(errno)); goto bad; } - p->snapshot = snaplen; - nit_setflags(p->fd, promisc, to_ms, ebuf); + nit_setflags(p->fd, p->opt.promisc, p->md.timeout, p->errbuf); /* * NIT supports only ethernets. @@ -292,17 +283,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, p->bufsize = BUFSPACE; p->buffer = (u_char *)malloc(p->bufsize); if (p->buffer == NULL) { - strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); - goto bad; - } - - /* - * We need the device name in order to send packets. - */ - p->device = strdup(device); - if (p->device == NULL) { - strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); - free(p->buffer); + strlcpy(p->errbuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); goto bad; } @@ -339,14 +320,23 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; p->stats_op = pcap_stats_nit; - p->close_op = pcap_close_nit; - return (p); + return (0); bad: - if (fd >= 0) - close(fd); - free(p); - return (NULL); + return (PCAP_ERROR); +} + +pcap_t * +pcap_create(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 diff --git a/libpcap/pcap-nit.h b/libpcap/pcap-nit.h deleted file mode 100644 index 52f5fc4bd..000000000 --- a/libpcap/pcap-nit.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 1990, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Lawrence Berkeley Laboratory, - * Berkeley, CA. The name of the University 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 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * @(#) $Header: /tcpdump/master/libpcap/pcap-nit.h,v 1.2.1.1 1999/10/07 23:46:40 mcr Exp $ (LBL) - */ diff --git a/libpcap/pcap-null.c b/libpcap/pcap-null.c index 06e3ab3ac..f72a0c3c4 100644 --- a/libpcap/pcap-null.c +++ b/libpcap/pcap-null.c @@ -20,7 +20,7 @@ */ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-null.c,v 1.21 2003/11/15 23:24:03 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-null.c,v 1.21.4.1 2008-04-04 19:39:06 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -40,10 +40,9 @@ static const char rcsid[] _U_ = static char nosup[] = "live packet capture not supported on this system"; pcap_t * -pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, - char *ebuf) +pcap_activate(pcap_t *p) { - (void)strlcpy(ebuf, nosup, PCAP_ERRBUF_SIZE); + (void)strlcpy(p->errbuf, nosup, PCAP_ERRBUF_SIZE); return (NULL); } diff --git a/libpcap/pcap-pf.c b/libpcap/pcap-pf.c index e7335404e..be9381440 100644 --- a/libpcap/pcap-pf.c +++ b/libpcap/pcap-pf.c @@ -24,7 +24,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.91.2.2 2005/05/03 18:54:37 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.94.2.3 2008-04-14 20:41:52 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -62,7 +62,7 @@ struct rtentry; #include /* - * Make "pcap.h" not include "pcap-bpf.h"; we are going to include the + * 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 @@ -88,7 +88,6 @@ static int pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user) { register u_char *p, *bp; - struct bpf_insn *fcode; register int cc, n, buflen, inc; register struct enstamp *sp; #ifdef LBL_ALIGN @@ -98,7 +97,6 @@ pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user) register int pad; #endif - fcode = pc->md.use_bpf ? NULL : pc->fcode.bf_insns; again: cc = pc->cc; if (cc == 0) { @@ -187,7 +185,8 @@ pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user) /* * Short-circuit evaluation: if using BPF filter - * in kernel, no need to do it now. + * 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 @@ -197,8 +196,8 @@ pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user) * skipping that padding. #endif */ - if (fcode == NULL || - bpf_filter(fcode, p, sp->ens_count, buflen)) { + 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; @@ -285,30 +284,21 @@ pcap_stats_pf(pcap_t *p, struct pcap_stat *ps) } /* - * We include the OS's , not our "pcap-bpf.h", so we probably + * 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 -pcap_t * -pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, - char *ebuf) +static int +pcap_activate_pf(pcap_t *p) { - pcap_t *p; short enmode; int backlog = -1; /* request the most */ struct enfilter Filter; struct endevp devparams; - p = (pcap_t *)malloc(sizeof(*p)); - if (p == NULL) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, - "pcap_open_live: %s", pcap_strerror(errno)); - return (0); - } - memset(p, 0, sizeof(*p)); /* * Initially try a read/write open (to allow the inject * method to work). If that fails due to permission @@ -328,21 +318,21 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, * "const char *" as its first argument. That appears to be * the case, at least on Digital UNIX 4.0. */ - p->fd = pfopen(device, O_RDWR); + p->fd = pfopen(p->opt.source, O_RDWR); if (p->fd == -1 && errno == EACCES) - p->fd = pfopen(device, O_RDONLY); + p->fd = pfopen(p->opt.source, O_RDONLY); if (p->fd < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "pf open: %s: %s\n\ + 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", - device, pcap_strerror(errno)); + p->opt.source, pcap_strerror(errno)); goto bad; } p->md.OrigMissed = -1; enmode = ENTSTAMP|ENBATCH|ENNONEXCL; - if (promisc) + if (p->opt.promisc) enmode |= ENPROMISC; if (ioctl(p->fd, EIOCMBIS, (caddr_t)&enmode) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCMBIS: %s", + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCMBIS: %s", pcap_strerror(errno)); goto bad; } @@ -353,13 +343,13 @@ your system may not be properly configured; see the packetfilter(4) man page\n", #endif /* set the backlog */ if (ioctl(p->fd, EIOCSETW, (caddr_t)&backlog) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCSETW: %s", + 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(ebuf, PCAP_ERRBUF_SIZE, "EIOCDEVP: %s", + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCDEVP: %s", pcap_strerror(errno)); goto bad; } @@ -441,8 +431,8 @@ your system may not be properly configured; see the packetfilter(4) man page\n", * framing", there's not much we can do, as that * doesn't specify a particular type of header. */ - snprintf(ebuf, PCAP_ERRBUF_SIZE, "unknown data-link type %u", - devparams.end_dev_type); + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "unknown data-link type %u", devparams.end_dev_type); goto bad; } /* set truncation */ @@ -451,32 +441,31 @@ your system may not be properly configured; see the packetfilter(4) man page\n", p->fddipad = PCAP_FDDIPAD; /* packetfilter includes the padding in the snapshot */ - snaplen += PCAP_FDDIPAD; + p->snapshot += PCAP_FDDIPAD; } else p->fddipad = 0; #endif - if (ioctl(p->fd, EIOCTRUNCATE, (caddr_t)&snaplen) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCTRUNCATE: %s", + if (ioctl(p->fd, EIOCTRUNCATE, (caddr_t)&p->snapshot) < 0) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCTRUNCATE: %s", pcap_strerror(errno)); goto bad; } - p->snapshot = snaplen; /* 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(ebuf, PCAP_ERRBUF_SIZE, "EIOCSETF: %s", + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCSETF: %s", pcap_strerror(errno)); goto bad; } - if (to_ms != 0) { + if (p->md.timeout != 0) { struct timeval timeout; - timeout.tv_sec = to_ms / 1000; - timeout.tv_usec = (to_ms * 1000) % 1000000; + 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(ebuf, PCAP_ERRBUF_SIZE, "EIOCSRTIMEOUT: %s", + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCSRTIMEOUT: %s", pcap_strerror(errno)); goto bad; } @@ -485,7 +474,7 @@ your system may not be properly configured; see the packetfilter(4) man page\n", p->bufsize = BUFSPACE; p->buffer = (u_char*)malloc(p->bufsize + p->offset); if (p->buffer == NULL) { - strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); + strlcpy(p->errbuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); goto bad; } @@ -502,19 +491,23 @@ your system may not be properly configured; see the packetfilter(4) man page\n", p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; p->stats_op = pcap_stats_pf; - p->close_op = pcap_close_common; - return (p); + return (0); bad: - if (p->fd >= 0) - close(p->fd); - /* - * Get rid of any link-layer type list we allocated. - */ - if (p->dlt_list != NULL) - free(p->dlt_list); - free(p); - return (NULL); + return (PCAP_ERROR); +} + +pcap_t * +pcap_create(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 diff --git a/libpcap/pcap-pf.h b/libpcap/pcap-pf.h deleted file mode 100644 index 60bea83a7..000000000 --- a/libpcap/pcap-pf.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 1990, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Lawrence Berkeley Laboratory, - * Berkeley, CA. The name of the University 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 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * @(#) $Header: /tcpdump/master/libpcap/pcap-pf.h,v 1.2.1.1 1999/10/07 23:46:40 mcr Exp $ (LBL) - */ diff --git a/libpcap/pcap-savefile.manfile.in b/libpcap/pcap-savefile.manfile.in new file mode 100644 index 000000000..3b9503fd2 --- /dev/null +++ b/libpcap/pcap-savefile.manfile.in @@ -0,0 +1,127 @@ +'\" t +.\" @(#) $Header: /tcpdump/master/libpcap/pcap-savefile.manfile.in,v 1.1.2.3 2008-10-24 07:34:06 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-SAVEFILE @MAN_FILE_FORMATS@ "21 October 2008" +.SH NAME +pcap-savefile \- libpcap savefile format +.SH DESCRIPTION +NOTE: applications and libraries should, if possible, use libpcap to +read savefiles, rather than having their own code to read savefiles. +If, in the future, a new file format is supported by libpcap, +applications and libraries using libpcap to read savefiles will be able +to read the new format of savefiles, but applications and libraries +using their own code to read savefiles will have to be changed to +support the new file format. +.PP +``Savefiles'' read and written by libpcap and applications using libpcap +start with a per-file header. The format of the per-file header is: +.RS +.TS +box; +c s +c | c +c s. +Magic number +_ +Major version Minor version +_ +Time zone offset +_ +Time stamp accuracy +_ +Snapshot length +_ +Link-layer header type +.TE +.RE +.PP +All fields in the per-file header are in the byte order of the host +writing the file. The first field in the per-file header is a 4-byte +magic number, with the value 0xa1b2c3d4. The magic number, when read by +a host with the same byte order as the host that wrote the file, will +have the value 0xa1b2c3d4, and, when read by a host with the opposite +byte order as the host that wrote the file, will have the value +0xd4c3b2a1. That allows software reading the file to determine whether +the byte order of the host that wrote the file is the same as the byte +order of the host on which the file is being read, and thus whether the +values in the per-file and per-packet headers need to be byte-swapped. +.PP +Following this are: +.IP +A 2-byte file format major version number; the current version number is +2. +.IP +A 2-byte file format minor version number; the current version number is +4. +.IP +A 4-byte time zone offset; this is always 0. +.IP +A 4-byte number giving the accuracy of time stamps in the file; this is +always 0. +.IP +A 4-byte number giving the "snapshot length" of the capture; packets +longer than the snapshot length are truncated to the snapshot length, so +that, if the snapshot length is +.IR N , +only the first +.I N +bytes of a packet longer than +.I N +bytes will be saved in the capture. +.IP +a 4-byte number giving the link-layer header type for packets in the +capture; see +.BR pcap-linktype (@MAN_MISC_INFO@) +for the +.B LINKTYPE_ +values that can appear in this field. +.PP +Following the per-file header are zero or more packets; each packet +begins with a per-packet header, which is immediately followed by the +raw packet data. The format of the per-packet header is: +.RS +.TS +box; +c. +Time stamp, seconds value +_ +Time stamp, microseconds value +_ +Length of captured packet data +_ +Un-truncated length of the packet data +.TE +.RE +.PP +All fields in the per-packet header are in the byte order of the host +writing the file. The per-packet header begins with a time stamp giving +the approximate time the packet was captured; the time stamp consists of +a 4-byte value, giving the time in seconds since January 1, 1970, +00:00:00 UTC, followed by a 4-byte value, giving the time in +microseconds since that second. Following that are a 4-byte value +giving the number of bytes of captured data that follow the per-packet +header and a 4-byte value giving the number of bytes that would have +been present had the packet not been truncated by the snapshot length. +The two lengths will be equal if the number of bytes of packet data are +less than or equal to the snapshot length. +.SH SEE ALSO +pcap(3PCAP), pcap-linktype(@MAN_MISC_INFO@) diff --git a/libpcap/pcap-septel.c b/libpcap/pcap-septel.c index 5169ec063..c0473bbb9 100644 --- a/libpcap/pcap-septel.c +++ b/libpcap/pcap-septel.c @@ -16,7 +16,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-septel.c,v 1.1.2.2 2005/06/21 01:03:23 guy Exp $"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-septel.c,v 1.2.2.2 2008-04-14 20:41:52 guy Exp $"; #endif #ifdef HAVE_CONFIG_H @@ -50,8 +50,8 @@ static const char rcsid[] _U_ = /* This code is required when compiling for a Septel device only. */ #include "pcap-septel.h" -/* Replace dag function names with pcap equivalent. */ -#define septel_open_live pcap_open_live +/* Replace septel function names with pcap equivalent. */ +#define septel_create pcap_create #define septel_platform_finddevs pcap_platform_finddevs #endif /* SEPTEL_ONLY */ @@ -59,12 +59,6 @@ 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); -static void septel_platform_close(pcap_t *p) { - -} - - - /* * 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 @@ -199,28 +193,14 @@ septel_inject(pcap_t *handle, const void *buf _U_, size_t size _U_) } /* - * Get a handle for a live capture from the given Septel device. Always pass a NULL device + * 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 to_ms parameter is also ignored as it is - * not supported in hardware. + * The timeout is also ignored as it is not supported in hardware. * * See also pcap(3). */ -pcap_t *septel_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf) { - pcap_t *handle; - - handle = malloc(sizeof(*handle)); - if (handle == NULL) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc %s: %s", device, pcap_strerror(errno)); - return NULL; - } - - /* Initialize some components of the pcap structure. */ - - memset(handle, 0, sizeof(*handle)); - - handle->snapshot = snaplen; - +static pcap_t *septel_activate(pcap_t* handle) { + /* Initialize some components of the pcap structure. */ handle->linktype = DLT_MTP2; handle->bufsize = 0; @@ -237,16 +217,19 @@ pcap_t *septel_open_live(const char *device, int snaplen, int promisc, int to_ms handle->getnonblock_op = pcap_getnonblock_fd; handle->setnonblock_op = septel_setnonblock; handle->stats_op = septel_stats; - handle->close_op = septel_platform_close; - return handle; + return 0; +} -fail: - if (handle != NULL) { - free(handle); - } +pcap_t *septel_create(const char *device, char *ebuf) { + pcap_t *p; - return NULL; + 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) { diff --git a/libpcap/pcap-septel.h b/libpcap/pcap-septel.h index 1de6377a1..c91679768 100644 --- a/libpcap/pcap-septel.h +++ b/libpcap/pcap-septel.h @@ -8,8 +8,8 @@ * Authors: Gilbert HOYEK (gil_hoyek@hotmail.com), Elias M. KHOURY * (+961 3 485343); * - * @(#) $Header: /tcpdump/master/libpcap/pcap-septel.h,v 1.1.2.1 2005/06/20 21:30:19 guy Exp $ + * @(#) $Header: /tcpdump/master/libpcap/pcap-septel.h,v 1.1.4.1 2008-04-04 19:39:06 guy Exp $ */ -pcap_t *septel_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf); +pcap_t *septel_create(const char *device, char *ebuf); diff --git a/libpcap/pcap-sita.c b/libpcap/pcap-sita.c new file mode 100644 index 000000000..971f8b03a --- /dev/null +++ b/libpcap/pcap-sita.c @@ -0,0 +1,980 @@ +/* + * 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 */ + } +} + +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)); + } + ip = u->ip; + bzero((char *)u->serv_addr, 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)); + + iface->iftype = iftype; /* remember the interface type of this interface */ + + name = malloc(strlen(IOPname) + 1); /* get memory for the IOP's name */ + 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 */ + 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)); + 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)); + 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)); + 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)); + 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)); + 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)); + 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); + 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 *p; + + p = pcap_create_common(device, ebuf); + if (p == NULL) + return (NULL); + + p->activate_op = pcap_activate_sita; + return (p); +} diff --git a/libpcap/pcap-sita.h b/libpcap/pcap-sita.h new file mode 100644 index 000000000..b232ee2c3 --- /dev/null +++ b/libpcap/pcap-sita.h @@ -0,0 +1,10 @@ +/* + * pcap-sita.h: Packet capture interface for SITA WAN devices + * + * Authors: Fulko Hew (fulko.hew@sita.aero) (+1 905 6815570); + * + * @(#) $Header: /tcpdump/master/libpcap/pcap-sita.h + */ + +extern int acn_parse_hosts_file(char *errbuf); +extern int acn_findalldevs(char *errbuf); diff --git a/libpcap/pcap-sita.html b/libpcap/pcap-sita.html new file mode 100644 index 000000000..5f7884f99 --- /dev/null +++ b/libpcap/pcap-sita.html @@ -0,0 +1,943 @@ + + + + + + + + +
+ A "Distributed Pcap" for
Remote Monitoring LANs & WANs

+ (Design Notes for the SITA ACN device)
+
+ Fulko Hew
SITA INC Canada, Inc.
Revised: October 2, 2007 +
+ + +

SUMMARY

+
    + Note: This document is part of the libpcap CVS and was derived from 'pcap.3' (circa Aug/07). +

    + The ACN provides a customized/distributed version of this library that alows SMPs to + interact with the various IOPs within the site providing a standard mechanism + to capture LAN and WAN message traffic. +

    +

    + + + + + + + + + +
    SMPThe Supervisory Management Processor where Wireshark (or equivalent) + runs in conjuction with a libpcap front-end.
    IOPI/O Processors where the monitored ports exist in conjunction + with a custom device driver/libpcap back-end.
    +
    +

    + Each IOP will be capable of supporting multiple connections from an SMP + enabling monitoring of more than one interface at a time, each through + its own seperate connection. The IOP is responsible to ensure and report + an error if any attempt is made to monitor the same interface more than once. +

    + There are three applications that will be supported by the ACN version of libpcap. + They each use a slightly different mode for looping/capturing and termination + as summarized in the following table: +

    +

    + + + + + + + + + + + + + + +
    Application Capture Termination
    wiresharkpcap_dispatch(all packets in one buffer of capture only)pcap_breakloop()
    tsharkpcap_dispatch(one buffer of capture only)Since a CTRL-C was used to terminate the application, pcap_breakloop() is never called.
    tcpdumppcap_loop(all packets in the next buffer, and loop forever)pcap_breakloop()
    +
    +

    + Note: In all cases, the termination of capturing is always (apparently) followed by + pcap_close(). Pcap_breakloop() is only used to stop/suspend looping/processing, + and upon close interpretation of the function definitions, it is possible to resume + capturing following a pcap_breakloop() without any re-initialization. +

    +

    ACN Limitations

    +
      +
    1. Monitoring of backup IOPs is not currently supported. +
    2. Ethernet interfaces cannot be monitored in promiscuous mode. +
    + +
+ +

ROUTINES

+
    + The following list of functions is the sub-set of Pcap functions that have been + altered/enhanced to support the ACN remote monitoring facility. The remainder of the Pcap + functions continue to perform their duties un-altered. Libpcap only supports this + mode of operation if it has been configured/compiled for SITA/ACN support. +

    +

      + pcap_findalldevs
      + pcap_freealldevs
      + pcap_open_live
      + pcap_close
      + pcap_setfilter
      + pcap_dispatch
      + pcap_loop
      + pcap_next
      + pcap_next_ex
      + pcap_stats
      +
    + + These subroutines have been modified for the ACN specific distributed and remote monitoring + ability perform the following basic functions. More detail is provided in the + "SMP/IOP Inter-Process Communication Protocol" section. +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    pcap_open_live()Used to obtain a packet capture descriptor to look at packets on the network.
    + + + + + + +
    SMP -> IOP + The SMP will open a connection to the selected IOP on its 'sniffer' port + to ensure it is available. It sends a null terminated string identifying + the interface to be monitored. +
    IOP -> SMP + After any required processing is complete, the IOP will return a + null terminated string containing an error message if one occured. + If no error occured, a empty string is still returned. + Errors are: +
      +
    • "Interface (xxx) does not exist." +
    • "Interface (xxx) not configured." +
    • "Interface (xxx) already being monitored." +
    +
    pcap_findalldevs()It constructs a list of network devices that can be opened with pcap_open_live().
    + + + + + + + + + + + + + + + +
    SMP + It obtains a list of IOPs currently available (via /etc/hosts). +
    SMP -> IOP + The SMP will sequentially open a connection to each IOP on its 'sniffer' port to ensure + the IOP is available. + It sends a null terminated empty interface ID followed by the query request command. +
    IOP -> SMPThe IOP returns an error response and its list of devices. +
    SMP -> IOP + The SMP closes the TCP connection with each IOP. +
    SMP + The SMP adds the received information to its internal structure. +
    pcap_freealldevs()Used to free a list allocated by pcap_findalldevs().
    + + + +
    SMP + The SMP frees the structure it built as a result of the previous + invocation of pcap_findalldevs(). +
    pcap_dispatch()Used to collect and process packets.
    + + + + + + + + + + + + +
    SMP -> IOP + On the first invocation of pcap_dispatch(), pcap_loop(), or pcap_next(), or pcap_next_ex() following a pcap_open_live(), + the SMP will pass down the monitor start command and various parameters the IOP should use. +
    IOP -> SMP + The IOP now sends a stream of captured data. +
    SMP + The SMP will read the reverse channel of the connection between the SMP and the + IOP that provides the captured data (via 'p->read_op' which is 'pcap_read_linux()' + until the select() call returns a 'no more data' indication. + It will the process (at most) the next 'cnt' packets and invoke the specified + callback function for each packet processed. +
    IOP + The IOP continues to listen for additional commands as well as capturing and forwarding data to the SMP. +
    pcap_loop() + Is similar to pcap_dispatch() except it keeps reading packets until + the requested number of packets are processed or an error occurs. +
    + + + + + + + + + + + + +
    SMP -> IOP + On the first invocation of pcap_dispatch(), pcap_loop(), or pcap_next(), or pcap_next_ex() following a pcap_open_live(), + the SMP will pass down the monitor start command and various parameters the IOP should use. +
    IOP -> SMP + The IOP now sends a stream of captured data. +
    SMP + The SMP continuously reads the next packet from the reverse channel of the connection + between the SMP and the IOP that provides the captured data (via 'p->read_op' + which is 'pcap_read_linux()' until 'cnt' packets have been received. + The specified callback function will be invoked for each packet received. +
    IOP + The IOP continues to listen for additional commands as well as capturing and forwarding data to the SMP. +
    pcap_next() + It reads the next packet (by calling pcap_dispatch() with a count of 1) + and returns a pointer to the data in that packet. +
    + + + + + + + + + + + + +
    SMP -> IOP + On the first invocation of pcap_dispatch(), pcap_loop(), or pcap_next(), or pcap_next_ex() following a pcap_open_live(), + the SMP will pass down the monitor start command and various parameters the IOP should use. +
    IOP -> SMP + The IOP now sends a stream of captured data. +
    SMP + The SMP reads only the next packet from the reverse channel of the connection + between the SMP and the IOP that provides the captured data (via calling pcap_dispatch() + with a count of 1) and returns a pointer to that data by invoking an internal callback. +
    IOP + The IOP continues to listen for additional commands as well as capturing and forwarding data to the SMP. +
    pcap_next_ex()Reads the next packet and returns a success/failure indication.
    + + + + + + + + + + + + +
    SMP -> IOP + On the first invocation of pcap_dispatch(), pcap_loop(), or pcap_next(), or pcap_next_ex() following a pcap_open_live(), + the SMP will pass down the monitor start command and various parameters the IOP should use. +
    IOP -> SMP + The IOP now sends a stream of captured data. +
    SMP + The SMP reads only the next packet from the reverse channel of the connection + between the SMP and the IOP that provides the captured data (via calling pcap_dispatch() + with a count of 1) and returns seperate pointers to both the + packet header and packet data by invoking an internal callback. +
    IOP + The IOP continues to listen for additional commands as well as capturing and forwarding data to the SMP. +
    pcap_setfilter()Used to specify a filter program.
    + + + + + + +
    SMP -> IOP + The SMP sends a 'set filter' command followed by the BPF commands. +
    IOP -> SMP + The IOP returns a null terminated error string if it failed to accept the filter. + If no error occured, then a NULL terminated empty string is returned instead. + Errors are: +
      +
    • "Invalid BPF." +
    • "Insufficient resources for BPF." +
    +
    pcap_stats()Fills in a pcap_stat struct with packet statistics.
    + + + + + + + + + +
    SMP -> IOP + The SMP sends a message to the IOP requesting its statistics. +
    IOP -> SMP + The IOP returns the statistics. +
    SMP + The SMP fills in the structure provided with the information retrieved from the IOP. +
    pcap_close()Closes the file and deallocates resources.
    + + + + + + +
    SMP -> IOP + The SMP closes the file descriptor, and if the descriptor is that of + the comminucation session with an IOP, it too is terminated. +
    IOP + If the IOP detects that its communication session with an SMP + has closed, it will terminate any monitoring in progress, + release any resources and close its end of the session. + It will not maintain persistance of any information or prior mode of operation. +
    +

+ +

+

SMP/IOP Inter-Process Communication Protocol

+ +
    +
  • Communications between an SMP and an IOP consists of a TCP session + between an ephemeral port on the SMP and the well known port of 49152 + (which is the first available port in the 'dynamic and/or private port' + range) on an IOP. +

  • Following a TCP open operation the IOP receives a null terminated + 'interface ID' string to determine the type of operation that follows: +

  • Every command received by an IOP implies a 'stop trace/stop forwarding' operation must + occur before executing the received command. +

  • A session is closed when the SMP closes the TCP session with the IOP. + Obviously monitoring and forwarding is also stopped at that time. + + Note: All multi-octet entities are sent in network neutral order. +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    pcap_findalldevs()SMP -> IOPOpen socket (to each IOP), and sends: +

    + + + + + + + + + + + +
    Name/
    Purpose
    Size
    (in bytes)
    Description
    Interface ID1A NULL to indicate an an empty 'interface ID'.
    +

    IOP -> SMPSend its (possibly empty) NULL terminated error response string.
    SMP -> IOPSends the 'interface query request': +

    + + + + + + + + + + + +
    Name/
    Purpose
    Size
    (in bytes)
    Description
    Interface ID1A 'Q' (indicating 'interface query request').
    +

    IOP -> SMPThe IOP returns a list of sequences of information as + defined by the return parameter of this function call (as shown in the following table). + Elements are specified by providing an unsigned byte preceeding the actual data that contains length information. +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Notes:Name/
    Purpose
    Size
    (in bytes)
    Description
     length1The number of octets in the name field that follows.
    Name1-255The name of the interface. The format of the name is an alphabetic string (indicating + the type of interface) followed by an optional numeric string (indicating the interface's + sequence number). + Sequence numbers (if needed) will begin at zero and progress monotonically upwards. + (i.e. 'eth0', 'lo', 'wan0', etc.) +

    + For an IOP, the alphabetic string will be one of: 'eth', 'wan', and 'lo' + for Ethernet, WAN ports and the IP loopback device respectively. + An IOP currently supports: 'eth0', 'eth1', 'lo', 'wan0' ... 'wan7'. +

    + Note: IOPs and ACNs will not currently support the concept of 'any' interface.

    length1The number of octets in the interface description field that follows.
    Interface Description0-255A description of the interface or it may be an empty string. (i.e. 'ALC')
    Interface Type4The type of interface as defined in the description for pcap_datalink() (in network neutral order).
    Loopback Flag11 = if the interface is a loopback interface, zero = otherwise.
    count1# of address entries that follow. + Each entry is a series of bytes in network neutral order. + See the parameter definition above for more details.
    Repeated 'count' number of times.length1The number of octets in the address field that follows.
    Address1-255The address of this interface (in network neutral order).
    length1The number of octets in the netmask field that follows.
    Network Mask0-255The network mask used on this interface (if applicable) (in network neutral order).
    length1The number of octets in the broadcast address field that follows.
    Broadcast Address0-255The broadcast address of this interface (if applicable) (in network neutral order).
    length1The number of octets in the destination address field that follows.
    Destination Address0-255The destination address of this interface (if applicable) (in network neutral order).
    +

    SMP -> IOPClose the socket.
    IOP -> SMPClose the socket.

    pcap_open_live()SMP -> IOPOpen socket, and sends: +

    + + + + + + + + + + + +
    Name/
    Purpose
    Size
    (in bytes)
    Description
    Interface ID'n''n' octets containing a NULL terminated interface name string.
    +

    IOP -> SMPSend its NULL terminated error response string.

    pcap_dispatch()
    pcap_loop()
    pcap_next()
    pcap_next_ex()
    SMP -> IOPOn the first invocation following a pcap_open_live() or pcap_breakloop() additional information is sent: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Name/
    Purpose
    Size
    (in bytes)
    Description
    command1'M' (indicating 'monitor start')
    snaplen4snaplen
    timeout1timeout value (in milliseconds)
    promiscuous1A flag indicating that the interface being monitored show operate + in promiscuous mode. [off(0) / on(NZ)]
    direction1A flag indicating the direction of traffic that should be captuted [both(0) / in(1) / out(2)]
    +

    IOP -> SMPSends captured packets.

    pcap_setfilter()SMP -> IOPAt any time, the SMP can issue a set filter command which contains + an indicator, a count of the number of statements in the filter, + followed by the sequence of filter commands represented as a sequence + of C-style structures. +

    + + + + + + + + + + + + + + + + + + + + + +
    Name/
    Purpose
    Size
    (in bytes)
    Description
    command1'F' (indicating 'filter')
    count4The number of command in the Berkeley Packet Filter that follow.
    BPF program'n'8 bytes of each command (repeated 'n' times).
    + Each command consists of that C-style structure which contains: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Name/
    Purpose
    Size
    (in bytes)
    Description
    opcode2The command's opcode.
    'jt'1The 'jump if true' program counter offset.
    'jf'1The 'jump if false' program counter offset.
    'k'4The 'other' data field.
    +

    + Refer to the bpf(4) man page for more details. +

    +

    IOP -> SMPIn return the IOP will send its (possibly empty) NULL terminated error response string.

    pcap_stats()SMP -> IOPAt any time, the SMP can issue a 'retrieve statistics' command which contains:
    +

    + + + + + + + + + + + +
    Name/
    Purpose
    Size
    (in bytes)
    Description
    command1'S' (indicating 'request statistics')
    +

    IOP -> SMPIn return the IOP will send: +

    + + + + + + + + + + + + + + + + + + + + + +
    Name/
    Purpose
    Size
    (in bytes)
    Description
    ps_recv4The number of packets that passed the filter.
    ps_drop4The number of packets that were dropped because the input queue was full, + regardless of whether they passed the filter.
    ps_ifdrop4The number of packets dropped by the network inteface + (regardless of whether they would have passed the input filter).
    +


    pcap_close()SMP -> IOPAt any time, the SMP can close the TCP session with the IOP.

    +

+ +

Interface ID Naming Convention

+
    + Each interface within an IOP will be referred to uniquely. Since an currently contains + 8 monitorable WAN ports and a monitorable Ethernet port, the naming convention is: +

    +

    + + + + + + + + + + + + +
    Interface # Type Name
    1 WAN wan0
    2 WAN wan1
    3 WAN wan2
    4 WAN wan3
    5 WAN wan4
    6 WAN wan5
    7 WAN wan6
    8 WAN wan7
    9 Ethernet eth0
    10 Ethernet eth1
    +
    +
+ +

Packet Trace Data Format

+
    + The format of the trace data that is sent to the SMP follows a portion of the libpcap file format + and is summarized here. This format specifies the generic requirements needed to + be able to decode packets, but does not cover ACN specifics such as custom MAC addressing + and WAN protocol support. +

    + + Although a libpcap file begins with a global header followed by zero or + more records for each captured packet, trace data sent to the SMP does NOT begin with a global header. + A trace sequence looks like this: +

    + + + + + + + + + + +
     [Packet Header]  [Packet Data]  [Packet Header]  [Packet Data]  [Packet Header]  [Packet Data] ...
    + +

    Packet Header

    +
      + Each captured packet starts with a header that contains the following values + (in network neutral order): + + +
      + uint32 tv_sec;  /* timestamp seconds */
      + uint32 tv_usec; /* timestamp microseconds */
      + uint32 caplen;  /* number of octets in the following packet */
      + uint32 len;     /* original length of packet on the wire */
      +		
      +
      + + + + + + + + + + + + + + + + + + +
      tv_secThe date and time when this packet was captured. + This value is in seconds since January 1, 1970 00:00:00 GMT; + this is also known as a UN*X time_t. You can use the ANSI C + time() function from time.h to get this value, + but you might use a more optimized way to get this timestamp value. + If this timestamp isn't based on GMT (UTC), use thiszone + from the global header for adjustments.
      tv_usecThe microseconds when this packet was captured, as an offset to ts_sec. + Beware: this value must never reach 1 second (1,000,000), + in this case ts_sec must be increased instead!
      caplenThe number of bytes actually provided in the capture record. + This value should never become larger than len or the + snaplen value specified during the capture.
      lenThe length of the packet "on the wire" when it was captured. + If caplen and len differ, the actually + saved packet size was limited by the value of snaplen specified + during one of the capture directives such as pcap_dispatch().
      +
    + +

    Packet Data

    +
      + The actual packet data will immediately follow the packet header as a sequence of caplen octets. + Depending on the DLT encoding number assigned to the interface, the packet data will contain an additional + custom header used to convey WAN port related information. +
    + +

    ACN Custom Packet Header

    +
      + PCAP, Wireshark and Tcpdump enhancements have been added to the ACN to support + monitoring of its ports, however each of these facilities were focused on capturing + and displaying traffic from LAN interfaces. The SITA extentions to these facilities + are used to also provide the ability to capture, filter, and display information from + an ACN's WAN ports. +

      + Although each packet follows the standard libpcap format, since there are + two types of interfaces that can be monitored, the format of the data + packet varies slightly. +

      +

        +
      • For Ethernet (like) devices, the packet format is unchanged from the standard Pcap format. +
      • For WAN devices, the packet contains a 5 byte header that preceeds the actual captured data + described by the following table: +
      +

      +

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      OctetNameMask/ValueDefinition
      0Control / Statusxxxxxxx0Transmitted by capture device(see 'Errors' octets)
      xxxxxxx1Received by capture device
      1xxxxxxxNo buffer was available during capture of previous packet.
      1Signalsxxxxxxx1 DSR asserted
      xxxxxx1x DTR asserted
      xxxxx1xx CTS asserted
      xxxx1xxx RTS asserted
      xxx1xxxx DCD asserted
      xx1xxxxx Undefined
      x1xxxxxx Undefined
      1xxxxxxx Undefined
      2Errors
      (octet 1)
        Tx Rx
      xxxxxxx1 Underrun Framing
      xxxxxx1x CTS Lost Parity
      xxxxx1xx UART Error Collision
      xxxx1xxx Re-Tx Limit Reached Long Frame
      xxx1xxxx Undefined Short Frame
      xx1xxxxx Undefined Undefined
      x1xxxxxx Undefined Undefined
      1xxxxxxx Undefined Undefined
      3Errors
      (octet 2)
        Tx Rx
      xxxxxxx1 Undefined Non-Octet Aligned
      xxxxxx1x Undefined Abort Received
      xxxxx1xx Undefined CD Lost
      xxxx1xxx Undefined Digital PLL Error
      xxx1xxxx Undefined Overrun
      xx1xxxxx Undefined Frame Length Violation
      x1xxxxxx Undefined CRC Error
      1xxxxxxx Undefined Break Received
      4Protocol +
      + + + + + + + + + + + + + +
      0x01 - LAPB (BOP)  
      0x02 - Ethernet 1
      0x03 - Async (Interrupt IO)  
      0x04 - Async (Block IO)  
      0x05 - IPARS  
      0x06 - UTS  
      0x07 - PPP (HDLC)  
      0x08 - SDLC  
      0x09 - Token Ring 1
      0x10 - I2C  
      0x11 - DPM Link  
      0x12 - Frame Relay (BOP)  
      +
      +

      + Note 1: + Ethernet and Token Ring frames will never be sent as DLT_SITA (with the 5 octet header), + but will be sent as their corresponding DLT types instead. +

      +
      +
    +

    +

+ diff --git a/libpcap/pcap-snit.c b/libpcap/pcap-snit.c index 60abe6444..8f937be32 100644 --- a/libpcap/pcap-snit.c +++ b/libpcap/pcap-snit.c @@ -25,7 +25,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.72.2.1 2005/05/03 18:54:38 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.73.2.4 2008-04-14 20:41:52 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -113,7 +113,6 @@ static int pcap_read_snit(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { register int cc, n; - register struct bpf_insn *fcode = p->fcode.bf_insns; register u_char *bp, *cp, *ep; register struct nit_bufhdr *hdrp; register struct nit_iftime *ntp; @@ -187,13 +186,13 @@ pcap_read_snit(pcap_t *p, int cnt, pcap_handler callback, u_char *user) if (caplen > p->snapshot) caplen = p->snapshot; - if (bpf_filter(fcode, cp, nlp->nh_pktlen, caplen)) { + 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) { + if (++n >= cnt && cnt > 0) { p->cc = ep - bp; p->bp = bp; return (n); @@ -261,30 +260,29 @@ nit_setflags(int fd, int promisc, int to_ms, char *ebuf) return (0); } -pcap_t * -pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, - char *ebuf) +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"; - register pcap_t *p; - p = (pcap_t *)malloc(sizeof(*p)); - if (p == NULL) { - strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); - return (NULL); + 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 (snaplen < 96) + if (p->snapshot < 96) /* * NIT requires a snapshot length of at least 96. */ - snaplen = 96; + p->snapshot = 96; - memset(p, 0, sizeof(*p)); /* * Initially try a read/write open (to allow the inject * method to work). If that fails due to permission @@ -303,19 +301,19 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, if (fd < 0 && errno == EACCES) p->fd = fd = open(dev, O_RDONLY); if (fd < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s", dev, + 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(ebuf, PCAP_ERRBUF_SIZE, "I_SRDOPT: %s", + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "I_SRDOPT: %s", pcap_strerror(errno)); goto bad; } if (ioctl(fd, I_PUSH, "nbuf") < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "push nbuf: %s", + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "push nbuf: %s", pcap_strerror(errno)); goto bad; } @@ -325,34 +323,33 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, si.ic_len = sizeof(chunksize); si.ic_dp = (char *)&chunksize; if (ioctl(fd, I_STR, (char *)&si) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "NIOCSCHUNK: %s", + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSCHUNK: %s", pcap_strerror(errno)); goto bad; } /* request the interface */ - strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); + 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(ebuf, PCAP_ERRBUF_SIZE, "NIOCBIND: %s: %s", + 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(snaplen); - si.ic_dp = (char *)&snaplen; + si.ic_len = sizeof(p->snapshot); + si.ic_dp = (char *)&p->snapshot; if (ioctl(fd, I_STR, (char *)&si) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "NIOCSSNAP: %s", + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSSNAP: %s", pcap_strerror(errno)); goto bad; } - p->snapshot = snaplen; - if (nit_setflags(p->fd, promisc, to_ms, ebuf) < 0) + if (nit_setflags(p->fd, p->opt.promisc, p->md.timeout, p->errbuf) < 0) goto bad; (void)ioctl(fd, I_FLUSH, (char *)FLUSHR); @@ -364,7 +361,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, p->bufsize = BUFSPACE; p->buffer = (u_char *)malloc(p->bufsize); if (p->buffer == NULL) { - strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); + strlcpy(p->errbuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); goto bad; } @@ -402,14 +399,23 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; p->stats_op = pcap_stats_snit; - p->close_op = pcap_close_common; - return (p); + return (0); bad: - if (fd >= 0) - close(fd); - free(p); - return (NULL); + return (PCAP_ERROR); +} + +pcap_t * +pcap_create(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 diff --git a/libpcap/pcap-snoop.c b/libpcap/pcap-snoop.c index f6425f1b1..a8034341c 100644 --- a/libpcap/pcap-snoop.c +++ b/libpcap/pcap-snoop.c @@ -20,7 +20,7 @@ */ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.54.2.1 2005/05/03 18:54:38 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.55.2.3 2008-04-14 20:41:52 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -194,9 +194,8 @@ pcap_stats_snoop(pcap_t *p, struct pcap_stat *ps) } /* XXX can't disable promiscuous */ -pcap_t * -pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, - char *ebuf) +static int +pcap_activate_snoop(pcap_t *p) { int fd; struct sockaddr_raw sr; @@ -204,55 +203,50 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, u_int v; int ll_hdrlen; int snooplen; - pcap_t *p; struct ifreq ifr; - p = (pcap_t *)malloc(sizeof(*p)); - if (p == NULL) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", - pcap_strerror(errno)); - return (NULL); - } - memset(p, 0, sizeof(*p)); fd = socket(PF_RAW, SOCK_RAW, RAWPROTO_SNOOP); if (fd < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "snoop socket: %s", + 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, device, sizeof(sr.sr_ifname)); + (void)strncpy(sr.sr_ifname, p->opt.source, sizeof(sr.sr_ifname)); if (bind(fd, (struct sockaddr *)&sr, sizeof(sr))) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "snoop bind: %s", + 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(ebuf, PCAP_ERRBUF_SIZE, "SIOCADDSNOOP: %s", + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCADDSNOOP: %s", pcap_strerror(errno)); goto bad; } - v = 64 * 1024; + if (handle->opt.buffer_size != 0) + v = handle->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", device, 2) == 0 || /* Challenge 10 Mbit */ - strncmp("ec", device, 2) == 0 || /* Indigo/Indy 10 Mbit, - O2 10/100 */ - strncmp("ef", device, 2) == 0 || /* O200/2000 10/100 Mbit */ - strncmp("eg", device, 2) == 0 || /* Octane/O2xxx/O3xxx Gigabit */ - strncmp("gfe", device, 3) == 0 || /* GIO 100 Mbit */ - strncmp("fxp", device, 3) == 0 || /* Challenge VME Enet */ - strncmp("ep", device, 2) == 0 || /* Challenge 8x10 Mbit EPLEX */ - strncmp("vfe", device, 3) == 0 || /* Challenge VME 100Mbit */ - strncmp("fa", device, 2) == 0 || - strncmp("qaa", device, 3) == 0 || - strncmp("cip", device, 3) == 0 || - strncmp("el", device, 2) == 0) { + 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); @@ -285,29 +279,38 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, p->dlt_list[1] = DLT_DOCSIS; p->dlt_count = 2; } - } else if (strncmp("ipg", device, 3) == 0 || - strncmp("rns", device, 3) == 0 || /* O2/200/2000 FDDI */ - strncmp("xpi", device, 3) == 0) { + } 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", device, 3) == 0) { + } 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", device, 3) == 0) { + } else if (strncmp("qfa", p->opt.source, 3) == 0) { p->linktype = DLT_IP_OVER_FC; ll_hdrlen = 24; - } else if (strncmp("pl", device, 2) == 0) { + } 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", device, 2) == 0) { + } else if (strncmp("lo", p->opt.source, 2) == 0) { p->linktype = DLT_NULL; ll_hdrlen = 4; } else { - snprintf(ebuf, PCAP_ERRBUF_SIZE, + 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 @@ -315,9 +318,9 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, * the MTU first and, if that succeeds, trim the snap length * to be no greater than the MTU. */ - (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); + (void)strncpy(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name)); if (ioctl(fd, SIOCGIFMTU, (char *)&ifr) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCGIFMTU: %s", + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFMTU: %s", pcap_strerror(errno)); goto bad; } @@ -338,8 +341,8 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, #ifndef ifr_mtu #define ifr_mtu ifr_metric #endif - if (snaplen > ifr.ifr_mtu + ll_hdrlen) - snaplen = ifr.ifr_mtu + ll_hdrlen; + if (p->snapshot > ifr.ifr_mtu + ll_hdrlen) + p->snapshot = ifr.ifr_mtu + ll_hdrlen; #endif /* @@ -347,18 +350,17 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, * payload bytes to capture - it doesn't count link-layer * header bytes. */ - snooplen = snaplen - ll_hdrlen; + snooplen = p->snapshot - ll_hdrlen; if (snooplen < 0) snooplen = 0; if (ioctl(fd, SIOCSNOOPLEN, &snooplen) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPLEN: %s", + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPLEN: %s", pcap_strerror(errno)); goto bad; } - p->snapshot = snaplen; v = 1; if (ioctl(fd, SIOCSNOOPING, &v) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPING: %s", + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPING: %s", pcap_strerror(errno)); goto bad; } @@ -366,7 +368,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, p->bufsize = 4096; /* XXX */ p->buffer = (u_char *)malloc(p->bufsize); if (p->buffer == NULL) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); goto bad; } @@ -384,18 +386,23 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; p->stats_op = pcap_stats_snoop; - p->close_op = pcap_close_common; - return (p); + return (0); bad: - (void)close(fd); - /* - * Get rid of any link-layer type list we allocated. - */ - if (p->dlt_list != NULL) - free(p->dlt_list); - free(p); - return (NULL); + return (PCAP_ERROR); +} + +pcap_t * +pcap_create(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 diff --git a/libpcap/pcap-stdinc.h b/libpcap/pcap-stdinc.h index 12810247e..870e33494 100644 --- a/libpcap/pcap-stdinc.h +++ b/libpcap/pcap-stdinc.h @@ -28,6 +28,7 @@ * (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-stdinc.h,v 1.10.2.1 2008-10-06 15:38:39 gianluca Exp $ (LBL) */ #define SIZEOF_CHAR 1 @@ -61,4 +62,29 @@ #define snprintf _snprintf #define vsnprintf _vsnprintf +#define strdup _strdup #define inline __inline + +#ifdef __MINGW32__ +#include +#else /*__MINGW32__*/ +/* MSVC compiler */ +#ifndef _UINTPTR_T_DEFINED +#ifdef _WIN64 +typedef unsigned __int64 uintptr_t; +#else +typedef _W64 unsigned int uintptr_t; +#endif +#define _UINTPTR_T_DEFINED +#endif + +#ifndef _INTPTR_T_DEFINED +#ifdef _WIN64 +typedef __int64 intptr_t; +#else +typedef _W64 int intptr_t; +#endif +#define _INTPTR_T_DEFINED +#endif + +#endif /*__MINGW32__*/ diff --git a/libpcap/pcap-usb-linux.c b/libpcap/pcap-usb-linux.c new file mode 100644 index 000000000..830abc775 --- /dev/null +++ b/libpcap/pcap-usb-linux.c @@ -0,0 +1,730 @@ +/* + * 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.16.2.8 2008-04-14 21:06:29 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 + +#define USB_IFACE "usb" +#define USB_TEXT_DIR "/sys/kernel/debug/usbmon" +#define USB_BUS_DIR "/proc/bus/usb" +#define USB_LINE_LEN 4096 + + +#define PIPE_IN 0x80 +#define PIPE_ISOCHRONOUS 0 +#define PIPE_INTERRUPT 1 +#define PIPE_CONTROL 2 +#define PIPE_BULK 3 + +#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_setfilter_linux(pcap_t *, struct bpf_program *); +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) +{ + struct dirent* data; + int ret = 0; + DIR* dir; + + /* scan procfs usb bus directory */ + dir = opendir(USB_BUS_DIR); + if (!dir) return 0; + while ((ret == 0) && ((data = readdir(dir)) != 0)) { + int n; + char* name = data->d_name; + int 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; +} + +static +int usb_mmap(pcap_t* handle) +{ + int len = ioctl(handle->fd, MON_IOCQ_RING_SIZE); + if (len < 0) + return 0; + + handle->buffer = mmap(0, len, PROT_READ, MAP_SHARED, handle->fd, 0); + return handle->buffer != MAP_FAILED; +} + +pcap_t * +usb_create(const char *device, char *ebuf) +{ + pcap_t *p; + + 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 = usb_setfilter_linux; + 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. + */ + return PCAP_ERROR_RFMON_NOTSUP; + } + + /* binary api is available, try to use fast mmap access */ + if (usb_mmap(handle)) { + handle->stats_op = usb_stats_linux_bin; + handle->read_op = usb_read_linux_mmap; + handle->cleanup_op = usb_cleanup_linux_mmap; + + /* + * "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; + } + 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) + { + /* 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; + } + handle->stats_op = usb_stats_linux; + handle->read_op = usb_read_linux; + } + + if (handle->opt.rfmon) { + /* + * Monitor mode doesn't apply to USB devices. + */ + return PCAP_ERROR_RFMON_NOTSUP; + } + + /* + * "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)); + 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->endpoint_number = ep_num; + 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') { + urb_transfer |= 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; + 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 == pkth.caplen) + 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; + handle->md.packets_read++; + if (pkth.caplen > handle->snapshot) + pkth.caplen = handle->snapshot; + + callback(user, &pkth, handle->buffer); + return 1; +} + +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; + snprintf(string, USB_LINE_LEN, USB_TEXT_DIR"/%ds", handle->md.ifindex); + + int 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*/ + cnt = -1; + int 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_setfilter_linux(pcap_t *p, struct bpf_program *fp) +{ + 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_ifdrop = st.dropped; + 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->urb_len + sizeof(pcap_usb_header); + pkth.ts.tv_sec = info.hdr->ts_sec; + pkth.ts.tv_usec = info.hdr->ts_usec; + + handle->md.packets_read++; + callback(user, &pkth, handle->buffer); + return 1; +} + +/* + * 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; + + 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; ibuffer[vec[i]]; + if (hdr->event_type == '@') + continue; + + /* get packet info from header*/ + pkth.caplen = hdr->data_len + sizeof(pcap_usb_header); + pkth.len = hdr->urb_len + sizeof(pcap_usb_header); + pkth.ts.tv_sec = hdr->ts_sec; + pkth.ts.tv_usec = hdr->ts_usec; + + 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) +{ + /* buffer must not be freed because it's memory mapped */ + /* XXX - does it need to be unmapped? */ + handle->buffer = NULL; + pcap_cleanup_live_common(handle); +} diff --git a/libpcap/pcap-usb-linux.h b/libpcap/pcap-usb-linux.h new file mode 100644 index 000000000..a15790743 --- /dev/null +++ b/libpcap/pcap-usb-linux.h @@ -0,0 +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.4.2.1 2008-04-04 19:39:06 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); diff --git a/libpcap/pcap-win32.c b/libpcap/pcap-win32.c index 435da6658..4fea62122 100644 --- a/libpcap/pcap-win32.c +++ b/libpcap/pcap-win32.c @@ -1,6 +1,6 @@ /* * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy) - * Copyright (c) 2005 - 2007 CACE Technologies, Davis (California) + * Copyright (c) 2005 - 2008 CACE Technologies, Davis (California) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -33,12 +33,16 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.25.2.7 2007/06/14 22:07:14 gianluca Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.34.2.8 2008-05-21 22:11:26 gianluca Exp $ (LBL)"; #endif #include #include -#include +#ifdef __MINGW32__ +#include +#else /*__MINGW32__*/ +#include +#endif /*__MINGW32__*/ #ifdef HAVE_DAG_API #include #include @@ -53,8 +57,11 @@ static int pcap_setfilter_win32_dag(pcap_t *, struct bpf_program *); static int pcap_getnonblock_win32(pcap_t *, char *); static int pcap_setnonblock_win32(pcap_t *, int, char *); -#define PcapBufSize 256000 /*dimension of the buffer in the pcap_t structure*/ -#define SIZE_BUF 1000000 +/*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) @@ -100,6 +107,43 @@ pcap_stats_win32(pcap_t *p, struct pcap_stat *ps) 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) { @@ -376,9 +420,8 @@ pcap_inject_win32(pcap_t *p, const void *buf, size_t size){ } static void -pcap_close_win32(pcap_t *p) +pcap_cleanup_win32(pcap_t *p) { - pcap_close_common(p); if (p->adapter != NULL) { PacketCloseAdapter(p->adapter); p->adapter = NULL; @@ -387,41 +430,39 @@ pcap_close_win32(pcap_t *p) PacketFreePacket(p->Packet); p->Packet = NULL; } + pcap_cleanup_live_common(p); } -pcap_t * -pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, - char *ebuf) +static int +pcap_activate_win32(pcap_t *p) { - register 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 = (pcap_t *)malloc(sizeof(*p)); - if (p == NULL) - { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); - return (NULL); - } - memset(p, 0, sizeof(*p)); - p->adapter=NULL; - - p->adapter = PacketOpenAdapter((char*)device); + p->adapter = PacketOpenAdapter(p->opt.source); if (p->adapter == NULL) { - free(p); /* Adapter detected but we are not able to open it. Return failure. */ - snprintf(ebuf, PCAP_ERRBUF_SIZE, "Error opening adapter: %s", pcap_win32strerror()); - return NULL; + 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(ebuf, PCAP_ERRBUF_SIZE, "Cannot determine the network type: %s", pcap_win32strerror()); + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Cannot determine the network type: %s", pcap_win32strerror()); goto bad; } @@ -505,12 +546,12 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, } /* Set promiscuous mode */ - if (promisc) + if (p->opt.promisc) { if (PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_PROMISCUOUS) == FALSE) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to promiscuous mode"); + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to promiscuous mode"); goto bad; } } @@ -518,21 +559,18 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, { if (PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_ALL_LOCAL) == FALSE) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to non-promiscuous mode"); + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to non-promiscuous mode"); goto bad; } } /* Set the buffer size */ - p->bufsize = PcapBufSize; - - /* Store the timeout. Used by pcap_setnonblock() */ - p->timeout= to_ms; + p->bufsize = WIN32_DEFAULT_USER_BUFFER_SIZE; /* allocate Packet structure used during the capture */ if((p->Packet = PacketAllocatePacket())==NULL) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "failed to allocate the PACKET structure"); + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to allocate the PACKET structure"); goto bad; } @@ -541,29 +579,32 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, /* * 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(PcapBufSize); + p->buffer = (u_char *)malloc(p->bufsize); if (p->buffer == NULL) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); goto bad; } PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize); - p->snapshot = snaplen; - - /* allocate the standard buffer in the driver */ - if(PacketSetBuff( p->adapter, SIZE_BUF)==FALSE) - { - snprintf(ebuf, PCAP_ERRBUF_SIZE,"driver error: not enough memory to allocate the kernel buffer\n"); - goto bad; - } - /* tell the driver to copy the buffer only if it contains at least 16K */ if(PacketSetMinToCopy(p->adapter,16000)==FALSE) { - snprintf(ebuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s\n", pcap_win32strerror()); + snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s", pcap_win32strerror()); goto bad; } } @@ -582,7 +623,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, snprintf(keyname, sizeof(keyname), "%s\\CardParams\\%s", "SYSTEM\\CurrentControlSet\\Services\\DAG", - strstr(_strlwr((char*)device), "dag")); + strstr(_strlwr(p->opt.source), "dag")); do { status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &dagkey); @@ -616,7 +657,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, goto bad; #endif /* HAVE_DAG_API */ - PacketSetReadTimeout(p->adapter, to_ms); + PacketSetReadTimeout(p->adapter, p->md.timeout); #ifdef HAVE_DAG_API if(p->adapter->Flags & INFO_FLAG_DAG_CARD) @@ -641,25 +682,60 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, p->getnonblock_op = pcap_getnonblock_win32; p->setnonblock_op = pcap_setnonblock_win32; p->stats_op = pcap_stats_win32; - p->close_op = pcap_close_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 (p); + return (0); bad: - if (p->adapter) - PacketCloseAdapter(p->adapter); - if (p->buffer != NULL) - free(p->buffer); - if(p->Packet) - PacketFreePacket(p->Packet); - /* - * Get rid of any link-layer type list we allocated. - */ - if (p->dlt_list != NULL) - free(p->dlt_list); - free(p); - return (NULL); + pcap_cleanup_win32(p); + return (PCAP_ERROR); } +pcap_t * +pcap_create(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) @@ -736,7 +812,7 @@ pcap_setnonblock_win32(pcap_t *p, int nonblock, char *errbuf) * (Note that this may be -1, in which case we're not * really leaving non-blocking mode.) */ - newtimeout = p->timeout; + newtimeout = p->md.timeout; } if (!PacketSetReadTimeout(p->adapter, newtimeout)) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, @@ -747,57 +823,9 @@ pcap_setnonblock_win32(pcap_t *p, int nonblock, char *errbuf) return (0); } -/* Set the driver working mode */ -int -pcap_setmode(pcap_t *p, int mode){ - - if (p->adapter==NULL) - { - snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "impossible to set mode while reading from a file"); - return -1; - } - - if(PacketSetMode(p->adapter,mode)==FALSE) - { - snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized"); - return -1; - } - - return 0; -} - -/* Set the dimension of the kernel-level capture buffer */ -int -pcap_setbuff(pcap_t *p, int dim) +/*platform-dependent routine to add devices other than NDIS interfaces*/ +int +pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) { - if (p->adapter==NULL) - { - snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "The kernel buffer size cannot be set while reading from a file"); - return -1; - } - - 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 minimum amount of data that will release a read call*/ -int -pcap_setmintocopy(pcap_t *p, int size) -{ - if (p->adapter==NULL) - { - snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Impossible to set the mintocopy parameter on an offline capture"); - return -1; - } - - 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; + return (0); } diff --git a/libpcap/pcap.3 b/libpcap/pcap.3 deleted file mode 100644 index 94b1f6a55..000000000 --- a/libpcap/pcap.3 +++ /dev/null @@ -1,1312 +0,0 @@ -.\" @(#) $Header: /tcpdump/master/libpcap/pcap.3,v 1.64.2.11 2007/06/11 09:52:05 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 3 "27 February 2004" -.SH NAME -pcap \- Packet Capture library -.SH SYNOPSIS -.nf -.ft B -#include -.ft -.LP -.nf -.ft B -char errbuf[PCAP_ERRBUF_SIZE]; -.ft -.LP -.ft B -pcap_t *pcap_open_live(const char *device, int snaplen, -.ti +8 -int promisc, int to_ms, char *errbuf) -pcap_t *pcap_open_dead(int linktype, int snaplen) -pcap_t *pcap_open_offline(const char *fname, char *errbuf) -pcap_t *pcap_fopen_offline(FILE *fp, char *errbuf) -pcap_dumper_t *pcap_dump_open(pcap_t *p, const char *fname) -pcap_dumper_t *pcap_dump_fopen(pcap_t *p, FILE *fp) -.ft -.LP -.ft B -int pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf); -int pcap_getnonblock(pcap_t *p, char *errbuf); -.ft -.LP -.ft B -int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) -void pcap_freealldevs(pcap_if_t *alldevs) -char *pcap_lookupdev(char *errbuf) -int pcap_lookupnet(const char *device, bpf_u_int32 *netp, -.ti +8 -bpf_u_int32 *maskp, char *errbuf) -.ft -.LP -.ft B -typedef void (*pcap_handler)(u_char *user, const struct pcap_pkthdr *h, -.ti +8 - const u_char *bytes); -.ft B -int pcap_dispatch(pcap_t *p, int cnt, -.ti +8 -pcap_handler callback, u_char *user) -int pcap_loop(pcap_t *p, int cnt, -.ti +8 -pcap_handler callback, u_char *user) -void pcap_dump(u_char *user, struct pcap_pkthdr *h, -.ti +8 -u_char *sp) -.ft -.LP -.ft B -int pcap_compile(pcap_t *p, struct bpf_program *fp, -.ti +8 -const char *str, int optimize, bpf_u_int32 netmask) -int pcap_setfilter(pcap_t *p, struct bpf_program *fp) -void pcap_freecode(struct bpf_program *) -int pcap_setdirection(pcap_t *p, pcap_direction_t d) -.ft -.LP -.ft B -const u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h) -int pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header, -.ti +8 -const u_char **pkt_data) -.ft -.LP -.ft B -void pcap_breakloop(pcap_t *) -.ft -.LP -.ft B -int pcap_inject(pcap_t *p, const void *buf, size_t size) -int pcap_sendpacket(pcap_t *p, const u_char *buf, int size) -.ft -.LP -.ft B -int pcap_datalink(pcap_t *p) -int pcap_list_datalinks(pcap_t *p, int **dlt_buf); -int pcap_set_datalink(pcap_t *p, int dlt); -int pcap_datalink_name_to_val(const char *name); -const char *pcap_datalink_val_to_name(int dlt); -const char *pcap_datalink_val_to_description(int dlt); -int pcap_snapshot(pcap_t *p) -int pcap_is_swapped(pcap_t *p) -int pcap_major_version(pcap_t *p) -int pcap_minor_version(pcap_t *p) -int pcap_stats(pcap_t *p, struct pcap_stat *ps) -FILE *pcap_file(pcap_t *p) -int pcap_fileno(pcap_t *p) -int pcap_get_selectable_fd(pcap_t *p); -void pcap_perror(pcap_t *p, char *prefix) -char *pcap_geterr(pcap_t *p) -const char *pcap_strerror(int error) -const char *pcap_lib_version(void) -.ft -.LP -.ft B -void pcap_close(pcap_t *p) -int pcap_dump_flush(pcap_dumper_t *p) -long pcap_dump_ftell(pcap_dumper_t *p) -FILE *pcap_dump_file(pcap_dumper_t *p) -void pcap_dump_close(pcap_dumper_t *p) -.ft -.fi -.SH DESCRIPTION -The Packet Capture library -provides a high level interface to packet capture systems. All packets -on the network, even those destined for other hosts, are accessible -through this mechanism. -.PP -.SH ROUTINES -NOTE: -.I errbuf -in -.BR pcap_open_live() , -.BR pcap_open_dead() , -.BR pcap_open_offline() , -.BR pcap_fopen_offline() , -.BR pcap_setnonblock() , -.BR pcap_getnonblock() , -.BR pcap_findalldevs() , -.BR pcap_lookupdev() , -and -.B pcap_lookupnet() -is assumed to be able to hold at least -.B PCAP_ERRBUF_SIZE -chars. -.PP -.B pcap_open_live() -is used to obtain a packet capture descriptor to look -at packets on the network. -.I device -is a string that specifies the network device to open; on Linux systems -with 2.2 or later kernels, a -.I device -argument of "any" or -.B NULL -can be used to capture packets from all interfaces. -.I snaplen -specifies the maximum number of bytes to capture. If this value is less -than the size of a packet that is captured, only the first -.I snaplen -bytes of that packet will be captured and provided as packet data. A -value of 65535 should be sufficient, on most if not all networks, to -capture all the data available from the packet. -.I promisc -specifies if the interface is to be put into promiscuous mode. -(Note that even if this parameter is false, the interface -could well be in promiscuous mode for some other reason.) For now, this -doesn't work on the "any" device; if an argument of "any" or NULL is -supplied, the -.I promisc -flag is ignored. -.I to_ms -specifies the read timeout in milliseconds. The read timeout is used to -arrange that the read not necessarily return immediately when a packet -is seen, but that it wait for some amount of time to allow more packets -to arrive and to read multiple packets from the OS kernel in one -operation. Not all platforms support a read timeout; on platforms that -don't, the read timeout is ignored. A zero value for -.IR to_ms , -on platforms that support a read timeout, -will cause a read to wait forever to allow enough packets to -arrive, with no timeout. -.I errbuf -is used to return error or warning text. It will be set to error text when -.B pcap_open_live() -fails and returns -.BR NULL . -.I errbuf -may also be set to warning text when -.B pcap_open_live() -succeds; to detect this case the caller should store a zero-length string in -.I errbuf -before calling -.B pcap_open_live() -and display the warning to the user if -.I errbuf -is no longer a zero-length string. -.PP -.B pcap_open_dead() -is used for creating a -.B pcap_t -structure to use when calling the other functions in libpcap. It is -typically used when just using libpcap for compiling BPF code. -.PP -.B pcap_open_offline() -is called to open a ``savefile'' for reading. -.I fname -specifies the name of the file to open. The file has -the same format as those used by -.B tcpdump(1) -and -.BR tcpslice(1) . -The name "-" in a synonym for -.BR stdin . -Alternatively, you may call -.B pcap_fopen_offline() -to read dumped data from an existing open stream -.IR fp . -Note that on Windows, that stream should be opened in binary mode. -.I errbuf -is used to return error text and is only set when -.B pcap_open_offline() -or -.B pcap_fopen_offline() -fails and returns -.BR NULL . -.PP -.B pcap_dump_open() -is called to open a ``savefile'' for writing. The name "-" in a synonym -for -.BR stdout . -.B NULL -is returned on failure. -.I p -is a -.I pcap -struct as returned by -.B pcap_open_offline() -or -.BR pcap_open_live() . -.I fname -specifies the name of the file to open. Alternatively, you may call -.B pcap_dump_fopen() -to write data to an existing open stream -.IR fp . -Note that on Windows, that stream should be opened in binary mode. -If -.B NULL -is returned, -.B pcap_geterr() -can be used to get the error text. -.PP -.PP -.B pcap_setnonblock() -puts a capture descriptor, opened with -.BR pcap_open_live() , -into ``non-blocking'' mode, or takes it out of ``non-blocking'' mode, -depending on whether the -.I nonblock -argument is non-zero or zero. It has no effect on ``savefiles''. -If there is an error, \-1 is returned and -.I errbuf -is filled in with an appropriate error message; otherwise, 0 is -returned. -In -``non-blocking'' mode, an attempt to read from the capture descriptor -with -.B pcap_dispatch() -will, if no packets are currently available to be read, return 0 -immediately rather than blocking waiting for packets to arrive. -.B pcap_loop() -and -.B pcap_next() -will not work in ``non-blocking'' mode. -.PP -.B pcap_getnonblock() -returns the current ``non-blocking'' state of the capture descriptor; it -always returns 0 on ``savefiles''. -If there is an error, \-1 is returned and -.I errbuf -is filled in with an appropriate error message. -.PP -.B pcap_findalldevs() -constructs a list of network devices that can be opened with -.BR pcap_open_live() . -(Note that there may be network devices that cannot be opened with -.BR pcap_open_live() -by the -process calling -.BR pcap_findalldevs() , -because, for example, that process might not have sufficient privileges -to open them for capturing; if so, those devices will not appear on the -list.) -.I alldevsp -is set to point to the first element of the list; each element of the -list is of type -.BR pcap_if_t , -and has the following members: -.RS -.TP -.B next -if not -.BR NULL , -a pointer to the next element in the list; -.B NULL -for the last element of the list -.TP -.B name -a pointer to a string giving a name for the device to pass to -.B pcap_open_live() -.TP -.B description -if not -.BR NULL , -a pointer to a string giving a human-readable description of the device -.TP -.B addresses -a pointer to the first element of a list of addresses for the interface -.TP -.B flags -interface flags: -.RS -.TP -.B PCAP_IF_LOOPBACK -set if the interface is a loopback interface -.RE -.RE -.PP -Each element of the list of addresses is of type -.BR pcap_addr_t , -and has the following members: -.RS -.TP -.B next -if not -.BR NULL , -a pointer to the next element in the list; -.B NULL -for the last element of the list -.TP -.B addr -a pointer to a -.B "struct sockaddr" -containing an address -.TP -.B netmask -if not -.BR NULL , -a pointer to a -.B "struct sockaddr" -that contains the netmask corresponding to the address pointed to by -.B addr -.TP -.B broadaddr -if not -.BR NULL , -a pointer to a -.B "struct sockaddr" -that contains the broadcast address corresponding to the address pointed -to by -.BR addr ; -may be null if the interface doesn't support broadcasts -.TP -.B dstaddr -if not -.BR NULL , -a pointer to a -.B "struct sockaddr" -that contains the destination address corresponding to the address pointed -to by -.BR addr ; -may be null if the interface isn't a point-to-point interface -.RE -.PP -Note that not all the addresses in the list of addresses are -necessarily IPv4 or IPv6 addresses - you must check the -.B sa_family -member of the -.B "struct sockaddr" -before interpreting the contents of the address. -.PP -.B \-1 -is returned on failure, in which case -.B errbuf -is filled in with an appropriate error message; -.B 0 -is returned on success. -.PP -.B pcap_freealldevs() -is used to free a list allocated by -.BR pcap_findalldevs() . -.PP -.B pcap_lookupdev() -returns a pointer to a network device suitable for use with -.B pcap_open_live() -and -.BR pcap_lookupnet() . -If there is an error, -.B NULL -is returned and -.I errbuf -is filled in with an appropriate error message. -.PP -.B pcap_lookupnet() -is used to determine the network number and mask -associated with the network device -.BR device . -Both -.I netp -and -.I maskp -are -.I bpf_u_int32 -pointers. -A return of \-1 indicates an error in which case -.I errbuf -is filled in with an appropriate error message. -.PP -.B pcap_dispatch() -is used to collect and process packets. -.I cnt -specifies the maximum number of packets to process before returning. -This 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 -.I cnt -of \-1 processes all the packets received in one buffer when reading a -live capture, or all the packets in the file when reading a -``savefile''. -.I callback -specifies a routine to be called with three arguments: -a -.I u_char -pointer which is passed in from -.BR pcap_dispatch() , -a -.I const struct pcap_pkthdr -pointer to a structure with the following members: -.RS -.TP -.B ts -a -.I struct timeval -containing the time when the packet was captured -.TP -.B caplen -a -.I bpf_u_int32 -giving the number of bytes of the packet that are available from the -capture -.TP -.B len -a -.I bpf_u_int32 -giving the length of the packet, in bytes (which might be more than the -number of bytes available from the capture, if the length of the packet -is larger than the maximum number of bytes to capture) -.RE -.PP -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 (which won't necessarily be the entire -packet; to capture the entire packet, you will have to provide a value -for -.I snaplen -in your call to -.B pcap_open_live() -that is sufficiently large to get all of the packet's data - a value of -65535 should be sufficient on most if not all networks). -.PP -The number of packets read is returned. -0 is returned 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.'' A return of \-1 indicates -an error in which case -.B pcap_perror() -or -.B pcap_geterr() -may be used to display the error text. -A return of \-2 indicates that 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 -.BR NOTE : -when reading a live capture, -.B pcap_dispatch() -will not necessarily return when the read times out; on some platforms, -the read timeout isn't supported, and, on other platforms, the timer -doesn't start until at least one packet arrives. This means that the -read timeout should -.B NOT -be used in, for example, an interactive application, to allow the packet -capture loop to ``poll'' for user input periodically, as there's no -guarantee that -.B pcap_dispatch() -will return after the timeout expires. -.PP -.B pcap_loop() -is similar to -.B pcap_dispatch() -except it keeps reading packets until -.I cnt -packets are processed or an error occurs. -It does -.B not -return when live read timeouts occur. -Rather, specifying a non-zero read timeout to -.B pcap_open_live() -and then calling -.B pcap_dispatch() -allows the reception and processing of any packets that arrive when the -timeout occurs. -A negative -.I cnt -causes -.B pcap_loop() -to loop forever (or at least until an error occurs). \-1 is returned on -an error; 0 is returned if -.I cnt -is exhausted; \-2 is returned 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 -.B pcap_next() -reads the next packet (by calling -.B pcap_dispatch() -with a -.I cnt -of 1) and returns a -.I u_char -pointer to the data in that packet. (The -.I pcap_pkthdr -struct for that packet is not supplied.) -.B NULL -is returned if an error occured, or 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.'' Unfortunately, there is -no way to determine whether an error occured or not. -.PP -.B pcap_next_ex() -reads the next packet and returns a success/failure indication: -.RS -.TP -1 -the packet was read without problems -.TP -0 -packets are being read from a live capture, and the timeout expired -.TP -\-1 -an error occurred while reading the packet -.TP -\-2 -packets are being read from a ``savefile'', and there are no more -packets to read from the savefile. -.RE -.PP -If the packet was read without problems, the pointer pointed to by the -.I pkt_header -argument is set to point to the -.I pcap_pkthdr -struct for the packet, and the -pointer pointed to by the -.I pkt_data -argument is set to point to the data in the packet. -.PP -.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. -.PP -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. -.ft R -.PP -Note that -.B pcap_next() -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() -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. -.PP -.B pcap_inject() -sends a raw packet through the network interface; -.I buf -points to the data of the packet, including the link-layer header, and -.I size -is the number of bytes in the packet. -It returns the number of bytes written on success. A return of \-1 -indicates an error in which case -.B pcap_perror() -or -.B pcap_geterr() -may be used to display the error text. -Note that, even if you successfully open the network interface, you -might not have permission to send packets on it, or it might not support -sending packets; as -.I pcap_open_live() -doesn't have a flag to indicate whether to open for capturing, sending, -or capturing and sending, you cannot request an open that supports -sending and be notified at open time whether sending will be possible. -Note also that some devices might not support sending packets. -.PP -Note that, on some platforms, the link-layer header of the packet that's -sent might not be the same as the link-layer header of the packet -supplied to -.BR pcap_inject() , -as the source link-layer address, if the header contains such an -address, might be changed to be the address assigned to the interface on -which the packet it sent, if the platform doesn't support sending -completely raw and unchanged packets. Even worse, some drivers on some -platforms might change the link-layer type field to whatever value -libpcap used when attaching to the device, even on platforms that -.I do -nominally support sending completely raw and unchanged packets. -.PP -.B pcap_sendpacket() -is like -.BR pcap_inject() , -but it returns 0 on success and \-1 on failure. -.RB ( pcap_inject() -comes from OpenBSD; -.B pcap_sendpacket() -comes from WinPcap. Both are provided for compatibility.) -.PP -.B pcap_dump() -outputs a packet to the ``savefile'' opened with -.BR pcap_dump_open() . -Note that its calling arguments are suitable for use with -.B pcap_dispatch() -or -.BR pcap_loop() . -If called directly, the -.I user -parameter is of type -.I pcap_dumper_t -as returned by -.BR pcap_dump_open() . -.PP -.B pcap_compile() -is used to compile the string -.I str -into a filter program. -.I program -is a pointer to a -.I bpf_program -struct and is filled in by -.BR pcap_compile() . -.I optimize -controls whether optimization on the resulting code is performed. -.I netmask -specifies the IPv4 netmask of the network on which packets are being -captured; it is used only when checking for IPv4 broadcast addresses in -the filter program. If the netmask of the network on which packets are -being captured isn't known to the program, or if packets are being -captured on the Linux "any" pseudo-interface that can capture on more -than one network, a value of 0 can be supplied; tests for IPv4 broadcast -addreses won't be done correctly, but all other tests in the filter -program will be OK. A return of \-1 indicates an error in which case -.BR pcap_geterr() -may be used to display the error text. -.PP -.B pcap_compile_nopcap() -is similar to -.B pcap_compile() -except that instead of passing a pcap structure, one passes the -snaplen and linktype explicitly. It is intended to be used for -compiling filters for direct BPF usage, without necessarily having -called -.BR pcap_open() . -A return of \-1 indicates an error; the error text is unavailable. -.RB ( pcap_compile_nopcap() -is a wrapper around -.BR pcap_open_dead() , -.BR pcap_compile() , -and -.BR pcap_close() ; -the latter three routines can be used directly in order to get the error -text for a compilation error.) -.B -.PP -.B pcap_setfilter() -is used to specify a filter program. -.I fp -is a pointer to a -.I bpf_program -struct, usually the result of a call to -.BR pcap_compile() . -.B \-1 -is returned on failure, in which case -.BR pcap_geterr() -may be used to display the error text; -.B 0 -is returned on success. -.PP -.B pcap_freecode() -is used to free up allocated memory pointed to by a -.I bpf_program -struct generated by -.B pcap_compile() -when that BPF program is no longer needed, for example after it -has been made the filter program for a pcap structure by a call to -.BR pcap_setfilter() . -.PP -.B pcap_setdirection() -is used to specify a direction that packets will be captured. -.I pcap_direction_t -is one of the constants -.BR PCAP_D_IN , -.B PCAP_D_OUT -or -.BR PCAP_D_INOUT . -.B PCAP_D_IN -will only capture packets received by the device, -.B PCAP_D_OUT -will only capture packets sent by the device and -.B PCAP_D_INOUT -will capture packets received by or sent by the device. -.B PCAP_D_INOUT -is the default setting if this function is not called. This isn't -necessarily supported on all platforms; some platforms might return an -error, and some other platforms might not support -.BR PCAP_D_OUT . -This operation is not supported if a ``savefile'' is being read. -.B \-1 -is returned on failure, -.B 0 -is returned on success. -.PP -.B pcap_datalink() -returns the link layer type; link layer types it can return include: -.PP -.RS 5 -.TP 5 -.B DLT_NULL -BSD loopback encapsulation; the link layer header is a 4-byte field, in -.I host -byte order, containing a PF_ value from -.B socket.h -for the network-layer protocol of the packet. -.IP -Note that ``host byte order'' is the byte order of the machine on which -the packets are captured, and the PF_ values are for the OS of the -machine on which the packets are captured; if a live capture is being -done, ``host byte order'' is the byte order of the machine capturing the -packets, and the PF_ values are those of the OS of the machine capturing -the packets, but if a ``savefile'' is being read, the byte order and PF_ -values are -.I not -necessarily those of the machine reading the capture file. -.TP 5 -.B DLT_EN10MB -Ethernet (10Mb, 100Mb, 1000Mb, and up) -.TP 5 -.B DLT_IEEE802 -IEEE 802.5 Token Ring -.TP 5 -.B DLT_ARCNET -ARCNET -.TP 5 -.B DLT_SLIP -SLIP; the link layer header contains, in order: -.RS 10 -.LP -a 1-byte flag, which is 0 for packets received by the machine and 1 for -packets sent by the machine; -.LP -a 1-byte field, the upper 4 bits of which indicate the type of packet, -as per RFC 1144: -.RS 5 -.TP 5 -0x40 -an unmodified IP datagram (TYPE_IP); -.TP 5 -0x70 -an uncompressed-TCP IP datagram (UNCOMPRESSED_TCP), with that byte being -the first byte of the raw IP header on the wire, containing the -connection number in the protocol field; -.TP 5 -0x80 -a compressed-TCP IP datagram (COMPRESSED_TCP), with that byte being the -first byte of the compressed TCP/IP datagram header; -.RE -.LP -for UNCOMPRESSED_TCP, the rest of the modified IP header, and for -COMPRESSED_TCP, the compressed TCP/IP datagram header; -.RE -.RS 5 -.LP -for a total of 16 bytes; the uncompressed IP datagram follows the header. -.RE -.TP 5 -.B DLT_PPP -PPP; if the first 2 bytes are 0xff and 0x03, it's PPP in HDLC-like -framing, with the PPP header following those two bytes, otherwise it's -PPP without framing, and the packet begins with the PPP header. -.TP 5 -.B DLT_FDDI -FDDI -.TP 5 -.B DLT_ATM_RFC1483 -RFC 1483 LLC/SNAP-encapsulated ATM; the packet begins with an IEEE 802.2 -LLC header. -.TP 5 -.B DLT_RAW -raw IP; the packet begins with an IP header. -.TP 5 -.B DLT_PPP_SERIAL -PPP in HDLC-like framing, as per RFC 1662, or Cisco PPP with HDLC -framing, as per section 4.3.1 of RFC 1547; the first byte will be 0xFF -for PPP in HDLC-like framing, and will be 0x0F or 0x8F for Cisco PPP -with HDLC framing. -.TP 5 -.B DLT_PPP_ETHER -PPPoE; the packet begins with a PPPoE header, as per RFC 2516. -.TP 5 -.B DLT_C_HDLC -Cisco PPP with HDLC framing, as per section 4.3.1 of RFC 1547. -.TP 5 -.B DLT_IEEE802_11 -IEEE 802.11 wireless LAN -.TP 5 -.B DLT_FRELAY -Frame Relay -.TP 5 -.B DLT_LOOP -OpenBSD loopback encapsulation; the link layer header is a 4-byte field, in -.I network -byte order, containing a PF_ value from OpenBSD's -.B socket.h -for the network-layer protocol of the packet. -.IP -Note that, if a ``savefile'' is being read, those PF_ values are -.I not -necessarily those of the machine reading the capture file. -.TP 5 -.B DLT_LINUX_SLL -Linux "cooked" capture encapsulation; the link layer header contains, in -order: -.RS 10 -.LP -a 2-byte "packet type", in network byte order, which is one of: -.RS 5 -.TP 5 -0 -packet was sent to us by somebody else -.TP 5 -1 -packet was broadcast by somebody else -.TP 5 -2 -packet was multicast, but not broadcast, by somebody else -.TP 5 -3 -packet was sent by somebody else to somebody else -.TP 5 -4 -packet was sent by us -.RE -.LP -a 2-byte field, in network byte order, containing a Linux ARPHRD_ value -for the link layer device type; -.LP -a 2-byte field, in network byte order, containing the length of the -link layer address of the sender of the packet (which could be 0); -.LP -an 8-byte field containing that number of bytes of the link layer header -(if there are more than 8 bytes, only the first 8 are present); -.LP -a 2-byte field containing an Ethernet protocol type, in network byte -order, or containing 1 for Novell 802.3 frames without an 802.2 LLC -header or 4 for frames beginning with an 802.2 LLC header. -.RE -.TP 5 -.B DLT_LTALK -Apple LocalTalk; the packet begins with an AppleTalk LLAP header. -.TP 5 -.B DLT_PFLOG -OpenBSD pflog; the link layer header contains, in order: -.RS 10 -.LP -a 1-byte header length, in host byte order; -.LP -a 4-byte PF_ value, in host byte order; -.LP -a 2-byte action code, in network byte order, which is one of: -.RS 5 -.TP 5 -0 -passed -.TP 5 -1 -dropped -.TP 5 -2 -scrubbed -.RE -.LP -a 2-byte reason code, in network byte order, which is one of: -.RS 5 -.TP 5 -0 -match -.TP 5 -1 -bad offset -.TP 5 -2 -fragment -.TP 5 -3 -short -.TP 5 -4 -normalize -.TP 5 -5 -memory -.RE -.LP -a 16-character interface name; -.LP -a 16-character ruleset name (only meaningful if subrule is set); -.LP -a 4-byte rule number, in network byte order; -.LP -a 4-byte subrule number, in network byte order; -.LP -a 1-byte direction, in network byte order, which is one of: -.RS 5 -.TP 5 -0 -incoming or outgoing -.TP 5 -1 -incoming -.TP 5 -2 -outgoing -.RE -.RE -.TP 5 -.B DLT_PRISM_HEADER -Prism monitor mode information followed by an 802.11 header. -.TP 5 -.B DLT_IP_OVER_FC -RFC 2625 IP-over-Fibre Channel, with the link-layer header being the -Network_Header as described in that RFC. -.TP 5 -.B DLT_SUNATM -SunATM devices; the link layer header contains, in order: -.RS 10 -.LP -a 1-byte flag field, containing a direction flag in the uppermost bit, -which is set for packets transmitted by the machine and clear for -packets received by the machine, and a 4-byte traffic type in the -low-order 4 bits, which is one of: -.RS 5 -.TP 5 -0 -raw traffic -.TP 5 -1 -LANE traffic -.TP 5 -2 -LLC-encapsulated traffic -.TP 5 -3 -MARS traffic -.TP 5 -4 -IFMP traffic -.TP 5 -5 -ILMI traffic -.TP 5 -6 -Q.2931 traffic -.RE -.LP -a 1-byte VPI value; -.LP -a 2-byte VCI field, in network byte order. -.RE -.TP 5 -.B DLT_IEEE802_11_RADIO -link-layer information followed by an 802.11 header - see -http://www.shaftnet.org/~pizza/software/capturefrm.txt for a description -of the link-layer information. -.TP 5 -.B DLT_ARCNET_LINUX -ARCNET, with no exception frames, reassembled packets rather than raw -frames, and an extra 16-bit offset field between the destination host -and type bytes. -.TP 5 -.B DLT_LINUX_IRDA -Linux-IrDA packets, with a -.B DLT_LINUX_SLL -header followed by the IrLAP header. -.TP 5 -.B DLT_LINUX_LAPD -LAPD (Q.921) frames, with a -.B DLT_LINUX_SLL -header captured via vISDN. -.RE -.PP -.B pcap_list_datalinks() -is used to get a list of the supported data link types of the interface -associated with the pcap descriptor. -.B pcap_list_datalinks() -allocates an array to hold the list and sets -.IR *dlt_buf . -The caller is responsible for freeing the array. -.B \-1 -is returned on failure; -otherwise, the number of data link types in the array is returned. -.PP -.B pcap_set_datalink() -is used to set the current data link type of the pcap descriptor -to the type specified by -.IR dlt . -.B \-1 -is returned on failure. -.PP -.B pcap_datalink_name_to_val() -translates a data link type name, which is a -.B DLT_ -name with the -.B DLT_ -removed, to the corresponding data link type value. The translation -is case-insensitive. -.B \-1 -is returned on failure. -.PP -.B pcap_datalink_val_to_name() -translates a data link type value to the corresponding data link type -name. NULL is returned on failure. -.PP -.B pcap_datalink_val_to_description() -translates a data link type value to a short description of that data -link type. NULL is returned on failure. -.PP -.B pcap_snapshot() -returns the snapshot length specified when -.B pcap_open_live() -was called. -.PP -.B pcap_is_swapped() -returns true if the current ``savefile'' uses a different byte order -than the current system. -.PP -.B pcap_major_version() -returns the major number of the file format of the savefile; -.B pcap_minor_version() -returns the minor number of the file format of the savefile. The -version number is stored in the header of the savefile. -.PP -.B pcap_file() -returns the standard I/O stream of the ``savefile,'' if a ``savefile'' -was opened with -.BR pcap_open_offline() , -or NULL, if a network device was opened with -.BR pcap_open_live() . -.PP -.B pcap_stats() -returns 0 and fills in the -.B pcap_stat -structure pointed to by its second argument. The values represent -packet statistics from the start of the run to the time of the call. If -there is an error or the underlying packet capture doesn't support -packet statistics, \-1 is returned and the error text can be obtained -with -.B pcap_perror() -or -.BR pcap_geterr() . -.B pcap_stats() -is supported only on live captures, not on ``savefiles''; no statistics -are stored in ``savefiles'', so no statistics are available when reading -from a ``savefile''. -.PP -.B pcap_fileno() -returns the file descriptor number from which captured packets are read, -if a network device was opened with -.BR pcap_open_live() , -or \-1, if a ``savefile'' was opened with -.BR pcap_open_offline() . -.PP -.B pcap_get_selectable_fd() -returns, on UNIX, a file descriptor number for a file descriptor on -which one can -do a -.B select() -or -.B poll() -to wait for it to be possible to read packets without blocking, if such -a descriptor exists, or \-1, if no such descriptor exists. Some network -devices opened with -.B pcap_open_live() -do not support -.B select() -or -.B poll() -(for example, regular network devices on FreeBSD 4.3 and 4.4, and Endace -DAG devices), so \-1 is returned for those devices. -.PP -Note that on most versions of most BSDs (including Mac OS X) -.B select() -and -.B poll() -do not work correctly on BPF devices; -.B pcap_get_selectable_fd() -will return a file descriptor on most of those versions (the exceptions -being FreeBSD 4.3 and 4.4), a simple -.B select() -or -.B poll() -will not return even after a timeout specified in -.B pcap_open_live() -expires. To work around this, an application that uses -.B select() -or -.B poll() -to wait for packets to arrive must put the -.B pcap_t -in non-blocking mode, and must arrange that the -.B select() -or -.B poll() -have a timeout less than or equal to the timeout specified in -.BR pcap_open_live() , -and must try to read packets after that timeout expires, regardless of -whether -.B select() -or -.B poll() -indicated that the file descriptor for the -.B pcap_t -is ready to be read or not. (That workaround will not work in FreeBSD -4.3 and later; however, in FreeBSD 4.6 and later, -.B select() -and -.B poll() -work correctly on BPF devices, so the workaround isn't necessary, -although it does no harm.) -.PP -.B pcap_get_selectable_fd() -is not available on Windows. -.PP -.B pcap_perror() -prints the text of the last pcap library error on -.BR stderr , -prefixed by -.IR prefix . -.PP -.B pcap_geterr() -returns the error text pertaining to the last pcap library error. -.BR NOTE : -the pointer it returns will no longer point to a valid error message -string after the -.B pcap_t -passed to it is closed; you must use or copy the string before closing -the -.BR pcap_t . -.PP -.B pcap_strerror() -is provided in case -.BR strerror (1) -isn't available. -.PP -.B pcap_lib_version() -returns a pointer to a string giving information about the version of -the libpcap library being used; note that it contains more information -than just a version number. -.PP -.B pcap_close() -closes the files associated with -.I p -and deallocates resources. -.PP -.B pcap_dump_file() -returns the standard I/O stream of the ``savefile'' opened by -.BR pcap_dump_open(). -.PP -.B pcap_dump_flush() -flushes the output buffer to the ``savefile,'' so that any packets -written with -.B pcap_dump() -but not yet written to the ``savefile'' will be written. -.B \-1 -is returned on error, 0 on success. -.PP -.B pcap_dump_ftell() -returns the current file position for the ``savefile'', representing the -number of bytes written by -.B pcap_dump_open() -and -.BR pcap_dump() . -.B \-1 -is returned on error. -.PP -.B pcap_dump_close() -closes the ``savefile.'' -.PP -.SH SEE ALSO -tcpdump(1), tcpslice(1) -.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 -The current version is available from "The Tcpdump Group"'s Web site at -.LP -.RS -.I http://www.tcpdump.org/ -.RE -.SH BUGS -Please send problems, bugs, questions, desirable enhancements, etc. to: -.LP -.RS -tcpdump-workers@tcpdump.org -.RE -.LP -Please send source code contributions, etc. to: -.LP -.RS -patches@tcpdump.org -.RE diff --git a/libpcap/pcap.3pcap.in b/libpcap/pcap.3pcap.in new file mode 100644 index 000000000..1c6650837 --- /dev/null +++ b/libpcap/pcap.3pcap.in @@ -0,0 +1,386 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap.3pcap.in,v 1.1.2.2 2008-10-21 07:44:57 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 3PCAP "4 April 2008" +.SH NAME +pcap \- Packet Capture library +.SH SYNOPSIS +.nf +.ft B +#include +.LP +.ft B +.ft +.fi +.SH DESCRIPTION +The Packet Capture library +provides a high level interface to packet capture systems. All packets +on the network, even those destined for other hosts, are accessible +through this mechanism. +It also supports saving captured packets to a ``savefile'', and reading +packets from a ``savefile''. +.PP +To open a handle for a live capture, call +.BR pcap_create() , +set the appropriate options on the handle, and then activate it with +.BR pcap_activate() . +To open a handle for a ``savefile'' with captured packets, call +.BR pcap_open_offline() . +Both +.B pcap_create() +and +.B pcap_open_offline() +return a pointer to a +.BR pcap_t , +which is the handle used for reading packets from the capture stream or +the ``savefile'', and for finding out information about the capture +stream or ``savefile''. +.PP +The options that can be set on a capture handle include +.IP "snapshot length" +If, when capturing, you capture the entire contents of the packet, that +requires more CPU time to copy the packet to your application, more disk +and possibly network bandwidth to write the packet data to a file, and +more disk space to save the packet. If you don't need the entire +contents of the packet - for example, if you are only interested in the +TCP headers of packets - you can set the "snapshot length" for the +capture to an appropriate value. If the snapshot length is set to +.IR snaplen , +and +.I snaplen +is less +than the size of a packet that is captured, only the first +.I snaplen +bytes of that packet will be captured and provided as packet data. +.IP +A snapshot length of 65535 should be sufficient, on most if not all +networks, to capture all the data available from the packet. +.IP +The snapshot length is set with +.BR pcap_set_snaplen() . +.IP "promiscuous mode" +On broadcast LANs such as Ethernet, if the network isn't switched, or if +the adapter is connected to a "mirror port" on a switch to which all +packets passing through the switch are sent, a network adapter receives +all packets on the LAN, including unicast or multicast packets not sent +to a network address that the network adapter isn't configured to +recognize. +.IP +Normally, the adapter will discard those packets; however, many network +adapters support "promiscuous mode", which is a mode in which all +packets, even if they are not sent to an address that the adapter +recognizes, are provided to the host. This is useful for passively +capturing traffic between two or more other hosts for analysis. +.IP +Note that even if an application does not set promiscuous mode, the +adapter could well be in promiscuous mode for some other reason. +.IP +For now, this doesn't work on the "any" device; if an argument of "any" +or NULL is supplied, the setting of promiscuous mode is ignored. +.IP +Promiscuous mode is set with +.BR pcap_set_promisc() . +.IP "monitor mode" +On IEEE 802.11 wireless LANs, even if an adapter is in promiscuous mode, +it will supply to the host only frames for the network with which it's +associated. It might also supply only data frames, not management or +control frames, and might not provide the 802.11 header or radio +information pseudo-header for those frames. +.IP +In "monitor mode", sometimes also called "rfmon mode" (for "Radio +Frequency MONitor"), the adapter will supply all frames that it +receives, with 802.11 headers, and might supply a pseudo-header with +radio information about the frame as well. +.IP +Note that in monitor mode the adapter might disassociate from the +network with which it's associated, so that you will not be able to use +any wireless networks with that adapter. This could prevent accessing +files on a network server, or resolving host names or network addresses, +if you are capturing in monitor mode and are not connected to another +network with another adapter. +.IP +Monitor mode is set with +.BR pcap_set_rfmon() , +and +.B pcap_can_set_rfmon() +can be used to determine whether an adapter can be put into monitor +mode. +.IP "read timeout" +If, when capturing, packets are delivered as soon as they arrive, the +application capturing the packets will be woken up for each packet as it +arrives, and might have to make one or more calls to the operating +system to fetch each packet. +.IP +If, instead, packets are not delivered as soon as they arrive, but are +delivered after a short delay (called a "read timeout"), more than one +packet can be accumulated before the packets are delivered, so that a +single wakeup would be done for multiple packets, and each set of calls +made to the operating system would supply multiple packets, rather than +a single packet. This reduces the per-packet CPU overhead if packets +are arriving at a high rate, increasing the number of packets per second +that can be captured. +.IP +The read timeout is required so that an application won't wait for the +operating system's capture buffer to fill up before packets are +delivered; if packets are arriving slowly, that wait could take an +arbitrarily long period of time. +.IP +Not all platforms support a read timeout; on platforms that +don't, the read timeout is ignored. A zero value for the timeout, +on platforms that support a read timeout, +will cause a read to wait forever to allow enough packets to +arrive, with no timeout. +.IP +.BR NOTE : +the read timeout cannot be used to cause calls that read +packets to return within a limited period of time, because, on some +platforms, the read timeout isn't supported, and, on other platforms, +the timer doesn't start until at least one packet arrives. This means +that the read timeout should +.B NOT +be used, for example, in an interactive application to allow the packet +capture loop to ``poll'' for user input periodically, as there's no +guarantee that a call reading packets will return after the timeout +expires even if no packets have arrived. +.IP +The read timeout is set with +.BR pcap_set_timeout() . +.IP "buffer size" +Packets that arrive for a capture are stored in a buffer, so that they +do not have to be read by the application as soon as they arrive. On +some platforms, the buffer's size can be set; a size that's too small +could mean that, if too many packets are being captured and the snapshot +length doesn't limit the amount of data that's buffered, packets could +be dropped if the buffer fills up before the application can read +packets from it, while a size that's too large could use more +non-pageable operating system memory than is necessary to prevent +packets from being dropped. +.IP +The buffer size is set with +.BR pcap_set_buffer_size() . +.PP +Reading packets from a network interface may require that you have +special privileges: +.TP +.B Under SunOS 3.x or 4.x with NIT or BPF: +You must have read access to +.I /dev/nit +or +.IR /dev/bpf* . +.TP +.B Under Solaris with DLPI: +You must have read/write access to the network pseudo device, e.g. +.IR /dev/le . +On at least some versions of Solaris, however, this is not sufficient to +allow +.I tcpdump +to capture in promiscuous mode; on those versions of Solaris, you must +be root, or the application capturing packets +must be installed setuid to root, in order to capture in promiscuous +mode. Note that, on many (perhaps all) interfaces, if you don't capture +in promiscuous mode, you will not see any outgoing packets, so a capture +not done in promiscuous mode may not be very useful. +.IP +In newer versions of Solaris, you must have been given the +.B net_rawaccess +privilege; this is both necessary and sufficient to give you access to the +network pseudo-device - there is no need to change the privileges on +that device. A user can be given that privilege by, for example, adding +that privilege to the user's +.B defaultpriv +key with the +.B usermod (1M) +command. +.TP +.B Under HP-UX with DLPI: +You must be root or the application capturing packets must be installed +setuid to root. +.TP +.B Under IRIX with snoop: +You must be root or the application capturing packets must be installed +setuid to root. +.TP +.B Under Linux: +You must be root or the application capturing packets must be installed +setuid to root (unless your distribution has a kernel +that supports capability bits such as CAP_NET_RAW and code to allow +those capability bits to be given to particular accounts and to cause +those bits to be set on a user's initial processes when they log in, in +which case you must have CAP_NET_RAW in order to capture and +CAP_NET_ADMIN to enumerate network devices with, for example, the +.B \-D +flag). +.TP +.B Under ULTRIX and Digital UNIX/Tru64 UNIX: +Any user may capture network traffic. +However, no user (not even the super-user) can capture in promiscuous +mode on an interface unless the super-user has enabled promiscuous-mode +operation on that interface using +.IR pfconfig (8), +and no user (not even the super-user) can capture unicast traffic +received by or sent by the machine on an interface unless the super-user +has enabled copy-all-mode operation on that interface using +.IR pfconfig , +so +.I useful +packet capture on an interface probably requires that either +promiscuous-mode or copy-all-mode operation, or both modes of +operation, be enabled on that interface. +.TP +.B Under BSD (this includes Mac OS X): +You must have read access to +.I /dev/bpf* +on systems that don't have a cloning BPF device, or to +.I /dev/bpf +on systems that do. +On BSDs with a devfs (this includes Mac OS X), this might involve more +than just having somebody with super-user access setting the ownership +or permissions on the BPF devices - it might involve configuring devfs +to set the ownership or permissions every time the system is booted, +if the system even supports that; if it doesn't support that, you might +have to find some other way to make that happen at boot time. +.PP +Reading a saved packet file doesn't require special privileges. +.PP +To open a ``savefile`` to which to write packets, call +.BR pcap_dump_open() . +It returns a pointer to a +.BR pcap_dumper_t , +which is the handle used for writing packets to the ``savefile''. +.PP +Packets are read with +.B pcap_dispatch() +or +.BR pcap_loop() , +which process one or more packets, calling a callback routine for each +packet, or with +.B pcap_next() +or +.BR pcap_next_ex() , +which return the next packet. +The callback for +.B pcap_dispatch() +and +.BR pcap_loop() +is supplied a pointer to a +.IR "struct pcap_pkthdr" , +which includes the following members: +.RS +.TP +.B ts +a +.I struct timeval +containing the time when the packet was captured +.TP +.B caplen +a +.I bpf_u_int32 +giving the number of bytes of the packet that are available from the +capture +.TP +.B len +a +.I bpf_u_int32 +giving the length of the packet, in bytes (which might be more than the +number of bytes available from the capture, if the length of the packet +is larger than the maximum number of bytes to capture). +.RE +.PP +.B pcap_next_ex() +supplies that pointer through a pointer argument. +.B pcap_next() +is passed an argument that points to a +.I struct pcap_pkthdr +structure, and fills it in. +.PP +The callback is also supplied 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. This won't necessarily be the entire +packet; to capture the entire packet, you will have to provide a value +for +.I snaplen +in your call to +.B pcap_open_live() +that is sufficiently large to get all of the packet's data - a value of +65535 should be sufficient on most if not all networks). When reading +from a ``savefile'', the snapshot length specified when the capture was +performed will limit the amount of packet data available. +.B pcap_next() +returns that pointer; +.B pcap_next_ex() +supplies that pointer through a pointer argument. +.SH BACKWARDS COMPATIBILITY +.PP +In versions of libpcap prior to 1.0, the +.B pcap.h +header file was not in a +.B pcap +directory on most platforms; if you are writing an application that must +work on versions of libpcap prior to 1.0, include +.BR , +which will include +.B +for you, rather than including +.BR . +.PP +.B pcap_create() +and +.B pcap_activate() +were not available in versions of libpcap prior to 1.0; if you are +writing an application that must work on versions of libpcap prior to +1.0, either use +.B pcap_open_live() +to get a handle for a live capture or, if you want to be able to use the +additional capabilities offered by using +.B pcap_create() +and +.BR pcap_activate() , +use an +.BR autoconf (1) +script or some other configuration script to check whether the libpcap +1.0 APIs are available and use them only if they are. +.SH SEE ALSO +autoconf(1), tcpdump(1), tcpslice(1), pcap-filter(@MAN_MISC_INFO@), pfconfig(8), +usermod(1M) +.SH AUTHORS +The original authors of libpcap are: +.LP +Van Jacobson, +Craig Leres and +Steven McCanne, all of the +Lawrence Berkeley National Laboratory, University of California, Berkeley, CA. +.LP +The current version is available from "The Tcpdump Group"'s Web site at +.LP +.RS +.I http://www.tcpdump.org/ +.RE +.SH BUGS +Please send problems, bugs, questions, desirable enhancements, etc. to: +.LP +.RS +tcpdump-workers@lists.tcpdump.org +.RE diff --git a/libpcap/pcap.c b/libpcap/pcap.c index 05ba1418c..010ef74cd 100644 --- a/libpcap/pcap.c +++ b/libpcap/pcap.c @@ -33,7 +33,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.88.2.17 2007/06/22 06:43:58 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.112.2.12 2008-09-22 20:16:01 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -70,10 +70,205 @@ static const char rcsid[] _U_ = #include #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); +} + +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 */ +#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, it can set the op to its routine to check + * whether a particular device supports it. + */ + p->can_set_rfmon_op = pcap_cant_set_rfmon; + + /* + * Some operations can be performed only on activated pcap_t's; + * have those operations handled by a "not supported" handler + * until the pcap_t is activated. + */ + 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 + p->cleanup_op = pcap_cleanup_live_common; + + /* 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; + 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_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; + + status = p->activate_op(p); + if (status >= 0) + p->activated = 1; + 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 || status == PCAP_ERROR_NO_SUCH_DEVICE || + status == PCAP_ERROR_PERM_DENIED) + strlcpy(errbuf, p->errbuf, PCAP_ERRBUF_SIZE); + 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); } @@ -221,6 +416,12 @@ 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) { @@ -240,7 +441,7 @@ pcap_list_datalinks(pcap_t *p, int **dlt_buffer) **dlt_buffer = p->linktype; return (1); } else { - *dlt_buffer = (int*)malloc(sizeof(**dlt_buffer) * p->dlt_count); + *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)); @@ -252,6 +453,23 @@ pcap_list_datalinks(pcap_t *p, int **dlt_buffer) } } +/* + * 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) { @@ -327,7 +545,7 @@ 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, "ARCNET"), + DLT_CHOICE(DLT_ARCNET, "BSD ARCNET"), DLT_CHOICE(DLT_SLIP, "SLIP"), DLT_CHOICE(DLT_PPP, "PPP"), DLT_CHOICE(DLT_FDDI, "FDDI"), @@ -338,6 +556,7 @@ static struct dlt_choice dlt_choices[] = { 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"), @@ -349,17 +568,25 @@ static struct dlt_choice dlt_choices[] = { 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 BSD radio information header"), - DLT_CHOICE(DLT_APPLE_IP_OVER_IEEE1394, "Apple IP-over-IEEE 1394"), + 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_LINUX_LAPD, "Linux vISDN LAPD"), DLT_CHOICE(DLT_IEEE802_11_RADIO_AVS, "802.11 plus AVS radio information header"), - DLT_CHOICE(DLT_SYMANTEC_FIREWALL, "Symantec Firewall"), - DLT_CHOICE(DLT_JUNIPER_ATM1, "Juniper ATM1 PIC"), - DLT_CHOICE(DLT_JUNIPER_ATM2, "Juniper ATM2 PIC"), - DLT_CHOICE(DLT_JUNIPER_MLPPP, "Juniper Multi-Link PPP"), + DLT_CHOICE(DLT_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"), @@ -367,27 +594,35 @@ static struct dlt_choice dlt_choices[] = { DLT_CHOICE(DLT_GPF_T, "GPF-T"), DLT_CHOICE(DLT_GPF_F, "GPF-F"), DLT_CHOICE(DLT_JUNIPER_PIC_PEER, "Juniper PIC Peer"), - DLT_CHOICE(DLT_JUNIPER_MLFR, "Juniper Multi-Link Frame Relay"), DLT_CHOICE(DLT_ERF_ETH, "Ethernet with Endace ERF header"), DLT_CHOICE(DLT_ERF_POS, "Packet-over-SONET with Endace ERF header"), - DLT_CHOICE(DLT_JUNIPER_GGSN, "Juniper GGSN PIC"), - DLT_CHOICE(DLT_JUNIPER_ES, "Juniper Encryption Services PIC"), - DLT_CHOICE(DLT_JUNIPER_MONITOR, "Juniper Passive Monitor PIC"), - DLT_CHOICE(DLT_JUNIPER_SERVICES, "Juniper Advanced Services PIC"), - DLT_CHOICE(DLT_JUNIPER_MFR, "Juniper FRF.16 Frame Relay"), + 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_MTP2, "SS7 MTP2"), 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_MTP2_WITH_PHDR, "SS7 MTP2 with Pseudo-header"), + 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"), + 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_SENTINEL }; @@ -678,6 +913,53 @@ pcap_win32strerror(void) } #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_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"); + } + (void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum); + return(ebuf); +} + /* * Not all systems have strerror(). */ @@ -689,7 +971,7 @@ pcap_strerror(int errnum) #else extern int sys_nerr; extern const char *const sys_errlist[]; - static char ebuf[20]; + static char ebuf[15+10+1]; if ((unsigned int)errnum < sys_nerr) return ((char *)sys_errlist[errnum]); @@ -735,19 +1017,162 @@ pcap_stats_dead(pcap_t *p, struct pcap_stat *ps _U_) return (-1); } -void -pcap_close_common(pcap_t *p) +#ifdef WIN32 +int +pcap_setbuff(pcap_t *p, int dim) { - if (p->buffer != NULL) + 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; + } + pcap_freecode(&p->fcode); #if !defined(WIN32) && !defined(MSDOS) - if (p->fd >= 0) + if (p->fd >= 0) { close(p->fd); + p->fd = -1; + } #endif } static void -pcap_close_dead(pcap_t *p _U_) +pcap_cleanup_dead(pcap_t *p _U_) { /* Nothing to do. */ } @@ -764,7 +1189,13 @@ pcap_open_dead(int linktype, int snaplen) p->snapshot = snaplen; p->linktype = linktype; p->stats_op = pcap_stats_dead; - p->close_op = pcap_close_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; } @@ -795,13 +1226,30 @@ pcap_inject(pcap_t *p, const void *buf, size_t size) void pcap_close(pcap_t *p) { - p->close_op(p); - if (p->dlt_list != NULL) - free(p->dlt_list); - pcap_freecode(&p->fcode); + 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, + const u_char *pkt) +{ + 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, @@ -817,7 +1265,7 @@ pcap_close(pcap_t *p) #ifdef HAVE_VERSION_H #include "version.h" #else -static const char pcap_version_string[] = "libpcap version 0.9.7"; +static const char pcap_version_string[] = "libpcap version 0.9[.x]"; #endif #ifdef WIN32 diff --git a/libpcap/pcap.h b/libpcap/pcap.h index 9c8767e25..935f9494c 100644 --- a/libpcap/pcap.h +++ b/libpcap/pcap.h @@ -1,4 +1,3 @@ -/* -*- 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. @@ -31,294 +30,16 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.52.2.7 2007/06/11 09:52:05 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.59 2006/10/04 18:09:22 guy Exp $ (LBL) */ -#ifndef lib_pcap_h -#define lib_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 */ - -#ifndef PCAP_DONT_INCLUDE_PCAP_BPF_H -#include -#endif - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#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. + * For backwards compatibility. * - * Do not change the layout of this structure, in any way (this includes - * changes that only affect the length of fields in this structure). - * - * Also, do not change the interpretation of any of the members of this - * structure, in any way (this includes using values other than - * LINKTYPE_ values, as defined in "savefile.c", in the "linktype" - * field). - * - * Instead: - * - * introduce a new structure for the new format, if the layout - * of the structure changed; - * - * send mail to "tcpdump-workers@tcpdump.org", requesting a new - * magic number for your new capture file format, and, when - * you get the new magic number, put it in "savefile.c"; - * - * use that magic number for save files with the changed file - * header; - * - * make the code in "savefile.c" capable of reading files with - * the old file header as well as files with the new file header - * (using the magic number to determine the header format). - * - * Then supply the changes to "patches@tcpdump.org", so that future - * versions of libpcap and programs that use it (such as tcpdump) will - * be able to read your new capture file format. + * Note to OS vendors: do NOT get rid of this file! Many applications + * expect to be able to include , and at least some of them + * go through contortions in their configure scripts to try to detect + * OSes that have "helpfully" moved pcap.h to without + * leaving behind a file. */ -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_*) */ -}; - -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 XXX not yet supported */ -#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 *); - -char *pcap_lookupdev(char *); -int pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *); -pcap_t *pcap_open_live(const char *, int, int, int, char *); -pcap_t *pcap_open_dead(int, int); -pcap_t *pcap_open_offline(const char *, char *); -pcap_t *pcap_fopen_offline(FILE *, char *); -void pcap_close(pcap_t *); -int pcap_loop(pcap_t *, int, pcap_handler, u_char *); -int pcap_dispatch(pcap_t *, int, pcap_handler, u_char *); -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 *); -void pcap_perror(pcap_t *, char *); -int pcap_inject(pcap_t *, const void *, size_t); -int pcap_sendpacket(pcap_t *, const u_char *, int); -const char *pcap_strerror(int); -char *pcap_geterr(pcap_t *); -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_datalink(pcap_t *); -int pcap_list_datalinks(pcap_t *, int **); -int pcap_set_datalink(pcap_t *, int); -int pcap_datalink_name_to_val(const char *); -const char *pcap_datalink_val_to_name(int); -const char *pcap_datalink_val_to_description(int); -int pcap_snapshot(pcap_t *); -int pcap_is_swapped(pcap_t *); -int pcap_major_version(pcap_t *); -int pcap_minor_version(pcap_t *); - -/* XXX */ -FILE *pcap_file(pcap_t *); -int pcap_fileno(pcap_t *); - -pcap_dumper_t *pcap_dump_open(pcap_t *, const char *); -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); - -/* XXX this guy lives in the bpf tree */ -u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int); -int bpf_validate(struct bpf_insn *f, int len); -char *bpf_image(struct bpf_insn *, int); -void bpf_dump(struct bpf_program *, int); - -#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 +#include diff --git a/libpcap/pcap/bluetooth.h b/libpcap/pcap/bluetooth.h new file mode 100644 index 000000000..7bf65df03 --- /dev/null +++ b/libpcap/pcap/bluetooth.h @@ -0,0 +1,48 @@ +/* + * 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 data struct + * By Paolo Abeni + * + * @(#) $Header: /tcpdump/master/libpcap/pcap/bluetooth.h,v 1.1 2007/09/22 02:10:17 guy Exp $ + */ + +#ifndef _PCAP_BLUETOOTH_STRUCTS_H__ +#define _PCAP_BLUETOOTH_STRUCTS_H__ + +/* + * Header prepended libpcap to each bluetooth h:4 frame. + * fields are in network byte order + */ +typedef struct _pcap_bluetooth_h4_header { + u_int32_t direction; /* if first bit is set direction is incoming */ +} pcap_bluetooth_h4_header; + + +#endif diff --git a/libpcap/pcap/bpf.h b/libpcap/pcap/bpf.h new file mode 100644 index 000000000..9f4ca33e3 --- /dev/null +++ b/libpcap/pcap/bpf.h @@ -0,0 +1,934 @@ +/*- + * 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.19.2.8 2008-09-22 20:16:01 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. + * + * XXX - should this all just be moved to "pcap.h"? + */ + +#ifndef BPF_MAJOR_VERSION + +#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. + */ +#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)) + +#define BPF_MAXBUFSIZE 0x8000 +#define BPF_MINBUFSIZE 32 + +/* + * Structure for "pcap_compile()", "pcap_setfilter()", etc.. + */ +struct bpf_program { + u_int bf_len; + struct bpf_insn *bf_insns; +}; + +/* + * Struct return by BIOCVERSION. This represents the version number of + * the filter language described by the instruction encodings below. + * bpf understands a program iff kernel_major == filter_major && + * kernel_minor >= filter_minor, that is, if the value returned by the + * running kernel has the same major number and a minor number equal + * equal to or less than the filter being downloaded. Otherwise, the + * results are undefined, meaning an error may be returned or packets + * may be accepted haphazardly. + * It has nothing to do with the source code version. + */ +struct bpf_version { + u_short bv_major; + u_short bv_minor; +}; +/* Current version number of filter architecture. */ +#define BPF_MAJOR_VERSION 1 +#define BPF_MINOR_VERSION 1 + +/* + * Data-link level 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). + */ + +/* + * 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 is used for DLT_OLD_PFLOG in OpenBSD; + * OBSOLETE: DLT_PFLOG is 117 in OpenBSD now as well. See below. + * 18 is used for DLT_PFSYNC in OpenBSD; don't use it for anything else. + */ + +#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 types corresponding to DLT_ types that differ + * between platforms; don't use those values for new DLT_ new types. + */ + +/* + * This value was defined by libpcap 0.5; platforms that have defined + * 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; DLT_PFLOG is 17 in OpenBSD, but that's DLT_LANE8023 + * in SuSE 6.3, so we can't use 17 for it in capture-file headers. + * + * XXX: is there a conflict with DLT_PFSYNC 18 as well? + */ +#ifdef __OpenBSD__ +#define DLT_OLD_PFLOG 17 +#define DLT_PFSYNC 18 +#endif +#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 + +/* + * Reserved for Siemens HiPath HDLC. + */ +#define DLT_HHDLC 121 + +/* + * 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 + +/* + * Reserved for BACnet MS/TP. + */ +#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 . + */ +#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 + + +/* + * 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(const struct bpf_insn *, const 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 diff --git a/libpcap/pcap/namedb.h b/libpcap/pcap/namedb.h new file mode 100644 index 000000000..9002c7509 --- /dev/null +++ b/libpcap/pcap/namedb.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 1994, 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/namedb.h,v 1.1 2006/10/04 18:09:22 guy Exp $ (LBL) + */ + +#ifndef lib_pcap_namedb_h +#define lib_pcap_namedb_h + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * As returned by the pcap_next_etherent() + * XXX this stuff doesn't belong in this interface, but this + * library already must do name to address translation, so + * on systems that don't have support for /etc/ethers, we + * export these hooks since they'll + */ +struct pcap_etherent { + u_char addr[6]; + char name[122]; +}; +#ifndef PCAP_ETHERS_FILE +#define PCAP_ETHERS_FILE "/etc/ethers" +#endif +struct pcap_etherent *pcap_next_etherent(FILE *); +u_char *pcap_ether_hostton(const char*); +u_char *pcap_ether_aton(const char *); + +bpf_u_int32 **pcap_nametoaddr(const char *); +#ifdef INET6 +struct addrinfo *pcap_nametoaddrinfo(const char *); +#endif +bpf_u_int32 pcap_nametonetaddr(const char *); + +int pcap_nametoport(const char *, int *, int *); +int pcap_nametoportrange(const char *, int *, int *, int *); +int pcap_nametoproto(const char *); +int pcap_nametoeproto(const char *); +int pcap_nametollc(const char *); +/* + * If a protocol is unknown, PROTO_UNDEF is returned. + * Also, pcap_nametoport() returns the protocol along with the port number. + * If there are ambiguous entried in /etc/services (i.e. domain + * can be either tcp or udp) PROTO_UNDEF is returned. + */ +#define PROTO_UNDEF -1 + +/* XXX move these to pcap-int.h? */ +int __pcap_atodn(const char *, bpf_u_int32 *); +int __pcap_atoin(const char *, bpf_u_int32 *); +u_short __pcap_nametodnaddr(const char *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libpcap/pcap1.h b/libpcap/pcap/pcap.h similarity index 52% rename from libpcap/pcap1.h rename to libpcap/pcap/pcap.h index 08d0c5a6e..ea18edcff 100644 --- a/libpcap/pcap1.h +++ b/libpcap/pcap/pcap.h @@ -31,21 +31,24 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#) $Header: /tcpdump/master/libpcap/pcap1.h,v 1.2 2004/03/30 14:42:50 mcr Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/pcap/pcap.h,v 1.4.2.11 2008-10-06 15:38:39 gianluca Exp $ (LBL) */ -#ifndef lib_pcap_h -#define lib_pcap_h +#ifndef lib_pcap_pcap_h +#define lib_pcap_pcap_h -#ifdef WIN32 -#include -#else /* WIN32 */ -#include -#include -#endif /* WIN32 */ +#if defined(WIN32) + #include +#elif defined(MSDOS) + #include + #include /* u_int, u_char etc. */ +#else /* UN*X */ + #include + #include +#endif /* WIN32/MSDOS/UN*X */ #ifndef PCAP_DONT_INCLUDE_PCAP_BPF_H -#include +#include #endif #include @@ -54,8 +57,8 @@ extern "C" { #endif -#define PCAP_VERSION_MAJOR 3 -#define PCAP_VERSION_MINOR 0 +#define PCAP_VERSION_MAJOR 2 +#define PCAP_VERSION_MINOR 4 #define PCAP_ERRBUF_SIZE 256 @@ -92,8 +95,8 @@ typedef struct pcap_addr pcap_addr_t; * introduce a new structure for the new format, if the layout * of the structure changed; * - * send mail to "tcpdump-workers@tcpdump.org", requesting a new - * magic number for your new capture file format, and, when + * 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 @@ -103,75 +106,56 @@ typedef struct pcap_addr pcap_addr_t; * the old file header as well as files with the new file header * (using the magic number to determine the header format). * - * Then supply the changes to "patches@tcpdump.org", so that future - * versions of libpcap and programs that use it (such as tcpdump) will - * be able to read your new capture file format. + * Then supply the changes as a patch at + * + * http://sourceforge.net/projects/libpcap/ + * + * so that future versions of libpcap and programs that use it (such as + * tcpdump) will be able to read your new capture file format. */ - -enum pcap1_info_types { - PCAP_DATACAPTURE, - PCAP_TIMESTAMP, - PCAP_WALLTIME, - PCAP_TIMESKEW, - PCAP_PROBEPLACE, /* aka direction */ - PCAP_COMMENT, /* comment */ -}; - -struct pcap1_info_container { - bpf_u_int32 info_len; /* in bytes */ - bpf_u_int32 info_type; /* enum pcap1_info_types */ - unsigned char info_data[0]; -}; - -struct pcap1_info_timestamp { - struct pcap1_info_container pic; - bpf_u_int32 nanoseconds; /* 10^-9 of seconds */ - bpf_u_int32 seconds; /* seconds since Unix epoch - GMT */ - bpf_u_int16 macroseconds; /* 16 bits more of MSB of time */ - bpf_u_int16 sigfigs; /* accuracy of timestamps - LSB bits */ -}; - -struct pcap1_info_packet { - struct pcap1_info_container pic; - bpf_u_int32 caplen; /* length of portion present */ - bpf_u_int32 len; /* length this packet (off wire) */ - bpf_u_int32 linktype; /* data link type (LINKTYPE_*) */ - bpf_u_int32 ifIndex; /* abstracted interface index */ - unsigned char packet_data[0]; -}; - -enum pcap1_probe { - INBOUND =1, - OUTBOUND =2, - FORWARD =3, - PREENCAP =4, - POSTDECAP=5, -}; - -struct pcap1_info_probe { - struct pcap1_info_container pic; - bpf_u_int32 probeloc; /* enum pcap1_probe */ - unsigned char probe_desc[0]; -}; - -struct pcap1_info_comment { - struct pcap1_info_container pic; - unsigned char comment[0]; -}; - -struct pcap1_packet_header { +struct pcap_file_header { bpf_u_int32 magic; - u_short version_major; - u_short version_minor; - bpf_u_int32 block_len; - struct pcap1_info_container pics[0]; + 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_*) */ }; /* - * Each packet in the dump file is prepended with this generic header. - * This gets around the problem of different headers for different - * packet interfaces. + * 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() @@ -185,6 +169,39 @@ struct pcap_stat { #endif /* WIN32 */ }; +#ifdef MSDOS +/* + * As returned by the pcap_stats_ex() + */ +struct pcap_stat_ex { + u_long rx_packets; /* total packets received */ + u_long tx_packets; /* total packets transmitted */ + u_long rx_bytes; /* total bytes received */ + u_long tx_bytes; /* total bytes transmitted */ + u_long rx_errors; /* bad packets received */ + u_long tx_errors; /* packet transmit problems */ + u_long rx_dropped; /* no space in Rx buffers */ + u_long tx_dropped; /* no space available for Tx */ + u_long multicast; /* multicast packets received */ + u_long collisions; + + /* detailed rx_errors: */ + u_long rx_length_errors; + u_long rx_over_errors; /* receiver ring buff overflow */ + u_long rx_crc_errors; /* recv'd pkt with crc error */ + u_long rx_frame_errors; /* recv'd frame alignment error */ + u_long rx_fifo_errors; /* recv'r fifo overrun */ + u_long rx_missed_errors; /* recv'r missed packet */ + + /* detailed tx_errors */ + u_long tx_aborted_errors; + u_long tx_carrier_errors; + u_long tx_fifo_errors; + u_long tx_heartbeat_errors; + u_long tx_window_errors; + }; +#endif + /* * Item in a list of interfaces. */ @@ -212,11 +229,57 @@ struct pcap_addr { 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 */ + +/* + * 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 */ + 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_buffer_size(pcap_t *, int); +int pcap_activate(pcap_t *); + 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 *); @@ -226,19 +289,27 @@ 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 *); -void pcap_perror(pcap_t *, char *); -char *pcap_strerror(int); +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 *); -int pcap_compile(pcap_t *, struct bpf_program *, char *, int, +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 *, - char *, int, bpf_u_int32); + 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_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); @@ -252,10 +323,12 @@ 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 *); -FILE *pcap_dump_file(pcap_dumper_t *); int pcap_findalldevs(pcap_if_t **, char *); void pcap_freealldevs(pcap_if_t *); @@ -263,37 +336,49 @@ void pcap_freealldevs(pcap_if_t *); const char *pcap_lib_version(void); /* XXX this guy lives in the bpf tree */ -u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int); -int bpf_validate(struct bpf_insn *f, int len); -char *bpf_image(struct bpf_insn *, int); -void bpf_dump(struct bpf_program *, int); +u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int); +int bpf_validate(const struct bpf_insn *f, int len); +char *bpf_image(const struct bpf_insn *, int); +void bpf_dump(const struct bpf_program *, int); + +#if defined(WIN32) -#ifdef WIN32 /* * Win32 definitions */ int pcap_setbuff(pcap_t *p, int dim); int pcap_setmode(pcap_t *p, int mode); -int pcap_sendpacket(pcap_t *p, u_char *buf, int size); int pcap_setmintocopy(pcap_t *p, int size); #ifdef WPCAP /* Include file with the wpcap-specific extensions */ #include -#endif +#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 */ -#else /* * UN*X definitions */ int pcap_get_selectable_fd(pcap_t *); -#endif /* WIN32 */ +#endif /* WIN32/MSDOS/UN*X */ #ifdef __cplusplus } diff --git a/libpcap/sll.h b/libpcap/pcap/sll.h similarity index 94% rename from libpcap/sll.h rename to libpcap/pcap/sll.h index 85a3a9d97..e9d5452af 100644 --- a/libpcap/sll.h +++ b/libpcap/pcap/sll.h @@ -35,7 +35,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#) $Header: /tcpdump/master/libpcap/sll.h,v 1.7 2002/06/11 17:04:48 itojun Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/pcap/sll.h,v 1.2.2.1 2008-05-30 01:36:06 guy Exp $ (LBL) */ /* @@ -64,8 +64,8 @@ * DO NOT change the layout of this structure, or change any of the * LINUX_SLL_ values below. If you must change the link-layer header * for a "cooked" Linux capture, introduce a new DLT_ type (ask - * "tcpdump-workers@tcpdump.org" for one, so that you don't give it a - * value that collides with a value already being used), and use the + * "tcpdump-workers@lists.tcpdump.org" for one, so that you don't give it + * a value that collides with a value already being used), and use the * new header in captures of that type, so that programs that can * handle DLT_LINUX_SLL captures will continue to handle them correctly * without any change, and so that capture files with different headers @@ -73,6 +73,9 @@ * packets in them. */ +#ifndef lib_pcap_sll_h +#define lib_pcap_sll_h + /* * A DLT_LINUX_SLL fake link-layer header. */ @@ -122,3 +125,5 @@ struct sll_header { */ #define LINUX_SLL_P_802_3 0x0001 /* Novell 802.3 frames without 802.2 LLC header */ #define LINUX_SLL_P_802_2 0x0004 /* 802.2 frames (not D/I/X Ethernet) */ + +#endif diff --git a/libpcap/pcap/usb.h b/libpcap/pcap/usb.h new file mode 100644 index 000000000..adcd19c05 --- /dev/null +++ b/libpcap/pcap/usb.h @@ -0,0 +1,90 @@ +/* + * 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. + * + * Basic USB data struct + * By Paolo Abeni + * + * @(#) $Header: /tcpdump/master/libpcap/pcap/usb.h,v 1.6 2007/09/22 02:06:08 guy Exp $ + */ + +#ifndef _PCAP_USB_STRUCTS_H__ +#define _PCAP_USB_STRUCTS_H__ + +/* + * possible transfer mode + */ +#define URB_TRANSFER_IN 0x80 +#define URB_ISOCHRONOUS 0x0 +#define URB_INTERRUPT 0x1 +#define URB_CONTROL 0x2 +#define URB_BULK 0x3 + +/* + * possible event type + */ +#define URB_SUBMIT 'S' +#define URB_COMPLETE 'C' +#define URB_ERROR 'E' + +/* + * USB setup header as defined in USB specification. + * Appears at the front of each packet in DLT_USB captures. + */ +typedef struct _usb_setup { + u_int8_t bmRequestType; + u_int8_t bRequest; + u_int16_t wValue; + u_int16_t wIndex; + u_int16_t wLength; +} pcap_usb_setup; + + +/* + * Header prepended by linux kernel to each event. + * Appears at the front of each packet in DLT_USB_LINUX captures. + */ +typedef struct _usb_header { + u_int64_t id; + u_int8_t event_type; + u_int8_t transfer_type; + u_int8_t endpoint_number; + u_int8_t device_address; + u_int16_t bus_id; + char setup_flag;/*if !=0 the urb setup header is not present*/ + char data_flag; /*if !=0 no urb data is present*/ + int64_t ts_sec; + int32_t ts_usec; + int32_t status; + u_int32_t urb_len; + u_int32_t data_len; /* amount of urb data really present in this event*/ + pcap_usb_setup setup; +} pcap_usb_header; + + +#endif diff --git a/libpcap/pcap/vlan.h b/libpcap/pcap/vlan.h new file mode 100644 index 000000000..b0cb7949b --- /dev/null +++ b/libpcap/pcap/vlan.h @@ -0,0 +1,46 @@ +/*- + * Copyright (c) 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 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. + * + * @(#) $Header: /tcpdump/master/libpcap/pcap/vlan.h,v 1.1.2.2 2008-08-06 07:45:59 guy Exp $ + */ + +#ifndef lib_pcap_vlan_h +#define lib_pcap_vlan_h + +struct vlan_tag { + u_int16_t vlan_tpid; /* ETH_P_8021Q */ + u_int16_t vlan_tci; /* VLAN TCI */ +}; + +#define VLAN_TAG_LEN 4 + +#endif diff --git a/libpcap/pcap_activate.3pcap b/libpcap/pcap_activate.3pcap new file mode 100644 index 000000000..5b1913604 --- /dev/null +++ b/libpcap/pcap_activate.3pcap @@ -0,0 +1,89 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_activate.3pcap,v 1.1.2.5 2008-07-01 08:04:03 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_ACTIVATE 3PCAP "5 April 2008" +.SH NAME +pcap_activate \- activate a capture handle +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +int pcap_activate(pcap_t *p); +.ft +.fi +.SH DESCRIPTION +.B pcap_activate() +is used to activate a packet capture handle to look +at packets on the network, with the options that were set on the handle +being in effect. +.SH RETURN VALUE +.B pcap_activate() +returns 0 on success without warnings, +.B PCAP_WARNING_PROMISC_NOTSUP +on success on a device that doesn't support promiscuous mode if +promiscuous mode was requested, +.B PCAP_WARNING +on success with any other warning, +.B PCAP_ERROR_ACTIVATED +if the handle has already been activated, +.B PCAP_ERROR_NO_SUCH_DEVICE +if the capture source specified when the handle was created doesn't +exist, +.B PCAP_ERROR_PERM_DENIED +if the process doesn't have permission to open the capture source, +.B PCAP_ERROR_RFMON_NOTSUP +if monitor mode was specified but the capture source doesn't support +monitor mode, +.B PCAP_ERROR_IFACE_NOT_UP +if the capture source is not up, and +.B PCAP_ERROR +if another error occurred. +If +.B PCAP_WARNING +or +.B PCAP_ERROR +is returned, +.B pcap_geterr() +or +.B pcap_perror() +may be called with +.I p +as an argument to fetch or display a message describing the warning or +error. +If +.BR PCAP_WARNING_PROMISC_NOTSUP , +.BR PCAP_ERROR_NO_SUCH_DEVICE , +or +.B PCAP_ERROR_PERM_DENIED +is returned, +.B pcap_geterr() +or +.B pcap_perror() +may be called with +.I p +as an argument to fetch or display an message giving additional details +about the problem that might be useful for debugging the problem if it's +unexpected. +.SH SEE ALSO +pcap(3PCAP) diff --git a/libpcap/pcap_breakloop.3pcap b/libpcap/pcap_breakloop.3pcap new file mode 100644 index 000000000..cf7886032 --- /dev/null +++ b/libpcap/pcap_breakloop.3pcap @@ -0,0 +1,105 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_breakloop.3pcap,v 1.1.2.3 2008-04-06 03:21:55 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. +.PP +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. +.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) diff --git a/libpcap/pcap_can_set_rfmon.3pcap b/libpcap/pcap_can_set_rfmon.3pcap new file mode 100644 index 000000000..992d2c8c4 --- /dev/null +++ b/libpcap/pcap_can_set_rfmon.3pcap @@ -0,0 +1,60 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_can_set_rfmon.3pcap,v 1.1.2.1 2008-04-06 03:21:55 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_CAN_SET_RFMON 3PCAP "5 April 2008" +.SH NAME +pcap_can_set_rfmon \- check whether monitor mode can be set for a +not-yet-activated capture handle +.SH SYNOPSIS +.nf +.ft B +#include +.LP +.ft B +int pcap_can_set_rfmon(pcap_t *p); +.ft +.fi +.SH DESCRIPTION +.B pcap_can_set_rfmon() +checks whether monitor mode could be set on a capture handle when +the handle is activated. +.SH RETURN VALUE +.B pcap_set_rfmon() +returns 0 if monitor mode could not be set, +1 if monitor mode could be set, +.B PCAP_ERROR_NO_SUCH_DEVICE +if the device specified when the handle was created doesn't exist, +.B PCAP_ERROR_ACTIVATED +if called on a capture handle that has been activated, or +.B PCAP_ERROR +if an error occurred. +If +.B PCAP_ERROR +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_create(3PCAP), pcap_activate(3PCAP), +pcap_set_rfmon(3PCAP) diff --git a/libpcap/pcap_close.3pcap b/libpcap/pcap_close.3pcap new file mode 100644 index 000000000..3d92f0306 --- /dev/null +++ b/libpcap/pcap_close.3pcap @@ -0,0 +1,41 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_close.3pcap,v 1.1.2.3 2008-04-06 03:21:55 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_CLOSE 3PCAP "5 April 2008" +.SH NAME +pcap_close \- close a capture device or savefile +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +void pcap_close(pcap_t *p); +.ft +.fi +.SH DESCRIPTION +.B pcap_close() +closes the files associated with +.I p +and deallocates resources. +.SH SEE ALSO +pcap(3PCAP) diff --git a/libpcap/pcap_compile.3pcap.in b/libpcap/pcap_compile.3pcap.in new file mode 100644 index 000000000..87e277869 --- /dev/null +++ b/libpcap/pcap_compile.3pcap.in @@ -0,0 +1,72 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_compile.3pcap.in,v 1.1.2.2 2008-10-21 07:44:57 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_COMPILE 3PCAP "5 April 2008" +.SH NAME +pcap_compile \- compile a filter expression +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +int pcap_compile(pcap_t *p, struct bpf_program *fp, +.ti +8 +const char *str, int optimize, bpf_u_int32 netmask); +.ft +.fi +.SH DESCRIPTION +.B pcap_compile() +is used to compile the string +.I str +into a filter program. See +.BR pcap-filter (@MAN_MISC_INFO@) +for the syntax of that string. +.I program +is a pointer to a +.I bpf_program +struct and is filled in by +.BR pcap_compile() . +.I optimize +controls whether optimization on the resulting code is performed. +.I netmask +specifies the IPv4 netmask of the network on which packets are being +captured; it is used only when checking for IPv4 broadcast addresses in +the filter program. If the netmask of the network on which packets are +being captured isn't known to the program, or if packets are being +captured on the Linux "any" pseudo-interface that can capture on more +than one network, a value of 0 can be supplied; tests for IPv4 broadcast +addreses won't be done correctly, but all other tests in the filter +program will be OK. +.SH RETURN VALUE +.B pcap_compile() +returns 0 on success and \-1 on failure. +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_setfilter(3PCAP), pcap_freecode(3PCAP), +pcap_geterr(3PCAP), pcap-filter(@MAN_MISC_INFO@) diff --git a/libpcap/pcap_create.3pcap b/libpcap/pcap_create.3pcap new file mode 100644 index 000000000..32071b335 --- /dev/null +++ b/libpcap/pcap_create.3pcap @@ -0,0 +1,74 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_create.3pcap,v 1.1.2.1 2008-04-06 03:21:55 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_CREATE 3PCAP "5 April 2008" +.SH NAME +pcap_create \- create a live capture handle +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.nf +.ft B +char errbuf[PCAP_ERRBUF_SIZE]; +.ft +.LP +.ft B +pcap_t *pcap_create(const char *source, char *errbuf); +.ft +.fi +.SH DESCRIPTION +.B pcap_create() +is used to create a packet capture handle to look +at packets on the network. +.I source +is a string that specifies the network device to open; on Linux systems +with 2.2 or later kernels, a +.I source +argument of "any" or +.B NULL +can be used to capture packets from all interfaces. +.PP +The returned handle must be activated with +.B pcap_activate() +before packets can be captured +with it; options for the capture, such as promiscuous mode, can be set +on the handle before activating it. +.SH RETURN VALUE +.B pcap_create() +returns a +.I pcap_t * +on success and +.B NULL +on failure. +If +.B NULL +is returned, +.I errbuf +is filled in with an appropriate error message. +.I errbuf +is assumed to be able to hold at least +.B PCAP_ERRBUF_SIZE +chars. +.SH SEE ALSO +pcap(3PCAP), pcap_activate(3PCAP) diff --git a/libpcap/pcap_datalink.3pcap.in b/libpcap/pcap_datalink.3pcap.in new file mode 100644 index 000000000..83426f05c --- /dev/null +++ b/libpcap/pcap_datalink.3pcap.in @@ -0,0 +1,41 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_datalink.3pcap.in,v 1.1.2.2 2008-10-21 07:44:57 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_DATALINK 3PCAP "5 April 2008" +.SH NAME +pcap_datalink \- get the link-layer header type +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +int pcap_datalink(pcap_t *p); +.ft +.fi +.SH DESCRIPTION +.B pcap_datalink() +returns the link layer type for the live capture or ``savefile'' +specified by +.IR p . +.SH SEE ALSO +pcap(3PCAP), pcap-linktype(@MAN_MISC_INFO@) diff --git a/libpcap/pcap_datalink_name_to_val.3pcap b/libpcap/pcap_datalink_name_to_val.3pcap new file mode 100644 index 000000000..f51b933e3 --- /dev/null +++ b/libpcap/pcap_datalink_name_to_val.3pcap @@ -0,0 +1,48 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_datalink_name_to_val.3pcap,v 1.1.2.3 2008-04-06 03:21:55 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_DATALINK_NAME_TO_VAL 3PCAP "5 April 2008" +.SH NAME +pcap_datalink_name_to_val \- get the link-layer header type value +corresponding to a header type name +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +int pcap_datalink_name_to_val(const char *name); +.ft +.fi +.SH DESCRIPTION +.B pcap_datalink_name_to_val() +translates a data link type name, which is a +.B DLT_ +name with the +.B DLT_ +removed, to the corresponding data link type value. The translation +is case-insensitive. +.SH RETURN VALUE +.B pcap_datalink_name_to_val() +returns 0 on success and \-1 on failure. +.SH SEE ALSO +pcap(3PCAP) diff --git a/libpcap/pcap_datalink_val_to_name.3pcap b/libpcap/pcap_datalink_val_to_name.3pcap new file mode 100644 index 000000000..476bf1036 --- /dev/null +++ b/libpcap/pcap_datalink_val_to_name.3pcap @@ -0,0 +1,44 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_datalink_val_to_name.3pcap,v 1.1.2.2 2008-05-30 01:32:55 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_DATALINK_VAL_TO_NAME 3 "4 April 2008" +.SH NAME +pcap_datalink_val_to_name, pcap_datalink_val_to_description \- get a +name or description for a link-layer header type value +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +const char *pcap_datalink_val_to_name(int dlt); +const char *pcap_datalink_val_to_description(int dlt); +.ft +.fi +.SH DESCRIPTION +.B pcap_datalink_val_to_name() +translates a data link type value to the corresponding data link type +name. NULL is returned on failure. +.PP +.B pcap_datalink_val_to_description() +translates a data link type value to a short description of that data +link type. NULL is returned on failure. diff --git a/libpcap/pcap_dump.3pcap b/libpcap/pcap_dump.3pcap new file mode 100644 index 000000000..1808869b7 --- /dev/null +++ b/libpcap/pcap_dump.3pcap @@ -0,0 +1,53 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_dump.3pcap,v 1.1.2.3 2008-04-06 03:21:55 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_DUMP 3PCAP "5 April 2008" +.SH NAME +pcap_dump \- write a packet to a capture file +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +void pcap_dump(u_char *user, struct pcap_pkthdr *h, +.ti +8 +u_char *sp); +.ft +.fi +.SH DESCRIPTION +.B pcap_dump() +outputs a packet to the ``savefile'' opened with +.BR pcap_dump_open() . +Note that its calling arguments are suitable for use with +.B pcap_dispatch() +or +.BR pcap_loop() . +If called directly, the +.I user +parameter is of type +.B pcap_dumper_t +as returned by +.BR pcap_dump_open() . +.SH SEE ALSO +pcap(3PCAP), pcap_dump_open(3PCAP), pcap_dispatch(3PCAP), +pcap_loop(3PCAP) diff --git a/libpcap/pcap_dump_close.3pcap b/libpcap/pcap_dump_close.3pcap new file mode 100644 index 000000000..07b690a86 --- /dev/null +++ b/libpcap/pcap_dump_close.3pcap @@ -0,0 +1,39 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_dump_close.3pcap,v 1.1.2.3 2008-04-06 03:21:55 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_DUMP_CLOSE 3PCAP "5 April 2008" +.SH NAME +pcap_dump_close \- close a savefile being written to +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +void pcap_dump_close(pcap_dumper_t *p); +.ft +.fi +.SH DESCRIPTION +.B pcap_dump_close() +closes the ``savefile.'' +.SH SEE ALSO +pcap(3PCAP), pcap_dump_open(3PCAP), pcap_dump(3PCAP) diff --git a/libpcap/pcap_dump_file.3pcap b/libpcap/pcap_dump_file.3pcap new file mode 100644 index 000000000..5cf0de65a --- /dev/null +++ b/libpcap/pcap_dump_file.3pcap @@ -0,0 +1,40 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_dump_file.3pcap,v 1.1.2.3 2008-04-06 03:21:55 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_DUMP_FILE 3PCAP "5 April 2008" +.SH NAME +pcap_dump_file \- get the standard I/O stream for a savefile being written +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +FILE *pcap_dump_file(pcap_dumper_t *p); +.ft +.fi +.SH DESCRIPTION +.B pcap_dump_file() +returns the standard I/O stream of the ``savefile'' opened by +.BR pcap_dump_open() . +.SH SEE ALSO +pcap(3PCAP) diff --git a/libpcap/pcap_dump_flush.3pcap b/libpcap/pcap_dump_flush.3pcap new file mode 100644 index 000000000..e83e2a074 --- /dev/null +++ b/libpcap/pcap_dump_flush.3pcap @@ -0,0 +1,45 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_dump_flush.3pcap,v 1.1.2.3 2008-04-06 03:21:55 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_DUMP_FLUSH 3PCAP "5 April 2008" +.SH NAME +pcap_dump_flush \- flush to a savefile packets dumped +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +int pcap_dump_flush(pcap_dumper_t *p); +.ft +.fi +.SH DESCRIPTION +.B pcap_dump_flush() +flushes the output buffer to the ``savefile,'' so that any packets +written with +.B pcap_dump() +but not yet written to the ``savefile'' will be written. +.SH RETURN VALUE +.B pcap_dump_flush() +returns 0 on success and \-1 on failure. +.SH SEE ALSO +pcap(3PCAP), pcap_dump_open(3PCAP), pcap_dump(3PCAP) diff --git a/libpcap/pcap_dump_ftell.3pcap b/libpcap/pcap_dump_ftell.3pcap new file mode 100644 index 000000000..d9c3600ce --- /dev/null +++ b/libpcap/pcap_dump_ftell.3pcap @@ -0,0 +1,44 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_dump_ftell.3pcap,v 1.1.2.3 2008-04-06 03:21:55 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_DUMP_FTELL 3PCAP "5 April 2008" +.SH NAME +pcap_dump_ftell \- get the current file offset for a savefile being written +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +long pcap_dump_ftell(pcap_dumper_t *p); +.ft +.fi +.SH DESCRIPTION +.B pcap_dump_ftell() +returns the current file position for the ``savefile'', representing the +number of bytes written by +.B pcap_dump_open() +and +.BR pcap_dump() . +\-1 is returned on error. +.SH SEE ALSO +pcap(3PCAP), pcap_dump_open(3PCAP), pcap_dump(3PCAP) diff --git a/libpcap/pcap_dump_open.3pcap.in b/libpcap/pcap_dump_open.3pcap.in new file mode 100644 index 000000000..9fe116bb7 --- /dev/null +++ b/libpcap/pcap_dump_open.3pcap.in @@ -0,0 +1,87 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_dump_open.3pcap.in,v 1.1.2.2 2008-10-23 05:59:43 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_DUMP_OPEN 3PCAP "5 April 2008" +.SH NAME +pcap_dump_open, pcap_dump_fopen \- open a file to which to write packets +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.nf +.LP +.ft B +pcap_dumper_t *pcap_dump_open(pcap_t *p, const char *fname); +pcap_dumper_t *pcap_dump_fopen(pcap_t *p, FILE *fp); +.ft +.fi +.SH DESCRIPTION +.B pcap_dump_open() +is called to open a ``savefile'' for writing. +.I fname +specifies the name of the file to open. The file will have +the same format as those used by +.BR tcpdump (1) +and +.BR tcpslice (1). +The name "-" in a synonym +for +.BR stdout . +.PP +.B pcap_dump_fopen() +is called to write data to an existing open stream +.IR fp . +Note that on Windows, that stream should be opened in binary mode. +.PP +.I p +is a capture or ``savefile'' handle returned by an earlier call to +.B pcap_create() +and activated by an earlier call to +.BR pcap_activate() , +or returned by an earlier call to +.BR pcap_open_offline() , +.BR pcap_open_live() , +or +.BR pcap_open_dead() . +The link-layer type and snapshot length from +.I p +are used as the link-layer type and snapshot length of the output file. +.SH RETURN VALUES +A pointer to a +.B pcap_dumper_t +structure to use in subsequent +.B pcap_dump() +and +.B pcap_dump_close() +calls is returned on success. +.B NULL +is returned on failure. +If +.B NULL +is returned, +.B pcap_geterr(\fIp\fB) +can be used to get the error text. +.SH SEE ALSO +pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP), +pcap_open_offline(3PCAP), pcap_open_live(3PCAP), pcap_open_dead(3PCAP), +pcap_dump(3PCAP), pcap_dump_close(3PCAP), pcap_geterr(3PCAP), +pcap-savefile(@MAN_FILE_FORMATS@) diff --git a/libpcap/pcap_file.3pcap b/libpcap/pcap_file.3pcap new file mode 100644 index 000000000..b74e50216 --- /dev/null +++ b/libpcap/pcap_file.3pcap @@ -0,0 +1,59 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_file.3pcap,v 1.1.2.3 2008-04-06 03:21:55 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_FILE 3PCAP "5 April 2008" +.SH NAME +pcap_file \- get the standard I/O stream for a savefile being read +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +FILE *pcap_file(pcap_t *p); +.ft +.fi +.SH DESCRIPTION +.B pcap_file() +returns the standard I/O stream of the ``savefile,'' if a ``savefile'' +was opened with +.BR pcap_open_offline() , +or NULL, if a network device was opened with +.B pcap_create() +and +.BR pcap_activate() , +or with +.BR pcap_open_live() . +.PP +Note that the Packet Capture library is usually built with large file +support, so the standard I/O stream of the ``savefile'' might refer to +a file larger than 2 gigabytes; applications that use +.B pcap_file() +should, if possible, use calls that support large files on the return +value of +.B pcap_file() +or the value returned by +.B fileno() +when passed the return value of +.BR pcap_file() . +.SH SEE ALSO +pcap(3PCAP), pcap_open_offline(3PCAP) diff --git a/libpcap/pcap_fileno.3pcap b/libpcap/pcap_fileno.3pcap new file mode 100644 index 000000000..9c05be0d0 --- /dev/null +++ b/libpcap/pcap_fileno.3pcap @@ -0,0 +1,47 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_fileno.3pcap,v 1.1.2.3 2008-04-06 03:21:55 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_FILENO 3PCAP "5 April 2008" +.SH NAME +pcap_fileno \- get the file descriptor for a live capture +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +int pcap_fileno(pcap_t *p); +.ft +.fi +.SH DESCRIPTION +.B pcap_fileno() +returns the file descriptor number from which captured packets are read, +if a network device was opened with +.B pcap_create() +and +.B pcap_activate() +or with +.BR pcap_open_live() , +or \-1, if a ``savefile'' was opened with +.BR pcap_open_offline() . +.SH SEE ALSO +pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP) diff --git a/libpcap/pcap_findalldevs.3pcap b/libpcap/pcap_findalldevs.3pcap new file mode 100644 index 000000000..93c0455f8 --- /dev/null +++ b/libpcap/pcap_findalldevs.3pcap @@ -0,0 +1,156 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_findalldevs.3pcap,v 1.1.2.3 2008-04-06 03:21:55 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_FINDALLDEVS 3PCAP "5 April 2008" +.SH NAME +pcap_findalldevs \- get a list of capture devices +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.nf +.ft B +char errbuf[PCAP_ERRBUF_SIZE]; +.ft +.LP +.ft B +int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf); +.ft +.fi +.SH DESCRIPTION +.B pcap_findalldevs() +constructs a list of network devices that can be opened with +.B pcap_create() +and +.B pcap_activate() +or with +.BR pcap_open_live() . +(Note that there may be network devices that cannot be opened by the +process calling +.BR pcap_findalldevs() , +because, for example, that process might not have sufficient privileges +to open them for capturing; if so, those devices will not appear on the +list.) +.I alldevsp +is set to point to the first element of the list; each element of the +list is of type +.BR pcap_if_t , +and has the following members: +.RS +.TP +.B next +if not +.BR NULL , +a pointer to the next element in the list; +.B NULL +for the last element of the list +.TP +.B name +a pointer to a string giving a name for the device to pass to +.B pcap_open_live() +.TP +.B description +if not +.BR NULL , +a pointer to a string giving a human-readable description of the device +.TP +.B addresses +a pointer to the first element of a list of addresses for the interface +.TP +.B flags +interface flags: +.RS +.TP +.B PCAP_IF_LOOPBACK +set if the interface is a loopback interface +.RE +.RE +.PP +Each element of the list of addresses is of type +.BR pcap_addr_t , +and has the following members: +.RS +.TP +.B next +if not +.BR NULL , +a pointer to the next element in the list; +.B NULL +for the last element of the list +.TP +.B addr +a pointer to a +.B "struct sockaddr" +containing an address +.TP +.B netmask +if not +.BR NULL , +a pointer to a +.B "struct sockaddr" +that contains the netmask corresponding to the address pointed to by +.B addr +.TP +.B broadaddr +if not +.BR NULL , +a pointer to a +.B "struct sockaddr" +that contains the broadcast address corresponding to the address pointed +to by +.BR addr ; +may be null if the interface doesn't support broadcasts +.TP +.B dstaddr +if not +.BR NULL , +a pointer to a +.B "struct sockaddr" +that contains the destination address corresponding to the address pointed +to by +.BR addr ; +may be null if the interface isn't a point-to-point interface +.RE +.PP +Note that not all the addresses in the list of addresses are +necessarily IPv4 or IPv6 addresses - you must check the +.B sa_family +member of the +.B "struct sockaddr" +before interpreting the contents of the address. +.PP +The list of devices must be freed with +.BR pcap_freealldevs() . +.SH RETURN VALUE +.B pcap_findalldevs() +returns 0 on success and \-1 on failure. +If \-1 is returned, +.I errbuf +is filled in with an appropriate error message. +.I errbuf +is assumed to be able to hold at least +.B PCAP_ERRBUF_SIZE +chars. +.SH SEE ALSO +pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP), +pcap_open_live(3PCAP), pcap_freealldevs(3PCAP) diff --git a/libpcap/pcap_free_datalinks.3pcap b/libpcap/pcap_free_datalinks.3pcap new file mode 100644 index 000000000..8bb7899c7 --- /dev/null +++ b/libpcap/pcap_free_datalinks.3pcap @@ -0,0 +1,41 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_free_datalinks.3pcap,v 1.1.2.1 2008-05-26 19:58:59 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_FREE_DATALINKS 3PCAP "26 May 2008" +.SH NAME +pcap_free_datalinks \- free a list of link-layer header types from +pcap_get_datalinks() +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +void pcap_free_datalinks(int *dlt_list); +.ft +.fi +.SH DESCRIPTION +.B pcap_free_datalinks() +is used to free a list of supported data link types returned by +.BR pcap_list_datalinks() . +.SH SEE ALSO +pcap(3PCAP), pcap_list_datalinks(3PCAP) diff --git a/libpcap/pcap_freealldevs.3pcap b/libpcap/pcap_freealldevs.3pcap new file mode 100644 index 000000000..09d4706df --- /dev/null +++ b/libpcap/pcap_freealldevs.3pcap @@ -0,0 +1,40 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_freealldevs.3pcap,v 1.1.2.3 2008-04-06 03:21:55 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_FREEALLDEVS 3PCAP "5 April 2008" +.SH NAME +pcap_freealldevs \- free a list of capture devices +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +void pcap_freealldevs(pcap_if_t *alldevs); +.ft +.fi +.SH DESCRIPTION +.B pcap_freealldevs() +is used to free a list allocated by +.BR pcap_findalldevs() . +.SH SEE ALSO +pcap(3PCAP), pcap_findalldevs(3PCAP) diff --git a/libpcap/pcap_freecode.3pcap b/libpcap/pcap_freecode.3pcap new file mode 100644 index 000000000..061b50641 --- /dev/null +++ b/libpcap/pcap_freecode.3pcap @@ -0,0 +1,45 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_freecode.3pcap,v 1.1.2.3 2008-04-06 03:21:55 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_FREECODE 3PCAP "5 April 2008" +.SH NAME +pcap_freecode \- free a BPF program +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +void pcap_freecode(struct bpf_program *); +.ft +.fi +.SH DESCRIPTION +.B pcap_freecode() +is used to free up allocated memory pointed to by a +.I bpf_program +struct generated by +.B pcap_compile() +when that BPF program is no longer needed, for example after it +has been made the filter program for a pcap structure by a call to +.BR pcap_setfilter() . +.SH SEE ALSO +pcap(3PCAP), pcap_compile(3PCAP), pcap_setfilter(3PCAP) diff --git a/libpcap/pcap_get_selectable_fd.3pcap b/libpcap/pcap_get_selectable_fd.3pcap new file mode 100644 index 000000000..9026f451b --- /dev/null +++ b/libpcap/pcap_get_selectable_fd.3pcap @@ -0,0 +1,114 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_get_selectable_fd.3pcap,v 1.1.2.3 2008-04-06 03:21: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_GET_SELECTABLE_FD 3PCAP "5 April 2008" +.SH NAME +pcap_get_selectable_fd \- get a file descriptor on which a select() can +be done for a live capture +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +int pcap_get_selectable_fd(pcap_t *p); +.ft +.fi +.SH DESCRIPTION +.B pcap_get_selectable_fd() +returns, on UNIX, a file descriptor number for a file descriptor on +which one can +do a +.B select() +or +.B poll() +to wait for it to be possible to read packets without blocking, if such +a descriptor exists, or \-1, if no such descriptor exists. Some network +devices opened with +.B pcap_create() +and +.BR pcap_activate() , +or with +.BR pcap_open_live() , +do not support +.B select() +or +.B poll() +(for example, regular network devices on FreeBSD 4.3 and 4.4, and Endace +DAG devices), so \-1 is returned for those devices. +.PP +Note that on most versions of most BSDs (including Mac OS X) +.B select() +and +.B poll() +do not work correctly on BPF devices; +.B pcap_get_selectable_fd() +will return a file descriptor on most of those versions (the exceptions +being FreeBSD 4.3 and 4.4), a simple +.B select() +or +.B poll() +will not return even after the read timeout expires. To work around +this, an application that uses +.B select() +or +.B poll() +to wait for packets to arrive must put the +.B pcap_t +in non-blocking mode, and must arrange that the +.B select() +or +.B poll() +have a timeout less than or equal to the read timeout, +and must try to read packets after that timeout expires, regardless of +whether +.B select() +or +.B poll() +indicated that the file descriptor for the +.B pcap_t +is ready to be read or not. (That workaround will not work in FreeBSD +4.3 and later; however, in FreeBSD 4.6 and later, +.B select() +and +.B poll() +work correctly on BPF devices, so the workaround isn't necessary, +although it does no harm.) +.PP +Note also that +.B poll() +doesn't work on character special files, including BPF devices, in Mac +OS X 10.4 and 10.5, so, while +.B select() +can be used on the descriptor returned by +.BR pcap_get_selectable_fd() , +.B poll() +cannot be used on it those versions of Mac OS X. Kqueues also don't +work on that descriptor. +.PP +.B pcap_get_selectable_fd() +is not available on Windows. +.SH RETURN VALUE +A selectable file descriptor is returned if one exists; otherwise, \-1 +is returned. +.SH SEE ALSO +pcap(3PCAP), select(2), poll(2) diff --git a/libpcap/pcap_geterr.3pcap b/libpcap/pcap_geterr.3pcap new file mode 100644 index 000000000..9a46a830c --- /dev/null +++ b/libpcap/pcap_geterr.3pcap @@ -0,0 +1,53 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_geterr.3pcap,v 1.1.2.3 2008-04-06 03:21: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_GETERR 3PCAP "5 April 2008" +.SH NAME +pcap_geterr, pcap_perror \- get or print libpcap error message text +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +char *pcap_geterr(pcap_t *p); +void pcap_perror(pcap_t *p, char *prefix); +.ft +.fi +.SH DESCRIPTION +.B pcap_geterr() +returns the error text pertaining to the last pcap library error. +.BR NOTE : +the pointer it returns will no longer point to a valid error message +string after the +.B pcap_t +passed to it is closed; you must use or copy the string before closing +the +.BR pcap_t . +.PP +.B pcap_perror() +prints the text of the last pcap library error on +.BR stderr , +prefixed by +.IR prefix . +.SH SEE ALSO +pcap(3PCAP) diff --git a/libpcap/pcap_inject.3pcap b/libpcap/pcap_inject.3pcap new file mode 100644 index 000000000..954984c7f --- /dev/null +++ b/libpcap/pcap_inject.3pcap @@ -0,0 +1,90 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_inject.3pcap,v 1.1.2.3 2008-04-06 03:21: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_INJECT 3PCAP "5 April 2008" +.SH NAME +pcap_inject, pcap_sendpacket \- transmit a packet +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +int pcap_inject(pcap_t *p, const void *buf, size_t size); +int pcap_sendpacket(pcap_t *p, const u_char *buf, int size); +.ft +.fi +.SH DESCRIPTION +.B pcap_inject() +sends a raw packet through the network interface; +.I buf +points to the data of the packet, including the link-layer header, and +.I size +is the number of bytes in the packet. +.PP +Note that, even if you successfully open the network interface, you +might not have permission to send packets on it, or it might not support +sending packets; as +.I pcap_open_live() +doesn't have a flag to indicate whether to open for capturing, sending, +or capturing and sending, you cannot request an open that supports +sending and be notified at open time whether sending will be possible. +Note also that some devices might not support sending packets. +.PP +Note that, on some platforms, the link-layer header of the packet that's +sent might not be the same as the link-layer header of the packet +supplied to +.BR pcap_inject() , +as the source link-layer address, if the header contains such an +address, might be changed to be the address assigned to the interface on +which the packet it sent, if the platform doesn't support sending +completely raw and unchanged packets. Even worse, some drivers on some +platforms might change the link-layer type field to whatever value +libpcap used when attaching to the device, even on platforms that +.I do +nominally support sending completely raw and unchanged packets. +.PP +.B pcap_sendpacket() +is like +.BR pcap_inject() , +but it returns 0 on success, rather than returning the number of bytes +written. +.RB ( pcap_inject() +comes from OpenBSD; +.B pcap_sendpacket() +comes from WinPcap. Both are provided for compatibility.) +.SH RETURN VALUE +.B pcap_inject() +returns the number of bytes written on success and \-1 on failure. +.PP +.B pcap_sendpacket() +returns 0 on success and \-1 on failure. +.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) diff --git a/libpcap/pcap_is_swapped.3pcap b/libpcap/pcap_is_swapped.3pcap new file mode 100644 index 000000000..6cc70896f --- /dev/null +++ b/libpcap/pcap_is_swapped.3pcap @@ -0,0 +1,42 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_is_swapped.3pcap,v 1.1.2.3 2008-04-06 03:21: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_IS_SWAPPED 3PCAP "5 April 2008" +.SH NAME +pcap_is_swapped \- find out whether a savefile has the native byte order +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +int pcap_is_swapped(pcap_t *p); +.ft +.fi +.SH DESCRIPTION +.B pcap_is_swapped() +returns true if +.I p +refers to a ``savefile'' that uses a different byte order +than the current system. For a live capture, it always returns false. +.SH SEE ALSO +pcap(3PCAP) diff --git a/libpcap/pcap_lib_version.3pcap b/libpcap/pcap_lib_version.3pcap new file mode 100644 index 000000000..fff914971 --- /dev/null +++ b/libpcap/pcap_lib_version.3pcap @@ -0,0 +1,41 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_lib_version.3pcap,v 1.1.2.3 2008-04-06 03:21: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_LIB_VERSION 3PCAP "5 April 2008" +.SH NAME +pcap_lib_version \- get the version information for libpcap +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +const char *pcap_lib_version(void); +.ft +.fi +.SH DESCRIPTION +.B pcap_lib_version() +returns a pointer to a string giving information about the version of +the libpcap library being used; note that it contains more information +than just a version number. +.SH SEE ALSO +pcap(3PCAP) diff --git a/libpcap/pcap_list_datalinks.3pcap.in b/libpcap/pcap_list_datalinks.3pcap.in new file mode 100644 index 000000000..822c70c51 --- /dev/null +++ b/libpcap/pcap_list_datalinks.3pcap.in @@ -0,0 +1,58 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_list_datalinks.3pcap.in,v 1.1.2.2 2008-10-21 07:44:57 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_LIST_DATALINKS 3PCAP "5 April 2008" +.SH NAME +pcap_list_datalinks \- get a list of link-layer header types supported +by a capture device +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +int pcap_list_datalinks(pcap_t *p, int **dlt_buf); +.ft +.fi +.SH DESCRIPTION +.B pcap_list_datalinks() +is used to get a list of the supported data link types of the interface +associated with the pcap descriptor. +.B pcap_list_datalinks() +allocates an array to hold the list and sets +.IR *dlt_buf . +The caller is responsible for freeing the array with +.BR pcap_free_datalinks (3PCAP). +.SH RETURN VALUE +.B pcap_list_datalinks() +returns the number of data link types in the array on success and \-1 +on failure. +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_free_datalinks(3PCAP), +pcap-linktype(@MAN_MISC_INFO@) diff --git a/libpcap/pcap_lookupdev.3pcap b/libpcap/pcap_lookupdev.3pcap new file mode 100644 index 000000000..2d80bf5b6 --- /dev/null +++ b/libpcap/pcap_lookupdev.3pcap @@ -0,0 +1,62 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_lookupdev.3pcap,v 1.1.2.3 2008-04-06 03:21: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_LOOKUPDEV 3PCAP "5 April 2008" +.SH NAME +pcap_lookupdev \- find the default device on which to capture +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.nf +.ft B +char errbuf[PCAP_ERRBUF_SIZE]; +.ft +.LP +.ft B +char *pcap_lookupdev(char *errbuf); +.ft +.fi +.SH DESCRIPTION +.B pcap_lookupdev() +returns a pointer to a string giving the name of a network device +suitable for use with +.B pcap_create() +and +.BR pcap_activate() , +or with +.BR pcap_open_live() , +and with +.BR pcap_lookupnet() . +If there is an error, +.B NULL +is returned and +.I errbuf +is filled in with an appropriate error message. +.I errbuf +is assumed to be able to hold at least +.B PCAP_ERRBUF_SIZE +chars. +.SH SEE ALSO +pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP), +pcap_open_live(3PCAP), pcap_lookupnet(3PCAP) diff --git a/libpcap/pcap_lookupnet.3pcap b/libpcap/pcap_lookupnet.3pcap new file mode 100644 index 000000000..031acb781 --- /dev/null +++ b/libpcap/pcap_lookupnet.3pcap @@ -0,0 +1,65 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_lookupnet.3pcap,v 1.1.2.3 2008-04-06 03:21: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_LOOKUPNET 3PCAP "5 April 2008" +.SH NAME +pcap_lookupnet \- find the IPv4 network number and netmask for a device +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.nf +.ft B +char errbuf[PCAP_ERRBUF_SIZE]; +.ft +.LP +.ft B +int pcap_lookupnet(const char *device, bpf_u_int32 *netp, +.ti +8 +bpf_u_int32 *maskp, char *errbuf); +.ft +.fi +.SH DESCRIPTION +.B pcap_lookupnet() +is used to determine the IPv4 network number and mask +associated with the network device +.IR device . +Both +.I netp +and +.I maskp +are +.I bpf_u_int32 +pointers. +.SH RETURN VALUE +.B pcap_lookupnet() +returns 0 on success and \-1 on failure. +If \-1 is returned, +.I errbuf +is filled in with an appropriate error message. +.I errbuf +is assumed to be able to hold at least +.B PCAP_ERRBUF_SIZE +chars. +.SH SEE ALSO +pcap(3PCAP) diff --git a/libpcap/pcap_loop.3pcap b/libpcap/pcap_loop.3pcap new file mode 100644 index 000000000..8e491d4c1 --- /dev/null +++ b/libpcap/pcap_loop.3pcap @@ -0,0 +1,150 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_loop.3pcap,v 1.1.2.3 2008-04-06 03:21: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_LOOP 3PCAP "5 April 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 +\fIcnt\fP.) +.ft R +.PP +.I callback +specifies a 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. +.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 +.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) diff --git a/libpcap/pcap_major_version.3pcap b/libpcap/pcap_major_version.3pcap new file mode 100644 index 000000000..1eabcf00f --- /dev/null +++ b/libpcap/pcap_major_version.3pcap @@ -0,0 +1,54 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_major_version.3pcap,v 1.1.2.3 2008-04-06 03:21: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_MAJOR_VERSION 3PCAP "5 April 2008" +.SH NAME +pcap_major_version, pcap_minor_version \- get the version number of a savefile +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +int pcap_major_version(pcap_t *p); +int pcap_minor_version(pcap_t *p); +.ft +.fi +.SH DESCRIPTION +If +.I p +refers to a savefile, +.B pcap_major_version() +returns the major number of the file format of the savefile and +.B pcap_minor_version() +returns the minor number of the file format of the savefile. The +version number is stored in the header of the savefile. +.PP +If +.I p +refers to a live capture, the values returned by +.B pcap_major_version() +and +.B pcap_minor_version() +are not meaningful. +.SH SEE ALSO +pcap(3PCAP) diff --git a/libpcap/pcap_next_ex.3pcap b/libpcap/pcap_next_ex.3pcap new file mode 100644 index 000000000..d472a2b6e --- /dev/null +++ b/libpcap/pcap_next_ex.3pcap @@ -0,0 +1,90 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_next_ex.3pcap,v 1.1.2.3 2008-04-06 03:21: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_NEXT_EX 3PCAP "5 April 2008" +.SH NAME +pcap_next_ex, pcap_next \- read the next packet from a pcap_t +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +int pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header, +.ti +8 +const u_char **pkt_data); +const u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h); +.ft +.fi +.SH DESCRIPTION +.B pcap_next_ex() +reads the next packet and returns a success/failure indication. +If the packet was read without problems, the pointer pointed to by the +.I pkt_header +argument is set to point to the +.I pcap_pkthdr +struct for the packet, and the +pointer pointed to by the +.I pkt_data +argument is set to point to the data in the packet. +.PP +.B pcap_next() +reads the next packet (by calling +.B pcap_dispatch() +with a +.I cnt +of 1) and returns a +.I u_char +pointer to the data in that packet. +The +.I pcap_pkthdr +structure pointed to by +.I h +is filled in with the appropriate values for the packet. +.SH RETURN VALUE +.B pcap_next_ex() +returns 1 if the packet was read without problems, 0 +if packets are being read from a live capture, and the timeout expired, +\-1 if an error occurred while reading the packet, and \-2 if +packets are being read from a ``savefile'', and there are no more +packets to read from the savefile. +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. +.PP +.B pcap_next() +returns a pointer to the packet data on success, and returns +.B NULL +if an error occured, or 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.'' Unfortunately, there is +no way to determine whether an error occured or not. +.SH SEE ALSO +pcap(3PCAP), pcap_geterr(3PCAP), pcap_dispatch(3PCAP) diff --git a/libpcap/pcap_offline_filter.3pcap b/libpcap/pcap_offline_filter.3pcap new file mode 100644 index 000000000..0ec697788 --- /dev/null +++ b/libpcap/pcap_offline_filter.3pcap @@ -0,0 +1,57 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_offline_filter.3pcap,v 1.1.2.1 2008-05-13 15:20:44 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, +.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) diff --git a/libpcap/pcap_open_dead.3pcap.in b/libpcap/pcap_open_dead.3pcap.in new file mode 100644 index 000000000..18c98ffca --- /dev/null +++ b/libpcap/pcap_open_dead.3pcap.in @@ -0,0 +1,52 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_open_dead.3pcap.in,v 1.1.2.2 2008-10-21 07:44:57 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_OPEN_DEAD 3PCAP "5 April 2008" +.SH NAME +pcap_open_dead \- open a fake pcap_t for compiling filters or opening a +capture for output +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +pcap_t *pcap_open_dead(int linktype, int snaplen); +.ft +.fi +.SH DESCRIPTION +.PP +.B pcap_open_dead() +is used for creating a +.B pcap_t +structure to use when calling the other functions in libpcap. It is +typically used when just using libpcap for compiling BPF code. +.PP +.I linktype +specifies the link-layer type for the +.BR pcap_t . +.PP +.I snaplen +specifies the snapshot length for the +.BR pcap_t . +.SH SEE ALSO +pcap(3PCAP), pcap-linktype(@MAN_MISC_INFO@) diff --git a/libpcap/pcap_open_live.3pcap b/libpcap/pcap_open_live.3pcap new file mode 100644 index 000000000..6ef1d5fbd --- /dev/null +++ b/libpcap/pcap_open_live.3pcap @@ -0,0 +1,89 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_open_live.3pcap,v 1.1.2.3 2008-04-06 03:21: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_OPEN_LIVE 3PCAP "5 April 2008" +.SH NAME +pcap_open_live \- open a device for capturing +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.nf +.ft B +char errbuf[PCAP_ERRBUF_SIZE]; +.ft +.LP +.ft B +pcap_t *pcap_open_live(const char *device, int snaplen, +.ti +8 +int promisc, int to_ms, char *errbuf); +.ft +.fi +.SH DESCRIPTION +.B pcap_open_live() +is used to obtain a packet capture handle to look +at packets on the network. +.I device +is a string that specifies the network device to open; on Linux systems +with 2.2 or later kernels, a +.I device +argument of "any" or +.B NULL +can be used to capture packets from all interfaces. +.PP +.I snaplen +specifies the snapshot length to be set on the handle. +.PP +.I promisc +specifies if the interface is to be put into promiscuous mode. +.PP +.I to_ms +specifies the read timeout in milliseconds. +.SH RETURN VALUE +.B pcap_open_live() +returns a +.I pcap_t * +on success and +.B NULL +on failure. +If +.B NULL +is returned, +.I errbuf +is filled in with an appropriate error message. +.I errbuf +may also be set to warning text when +.B pcap_open_live() +succeds; to detect this case the caller should store a zero-length string in +.I errbuf +before calling +.B pcap_open_live() +and display the warning to the user if +.I errbuf +is no longer a zero-length string. +.I errbuf +is assumed to be able to hold at least +.B PCAP_ERRBUF_SIZE +chars. +.SH SEE ALSO +pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP) diff --git a/libpcap/pcap_open_offline.3pcap.in b/libpcap/pcap_open_offline.3pcap.in new file mode 100644 index 000000000..ce350ddf7 --- /dev/null +++ b/libpcap/pcap_open_offline.3pcap.in @@ -0,0 +1,78 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_open_offline.3pcap.in,v 1.1.2.2 2008-10-23 05:59:43 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_OPEN_OFFLINE 3PCAP "5 April 2008" +.SH NAME +pcap_open_offline, pcap_fopen_offline \- open a saved capture file for reading +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.nf +.ft B +char errbuf[PCAP_ERRBUF_SIZE]; +.ft +.LP +.ft B +pcap_t *pcap_open_offline(const char *fname, char *errbuf); +pcap_t *pcap_fopen_offline(FILE *fp, char *errbuf); +.ft +.fi +.SH DESCRIPTION +.B pcap_open_offline() +is called to open a ``savefile'' for reading. +.PP +.I fname +specifies the name of the file to open. The file has +the same format as those used by +.BR tcpdump (1) +and +.BR tcpslice (1). +The name "-" in a synonym for +.BR stdin . +.PP +Alternatively, you may call +.B pcap_fopen_offline() +to read dumped data from an existing open stream +.IR fp . +Note that on Windows, that stream should be opened in binary mode. +.SH RETURN VALUE +.B pcap_open_offline() +and +.B pcap_fopen_offline() +return a +.I pcap_t * +on success and +.B NULL +on failure. +If +.B NULL +is returned, +.I errbuf +is filled in with an appropriate error message. +.I errbuf +is assumed to be able to hold at least +.B PCAP_ERRBUF_SIZE +chars. +.SH SEE ALSO +pcap(3PCAP), pcap-savefile(@MAN_FILE_FORMATS@) diff --git a/libpcap/pcap_set_buffer_size.3pcap b/libpcap/pcap_set_buffer_size.3pcap new file mode 100644 index 000000000..d26a7a5d0 --- /dev/null +++ b/libpcap/pcap_set_buffer_size.3pcap @@ -0,0 +1,47 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_set_buffer_size.3pcap,v 1.1.2.1 2008-04-06 03:21: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_SET_BUFFER_SIZE 3PCAP "5 April 2008" +.SH NAME +pcap_set_buffer_size \- set the buffer size for a not-yet-activated +capture handle +.SH SYNOPSIS +.nf +.ft B +#include +.LP +.ft B +int pcap_set_buffer_size(pcap_t *p, int buffer_size); +.ft +.fi +.SH DESCRIPTION +.B pcap_set_buffer_size() +sets the buffer size that will be used on a capture handle when +the handle is activated to +.IR buffer_size , +which is in units of bytes. +.SH RETURN VALUE +.B pcap_set_buffer_size() +returns 0 on success or +.B PCAP_ERROR_ACTIVATED +if called on a capture handle that has been activated. +.SH SEE ALSO +pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP) diff --git a/libpcap/pcap_set_datalink.3pcap b/libpcap/pcap_set_datalink.3pcap new file mode 100644 index 000000000..5754d764d --- /dev/null +++ b/libpcap/pcap_set_datalink.3pcap @@ -0,0 +1,52 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_set_datalink.3pcap,v 1.1.2.3 2008-04-06 03:21: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_SET_DATALINK 3PCAP "5 April 2008" +.SH NAME +pcap_set_datalink \- set the link-layer header type to be used by a +capture device +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +int pcap_set_datalink(pcap_t *p, int dlt); +.ft +.fi +.SH DESCRIPTION +.B pcap_set_datalink() +is used to set the current data link type of the pcap descriptor +to the type specified by +.IR dlt . +.SH RETURN VALUE +.B pcap_set_datalink() +returns 0 on success and \-1 on failure. +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) diff --git a/libpcap/pcap_set_promisc.3pcap b/libpcap/pcap_set_promisc.3pcap new file mode 100644 index 000000000..27c071455 --- /dev/null +++ b/libpcap/pcap_set_promisc.3pcap @@ -0,0 +1,48 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_set_promisc.3pcap,v 1.1.2.1 2008-04-06 03:21: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_SET_PROMISC 3PCAP "5 April 2008" +.SH NAME +pcap_set_promisc \- set promiscuous mode for a not-yet-activated +capture handle +.SH SYNOPSIS +.nf +.ft B +#include +.LP +.ft B +int pcap_set_promisc(pcap_t *p, int promisc); +.ft +.fi +.SH DESCRIPTION +.B pcap_set_promisc() +sets whether promiscuous mode should be set on a capture handle when +the handle is activated. +If +.I promisc +is non-zero, promiscuous mode will be set, otherwise it will not be set. +.SH RETURN VALUE +.B pcap_set_promisc() +returns 0 on success or +.B PCAP_ERROR_ACTIVATED +if called on a capture handle that has been activated. +.SH SEE ALSO +pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP) diff --git a/libpcap/pcap_set_rfmon.3pcap b/libpcap/pcap_set_rfmon.3pcap new file mode 100644 index 000000000..ceb62a676 --- /dev/null +++ b/libpcap/pcap_set_rfmon.3pcap @@ -0,0 +1,49 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_set_rfmon.3pcap,v 1.1.2.1 2008-04-06 03:21: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_SET_RFMON 3PCAP "5 April 2008" +.SH NAME +pcap_set_rfmon \- set monitor mode for a not-yet-activated capture +handle +.SH SYNOPSIS +.nf +.ft B +#include +.LP +.ft B +int pcap_set_rfmon(pcap_t *p, int rfmon); +.ft +.fi +.SH DESCRIPTION +.B pcap_set_rfmon() +sets whether monitor mode should be set on a capture handle when +the handle is activated. +If +.I rfmon +is non-zero, monitor mode will be set, otherwise it will not be set. +.SH RETURN VALUE +.B pcap_set_rfmon() +returns 0 on success or +.B PCAP_ERROR_ACTIVATED +if called on a capture handle that has been activated. +.SH SEE ALSO +pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP), +pcap_can_set_rfmon(3PCAP) diff --git a/libpcap/pcap_set_snaplen.3pcap b/libpcap/pcap_set_snaplen.3pcap new file mode 100644 index 000000000..10093e482 --- /dev/null +++ b/libpcap/pcap_set_snaplen.3pcap @@ -0,0 +1,46 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_set_snaplen.3pcap,v 1.1.2.1 2008-04-06 03:21: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_SET_SNAPLEN 3PCAP "5 April 2008" +.SH NAME +pcap_set_snaplen \- set the snapshot length for a not-yet-activated +capture handle +.SH SYNOPSIS +.nf +.ft B +#include +.LP +.ft B +int pcap_set_snaplen(pcap_t *p, int snaplen); +.ft +.fi +.SH DESCRIPTION +.B pcap_set_snaplen() +sets the snapshot length to be used on a capture handle when the handle +is activated to +.IR snaplen . +.SH RETURN VALUE +.B pcap_set_snaplen() +returns 0 on success or +.B PCAP_ERROR_ACTIVATED +if called on a capture handle that has been activated. +.SH SEE ALSO +pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP) diff --git a/libpcap/pcap_set_timeout.3pcap b/libpcap/pcap_set_timeout.3pcap new file mode 100644 index 000000000..17f2c31e4 --- /dev/null +++ b/libpcap/pcap_set_timeout.3pcap @@ -0,0 +1,47 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_set_timeout.3pcap,v 1.1.2.1 2008-04-06 03:21: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_SET_TIMEOUT 3PCAP "5 April 2008" +.SH NAME +pcap_set_timeout \- set the read timeout for a not-yet-activated +capture handle +.SH SYNOPSIS +.nf +.ft B +#include +.LP +.ft B +int pcap_set_timeout(pcap_t *p, int to_ms); +.ft +.fi +.SH DESCRIPTION +.B pcap_set_timeout() +sets the read timeout that will be used on a capture handle when +the handle is activated to +.IR to_ms , +which is in units of milliseconds. +.SH RETURN VALUE +.B pcap_set_timeout() +returns 0 on success or +.B PCAP_ERROR_ACTIVATED +if called on a capture handle that has been activated. +.SH SEE ALSO +pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP) diff --git a/libpcap/pcap_setdirection.3pcap b/libpcap/pcap_setdirection.3pcap new file mode 100644 index 000000000..70891a258 --- /dev/null +++ b/libpcap/pcap_setdirection.3pcap @@ -0,0 +1,71 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_setdirection.3pcap,v 1.1.2.3 2008-04-06 03:21: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_SETDIRECTION 3PCAP "5 April 2008" +.SH NAME +pcap_setdirection \- set the direction for which packets will be captured +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +int pcap_setdirection(pcap_t *p, pcap_direction_t d); +.ft +.fi +.SH DESCRIPTION +.B pcap_setdirection() +is used to specify a direction that packets will be captured. +.I d +is one of the constants +.BR PCAP_D_IN , +.B PCAP_D_OUT +or +.BR PCAP_D_INOUT . +.B PCAP_D_IN +will only capture packets received by the device, +.B PCAP_D_OUT +will only capture packets sent by the device and +.B PCAP_D_INOUT +will capture packets received by or sent by the device. +.B PCAP_D_INOUT +is the default setting if this function is not called. +.PP +.B pcap_setdirection() +isn't necessarily fully supported on all platforms; some platforms might +return an error for all values, and some other platforms might not +support +.BR PCAP_D_OUT . +.PP +This operation is not supported if a ``savefile'' is being read. +.SH RETURN VALUE +.B pcap_setdirection() +returns 0 on success and \-1 on failure. +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) diff --git a/libpcap/pcap_setfilter.3pcap b/libpcap/pcap_setfilter.3pcap new file mode 100644 index 000000000..67c1214fa --- /dev/null +++ b/libpcap/pcap_setfilter.3pcap @@ -0,0 +1,54 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_setfilter.3pcap,v 1.1.2.4 2008-05-13 15:20:44 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_SETFILTER 3PCAP "5 April 2008" +.SH NAME +pcap_setfilter \- set the filter +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +int pcap_setfilter(pcap_t *p, struct bpf_program *fp); +.ft +.fi +.SH DESCRIPTION +.B pcap_setfilter() +is used to specify a filter program. +.I fp +is a pointer to a +.I bpf_program +struct, usually the result of a call to +.BR pcap_compile() . +.SH RETURN VALUE +.B pcap_setfilter() +returns 0 on success and \-1 on failure. +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_compile(3PCAP), pcap_geterr(3PCAP) diff --git a/libpcap/pcap_setnonblock.3pcap b/libpcap/pcap_setnonblock.3pcap new file mode 100644 index 000000000..07d962938 --- /dev/null +++ b/libpcap/pcap_setnonblock.3pcap @@ -0,0 +1,75 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_setnonblock.3pcap,v 1.1.2.3 2008-04-06 03:21: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_SETNONBLOCK 3PCAP "5 April 2008" +.SH NAME +pcap_setnonblock, pcap_getnonblock \- set or get the state of +non-blocking mode on a capture device +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.nf +.ft B +char errbuf[PCAP_ERRBUF_SIZE]; +.ft +.LP +.ft B +int pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf); +int pcap_getnonblock(pcap_t *p, char *errbuf); +.ft +.fi +.SH DESCRIPTION +.B pcap_setnonblock() +puts a capture handle into ``non-blocking'' mode, or takes it out +of ``non-blocking'' mode, depending on whether the +.I nonblock +argument is non-zero or zero. It has no effect on ``savefiles''. +If there is an error, \-1 is returned and +.I errbuf +is filled in with an appropriate error message; otherwise, 0 is +returned. +In +``non-blocking'' mode, an attempt to read from the capture descriptor +with +.B pcap_dispatch() +will, if no packets are currently available to be read, return 0 +immediately rather than blocking waiting for packets to arrive. +.B pcap_loop() +and +.B pcap_next() +will not work in ``non-blocking'' mode. +.SH RETURN VALUE +.B pcap_getnonblock() +returns the current ``non-blocking'' state of the capture descriptor; it +always returns 0 on ``savefiles''. +If there is an error, \-1 is returned and +.I errbuf +is filled in with an appropriate error message. +.PP +.I errbuf +is assumed to be able to hold at least +.B PCAP_ERRBUF_SIZE +chars. +.SH SEE ALSO +pcap(3PCAP), pcap_loop(3PCAP), pcap_next_ex(3PCAP), pcap_geterr(3PCAP) diff --git a/libpcap/pcap_snapshot.3pcap b/libpcap/pcap_snapshot.3pcap new file mode 100644 index 000000000..19bb9dec6 --- /dev/null +++ b/libpcap/pcap_snapshot.3pcap @@ -0,0 +1,44 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_snapshot.3pcap,v 1.1.2.3 2008-04-06 03:21: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_SNAPSHOT 3PCAP "5 April 2008" +.SH NAME +pcap_snapshot \- get the snapshot length +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +int pcap_snapshot(pcap_t *p); +.ft +.fi +.SH DESCRIPTION +.B pcap_snapshot() +returns the snapshot length specified when +.B pcap_set_snapshot() +or +.B pcap_open_live() +was called, for a live capture, or the snapshot length from the capture +file, for a ``savefile''. +.SH SEE ALSO +pcap(3PCAP) diff --git a/libpcap/pcap_stats.3pcap b/libpcap/pcap_stats.3pcap new file mode 100644 index 000000000..0a68c1ec2 --- /dev/null +++ b/libpcap/pcap_stats.3pcap @@ -0,0 +1,59 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_stats.3pcap,v 1.1.2.3 2008-04-06 03:21: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_SNAPSHOT 3PCAP "5 April 2008" +.SH NAME +pcap_stats \- get capture statistics +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +int pcap_stats(pcap_t *p, struct pcap_stat *ps); +.ft +.fi +.SH DESCRIPTION +.B pcap_stats() +fills in the +.I pcap_stat +structure pointed to by its second argument. The values represent +packet statistics from the start of the run to the time of the call. +.PP +.B pcap_stats() +is supported only on live captures, not on ``savefiles''; no statistics +are stored in ``savefiles'', so no statistics are available when reading +from a ``savefile''. +.SH RETURN VALUE +.B pcap_stats() +returns 0 on success and returns \-1 if there is an error or the +.I p +doesn't support packet statistics. +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) diff --git a/libpcap/pcap_statustostr.3pcap b/libpcap/pcap_statustostr.3pcap new file mode 100644 index 000000000..5e8942c15 --- /dev/null +++ b/libpcap/pcap_statustostr.3pcap @@ -0,0 +1,43 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_statustostr.3pcap,v 1.1.2.1 2008-04-09 21:41:53 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_STATUSTOSTR 3PCAP "9 April 2008" +.SH NAME +pcap_statustostr \- convert a PCAP_ERROR_ or PCAP_WARNING_ value to a string +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +const char *pcap_statustostr(int error); +.ft +.fi +.SH DESCRIPTION +.B pcap_statustostr() +converts a +.B PCAP_ERROR_ +or +.B PCAP_WARNING_ +value returned by a libpcap routine to an error string. +.SH SEE ALSO +pcap(3PCAP) diff --git a/libpcap/pcap_strerror.3pcap b/libpcap/pcap_strerror.3pcap new file mode 100644 index 000000000..eacdce492 --- /dev/null +++ b/libpcap/pcap_strerror.3pcap @@ -0,0 +1,42 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_strerror.3pcap,v 1.1.2.3 2008-04-06 03:21: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_STRERROR 3PCAP "4 April 2008" +.SH NAME +pcap_strerror \- convert an errno value to a string +.SH SYNOPSIS +.nf +.ft B +#include +.ft +.LP +.ft B +const char *pcap_strerror(int error); +.ft +.fi +.SH DESCRIPTION +.B pcap_strerror() +is provided in case +.BR strerror (3) +isn't available. It returns an error message string corresponding to +.IR error . +.SH SEE ALSO +strerror(3) diff --git a/libpcap/pf.h b/libpcap/pf.h deleted file mode 100644 index a9b127ac2..000000000 --- a/libpcap/pf.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2001 Daniel Hartmeier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - 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. - * - * 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 HOLDERS 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/pf.h,v 1.3 2004/04/02 06:33:30 guy Exp $ (LBL) - */ - -/* from $OpenBSD: pfvar.h,v 1.170 2003/08/22 21:50:34 david Exp $ */ - -enum { PF_INOUT=0, PF_IN=1, PF_OUT=2 }; -enum { PF_PASS=0, PF_DROP=1, PF_SCRUB=2, PF_NAT=3, PF_NONAT=4, - PF_BINAT=5, PF_NOBINAT=6, PF_RDR=7, PF_NORDR=8, PF_SYNPROXY_DROP=9 }; - -/* Reasons code for passing/dropping a packet */ -#define PFRES_MATCH 0 /* Explicit match of a rule */ -#define PFRES_BADOFF 1 /* Bad offset for pull_hdr */ -#define PFRES_FRAG 2 /* Dropping following fragment */ -#define PFRES_SHORT 3 /* Dropping short packet */ -#define PFRES_NORM 4 /* Dropping by normalizer */ -#define PFRES_MEMORY 5 /* Dropped due to lacking mem */ -#define PFRES_MAX 6 /* total+1 */ - -#define PFRES_NAMES { \ - "match", \ - "bad-offset", \ - "fragment", \ - "short", \ - "normalize", \ - "memory", \ - NULL \ -} - -#define PF_RULESET_NAME_SIZE 16 - -/* from $OpenBSD: if_pflog.h,v 1.9 2003/07/15 20:27:27 dhartmei Exp $ */ - -#ifndef IFNAMSIZ -#define IFNAMSIZ 16 -#endif - -struct pfloghdr { - u_int8_t length; - u_int8_t af; - u_int8_t action; - u_int8_t reason; - char ifname[IFNAMSIZ]; - char ruleset[PF_RULESET_NAME_SIZE]; - u_int32_t rulenr; - u_int32_t subrulenr; - u_int8_t dir; - u_int8_t pad[3]; -}; -#define PFLOG_HDRLEN sizeof(struct pfloghdr) diff --git a/libpcap/runlex.sh b/libpcap/runlex.sh new file mode 100755 index 000000000..497a6186f --- /dev/null +++ b/libpcap/runlex.sh @@ -0,0 +1,235 @@ +#! /bin/sh + +# +# runlex.sh +# Script to run Lex/Flex. +# First argument is the (quoted) name of the command; if it's null, that +# means that neither Flex nor Lex was found, so we report an error and +# quit. +# +# @(#) $Header: /tcpdump/master/libpcap/runlex.sh,v 1.1.2.4 2007/12/31 03:39:06 guy Exp $ +# + +# +# Get the name of the command to run, and then shift to get the arguments. +# +if [ $# -eq 0 ] +then + echo "Usage: runlex [ arguments ]" 1>&2 + exit 1 +fi +LEX="$1" +shift + +# +# Check whether we have Lex or Flex. +# +if [ -z "${LEX}" ] +then + echo "Neither lex nor flex was found" 1>&2 + exit 1 +fi + +# +# Process the flags. We don't use getopt because we don't want to +# embed complete knowledge of what options are supported by Lex/Flex. +# +flags="" +outfile=lex.yy.c +while [ $# -ne 0 ] +do + case "$1" in + + -o*) + # + # Set the output file name. + # + outfile=`echo "$1" | sed 's/-o\(.*\)/\1/'` + ;; + + -*) + # + # Add this to the list of flags. + # + flags="$flags $1" + ;; + + --|*) + # + # End of flags. + # + break + ;; + esac + shift +done + +# +# Is it Lex, or is it Flex? +# +if [ "${LEX}" = flex ] +then + # + # It's Flex. + # + have_flex=yes + + # + # Does it support the --noFUNCTION options? If so, we pass + # --nounput, as at least some versions that support those + # options don't support disabling yyunput by defining + # YY_NO_UNPUT. + # + if flex --help | egrep noFUNCTION >/dev/null + then + flags="$flags --nounput" + + # + # Does it support -R, for generating reentrant scanners? + # If so, we're not currently using that feature, but + # it'll generate some unused functions anyway - and there + # won't be any header file declaring them, so there'll be + # defined-but-not-declared warnings. Therefore, we use + # --noFUNCTION options to suppress generating those + # functions. + # + if flex --help | egrep reentrant >/dev/null + then + flags="$flags --noyyget_lineno --noyyget_in --noyyget_out --noyyget_leng --noyyget_text --noyyset_lineno --noyyset_in --noyyset_out" + fi + fi +else + # + # It's Lex. + # + have_flex=no +fi + +# +# OK, run it. +# If it's lex, it doesn't support -o, so we just write to +# lex.yy.c and, if it succeeds, rename it to the right name, +# otherwise we remove lex.yy.c. +# If it's flex, it supports -o, so we use that - flex with -P doesn't +# write to lex.yy.c, it writes to a lex.{prefix from -P}.c. +# +if [ $have_flex = yes ] +then + ${LEX} $flags -o"$outfile" "$@" + + # + # Did it succeed? + # + status=$? + if [ $status -ne 0 ] + then + # + # No. Exit with the failing exit status. + # + exit $status + fi + + # + # Flex has the annoying habit of stripping all but the last + # component of the "-o" flag argument and using that as the + # place to put the output. This gets in the way of building + # in a directory different from the source directory. Try + # to work around this. + # + # Is the outfile where we think it is? + # + outfile_base=`basename "$outfile"` + if [ "$outfile_base" != "$outfile" -a \( ! -r "$outfile" \) -a -r "$outfile_base" ] + then + # + # No, it's not, but it is in the current directory. Put it + # where it's supposed to be. + # + mv "$outfile_base" "$outfile" + + # + # Did that succeed? + # + status=$? + if [ $status -ne 0 ] + then + # + # No. Exit with the failing exit status. + # + exit $status + fi + fi +else + ${LEX} $flags "$@" + + # + # Did it succeed? + # + status=$? + if [ $status -ne 0 ] + then + # + # No. Get rid of any lex.yy.c file we generated, and + # exit with the failing exit status. + # + rm -f lex.yy.c + exit $status + fi + + # + # OK, rename lex.yy.c to the right output file. + # + mv lex.yy.c "$outfile" + + # + # Did that succeed? + # + status=$? + if [ $status -ne 0 ] + then + # + # No. Get rid of any lex.yy.c file we generated, and + # exit with the failing exit status. + # + rm -f lex.yy.c + exit $status + fi +fi + +# +# OK, now let's generate a header file declaring the relevant functions +# defined by the .c file; if the .c file is .../foo.c, the header file +# will be .../foo.h. +# +# This works around some other Flex suckage, wherein it doesn't declare +# the lex routine before defining it, causing compiler warnings. +# XXX - newer versions of Flex support --header-file=, to generate the +# appropriate header file. With those versions, we should use that option. +# + +# +# Get the name of the prefix; scan the source files for a %option prefix +# line. We use the last one. +# +prefix=`sed -n 's/%option[ ][ ]*prefix="\(.*\)".*/\1/p' "$@" | tail -1` +if [ ! -z "$prefix" ] +then + prefixline="#define yylex ${prefix}lex" +fi + +# +# Construct the name of the header file. +# +header_file=`dirname "$outfile"`/`basename "$outfile" .c`.h + +# +# Spew out the declaration. +# +cat <$header_file +/* This is generated by runlex.sh. Do not edit it. */ +$prefixline +#ifndef YY_DECL +#define YY_DECL int yylex(void) +#endif +YY_DECL; +EOF diff --git a/libpcap/savefile.c b/libpcap/savefile.c index b8658502c..65416f64d 100644 --- a/libpcap/savefile.c +++ b/libpcap/savefile.c @@ -30,7 +30,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/savefile.c,v 1.126.2.27 2007/07/19 06:20:53 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/savefile.c,v 1.168.2.10 2008-10-06 15:38:39 gianluca Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -44,6 +44,7 @@ static const char rcsid[] _U_ = #include #include "pcap-int.h" +#include "pcap/usb.h" #ifdef HAVE_OS_PROTO_H #include "os-proto.h" @@ -146,11 +147,12 @@ static const char rcsid[] _U_ = * * 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@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 CVS repository, so that a future - * libpcap release will include it. + * 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 CVS 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 @@ -312,9 +314,9 @@ static const char rcsid[] _U_ = * for *their* private type and tools using them for *your* private type * would have to read them. * - * Instead, in those cases, ask "tcpdump-workers@tcpdump.org" for a new DLT_ - * and LINKTYPE_ value, as per the comment in pcap-bpf.h, and use the type - * you're given. + * 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 @@ -530,6 +532,121 @@ static const char rcsid[] _U_ = */ #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 + static struct linktype_map { int dlt; @@ -781,9 +898,75 @@ static struct linktype_map { /* Various link-layer types for SITA */ { DLT_SITA, LINKTYPE_SITA }, + /* Various link-layer types for Endace */ + { DLT_ERF, LINKTYPE_ERF }, + + /* Special header for u10 Networks boards */ + { DLT_RAIF1, LINKTYPE_RAIF1 }, + + /* IPMB */ + { DLT_IPMB, LINKTYPE_IPMB }, + + /* Juniper Secure Tunnel */ + { DLT_JUNIPER_ST, LINKTYPE_JUNIPER_ST }, + + /* Bluetooth HCI UART transport layer, with pseudo-header */ + { DLT_BLUETOOTH_HCI_H4_WITH_PHDR, LINKTYPE_BLUETOOTH_HCI_H4_WITH_PHDR }, + + /* AX.25 with KISS header */ + { DLT_AX25_KISS, LINKTYPE_AX25_KISS }, + + /* Raw LAPD, with no pseudo-header */ + { DLT_LAPD, LINKTYPE_LAPD }, + + /* PPP with one-byte pseudo-header giving direction */ + { DLT_PPP_WITH_DIR, LINKTYPE_PPP_WITH_DIR }, + + /* Cisco HDLC with one-byte pseudo-header giving direction */ + { DLT_C_HDLC_WITH_DIR, LINKTYPE_C_HDLC_WITH_DIR }, + + /* Frame Relay with one-byte pseudo-header giving direction */ + { DLT_FRELAY_WITH_DIR, LINKTYPE_FRELAY_WITH_DIR }, + + /* LAPB with one-byte pseudo-header giving direction */ + { DLT_LAPB_WITH_DIR, LINKTYPE_LAPB_WITH_DIR }, + + /* IPMB with Linux pseudo-header */ + { DLT_IPMB_LINUX, LINKTYPE_IPMB_LINUX }, + + /* FlexRay */ + { DLT_FLEXRAY, LINKTYPE_FLEXRAY }, + + /* MOST */ + { DLT_MOST, LINKTYPE_MOST }, + + /* LIN */ + { DLT_LIN, LINKTYPE_LIN }, + + /* X2E-private serial line capture */ + { DLT_X2E_SERIAL, LINKTYPE_X2E_SERIAL }, + + /* X2E-private for Xoraya data logger family */ + { DLT_X2E_XORAYA, LINKTYPE_X2E_XORAYA }, + + /* IEEE 802.15.4 with PHY data for non-ASK PHYs */ + { DLT_IEEE802_15_4_NONASK_PHY, LINKTYPE_IEEE802_15_4_NONASK_PHY }, + { -1, -1 } }; +/* + * Mechanism for storing information about a capture in the upper + * 6 bits of a linktype value in a capture file. + * + * LT_LINKTYPE_EXT(x) extracts the additional information. + * + * The rest of the bits are for a value describing the link-layer + * value. LT_LINKTYPE(x) extracts that value. + */ +#define LT_LINKTYPE(x) ((x) & 0x03FFFFFF) +#define LT_LINKTYPE_EXT(x) ((x) & 0xFC000000) + static int dlt_to_linktype(int dlt) { @@ -879,6 +1062,32 @@ sf_stats(pcap_t *p, struct pcap_stat *ps) return (-1); } +#ifdef WIN32 +static int +sf_setbuff(pcap_t *p, int dim) +{ + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "The kernel buffer size cannot be set while reading from a file"); + return (-1); +} + +static int +sf_setmode(pcap_t *p, int mode) +{ + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "impossible to set mode while reading from a file"); + return (-1); +} + +static int +sf_setmintocopy(pcap_t *p, int size) +{ + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "The mintocopy parameter cannot be set while reading from a file"); + return (-1); +} +#endif + static int sf_inject(pcap_t *p, const void *buf _U_, size_t size _U_) { @@ -900,7 +1109,7 @@ sf_setdirection(pcap_t *p, pcap_direction_t d) } static void -sf_close(pcap_t *p) +sf_cleanup(pcap_t *p) { if (p->sf.rfile != stdin) (void)fclose(p->sf.rfile); @@ -945,6 +1154,33 @@ pcap_open_offline(const char *fname, char *errbuf) return (p); } +#ifdef WIN32 +pcap_t* pcap_hopen_offline(intptr_t osfd, char *errbuf) +{ + int fd; + FILE *file; + + fd = _open_osfhandle(osfd, _O_RDONLY); + if ( fd < 0 ) + { + snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno)); + return NULL; + } + + file = _fdopen(fd, "rb"); + if ( file == NULL ) + { + snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno)); + return NULL; + } + + return pcap_fopen_offline(file, errbuf); +} +#endif + +#ifdef WIN32 +static +#endif pcap_t * pcap_fopen_offline(FILE *fp, char *errbuf) { @@ -1014,7 +1250,8 @@ pcap_fopen_offline(FILE *fp, char *errbuf) } p->tzoff = hdr.thiszone; p->snapshot = hdr.snaplen; - p->linktype = linktype_to_dlt(hdr.linktype); + p->linktype = linktype_to_dlt(LT_LINKTYPE(hdr.linktype)); + p->linktype_ext = LT_LINKTYPE_EXT(hdr.linktype); if (magic == KUZNETZOV_TCPDUMP_MAGIC && p->linktype == DLT_EN10MB) { /* * This capture might have been done in raw mode or cooked @@ -1127,7 +1364,13 @@ pcap_fopen_offline(FILE *fp, char *errbuf) p->getnonblock_op = sf_getnonblock; p->setnonblock_op = sf_setnonblock; p->stats_op = sf_stats; - p->close_op = sf_close; +#ifdef WIN32 + p->setbuff_op = sf_setbuff; + p->setmode_op = sf_setmode; + p->setmintocopy_op = sf_setmintocopy; +#endif + p->cleanup_op = sf_cleanup; + p->activated = 1; return (p); bad: @@ -1165,8 +1408,9 @@ sf_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char *buf, u_int buflen) } else { if (amt_read != 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, - "truncated dump file; tried to read %d header bytes, only got %lu", - p->sf.hdrsize, (unsigned long)amt_read); + "truncated dump file; tried to read %lu header bytes, only got %lu", + (unsigned long)p->sf.hdrsize, + (unsigned long)amt_read); return (-1); } /* EOF */ @@ -1276,6 +1520,44 @@ sf_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char *buf, u_int buflen) return (-1); } } + + /* + * The DLT_USB_LINUX header is 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 capture file, we need to convert + * it from the capturing host's byte order to the reading host's + * byte order. + */ + if (p->sf.swapped && p->linktype == DLT_USB_LINUX) { + pcap_usb_header* uhdr = (pcap_usb_header*) buf; + /* + * The URB id is a totally opaque value; do we really need to + * converte it to the reading host's byte order??? + */ + if (hdr->caplen < 8) + return 0; + uhdr->id = SWAPLL(uhdr->id); + if (hdr->caplen < 14) + return 0; + uhdr->bus_id = SWAPSHORT(uhdr->bus_id); + if (hdr->caplen < 24) + return 0; + uhdr->ts_sec = SWAPLL(uhdr->ts_sec); + if (hdr->caplen < 28) + return 0; + uhdr->ts_usec = SWAPLONG(uhdr->ts_usec); + if (hdr->caplen < 32) + return 0; + uhdr->status = SWAPLONG(uhdr->status); + if (hdr->caplen < 36) + return 0; + uhdr->urb_len = SWAPLONG(uhdr->urb_len); + if (hdr->caplen < 40) + return 0; + uhdr->data_len = SWAPLONG(uhdr->data_len); + } return (0); } @@ -1390,6 +1672,7 @@ pcap_dump_open(pcap_t *p, const char *fname) fname, linktype); return (NULL); } + linktype |= p->linktype_ext; if (fname[0] == '-' && fname[1] == '\0') { f = stdout; @@ -1424,6 +1707,7 @@ pcap_dump_fopen(pcap_t *p, FILE *f) linktype); return (NULL); } + linktype |= p->linktype_ext; return (pcap_setup_dump(p, linktype, f, "stream")); } diff --git a/libpcap/scanner.c b/libpcap/scanner.c deleted file mode 100644 index 79c46e616..000000000 --- a/libpcap/scanner.c +++ /dev/null @@ -1,4532 +0,0 @@ - -#line 3 "" - -#define YY_INT_ALIGNED short int - -/* A lexical scanner generated by flex */ - -#define FLEX_SCANNER -#define YY_FLEX_MAJOR_VERSION 2 -#define YY_FLEX_MINOR_VERSION 5 -#define YY_FLEX_SUBMINOR_VERSION 33 -#if YY_FLEX_SUBMINOR_VERSION > 0 -#define FLEX_BETA -#endif - -/* First, we deal with platform-specific or compiler-specific issues. */ - -/* begin standard C headers. */ -#include -#include -#include -#include - -/* end standard C headers. */ - -/* flex integer type definitions */ - -#ifndef FLEXINT_H -#define FLEXINT_H - -/* C99 systems have . Non-C99 systems may or may not. */ - -#if __STDC_VERSION__ >= 199901L - -/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, - * if you want the limit (max/min) macros for int types. - */ -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS 1 -#endif - -#include -typedef int8_t flex_int8_t; -typedef uint8_t flex_uint8_t; -typedef int16_t flex_int16_t; -typedef uint16_t flex_uint16_t; -typedef int32_t flex_int32_t; -typedef uint32_t flex_uint32_t; -#else -typedef signed char flex_int8_t; -typedef short int flex_int16_t; -typedef int flex_int32_t; -typedef unsigned char flex_uint8_t; -typedef unsigned short int flex_uint16_t; -typedef unsigned int flex_uint32_t; -#endif /* ! C99 */ - -/* Limits of integral types. */ -#ifndef INT8_MIN -#define INT8_MIN (-128) -#endif -#ifndef INT16_MIN -#define INT16_MIN (-32767-1) -#endif -#ifndef INT32_MIN -#define INT32_MIN (-2147483647-1) -#endif -#ifndef INT8_MAX -#define INT8_MAX (127) -#endif -#ifndef INT16_MAX -#define INT16_MAX (32767) -#endif -#ifndef INT32_MAX -#define INT32_MAX (2147483647) -#endif -#ifndef UINT8_MAX -#define UINT8_MAX (255U) -#endif -#ifndef UINT16_MAX -#define UINT16_MAX (65535U) -#endif -#ifndef UINT32_MAX -#define UINT32_MAX (4294967295U) -#endif - -#endif /* ! FLEXINT_H */ - -#ifdef __cplusplus - -/* The "const" storage-class-modifier is valid. */ -#define YY_USE_CONST - -#else /* ! __cplusplus */ - -#if __STDC__ - -#define YY_USE_CONST - -#endif /* __STDC__ */ -#endif /* ! __cplusplus */ - -#ifdef YY_USE_CONST -#define yyconst const -#else -#define yyconst -#endif - -/* Returned upon end-of-file. */ -#define YY_NULL 0 - -/* Promotes a possibly negative, possibly signed char to an unsigned - * integer for use as an array index. If the signed char is negative, - * we want to instead treat it as an 8-bit unsigned char, hence the - * double cast. - */ -#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) - -/* Enter a start condition. This macro really ought to take a parameter, - * but we do it the disgusting crufty way forced on us by the ()-less - * definition of BEGIN. - */ -#define BEGIN (yy_start) = 1 + 2 * - -/* Translate the current start state into a value that can be later handed - * to BEGIN to return to the state. The YYSTATE alias is for lex - * compatibility. - */ -#define YY_START (((yy_start) - 1) / 2) -#define YYSTATE YY_START - -/* Action number for EOF rule of a given start state. */ -#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) - -/* Special action meaning "start processing a new file". */ -#define YY_NEW_FILE pcap_restart(pcap_in ) - -#define YY_END_OF_BUFFER_CHAR 0 - -/* Size of default input buffer. */ -#ifndef YY_BUF_SIZE -#define YY_BUF_SIZE 16384 -#endif - -/* The state buf must be large enough to hold one state per character in the main buffer. - */ -#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) - -#ifndef YY_TYPEDEF_YY_BUFFER_STATE -#define YY_TYPEDEF_YY_BUFFER_STATE -typedef struct yy_buffer_state *YY_BUFFER_STATE; -#endif - -extern int pcap_leng; - -extern FILE *pcap_in, *pcap_out; - -#define EOB_ACT_CONTINUE_SCAN 0 -#define EOB_ACT_END_OF_FILE 1 -#define EOB_ACT_LAST_MATCH 2 - - #define YY_LESS_LINENO(n) - -/* Return all but the first "n" matched characters back to the input stream. */ -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up pcap_text. */ \ - int yyless_macro_arg = (n); \ - YY_LESS_LINENO(yyless_macro_arg);\ - *yy_cp = (yy_hold_char); \ - YY_RESTORE_YY_MORE_OFFSET \ - (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ - YY_DO_BEFORE_ACTION; /* set up pcap_text again */ \ - } \ - while ( 0 ) - -#define unput(c) yyunput( c, (yytext_ptr) ) - -/* The following is because we cannot portably get our hands on size_t - * (without autoconf's help, which isn't available because we want - * flex-generated scanners to compile on their own). - */ - -#ifndef YY_TYPEDEF_YY_SIZE_T -#define YY_TYPEDEF_YY_SIZE_T -typedef unsigned int yy_size_t; -#endif - -#ifndef YY_STRUCT_YY_BUFFER_STATE -#define YY_STRUCT_YY_BUFFER_STATE -struct yy_buffer_state - { - FILE *yy_input_file; - - char *yy_ch_buf; /* input buffer */ - char *yy_buf_pos; /* current position in input buffer */ - - /* Size of input buffer in bytes, not including room for EOB - * characters. - */ - yy_size_t yy_buf_size; - - /* Number of characters read into yy_ch_buf, not including EOB - * characters. - */ - int yy_n_chars; - - /* Whether we "own" the buffer - i.e., we know we created it, - * and can realloc() it to grow it, and should free() it to - * delete it. - */ - int yy_is_our_buffer; - - /* Whether this is an "interactive" input source; if so, and - * if we're using stdio for input, then we want to use getc() - * instead of fread(), to make sure we stop fetching input after - * each newline. - */ - int yy_is_interactive; - - /* Whether we're considered to be at the beginning of a line. - * If so, '^' rules will be active on the next match, otherwise - * not. - */ - int yy_at_bol; - - int yy_bs_lineno; /**< The line count. */ - int yy_bs_column; /**< The column count. */ - - /* Whether to try to fill the input buffer when we reach the - * end of it. - */ - int yy_fill_buffer; - - int yy_buffer_status; - -#define YY_BUFFER_NEW 0 -#define YY_BUFFER_NORMAL 1 - /* When an EOF's been seen but there's still some text to process - * then we mark the buffer as YY_EOF_PENDING, to indicate that we - * shouldn't try reading from the input source any more. We might - * still have a bunch of tokens to match, though, because of - * possible backing-up. - * - * When we actually see the EOF, we change the status to "new" - * (via pcap_restart()), so that the user can continue scanning by - * just pointing pcap_in at a new input file. - */ -#define YY_BUFFER_EOF_PENDING 2 - - }; -#endif /* !YY_STRUCT_YY_BUFFER_STATE */ - -/* Stack of input buffers. */ -static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ -static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ -static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ - -/* We provide macros for accessing buffer states in case in the - * future we want to put the buffer states in a more general - * "scanner state". - * - * Returns the top of the stack, or NULL. - */ -#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ - ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ - : NULL) - -/* Same as previous macro, but useful when we know that the buffer stack is not - * NULL or when we need an lvalue. For internal use only. - */ -#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] - -/* yy_hold_char holds the character lost when pcap_text is formed. */ -static char yy_hold_char; -static int yy_n_chars; /* number of characters read into yy_ch_buf */ -int pcap_leng; - -/* Points to current character in buffer. */ -static char *yy_c_buf_p = (char *) 0; -static int yy_init = 0; /* whether we need to initialize */ -static int yy_start = 0; /* start state number */ - -/* Flag which is used to allow pcap_wrap()'s to do buffer switches - * instead of setting up a fresh pcap_in. A bit of a hack ... - */ -static int yy_did_buffer_switch_on_eof; - -void pcap_restart (FILE *input_file ); -void pcap__switch_to_buffer (YY_BUFFER_STATE new_buffer ); -YY_BUFFER_STATE pcap__create_buffer (FILE *file,int size ); -void pcap__delete_buffer (YY_BUFFER_STATE b ); -void pcap__flush_buffer (YY_BUFFER_STATE b ); -void pcap_push_buffer_state (YY_BUFFER_STATE new_buffer ); -void pcap_pop_buffer_state (void ); - -static void pcap_ensure_buffer_stack (void ); -static void pcap__load_buffer_state (void ); -static void pcap__init_buffer (YY_BUFFER_STATE b,FILE *file ); - -#define YY_FLUSH_BUFFER pcap__flush_buffer(YY_CURRENT_BUFFER ) - -YY_BUFFER_STATE pcap__scan_buffer (char *base,yy_size_t size ); -YY_BUFFER_STATE pcap__scan_string (yyconst char *yy_str ); -YY_BUFFER_STATE pcap__scan_bytes (yyconst char *bytes,int len ); - -void *pcap_alloc (yy_size_t ); -void *pcap_realloc (void *,yy_size_t ); -void pcap_free (void * ); - -#define yy_new_buffer pcap__create_buffer - -#define yy_set_interactive(is_interactive) \ - { \ - if ( ! YY_CURRENT_BUFFER ){ \ - pcap_ensure_buffer_stack (); \ - YY_CURRENT_BUFFER_LVALUE = \ - pcap__create_buffer(pcap_in,YY_BUF_SIZE ); \ - } \ - YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ - } - -#define yy_set_bol(at_bol) \ - { \ - if ( ! YY_CURRENT_BUFFER ){\ - pcap_ensure_buffer_stack (); \ - YY_CURRENT_BUFFER_LVALUE = \ - pcap__create_buffer(pcap_in,YY_BUF_SIZE ); \ - } \ - YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ - } - -#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) - -/* Begin user sect3 */ - -typedef unsigned char YY_CHAR; - -FILE *pcap_in = (FILE *) 0, *pcap_out = (FILE *) 0; - -typedef int yy_state_type; - -extern int pcap_lineno; - -int pcap_lineno = 1; - -extern char *pcap_text; -#define yytext_ptr pcap_text - -static yy_state_type yy_get_previous_state (void ); -static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); -static int yy_get_next_buffer (void ); -static void yy_fatal_error (yyconst char msg[] ); - -/* Done after the current pattern has been matched and before the - * corresponding action - sets up pcap_text. - */ -#define YY_DO_BEFORE_ACTION \ - (yytext_ptr) = yy_bp; \ - pcap_leng = (size_t) (yy_cp - yy_bp); \ - (yy_hold_char) = *yy_cp; \ - *yy_cp = '\0'; \ - (yy_c_buf_p) = yy_cp; - -#define YY_NUM_RULES 137 -#define YY_END_OF_BUFFER 138 -/* This struct is not used in this scanner, - but its presence is necessary. */ -struct yy_trans_info - { - flex_int32_t yy_verify; - flex_int32_t yy_nxt; - }; -static yyconst flex_int16_t yy_accept[1330] = - { 0, - 0, 0, 138, 135, 95, 95, 95, 96, 135, 96, - 96, 96, 136, 104, 104, 96, 96, 96, 96, 133, - 133, 135, 133, 133, 133, 133, 133, 133, 133, 133, - 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, - 133, 133, 96, 135, 99, 103, 57, 0, 133, 104, - 0, 133, 133, 133, 107, 101, 98, 100, 97, 102, - 134, 134, 133, 133, 19, 133, 133, 133, 133, 133, - 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, - 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, - 7, 133, 33, 34, 133, 133, 133, 133, 133, 133, - - 133, 133, 133, 133, 133, 133, 133, 133, 81, 133, - 58, 133, 133, 133, 133, 133, 133, 133, 133, 133, - 133, 133, 75, 133, 133, 133, 133, 133, 133, 133, - 4, 133, 133, 133, 133, 133, 133, 58, 103, 105, - 105, 104, 133, 0, 107, 104, 107, 107, 107, 133, - 133, 57, 5, 133, 70, 133, 133, 133, 133, 133, - 133, 93, 1, 0, 133, 20, 133, 133, 133, 133, - 133, 133, 133, 133, 133, 133, 35, 133, 133, 17, - 42, 0, 133, 28, 133, 24, 60, 133, 133, 68, - 36, 133, 89, 133, 133, 133, 133, 90, 133, 45, - - 59, 71, 92, 133, 14, 133, 3, 133, 133, 133, - 133, 133, 83, 133, 133, 25, 133, 91, 133, 94, - 37, 2, 133, 41, 133, 9, 10, 78, 133, 77, - 133, 133, 133, 133, 104, 0, 133, 0, 108, 107, - 107, 0, 107, 0, 107, 0, 107, 0, 22, 133, - 133, 133, 54, 40, 133, 38, 133, 133, 29, 133, - 87, 133, 133, 44, 11, 133, 12, 13, 133, 133, - 133, 31, 67, 133, 52, 3, 88, 46, 133, 133, - 133, 64, 133, 133, 133, 133, 47, 133, 133, 39, - 133, 6, 133, 82, 133, 8, 84, 133, 0, 133, - - 63, 15, 105, 105, 105, 104, 0, 107, 0, 0, - 107, 0, 107, 108, 107, 0, 0, 0, 0, 107, - 107, 107, 107, 107, 0, 133, 21, 133, 133, 133, - 30, 133, 133, 0, 18, 133, 133, 133, 76, 133, - 32, 133, 69, 27, 26, 133, 133, 72, 133, 133, - 133, 49, 16, 133, 133, 133, 133, 133, 133, 133, - 133, 133, 133, 133, 133, 133, 0, 0, 107, 107, - 107, 0, 0, 108, 107, 107, 108, 107, 0, 0, - 107, 107, 107, 107, 107, 0, 0, 0, 0, 107, - 107, 0, 107, 0, 107, 0, 86, 133, 133, 23, - - 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, - 133, 133, 133, 60, 133, 133, 133, 133, 133, 133, - 133, 65, 66, 133, 85, 133, 133, 133, 133, 133, - 133, 133, 133, 133, 133, 105, 105, 105, 0, 107, - 107, 0, 107, 0, 0, 107, 0, 107, 108, 107, - 0, 0, 0, 107, 107, 0, 107, 108, 107, 0, - 0, 0, 0, 0, 0, 0, 107, 107, 107, 107, - 107, 0, 133, 133, 51, 53, 133, 133, 133, 133, - 133, 133, 133, 133, 133, 133, 133, 133, 61, 133, - 133, 43, 73, 74, 133, 133, 133, 133, 131, 127, - - 133, 129, 128, 132, 133, 133, 0, 0, 107, 107, - 107, 107, 107, 107, 0, 0, 108, 107, 107, 107, - 0, 0, 107, 107, 107, 107, 107, 0, 0, 0, - 0, 0, 0, 0, 107, 107, 107, 107, 107, 0, - 0, 0, 0, 0, 107, 107, 0, 107, 0, 107, - 0, 133, 133, 133, 133, 133, 133, 133, 133, 133, - 133, 133, 133, 110, 109, 133, 133, 62, 133, 133, - 133, 130, 126, 105, 0, 107, 107, 0, 107, 107, - 0, 107, 0, 0, 107, 0, 107, 108, 107, 0, - 0, 0, 107, 107, 0, 107, 108, 107, 0, 0, - - 0, 0, 0, 107, 107, 0, 107, 108, 107, 0, - 107, 107, 0, 0, 0, 0, 0, 0, 0, 107, - 107, 107, 107, 107, 0, 55, 133, 115, 122, 133, - 133, 133, 133, 133, 133, 133, 133, 133, 56, 48, - 133, 133, 0, 0, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 0, 0, 108, 107, 107, 107, 0, - 0, 107, 107, 107, 107, 107, 0, 0, 0, 0, - 0, 0, 0, 107, 107, 107, 107, 107, 0, 107, - 107, 0, 0, 0, 0, 0, 0, 0, 107, 107, - 107, 107, 107, 0, 0, 0, 0, 0, 0, 107, - - 107, 0, 107, 0, 107, 0, 79, 133, 133, 133, - 133, 133, 133, 133, 133, 133, 133, 133, 50, 0, - 107, 107, 0, 107, 107, 0, 107, 107, 0, 107, - 0, 106, 107, 0, 107, 108, 107, 0, 0, 0, - 107, 107, 0, 107, 108, 107, 0, 0, 0, 0, - 0, 107, 107, 0, 107, 108, 107, 0, 0, 0, - 0, 0, 0, 107, 107, 0, 107, 108, 107, 0, - 107, 107, 107, 0, 0, 0, 0, 0, 0, 0, - 107, 107, 107, 107, 107, 0, 133, 133, 133, 133, - 133, 133, 133, 133, 120, 133, 80, 0, 0, 107, - - 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 0, 106, 108, 107, 107, 107, 0, 0, 107, - 107, 107, 107, 107, 0, 0, 0, 0, 0, 0, - 0, 107, 107, 107, 107, 107, 0, 107, 107, 0, - 0, 0, 0, 0, 0, 0, 107, 107, 107, 107, - 107, 0, 107, 107, 107, 0, 0, 0, 0, 0, - 0, 0, 107, 107, 107, 107, 107, 0, 0, 0, - 0, 0, 0, 107, 107, 0, 107, 0, 107, 0, - 133, 133, 133, 124, 133, 133, 133, 133, 133, 133, - 133, 112, 0, 107, 107, 0, 107, 107, 0, 107, - - 107, 0, 107, 107, 0, 107, 0, 0, 0, 107, - 0, 0, 107, 108, 107, 0, 0, 0, 107, 107, - 0, 107, 108, 107, 0, 0, 0, 0, 0, 107, - 107, 0, 107, 108, 107, 0, 0, 0, 0, 0, - 0, 107, 107, 0, 107, 108, 107, 0, 0, 0, - 0, 0, 0, 107, 107, 0, 107, 108, 107, 0, - 107, 107, 107, 0, 0, 0, 0, 0, 0, 0, - 107, 107, 107, 107, 107, 0, 133, 133, 133, 133, - 114, 133, 133, 133, 118, 133, 0, 0, 107, 107, - 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - - 107, 107, 107, 0, 0, 0, 108, 0, 0, 107, - 0, 0, 107, 107, 107, 0, 0, 0, 0, 0, - 0, 0, 107, 107, 107, 0, 107, 107, 0, 0, - 0, 0, 0, 0, 0, 107, 107, 107, 0, 107, - 107, 107, 0, 0, 0, 0, 0, 0, 0, 107, - 107, 107, 0, 107, 107, 107, 0, 0, 0, 0, - 0, 0, 0, 107, 107, 107, 0, 0, 0, 0, - 0, 0, 107, 107, 0, 107, 0, 107, 0, 111, - 123, 125, 119, 133, 133, 133, 133, 0, 0, 107, - 0, 107, 0, 107, 107, 0, 107, 107, 0, 107, - - 107, 0, 107, 107, 0, 107, 0, 0, 0, 0, - 107, 107, 0, 107, 0, 0, 107, 107, 107, 0, - 0, 0, 0, 107, 107, 107, 0, 0, 0, 0, - 0, 107, 107, 107, 0, 0, 0, 0, 0, 107, - 107, 107, 0, 0, 0, 0, 0, 107, 107, 107, - 107, 107, 107, 0, 0, 0, 0, 0, 0, 0, - 107, 107, 107, 0, 133, 133, 133, 133, 0, 0, - 0, 107, 107, 107, 107, 107, 107, 0, 0, 0, - 0, 107, 107, 0, 0, 0, 0, 107, 107, 107, - 0, 0, 0, 0, 0, 107, 107, 107, 107, 0, - - 0, 0, 0, 0, 107, 107, 107, 107, 0, 0, - 0, 0, 0, 107, 107, 107, 107, 0, 0, 0, - 0, 0, 107, 0, 0, 0, 0, 0, 107, 107, - 107, 133, 133, 133, 121, 107, 107, 107, 107, 107, - 107, 107, 107, 0, 0, 0, 0, 107, 107, 0, - 0, 107, 0, 0, 0, 107, 0, 0, 0, 107, - 0, 0, 0, 107, 0, 0, 0, 107, 107, 107, - 107, 0, 0, 0, 0, 0, 107, 116, 133, 113, - 107, 0, 0, 107, 107, 0, 107, 107, 107, 0, - 107, 107, 107, 0, 107, 107, 107, 0, 107, 107, - - 107, 0, 0, 0, 0, 107, 117, 107, 107, 0, - 0, 0, 0, 0, 0, 107, 107, 107, 0, 0, - 107, 107, 107, 107, 107, 0, 107, 107, 0 - } ; - -static yyconst flex_int32_t yy_ec[256] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, - 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 5, 1, 1, 6, 1, 7, 1, 8, - 8, 9, 9, 1, 10, 11, 9, 12, 13, 14, - 15, 16, 15, 17, 15, 15, 15, 18, 1, 19, - 20, 21, 1, 1, 22, 22, 22, 22, 22, 22, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 24, 23, 23, - 25, 26, 25, 1, 27, 1, 28, 29, 30, 31, - - 32, 33, 34, 35, 36, 23, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 23, 1, 52, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1 - } ; - -static yyconst flex_int32_t yy_meta[53] = - { 0, - 1, 2, 2, 1, 2, 1, 3, 2, 1, 4, - 5, 6, 6, 6, 6, 6, 6, 7, 3, 3, - 3, 8, 4, 9, 3, 1, 4, 8, 8, 8, - 8, 8, 8, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, - 4, 3 - } ; - -static yyconst flex_int16_t yy_base[1703] = - { 0, - 0, 0, 3454, 52, 6570, 6570, 53, 3419, 59, 3431, - 6570, 63, 6570, 80, 49, 131, 55, 3417, 62, 147, - 186, 147, 106, 36, 129, 134, 55, 102, 111, 3395, - 190, 193, 140, 113, 149, 198, 205, 148, 139, 3404, - 211, 3395, 3379, 250, 6570, 0, 6570, 0, 248, 266, - 3403, 258, 0, 288, 321, 6570, 6570, 6570, 6570, 6570, - 305, 0, 344, 40, 0, 3389, 3376, 3371, 183, 3357, - 3351, 3355, 3353, 3352, 192, 3361, 3330, 248, 3340, 213, - 3329, 3327, 3340, 3325, 3330, 3328, 103, 3323, 3318, 3307, - 38, 305, 0, 0, 165, 135, 3295, 3304, 244, 3287, - - 3284, 3287, 3290, 3266, 3274, 3265, 3264, 3270, 0, 3277, - 0, 3260, 3266, 3251, 3252, 3232, 3232, 282, 3243, 3223, - 3234, 3227, 220, 3209, 326, 3207, 302, 3206, 3218, 3204, - 0, 3202, 3206, 3204, 3195, 3166, 3180, 6570, 6570, 378, - 243, 417, 352, 3188, 439, 3193, 462, 320, 3185, 3160, - 3151, 0, 0, 3148, 361, 3157, 3152, 3139, 3140, 3137, - 502, 0, 0, 3133, 3103, 0, 3115, 272, 3099, 3112, - 3114, 3095, 3098, 3102, 3087, 3066, 0, 3071, 3065, 0, - 0, 3068, 3056, 0, 3068, 0, 3056, 3023, 3030, 0, - 0, 3019, 0, 3027, 3034, 352, 3016, 0, 3014, 3021, - - 0, 3016, 0, 2999, 0, 2981, 2985, 2978, 2980, 2985, - 2978, 2965, 0, 2963, 2956, 0, 2945, 0, 2944, 0, - 0, 0, 2940, 0, 2938, 370, 0, 0, 2941, 0, - 2938, 2918, 392, 531, 554, 2939, 2938, 2937, 2936, 562, - 360, 2934, 2933, 399, 602, 624, 406, 0, 0, 2909, - 2864, 2869, 0, 0, 2867, 0, 2866, 2852, 0, 2851, - 0, 2845, 2847, 0, 479, 2840, 0, 0, 2848, 2830, - 2831, 0, 0, 2829, 0, 0, 0, 0, 2843, 2834, - 2841, 0, 2795, 2798, 2813, 2787, 2783, 2793, 2783, 0, - 2782, 0, 2768, 0, 247, 0, 0, 2761, 455, 2769, - - 0, 0, 647, 374, 2795, 2787, 2785, 686, 2784, 2783, - 708, 491, 731, 753, 515, 0, 2743, 375, 522, 776, - 585, 799, 376, 2742, 2748, 2718, 0, 2727, 2725, 2708, - 0, 2725, 2707, 818, 0, 2697, 2686, 2704, 0, 2695, - 0, 2698, 2691, 0, 0, 2701, 2650, 395, 2649, 2667, - 356, 2664, 0, 2653, 2644, 2658, 2651, 2645, 2638, 2626, - 2627, 2620, 2625, 2640, 591, 854, 2649, 2628, 877, 412, - 2627, 2626, 2625, 2624, 917, 413, 2622, 2621, 474, 661, - 957, 668, 980, 414, 2620, 2606, 2598, 653, 0, 447, - 2597, 674, 1020, 1042, 822, 0, 0, 2586, 2567, 0, - - 2560, 2566, 2579, 2564, 2567, 2566, 469, 2552, 475, 2552, - 2560, 2547, 2557, 0, 2547, 2536, 2527, 2532, 2531, 2519, - 2518, 0, 0, 2522, 0, 2504, 2496, 2509, 2503, 2497, - 2491, 2489, 2472, 2477, 2476, 1064, 499, 2498, 2489, 1103, - 2488, 1125, 2487, 2473, 2472, 1147, 828, 1170, 1192, 900, - 0, 906, 0, 448, 2471, 939, 1215, 1237, 946, 0, - 598, 1003, 2477, 1010, 599, 1078, 1260, 1085, 1283, 531, - 2466, 2472, 2423, 2428, 0, 0, 2431, 2433, 2419, 2418, - 2430, 2413, 2398, 2405, 2396, 2396, 2392, 2389, 0, 2380, - 2373, 0, 0, 0, 2385, 2350, 2355, 2342, 0, 0, - - 2343, 0, 0, 0, 2332, 1322, 2343, 2342, 1345, 532, - 2341, 1385, 533, 2340, 2337, 2335, 2325, 1425, 561, 2324, - 681, 1092, 1465, 1306, 1488, 597, 2303, 2309, 682, 1313, - 2308, 1368, 683, 1375, 1528, 1408, 1551, 601, 2299, 2303, - 1070, 0, 1414, 0, 540, 2295, 1447, 1591, 1613, 1454, - 0, 2252, 2252, 2254, 2251, 2255, 2263, 2254, 2234, 2214, - 2207, 2228, 2222, 0, 0, 2220, 2205, 0, 2203, 2198, - 2185, 0, 0, 0, 2213, 1635, 1658, 1680, 1511, 1703, - 1725, 1518, 2211, 2210, 1747, 1573, 1770, 1792, 1580, 0, - 1814, 0, 632, 2209, 1820, 1827, 1849, 1872, 0, 1878, - - 0, 1884, 0, 693, 2177, 1890, 1897, 1919, 1942, 0, - 685, 1948, 2183, 848, 1955, 2178, 1962, 850, 1969, 1976, - 1999, 2006, 704, 2170, 2176, 297, 700, 685, 955, 956, - 2015, 1018, 745, 318, 746, 2016, 617, 769, 433, 686, - 1103, 2019, 2137, 2136, 2048, 728, 2135, 2088, 750, 2130, - 2128, 796, 2129, 2097, 2093, 2091, 2168, 798, 2090, 914, - 2036, 2208, 2071, 2231, 801, 2089, 2064, 1099, 2078, 2063, - 2111, 1100, 2118, 2271, 2151, 2294, 802, 2055, 2058, 823, - 2157, 2022, 1321, 2191, 2020, 2198, 1382, 2254, 2334, 2261, - 2357, 829, 1985, 1991, 0, 2316, 0, 2322, 0, 739, - - 1983, 2379, 2397, 2419, 2386, 0, 770, 792, 848, 974, - 1019, 1033, 1102, 1141, 1162, 1589, 1118, 1462, 791, 1982, - 2441, 2464, 2486, 2509, 2516, 2538, 2561, 2568, 2590, 2613, - 1981, 1979, 2619, 2641, 2648, 2670, 2693, 0, 2699, 0, - 740, 1978, 2705, 2712, 2734, 2757, 0, 2763, 0, 2769, - 0, 885, 1977, 2775, 2782, 2804, 2827, 0, 0, 2833, - 0, 2839, 0, 886, 1927, 2845, 2852, 2874, 2897, 0, - 0, 831, 2903, 1931, 1587, 2910, 1929, 2917, 1629, 2924, - 2931, 2954, 2961, 953, 1906, 1909, 1590, 2395, 2396, 1321, - 1185, 1464, 1527, 1164, 1463, 1117, 916, 1855, 1852, 3001, - - 957, 1833, 3041, 1016, 1797, 3081, 1017, 1776, 3121, 1143, - 1775, 1752, 1733, 3160, 3183, 1147, 1730, 1674, 2984, 3223, - 2991, 3246, 1166, 1689, 1671, 2021, 3024, 1651, 3031, 2125, - 3064, 3286, 3071, 3309, 1189, 1636, 1623, 1210, 3103, 1607, - 2330, 3110, 1604, 3144, 2393, 3151, 3349, 3206, 3372, 1211, - 1596, 1565, 0, 1212, 3212, 1560, 2435, 3269, 1544, 3276, - 3078, 3332, 3412, 3339, 3435, 1214, 1531, 1536, 0, 3394, - 0, 3400, 0, 926, 1497, 3457, 3475, 3497, 3464, 0, - 2030, 3505, 3506, 1230, 3490, 1526, 1253, 3508, 1696, 1275, - 1276, 1231, 1495, 3538, 3561, 3583, 3525, 3606, 3628, 3651, - - 3658, 3680, 3703, 3710, 3732, 3755, 1468, 3762, 1259, 1466, - 1430, 3784, 3802, 1428, 3791, 0, 3824, 0, 1200, 1427, - 3830, 3837, 1426, 3860, 0, 3866, 0, 3872, 0, 1329, - 1392, 3878, 3885, 1390, 3908, 0, 0, 3914, 0, 3920, - 0, 1331, 1352, 3926, 3933, 1348, 3956, 0, 0, 3962, - 0, 3968, 0, 1393, 1346, 3974, 3981, 1325, 4004, 0, - 0, 1322, 4010, 1330, 3159, 4017, 1299, 4024, 3219, 4031, - 4038, 4061, 4068, 1344, 1263, 1268, 1650, 1695, 1717, 1423, - 1277, 1651, 4077, 1718, 1424, 3538, 1238, 4107, 4130, 1461, - 1224, 4170, 1464, 1201, 4210, 1524, 1199, 4250, 1527, 1152, - - 4290, 1528, 1148, 1108, 4093, 4330, 1104, 4153, 0, 1103, - 3408, 4160, 4353, 4193, 1051, 1057, 3471, 4200, 1052, 4233, - 3472, 4240, 4376, 4273, 1029, 1033, 1586, 4279, 1028, 3534, - 4313, 994, 4320, 3535, 4399, 4406, 4429, 962, 967, 0, - 1588, 4435, 965, 3577, 4442, 931, 4449, 4078, 4456, 4463, - 4486, 922, 925, 0, 1609, 4492, 913, 4103, 4499, 891, - 4506, 4106, 4513, 4520, 4543, 860, 866, 0, 4549, 0, - 4555, 0, 1394, 838, 4561, 4568, 0, 4591, 0, 1629, - 1673, 1739, 1762, 1763, 2477, 4582, 4583, 4612, 1631, 0, - 785, 4652, 0, 4600, 4675, 0, 4635, 4698, 0, 4642, - - 4721, 0, 4744, 4751, 0, 4774, 4247, 4781, 4788, 4811, - 777, 624, 618, 610, 4817, 0, 1756, 608, 571, 4823, - 0, 4829, 0, 1800, 570, 569, 0, 4835, 0, 4841, - 0, 1801, 536, 534, 0, 4847, 0, 4853, 0, 1835, - 532, 523, 0, 4859, 0, 4865, 0, 1836, 522, 504, - 0, 1634, 4871, 510, 4327, 4878, 476, 4885, 4649, 4892, - 4899, 4922, 0, 471, 2206, 1786, 1842, 2086, 4929, 463, - 4952, 0, 0, 0, 0, 0, 0, 4958, 0, 1857, - 426, 424, 0, 4965, 4966, 430, 4979, 0, 1679, 4985, - 386, 4992, 4993, 374, 5006, 0, 0, 1680, 5012, 371, - - 5019, 5020, 370, 5033, 0, 0, 1702, 5039, 368, 5046, - 5047, 329, 5060, 0, 0, 1747, 5066, 318, 5073, 5074, - 274, 5087, 0, 0, 5093, 0, 5099, 0, 1905, 229, - 0, 2269, 2529, 1911, 1912, 0, 6570, 0, 0, 0, - 0, 0, 0, 5106, 5120, 235, 5127, 0, 6570, 5112, - 0, 6570, 0, 5133, 0, 6570, 0, 5145, 0, 6570, - 0, 5151, 0, 6570, 0, 5157, 0, 6570, 0, 1767, - 5163, 201, 5170, 5171, 199, 5184, 0, 2017, 2330, 2087, - 0, 5190, 0, 1824, 5196, 198, 0, 1826, 5202, 179, - 0, 1893, 5209, 133, 0, 1894, 5215, 132, 0, 2017, - - 5221, 95, 0, 5227, 0, 6570, 2166, 2127, 5233, 94, - 0, 0, 0, 0, 0, 0, 2167, 5239, 65, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 6570, 5256, - 5264, 5268, 5271, 5274, 5277, 5280, 5283, 5286, 5289, 5292, - 5295, 5298, 5301, 5304, 5307, 5310, 5314, 5318, 5321, 5324, - 5327, 5330, 5333, 5337, 5341, 5344, 5348, 5350, 5353, 5356, - 5359, 5362, 5365, 5369, 5371, 5375, 5380, 5384, 5387, 5390, - 5393, 5396, 5399, 5402, 5405, 5409, 5413, 5417, 5422, 5426, - 5429, 5432, 5436, 5438, 5441, 5444, 5447, 5450, 5453, 5457, - 5459, 5462, 5465, 5469, 5471, 5474, 5479, 5484, 5488, 5492, - - 5496, 5501, 5505, 5508, 5511, 5514, 5517, 5520, 5523, 5526, - 5530, 5534, 5538, 5542, 5547, 5551, 5555, 5559, 5562, 5567, - 5571, 5576, 5580, 5584, 5588, 5591, 5594, 5597, 5601, 5603, - 5608, 5612, 5615, 5618, 5621, 5624, 5628, 5630, 5633, 5636, - 5640, 5642, 5645, 5648, 5651, 5655, 5657, 5660, 5663, 5668, - 5672, 5677, 5681, 5685, 5689, 5694, 5698, 5701, 5704, 5707, - 5710, 5713, 5716, 5719, 5723, 5727, 5731, 5735, 5740, 5744, - 5748, 5752, 5755, 5760, 5764, 5769, 5773, 5777, 5781, 5784, - 5787, 5792, 5796, 5801, 5805, 5809, 5813, 5816, 5819, 5822, - 5826, 5828, 5833, 5837, 5840, 5843, 5846, 5849, 5852, 5855, - - 5859, 5861, 5864, 5867, 5870, 5874, 5876, 5879, 5882, 5885, - 5888, 5892, 5894, 5897, 5900, 5903, 5906, 5910, 5912, 5915, - 5918, 5921, 5926, 5930, 5935, 5939, 5943, 5947, 5952, 5956, - 5959, 5962, 5965, 5968, 5971, 5974, 5977, 5980, 5984, 5988, - 5992, 5996, 6001, 6005, 6009, 6013, 6016, 6021, 6025, 6030, - 6034, 6038, 6042, 6045, 6048, 6053, 6057, 6062, 6066, 6070, - 6074, 6077, 6080, 6085, 6089, 6094, 6098, 6102, 6106, 6109, - 6112, 6115, 6119, 6121, 6124, 6129, 6133, 6136, 6139, 6142, - 6145, 6148, 6151, 6155, 6159, 6162, 6166, 6169, 6172, 6176, - 6178, 6181, 6184, 6188, 6190, 6193, 6196, 6199, 6203, 6205, - - 6208, 6211, 6214, 6218, 6220, 6223, 6226, 6229, 6233, 6235, - 6238, 6241, 6246, 6250, 6255, 6259, 6263, 6267, 6272, 6276, - 6279, 6282, 6285, 6288, 6291, 6294, 6297, 6301, 6303, 6306, - 6310, 6315, 6318, 6321, 6326, 6330, 6335, 6338, 6341, 6344, - 6349, 6353, 6358, 6361, 6364, 6367, 6372, 6376, 6381, 6384, - 6387, 6390, 6395, 6399, 6404, 6407, 6410, 6413, 6416, 6420, - 6422, 6427, 6431, 6434, 6437, 6440, 6443, 6446, 6449, 6453, - 6458, 6461, 6464, 6467, 6470, 6473, 6476, 6479, 6482, 6485, - 6488, 6491, 6496, 6500, 6503, 6506, 6509, 6513, 6517, 6521, - 6525, 6529, 6532, 6535, 6539, 6542, 6545, 6548, 6551, 6554, - - 6558, 6561 - } ; - -static yyconst flex_int16_t yy_def[1703] = - { 0, - 1329, 1, 1329, 1329, 1329, 1329, 1329, 1329, 1330, 1329, - 1329, 1329, 1329, 1329, 14, 1329, 1329, 1329, 1329, 14, - 20, 1331, 20, 20, 20, 20, 20, 20, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 1329, 1329, 1329, 1332, 1329, 21, 21, 20, - 1333, 50, 21, 21, 1329, 1329, 1329, 1329, 1329, 1329, - 1331, 1331, 50, 63, 21, 21, 21, 21, 63, 21, - 21, 21, 21, 21, 63, 21, 21, 21, 21, 63, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 1329, 1329, 21, - 140, 50, 142, 1334, 1329, 54, 1329, 147, 1335, 21, - 21, 21, 21, 21, 142, 21, 21, 21, 21, 21, - 142, 21, 21, 21, 21, 21, 21, 161, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 1336, 21, 1337, 1338, 1329, - 240, 1339, 1340, 1329, 1329, 1329, 245, 1341, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - - 21, 21, 21, 303, 234, 235, 1342, 1329, 1343, 1344, - 1329, 1329, 1329, 1329, 313, 1345, 1346, 1347, 1329, 1329, - 320, 1329, 322, 1348, 1341, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 1337, 1349, 1329, 369, - 1350, 1329, 1351, 1352, 1329, 375, 1339, 1353, 1354, 1329, - 1329, 381, 1329, 383, 1355, 1345, 1329, 1329, 1356, 1357, - 1329, 1329, 1329, 1329, 393, 1358, 21, 21, 21, 21, - - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 436, 366, 1359, 1329, - 313, 1329, 315, 1360, 1361, 1329, 1329, 1329, 1329, 448, - 1362, 1329, 1363, 1364, 1329, 1329, 1329, 1329, 457, 1365, - 1366, 1329, 1356, 1329, 1367, 1329, 1329, 467, 1329, 469, - 1368, 1358, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - - 21, 21, 21, 21, 21, 21, 1369, 1370, 1329, 509, - 1371, 1329, 512, 1372, 1329, 1373, 1374, 1329, 518, 1375, - 1376, 1329, 1329, 523, 1329, 525, 1377, 1362, 1378, 1329, - 1363, 1329, 1379, 1329, 1329, 535, 1329, 537, 1380, 1365, - 1329, 1381, 1329, 1382, 1383, 1329, 1329, 1329, 1329, 548, - 1384, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 506, 1385, 1329, 1329, 1329, 577, 1329, - 1329, 580, 1386, 1387, 1329, 1329, 1329, 1329, 587, 1388, - 1329, 1389, 1390, 1329, 1329, 1329, 1329, 596, 1391, 1329, - - 1392, 1329, 1393, 1394, 1329, 1329, 1329, 1329, 607, 1395, - 1396, 1329, 1381, 1397, 1329, 1398, 1329, 1399, 1329, 1329, - 620, 1329, 622, 1400, 1401, 1402, 1402, 1402, 1402, 1402, - 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, - 1402, 1402, 1403, 1404, 1329, 645, 1405, 1329, 648, 1406, - 1329, 651, 1407, 1329, 1408, 1409, 1329, 657, 1410, 1411, - 1329, 1329, 662, 1329, 664, 1412, 1413, 1414, 1329, 1415, - 1329, 1416, 1329, 1329, 674, 1329, 676, 1417, 1418, 1419, - 1329, 1420, 1421, 1329, 1422, 1329, 1423, 1329, 1329, 689, - 1329, 691, 1424, 1425, 1426, 1329, 1427, 1329, 1428, 1429, - - 1329, 1329, 1329, 1329, 703, 1430, 1431, 1431, 1431, 1431, - 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1432, - 1329, 1329, 1329, 722, 1329, 1329, 725, 1329, 1329, 728, - 1433, 1434, 1329, 1329, 1329, 1329, 735, 1435, 1329, 1436, - 1437, 1329, 1329, 1329, 1329, 744, 1438, 1329, 1439, 1329, - 1440, 1441, 1329, 1329, 1329, 1329, 755, 1442, 1443, 1329, - 1444, 1329, 1445, 1446, 1329, 1329, 1329, 1329, 767, 1447, - 1448, 1449, 1329, 1450, 1451, 1329, 1452, 1329, 1453, 1329, - 1329, 781, 1329, 783, 1454, 1455, 1456, 1456, 1456, 1456, - 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1457, 1458, 1329, - - 800, 1459, 1329, 803, 1460, 1329, 806, 1461, 1329, 809, - 1462, 1329, 1463, 1329, 1329, 815, 1464, 1465, 1329, 1329, - 820, 1329, 822, 1466, 1467, 1468, 1329, 1469, 1329, 1470, - 1329, 1329, 832, 1329, 834, 1471, 1472, 1473, 1329, 1474, - 1475, 1329, 1476, 1329, 1477, 1329, 1329, 847, 1329, 849, - 1478, 1479, 1480, 1481, 1329, 1482, 1483, 1329, 1484, 1329, - 1485, 1329, 1329, 863, 1329, 865, 1486, 1487, 1488, 1329, - 1489, 1329, 1490, 1491, 1329, 1329, 1329, 1329, 877, 1492, - 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, - 1493, 1493, 1494, 1329, 1329, 1329, 895, 1329, 1329, 898, - - 1329, 1329, 901, 1329, 1329, 904, 1495, 1329, 908, 1496, - 1497, 1329, 1329, 1498, 913, 1499, 1329, 1500, 1501, 1329, - 1329, 1329, 1502, 922, 1503, 1329, 1504, 1329, 1505, 1506, - 1329, 1329, 1329, 1507, 933, 1508, 1509, 1329, 1510, 1329, - 1511, 1512, 1329, 1329, 1329, 1513, 945, 1514, 1515, 1329, - 1516, 1329, 1517, 1518, 1329, 1329, 1329, 1519, 957, 1520, - 1521, 1522, 1329, 1523, 1524, 1329, 1525, 1329, 1526, 1329, - 1329, 971, 1329, 973, 1527, 1528, 1529, 1529, 1529, 1529, - 1529, 1529, 1529, 1529, 1529, 1529, 1530, 1329, 1329, 989, - 1531, 1329, 992, 1532, 1329, 995, 1533, 1329, 998, 1534, - - 1329, 1001, 1535, 1329, 1329, 1329, 1536, 1006, 1537, 1538, - 1539, 1329, 1329, 1013, 1540, 1541, 1542, 1329, 1543, 1329, - 1544, 1329, 1329, 1023, 1545, 1546, 1547, 1329, 1548, 1549, - 1329, 1550, 1329, 1551, 1329, 1329, 1036, 1552, 1553, 1554, - 1555, 1329, 1556, 1557, 1329, 1558, 1329, 1559, 1329, 1329, - 1050, 1560, 1561, 1562, 1563, 1329, 1564, 1565, 1329, 1566, - 1329, 1567, 1329, 1329, 1064, 1568, 1569, 1570, 1329, 1571, - 1329, 1572, 1573, 1329, 1329, 1329, 1574, 1076, 1575, 1576, - 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1329, 1088, 1577, - 1578, 1329, 1579, 1092, 1329, 1580, 1095, 1329, 1581, 1098, - - 1329, 1582, 1101, 1329, 1583, 1104, 1584, 1329, 1329, 1109, - 1585, 1586, 1587, 1588, 1329, 1589, 1590, 1329, 1591, 1329, - 1592, 1329, 1593, 1594, 1329, 1595, 1596, 1329, 1597, 1329, - 1598, 1599, 1329, 1600, 1601, 1329, 1602, 1329, 1603, 1604, - 1329, 1605, 1606, 1329, 1607, 1329, 1608, 1609, 1329, 1610, - 1611, 1612, 1329, 1613, 1614, 1329, 1615, 1329, 1616, 1329, - 1329, 1161, 1617, 1618, 1619, 1619, 1619, 1619, 1329, 1620, - 1169, 1621, 1622, 1623, 1624, 1625, 1626, 1329, 1627, 1628, - 1329, 1629, 1630, 1631, 1329, 1632, 1329, 1633, 1634, 1329, - 1635, 1636, 1329, 1637, 1329, 1638, 1639, 1640, 1329, 1641, - - 1642, 1329, 1643, 1329, 1644, 1645, 1646, 1329, 1647, 1648, - 1329, 1649, 1329, 1650, 1651, 1652, 1329, 1653, 1654, 1329, - 1655, 1329, 1656, 1657, 1329, 1658, 1329, 1659, 1660, 1329, - 1661, 1662, 1662, 1662, 1662, 1663, 1329, 1664, 1665, 1666, - 1667, 1668, 1669, 1670, 1329, 1671, 1329, 1672, 1329, 1329, - 1673, 1329, 1674, 1329, 1675, 1329, 1676, 1329, 1677, 1329, - 1678, 1329, 1679, 1329, 1680, 1329, 1681, 1329, 1657, 1682, - 1329, 1658, 1683, 1329, 1659, 1329, 1684, 1662, 1662, 1662, - 1685, 1329, 1686, 1687, 1329, 1673, 1674, 1688, 1329, 1675, - 1676, 1689, 1329, 1677, 1678, 1690, 1329, 1679, 1680, 1691, - - 1329, 1681, 1692, 1329, 1693, 1329, 1662, 1694, 1329, 1686, - 1695, 1696, 1697, 1698, 1699, 1692, 1700, 1329, 1693, 1701, - 1695, 1696, 1697, 1698, 1699, 1702, 1701, 1702, 0, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - - 1329, 1329 - } ; - -static yyconst flex_int16_t yy_nxt[6623] = - { 0, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 11, - 13, 14, 15, 15, 15, 15, 15, 16, 17, 18, - 19, 20, 21, 21, 11, 22, 13, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 21, 32, 33, 34, - 35, 36, 21, 37, 38, 39, 40, 41, 42, 21, - 21, 43, 44, 44, 180, 44, 44, 44, 44, 44, - 44, 44, 44, 44, 44, 69, 44, 44, 44, 44, - 44, 44, 53, 56, 57, 1304, 44, 44, 44, 70, - 44, 59, 60, 53, 44, 151, 71, 181, 44, 48, - 49, 50, 50, 50, 50, 50, 50, 51, 53, 78, - - 79, 52, 53, 54, 1282, 1266, 48, 52, 52, 52, - 52, 52, 52, 53, 53, 53, 53, 53, 53, 53, - 53, 53, 53, 53, 53, 53, 53, 53, 53, 54, - 53, 44, 80, 63, 44, 64, 44, 81, 82, 44, - 65, 175, 1262, 1258, 106, 66, 176, 61, 55, 67, - 61, 68, 61, 107, 83, 61, 44, 53, 52, 52, - 52, 52, 52, 52, 61, 75, 72, 100, 130, 73, - 53, 101, 61, 74, 187, 76, 108, 123, 77, 188, - 102, 103, 131, 124, 104, 125, 105, 126, 109, 1254, - 110, 127, 111, 128, 129, 112, 53, 53, 53, 53, - - 53, 53, 53, 1329, 185, 93, 94, 53, 1250, 1227, - 186, 1225, 155, 53, 53, 53, 53, 53, 53, 85, - 95, 161, 86, 87, 96, 88, 53, 89, 97, 90, - 98, 91, 118, 113, 92, 53, 119, 99, 114, 115, - 133, 116, 117, 168, 120, 1178, 1077, 216, 134, 121, - 44, 122, 135, 44, 136, 44, 53, 164, 44, 140, - 141, 141, 141, 141, 141, 217, 53, 44, 53, 143, - 143, 143, 143, 143, 143, 44, 49, 142, 142, 142, - 142, 142, 142, 165, 1146, 191, 355, 143, 192, 166, - 193, 356, 53, 143, 143, 143, 143, 143, 143, 146, - - 146, 146, 146, 146, 146, 61, 48, 131, 61, 146, - 61, 53, 210, 61, 182, 146, 146, 146, 146, 146, - 146, 44, 61, 48, 44, 211, 44, 48, 1144, 44, - 61, 222, 147, 148, 148, 148, 148, 148, 44, 1138, - 183, 223, 149, 1329, 48, 184, 44, 714, 149, 149, - 149, 149, 149, 149, 53, 143, 143, 143, 143, 143, - 143, 219, 53, 237, 237, 237, 237, 237, 237, 1329, - 220, 53, 237, 237, 237, 237, 237, 237, 1136, 299, - 1130, 1128, 280, 1329, 1122, 388, 422, 150, 233, 141, - 141, 141, 141, 141, 141, 281, 1120, 53, 389, 1329, - - 423, 234, 300, 303, 304, 304, 304, 304, 304, 1329, - 318, 319, 319, 319, 319, 319, 1329, 321, 321, 321, - 321, 321, 321, 53, 389, 1329, 418, 234, 235, 235, - 235, 235, 235, 235, 236, 1329, 1329, 1329, 237, 419, - 1115, 377, 48, 1170, 237, 237, 237, 237, 237, 237, - 240, 241, 241, 241, 241, 241, 242, 244, 312, 48, - 243, 1329, 1329, 1329, 246, 442, 243, 243, 243, 243, - 243, 243, 244, 245, 245, 245, 245, 245, 245, 246, - 1237, 1075, 358, 247, 452, 248, 1071, 359, 334, 247, - 247, 247, 247, 247, 247, 335, 360, 453, 361, 362, - - 481, 363, 379, 380, 380, 380, 380, 380, 336, 482, - 484, 248, 53, 237, 237, 237, 237, 237, 237, 485, - 1069, 377, 53, 453, 337, 1329, 382, 382, 382, 382, - 382, 382, 388, 319, 319, 319, 319, 319, 319, 1105, - 377, 257, 305, 305, 305, 305, 305, 305, 53, 1102, - 392, 377, 305, 1099, 1329, 1329, 1329, 394, 305, 305, - 305, 305, 305, 305, 49, 306, 306, 306, 306, 306, - 306, 236, 312, 313, 313, 313, 313, 313, 313, 314, - 1329, 1329, 1329, 315, 1329, 316, 377, 1096, 377, 315, - 315, 315, 315, 315, 315, 1329, 391, 391, 391, 391, - - 391, 391, 436, 437, 437, 437, 437, 437, 541, 543, - 1329, 316, 244, 320, 320, 320, 320, 320, 320, 246, - 1329, 542, 544, 321, 1329, 1093, 48, 377, 1005, 321, - 321, 321, 321, 321, 321, 322, 323, 323, 323, 323, - 323, 377, 447, 48, 717, 324, 1329, 542, 544, 578, - 1329, 324, 324, 324, 324, 324, 324, 365, 304, 304, - 304, 304, 304, 304, 461, 462, 462, 462, 462, 462, - 366, 452, 380, 380, 380, 380, 380, 380, 1329, 455, - 455, 455, 455, 455, 455, 465, 466, 466, 466, 466, - 466, 591, 600, 602, 48, 48, 366, 369, 370, 370, - - 370, 370, 370, 456, 592, 601, 603, 371, 695, 48, - 581, 48, 48, 371, 371, 371, 371, 371, 371, 375, - 376, 376, 376, 376, 376, 377, 48, 1329, 708, 378, - 592, 601, 603, 707, 695, 378, 378, 378, 378, 378, - 378, 312, 381, 381, 381, 381, 381, 381, 314, 547, - 586, 1329, 382, 1329, 48, 48, 549, 723, 382, 382, - 382, 382, 382, 382, 383, 384, 384, 384, 384, 384, - 377, 48, 48, 1329, 385, 715, 713, 1329, 48, 48, - 385, 385, 385, 385, 385, 385, 244, 390, 390, 390, - 390, 390, 390, 246, 377, 48, 48, 391, 718, 1329, - - 48, 48, 1170, 391, 391, 391, 391, 391, 391, 392, - 393, 393, 393, 393, 393, 393, 394, 48, 48, 1329, - 395, 1329, 396, 787, 1329, 1329, 395, 395, 395, 395, - 395, 395, 1329, 468, 468, 468, 468, 468, 468, 521, - 522, 522, 522, 522, 522, 1329, 759, 1329, 396, 403, - 1329, 1329, 1329, 404, 869, 878, 405, 48, 696, 406, - 698, 407, 408, 409, 410, 438, 438, 438, 438, 438, - 438, 697, 759, 699, 48, 438, 956, 377, 1329, 788, - 869, 438, 438, 438, 438, 438, 438, 312, 441, 441, - 441, 441, 441, 441, 442, 595, 606, 697, 443, 699, - - 316, 952, 726, 729, 443, 443, 443, 443, 443, 443, - 1329, 524, 524, 524, 524, 524, 524, 529, 530, 530, - 530, 530, 530, 950, 739, 48, 316, 447, 448, 448, - 448, 448, 448, 448, 449, 944, 702, 740, 450, 377, - 451, 940, 48, 704, 450, 450, 450, 450, 450, 450, - 533, 534, 534, 534, 534, 534, 1329, 536, 536, 536, - 536, 536, 536, 740, 48, 48, 451, 312, 454, 454, - 454, 454, 454, 454, 442, 938, 1329, 932, 455, 377, - 1329, 48, 48, 48, 455, 455, 455, 455, 455, 455, - 456, 457, 457, 457, 457, 457, 457, 458, 709, 710, - - 48, 459, 1329, 460, 928, 789, 1329, 459, 459, 459, - 459, 459, 459, 541, 462, 462, 462, 462, 462, 462, - 244, 464, 464, 464, 464, 464, 464, 48, 48, 460, - 392, 467, 467, 467, 467, 467, 467, 394, 926, 1329, - 1329, 468, 48, 921, 48, 48, 377, 468, 468, 468, - 468, 468, 468, 469, 470, 470, 470, 470, 470, 48, - 790, 712, 917, 471, 791, 1329, 1329, 912, 377, 471, - 471, 471, 471, 471, 471, 437, 437, 437, 437, 437, - 437, 611, 612, 612, 612, 612, 612, 506, 543, 466, - 466, 466, 466, 466, 466, 1329, 546, 546, 546, 546, - - 546, 546, 591, 522, 522, 522, 522, 522, 522, 748, - 750, 48, 48, 506, 509, 510, 510, 510, 510, 510, - 377, 1112, 749, 751, 511, 988, 48, 48, 48, 48, - 511, 511, 511, 511, 511, 511, 512, 513, 513, 513, - 513, 513, 719, 48, 48, 792, 514, 796, 749, 751, - 48, 892, 514, 514, 514, 514, 514, 514, 518, 519, - 519, 519, 519, 519, 377, 1105, 1329, 48, 520, 1102, - 1329, 48, 793, 48, 520, 520, 520, 520, 520, 520, - 447, 523, 523, 523, 523, 523, 523, 449, 48, 1329, - 48, 524, 1329, 794, 48, 890, 1329, 524, 524, 524, - - 524, 524, 524, 525, 526, 526, 526, 526, 526, 377, - 734, 48, 1329, 527, 886, 1329, 1099, 896, 1096, 527, - 527, 527, 527, 527, 527, 456, 535, 535, 535, 535, - 535, 535, 458, 937, 1329, 949, 536, 1329, 1329, 48, - 48, 1093, 536, 536, 536, 536, 536, 536, 537, 538, - 538, 538, 538, 538, 377, 988, 48, 48, 539, 937, - 1329, 949, 48, 1329, 539, 539, 539, 539, 539, 539, - 392, 545, 545, 545, 545, 545, 545, 394, 876, 48, - 1077, 546, 1329, 982, 48, 48, 48, 546, 546, 546, - 546, 546, 546, 547, 548, 548, 548, 548, 548, 548, - - 549, 48, 48, 48, 550, 985, 551, 986, 1329, 872, - 550, 550, 550, 550, 550, 550, 1329, 594, 594, 594, - 594, 594, 594, 600, 530, 530, 530, 530, 530, 530, - 48, 760, 551, 574, 574, 574, 574, 574, 574, 743, - 870, 754, 377, 574, 761, 1068, 899, 48, 902, 574, - 574, 574, 574, 574, 574, 447, 577, 577, 577, 577, - 577, 577, 578, 905, 885, 377, 579, 1329, 451, 902, - 761, 1068, 579, 579, 579, 579, 579, 579, 312, 532, - 532, 532, 532, 532, 532, 602, 534, 534, 534, 534, - 534, 534, 762, 1329, 451, 456, 580, 580, 580, 580, - - 580, 580, 581, 766, 876, 763, 582, 377, 460, 899, - 905, 878, 582, 582, 582, 582, 582, 582, 1329, 605, - 605, 605, 605, 605, 605, 614, 615, 615, 615, 615, - 615, 763, 48, 48, 460, 586, 587, 587, 587, 587, - 587, 587, 588, 377, 896, 377, 589, 1007, 590, 48, - 48, 1083, 589, 589, 589, 589, 589, 589, 618, 619, - 619, 619, 619, 619, 1329, 621, 621, 621, 621, 621, - 621, 48, 48, 48, 590, 447, 593, 593, 593, 593, - 593, 593, 578, 377, 1329, 988, 594, 1329, 48, 48, - 48, 887, 594, 594, 594, 594, 594, 594, 595, 596, - - 596, 596, 596, 596, 596, 597, 891, 797, 888, 598, - 1329, 599, 988, 1329, 704, 598, 598, 598, 598, 598, - 598, 1329, 524, 524, 524, 524, 524, 524, 1329, 536, - 536, 536, 536, 536, 536, 48, 48, 599, 456, 604, - 604, 604, 604, 604, 604, 581, 766, 1329, 958, 605, - 1329, 1329, 48, 48, 762, 605, 605, 605, 605, 605, - 605, 606, 607, 607, 607, 607, 607, 607, 608, 889, - 760, 981, 609, 1329, 610, 754, 1329, 1329, 609, 609, - 609, 609, 609, 609, 660, 661, 661, 661, 661, 661, - 1329, 663, 663, 663, 663, 663, 663, 870, 48, 48, - - 610, 547, 620, 620, 620, 620, 620, 620, 549, 1127, - 871, 1135, 621, 946, 750, 48, 48, 748, 621, 621, - 621, 621, 621, 621, 622, 623, 623, 623, 623, 623, - 795, 881, 1143, 743, 624, 1127, 871, 1135, 48, 872, - 624, 624, 624, 624, 624, 624, 645, 646, 646, 646, - 646, 646, 873, 934, 1329, 48, 647, 1224, 1143, 48, - 48, 739, 647, 647, 647, 647, 647, 647, 447, 523, - 523, 523, 523, 523, 523, 578, 48, 48, 873, 524, - 1329, 734, 48, 1224, 917, 524, 524, 524, 524, 524, - 524, 648, 649, 649, 649, 649, 649, 918, 1084, 48, - - 1080, 650, 1253, 1257, 48, 48, 923, 650, 650, 650, - 650, 650, 650, 456, 535, 535, 535, 535, 535, 535, - 581, 48, 48, 918, 536, 1261, 48, 48, 1253, 1257, - 536, 536, 536, 536, 536, 536, 651, 652, 652, 652, - 652, 652, 984, 48, 48, 1081, 653, 914, 48, 1086, - 814, 1261, 653, 653, 653, 653, 653, 653, 657, 658, - 658, 658, 658, 658, 377, 48, 912, 1082, 659, 799, - 1265, 48, 48, 1093, 659, 659, 659, 659, 659, 659, - 586, 662, 662, 662, 662, 662, 662, 588, 48, 48, - 1303, 663, 905, 902, 1165, 48, 1265, 663, 663, 663, - - 663, 663, 663, 664, 665, 665, 665, 665, 665, 377, - 921, 932, 48, 666, 899, 1233, 1303, 1096, 1099, 666, - 666, 666, 666, 666, 666, 668, 669, 669, 669, 669, - 669, 672, 673, 673, 673, 673, 673, 595, 674, 674, - 674, 674, 674, 674, 597, 944, 956, 1311, 675, 1312, - 896, 48, 1102, 1105, 675, 675, 675, 675, 675, 675, - 676, 677, 677, 677, 677, 677, 377, 1005, 48, 894, - 678, 1234, 799, 1311, 1170, 1312, 678, 678, 678, 678, - 678, 678, 1329, 675, 675, 675, 675, 675, 675, 680, - 681, 681, 681, 681, 681, 683, 684, 684, 684, 684, - - 684, 687, 688, 688, 688, 688, 688, 606, 689, 689, - 689, 689, 689, 689, 608, 1075, 1313, 1314, 690, 702, - 48, 48, 1077, 878, 690, 690, 690, 690, 690, 690, - 691, 692, 692, 692, 692, 692, 377, 48, 48, 698, - 693, 696, 1313, 1314, 729, 1280, 693, 693, 693, 693, - 693, 693, 1329, 690, 690, 690, 690, 690, 690, 612, - 612, 612, 612, 612, 612, 696, 615, 615, 615, 615, - 615, 615, 392, 617, 617, 617, 617, 617, 617, 698, - 619, 619, 619, 619, 619, 619, 547, 700, 700, 700, - 700, 700, 700, 549, 726, 723, 814, 701, 799, 799, - - 549, 606, 768, 701, 701, 701, 701, 701, 701, 1329, - 701, 701, 701, 701, 701, 701, 702, 703, 703, 703, - 703, 703, 703, 704, 48, 48, 48, 705, 48, 706, - 602, 926, 600, 705, 705, 705, 705, 705, 705, 48, - 1315, 48, 48, 48, 927, 48, 739, 661, 661, 661, - 661, 661, 661, 711, 716, 706, 48, 297, 586, 722, - 722, 722, 722, 722, 722, 723, 1315, 977, 595, 724, - 927, 590, 756, 591, 586, 724, 724, 724, 724, 724, - 724, 1329, 742, 742, 742, 742, 742, 742, 748, 669, - 669, 669, 669, 669, 669, 48, 48, 590, 595, 725, - - 725, 725, 725, 725, 725, 726, 745, 736, 733, 727, - 656, 599, 48, 48, 644, 727, 727, 727, 727, 727, - 727, 447, 671, 671, 671, 671, 671, 671, 750, 673, - 673, 673, 673, 673, 673, 928, 1235, 599, 606, 728, - 728, 728, 728, 728, 728, 729, 729, 726, 929, 730, - 1320, 610, 723, 721, 644, 730, 730, 730, 730, 730, - 730, 1329, 753, 753, 753, 753, 753, 753, 681, 681, - 681, 681, 681, 681, 929, 48, 1320, 610, 734, 735, - 735, 735, 735, 735, 735, 736, 547, 704, 543, 737, - 1326, 738, 48, 541, 581, 737, 737, 737, 737, 737, - - 737, 760, 684, 684, 684, 684, 684, 684, 456, 686, - 686, 686, 686, 686, 686, 48, 1326, 738, 586, 741, - 741, 741, 741, 741, 741, 723, 578, 656, 644, 742, - 644, 642, 48, 641, 640, 742, 742, 742, 742, 742, - 742, 743, 744, 744, 744, 744, 744, 744, 745, 1232, - 639, 638, 746, 637, 747, 636, 635, 634, 746, 746, - 746, 746, 746, 746, 762, 688, 688, 688, 688, 688, - 688, 1329, 765, 765, 765, 765, 765, 765, 48, 633, - 747, 595, 752, 752, 752, 752, 752, 752, 726, 632, - 631, 630, 753, 629, 628, 48, 627, 626, 753, 753, - - 753, 753, 753, 753, 754, 755, 755, 755, 755, 755, - 755, 756, 394, 456, 1278, 757, 608, 758, 452, 447, - 597, 757, 757, 757, 757, 757, 757, 772, 773, 773, - 773, 773, 773, 775, 776, 776, 776, 776, 776, 48, - 938, 588, 585, 758, 606, 764, 764, 764, 764, 764, - 764, 729, 517, 939, 508, 765, 48, 581, 578, 576, - 508, 765, 765, 765, 765, 765, 765, 766, 767, 767, - 767, 767, 767, 767, 768, 1307, 573, 572, 769, 939, - 770, 571, 570, 569, 769, 769, 769, 769, 769, 769, - 779, 780, 780, 780, 780, 780, 1329, 782, 782, 782, - - 782, 782, 782, 940, 48, 48, 770, 702, 781, 781, - 781, 781, 781, 781, 704, 568, 941, 567, 782, 566, - 565, 48, 48, 564, 782, 782, 782, 782, 782, 782, - 783, 784, 784, 784, 784, 784, 882, 883, 884, 563, - 785, 562, 941, 561, 560, 950, 785, 785, 785, 785, - 785, 785, 800, 801, 801, 801, 801, 801, 951, 559, - 558, 557, 802, 556, 555, 554, 553, 552, 802, 802, - 802, 802, 802, 802, 586, 662, 662, 662, 662, 662, - 662, 723, 392, 549, 951, 663, 48, 388, 442, 517, - 508, 663, 663, 663, 663, 663, 663, 803, 804, 804, - - 804, 804, 804, 48, 442, 442, 508, 805, 365, 505, - 504, 503, 1166, 805, 805, 805, 805, 805, 805, 1329, - 663, 663, 663, 663, 663, 663, 595, 674, 674, 674, - 674, 674, 674, 726, 502, 501, 500, 675, 48, 499, - 498, 294, 213, 675, 675, 675, 675, 675, 675, 806, - 807, 807, 807, 807, 807, 48, 497, 496, 495, 808, - 494, 493, 492, 491, 1279, 808, 808, 808, 808, 808, - 808, 1329, 675, 675, 675, 675, 675, 675, 606, 689, - 689, 689, 689, 689, 689, 729, 490, 489, 488, 690, - 487, 486, 483, 480, 479, 690, 690, 690, 690, 690, - - 690, 809, 810, 810, 810, 810, 810, 478, 477, 476, - 475, 811, 474, 473, 246, 377, 312, 811, 811, 811, - 811, 811, 811, 1329, 690, 690, 690, 690, 690, 690, - 815, 816, 816, 816, 816, 816, 377, 458, 449, 377, - 817, 446, 374, 368, 442, 440, 817, 817, 817, 817, - 817, 817, 818, 819, 819, 819, 819, 819, 734, 820, - 820, 820, 820, 820, 820, 736, 368, 435, 434, 821, - 433, 432, 431, 430, 429, 821, 821, 821, 821, 821, - 821, 822, 823, 823, 823, 823, 823, 377, 428, 427, - 426, 824, 425, 424, 421, 420, 417, 824, 824, 824, - - 824, 824, 824, 1329, 821, 821, 821, 821, 821, 821, - 826, 827, 827, 827, 827, 827, 830, 831, 831, 831, - 831, 831, 743, 832, 832, 832, 832, 832, 832, 745, - 416, 415, 414, 833, 413, 109, 412, 411, 402, 833, - 833, 833, 833, 833, 833, 834, 835, 835, 835, 835, - 835, 377, 401, 400, 399, 836, 398, 397, 244, 394, - 377, 836, 836, 836, 836, 836, 836, 1329, 833, 833, - 833, 833, 833, 833, 838, 839, 839, 839, 839, 839, - 841, 842, 842, 842, 842, 842, 845, 846, 846, 846, - 846, 846, 754, 847, 847, 847, 847, 847, 847, 756, - - 374, 368, 368, 848, 1329, 233, 364, 357, 354, 848, - 848, 848, 848, 848, 848, 849, 850, 850, 850, 850, - 850, 377, 353, 352, 351, 851, 350, 349, 348, 347, - 346, 851, 851, 851, 851, 851, 851, 1329, 848, 848, - 848, 848, 848, 848, 854, 855, 855, 855, 855, 855, - 857, 858, 858, 858, 858, 858, 861, 862, 862, 862, - 862, 862, 766, 863, 863, 863, 863, 863, 863, 768, - 345, 344, 343, 864, 342, 341, 340, 339, 338, 864, - 864, 864, 864, 864, 864, 865, 866, 866, 866, 866, - 866, 377, 333, 332, 276, 867, 331, 330, 329, 328, - - 327, 867, 867, 867, 867, 867, 867, 1329, 864, 864, - 864, 864, 864, 864, 773, 773, 773, 773, 773, 773, - 870, 776, 776, 776, 776, 776, 776, 547, 778, 778, - 778, 778, 778, 778, 872, 780, 780, 780, 780, 780, - 780, 702, 874, 874, 874, 874, 874, 874, 704, 326, - 314, 242, 875, 311, 239, 236, 308, 131, 875, 875, - 875, 875, 875, 875, 1329, 875, 875, 875, 875, 875, - 875, 876, 877, 877, 877, 877, 877, 877, 878, 302, - 301, 298, 879, 297, 880, 276, 296, 295, 879, 879, - 879, 879, 879, 879, 917, 819, 819, 819, 819, 819, - - 819, 1329, 920, 920, 920, 920, 920, 920, 294, 293, - 880, 734, 895, 895, 895, 895, 895, 895, 896, 292, - 291, 290, 897, 289, 738, 288, 287, 286, 897, 897, - 897, 897, 897, 897, 926, 827, 827, 827, 827, 827, - 827, 586, 829, 829, 829, 829, 829, 829, 285, 284, - 738, 743, 898, 898, 898, 898, 898, 898, 899, 283, - 282, 279, 900, 278, 747, 277, 276, 275, 900, 900, - 900, 900, 900, 900, 928, 831, 831, 831, 831, 831, - 831, 1329, 931, 931, 931, 931, 931, 931, 952, 274, - 747, 754, 901, 901, 901, 901, 901, 901, 902, 273, - - 272, 953, 903, 271, 758, 270, 269, 268, 903, 903, - 903, 903, 903, 903, 839, 839, 839, 839, 839, 839, - 938, 842, 842, 842, 842, 842, 842, 953, 267, 266, - 758, 766, 904, 904, 904, 904, 904, 904, 905, 265, - 264, 263, 906, 262, 770, 261, 260, 259, 906, 906, - 906, 906, 906, 906, 595, 844, 844, 844, 844, 844, - 844, 940, 846, 846, 846, 846, 846, 846, 258, 1069, - 770, 908, 909, 909, 909, 909, 909, 910, 256, 255, - 254, 911, 1070, 253, 252, 251, 250, 911, 911, 911, - 911, 911, 911, 912, 913, 913, 913, 913, 913, 913, - - 914, 249, 246, 49, 915, 239, 916, 232, 1070, 231, - 915, 915, 915, 915, 915, 915, 1329, 943, 943, 943, - 943, 943, 943, 855, 855, 855, 855, 855, 855, 1071, - 230, 229, 916, 734, 919, 919, 919, 919, 919, 919, - 896, 228, 1072, 227, 920, 226, 225, 224, 221, 218, - 920, 920, 920, 920, 920, 920, 921, 922, 922, 922, - 922, 922, 922, 923, 215, 214, 213, 924, 1072, 925, - 212, 209, 208, 924, 924, 924, 924, 924, 924, 950, - 858, 858, 858, 858, 858, 858, 606, 860, 860, 860, - 860, 860, 860, 207, 206, 925, 743, 930, 930, 930, - - 930, 930, 930, 899, 205, 204, 203, 931, 202, 201, - 200, 199, 198, 931, 931, 931, 931, 931, 931, 932, - 933, 933, 933, 933, 933, 933, 934, 197, 196, 195, - 935, 194, 936, 190, 189, 179, 935, 935, 935, 935, - 935, 935, 952, 862, 862, 862, 862, 862, 862, 1329, - 955, 955, 955, 955, 955, 955, 178, 177, 936, 754, - 942, 942, 942, 942, 942, 942, 902, 174, 173, 172, - 943, 171, 170, 169, 167, 163, 943, 943, 943, 943, - 943, 943, 944, 945, 945, 945, 945, 945, 945, 946, - 162, 160, 159, 947, 158, 948, 157, 156, 154, 947, - - 947, 947, 947, 947, 947, 962, 963, 963, 963, 963, - 963, 965, 966, 966, 966, 966, 966, 153, 1115, 152, - 145, 948, 766, 954, 954, 954, 954, 954, 954, 905, - 138, 1116, 137, 955, 132, 84, 58, 47, 45, 955, - 955, 955, 955, 955, 955, 956, 957, 957, 957, 957, - 957, 957, 958, 1329, 1329, 1329, 959, 1116, 960, 1329, - 1329, 1329, 959, 959, 959, 959, 959, 959, 969, 970, - 970, 970, 970, 970, 1329, 972, 972, 972, 972, 972, - 972, 1120, 1122, 1329, 960, 876, 971, 971, 971, 971, - 971, 971, 878, 1329, 1121, 1123, 972, 1329, 1329, 48, - - 1329, 1329, 972, 972, 972, 972, 972, 972, 973, 974, - 974, 974, 974, 974, 48, 48, 48, 48, 975, 1329, - 1121, 1123, 1329, 1329, 975, 975, 975, 975, 975, 975, - 980, 48, 48, 1329, 48, 1329, 821, 821, 821, 821, - 821, 821, 978, 979, 1128, 1130, 1329, 48, 983, 989, - 990, 990, 990, 990, 990, 1329, 1329, 1129, 1131, 991, - 1329, 1329, 1329, 1329, 48, 991, 991, 991, 991, 991, - 991, 734, 820, 820, 820, 820, 820, 820, 896, 1087, - 1329, 1329, 821, 1129, 1131, 1329, 1329, 1136, 821, 821, - 821, 821, 821, 821, 992, 993, 993, 993, 993, 993, - - 1137, 1329, 1329, 1329, 994, 1329, 1329, 1329, 1329, 1329, - 994, 994, 994, 994, 994, 994, 743, 832, 832, 832, - 832, 832, 832, 899, 1329, 1329, 1137, 833, 1329, 1329, - 1329, 1329, 1329, 833, 833, 833, 833, 833, 833, 995, - 996, 996, 996, 996, 996, 1329, 1329, 1329, 1329, 997, - 1329, 1329, 1329, 1329, 1329, 997, 997, 997, 997, 997, - 997, 1329, 833, 833, 833, 833, 833, 833, 754, 847, - 847, 847, 847, 847, 847, 902, 1329, 1329, 1329, 848, - 1329, 1329, 1329, 1329, 1329, 848, 848, 848, 848, 848, - 848, 998, 999, 999, 999, 999, 999, 1329, 1329, 1329, - - 1329, 1000, 1329, 1329, 1329, 1329, 1329, 1000, 1000, 1000, - 1000, 1000, 1000, 1329, 848, 848, 848, 848, 848, 848, - 766, 863, 863, 863, 863, 863, 863, 905, 1329, 1329, - 1329, 864, 1329, 1329, 1329, 1329, 1329, 864, 864, 864, - 864, 864, 864, 1001, 1002, 1002, 1002, 1002, 1002, 1329, - 1329, 1329, 1329, 1003, 1329, 1329, 1329, 1329, 1329, 1003, - 1003, 1003, 1003, 1003, 1003, 1329, 864, 864, 864, 864, - 864, 864, 1005, 1006, 1006, 1006, 1006, 1006, 1006, 1007, - 1329, 1329, 1329, 1008, 1329, 1009, 1329, 1329, 1329, 1008, - 1008, 1008, 1008, 1008, 1008, 1011, 1012, 1012, 1012, 1012, - - 1012, 1329, 1014, 1014, 1014, 1014, 1014, 1014, 1329, 1329, - 1329, 1009, 912, 1013, 1013, 1013, 1013, 1013, 1013, 914, - 1329, 1329, 1329, 1014, 1329, 1329, 1329, 1329, 1329, 1014, - 1014, 1014, 1014, 1014, 1014, 1017, 1018, 1018, 1018, 1018, - 1018, 1021, 1022, 1022, 1022, 1022, 1022, 921, 1023, 1023, - 1023, 1023, 1023, 1023, 923, 1329, 1329, 1329, 1024, 1329, - 1329, 1329, 1329, 1329, 1024, 1024, 1024, 1024, 1024, 1024, - 1329, 1024, 1024, 1024, 1024, 1024, 1024, 1027, 1028, 1028, - 1028, 1028, 1028, 1030, 1031, 1031, 1031, 1031, 1031, 1034, - 1035, 1035, 1035, 1035, 1035, 932, 1036, 1036, 1036, 1036, - - 1036, 1036, 934, 1329, 1329, 1329, 1037, 1329, 1329, 1329, - 1329, 1329, 1037, 1037, 1037, 1037, 1037, 1037, 1329, 1037, - 1037, 1037, 1037, 1037, 1037, 1041, 1042, 1042, 1042, 1042, - 1042, 1044, 1045, 1045, 1045, 1045, 1045, 1048, 1049, 1049, - 1049, 1049, 1049, 944, 1050, 1050, 1050, 1050, 1050, 1050, - 946, 1329, 1329, 1329, 1051, 1329, 1329, 1329, 1329, 1329, - 1051, 1051, 1051, 1051, 1051, 1051, 1329, 1051, 1051, 1051, - 1051, 1051, 1051, 1055, 1056, 1056, 1056, 1056, 1056, 1058, - 1059, 1059, 1059, 1059, 1059, 1062, 1063, 1063, 1063, 1063, - 1063, 956, 1064, 1064, 1064, 1064, 1064, 1064, 958, 1329, - - 1329, 1329, 1065, 1329, 1329, 1329, 1329, 1329, 1065, 1065, - 1065, 1065, 1065, 1065, 1329, 1065, 1065, 1065, 1065, 1065, - 1065, 963, 963, 963, 963, 963, 963, 1069, 966, 966, - 966, 966, 966, 966, 702, 968, 968, 968, 968, 968, - 968, 1071, 970, 970, 970, 970, 970, 970, 876, 1073, - 1073, 1073, 1073, 1073, 1073, 878, 1329, 1329, 1329, 1074, - 1329, 1329, 1329, 1329, 1329, 1074, 1074, 1074, 1074, 1074, - 1074, 1329, 1074, 1074, 1074, 1074, 1074, 1074, 1075, 1076, - 1076, 1076, 1076, 1076, 1076, 1077, 48, 1329, 1138, 1078, - 1329, 1079, 1329, 1329, 1329, 1078, 1078, 1078, 1078, 1078, - - 1078, 1139, 1329, 48, 1107, 1108, 1108, 1108, 1108, 1108, - 1329, 1329, 1329, 1144, 1085, 1329, 1146, 1079, 1088, 1089, - 1089, 1089, 1089, 1089, 1090, 1329, 1145, 1139, 1091, 1147, - 1329, 1329, 1329, 1329, 1091, 1091, 1091, 1091, 1091, 1091, - 912, 1092, 1092, 1092, 1092, 1092, 1092, 1093, 1329, 1329, - 1329, 1094, 1145, 916, 1329, 1147, 1329, 1094, 1094, 1094, - 1094, 1094, 1094, 1329, 1110, 1110, 1110, 1110, 1110, 1110, - 1115, 1012, 1012, 1012, 1012, 1012, 1012, 1329, 1329, 916, - 921, 1095, 1095, 1095, 1095, 1095, 1095, 1096, 1329, 1329, - 1329, 1097, 1329, 925, 1329, 1329, 1329, 1097, 1097, 1097, - - 1097, 1097, 1097, 1329, 1118, 1118, 1118, 1118, 1118, 1118, - 1120, 1018, 1018, 1018, 1018, 1018, 1018, 1329, 1329, 925, - 932, 1098, 1098, 1098, 1098, 1098, 1098, 1099, 1329, 1329, - 1329, 1100, 1329, 936, 1329, 1329, 1329, 1100, 1100, 1100, - 1100, 1100, 1100, 734, 1020, 1020, 1020, 1020, 1020, 1020, - 1122, 1022, 1022, 1022, 1022, 1022, 1022, 1178, 1329, 936, - 944, 1101, 1101, 1101, 1101, 1101, 1101, 1102, 1329, 1329, - 1179, 1103, 1329, 948, 1329, 1329, 1329, 1103, 1103, 1103, - 1103, 1103, 1103, 1329, 1125, 1125, 1125, 1125, 1125, 1125, - 1028, 1028, 1028, 1028, 1028, 1028, 1179, 1329, 1329, 948, - - 956, 1104, 1104, 1104, 1104, 1104, 1104, 1105, 1329, 1329, - 1329, 1106, 1329, 960, 1329, 1329, 1329, 1106, 1106, 1106, - 1106, 1106, 1106, 1128, 1031, 1031, 1031, 1031, 1031, 1031, - 743, 1033, 1033, 1033, 1033, 1033, 1033, 1225, 1329, 960, - 1005, 1109, 1109, 1109, 1109, 1109, 1109, 1007, 1329, 1329, - 1226, 1110, 1329, 1329, 1329, 1329, 1329, 1110, 1110, 1110, - 1110, 1110, 1110, 912, 1117, 1117, 1117, 1117, 1117, 1117, - 1093, 1329, 1329, 1329, 1118, 1329, 1226, 1329, 1329, 1329, - 1118, 1118, 1118, 1118, 1118, 1118, 921, 1124, 1124, 1124, - 1124, 1124, 1124, 1096, 1329, 1329, 1329, 1125, 1329, 1329, - - 1329, 1329, 1329, 1125, 1125, 1125, 1125, 1125, 1125, 1130, - 1035, 1035, 1035, 1035, 1035, 1035, 932, 1132, 1132, 1132, - 1132, 1132, 1132, 1099, 1329, 1329, 1329, 1133, 1329, 1329, - 1329, 1329, 1329, 1133, 1133, 1133, 1133, 1133, 1133, 1329, - 1133, 1133, 1133, 1133, 1133, 1133, 1042, 1042, 1042, 1042, - 1042, 1042, 1136, 1045, 1045, 1045, 1045, 1045, 1045, 754, - 1047, 1047, 1047, 1047, 1047, 1047, 1138, 1049, 1049, 1049, - 1049, 1049, 1049, 944, 1140, 1140, 1140, 1140, 1140, 1140, - 1102, 1329, 1329, 1329, 1141, 1329, 1329, 1329, 1329, 1329, - 1141, 1141, 1141, 1141, 1141, 1141, 1329, 1141, 1141, 1141, - - 1141, 1141, 1141, 1056, 1056, 1056, 1056, 1056, 1056, 1144, - 1059, 1059, 1059, 1059, 1059, 1059, 766, 1061, 1061, 1061, - 1061, 1061, 1061, 1146, 1063, 1063, 1063, 1063, 1063, 1063, - 956, 1148, 1148, 1148, 1148, 1148, 1148, 1105, 1329, 1329, - 1329, 1149, 1329, 1329, 1329, 1329, 1329, 1149, 1149, 1149, - 1149, 1149, 1149, 1329, 1149, 1149, 1149, 1149, 1149, 1149, - 1152, 1153, 1153, 1153, 1153, 1153, 1155, 1156, 1156, 1156, - 1156, 1156, 1159, 1160, 1160, 1160, 1160, 1160, 1075, 1161, - 1161, 1161, 1161, 1161, 1161, 1077, 1329, 1329, 1329, 1162, - 1329, 48, 48, 1329, 1329, 1162, 1162, 1162, 1162, 1162, - - 1162, 1329, 1162, 1162, 1162, 1162, 1162, 1162, 48, 48, - 1329, 1014, 1014, 1014, 1014, 1014, 1014, 1329, 1329, 1329, - 1168, 1167, 1005, 1169, 1169, 1169, 1169, 1169, 1169, 1170, - 1329, 1329, 1329, 1171, 1329, 1009, 1329, 1329, 1329, 1171, - 1171, 1171, 1171, 1171, 1171, 1329, 1024, 1024, 1024, 1024, - 1024, 1024, 1329, 1037, 1037, 1037, 1037, 1037, 1037, 1227, - 1329, 1009, 912, 1013, 1013, 1013, 1013, 1013, 1013, 1093, - 1329, 1329, 1228, 1014, 1329, 1329, 1329, 1329, 1329, 1014, - 1014, 1014, 1014, 1014, 1014, 921, 1023, 1023, 1023, 1023, - 1023, 1023, 1096, 1329, 1329, 1329, 1024, 1329, 1228, 1329, - - 1329, 1329, 1024, 1024, 1024, 1024, 1024, 1024, 932, 1036, - 1036, 1036, 1036, 1036, 1036, 1099, 1329, 1329, 1329, 1037, - 1329, 1329, 1329, 1329, 1329, 1037, 1037, 1037, 1037, 1037, - 1037, 944, 1050, 1050, 1050, 1050, 1050, 1050, 1102, 1329, - 1329, 1329, 1051, 1329, 1329, 1329, 1329, 1329, 1051, 1051, - 1051, 1051, 1051, 1051, 1329, 1051, 1051, 1051, 1051, 1051, - 1051, 956, 1064, 1064, 1064, 1064, 1064, 1064, 1105, 1329, - 1329, 1329, 1065, 1329, 1329, 1329, 1329, 1329, 1065, 1065, - 1065, 1065, 1065, 1065, 1329, 1065, 1065, 1065, 1065, 1065, - 1065, 1178, 1108, 1108, 1108, 1108, 1108, 1108, 1005, 1180, - - 1180, 1180, 1180, 1180, 1180, 1170, 1329, 1329, 1329, 1181, - 1329, 1329, 1329, 1329, 1329, 1181, 1181, 1181, 1181, 1181, - 1181, 1329, 1181, 1181, 1181, 1181, 1181, 1181, 1184, 1185, - 1185, 1185, 1185, 1185, 1189, 1190, 1190, 1190, 1190, 1190, - 1192, 1193, 1193, 1193, 1193, 1193, 1198, 1199, 1199, 1199, - 1199, 1199, 1201, 1202, 1202, 1202, 1202, 1202, 1207, 1208, - 1208, 1208, 1208, 1208, 1210, 1211, 1211, 1211, 1211, 1211, - 1216, 1217, 1217, 1217, 1217, 1217, 1219, 1220, 1220, 1220, - 1220, 1220, 1153, 1153, 1153, 1153, 1153, 1153, 1225, 1156, - 1156, 1156, 1156, 1156, 1156, 876, 1158, 1158, 1158, 1158, - - 1158, 1158, 1227, 1160, 1160, 1160, 1160, 1160, 1160, 1075, - 1229, 1229, 1229, 1229, 1229, 1229, 1077, 1329, 1329, 1329, - 1230, 1329, 1329, 1329, 1329, 1329, 1230, 1230, 1230, 1230, - 1230, 1230, 1329, 1230, 1230, 1230, 1230, 1230, 1230, 1005, - 1109, 1109, 1109, 1109, 1109, 1109, 1170, 1329, 1329, 1329, - 1110, 1329, 1329, 1329, 1329, 1329, 1110, 1110, 1110, 1110, - 1110, 1110, 1329, 1110, 1110, 1110, 1110, 1110, 1110, 1244, - 1245, 1245, 1245, 1245, 1245, 1250, 1250, 1185, 1185, 1185, - 1185, 1185, 1185, 1329, 1329, 1329, 1329, 1329, 1251, 912, - 1187, 1187, 1187, 1187, 1187, 1187, 1190, 1190, 1190, 1190, - - 1190, 1190, 1254, 1254, 1193, 1193, 1193, 1193, 1193, 1193, - 1329, 1329, 1329, 1329, 1251, 1255, 921, 1195, 1195, 1195, - 1195, 1195, 1195, 1199, 1199, 1199, 1199, 1199, 1199, 1258, - 1258, 1202, 1202, 1202, 1202, 1202, 1202, 1329, 1329, 1329, - 1329, 1255, 1259, 932, 1204, 1204, 1204, 1204, 1204, 1204, - 1208, 1208, 1208, 1208, 1208, 1208, 1262, 1262, 1211, 1211, - 1211, 1211, 1211, 1211, 1329, 1329, 1329, 1329, 1259, 1263, - 944, 1213, 1213, 1213, 1213, 1213, 1213, 1217, 1217, 1217, - 1217, 1217, 1217, 1266, 1266, 1220, 1220, 1220, 1220, 1220, - 1220, 1329, 1329, 1329, 1329, 1263, 1267, 956, 1222, 1222, - - 1222, 1222, 1222, 1222, 1270, 1271, 1271, 1271, 1271, 1271, - 1273, 1274, 1274, 1274, 1274, 1274, 1282, 1329, 1329, 1329, - 1329, 1329, 1267, 1284, 1285, 1285, 1285, 1285, 1285, 1283, - 1282, 1245, 1245, 1245, 1245, 1245, 1245, 1005, 1247, 1247, - 1247, 1247, 1247, 1247, 1288, 1289, 1289, 1289, 1289, 1289, - 1329, 1329, 1329, 1329, 1329, 1283, 1292, 1293, 1293, 1293, - 1293, 1293, 1296, 1297, 1297, 1297, 1297, 1297, 1300, 1301, - 1301, 1301, 1301, 1301, 1271, 1271, 1271, 1271, 1271, 1271, - 1304, 1304, 1274, 1274, 1274, 1274, 1274, 1274, 1329, 1329, - 1329, 1329, 1329, 1305, 1075, 1276, 1276, 1276, 1276, 1276, - - 1276, 1308, 1309, 1309, 1309, 1309, 1309, 1285, 1285, 1285, - 1285, 1285, 1285, 1289, 1289, 1289, 1289, 1289, 1289, 1305, - 1293, 1293, 1293, 1293, 1293, 1293, 1297, 1297, 1297, 1297, - 1297, 1297, 1301, 1301, 1301, 1301, 1301, 1301, 1317, 1318, - 1318, 1318, 1318, 1318, 1309, 1309, 1309, 1309, 1309, 1309, - 1318, 1318, 1318, 1318, 1318, 1318, 46, 1329, 1329, 1329, - 1329, 46, 46, 46, 62, 1329, 62, 62, 62, 62, - 62, 62, 62, 139, 1329, 139, 144, 144, 144, 238, - 238, 238, 247, 247, 247, 307, 307, 307, 309, 309, - 309, 310, 310, 310, 317, 317, 317, 315, 315, 315, - - 325, 1329, 325, 367, 367, 367, 372, 372, 372, 373, - 373, 373, 386, 1329, 386, 387, 387, 387, 319, 319, - 1329, 1329, 319, 395, 395, 395, 439, 439, 439, 443, - 443, 443, 444, 444, 444, 445, 445, 445, 450, 450, - 450, 380, 380, 1329, 1329, 380, 459, 459, 459, 463, - 1329, 463, 464, 464, 464, 472, 1329, 472, 507, 507, - 507, 515, 515, 515, 516, 516, 516, 528, 1329, 528, - 531, 1329, 531, 532, 532, 532, 540, 1329, 540, 462, - 462, 1329, 1329, 462, 466, 466, 1329, 1329, 466, 550, - 550, 550, 444, 444, 444, 575, 575, 575, 579, 579, - - 579, 582, 582, 582, 583, 583, 583, 584, 584, 584, - 589, 589, 589, 522, 522, 1329, 1329, 522, 598, 598, - 598, 530, 530, 1329, 1329, 530, 534, 534, 1329, 1329, - 534, 609, 609, 609, 613, 1329, 613, 616, 1329, 616, - 617, 617, 617, 625, 1329, 625, 643, 643, 643, 654, - 654, 654, 655, 655, 655, 667, 1329, 667, 670, 1329, - 670, 671, 671, 671, 679, 1329, 679, 682, 1329, 682, - 685, 1329, 685, 686, 686, 686, 694, 1329, 694, 612, - 1329, 1329, 612, 615, 615, 1329, 1329, 615, 616, 616, - 1329, 616, 619, 619, 1329, 1329, 619, 705, 705, 705, - - 625, 625, 1329, 625, 53, 53, 53, 1329, 53, 53, - 583, 583, 583, 720, 720, 720, 724, 724, 724, 727, - 727, 727, 730, 730, 730, 731, 731, 731, 732, 732, - 732, 737, 737, 737, 661, 661, 1329, 1329, 661, 746, - 746, 746, 667, 667, 1329, 667, 669, 669, 1329, 1329, - 669, 670, 670, 1329, 670, 673, 673, 1329, 1329, 673, - 757, 757, 757, 679, 679, 1329, 679, 681, 1329, 1329, - 681, 682, 682, 1329, 682, 684, 684, 1329, 1329, 684, - 685, 685, 1329, 685, 688, 688, 1329, 1329, 688, 769, - 769, 769, 694, 694, 1329, 694, 771, 1329, 771, 774, - - 1329, 774, 777, 1329, 777, 778, 778, 778, 786, 1329, - 786, 53, 53, 53, 1329, 53, 53, 798, 798, 798, - 812, 812, 812, 813, 813, 813, 825, 1329, 825, 828, - 1329, 828, 829, 829, 829, 837, 1329, 837, 840, 1329, - 840, 843, 1329, 843, 844, 844, 844, 852, 1329, 852, - 853, 1329, 853, 856, 1329, 856, 859, 1329, 859, 860, - 860, 860, 868, 1329, 868, 771, 1329, 771, 773, 1329, - 1329, 773, 774, 774, 1329, 774, 776, 776, 1329, 1329, - 776, 777, 777, 1329, 777, 780, 780, 1329, 1329, 780, - 879, 879, 879, 786, 786, 1329, 786, 53, 53, 53, - - 1329, 53, 53, 731, 731, 731, 893, 893, 893, 897, - 897, 897, 900, 900, 900, 903, 903, 903, 906, 906, - 906, 907, 907, 907, 915, 915, 915, 819, 819, 1329, - 1329, 819, 924, 924, 924, 825, 825, 1329, 825, 827, - 827, 1329, 1329, 827, 828, 828, 1329, 828, 831, 831, - 1329, 1329, 831, 935, 935, 935, 837, 837, 1329, 837, - 839, 1329, 1329, 839, 840, 840, 1329, 840, 842, 842, - 1329, 1329, 842, 843, 843, 1329, 843, 846, 846, 1329, - 1329, 846, 947, 947, 947, 852, 852, 1329, 852, 853, - 1329, 853, 855, 1329, 1329, 855, 856, 856, 1329, 856, - - 858, 858, 1329, 1329, 858, 859, 859, 1329, 859, 862, - 862, 1329, 1329, 862, 959, 959, 959, 868, 868, 1329, - 868, 961, 1329, 961, 964, 1329, 964, 967, 1329, 967, - 968, 968, 968, 976, 1329, 976, 53, 53, 53, 1329, - 53, 53, 987, 987, 987, 1004, 1004, 1004, 1010, 1010, - 1010, 1008, 1008, 1008, 1015, 1015, 1015, 1016, 1329, 1016, - 1019, 1329, 1019, 1020, 1020, 1020, 1025, 1025, 1025, 1026, - 1329, 1026, 1029, 1329, 1029, 1032, 1329, 1032, 1033, 1033, - 1033, 1038, 1038, 1038, 1039, 1329, 1039, 1040, 1329, 1040, - 1043, 1329, 1043, 1046, 1329, 1046, 1047, 1047, 1047, 1052, - - 1052, 1052, 1053, 1329, 1053, 1054, 1329, 1054, 1057, 1329, - 1057, 1060, 1329, 1060, 1061, 1061, 1061, 1066, 1066, 1066, - 1067, 1329, 1067, 961, 1329, 961, 963, 1329, 1329, 963, - 964, 964, 1329, 964, 966, 966, 1329, 1329, 966, 967, - 967, 1329, 967, 970, 970, 1329, 1329, 970, 1078, 1078, - 1078, 976, 976, 1329, 976, 53, 53, 53, 1329, 53, - 53, 907, 907, 907, 1094, 1094, 1094, 1097, 1097, 1097, - 1100, 1100, 1100, 1103, 1103, 1103, 1106, 1106, 1106, 1111, - 1111, 1111, 1113, 1329, 1113, 1114, 1114, 1114, 1012, 1012, - 1329, 1329, 1012, 1119, 1119, 1119, 1016, 1016, 1329, 1016, - - 1018, 1018, 1329, 1329, 1018, 1019, 1019, 1329, 1019, 1022, - 1022, 1329, 1329, 1022, 1126, 1126, 1126, 1026, 1026, 1329, - 1026, 1028, 1329, 1329, 1028, 1029, 1029, 1329, 1029, 1031, - 1031, 1329, 1329, 1031, 1032, 1032, 1329, 1032, 1035, 1035, - 1329, 1329, 1035, 1134, 1134, 1134, 1039, 1039, 1329, 1039, - 1040, 1329, 1040, 1042, 1329, 1329, 1042, 1043, 1043, 1329, - 1043, 1045, 1045, 1329, 1329, 1045, 1046, 1046, 1329, 1046, - 1049, 1049, 1329, 1329, 1049, 1142, 1142, 1142, 1053, 1053, - 1329, 1053, 1054, 1329, 1054, 1056, 1329, 1329, 1056, 1057, - 1057, 1329, 1057, 1059, 1059, 1329, 1329, 1059, 1060, 1060, - - 1329, 1060, 1063, 1063, 1329, 1329, 1063, 1150, 1150, 1150, - 1067, 1067, 1329, 1067, 1151, 1329, 1151, 1154, 1329, 1154, - 1157, 1329, 1157, 1158, 1158, 1158, 1163, 1329, 1163, 1164, - 1329, 1164, 53, 53, 53, 1329, 53, 53, 1172, 1329, - 1172, 1171, 1171, 1171, 1173, 1329, 1173, 1174, 1329, 1174, - 1175, 1329, 1175, 1176, 1329, 1176, 1177, 1329, 1177, 1108, - 1108, 1329, 1329, 1108, 1182, 1182, 1182, 317, 317, 317, - 1113, 1113, 1329, 1113, 1183, 1183, 1183, 1186, 1329, 1186, - 1187, 1187, 1187, 1188, 1188, 1188, 1191, 1329, 1191, 1194, - 1329, 1194, 1195, 1195, 1195, 1196, 1196, 1196, 1197, 1329, - - 1197, 1200, 1329, 1200, 1203, 1329, 1203, 1204, 1204, 1204, - 1205, 1205, 1205, 1206, 1329, 1206, 1209, 1329, 1209, 1212, - 1329, 1212, 1213, 1213, 1213, 1214, 1214, 1214, 1215, 1329, - 1215, 1218, 1329, 1218, 1221, 1329, 1221, 1222, 1222, 1222, - 1223, 1223, 1223, 1151, 1329, 1151, 1153, 1329, 1329, 1153, - 1154, 1154, 1329, 1154, 1156, 1156, 1329, 1329, 1156, 1157, - 1157, 1329, 1157, 1160, 1160, 1329, 1329, 1160, 1231, 1329, - 1231, 1164, 1164, 1329, 1164, 53, 53, 53, 1329, 53, - 53, 1236, 1236, 1236, 1238, 1329, 1238, 1239, 1329, 1239, - 1240, 1329, 1240, 1241, 1329, 1241, 1242, 1329, 1242, 1243, - - 1329, 1243, 1246, 1329, 1246, 1247, 1247, 1247, 1248, 1248, - 1248, 1249, 1329, 1249, 1185, 1185, 1329, 1329, 1185, 1186, - 1186, 1329, 1186, 1252, 1329, 1252, 1190, 1329, 1329, 1190, - 1191, 1191, 1329, 1191, 1193, 1193, 1329, 1329, 1193, 1194, - 1194, 1329, 1194, 1256, 1329, 1256, 1197, 1329, 1197, 1199, - 1329, 1329, 1199, 1200, 1200, 1329, 1200, 1202, 1202, 1329, - 1329, 1202, 1203, 1203, 1329, 1203, 1260, 1329, 1260, 1206, - 1329, 1206, 1208, 1329, 1329, 1208, 1209, 1209, 1329, 1209, - 1211, 1211, 1329, 1329, 1211, 1212, 1212, 1329, 1212, 1264, - 1329, 1264, 1215, 1329, 1215, 1217, 1329, 1329, 1217, 1218, - - 1218, 1329, 1218, 1220, 1220, 1329, 1329, 1220, 1221, 1221, - 1329, 1221, 1268, 1329, 1268, 1269, 1329, 1269, 1272, 1329, - 1272, 1275, 1329, 1275, 1276, 1276, 1276, 1277, 1329, 1277, - 53, 53, 53, 1329, 53, 53, 1281, 1329, 1281, 1183, - 1329, 1183, 1188, 1329, 1188, 1196, 1329, 1196, 1205, 1329, - 1205, 1214, 1329, 1214, 1223, 1329, 1223, 1245, 1245, 1329, - 1329, 1245, 1246, 1246, 1329, 1246, 1237, 1329, 1237, 1286, - 1329, 1286, 1287, 1329, 1287, 1290, 1329, 1290, 1291, 1329, - 1291, 1294, 1329, 1294, 1295, 1329, 1295, 1298, 1329, 1298, - 1299, 1329, 1299, 1302, 1329, 1302, 1271, 1329, 1329, 1271, - - 1274, 1274, 1329, 1329, 1274, 1306, 1329, 1306, 1248, 1329, - 1248, 1310, 1329, 1310, 1285, 1329, 1329, 1285, 1289, 1329, - 1329, 1289, 1293, 1329, 1329, 1293, 1297, 1329, 1329, 1297, - 1301, 1329, 1329, 1301, 1316, 1329, 1316, 1319, 1329, 1319, - 1309, 1329, 1329, 1309, 1321, 1329, 1321, 1322, 1329, 1322, - 1323, 1329, 1323, 1324, 1329, 1324, 1325, 1329, 1325, 1318, - 1329, 1329, 1318, 1327, 1329, 1327, 1328, 1329, 1328, 3, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329 - } ; - -static yyconst flex_int16_t yy_chk[6623] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 4, 7, 91, 4, 7, 4, 7, 9, - 4, 7, 9, 12, 9, 24, 12, 9, 12, 4, - 7, 12, 15, 17, 17, 1319, 9, 4, 7, 24, - 12, 19, 19, 64, 9, 64, 24, 91, 12, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 15, 27, - - 27, 14, 14, 14, 1310, 1302, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 16, 28, 23, 16, 23, 16, 28, 29, 16, - 23, 87, 1298, 1294, 34, 23, 87, 22, 16, 23, - 22, 23, 22, 34, 29, 22, 16, 20, 20, 20, - 20, 20, 20, 20, 22, 26, 25, 33, 39, 25, - 20, 33, 22, 25, 96, 26, 35, 38, 26, 96, - 33, 33, 39, 38, 33, 38, 33, 38, 35, 1290, - 35, 38, 35, 38, 38, 35, 20, 21, 21, 21, - - 21, 21, 21, 21, 95, 32, 32, 21, 1286, 1275, - 95, 1272, 69, 21, 21, 21, 21, 21, 21, 31, - 32, 75, 31, 31, 32, 31, 69, 31, 32, 31, - 32, 31, 37, 36, 31, 75, 37, 32, 36, 36, - 41, 36, 36, 80, 37, 1246, 1230, 123, 41, 37, - 44, 37, 41, 44, 41, 44, 80, 78, 44, 49, - 49, 49, 49, 49, 49, 123, 141, 44, 52, 52, - 52, 52, 52, 52, 52, 44, 50, 50, 50, 50, - 50, 50, 50, 78, 1221, 99, 295, 50, 99, 78, - 99, 295, 141, 50, 50, 50, 50, 50, 50, 54, - - 54, 54, 54, 54, 54, 61, 626, 168, 61, 54, - 61, 168, 118, 61, 92, 54, 54, 54, 54, 54, - 54, 55, 61, 626, 55, 118, 55, 634, 1218, 55, - 61, 127, 55, 55, 55, 55, 55, 55, 55, 1212, - 92, 127, 55, 148, 634, 92, 55, 634, 55, 55, - 55, 55, 55, 55, 63, 63, 63, 63, 63, 63, - 63, 125, 143, 143, 143, 143, 143, 143, 143, 148, - 125, 155, 155, 155, 155, 155, 155, 155, 1209, 226, - 1203, 1200, 196, 241, 1194, 318, 351, 63, 140, 140, - 140, 140, 140, 140, 140, 196, 1191, 304, 318, 323, - - 351, 140, 226, 233, 233, 233, 233, 233, 233, 241, - 244, 244, 244, 244, 244, 244, 247, 247, 247, 247, - 247, 247, 247, 304, 318, 323, 348, 140, 142, 142, - 142, 142, 142, 142, 142, 370, 376, 384, 142, 348, - 1186, 1182, 639, 1181, 142, 142, 142, 142, 142, 142, - 145, 145, 145, 145, 145, 145, 145, 390, 454, 639, - 145, 370, 376, 384, 390, 454, 145, 145, 145, 145, - 145, 145, 147, 147, 147, 147, 147, 147, 147, 147, - 1170, 1164, 299, 147, 379, 147, 1157, 299, 265, 147, - 147, 147, 147, 147, 147, 265, 299, 379, 299, 299, - - 407, 299, 312, 312, 312, 312, 312, 312, 265, 407, - 409, 147, 161, 161, 161, 161, 161, 161, 161, 409, - 1154, 1150, 437, 379, 265, 315, 315, 315, 315, 315, - 315, 315, 319, 319, 319, 319, 319, 319, 319, 1149, - 1142, 161, 234, 234, 234, 234, 234, 234, 437, 1141, - 545, 1134, 234, 1133, 470, 510, 513, 545, 234, 234, - 234, 234, 234, 234, 235, 235, 235, 235, 235, 235, - 235, 235, 240, 240, 240, 240, 240, 240, 240, 240, - 470, 510, 513, 240, 519, 240, 1126, 1125, 1119, 240, - 240, 240, 240, 240, 240, 321, 321, 321, 321, 321, - - 321, 321, 365, 365, 365, 365, 365, 365, 461, 465, - 519, 240, 245, 245, 245, 245, 245, 245, 245, 245, - 526, 461, 465, 245, 538, 1118, 637, 1114, 1113, 245, - 245, 245, 245, 245, 245, 246, 246, 246, 246, 246, - 246, 1112, 593, 637, 637, 246, 526, 461, 465, 593, - 538, 246, 246, 246, 246, 246, 246, 303, 303, 303, - 303, 303, 303, 303, 388, 388, 388, 388, 388, 388, - 303, 380, 380, 380, 380, 380, 380, 380, 382, 382, - 382, 382, 382, 382, 382, 392, 392, 392, 392, 392, - 392, 521, 529, 533, 628, 640, 303, 308, 308, 308, - - 308, 308, 308, 604, 521, 529, 533, 308, 611, 627, - 604, 628, 640, 308, 308, 308, 308, 308, 308, 311, - 311, 311, 311, 311, 311, 311, 627, 623, 628, 311, - 521, 529, 533, 627, 611, 311, 311, 311, 311, 311, - 311, 313, 313, 313, 313, 313, 313, 313, 313, 700, - 741, 646, 313, 623, 633, 635, 700, 741, 313, 313, - 313, 313, 313, 313, 314, 314, 314, 314, 314, 314, - 314, 633, 635, 649, 314, 635, 633, 646, 638, 707, - 314, 314, 314, 314, 314, 314, 320, 320, 320, 320, - 320, 320, 320, 320, 1111, 638, 707, 320, 638, 649, - - 719, 708, 1091, 320, 320, 320, 320, 320, 320, 322, - 322, 322, 322, 322, 322, 322, 322, 719, 708, 652, - 322, 658, 322, 708, 665, 677, 322, 322, 322, 322, - 322, 322, 395, 395, 395, 395, 395, 395, 395, 447, - 447, 447, 447, 447, 447, 652, 680, 658, 322, 334, - 665, 677, 692, 334, 772, 1074, 334, 709, 614, 334, - 618, 334, 334, 334, 334, 366, 366, 366, 366, 366, - 366, 614, 680, 618, 709, 366, 1067, 1066, 692, 709, - 772, 366, 366, 366, 366, 366, 366, 369, 369, 369, - 369, 369, 369, 369, 369, 752, 764, 614, 369, 618, - - 369, 1060, 752, 764, 369, 369, 369, 369, 369, 369, - 450, 450, 450, 450, 450, 450, 450, 452, 452, 452, - 452, 452, 452, 1057, 660, 797, 369, 375, 375, 375, - 375, 375, 375, 375, 375, 1053, 874, 660, 375, 1052, - 375, 1046, 797, 874, 375, 375, 375, 375, 375, 375, - 456, 456, 456, 456, 456, 456, 459, 459, 459, 459, - 459, 459, 459, 660, 629, 630, 375, 381, 381, 381, - 381, 381, 381, 381, 381, 1043, 784, 1039, 381, 1038, - 801, 629, 630, 710, 381, 381, 381, 381, 381, 381, - 383, 383, 383, 383, 383, 383, 383, 383, 629, 630, - - 710, 383, 784, 383, 1032, 710, 801, 383, 383, 383, - 383, 383, 383, 462, 462, 462, 462, 462, 462, 462, - 464, 464, 464, 464, 464, 464, 464, 632, 711, 383, - 393, 393, 393, 393, 393, 393, 393, 393, 1029, 804, - 807, 393, 712, 1026, 632, 711, 1025, 393, 393, 393, - 393, 393, 393, 394, 394, 394, 394, 394, 394, 712, - 711, 632, 1019, 394, 712, 804, 807, 1016, 1015, 394, - 394, 394, 394, 394, 394, 436, 436, 436, 436, 436, - 436, 541, 541, 541, 541, 541, 541, 436, 466, 466, - 466, 466, 466, 466, 466, 468, 468, 468, 468, 468, - - 468, 468, 522, 522, 522, 522, 522, 522, 522, 668, - 672, 713, 641, 436, 440, 440, 440, 440, 440, 440, - 1010, 1007, 668, 672, 440, 1004, 796, 717, 713, 641, - 440, 440, 440, 440, 440, 440, 442, 442, 442, 442, - 442, 442, 641, 796, 717, 713, 442, 717, 668, 672, - 714, 796, 442, 442, 442, 442, 442, 442, 446, 446, - 446, 446, 446, 446, 446, 1003, 810, 714, 446, 1000, - 816, 715, 714, 794, 446, 446, 446, 446, 446, 446, - 448, 448, 448, 448, 448, 448, 448, 448, 715, 823, - 794, 448, 810, 715, 791, 794, 816, 448, 448, 448, - - 448, 448, 448, 449, 449, 449, 449, 449, 449, 449, - 919, 791, 835, 449, 791, 823, 997, 919, 994, 449, - 449, 449, 449, 449, 449, 457, 457, 457, 457, 457, - 457, 457, 457, 838, 850, 854, 457, 866, 835, 884, - 892, 991, 457, 457, 457, 457, 457, 457, 458, 458, - 458, 458, 458, 458, 458, 987, 884, 892, 458, 838, - 850, 854, 887, 866, 458, 458, 458, 458, 458, 458, - 467, 467, 467, 467, 467, 467, 467, 467, 976, 887, - 975, 467, 909, 887, 890, 891, 981, 467, 467, 467, - 467, 467, 467, 469, 469, 469, 469, 469, 469, 469, - - 469, 890, 891, 981, 469, 890, 469, 891, 909, 967, - 469, 469, 469, 469, 469, 469, 524, 524, 524, 524, - 524, 524, 524, 530, 530, 530, 530, 530, 530, 530, - 790, 683, 469, 506, 506, 506, 506, 506, 506, 930, - 964, 942, 958, 506, 683, 962, 930, 790, 942, 506, - 506, 506, 506, 506, 506, 509, 509, 509, 509, 509, - 509, 509, 509, 955, 790, 946, 509, 974, 509, 943, - 683, 962, 509, 509, 509, 509, 509, 509, 532, 532, - 532, 532, 532, 532, 532, 534, 534, 534, 534, 534, - 534, 534, 687, 974, 509, 512, 512, 512, 512, 512, - - 512, 512, 512, 954, 1073, 687, 512, 934, 512, 931, - 954, 1073, 512, 512, 512, 512, 512, 512, 536, 536, - 536, 536, 536, 536, 536, 543, 543, 543, 543, 543, - 543, 687, 980, 985, 512, 518, 518, 518, 518, 518, - 518, 518, 518, 923, 920, 914, 518, 911, 518, 980, - 985, 980, 518, 518, 518, 518, 518, 518, 547, 547, - 547, 547, 547, 547, 550, 550, 550, 550, 550, 550, - 550, 718, 795, 792, 518, 523, 523, 523, 523, 523, - 523, 523, 523, 910, 990, 907, 523, 993, 718, 795, - 792, 792, 523, 523, 523, 523, 523, 523, 525, 525, - - 525, 525, 525, 525, 525, 525, 795, 718, 792, 525, - 990, 525, 893, 993, 875, 525, 525, 525, 525, 525, - 525, 579, 579, 579, 579, 579, 579, 579, 582, 582, - 582, 582, 582, 582, 582, 886, 793, 525, 535, 535, - 535, 535, 535, 535, 535, 535, 868, 996, 867, 535, - 999, 1002, 886, 793, 859, 535, 535, 535, 535, 535, - 535, 537, 537, 537, 537, 537, 537, 537, 537, 793, - 856, 886, 537, 996, 537, 852, 999, 1002, 537, 537, - 537, 537, 537, 537, 586, 586, 586, 586, 586, 586, - 589, 589, 589, 589, 589, 589, 589, 775, 716, 787, - - 537, 548, 548, 548, 548, 548, 548, 548, 548, 1027, - 775, 1041, 548, 851, 843, 716, 787, 840, 548, 548, - 548, 548, 548, 548, 549, 549, 549, 549, 549, 549, - 716, 787, 1055, 837, 549, 1027, 775, 1041, 1080, 779, - 549, 549, 549, 549, 549, 549, 576, 576, 576, 576, - 576, 576, 779, 836, 1089, 1080, 576, 1152, 1055, 977, - 982, 828, 576, 576, 576, 576, 576, 576, 577, 577, - 577, 577, 577, 577, 577, 577, 977, 982, 779, 577, - 1089, 825, 1081, 1152, 818, 577, 577, 577, 577, 577, - 577, 578, 578, 578, 578, 578, 578, 818, 982, 1081, - - 977, 578, 1189, 1198, 978, 889, 824, 578, 578, 578, - 578, 578, 578, 580, 580, 580, 580, 580, 580, 580, - 580, 978, 889, 818, 580, 1207, 979, 984, 1189, 1198, - 580, 580, 580, 580, 580, 580, 581, 581, 581, 581, - 581, 581, 889, 979, 984, 978, 581, 817, 1082, 984, - 813, 1207, 581, 581, 581, 581, 581, 581, 585, 585, - 585, 585, 585, 585, 585, 1082, 1117, 979, 585, 812, - 1216, 1083, 1084, 1117, 585, 585, 585, 585, 585, 585, - 587, 587, 587, 587, 587, 587, 587, 587, 1083, 1084, - 1270, 587, 811, 808, 1084, 1166, 1216, 587, 587, 587, - - 587, 587, 587, 588, 588, 588, 588, 588, 588, 588, - 1124, 1132, 1166, 588, 805, 1166, 1270, 1124, 1132, 588, - 588, 588, 588, 588, 588, 591, 591, 591, 591, 591, - 591, 595, 595, 595, 595, 595, 595, 596, 596, 596, - 596, 596, 596, 596, 596, 1140, 1148, 1284, 596, 1288, - 802, 1167, 1140, 1148, 596, 596, 596, 596, 596, 596, - 597, 597, 597, 597, 597, 597, 597, 1180, 1167, 799, - 597, 1167, 798, 1284, 1180, 1288, 597, 597, 597, 597, - 597, 597, 598, 598, 598, 598, 598, 598, 598, 600, - 600, 600, 600, 600, 600, 602, 602, 602, 602, 602, - - 602, 606, 606, 606, 606, 606, 606, 607, 607, 607, - 607, 607, 607, 607, 607, 1229, 1292, 1296, 607, 786, - 1234, 1235, 1229, 785, 607, 607, 607, 607, 607, 607, - 608, 608, 608, 608, 608, 608, 608, 1234, 1235, 777, - 608, 774, 1292, 1296, 765, 1234, 608, 608, 608, 608, - 608, 608, 609, 609, 609, 609, 609, 609, 609, 612, - 612, 612, 612, 612, 612, 615, 615, 615, 615, 615, - 615, 615, 617, 617, 617, 617, 617, 617, 617, 619, - 619, 619, 619, 619, 619, 619, 620, 620, 620, 620, - 620, 620, 620, 620, 753, 742, 732, 620, 731, 720, - - 701, 694, 693, 620, 620, 620, 620, 620, 620, 621, - 621, 621, 621, 621, 621, 621, 622, 622, 622, 622, - 622, 622, 622, 622, 631, 636, 1278, 622, 642, 622, - 685, 826, 682, 622, 622, 622, 622, 622, 622, 881, - 1300, 631, 636, 1278, 826, 642, 661, 661, 661, 661, - 661, 661, 661, 631, 636, 622, 881, 642, 645, 645, - 645, 645, 645, 645, 645, 645, 1300, 881, 679, 645, - 826, 645, 678, 670, 667, 645, 645, 645, 645, 645, - 645, 663, 663, 663, 663, 663, 663, 663, 669, 669, - 669, 669, 669, 669, 669, 1168, 1280, 645, 648, 648, - - 648, 648, 648, 648, 648, 648, 666, 659, 656, 648, - 655, 648, 1168, 1280, 654, 648, 648, 648, 648, 648, - 648, 671, 671, 671, 671, 671, 671, 671, 673, 673, - 673, 673, 673, 673, 673, 830, 1168, 648, 651, 651, - 651, 651, 651, 651, 651, 651, 653, 650, 830, 651, - 1308, 651, 647, 644, 643, 651, 651, 651, 651, 651, - 651, 675, 675, 675, 675, 675, 675, 675, 681, 681, - 681, 681, 681, 681, 830, 1307, 1308, 651, 657, 657, - 657, 657, 657, 657, 657, 657, 625, 624, 616, 657, - 1317, 657, 1307, 613, 605, 657, 657, 657, 657, 657, - - 657, 684, 684, 684, 684, 684, 684, 684, 686, 686, - 686, 686, 686, 686, 686, 1165, 1317, 657, 662, 662, - 662, 662, 662, 662, 662, 662, 594, 584, 583, 662, - 575, 571, 1165, 570, 569, 662, 662, 662, 662, 662, - 662, 664, 664, 664, 664, 664, 664, 664, 664, 1165, - 567, 566, 664, 563, 664, 562, 561, 560, 664, 664, - 664, 664, 664, 664, 688, 688, 688, 688, 688, 688, - 688, 690, 690, 690, 690, 690, 690, 690, 1232, 559, - 664, 674, 674, 674, 674, 674, 674, 674, 674, 558, - 557, 556, 674, 555, 554, 1232, 553, 552, 674, 674, - - 674, 674, 674, 674, 676, 676, 676, 676, 676, 676, - 676, 676, 546, 540, 1232, 676, 539, 676, 531, 528, - 527, 676, 676, 676, 676, 676, 676, 696, 696, 696, - 696, 696, 696, 698, 698, 698, 698, 698, 698, 1279, - 841, 520, 517, 676, 689, 689, 689, 689, 689, 689, - 689, 689, 516, 841, 515, 689, 1279, 514, 511, 508, - 507, 689, 689, 689, 689, 689, 689, 691, 691, 691, - 691, 691, 691, 691, 691, 1279, 505, 501, 691, 841, - 691, 498, 497, 496, 691, 691, 691, 691, 691, 691, - 702, 702, 702, 702, 702, 702, 705, 705, 705, 705, - - 705, 705, 705, 845, 788, 789, 691, 703, 703, 703, - 703, 703, 703, 703, 703, 495, 845, 491, 703, 490, - 488, 788, 789, 487, 703, 703, 703, 703, 703, 703, - 704, 704, 704, 704, 704, 704, 788, 789, 789, 486, - 704, 485, 845, 484, 483, 857, 704, 704, 704, 704, - 704, 704, 721, 721, 721, 721, 721, 721, 857, 482, - 481, 480, 721, 479, 478, 477, 474, 473, 721, 721, - 721, 721, 721, 721, 722, 722, 722, 722, 722, 722, - 722, 722, 472, 471, 857, 722, 1085, 463, 455, 445, - 444, 722, 722, 722, 722, 722, 722, 723, 723, 723, - - 723, 723, 723, 1085, 443, 441, 439, 723, 438, 435, - 434, 433, 1085, 723, 723, 723, 723, 723, 723, 724, - 724, 724, 724, 724, 724, 724, 725, 725, 725, 725, - 725, 725, 725, 725, 432, 431, 430, 725, 1233, 429, - 428, 427, 426, 725, 725, 725, 725, 725, 725, 726, - 726, 726, 726, 726, 726, 1233, 424, 421, 420, 726, - 419, 418, 417, 416, 1233, 726, 726, 726, 726, 726, - 726, 727, 727, 727, 727, 727, 727, 727, 728, 728, - 728, 728, 728, 728, 728, 728, 415, 413, 412, 728, - 411, 410, 408, 406, 405, 728, 728, 728, 728, 728, - - 728, 729, 729, 729, 729, 729, 729, 404, 403, 402, - 401, 729, 399, 398, 391, 387, 386, 729, 729, 729, - 729, 729, 729, 730, 730, 730, 730, 730, 730, 730, - 733, 733, 733, 733, 733, 733, 733, 385, 378, 377, - 733, 374, 373, 372, 371, 368, 733, 733, 733, 733, - 733, 733, 734, 734, 734, 734, 734, 734, 735, 735, - 735, 735, 735, 735, 735, 735, 367, 364, 363, 735, - 362, 361, 360, 359, 358, 735, 735, 735, 735, 735, - 735, 736, 736, 736, 736, 736, 736, 736, 357, 356, - 355, 736, 354, 352, 350, 349, 347, 736, 736, 736, - - 736, 736, 736, 737, 737, 737, 737, 737, 737, 737, - 739, 739, 739, 739, 739, 739, 743, 743, 743, 743, - 743, 743, 744, 744, 744, 744, 744, 744, 744, 744, - 346, 343, 342, 744, 340, 338, 337, 336, 333, 744, - 744, 744, 744, 744, 744, 745, 745, 745, 745, 745, - 745, 745, 332, 330, 329, 745, 328, 326, 325, 324, - 317, 745, 745, 745, 745, 745, 745, 746, 746, 746, - 746, 746, 746, 746, 748, 748, 748, 748, 748, 748, - 750, 750, 750, 750, 750, 750, 754, 754, 754, 754, - 754, 754, 755, 755, 755, 755, 755, 755, 755, 755, - - 310, 309, 307, 755, 306, 305, 300, 298, 293, 755, - 755, 755, 755, 755, 755, 756, 756, 756, 756, 756, - 756, 756, 291, 289, 288, 756, 287, 286, 285, 284, - 283, 756, 756, 756, 756, 756, 756, 757, 757, 757, - 757, 757, 757, 757, 760, 760, 760, 760, 760, 760, - 762, 762, 762, 762, 762, 762, 766, 766, 766, 766, - 766, 766, 767, 767, 767, 767, 767, 767, 767, 767, - 281, 280, 279, 767, 274, 271, 270, 269, 266, 767, - 767, 767, 767, 767, 767, 768, 768, 768, 768, 768, - 768, 768, 263, 262, 260, 768, 258, 257, 255, 252, - - 251, 768, 768, 768, 768, 768, 768, 769, 769, 769, - 769, 769, 769, 769, 773, 773, 773, 773, 773, 773, - 776, 776, 776, 776, 776, 776, 776, 778, 778, 778, - 778, 778, 778, 778, 780, 780, 780, 780, 780, 780, - 780, 781, 781, 781, 781, 781, 781, 781, 781, 250, - 243, 242, 781, 239, 238, 237, 236, 232, 781, 781, - 781, 781, 781, 781, 782, 782, 782, 782, 782, 782, - 782, 783, 783, 783, 783, 783, 783, 783, 783, 231, - 229, 225, 783, 223, 783, 219, 217, 215, 783, 783, - 783, 783, 783, 783, 819, 819, 819, 819, 819, 819, - - 819, 821, 821, 821, 821, 821, 821, 821, 214, 212, - 783, 800, 800, 800, 800, 800, 800, 800, 800, 211, - 210, 209, 800, 208, 800, 207, 206, 204, 800, 800, - 800, 800, 800, 800, 827, 827, 827, 827, 827, 827, - 827, 829, 829, 829, 829, 829, 829, 829, 202, 200, - 800, 803, 803, 803, 803, 803, 803, 803, 803, 199, - 197, 195, 803, 194, 803, 192, 189, 188, 803, 803, - 803, 803, 803, 803, 831, 831, 831, 831, 831, 831, - 831, 833, 833, 833, 833, 833, 833, 833, 861, 187, - 803, 806, 806, 806, 806, 806, 806, 806, 806, 185, - - 183, 861, 806, 182, 806, 179, 178, 176, 806, 806, - 806, 806, 806, 806, 839, 839, 839, 839, 839, 839, - 842, 842, 842, 842, 842, 842, 842, 861, 175, 174, - 806, 809, 809, 809, 809, 809, 809, 809, 809, 173, - 172, 171, 809, 170, 809, 169, 167, 165, 809, 809, - 809, 809, 809, 809, 844, 844, 844, 844, 844, 844, - 844, 846, 846, 846, 846, 846, 846, 846, 164, 965, - 809, 814, 814, 814, 814, 814, 814, 814, 160, 159, - 158, 814, 965, 157, 156, 154, 151, 814, 814, 814, - 814, 814, 814, 815, 815, 815, 815, 815, 815, 815, - - 815, 150, 149, 146, 815, 144, 815, 137, 965, 136, - 815, 815, 815, 815, 815, 815, 848, 848, 848, 848, - 848, 848, 848, 855, 855, 855, 855, 855, 855, 969, - 135, 134, 815, 820, 820, 820, 820, 820, 820, 820, - 820, 133, 969, 132, 820, 130, 129, 128, 126, 124, - 820, 820, 820, 820, 820, 820, 822, 822, 822, 822, - 822, 822, 822, 822, 122, 121, 120, 822, 969, 822, - 119, 117, 116, 822, 822, 822, 822, 822, 822, 858, - 858, 858, 858, 858, 858, 858, 860, 860, 860, 860, - 860, 860, 860, 115, 114, 822, 832, 832, 832, 832, - - 832, 832, 832, 832, 113, 112, 110, 832, 108, 107, - 106, 105, 104, 832, 832, 832, 832, 832, 832, 834, - 834, 834, 834, 834, 834, 834, 834, 103, 102, 101, - 834, 100, 834, 98, 97, 90, 834, 834, 834, 834, - 834, 834, 862, 862, 862, 862, 862, 862, 862, 864, - 864, 864, 864, 864, 864, 864, 89, 88, 834, 847, - 847, 847, 847, 847, 847, 847, 847, 86, 85, 84, - 847, 83, 82, 81, 79, 77, 847, 847, 847, 847, - 847, 847, 849, 849, 849, 849, 849, 849, 849, 849, - 76, 74, 73, 849, 72, 849, 71, 70, 68, 849, - - 849, 849, 849, 849, 849, 870, 870, 870, 870, 870, - 870, 872, 872, 872, 872, 872, 872, 67, 1011, 66, - 51, 849, 863, 863, 863, 863, 863, 863, 863, 863, - 43, 1011, 42, 863, 40, 30, 18, 10, 8, 863, - 863, 863, 863, 863, 863, 865, 865, 865, 865, 865, - 865, 865, 865, 3, 0, 0, 865, 1011, 865, 0, - 0, 0, 865, 865, 865, 865, 865, 865, 876, 876, - 876, 876, 876, 876, 879, 879, 879, 879, 879, 879, - 879, 1017, 1021, 0, 865, 877, 877, 877, 877, 877, - 877, 877, 877, 0, 1017, 1021, 877, 0, 0, 885, - - 0, 0, 877, 877, 877, 877, 877, 877, 878, 878, - 878, 878, 878, 878, 882, 883, 885, 888, 878, 0, - 1017, 1021, 0, 0, 878, 878, 878, 878, 878, 878, - 885, 882, 883, 0, 888, 897, 897, 897, 897, 897, - 897, 897, 882, 883, 1030, 1034, 0, 986, 888, 894, - 894, 894, 894, 894, 894, 0, 0, 1030, 1034, 894, - 0, 0, 0, 0, 986, 894, 894, 894, 894, 894, - 894, 895, 895, 895, 895, 895, 895, 895, 895, 986, - 0, 0, 895, 1030, 1034, 0, 0, 1044, 895, 895, - 895, 895, 895, 895, 896, 896, 896, 896, 896, 896, - - 1044, 0, 0, 0, 896, 0, 0, 0, 0, 0, - 896, 896, 896, 896, 896, 896, 898, 898, 898, 898, - 898, 898, 898, 898, 0, 0, 1044, 898, 0, 0, - 0, 0, 0, 898, 898, 898, 898, 898, 898, 899, - 899, 899, 899, 899, 899, 0, 0, 0, 0, 899, - 0, 0, 0, 0, 0, 899, 899, 899, 899, 899, - 899, 900, 900, 900, 900, 900, 900, 900, 901, 901, - 901, 901, 901, 901, 901, 901, 0, 0, 0, 901, - 0, 0, 0, 0, 0, 901, 901, 901, 901, 901, - 901, 902, 902, 902, 902, 902, 902, 0, 0, 0, - - 0, 902, 0, 0, 0, 0, 0, 902, 902, 902, - 902, 902, 902, 903, 903, 903, 903, 903, 903, 903, - 904, 904, 904, 904, 904, 904, 904, 904, 0, 0, - 0, 904, 0, 0, 0, 0, 0, 904, 904, 904, - 904, 904, 904, 905, 905, 905, 905, 905, 905, 0, - 0, 0, 0, 905, 0, 0, 0, 0, 0, 905, - 905, 905, 905, 905, 905, 906, 906, 906, 906, 906, - 906, 906, 908, 908, 908, 908, 908, 908, 908, 908, - 0, 0, 0, 908, 0, 908, 0, 0, 0, 908, - 908, 908, 908, 908, 908, 912, 912, 912, 912, 912, - - 912, 915, 915, 915, 915, 915, 915, 915, 0, 0, - 0, 908, 913, 913, 913, 913, 913, 913, 913, 913, - 0, 0, 0, 913, 0, 0, 0, 0, 0, 913, - 913, 913, 913, 913, 913, 917, 917, 917, 917, 917, - 917, 921, 921, 921, 921, 921, 921, 922, 922, 922, - 922, 922, 922, 922, 922, 0, 0, 0, 922, 0, - 0, 0, 0, 0, 922, 922, 922, 922, 922, 922, - 924, 924, 924, 924, 924, 924, 924, 926, 926, 926, - 926, 926, 926, 928, 928, 928, 928, 928, 928, 932, - 932, 932, 932, 932, 932, 933, 933, 933, 933, 933, - - 933, 933, 933, 0, 0, 0, 933, 0, 0, 0, - 0, 0, 933, 933, 933, 933, 933, 933, 935, 935, - 935, 935, 935, 935, 935, 938, 938, 938, 938, 938, - 938, 940, 940, 940, 940, 940, 940, 944, 944, 944, - 944, 944, 944, 945, 945, 945, 945, 945, 945, 945, - 945, 0, 0, 0, 945, 0, 0, 0, 0, 0, - 945, 945, 945, 945, 945, 945, 947, 947, 947, 947, - 947, 947, 947, 950, 950, 950, 950, 950, 950, 952, - 952, 952, 952, 952, 952, 956, 956, 956, 956, 956, - 956, 957, 957, 957, 957, 957, 957, 957, 957, 0, - - 0, 0, 957, 0, 0, 0, 0, 0, 957, 957, - 957, 957, 957, 957, 959, 959, 959, 959, 959, 959, - 959, 963, 963, 963, 963, 963, 963, 966, 966, 966, - 966, 966, 966, 966, 968, 968, 968, 968, 968, 968, - 968, 970, 970, 970, 970, 970, 970, 970, 971, 971, - 971, 971, 971, 971, 971, 971, 0, 0, 0, 971, - 0, 0, 0, 0, 0, 971, 971, 971, 971, 971, - 971, 972, 972, 972, 972, 972, 972, 972, 973, 973, - 973, 973, 973, 973, 973, 973, 983, 0, 1048, 973, - 0, 973, 0, 0, 0, 973, 973, 973, 973, 973, - - 973, 1048, 0, 983, 1005, 1005, 1005, 1005, 1005, 1005, - 0, 0, 0, 1058, 983, 0, 1062, 973, 988, 988, - 988, 988, 988, 988, 988, 0, 1058, 1048, 988, 1062, - 0, 0, 0, 0, 988, 988, 988, 988, 988, 988, - 989, 989, 989, 989, 989, 989, 989, 989, 0, 0, - 0, 989, 1058, 989, 0, 1062, 0, 989, 989, 989, - 989, 989, 989, 1008, 1008, 1008, 1008, 1008, 1008, 1008, - 1012, 1012, 1012, 1012, 1012, 1012, 1012, 0, 0, 989, - 992, 992, 992, 992, 992, 992, 992, 992, 0, 0, - 0, 992, 0, 992, 0, 0, 0, 992, 992, 992, - - 992, 992, 992, 1014, 1014, 1014, 1014, 1014, 1014, 1014, - 1018, 1018, 1018, 1018, 1018, 1018, 1018, 0, 0, 992, - 995, 995, 995, 995, 995, 995, 995, 995, 0, 0, - 0, 995, 0, 995, 0, 0, 0, 995, 995, 995, - 995, 995, 995, 1020, 1020, 1020, 1020, 1020, 1020, 1020, - 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1107, 0, 995, - 998, 998, 998, 998, 998, 998, 998, 998, 0, 0, - 1107, 998, 0, 998, 0, 0, 0, 998, 998, 998, - 998, 998, 998, 1024, 1024, 1024, 1024, 1024, 1024, 1024, - 1028, 1028, 1028, 1028, 1028, 1028, 1107, 0, 0, 998, - - 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 0, 0, - 0, 1001, 0, 1001, 0, 0, 0, 1001, 1001, 1001, - 1001, 1001, 1001, 1031, 1031, 1031, 1031, 1031, 1031, 1031, - 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1155, 0, 1001, - 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 0, 0, - 1155, 1006, 0, 0, 0, 0, 0, 1006, 1006, 1006, - 1006, 1006, 1006, 1013, 1013, 1013, 1013, 1013, 1013, 1013, - 1013, 0, 0, 0, 1013, 0, 1155, 0, 0, 0, - 1013, 1013, 1013, 1013, 1013, 1013, 1023, 1023, 1023, 1023, - 1023, 1023, 1023, 1023, 0, 0, 0, 1023, 0, 0, - - 0, 0, 0, 1023, 1023, 1023, 1023, 1023, 1023, 1035, - 1035, 1035, 1035, 1035, 1035, 1035, 1036, 1036, 1036, 1036, - 1036, 1036, 1036, 1036, 0, 0, 0, 1036, 0, 0, - 0, 0, 0, 1036, 1036, 1036, 1036, 1036, 1036, 1037, - 1037, 1037, 1037, 1037, 1037, 1037, 1042, 1042, 1042, 1042, - 1042, 1042, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1047, - 1047, 1047, 1047, 1047, 1047, 1047, 1049, 1049, 1049, 1049, - 1049, 1049, 1049, 1050, 1050, 1050, 1050, 1050, 1050, 1050, - 1050, 0, 0, 0, 1050, 0, 0, 0, 0, 0, - 1050, 1050, 1050, 1050, 1050, 1050, 1051, 1051, 1051, 1051, - - 1051, 1051, 1051, 1056, 1056, 1056, 1056, 1056, 1056, 1059, - 1059, 1059, 1059, 1059, 1059, 1059, 1061, 1061, 1061, 1061, - 1061, 1061, 1061, 1063, 1063, 1063, 1063, 1063, 1063, 1063, - 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 0, 0, - 0, 1064, 0, 0, 0, 0, 0, 1064, 1064, 1064, - 1064, 1064, 1064, 1065, 1065, 1065, 1065, 1065, 1065, 1065, - 1069, 1069, 1069, 1069, 1069, 1069, 1071, 1071, 1071, 1071, - 1071, 1071, 1075, 1075, 1075, 1075, 1075, 1075, 1076, 1076, - 1076, 1076, 1076, 1076, 1076, 1076, 0, 0, 0, 1076, - 0, 1086, 1087, 0, 0, 1076, 1076, 1076, 1076, 1076, - - 1076, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1086, 1087, - 1094, 1094, 1094, 1094, 1094, 1094, 1094, 0, 0, 0, - 1087, 1086, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, - 0, 0, 0, 1088, 0, 1088, 0, 0, 0, 1088, - 1088, 1088, 1088, 1088, 1088, 1097, 1097, 1097, 1097, 1097, - 1097, 1097, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1159, - 0, 1088, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, - 0, 0, 1159, 1092, 0, 0, 0, 0, 0, 1092, - 1092, 1092, 1092, 1092, 1092, 1095, 1095, 1095, 1095, 1095, - 1095, 1095, 1095, 0, 0, 0, 1095, 0, 1159, 0, - - 0, 0, 1095, 1095, 1095, 1095, 1095, 1095, 1098, 1098, - 1098, 1098, 1098, 1098, 1098, 1098, 0, 0, 0, 1098, - 0, 0, 0, 0, 0, 1098, 1098, 1098, 1098, 1098, - 1098, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 0, - 0, 0, 1101, 0, 0, 0, 0, 0, 1101, 1101, - 1101, 1101, 1101, 1101, 1103, 1103, 1103, 1103, 1103, 1103, - 1103, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 0, - 0, 0, 1104, 0, 0, 0, 0, 0, 1104, 1104, - 1104, 1104, 1104, 1104, 1106, 1106, 1106, 1106, 1106, 1106, - 1106, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1109, 1109, - - 1109, 1109, 1109, 1109, 1109, 1109, 0, 0, 0, 1109, - 0, 0, 0, 0, 0, 1109, 1109, 1109, 1109, 1109, - 1109, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1115, 1115, - 1115, 1115, 1115, 1115, 1120, 1120, 1120, 1120, 1120, 1120, - 1122, 1122, 1122, 1122, 1122, 1122, 1128, 1128, 1128, 1128, - 1128, 1128, 1130, 1130, 1130, 1130, 1130, 1130, 1136, 1136, - 1136, 1136, 1136, 1136, 1138, 1138, 1138, 1138, 1138, 1138, - 1144, 1144, 1144, 1144, 1144, 1144, 1146, 1146, 1146, 1146, - 1146, 1146, 1153, 1153, 1153, 1153, 1153, 1153, 1156, 1156, - 1156, 1156, 1156, 1156, 1156, 1158, 1158, 1158, 1158, 1158, - - 1158, 1158, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1161, - 1161, 1161, 1161, 1161, 1161, 1161, 1161, 0, 0, 0, - 1161, 0, 0, 0, 0, 0, 1161, 1161, 1161, 1161, - 1161, 1161, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1169, - 1169, 1169, 1169, 1169, 1169, 1169, 1169, 0, 0, 0, - 1169, 0, 0, 0, 0, 0, 1169, 1169, 1169, 1169, - 1169, 1169, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1178, - 1178, 1178, 1178, 1178, 1178, 1184, 1185, 1185, 1185, 1185, - 1185, 1185, 1185, 0, 0, 0, 0, 0, 1184, 1187, - 1187, 1187, 1187, 1187, 1187, 1187, 1190, 1190, 1190, 1190, - - 1190, 1190, 1192, 1193, 1193, 1193, 1193, 1193, 1193, 1193, - 0, 0, 0, 0, 1184, 1192, 1195, 1195, 1195, 1195, - 1195, 1195, 1195, 1199, 1199, 1199, 1199, 1199, 1199, 1201, - 1202, 1202, 1202, 1202, 1202, 1202, 1202, 0, 0, 0, - 0, 1192, 1201, 1204, 1204, 1204, 1204, 1204, 1204, 1204, - 1208, 1208, 1208, 1208, 1208, 1208, 1210, 1211, 1211, 1211, - 1211, 1211, 1211, 1211, 0, 0, 0, 0, 1201, 1210, - 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1217, 1217, 1217, - 1217, 1217, 1217, 1219, 1220, 1220, 1220, 1220, 1220, 1220, - 1220, 0, 0, 0, 0, 1210, 1219, 1222, 1222, 1222, - - 1222, 1222, 1222, 1222, 1225, 1225, 1225, 1225, 1225, 1225, - 1227, 1227, 1227, 1227, 1227, 1227, 1244, 0, 0, 0, - 0, 0, 1219, 1250, 1250, 1250, 1250, 1250, 1250, 1244, - 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1247, 1247, 1247, - 1247, 1247, 1247, 1247, 1254, 1254, 1254, 1254, 1254, 1254, - 0, 0, 0, 0, 0, 1244, 1258, 1258, 1258, 1258, - 1258, 1258, 1262, 1262, 1262, 1262, 1262, 1262, 1266, 1266, - 1266, 1266, 1266, 1266, 1271, 1271, 1271, 1271, 1271, 1271, - 1273, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 0, 0, - 0, 0, 0, 1273, 1276, 1276, 1276, 1276, 1276, 1276, - - 1276, 1282, 1282, 1282, 1282, 1282, 1282, 1285, 1285, 1285, - 1285, 1285, 1285, 1289, 1289, 1289, 1289, 1289, 1289, 1273, - 1293, 1293, 1293, 1293, 1293, 1293, 1297, 1297, 1297, 1297, - 1297, 1297, 1301, 1301, 1301, 1301, 1301, 1301, 1304, 1304, - 1304, 1304, 1304, 1304, 1309, 1309, 1309, 1309, 1309, 1309, - 1318, 1318, 1318, 1318, 1318, 1318, 1330, 0, 0, 0, - 0, 1330, 1330, 1330, 1331, 0, 1331, 1331, 1331, 1331, - 1331, 1331, 1331, 1332, 0, 1332, 1333, 1333, 1333, 1334, - 1334, 1334, 1335, 1335, 1335, 1336, 1336, 1336, 1337, 1337, - 1337, 1338, 1338, 1338, 1339, 1339, 1339, 1340, 1340, 1340, - - 1341, 0, 1341, 1342, 1342, 1342, 1343, 1343, 1343, 1344, - 1344, 1344, 1345, 0, 1345, 1346, 1346, 1346, 1347, 1347, - 0, 0, 1347, 1348, 1348, 1348, 1349, 1349, 1349, 1350, - 1350, 1350, 1351, 1351, 1351, 1352, 1352, 1352, 1353, 1353, - 1353, 1354, 1354, 0, 0, 1354, 1355, 1355, 1355, 1356, - 0, 1356, 1357, 1357, 1357, 1358, 0, 1358, 1359, 1359, - 1359, 1360, 1360, 1360, 1361, 1361, 1361, 1362, 0, 1362, - 1363, 0, 1363, 1364, 1364, 1364, 1365, 0, 1365, 1366, - 1366, 0, 0, 1366, 1367, 1367, 0, 0, 1367, 1368, - 1368, 1368, 1369, 1369, 1369, 1370, 1370, 1370, 1371, 1371, - - 1371, 1372, 1372, 1372, 1373, 1373, 1373, 1374, 1374, 1374, - 1375, 1375, 1375, 1376, 1376, 0, 0, 1376, 1377, 1377, - 1377, 1378, 1378, 0, 0, 1378, 1379, 1379, 0, 0, - 1379, 1380, 1380, 1380, 1381, 0, 1381, 1382, 0, 1382, - 1383, 1383, 1383, 1384, 0, 1384, 1385, 1385, 1385, 1386, - 1386, 1386, 1387, 1387, 1387, 1388, 0, 1388, 1389, 0, - 1389, 1390, 1390, 1390, 1391, 0, 1391, 1392, 0, 1392, - 1393, 0, 1393, 1394, 1394, 1394, 1395, 0, 1395, 1396, - 0, 0, 1396, 1397, 1397, 0, 0, 1397, 1398, 1398, - 0, 1398, 1399, 1399, 0, 0, 1399, 1400, 1400, 1400, - - 1401, 1401, 0, 1401, 1402, 1402, 1402, 0, 1402, 1402, - 1403, 1403, 1403, 1404, 1404, 1404, 1405, 1405, 1405, 1406, - 1406, 1406, 1407, 1407, 1407, 1408, 1408, 1408, 1409, 1409, - 1409, 1410, 1410, 1410, 1411, 1411, 0, 0, 1411, 1412, - 1412, 1412, 1413, 1413, 0, 1413, 1414, 1414, 0, 0, - 1414, 1415, 1415, 0, 1415, 1416, 1416, 0, 0, 1416, - 1417, 1417, 1417, 1418, 1418, 0, 1418, 1419, 0, 0, - 1419, 1420, 1420, 0, 1420, 1421, 1421, 0, 0, 1421, - 1422, 1422, 0, 1422, 1423, 1423, 0, 0, 1423, 1424, - 1424, 1424, 1425, 1425, 0, 1425, 1426, 0, 1426, 1427, - - 0, 1427, 1428, 0, 1428, 1429, 1429, 1429, 1430, 0, - 1430, 1431, 1431, 1431, 0, 1431, 1431, 1432, 1432, 1432, - 1433, 1433, 1433, 1434, 1434, 1434, 1435, 0, 1435, 1436, - 0, 1436, 1437, 1437, 1437, 1438, 0, 1438, 1439, 0, - 1439, 1440, 0, 1440, 1441, 1441, 1441, 1442, 0, 1442, - 1443, 0, 1443, 1444, 0, 1444, 1445, 0, 1445, 1446, - 1446, 1446, 1447, 0, 1447, 1448, 0, 1448, 1449, 0, - 0, 1449, 1450, 1450, 0, 1450, 1451, 1451, 0, 0, - 1451, 1452, 1452, 0, 1452, 1453, 1453, 0, 0, 1453, - 1454, 1454, 1454, 1455, 1455, 0, 1455, 1456, 1456, 1456, - - 0, 1456, 1456, 1457, 1457, 1457, 1458, 1458, 1458, 1459, - 1459, 1459, 1460, 1460, 1460, 1461, 1461, 1461, 1462, 1462, - 1462, 1463, 1463, 1463, 1464, 1464, 1464, 1465, 1465, 0, - 0, 1465, 1466, 1466, 1466, 1467, 1467, 0, 1467, 1468, - 1468, 0, 0, 1468, 1469, 1469, 0, 1469, 1470, 1470, - 0, 0, 1470, 1471, 1471, 1471, 1472, 1472, 0, 1472, - 1473, 0, 0, 1473, 1474, 1474, 0, 1474, 1475, 1475, - 0, 0, 1475, 1476, 1476, 0, 1476, 1477, 1477, 0, - 0, 1477, 1478, 1478, 1478, 1479, 1479, 0, 1479, 1480, - 0, 1480, 1481, 0, 0, 1481, 1482, 1482, 0, 1482, - - 1483, 1483, 0, 0, 1483, 1484, 1484, 0, 1484, 1485, - 1485, 0, 0, 1485, 1486, 1486, 1486, 1487, 1487, 0, - 1487, 1488, 0, 1488, 1489, 0, 1489, 1490, 0, 1490, - 1491, 1491, 1491, 1492, 0, 1492, 1493, 1493, 1493, 0, - 1493, 1493, 1494, 1494, 1494, 1495, 1495, 1495, 1496, 1496, - 1496, 1497, 1497, 1497, 1498, 1498, 1498, 1499, 0, 1499, - 1500, 0, 1500, 1501, 1501, 1501, 1502, 1502, 1502, 1503, - 0, 1503, 1504, 0, 1504, 1505, 0, 1505, 1506, 1506, - 1506, 1507, 1507, 1507, 1508, 0, 1508, 1509, 0, 1509, - 1510, 0, 1510, 1511, 0, 1511, 1512, 1512, 1512, 1513, - - 1513, 1513, 1514, 0, 1514, 1515, 0, 1515, 1516, 0, - 1516, 1517, 0, 1517, 1518, 1518, 1518, 1519, 1519, 1519, - 1520, 0, 1520, 1521, 0, 1521, 1522, 0, 0, 1522, - 1523, 1523, 0, 1523, 1524, 1524, 0, 0, 1524, 1525, - 1525, 0, 1525, 1526, 1526, 0, 0, 1526, 1527, 1527, - 1527, 1528, 1528, 0, 1528, 1529, 1529, 1529, 0, 1529, - 1529, 1530, 1530, 1530, 1531, 1531, 1531, 1532, 1532, 1532, - 1533, 1533, 1533, 1534, 1534, 1534, 1535, 1535, 1535, 1536, - 1536, 1536, 1537, 0, 1537, 1538, 1538, 1538, 1539, 1539, - 0, 0, 1539, 1540, 1540, 1540, 1541, 1541, 0, 1541, - - 1542, 1542, 0, 0, 1542, 1543, 1543, 0, 1543, 1544, - 1544, 0, 0, 1544, 1545, 1545, 1545, 1546, 1546, 0, - 1546, 1547, 0, 0, 1547, 1548, 1548, 0, 1548, 1549, - 1549, 0, 0, 1549, 1550, 1550, 0, 1550, 1551, 1551, - 0, 0, 1551, 1552, 1552, 1552, 1553, 1553, 0, 1553, - 1554, 0, 1554, 1555, 0, 0, 1555, 1556, 1556, 0, - 1556, 1557, 1557, 0, 0, 1557, 1558, 1558, 0, 1558, - 1559, 1559, 0, 0, 1559, 1560, 1560, 1560, 1561, 1561, - 0, 1561, 1562, 0, 1562, 1563, 0, 0, 1563, 1564, - 1564, 0, 1564, 1565, 1565, 0, 0, 1565, 1566, 1566, - - 0, 1566, 1567, 1567, 0, 0, 1567, 1568, 1568, 1568, - 1569, 1569, 0, 1569, 1570, 0, 1570, 1571, 0, 1571, - 1572, 0, 1572, 1573, 1573, 1573, 1574, 0, 1574, 1575, - 0, 1575, 1576, 1576, 1576, 0, 1576, 1576, 1577, 0, - 1577, 1578, 1578, 1578, 1579, 0, 1579, 1580, 0, 1580, - 1581, 0, 1581, 1582, 0, 1582, 1583, 0, 1583, 1584, - 1584, 0, 0, 1584, 1585, 1585, 1585, 1586, 1586, 1586, - 1587, 1587, 0, 1587, 1588, 1588, 1588, 1589, 0, 1589, - 1590, 1590, 1590, 1591, 1591, 1591, 1592, 0, 1592, 1593, - 0, 1593, 1594, 1594, 1594, 1595, 1595, 1595, 1596, 0, - - 1596, 1597, 0, 1597, 1598, 0, 1598, 1599, 1599, 1599, - 1600, 1600, 1600, 1601, 0, 1601, 1602, 0, 1602, 1603, - 0, 1603, 1604, 1604, 1604, 1605, 1605, 1605, 1606, 0, - 1606, 1607, 0, 1607, 1608, 0, 1608, 1609, 1609, 1609, - 1610, 1610, 1610, 1611, 0, 1611, 1612, 0, 0, 1612, - 1613, 1613, 0, 1613, 1614, 1614, 0, 0, 1614, 1615, - 1615, 0, 1615, 1616, 1616, 0, 0, 1616, 1617, 0, - 1617, 1618, 1618, 0, 1618, 1619, 1619, 1619, 0, 1619, - 1619, 1620, 1620, 1620, 1621, 0, 1621, 1622, 0, 1622, - 1623, 0, 1623, 1624, 0, 1624, 1625, 0, 1625, 1626, - - 0, 1626, 1627, 0, 1627, 1628, 1628, 1628, 1629, 1629, - 1629, 1630, 0, 1630, 1631, 1631, 0, 0, 1631, 1632, - 1632, 0, 1632, 1633, 0, 1633, 1634, 0, 0, 1634, - 1635, 1635, 0, 1635, 1636, 1636, 0, 0, 1636, 1637, - 1637, 0, 1637, 1638, 0, 1638, 1639, 0, 1639, 1640, - 0, 0, 1640, 1641, 1641, 0, 1641, 1642, 1642, 0, - 0, 1642, 1643, 1643, 0, 1643, 1644, 0, 1644, 1645, - 0, 1645, 1646, 0, 0, 1646, 1647, 1647, 0, 1647, - 1648, 1648, 0, 0, 1648, 1649, 1649, 0, 1649, 1650, - 0, 1650, 1651, 0, 1651, 1652, 0, 0, 1652, 1653, - - 1653, 0, 1653, 1654, 1654, 0, 0, 1654, 1655, 1655, - 0, 1655, 1656, 0, 1656, 1657, 0, 1657, 1658, 0, - 1658, 1659, 0, 1659, 1660, 1660, 1660, 1661, 0, 1661, - 1662, 1662, 1662, 0, 1662, 1662, 1663, 0, 1663, 1664, - 0, 1664, 1665, 0, 1665, 1666, 0, 1666, 1667, 0, - 1667, 1668, 0, 1668, 1669, 0, 1669, 1670, 1670, 0, - 0, 1670, 1671, 1671, 0, 1671, 1672, 0, 1672, 1673, - 0, 1673, 1674, 0, 1674, 1675, 0, 1675, 1676, 0, - 1676, 1677, 0, 1677, 1678, 0, 1678, 1679, 0, 1679, - 1680, 0, 1680, 1681, 0, 1681, 1682, 0, 0, 1682, - - 1683, 1683, 0, 0, 1683, 1684, 0, 1684, 1685, 0, - 1685, 1686, 0, 1686, 1687, 0, 0, 1687, 1688, 0, - 0, 1688, 1689, 0, 0, 1689, 1690, 0, 0, 1690, - 1691, 0, 0, 1691, 1692, 0, 1692, 1693, 0, 1693, - 1694, 0, 0, 1694, 1695, 0, 1695, 1696, 0, 1696, - 1697, 0, 1697, 1698, 0, 1698, 1699, 0, 1699, 1700, - 0, 0, 1700, 1701, 0, 1701, 1702, 0, 1702, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, - 1329, 1329 - } ; - -static yy_state_type yy_last_accepting_state; -static char *yy_last_accepting_cpos; - -extern int pcap__flex_debug; -int pcap__flex_debug = 0; - -/* The intent behind this definition is that it'll catch - * any uses of REJECT which flex missed. - */ -#define REJECT reject_used_but_not_detected -#define yymore() yymore_used_but_not_detected -#define YY_MORE_ADJ 0 -#define YY_RESTORE_YY_MORE_OFFSET -char *pcap_text; -#line 1 "scanner.l" -#line 2 "scanner.l" -/* - * 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. - */ - -#ifndef lint -static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/scanner.l,v 1.99.2.9 2007/06/11 09:52:05 guy Exp $ (LBL)"; -#endif - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#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_UNPUT -static YY_BUFFER_STATE in_buffer; -#else -static char *in_buffer; - -#undef getc -#define getc(fp) (*in_buffer == 0 ? EOF : *in_buffer++) -#endif - -#define yylval pcap_lval -extern YYSTYPE yylval; - -#line 2510 "" - -#define INITIAL 0 - -#ifndef YY_NO_UNISTD_H -/* Special case for "unistd.h", since it is non-ANSI. We include it way - * down here because we want the user's section 1 to have been scanned first. - * The user has a chance to override it with an option. - */ -#include -#endif - -#ifndef YY_EXTRA_TYPE -#define YY_EXTRA_TYPE void * -#endif - -static int yy_init_globals (void ); - -/* Macros after this point can all be overridden by user definitions in - * section 1. - */ - -#ifndef YY_SKIP_YYWRAP -#ifdef __cplusplus -extern "C" int pcap_wrap (void ); -#else -extern int pcap_wrap (void ); -#endif -#endif - - static void yyunput (int c,char *buf_ptr ); - -#ifndef yytext_ptr -static void yy_flex_strncpy (char *,yyconst char *,int ); -#endif - -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen (yyconst char * ); -#endif - -#ifndef YY_NO_INPUT - -#ifdef __cplusplus -static int yyinput (void ); -#else -static int input (void ); -#endif - -#endif - -/* Amount of stuff to slurp up with each read. */ -#ifndef YY_READ_BUF_SIZE -#define YY_READ_BUF_SIZE 8192 -#endif - -/* Copy whatever the last rule matched to the standard output. */ -#ifndef ECHO -/* This used to be an fputs(), but since the string might contain NUL's, - * we now use fwrite(). - */ -#define ECHO (void) fwrite( pcap_text, pcap_leng, 1, pcap_out ) -#endif - -/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, - * is returned in "result". - */ -#ifndef YY_INPUT -#define YY_INPUT(buf,result,max_size) \ - if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ - { \ - int c = '*'; \ - size_t n; \ - for ( n = 0; n < max_size && \ - (c = getc( pcap_in )) != EOF && c != '\n'; ++n ) \ - buf[n] = (char) c; \ - if ( c == '\n' ) \ - buf[n++] = (char) c; \ - if ( c == EOF && ferror( pcap_in ) ) \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - result = n; \ - } \ - else \ - { \ - errno=0; \ - while ( (result = fread(buf, 1, max_size, pcap_in))==0 && ferror(pcap_in)) \ - { \ - if( errno != EINTR) \ - { \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - break; \ - } \ - errno=0; \ - clearerr(pcap_in); \ - } \ - }\ -\ - -#endif - -/* No semi-colon after return; correct usage is to write "yyterminate();" - - * we don't want an extra ';' after the "return" because that will cause - * some compilers to complain about unreachable statements. - */ -#ifndef yyterminate -#define yyterminate() return YY_NULL -#endif - -/* Number of entries by which start-condition stack grows. */ -#ifndef YY_START_STACK_INCR -#define YY_START_STACK_INCR 25 -#endif - -/* Report a fatal error. */ -#ifndef YY_FATAL_ERROR -#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) -#endif - -/* end tables serialization structures and prototypes */ - -/* Default declaration of generated scanner - a define so the user can - * easily add parameters. - */ -#ifndef YY_DECL -#define YY_DECL_IS_OURS 1 - -extern int pcap_lex (void); - -#define YY_DECL int pcap_lex (void) -#endif /* !YY_DECL */ - -/* Code executed at the beginning of each rule, after pcap_text and pcap_leng - * have been set up. - */ -#ifndef YY_USER_ACTION -#define YY_USER_ACTION -#endif - -/* Code executed at the end of each rule. */ -#ifndef YY_BREAK -#define YY_BREAK break; -#endif - -#define YY_RULE_SETUP \ - YY_USER_ACTION - -/** The main scanner function which does all the work. - */ -YY_DECL -{ - register yy_state_type yy_current_state; - register char *yy_cp, *yy_bp; - register int yy_act; - -#line 169 "scanner.l" - -#line 2665 "" - - if ( !(yy_init) ) - { - (yy_init) = 1; - -#ifdef YY_USER_INIT - YY_USER_INIT; -#endif - - if ( ! (yy_start) ) - (yy_start) = 1; /* first start state */ - - if ( ! pcap_in ) - pcap_in = stdin; - - if ( ! pcap_out ) - pcap_out = stdout; - - if ( ! YY_CURRENT_BUFFER ) { - pcap_ensure_buffer_stack (); - YY_CURRENT_BUFFER_LVALUE = - pcap__create_buffer(pcap_in,YY_BUF_SIZE ); - } - - pcap__load_buffer_state( ); - } - - while ( 1 ) /* loops until end-of-file is reached */ - { - yy_cp = (yy_c_buf_p); - - /* Support of pcap_text. */ - *yy_cp = (yy_hold_char); - - /* yy_bp points to the position in yy_ch_buf of the start of - * the current run. - */ - yy_bp = yy_cp; - - yy_current_state = (yy_start); -yy_match: - do - { - register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; - if ( yy_accept[yy_current_state] ) - { - (yy_last_accepting_state) = yy_current_state; - (yy_last_accepting_cpos) = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 1330 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - ++yy_cp; - } - while ( yy_base[yy_current_state] != 6570 ); - -yy_find_action: - yy_act = yy_accept[yy_current_state]; - if ( yy_act == 0 ) - { /* have to back up */ - yy_cp = (yy_last_accepting_cpos); - yy_current_state = (yy_last_accepting_state); - yy_act = yy_accept[yy_current_state]; - } - - YY_DO_BEFORE_ACTION; - -do_action: /* This label is used only to access EOF actions. */ - - switch ( yy_act ) - { /* beginning of action switch */ - case 0: /* must back up */ - /* undo the effects of YY_DO_BEFORE_ACTION */ - *yy_cp = (yy_hold_char); - yy_cp = (yy_last_accepting_cpos); - yy_current_state = (yy_last_accepting_state); - goto yy_find_action; - -case 1: -YY_RULE_SETUP -#line 170 "scanner.l" -return DST; - YY_BREAK -case 2: -YY_RULE_SETUP -#line 171 "scanner.l" -return SRC; - YY_BREAK -case 3: -YY_RULE_SETUP -#line 173 "scanner.l" -return LINK; - YY_BREAK -case 4: -YY_RULE_SETUP -#line 174 "scanner.l" -return LINK; - YY_BREAK -case 5: -YY_RULE_SETUP -#line 175 "scanner.l" -return ARP; - YY_BREAK -case 6: -YY_RULE_SETUP -#line 176 "scanner.l" -return RARP; - YY_BREAK -case 7: -YY_RULE_SETUP -#line 177 "scanner.l" -return IP; - YY_BREAK -case 8: -YY_RULE_SETUP -#line 178 "scanner.l" -return SCTP; - YY_BREAK -case 9: -YY_RULE_SETUP -#line 179 "scanner.l" -return TCP; - YY_BREAK -case 10: -YY_RULE_SETUP -#line 180 "scanner.l" -return UDP; - YY_BREAK -case 11: -YY_RULE_SETUP -#line 181 "scanner.l" -return ICMP; - YY_BREAK -case 12: -YY_RULE_SETUP -#line 182 "scanner.l" -return IGMP; - YY_BREAK -case 13: -YY_RULE_SETUP -#line 183 "scanner.l" -return IGRP; - YY_BREAK -case 14: -YY_RULE_SETUP -#line 184 "scanner.l" -return PIM; - YY_BREAK -case 15: -YY_RULE_SETUP -#line 185 "scanner.l" -return VRRP; - YY_BREAK -case 16: -YY_RULE_SETUP -#line 186 "scanner.l" -return RADIO; - YY_BREAK -case 17: -YY_RULE_SETUP -#line 188 "scanner.l" -{ -#ifdef INET6 - return IPV6; -#else - bpf_error("%s not supported", pcap_text); -#endif - } - YY_BREAK -case 18: -YY_RULE_SETUP -#line 195 "scanner.l" -{ -#ifdef INET6 - return ICMPV6; -#else - bpf_error("%s not supported", pcap_text); -#endif - } - YY_BREAK -case 19: -YY_RULE_SETUP -#line 202 "scanner.l" -return AH; - YY_BREAK -case 20: -YY_RULE_SETUP -#line 203 "scanner.l" -return ESP; - YY_BREAK -case 21: -YY_RULE_SETUP -#line 205 "scanner.l" -return ATALK; - YY_BREAK -case 22: -YY_RULE_SETUP -#line 206 "scanner.l" -return AARP; - YY_BREAK -case 23: -YY_RULE_SETUP -#line 207 "scanner.l" -return DECNET; - YY_BREAK -case 24: -YY_RULE_SETUP -#line 208 "scanner.l" -return LAT; - YY_BREAK -case 25: -YY_RULE_SETUP -#line 209 "scanner.l" -return SCA; - YY_BREAK -case 26: -YY_RULE_SETUP -#line 210 "scanner.l" -return MOPRC; - YY_BREAK -case 27: -YY_RULE_SETUP -#line 211 "scanner.l" -return MOPDL; - YY_BREAK -case 28: -YY_RULE_SETUP -#line 213 "scanner.l" -return ISO; - YY_BREAK -case 29: -YY_RULE_SETUP -#line 214 "scanner.l" -return ESIS; - YY_BREAK -case 30: -YY_RULE_SETUP -#line 215 "scanner.l" -return ESIS; - YY_BREAK -case 31: -YY_RULE_SETUP -#line 216 "scanner.l" -return ISIS; - YY_BREAK -case 32: -YY_RULE_SETUP -#line 217 "scanner.l" -return ISIS; - YY_BREAK -case 33: -YY_RULE_SETUP -#line 218 "scanner.l" -return L1; - YY_BREAK -case 34: -YY_RULE_SETUP -#line 219 "scanner.l" -return L2; - YY_BREAK -case 35: -YY_RULE_SETUP -#line 220 "scanner.l" -return IIH; - YY_BREAK -case 36: -YY_RULE_SETUP -#line 221 "scanner.l" -return LSP; - YY_BREAK -case 37: -YY_RULE_SETUP -#line 222 "scanner.l" -return SNP; - YY_BREAK -case 38: -YY_RULE_SETUP -#line 223 "scanner.l" -return CSNP; - YY_BREAK -case 39: -YY_RULE_SETUP -#line 224 "scanner.l" -return PSNP; - YY_BREAK -case 40: -YY_RULE_SETUP -#line 226 "scanner.l" -return CLNP; - YY_BREAK -case 41: -YY_RULE_SETUP -#line 228 "scanner.l" -return STP; - YY_BREAK -case 42: -YY_RULE_SETUP -#line 230 "scanner.l" -return IPX; - YY_BREAK -case 43: -YY_RULE_SETUP -#line 232 "scanner.l" -return NETBEUI; - YY_BREAK -case 44: -YY_RULE_SETUP -#line 234 "scanner.l" -return HOST; - YY_BREAK -case 45: -YY_RULE_SETUP -#line 235 "scanner.l" -return NET; - YY_BREAK -case 46: -YY_RULE_SETUP -#line 236 "scanner.l" -return NETMASK; - YY_BREAK -case 47: -YY_RULE_SETUP -#line 237 "scanner.l" -return PORT; - YY_BREAK -case 48: -YY_RULE_SETUP -#line 238 "scanner.l" -return PORTRANGE; - YY_BREAK -case 49: -YY_RULE_SETUP -#line 239 "scanner.l" -return PROTO; - YY_BREAK -case 50: -YY_RULE_SETUP -#line 240 "scanner.l" -{ -#ifdef NO_PROTOCHAIN - bpf_error("%s not supported", pcap_text); -#else - return PROTOCHAIN; -#endif - } - YY_BREAK -case 51: -YY_RULE_SETUP -#line 248 "scanner.l" -return GATEWAY; - YY_BREAK -case 52: -YY_RULE_SETUP -#line 250 "scanner.l" -return LESS; - YY_BREAK -case 53: -YY_RULE_SETUP -#line 251 "scanner.l" -return GREATER; - YY_BREAK -case 54: -YY_RULE_SETUP -#line 252 "scanner.l" -return CBYTE; - YY_BREAK -case 55: -YY_RULE_SETUP -#line 253 "scanner.l" -return TK_BROADCAST; - YY_BREAK -case 56: -YY_RULE_SETUP -#line 254 "scanner.l" -return TK_MULTICAST; - YY_BREAK -case 57: -YY_RULE_SETUP -#line 256 "scanner.l" -return AND; - YY_BREAK -case 58: -YY_RULE_SETUP -#line 257 "scanner.l" -return OR; - YY_BREAK -case 59: -YY_RULE_SETUP -#line 258 "scanner.l" -return '!'; - YY_BREAK -case 60: -YY_RULE_SETUP -#line 260 "scanner.l" -return LEN; - YY_BREAK -case 61: -YY_RULE_SETUP -#line 261 "scanner.l" -return INBOUND; - YY_BREAK -case 62: -YY_RULE_SETUP -#line 262 "scanner.l" -return OUTBOUND; - YY_BREAK -case 63: -YY_RULE_SETUP -#line 264 "scanner.l" -return VLAN; - YY_BREAK -case 64: -YY_RULE_SETUP -#line 265 "scanner.l" -return MPLS; - YY_BREAK -case 65: -YY_RULE_SETUP -#line 266 "scanner.l" -return PPPOED; - YY_BREAK -case 66: -YY_RULE_SETUP -#line 267 "scanner.l" -return PPPOES; - YY_BREAK -case 67: -YY_RULE_SETUP -#line 269 "scanner.l" -return LANE; - YY_BREAK -case 68: -YY_RULE_SETUP -#line 270 "scanner.l" -return LLC; - YY_BREAK -case 69: -YY_RULE_SETUP -#line 271 "scanner.l" -return METAC; - YY_BREAK -case 70: -YY_RULE_SETUP -#line 272 "scanner.l" -return BCC; - YY_BREAK -case 71: -YY_RULE_SETUP -#line 273 "scanner.l" -return OAM; - YY_BREAK -case 72: -YY_RULE_SETUP -#line 274 "scanner.l" -return OAMF4; - YY_BREAK -case 73: -YY_RULE_SETUP -#line 275 "scanner.l" -return OAMF4EC; - YY_BREAK -case 74: -YY_RULE_SETUP -#line 276 "scanner.l" -return OAMF4SC; - YY_BREAK -case 75: -YY_RULE_SETUP -#line 277 "scanner.l" -return SC; - YY_BREAK -case 76: -YY_RULE_SETUP -#line 278 "scanner.l" -return ILMIC; - YY_BREAK -case 77: -YY_RULE_SETUP -#line 279 "scanner.l" -return VPI; - YY_BREAK -case 78: -YY_RULE_SETUP -#line 280 "scanner.l" -return VCI; - YY_BREAK -case 79: -YY_RULE_SETUP -#line 281 "scanner.l" -return CONNECTMSG; - YY_BREAK -case 80: -YY_RULE_SETUP -#line 282 "scanner.l" -return METACONNECT; - YY_BREAK -case 81: -YY_RULE_SETUP -#line 284 "scanner.l" -return PF_IFNAME; - YY_BREAK -case 82: -YY_RULE_SETUP -#line 285 "scanner.l" -return PF_RSET; - YY_BREAK -case 83: -YY_RULE_SETUP -#line 286 "scanner.l" -return PF_RNR; - YY_BREAK -case 84: -YY_RULE_SETUP -#line 287 "scanner.l" -return PF_SRNR; - YY_BREAK -case 85: -YY_RULE_SETUP -#line 288 "scanner.l" -return PF_REASON; - YY_BREAK -case 86: -YY_RULE_SETUP -#line 289 "scanner.l" -return PF_ACTION; - YY_BREAK -case 87: -YY_RULE_SETUP -#line 291 "scanner.l" -return FISU; - YY_BREAK -case 88: -YY_RULE_SETUP -#line 292 "scanner.l" -return LSSU; - YY_BREAK -case 89: -YY_RULE_SETUP -#line 293 "scanner.l" -return LSSU; - YY_BREAK -case 90: -YY_RULE_SETUP -#line 294 "scanner.l" -return MSU; - YY_BREAK -case 91: -YY_RULE_SETUP -#line 295 "scanner.l" -return SIO; - YY_BREAK -case 92: -YY_RULE_SETUP -#line 296 "scanner.l" -return OPC; - YY_BREAK -case 93: -YY_RULE_SETUP -#line 297 "scanner.l" -return DPC; - YY_BREAK -case 94: -YY_RULE_SETUP -#line 298 "scanner.l" -return SLS; - YY_BREAK -case 95: -/* rule 95 can match eol */ -YY_RULE_SETUP -#line 300 "scanner.l" -; - YY_BREAK -case 96: -YY_RULE_SETUP -#line 301 "scanner.l" -return pcap_text[0]; - YY_BREAK -case 97: -YY_RULE_SETUP -#line 302 "scanner.l" -return GEQ; - YY_BREAK -case 98: -YY_RULE_SETUP -#line 303 "scanner.l" -return LEQ; - YY_BREAK -case 99: -YY_RULE_SETUP -#line 304 "scanner.l" -return NEQ; - YY_BREAK -case 100: -YY_RULE_SETUP -#line 305 "scanner.l" -return '='; - YY_BREAK -case 101: -YY_RULE_SETUP -#line 306 "scanner.l" -return LSH; - YY_BREAK -case 102: -YY_RULE_SETUP -#line 307 "scanner.l" -return RSH; - YY_BREAK -case 103: -YY_RULE_SETUP -#line 308 "scanner.l" -{ yylval.e = pcap_ether_aton(((char *)pcap_text)+1); - return AID; } - YY_BREAK -case 104: -YY_RULE_SETUP -#line 310 "scanner.l" -{ yylval.i = stoi((char *)pcap_text); return NUM; } - YY_BREAK -case 105: -YY_RULE_SETUP -#line 311 "scanner.l" -{ - yylval.s = sdup((char *)pcap_text); return HID; } - YY_BREAK -case 106: -YY_RULE_SETUP -#line 313 "scanner.l" -{ yylval.e = pcap_ether_aton((char *)pcap_text); - return EID; } - YY_BREAK -case 107: -YY_RULE_SETUP -#line 315 "scanner.l" -{ -#ifdef INET6 - struct addrinfo hints, *res; - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET6; - hints.ai_flags = AI_NUMERICHOST; - if (getaddrinfo(pcap_text, NULL, &hints, &res)) - bpf_error("bogus IPv6 address %s", pcap_text); - else { - yylval.s = sdup((char *)pcap_text); return HID6; - } -#else - bpf_error("IPv6 address %s not supported", pcap_text); -#endif /*INET6*/ - } - YY_BREAK -case 108: -YY_RULE_SETUP -#line 330 "scanner.l" -{ bpf_error("bogus ethernet address %s", pcap_text); } - YY_BREAK -case 109: -YY_RULE_SETUP -#line 331 "scanner.l" -{ yylval.i = 0; return NUM; } - YY_BREAK -case 110: -YY_RULE_SETUP -#line 332 "scanner.l" -{ yylval.i = 1; return NUM; } - YY_BREAK -case 111: -YY_RULE_SETUP -#line 333 "scanner.l" -{ yylval.i = 0; return NUM; } - YY_BREAK -case 112: -YY_RULE_SETUP -#line 334 "scanner.l" -{ yylval.i = 3; return NUM; } - YY_BREAK -case 113: -YY_RULE_SETUP -#line 335 "scanner.l" -{ yylval.i = 4; return NUM; } - YY_BREAK -case 114: -YY_RULE_SETUP -#line 336 "scanner.l" -{ yylval.i = 5; return NUM; } - YY_BREAK -case 115: -YY_RULE_SETUP -#line 337 "scanner.l" -{ yylval.i = 8; return NUM; } - YY_BREAK -case 116: -YY_RULE_SETUP -#line 338 "scanner.l" -{ yylval.i = 9; return NUM; } - YY_BREAK -case 117: -YY_RULE_SETUP -#line 339 "scanner.l" -{ yylval.i = 10; return NUM; } - YY_BREAK -case 118: -YY_RULE_SETUP -#line 340 "scanner.l" -{ yylval.i = 11; return NUM; } - YY_BREAK -case 119: -YY_RULE_SETUP -#line 341 "scanner.l" -{ yylval.i = 12; return NUM; } - YY_BREAK -case 120: -YY_RULE_SETUP -#line 342 "scanner.l" -{ yylval.i = 13; return NUM; } - YY_BREAK -case 121: -YY_RULE_SETUP -#line 343 "scanner.l" -{ yylval.i = 14; return NUM; } - YY_BREAK -case 122: -YY_RULE_SETUP -#line 344 "scanner.l" -{ yylval.i = 15; return NUM; } - YY_BREAK -case 123: -YY_RULE_SETUP -#line 345 "scanner.l" -{ yylval.i = 16; return NUM; } - YY_BREAK -case 124: -YY_RULE_SETUP -#line 346 "scanner.l" -{ yylval.i = 17; return NUM; } - YY_BREAK -case 125: -YY_RULE_SETUP -#line 347 "scanner.l" -{ yylval.i = 18; return NUM; } - YY_BREAK -case 126: -YY_RULE_SETUP -#line 348 "scanner.l" -{ yylval.i = 13; return NUM; } - YY_BREAK -case 127: -YY_RULE_SETUP -#line 349 "scanner.l" -{ yylval.i = 0x01; return NUM; } - YY_BREAK -case 128: -YY_RULE_SETUP -#line 350 "scanner.l" -{ yylval.i = 0x02; return NUM; } - YY_BREAK -case 129: -YY_RULE_SETUP -#line 351 "scanner.l" -{ yylval.i = 0x04; return NUM; } - YY_BREAK -case 130: -YY_RULE_SETUP -#line 352 "scanner.l" -{ yylval.i = 0x08; return NUM; } - YY_BREAK -case 131: -YY_RULE_SETUP -#line 353 "scanner.l" -{ yylval.i = 0x10; return NUM; } - YY_BREAK -case 132: -YY_RULE_SETUP -#line 354 "scanner.l" -{ yylval.i = 0x20; return NUM; } - YY_BREAK -case 133: -YY_RULE_SETUP -#line 355 "scanner.l" -{ - yylval.s = sdup((char *)pcap_text); return ID; } - YY_BREAK -case 134: -YY_RULE_SETUP -#line 357 "scanner.l" -{ yylval.s = sdup((char *)pcap_text + 1); return ID; } - YY_BREAK -case 135: -YY_RULE_SETUP -#line 358 "scanner.l" -{ - bpf_error("illegal token: %s", pcap_text); } - YY_BREAK -case 136: -YY_RULE_SETUP -#line 360 "scanner.l" -{ bpf_error("illegal char '%c'", *pcap_text); } - YY_BREAK -case 137: -YY_RULE_SETUP -#line 361 "scanner.l" -ECHO; - YY_BREAK -#line 3471 "" -case YY_STATE_EOF(INITIAL): - yyterminate(); - - case YY_END_OF_BUFFER: - { - /* Amount of text matched not including the EOB char. */ - int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; - - /* Undo the effects of YY_DO_BEFORE_ACTION. */ - *yy_cp = (yy_hold_char); - YY_RESTORE_YY_MORE_OFFSET - - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) - { - /* We're scanning a new file or input source. It's - * possible that this happened because the user - * just pointed pcap_in at a new source and called - * pcap_lex(). If so, then we have to assure - * consistency between YY_CURRENT_BUFFER and our - * globals. Here is the right place to do so, because - * this is the first action (other than possibly a - * back-up) that will match for the new input source. - */ - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - YY_CURRENT_BUFFER_LVALUE->yy_input_file = pcap_in; - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; - } - - /* Note that here we test for yy_c_buf_p "<=" to the position - * of the first EOB in the buffer, since yy_c_buf_p will - * already have been incremented past the NUL character - * (since all states make transitions on EOB to the - * end-of-buffer state). Contrast this with the test - * in input(). - */ - if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) - { /* This was really a NUL. */ - yy_state_type yy_next_state; - - (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state( ); - - /* Okay, we're now positioned to make the NUL - * transition. We couldn't have - * yy_get_previous_state() go ahead and do it - * for us because it doesn't know how to deal - * with the possibility of jamming (and we don't - * want to build jamming into it because then it - * will run more slowly). - */ - - yy_next_state = yy_try_NUL_trans( yy_current_state ); - - yy_bp = (yytext_ptr) + YY_MORE_ADJ; - - if ( yy_next_state ) - { - /* Consume the NUL. */ - yy_cp = ++(yy_c_buf_p); - yy_current_state = yy_next_state; - goto yy_match; - } - - else - { - yy_cp = (yy_c_buf_p); - goto yy_find_action; - } - } - - else switch ( yy_get_next_buffer( ) ) - { - case EOB_ACT_END_OF_FILE: - { - (yy_did_buffer_switch_on_eof) = 0; - - if ( pcap_wrap( ) ) - { - /* Note: because we've taken care in - * yy_get_next_buffer() to have set up - * pcap_text, we can now set up - * yy_c_buf_p so that if some total - * hoser (like flex itself) wants to - * call the scanner after we return the - * YY_NULL, it'll still work - another - * YY_NULL will get returned. - */ - (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; - - yy_act = YY_STATE_EOF(YY_START); - goto do_action; - } - - else - { - if ( ! (yy_did_buffer_switch_on_eof) ) - YY_NEW_FILE; - } - break; - } - - case EOB_ACT_CONTINUE_SCAN: - (yy_c_buf_p) = - (yytext_ptr) + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state( ); - - yy_cp = (yy_c_buf_p); - yy_bp = (yytext_ptr) + YY_MORE_ADJ; - goto yy_match; - - case EOB_ACT_LAST_MATCH: - (yy_c_buf_p) = - &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; - - yy_current_state = yy_get_previous_state( ); - - yy_cp = (yy_c_buf_p); - yy_bp = (yytext_ptr) + YY_MORE_ADJ; - goto yy_find_action; - } - break; - } - - default: - YY_FATAL_ERROR( - "fatal flex scanner internal error--no action found" ); - } /* end of action switch */ - } /* end of scanning one token */ -} /* end of pcap_lex */ - -/* yy_get_next_buffer - try to read in a new buffer - * - * Returns a code representing an action: - * EOB_ACT_LAST_MATCH - - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position - * EOB_ACT_END_OF_FILE - end of file - */ -static int yy_get_next_buffer (void) -{ - register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; - register char *source = (yytext_ptr); - register int number_to_move, i; - int ret_val; - - if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) - YY_FATAL_ERROR( - "fatal flex scanner internal error--end of buffer missed" ); - - if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) - { /* Don't try to fill the buffer, so this is an EOF. */ - if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) - { - /* We matched a single character, the EOB, so - * treat this as a final EOF. - */ - return EOB_ACT_END_OF_FILE; - } - - else - { - /* We matched some text prior to the EOB, first - * process it. - */ - return EOB_ACT_LAST_MATCH; - } - } - - /* Try to read more data. */ - - /* First move last chars to start of buffer. */ - number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; - - for ( i = 0; i < number_to_move; ++i ) - *(dest++) = *(source++); - - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) - /* don't do the read, it's not guaranteed to return an EOF, - * just force an EOF - */ - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; - - else - { - int num_to_read = - YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; - - while ( num_to_read <= 0 ) - { /* Not enough room in the buffer - grow it. */ - - /* just a shorter name for the current buffer */ - YY_BUFFER_STATE b = YY_CURRENT_BUFFER; - - int yy_c_buf_p_offset = - (int) ((yy_c_buf_p) - b->yy_ch_buf); - - if ( b->yy_is_our_buffer ) - { - int new_size = b->yy_buf_size * 2; - - if ( new_size <= 0 ) - b->yy_buf_size += b->yy_buf_size / 8; - else - b->yy_buf_size *= 2; - - b->yy_ch_buf = (char *) - /* Include room in for 2 EOB chars. */ - pcap_realloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); - } - else - /* Can't grow it, we don't own it. */ - b->yy_ch_buf = 0; - - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( - "fatal error - scanner input buffer overflow" ); - - (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; - - num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - - number_to_move - 1; - - } - - if ( num_to_read > YY_READ_BUF_SIZE ) - num_to_read = YY_READ_BUF_SIZE; - - /* Read in more data. */ - YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), - (yy_n_chars), (size_t) num_to_read ); - - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); - } - - if ( (yy_n_chars) == 0 ) - { - if ( number_to_move == YY_MORE_ADJ ) - { - ret_val = EOB_ACT_END_OF_FILE; - pcap_restart(pcap_in ); - } - - else - { - ret_val = EOB_ACT_LAST_MATCH; - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = - YY_BUFFER_EOF_PENDING; - } - } - - else - ret_val = EOB_ACT_CONTINUE_SCAN; - - (yy_n_chars) += number_to_move; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; - - (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; - - return ret_val; -} - -/* yy_get_previous_state - get the state just before the EOB char was reached */ - - static yy_state_type yy_get_previous_state (void) -{ - register yy_state_type yy_current_state; - register char *yy_cp; - - yy_current_state = (yy_start); - - for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) - { - register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); - if ( yy_accept[yy_current_state] ) - { - (yy_last_accepting_state) = yy_current_state; - (yy_last_accepting_cpos) = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 1330 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - } - - return yy_current_state; -} - -/* yy_try_NUL_trans - try to make a transition on the NUL character - * - * synopsis - * next_state = yy_try_NUL_trans( current_state ); - */ - static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) -{ - register int yy_is_jam; - register char *yy_cp = (yy_c_buf_p); - - register YY_CHAR yy_c = 1; - if ( yy_accept[yy_current_state] ) - { - (yy_last_accepting_state) = yy_current_state; - (yy_last_accepting_cpos) = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 1330 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 1329); - - return yy_is_jam ? 0 : yy_current_state; -} - - static void yyunput (int c, register char * yy_bp ) -{ - register char *yy_cp; - - yy_cp = (yy_c_buf_p); - - /* undo effects of setting up pcap_text */ - *yy_cp = (yy_hold_char); - - if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) - { /* need to shift things up to make room */ - /* +2 for EOB chars. */ - register int number_to_move = (yy_n_chars) + 2; - register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ - YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; - register char *source = - &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; - - while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) - *--dest = *--source; - - yy_cp += (int) (dest - source); - yy_bp += (int) (dest - source); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; - - if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) - YY_FATAL_ERROR( "flex scanner push-back overflow" ); - } - - *--yy_cp = (char) c; - - (yytext_ptr) = yy_bp; - (yy_hold_char) = *yy_cp; - (yy_c_buf_p) = yy_cp; -} - -#ifndef YY_NO_INPUT -#ifdef __cplusplus - static int yyinput (void) -#else - static int input (void) -#endif - -{ - int c; - - *(yy_c_buf_p) = (yy_hold_char); - - if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) - { - /* yy_c_buf_p now points to the character we want to return. - * If this occurs *before* the EOB characters, then it's a - * valid NUL; if not, then we've hit the end of the buffer. - */ - if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) - /* This was really a NUL. */ - *(yy_c_buf_p) = '\0'; - - else - { /* need more input */ - int offset = (yy_c_buf_p) - (yytext_ptr); - ++(yy_c_buf_p); - - switch ( yy_get_next_buffer( ) ) - { - case EOB_ACT_LAST_MATCH: - /* This happens because yy_g_n_b() - * sees that we've accumulated a - * token and flags that we need to - * try matching the token before - * proceeding. But for input(), - * there's no matching to consider. - * So convert the EOB_ACT_LAST_MATCH - * to EOB_ACT_END_OF_FILE. - */ - - /* Reset buffer status. */ - pcap_restart(pcap_in ); - - /*FALLTHROUGH*/ - - case EOB_ACT_END_OF_FILE: - { - if ( pcap_wrap( ) ) - return EOF; - - if ( ! (yy_did_buffer_switch_on_eof) ) - YY_NEW_FILE; -#ifdef __cplusplus - return yyinput(); -#else - return input(); -#endif - } - - case EOB_ACT_CONTINUE_SCAN: - (yy_c_buf_p) = (yytext_ptr) + offset; - break; - } - } - } - - c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ - *(yy_c_buf_p) = '\0'; /* preserve pcap_text */ - (yy_hold_char) = *++(yy_c_buf_p); - - return c; -} -#endif /* ifndef YY_NO_INPUT */ - -/** Immediately switch to a different input stream. - * @param input_file A readable stream. - * - * @note This function does not reset the start condition to @c INITIAL . - */ - void pcap_restart (FILE * input_file ) -{ - - if ( ! YY_CURRENT_BUFFER ){ - pcap_ensure_buffer_stack (); - YY_CURRENT_BUFFER_LVALUE = - pcap__create_buffer(pcap_in,YY_BUF_SIZE ); - } - - pcap__init_buffer(YY_CURRENT_BUFFER,input_file ); - pcap__load_buffer_state( ); -} - -/** Switch to a different input buffer. - * @param new_buffer The new input buffer. - * - */ - void pcap__switch_to_buffer (YY_BUFFER_STATE new_buffer ) -{ - - /* TODO. We should be able to replace this entire function body - * with - * pcap_pop_buffer_state(); - * pcap_push_buffer_state(new_buffer); - */ - pcap_ensure_buffer_stack (); - if ( YY_CURRENT_BUFFER == new_buffer ) - return; - - if ( YY_CURRENT_BUFFER ) - { - /* Flush out information for old buffer. */ - *(yy_c_buf_p) = (yy_hold_char); - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); - } - - YY_CURRENT_BUFFER_LVALUE = new_buffer; - pcap__load_buffer_state( ); - - /* We don't actually know whether we did this switch during - * EOF (pcap_wrap()) processing, but the only time this flag - * is looked at is after pcap_wrap() is called, so it's safe - * to go ahead and always set it. - */ - (yy_did_buffer_switch_on_eof) = 1; -} - -static void pcap__load_buffer_state (void) -{ - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; - pcap_in = YY_CURRENT_BUFFER_LVALUE->yy_input_file; - (yy_hold_char) = *(yy_c_buf_p); -} - -/** Allocate and initialize an input buffer state. - * @param file A readable stream. - * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. - * - * @return the allocated buffer state. - */ - YY_BUFFER_STATE pcap__create_buffer (FILE * file, int size ) -{ - YY_BUFFER_STATE b; - - b = (YY_BUFFER_STATE) pcap_alloc(sizeof( struct yy_buffer_state ) ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in pcap__create_buffer()" ); - - b->yy_buf_size = size; - - /* yy_ch_buf has to be 2 characters longer than the size given because - * we need to put in 2 end-of-buffer characters. - */ - b->yy_ch_buf = (char *) pcap_alloc(b->yy_buf_size + 2 ); - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in pcap__create_buffer()" ); - - b->yy_is_our_buffer = 1; - - pcap__init_buffer(b,file ); - - return b; -} - -/** Destroy the buffer. - * @param b a buffer created with pcap__create_buffer() - * - */ - void pcap__delete_buffer (YY_BUFFER_STATE b ) -{ - - if ( ! b ) - return; - - if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ - YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; - - if ( b->yy_is_our_buffer ) - pcap_free((void *) b->yy_ch_buf ); - - pcap_free((void *) b ); -} - -#ifndef __cplusplus -extern int isatty (int ); -#endif /* __cplusplus */ - -/* Initializes or reinitializes a buffer. - * This function is sometimes called more than once on the same buffer, - * such as during a pcap_restart() or at EOF. - */ - static void pcap__init_buffer (YY_BUFFER_STATE b, FILE * file ) - -{ - int oerrno = errno; - - pcap__flush_buffer(b ); - - b->yy_input_file = file; - b->yy_fill_buffer = 1; - - /* If b is the current buffer, then pcap__init_buffer was _probably_ - * called from pcap_restart() or through yy_get_next_buffer. - * In that case, we don't want to reset the lineno or column. - */ - if (b != YY_CURRENT_BUFFER){ - b->yy_bs_lineno = 1; - b->yy_bs_column = 0; - } - - b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; - - errno = oerrno; -} - -/** Discard all buffered characters. On the next scan, YY_INPUT will be called. - * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. - * - */ - void pcap__flush_buffer (YY_BUFFER_STATE b ) -{ - if ( ! b ) - return; - - b->yy_n_chars = 0; - - /* We always need two end-of-buffer characters. The first causes - * a transition to the end-of-buffer state. The second causes - * a jam in that state. - */ - b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; - b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; - - b->yy_buf_pos = &b->yy_ch_buf[0]; - - b->yy_at_bol = 1; - b->yy_buffer_status = YY_BUFFER_NEW; - - if ( b == YY_CURRENT_BUFFER ) - pcap__load_buffer_state( ); -} - -/** Pushes the new state onto the stack. The new state becomes - * the current state. This function will allocate the stack - * if necessary. - * @param new_buffer The new state. - * - */ -void pcap_push_buffer_state (YY_BUFFER_STATE new_buffer ) -{ - if (new_buffer == NULL) - return; - - pcap_ensure_buffer_stack(); - - /* This block is copied from pcap__switch_to_buffer. */ - if ( YY_CURRENT_BUFFER ) - { - /* Flush out information for old buffer. */ - *(yy_c_buf_p) = (yy_hold_char); - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); - } - - /* Only push if top exists. Otherwise, replace top. */ - if (YY_CURRENT_BUFFER) - (yy_buffer_stack_top)++; - YY_CURRENT_BUFFER_LVALUE = new_buffer; - - /* copied from pcap__switch_to_buffer. */ - pcap__load_buffer_state( ); - (yy_did_buffer_switch_on_eof) = 1; -} - -/** Removes and deletes the top of the stack, if present. - * The next element becomes the new top. - * - */ -void pcap_pop_buffer_state (void) -{ - if (!YY_CURRENT_BUFFER) - return; - - pcap__delete_buffer(YY_CURRENT_BUFFER ); - YY_CURRENT_BUFFER_LVALUE = NULL; - if ((yy_buffer_stack_top) > 0) - --(yy_buffer_stack_top); - - if (YY_CURRENT_BUFFER) { - pcap__load_buffer_state( ); - (yy_did_buffer_switch_on_eof) = 1; - } -} - -/* Allocates the stack if it does not exist. - * Guarantees space for at least one push. - */ -static void pcap_ensure_buffer_stack (void) -{ - int num_to_alloc; - - if (!(yy_buffer_stack)) { - - /* First allocation is just for 2 elements, since we don't know if this - * scanner will even need a stack. We use 2 instead of 1 to avoid an - * immediate realloc on the next call. - */ - num_to_alloc = 1; - (yy_buffer_stack) = (struct yy_buffer_state**)pcap_alloc - (num_to_alloc * sizeof(struct yy_buffer_state*) - ); - - memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); - - (yy_buffer_stack_max) = num_to_alloc; - (yy_buffer_stack_top) = 0; - return; - } - - if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ - - /* Increase the buffer to prepare for a possible push. */ - int grow_size = 8 /* arbitrary grow size */; - - num_to_alloc = (yy_buffer_stack_max) + grow_size; - (yy_buffer_stack) = (struct yy_buffer_state**)pcap_realloc - ((yy_buffer_stack), - num_to_alloc * sizeof(struct yy_buffer_state*) - ); - - /* zero only the new slots.*/ - memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); - (yy_buffer_stack_max) = num_to_alloc; - } -} - -/** Setup the input buffer state to scan directly from a user-specified character buffer. - * @param base the character buffer - * @param size the size in bytes of the character buffer - * - * @return the newly allocated buffer state object. - */ -YY_BUFFER_STATE pcap__scan_buffer (char * base, yy_size_t size ) -{ - YY_BUFFER_STATE b; - - if ( size < 2 || - base[size-2] != YY_END_OF_BUFFER_CHAR || - base[size-1] != YY_END_OF_BUFFER_CHAR ) - /* They forgot to leave room for the EOB's. */ - return 0; - - b = (YY_BUFFER_STATE) pcap_alloc(sizeof( struct yy_buffer_state ) ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in pcap__scan_buffer()" ); - - b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ - b->yy_buf_pos = b->yy_ch_buf = base; - b->yy_is_our_buffer = 0; - b->yy_input_file = 0; - b->yy_n_chars = b->yy_buf_size; - b->yy_is_interactive = 0; - b->yy_at_bol = 1; - b->yy_fill_buffer = 0; - b->yy_buffer_status = YY_BUFFER_NEW; - - pcap__switch_to_buffer(b ); - - return b; -} - -/** Setup the input buffer state to scan a string. The next call to pcap_lex() will - * scan from a @e copy of @a str. - * @param yystr a NUL-terminated string to scan - * - * @return the newly allocated buffer state object. - * @note If you want to scan bytes that may contain NUL values, then use - * pcap__scan_bytes() instead. - */ -YY_BUFFER_STATE pcap__scan_string (yyconst char * yystr ) -{ - - return pcap__scan_bytes(yystr,strlen(yystr) ); -} - -/** Setup the input buffer state to scan the given bytes. The next call to pcap_lex() will - * scan from a @e copy of @a bytes. - * @param bytes the byte buffer to scan - * @param len the number of bytes in the buffer pointed to by @a bytes. - * - * @return the newly allocated buffer state object. - */ -YY_BUFFER_STATE pcap__scan_bytes (yyconst char * yybytes, int _yybytes_len ) -{ - YY_BUFFER_STATE b; - char *buf; - yy_size_t n; - int i; - - /* Get memory for full buffer, including space for trailing EOB's. */ - n = _yybytes_len + 2; - buf = (char *) pcap_alloc(n ); - if ( ! buf ) - YY_FATAL_ERROR( "out of dynamic memory in pcap__scan_bytes()" ); - - for ( i = 0; i < _yybytes_len; ++i ) - buf[i] = yybytes[i]; - - buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; - - b = pcap__scan_buffer(buf,n ); - if ( ! b ) - YY_FATAL_ERROR( "bad buffer in pcap__scan_bytes()" ); - - /* It's okay to grow etc. this buffer, and we should throw it - * away when we're done. - */ - b->yy_is_our_buffer = 1; - - return b; -} - -#ifndef YY_EXIT_FAILURE -#define YY_EXIT_FAILURE 2 -#endif - -static void yy_fatal_error (yyconst char* msg ) -{ - (void) fprintf( stderr, "%s\n", msg ); - exit( YY_EXIT_FAILURE ); -} - -/* Redefine yyless() so it works in section 3 code. */ - -#undef yyless -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up pcap_text. */ \ - int yyless_macro_arg = (n); \ - YY_LESS_LINENO(yyless_macro_arg);\ - pcap_text[pcap_leng] = (yy_hold_char); \ - (yy_c_buf_p) = pcap_text + yyless_macro_arg; \ - (yy_hold_char) = *(yy_c_buf_p); \ - *(yy_c_buf_p) = '\0'; \ - pcap_leng = yyless_macro_arg; \ - } \ - while ( 0 ) - -/* Accessor methods (get/set functions) to struct members. */ - -/** Get the current line number. - * - */ -int pcap_get_lineno (void) -{ - - return pcap_lineno; -} - -/** Get the input stream. - * - */ -FILE *pcap_get_in (void) -{ - return pcap_in; -} - -/** Get the output stream. - * - */ -FILE *pcap_get_out (void) -{ - return pcap_out; -} - -/** Get the length of the current token. - * - */ -int pcap_get_leng (void) -{ - return pcap_leng; -} - -/** Get the current token. - * - */ - -char *pcap_get_text (void) -{ - return pcap_text; -} - -/** Set the current line number. - * @param line_number - * - */ -void pcap_set_lineno (int line_number ) -{ - - pcap_lineno = line_number; -} - -/** Set the input stream. This does not discard the current - * input buffer. - * @param in_str A readable stream. - * - * @see pcap__switch_to_buffer - */ -void pcap_set_in (FILE * in_str ) -{ - pcap_in = in_str ; -} - -void pcap_set_out (FILE * out_str ) -{ - pcap_out = out_str ; -} - -int pcap_get_debug (void) -{ - return pcap__flex_debug; -} - -void pcap_set_debug (int bdebug ) -{ - pcap__flex_debug = bdebug ; -} - -static int yy_init_globals (void) -{ - /* Initialization is the same as for the non-reentrant scanner. - * This function is called from pcap_lex_destroy(), so don't allocate here. - */ - - (yy_buffer_stack) = 0; - (yy_buffer_stack_top) = 0; - (yy_buffer_stack_max) = 0; - (yy_c_buf_p) = (char *) 0; - (yy_init) = 0; - (yy_start) = 0; - -/* Defined in main.c */ -#ifdef YY_STDINIT - pcap_in = stdin; - pcap_out = stdout; -#else - pcap_in = (FILE *) 0; - pcap_out = (FILE *) 0; -#endif - - /* For future reference: Set errno on error, since we are called by - * pcap_lex_init() - */ - return 0; -} - -/* pcap_lex_destroy is for both reentrant and non-reentrant scanners. */ -int pcap_lex_destroy (void) -{ - - /* Pop the buffer stack, destroying each element. */ - while(YY_CURRENT_BUFFER){ - pcap__delete_buffer(YY_CURRENT_BUFFER ); - YY_CURRENT_BUFFER_LVALUE = NULL; - pcap_pop_buffer_state(); - } - - /* Destroy the stack itself. */ - pcap_free((yy_buffer_stack) ); - (yy_buffer_stack) = NULL; - - /* Reset the globals. This is important in a non-reentrant scanner so the next time - * pcap_lex() is called, initialization will occur. */ - yy_init_globals( ); - - return 0; -} - -/* - * Internal utility routines. - */ - -#ifndef yytext_ptr -static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) -{ - register int i; - for ( i = 0; i < n; ++i ) - s1[i] = s2[i]; -} -#endif - -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen (yyconst char * s ) -{ - register int n; - for ( n = 0; s[n]; ++n ) - ; - - return n; -} -#endif - -void *pcap_alloc (yy_size_t size ) -{ - return (void *) malloc( size ); -} - -void *pcap_realloc (void * ptr, yy_size_t size ) -{ - /* The cast to (char *) in the following accommodates both - * implementations that use char* generic pointers, and those - * that use void* generic pointers. It works with the latter - * because both ANSI C and C++ allow castless assignment from - * any pointer type to void*, and deal with argument conversions - * as though doing an assignment. - */ - return (void *) realloc( (char *) ptr, size ); -} - -void pcap_free (void * ptr ) -{ - free( (char *) ptr ); /* see pcap_realloc() for (char *) cast */ -} - -#define YYTABLES_NAME "yytables" - -#line 361 "scanner.l" - - -void -lex_init(buf) - const char *buf; -{ -#ifdef FLEX_SCANNER - in_buffer = pcap__scan_string(buf); -#else - in_buffer = buf; -#endif -} - -/* - * Do any cleanup necessary after parsing. - */ -void -lex_cleanup() -{ -#ifdef FLEX_SCANNER - if (in_buffer != NULL) - pcap__delete_buffer(in_buffer); - in_buffer = NULL; -#endif -} - -/* - * Also define a pcap_wrap. Note that if we're using flex, it will - * define a macro to map this identifier to pcap_wrap. - */ -int -pcap_wrap() -{ - 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; -} - diff --git a/libpcap/scanner.l b/libpcap/scanner.l index 01face17d..c477684e1 100644 --- a/libpcap/scanner.l +++ b/libpcap/scanner.l @@ -22,7 +22,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/scanner.l,v 1.99.2.9 2007/06/11 09:52:05 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/scanner.l,v 1.110.2.2 2008/02/06 10:21:47 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -52,7 +52,7 @@ static const char rcsid[] _U_ = #define AI_NUMERICHOST 0x04 #endif #endif /*INET6*/ -#include +#include #include "tokdefs.h" #ifdef HAVE_OS_PROTO_H @@ -79,6 +79,7 @@ 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 @@ -166,6 +167,10 @@ 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; @@ -247,6 +252,14 @@ protochain { 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; + less return LESS; greater return GREATER; byte return CBYTE; @@ -307,11 +320,11 @@ sls return SLS; ">>" 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; } -{B}:{B}:{B}:{B}:{B}:{B} { yylval.e = pcap_ether_aton((char *)yytext); - return EID; } {V6} { #ifdef INET6 struct addrinfo hints, *res; diff --git a/libpcap/tokdefs.h b/libpcap/tokdefs.h deleted file mode 100644 index 8eb81b297..000000000 --- a/libpcap/tokdefs.h +++ /dev/null @@ -1,278 +0,0 @@ -/* A Bison parser, made by GNU Bison 2.3. */ - -/* Skeleton interface for Bison's Yacc-like parsers in C - - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 - Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - -/* Tokens. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - enum yytokentype { - DST = 258, - SRC = 259, - HOST = 260, - GATEWAY = 261, - NET = 262, - NETMASK = 263, - PORT = 264, - PORTRANGE = 265, - LESS = 266, - GREATER = 267, - PROTO = 268, - PROTOCHAIN = 269, - CBYTE = 270, - ARP = 271, - RARP = 272, - IP = 273, - SCTP = 274, - TCP = 275, - UDP = 276, - ICMP = 277, - IGMP = 278, - IGRP = 279, - PIM = 280, - VRRP = 281, - ATALK = 282, - AARP = 283, - DECNET = 284, - LAT = 285, - SCA = 286, - MOPRC = 287, - MOPDL = 288, - TK_BROADCAST = 289, - TK_MULTICAST = 290, - NUM = 291, - INBOUND = 292, - OUTBOUND = 293, - PF_IFNAME = 294, - PF_RSET = 295, - PF_RNR = 296, - PF_SRNR = 297, - PF_REASON = 298, - PF_ACTION = 299, - LINK = 300, - GEQ = 301, - LEQ = 302, - NEQ = 303, - ID = 304, - EID = 305, - HID = 306, - HID6 = 307, - AID = 308, - LSH = 309, - RSH = 310, - LEN = 311, - IPV6 = 312, - ICMPV6 = 313, - AH = 314, - ESP = 315, - VLAN = 316, - MPLS = 317, - PPPOED = 318, - PPPOES = 319, - ISO = 320, - ESIS = 321, - CLNP = 322, - ISIS = 323, - L1 = 324, - L2 = 325, - IIH = 326, - LSP = 327, - SNP = 328, - CSNP = 329, - PSNP = 330, - STP = 331, - IPX = 332, - NETBEUI = 333, - LANE = 334, - LLC = 335, - METAC = 336, - BCC = 337, - SC = 338, - ILMIC = 339, - OAMF4EC = 340, - OAMF4SC = 341, - OAM = 342, - OAMF4 = 343, - CONNECTMSG = 344, - METACONNECT = 345, - VPI = 346, - VCI = 347, - RADIO = 348, - FISU = 349, - LSSU = 350, - MSU = 351, - SIO = 352, - OPC = 353, - DPC = 354, - SLS = 355, - AND = 356, - OR = 357, - UMINUS = 358 - }; -#endif -/* Tokens. */ -#define DST 258 -#define SRC 259 -#define HOST 260 -#define GATEWAY 261 -#define NET 262 -#define NETMASK 263 -#define PORT 264 -#define PORTRANGE 265 -#define LESS 266 -#define GREATER 267 -#define PROTO 268 -#define PROTOCHAIN 269 -#define CBYTE 270 -#define ARP 271 -#define RARP 272 -#define IP 273 -#define SCTP 274 -#define TCP 275 -#define UDP 276 -#define ICMP 277 -#define IGMP 278 -#define IGRP 279 -#define PIM 280 -#define VRRP 281 -#define ATALK 282 -#define AARP 283 -#define DECNET 284 -#define LAT 285 -#define SCA 286 -#define MOPRC 287 -#define MOPDL 288 -#define TK_BROADCAST 289 -#define TK_MULTICAST 290 -#define NUM 291 -#define INBOUND 292 -#define OUTBOUND 293 -#define PF_IFNAME 294 -#define PF_RSET 295 -#define PF_RNR 296 -#define PF_SRNR 297 -#define PF_REASON 298 -#define PF_ACTION 299 -#define LINK 300 -#define GEQ 301 -#define LEQ 302 -#define NEQ 303 -#define ID 304 -#define EID 305 -#define HID 306 -#define HID6 307 -#define AID 308 -#define LSH 309 -#define RSH 310 -#define LEN 311 -#define IPV6 312 -#define ICMPV6 313 -#define AH 314 -#define ESP 315 -#define VLAN 316 -#define MPLS 317 -#define PPPOED 318 -#define PPPOES 319 -#define ISO 320 -#define ESIS 321 -#define CLNP 322 -#define ISIS 323 -#define L1 324 -#define L2 325 -#define IIH 326 -#define LSP 327 -#define SNP 328 -#define CSNP 329 -#define PSNP 330 -#define STP 331 -#define IPX 332 -#define NETBEUI 333 -#define LANE 334 -#define LLC 335 -#define METAC 336 -#define BCC 337 -#define SC 338 -#define ILMIC 339 -#define OAMF4EC 340 -#define OAMF4SC 341 -#define OAM 342 -#define OAMF4 343 -#define CONNECTMSG 344 -#define METACONNECT 345 -#define VPI 346 -#define VCI 347 -#define RADIO 348 -#define FISU 349 -#define LSSU 350 -#define MSU 351 -#define SIO 352 -#define OPC 353 -#define DPC 354 -#define SLS 355 -#define AND 356 -#define OR 357 -#define UMINUS 358 - - - - -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -typedef union YYSTYPE -#line 90 "grammar.y" -{ - 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; -} -/* Line 1489 of yacc.c. */ -#line 271 "y.tab.h" - YYSTYPE; -# define yystype YYSTYPE /* obsolescent; will be withdrawn */ -# define YYSTYPE_IS_DECLARED 1 -# define YYSTYPE_IS_TRIVIAL 1 -#endif - -extern YYSTYPE pcap_lval; -