diff options
Diffstat (limited to 'contrib/libpcap')
38 files changed, 2803 insertions, 730 deletions
diff --git a/contrib/libpcap/CHANGES b/contrib/libpcap/CHANGES index 015836d..d187a99 100644 --- a/contrib/libpcap/CHANGES +++ b/contrib/libpcap/CHANGES @@ -1,4 +1,17 @@ -@(#) $Header: /tcpdump/master/libpcap/CHANGES,v 1.59 2004/03/30 14:42:50 mcr Exp $ (LBL) +@(#) $Header: /tcpdump/master/libpcap/CHANGES,v 1.59.2.1 2005/07/05 21:04:27 mcr Exp $ (LBL) + +Tue. July 5, 2005. ken@xelerance.com. Summary for 3.9.x tcpdump + + Fixes for compiling on nearly every platform, + including improved 64bit support + MSDOS Support + Add support for sending packets + OpenBSD pf format support + IrDA capture (Linux only) + +Tue. May 27, 2005. mcr@sandelman.ottawa.on.ca. Summary for 0.9.1 release + + Numerous fixes for Tue. March 30, 2004. mcr@sandelman.ottawa.on.ca. Summary for 3.8.3 release diff --git a/contrib/libpcap/CREDITS b/contrib/libpcap/CREDITS index 870ec50..6b78ed4 100644 --- a/contrib/libpcap/CREDITS +++ b/contrib/libpcap/CREDITS @@ -33,6 +33,7 @@ Additional people who have contributed patches: Erik de Castro Lopo <erik.de.castro.lopo@sensorynetworks.com> Franz Schaefer <schaefer@mond.at> Gianluca Varenni <varenni@netgroup-serv.polito.it> + Gilbert Hoyek <gil_hoyek@hotmail.com> Gisle Vanem <giva@bgnett.no> Graeme Hewson <ghewson@cix.compulink.co.uk> Greg Stark <gsstark@mit.edu> @@ -58,6 +59,7 @@ Additional people who have contributed patches: Love Hörnquist-Åstrand <lha@stacken.kth.se> Maciej W. Rozycki <macro@ds2.pg.gda.pl> Marcus Felipe Pereira <marcus@task.com.br> + Mark C. Brown <mbrown@hp.com> Mark Pizzolato <List-tcpdump-workers@subscriptions.pizzolato.net> Martin Husemann <martin@netbsd.org> Matthew Luckie <mjl@luckie.org.nz> @@ -67,8 +69,10 @@ Additional people who have contributed patches: Octavian Cerna <tavy@ylabs.com> Olaf Kirch <okir@caldera.de> Onno van der Linden <onno@simplex.nl> + Patrick Marie <mycroft@virgaria.org> Paul Mundt <lethal@linux-sh.org> Pavel Kankovsky <kan@dcit.cz> + Pawel Pokrywka <publicpp@gmail.com> Peter Fales <peter@fales-lorenz.net> Peter Jeremy <peter.jeremy@alcatel.com.au> Phil Wood <cpw@lanl.gov> @@ -81,6 +85,7 @@ Additional people who have contributed patches: Solomon Peachy <pizza@shaftnet.org> Stefan Hudson <hudson@mbay.net> Takashi Yamamoto <yamt@mwd.biglobe.ne.jp> + Tanaka Shin-ya <zstanaka@archer.livedoor.com> Tony Li <tli@procket.com> Torsten Landschoff <torsten@debian.org> Uns Lider <unslider@miranda.org> diff --git a/contrib/libpcap/FILES b/contrib/libpcap/FILES index 95b75cf..879d74b 100644 --- a/contrib/libpcap/FILES +++ b/contrib/libpcap/FILES @@ -12,6 +12,7 @@ README.dag README.hpux README.linux README.macosx +README.septel README.tru64 README.Win32 SUNOS4/nit_if.o.sparc @@ -87,6 +88,8 @@ 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 @@ -96,7 +99,6 @@ pcap.c pcap.h pf.h ppp.h -rawss7.h savefile.c scanner.l sll.h diff --git a/contrib/libpcap/INSTALL.txt b/contrib/libpcap/INSTALL.txt index 2f9075d..d2c0180 100644 --- a/contrib/libpcap/INSTALL.txt +++ b/contrib/libpcap/INSTALL.txt @@ -1,4 +1,4 @@ -@(#) $Header: /tcpdump/master/libpcap/INSTALL.txt,v 1.12 2004/12/18 08:52:08 guy Exp $ (LBL) +@(#) $Header: /tcpdump/master/libpcap/INSTALL.txt,v 1.12.2.1 2005/06/20 21:30:14 guy Exp $ (LBL) To build libpcap, run "./configure" (a shell script). The configure script will determine your system attributes and generate an @@ -308,6 +308,7 @@ README.dag - notes on using libpcap to capture on Endace DAG devices README.hpux - notes on using libpcap on HP-UX README.linux - notes on using libpcap on Linux README.macosx - notes on using libpcap on Mac OS X +README.septel - notes on using libpcap to capture on Intel/Septel 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 @@ -363,6 +364,8 @@ 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-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 diff --git a/contrib/libpcap/README.septel b/contrib/libpcap/README.septel new file mode 100644 index 0000000..fbc88df --- /dev/null +++ b/contrib/libpcap/README.septel @@ -0,0 +1,50 @@ +The following instructions apply if you have a Linux platform and want +libpcap to support the Septel range of passive network monitoring cards +from Intel (http://www.intel.com) + +1) Install and build the Septel software distribution by following the +instructions supplied with that package. + +2) Configure libcap. To allow the 'configure' script to locate the Septel +software distribution use the '--with-septel' option: + + ./configure --with-septel=DIR + +where DIR is the root of the Septel software distribution, for example +/var/src/septel. + +By default (if you write only ./configure --with-septel) it takes +./../septel as argument for DIR. + +If the Septel software is correctly detected 'configure' will +report: + + checking whether we have Septel API... yes + +If 'configure' reports that there is no Septel API, the directory may have been +incorrectly specified or the Septel software was not built before configuring +libpcap. + +See also the libpcap INSTALL.txt file for further libpcap configuration +options. + +Building libpcap at this stage will include support for both the native +packet capture stream and for capturing from Septel cards. To build +libpcap with only Septel support specify the capture type as 'septel' +when configuring libpcap: + + ./configure --with-septel=DIR --with-pcap=septel + +Applications built with libpcap configured in this way will only detect Septel +cards and will not capture from the native OS packet stream. + +Note: As mentioned in pcap-septel.c we should first edit the system.txt +file to change the user part example (UPE) module id to 0xdd instead of +0x2d for technical reason. So this change in system.txt is crutial and +things will go wrong if it's not done. System.txt along with config.txt +are configuration files that are edited by the user before running the +gctload program that uses these files for initialising modules and +configuring parameters. + +---------------------------------------------------------------------- +for more information please contact me : gil_hoyek@hotmail.com diff --git a/contrib/libpcap/VERSION b/contrib/libpcap/VERSION index e80fc25..f374f66 100644 --- a/contrib/libpcap/VERSION +++ b/contrib/libpcap/VERSION @@ -1 +1 @@ -0.9-PRE-CVS +0.9.1 diff --git a/contrib/libpcap/aclocal.m4 b/contrib/libpcap/aclocal.m4 index 3c26c71..1efb474 100644 --- a/contrib/libpcap/aclocal.m4 +++ b/contrib/libpcap/aclocal.m4 @@ -1,4 +1,4 @@ -dnl @(#) $Header: /tcpdump/master/libpcap/aclocal.m4,v 1.85 2005/03/27 03:27:09 guy Exp $ (LBL) +dnl @(#) $Header: /tcpdump/master/libpcap/aclocal.m4,v 1.85.2.1 2005/04/21 03:42:09 guy Exp $ (LBL) dnl dnl Copyright (c) 1995, 1996, 1997, 1998 dnl The Regents of the University of California. All rights reserved. @@ -851,10 +851,10 @@ dnl AC_DEFUN(AC_C___ATTRIBUTE__, [ AC_MSG_CHECKING(for __attribute__) AC_CACHE_VAL(ac_cv___attribute__, [ -AC_TRY_COMPILE([ +AC_COMPILE_IFELSE( + AC_LANG_SOURCE([[ #include <stdlib.h> -], -[ + static void foo(void) __attribute__ ((noreturn)); static void @@ -862,7 +862,13 @@ foo(void) { exit(1); } -], + +int +main(int argc, char **argv) +{ + foo(); +} + ]]), ac_cv___attribute__=yes, ac_cv___attribute__=no)]) if test "$ac_cv___attribute__" = "yes"; then diff --git a/contrib/libpcap/config.h.in b/contrib/libpcap/config.h.in index 2ecdbc1..43a6b94 100644 --- a/contrib/libpcap/config.h.in +++ b/contrib/libpcap/config.h.in @@ -23,8 +23,8 @@ /* Define to 1 if you have the `ether_hostton' function. */ #undef HAVE_ETHER_HOSTTON -/* on HP-UX 10.20 */ -#undef HAVE_HPUX10_20 +/* on HP-UX 10.20 or later */ +#undef HAVE_HPUX10_20_OR_LATER /* on HP-UX 9.x */ #undef HAVE_HPUX9 @@ -53,6 +53,9 @@ /* define if you have a /proc/net/dev */ #undef HAVE_PROC_NET_DEV +/* define if you have a Septel API */ +#undef HAVE_SEPTEL_API + /* Define to 1 if you have the `snprintf' function. */ #undef HAVE_SNPRINTF @@ -83,6 +86,9 @@ /* Define to 1 if you have the `strlcpy' function. */ #undef HAVE_STRLCPY +/* Define to 1 if the system has the type `struct ether_addr'. */ +#undef HAVE_STRUCT_ETHER_ADDR + /* Define to 1 if you have the <sys/bufmod.h> header file. */ #undef HAVE_SYS_BUFMOD_H diff --git a/contrib/libpcap/configure b/contrib/libpcap/configure index ba01786..42b8153 100755 --- a/contrib/libpcap/configure +++ b/contrib/libpcap/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 1.120 . +# From configure.in Revision: 1.120.2.6 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.57. # @@ -855,9 +855,10 @@ Optional Packages: --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --without-gcc don't use gcc --with-pcap=TYPE use packet capture TYPE - --with-dag[=DIR] include Endace DAG support ("yes", "no" or DIR; default="yes" on BSD and Linux if present) + --with-dag[=DIR] include Endace DAG support ("yes", "no" or DIR; default="yes" on BSD and Linux if present) --with-dag-includes=DIR Endace DAG include directory --with-dag-libraries=DIR Endace DAG library directory + --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 @@ -2633,10 +2634,6 @@ cat >>conftest.$ac_ext <<_ACEOF #include <stdlib.h> -int -main () -{ - static void foo(void) __attribute__ ((noreturn)); static void @@ -2645,9 +2642,12 @@ foo(void) exit(1); } - ; - return 0; +int +main(int argc, char **argv) +{ + foo(); } + _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 @@ -4416,6 +4416,7 @@ cat >>conftest.$ac_ext <<_ACEOF #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> +#include <arpa/inet.h> struct mbuf; struct rtentry; #include <net/if.h> @@ -4458,26 +4459,14 @@ echo "$as_me:$LINENO: result: $ac_cv_have_decl_ether_hostton" >&5 echo "${ECHO_T}$ac_cv_have_decl_ether_hostton" >&6 if test $ac_cv_have_decl_ether_hostton = yes; then -cat >>confdefs.h <<_ACEOF -#define HAVE_DECL_ETHER_HOSTTON 1 -_ACEOF - - cat >>confdefs.h <<\_ACEOF #define NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON _ACEOF -else - cat >>confdefs.h <<_ACEOF -#define HAVE_DECL_ETHER_HOSTTON 0 -_ACEOF - - fi - fi # # Did that succeed? @@ -4688,27 +4677,101 @@ echo "$as_me:$LINENO: result: $ac_cv_have_decl_ether_hostton" >&5 echo "${ECHO_T}$ac_cv_have_decl_ether_hostton" >&6 if test $ac_cv_have_decl_ether_hostton = yes; then -cat >>confdefs.h <<_ACEOF -#define HAVE_DECL_ETHER_HOSTTON 1 + +cat >>confdefs.h <<\_ACEOF +#define NETINET_ETHER_H_DECLARES_ETHER_HOSTTON _ACEOF +fi -cat >>confdefs.h <<\_ACEOF -#define NETINET_ETHER_H_DECLARES_ETHER_HOSTTON + fi + fi + # + # Is ether_hostton() declared? + # + if test "$ac_cv_have_decl_ether_hostton" != yes; then + # + # No, we'll have to declare it ourselves. + # Do we have "struct ether_addr"? + # + echo "$as_me:$LINENO: checking for struct ether_addr" >&5 +echo $ECHO_N "checking for struct ether_addr... $ECHO_C" >&6 +if test "${ac_cv_type_struct_ether_addr+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ _ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +struct mbuf; +struct rtentry; +#include <net/if.h> +#include <netinet/if_ether.h> + +int +main () +{ +if ((struct ether_addr *) 0) + return 0; +if (sizeof (struct ether_addr)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_struct_ether_addr=yes else - cat >>confdefs.h <<_ACEOF -#define HAVE_DECL_ETHER_HOSTTON 0 + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_struct_ether_addr=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_struct_ether_addr" >&5 +echo "${ECHO_T}$ac_cv_type_struct_ether_addr" >&6 +if test $ac_cv_type_struct_ether_addr = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_ETHER_ADDR 1 _ACEOF fi - fi +cat >>confdefs.h <<\_ACEOF +#define HAVE_DECL_ETHER_HOSTTON 0 +_ACEOF + + else + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DECL_ETHER_HOSTTON 1 +_ACEOF + fi fi @@ -5433,6 +5496,10 @@ 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;} @@ -5513,8 +5580,8 @@ fi; case "$V_PCAP" in linux|bpf|dag) # - # We support the DAG API on Linux or BSD, or if we're building a - # DAG-only libpcap. + # We support the DAG API if we're on Linux or BSD, or if we're + # building a DAG-only libpcap. # ;; *) @@ -5540,7 +5607,7 @@ if test "$want_dag" != no; then echo "$as_me:$LINENO: checking whether we have DAG API headers" >&5 echo $ECHO_N "checking whether we have DAG API headers... $ECHO_C" >&6 - # If necessary, set default paths for DAG API headers and libraries. + # If necessary, set default paths for DAG API headers and libraries. if test -z "$dag_root"; then dag_root=/usr/local fi @@ -5560,7 +5627,7 @@ echo $ECHO_N "checking whether we have DAG API headers... $ECHO_C" >&6 if test -r $dag_include_dir/dagapi.h; then ac_cv_lbl_dag_api=yes fi - echo "$as_me:$LINENO: result: $ac_cv_lbl_dag_api ($dag_include_dir)" >&5 + echo "$as_me:$LINENO: result: $ac_cv_lbl_dag_api ($dag_include_dir)" >&5 echo "${ECHO_T}$ac_cv_lbl_dag_api ($dag_include_dir)" >&6 fi @@ -5570,32 +5637,27 @@ if test $ac_cv_lbl_dag_api = yes; then echo $ECHO_N "checking dagapi.o... $ECHO_C" >&6 dagapi_obj=no if test -r $dag_tools_dir/dagapi.o; then - - # 2.4.x. + # 2.4.x. dagapi_obj=$dag_tools_dir/dagapi.o - elif test -r $dag_lib_dir/dagapi.o; then - - # 2.5.x. - dagapi_obj=$dag_lib_dir/dagapi.o - - elif test -r $dag_lib_dir/libdag.a; then - - # 2.5.x. + # 2.5.x. + dagapi_obj=$dag_lib_dir/dagapi.o + elif test -r $dag_lib_dir/libdag.a; then + # 2.5.x. ar x $dag_lib_dir/libdag.a dagapi.o if test -r ./dagapi.o; then dagapi_obj=./dagapi.o fi - fi + fi if test $dagapi_obj = no; then - echo "$as_me:$LINENO: result: no (checked $dag_lib_dir $dag_tools_dir $dag_lib_dir/libdag.a)" >&5 + echo "$as_me:$LINENO: result: no (checked $dag_lib_dir $dag_tools_dir $dag_lib_dir/libdag.a)" >&5 echo "${ECHO_T}no (checked $dag_lib_dir $dag_tools_dir $dag_lib_dir/libdag.a)" >&6 ac_cv_lbl_dag_api=no else echo "$as_me:$LINENO: result: yes ($dagapi_obj)" >&5 echo "${ECHO_T}yes ($dagapi_obj)" >&6 - fi + fi fi if test $ac_cv_lbl_dag_api = yes; then @@ -5604,26 +5666,21 @@ if test $ac_cv_lbl_dag_api = yes; then echo $ECHO_N "checking dagopts.o... $ECHO_C" >&6 dagopts_obj=no if test -r $dag_tools_dir/dagopts.o; then - - # 2.4.x. + # 2.4.x. dagopts_obj=$dag_tools_dir/dagopts.o - elif test -r $dag_lib_dir/dagopts.o; then - - # 2.5.x. - dagopts_obj=$dag_lib_dir/dagopts.o - - elif test -r $dag_lib_dir/libdag.a; then - - # 2.5.x. + # 2.5.x. + dagopts_obj=$dag_lib_dir/dagopts.o + elif test -r $dag_lib_dir/libdag.a; then + # 2.5.x. ar x $dag_lib_dir/libdag.a dagopts.o if test -r ./dagopts.o; then dagopts_obj=./dagopts.o - fi + fi fi if test $dagopts_obj = no; then - echo "$as_me:$LINENO: result: no (checked $dag_lib_dir $dag_tools_dir $dag_lib_dir/libdag.a)" >&5 + echo "$as_me:$LINENO: result: no (checked $dag_lib_dir $dag_tools_dir $dag_lib_dir/libdag.a)" >&5 echo "${ECHO_T}no (checked $dag_lib_dir $dag_tools_dir $dag_lib_dir/libdag.a)" >&6 ac_cv_lbl_dag_api=no else @@ -5633,32 +5690,27 @@ echo "${ECHO_T}yes ($dagopts_obj)" >&6 fi if test $ac_cv_lbl_dag_api = yes; then - # Under 2.5.x only we need to add dagreg.o. if test -r $dag_include_dir/dagreg.h; then - - echo "$as_me:$LINENO: checking dagreg.o" >&5 + echo "$as_me:$LINENO: checking dagreg.o" >&5 echo $ECHO_N "checking dagreg.o... $ECHO_C" >&6 - dagreg_obj=no - if test -r $dag_lib_dir/dagreg.o; then - - # Object file is ready and waiting. - dagreg_obj=$dag_lib_dir/dagreg.o - - elif test -r $dag_lib_dir/libdag.a; then - - # Extract from libdag.a. + dagreg_obj=no + if test -r $dag_lib_dir/dagreg.o; then + # Object file is ready and waiting. + dagreg_obj=$dag_lib_dir/dagreg.o + elif test -r $dag_lib_dir/libdag.a; then + # Extract from libdag.a. ar x $dag_lib_dir/libdag.a dagreg.o if test -r ./dagreg.o; then - dagreg_obj=./dagreg.o - fi + dagreg_obj=./dagreg.o + fi fi if test $dagreg_obj = no; then - echo "$as_me:$LINENO: result: no (checked $dag_lib_dir $dag_lib_dir/libdag.a)" >&5 + echo "$as_me:$LINENO: result: no (checked $dag_lib_dir $dag_lib_dir/libdag.a)" >&5 echo "${ECHO_T}no (checked $dag_lib_dir $dag_lib_dir/libdag.a)" >&6 ac_cv_lbl_dag_api=no - else + else echo "$as_me:$LINENO: result: yes ($dagreg_obj)" >&5 echo "${ECHO_T}yes ($dagreg_obj)" >&6 fi @@ -5666,7 +5718,6 @@ echo "${ECHO_T}yes ($dagreg_obj)" >&6 fi if test $ac_cv_lbl_dag_api = yes; then - V_INCLS="$V_INCLS -I$dag_include_dir" V_LIBS="$V_LIBS $dagapi_obj $dagopts_obj $dagreg_obj" if test $V_PCAP != dag ; then @@ -5674,7 +5725,8 @@ if test $ac_cv_lbl_dag_api = yes; then fi # See if we can find a general version string. - # Don't need to save and restore LIBS to prevent -ldag being included if there's a found-action (arg 3). + # Don't need to save and restore LIBS to prevent -ldag being + # included if there's a found-action (arg 3). saved_ldflags=$LDFLAGS LDFLAGS="-L$dag_lib_dir" echo "$as_me:$LINENO: checking for dag_attach_stream in -ldag" >&5 @@ -5745,7 +5797,7 @@ 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 "$as_me:$LINENO: result: $dag_version" >&5 echo "${ECHO_T}$dag_version" >&6 cat >>confdefs.h <<\_ACEOF @@ -5756,18 +5808,119 @@ fi if test $ac_cv_lbl_dag_api = no; then if test "$want_dag" = yes; then - # User wanted DAG support but we couldn't find it. + # User wanted DAG support but we couldn't find it. { { echo "$as_me:$LINENO: error: DAG API requested, but not found at $dag_root: use --without-dag" >&5 echo "$as_me: error: DAG API requested, but not found at $dag_root: use --without-dag" >&2;} { (exit 1); exit 1; }; } fi - if test "$V_PCAP" = dag; then - # User requested "dag" capture type but the DAG API wasn't found. - { { echo "$as_me:$LINENO: error: Specifying the capture type as \"dag\" requires the DAG API to be present; use the --with-dag options to specify the location. (Try \"./configure --help\" for more information.)" >&5 + if test "$V_PCAP" = dag; then + # User requested "dag" capture type but the DAG API wasn't + # found. + { { echo "$as_me:$LINENO: error: Specifying the capture type as \"dag\" requires the DAG API to be present; use the --with-dag options to specify the location. (Try \"./configure --help\" for more information.)" >&5 echo "$as_me: error: Specifying the capture type as \"dag\" requires the DAG API to be present; use the --with-dag options to specify the location. (Try \"./configure --help\" for more information.)" >&2;} { (exit 1); exit 1; }; } - fi + fi +fi + + +# Check whether --with-septel or --without-septel was given. +if test "${with_septel+set}" = set; then + withval="$with_septel" + + if test "$withval" = no + then + want_septel=no + elif test "$withval" = yes + then + want_septel=yes + septel_root= + else + want_septel=yes + septel_root=$withval + fi + +else + + # + # Use Septel API if present, otherwise don't + # + want_septel=ifpresent + septel_root=./../septel + +fi; +ac_cv_lbl_septel_api=no +case "$V_PCAP" in +linux|septel) + # + # We support the Septel API if we're on Linux, or if we're building + # a Septel-only libpcap. + # + ;; +*) + # + # If the user explicitly requested Septel, tell them it's not + # supported. + # + # If they expressed no preference, don't include it. + # + if test $want_septel = yes; then + { { echo "$as_me:$LINENO: error: Septel support only available with 'linux' and 'septel' packet capture types" >&5 +echo "$as_me: error: Septel support only available with 'linux' and 'septel' packet capture types" >&2;} + { (exit 1); exit 1; }; } + elif test $want_septel = yes; then + want_septel=no + fi + ;; +esac + +if test "$with_septel" != no; then + echo "$as_me:$LINENO: checking whether we have Septel API" >&5 +echo $ECHO_N "checking whether we have Septel API... $ECHO_C" >&6 + + if test -z "$septel_root"; then + septel_root=$srcdir/../septel + + fi + + septel_tools_dir="$septel_root" + septel_include_dir="$septel_root/INC" + DEF="-DHAVE_SEPTEL_API" + + ac_cv_lbl_septel_api=no + if test -r "$septel_include_dir/msg.h"; then + V_INCLS="$V_INCLS -I$septel_include_dir" + V_DEFS="$V_DEFS $DEF" + V_LIBS="$V_LIBS $septel_tools_dir/asciibin.o $septel_tools_dir/bit2byte.o $septel_tools_dir/confirm.o $septel_tools_dir/fmtmsg.o $septel_tools_dir/gct_unix.o $septel_tools_dir/hqueue.o $septel_tools_dir/ident.o $septel_tools_dir/mem.o $septel_tools_dir/pack.o $septel_tools_dir/parse.o $septel_tools_dir/pool.o $septel_tools_dir/sdlsig.o $septel_tools_dir/strtonum.o $septel_tools_dir/timer.o $septel_tools_dir/trace.o " + + if test "$V_PCAP" != septel ; then + SSRC="pcap-septel.c" + + fi + ac_cv_lbl_septel_api=yes + fi + + echo "$as_me:$LINENO: result: $ac_cv_lbl_septel_api" >&5 +echo "${ECHO_T}$ac_cv_lbl_septel_api" >&6 + if test $ac_cv_lbl_septel_api = no; then + if test "$want_septel" = yes; then + { { echo "$as_me:$LINENO: error: Septel API not found under directory $septel_root; use --without-septel" >&5 +echo "$as_me: error: Septel API not found under directory $septel_root; use --without-septel" >&2;} + { (exit 1); exit 1; }; } + fi + else + +cat >>confdefs.h <<\_ACEOF +#define HAVE_SEPTEL_API 1 +_ACEOF + + fi +fi + +if test "$V_PCAP" = septel -a "$ac_cv_lbl_septel_api" = no; then + { { echo "$as_me:$LINENO: error: Specifying the capture type as 'septel' requires the Septel API to be present; use --with-septel=DIR" >&5 +echo "$as_me: error: Specifying the capture type as 'septel' requires the Septel API to be present; use --with-septel=DIR" >&2;} + { (exit 1); exit 1; }; } fi @@ -5966,7 +6119,7 @@ hpux10.1*) hpux*) cat >>confdefs.h <<\_ACEOF -#define HAVE_HPUX10_20 1 +#define HAVE_HPUX10_20_OR_LATER 1 _ACEOF ;; diff --git a/contrib/libpcap/configure.in b/contrib/libpcap/configure.in index d970fd5..fbc70b8 100755 --- a/contrib/libpcap/configure.in +++ b/contrib/libpcap/configure.in @@ -1,4 +1,4 @@ -dnl @(#) $Header: /tcpdump/master/libpcap/configure.in,v 1.120 2005/03/27 22:26:25 guy Exp $ (LBL) +dnl @(#) $Header: /tcpdump/master/libpcap/configure.in,v 1.120.2.6 2005/06/20 21:37:43 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 $) +AC_REVISION($Revision: 1.120.2.6 $) AC_PREREQ(2.50) AC_INIT(pcap.c) @@ -84,7 +84,7 @@ if test "$ac_cv_func_ether_hostton" = yes; then # # Yes. Does it declare ether_hostton()? # - AC_CHECK_DECLS(ether_hostton, + AC_CHECK_DECL(ether_hostton, [ AC_DEFINE(NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON,, [Define to 1 if netinet/if_ether.h declares `ether_hostton']) @@ -93,6 +93,7 @@ if test "$ac_cv_func_ether_hostton" = yes; then #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> +#include <arpa/inet.h> struct mbuf; struct rtentry; #include <net/if.h> @@ -115,7 +116,7 @@ struct rtentry; # suppress the next test. # unset ac_cv_have_decl_ether_hostton - AC_CHECK_DECLS(ether_hostton, + AC_CHECK_DECL(ether_hostton, [ AC_DEFINE(NETINET_ETHER_H_DECLARES_ETHER_HOSTTON,, [Define to 1 if netinet/ether.h declares `ether_hostton']) @@ -125,6 +126,33 @@ struct rtentry; ]) fi fi + # + # Is ether_hostton() declared? + # + if test "$ac_cv_have_decl_ether_hostton" != yes; then + # + # No, we'll have to declare it ourselves. + # Do we have "struct ether_addr"? + # + AC_CHECK_TYPES(struct ether_addr,,, + [ +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +struct mbuf; +struct rtentry; +#include <net/if.h> +#include <netinet/if_ether.h> + ]) + AC_DEFINE(HAVE_DECL_ETHER_HOSTTON, 0, + [Define to 1 if you have the declaration of `ether_hostton', and to 0 if you +don't.]) + else + AC_DEFINE(HAVE_DECL_ETHER_HOSTTON, 1, + [Define to 1 if you have the declaration of `ether_hostton', and to 0 if you +don't.]) + fi fi dnl to pacify those who hate protochain insn @@ -338,7 +366,11 @@ linux) dag) V_DEFS="$V_DEFS -DDAG_ONLY" - ;; + ;; + +septel) + V_DEFS="$V_DEFS -DSEPTEL_ONLY" + ;; null) AC_MSG_WARN(cannot determine packet capture interface) @@ -359,7 +391,7 @@ fi AC_MSG_RESULT($ac_cv_lbl_proc_net_dev) # Check for Endace DAG card support. -AC_ARG_WITH([dag], [ --with-dag[[=DIR]] include Endace DAG support ("yes", "no" or DIR; default="yes" on BSD and Linux if present)], +AC_ARG_WITH([dag], [ --with-dag[[=DIR]] include Endace DAG support ("yes", "no" or DIR; default="yes" on BSD and Linux if present)], [ if test "$withval" = no then @@ -398,8 +430,8 @@ AC_ARG_WITH([dag-libraries], [ --with-dag-libraries=DIR Endace DAG library dir case "$V_PCAP" in linux|bpf|dag) # - # We support the DAG API on Linux or BSD, or if we're building a - # DAG-only libpcap. + # We support the DAG API if we're on Linux or BSD, or if we're + # building a DAG-only libpcap. # ;; *) @@ -422,7 +454,7 @@ if test "$want_dag" != no; then AC_MSG_CHECKING([whether we have DAG API headers]) - # If necessary, set default paths for DAG API headers and libraries. + # If necessary, set default paths for DAG API headers and libraries. if test -z "$dag_root"; then dag_root=/usr/local fi @@ -442,7 +474,7 @@ if test "$want_dag" != no; then if test -r $dag_include_dir/dagapi.h; then ac_cv_lbl_dag_api=yes fi - AC_MSG_RESULT([$ac_cv_lbl_dag_api ($dag_include_dir)]) + AC_MSG_RESULT([$ac_cv_lbl_dag_api ($dag_include_dir)]) fi if test $ac_cv_lbl_dag_api = yes; then @@ -450,30 +482,25 @@ if test $ac_cv_lbl_dag_api = yes; then AC_MSG_CHECKING([dagapi.o]) dagapi_obj=no if test -r $dag_tools_dir/dagapi.o; then - - # 2.4.x. + # 2.4.x. dagapi_obj=$dag_tools_dir/dagapi.o - elif test -r $dag_lib_dir/dagapi.o; then - - # 2.5.x. - dagapi_obj=$dag_lib_dir/dagapi.o - - elif test -r $dag_lib_dir/libdag.a; then - - # 2.5.x. + # 2.5.x. + dagapi_obj=$dag_lib_dir/dagapi.o + elif test -r $dag_lib_dir/libdag.a; then + # 2.5.x. ar x $dag_lib_dir/libdag.a dagapi.o if test -r ./dagapi.o; then dagapi_obj=./dagapi.o fi - fi + fi if test $dagapi_obj = no; then - AC_MSG_RESULT([no (checked $dag_lib_dir $dag_tools_dir $dag_lib_dir/libdag.a)]) + AC_MSG_RESULT([no (checked $dag_lib_dir $dag_tools_dir $dag_lib_dir/libdag.a)]) ac_cv_lbl_dag_api=no else AC_MSG_RESULT([yes ($dagapi_obj)]) - fi + fi fi if test $ac_cv_lbl_dag_api = yes; then @@ -481,26 +508,21 @@ if test $ac_cv_lbl_dag_api = yes; then AC_MSG_CHECKING([dagopts.o]) dagopts_obj=no if test -r $dag_tools_dir/dagopts.o; then - - # 2.4.x. + # 2.4.x. dagopts_obj=$dag_tools_dir/dagopts.o - elif test -r $dag_lib_dir/dagopts.o; then - - # 2.5.x. - dagopts_obj=$dag_lib_dir/dagopts.o - - elif test -r $dag_lib_dir/libdag.a; then - - # 2.5.x. + # 2.5.x. + dagopts_obj=$dag_lib_dir/dagopts.o + elif test -r $dag_lib_dir/libdag.a; then + # 2.5.x. ar x $dag_lib_dir/libdag.a dagopts.o if test -r ./dagopts.o; then dagopts_obj=./dagopts.o - fi + fi fi if test $dagopts_obj = no; then - AC_MSG_RESULT([no (checked $dag_lib_dir $dag_tools_dir $dag_lib_dir/libdag.a)]) + AC_MSG_RESULT([no (checked $dag_lib_dir $dag_tools_dir $dag_lib_dir/libdag.a)]) ac_cv_lbl_dag_api=no else AC_MSG_RESULT([yes ($dagopts_obj)]) @@ -508,37 +530,31 @@ if test $ac_cv_lbl_dag_api = yes; then fi if test $ac_cv_lbl_dag_api = yes; then - # Under 2.5.x only we need to add dagreg.o. if test -r $dag_include_dir/dagreg.h; then - - AC_MSG_CHECKING([dagreg.o]) - dagreg_obj=no - if test -r $dag_lib_dir/dagreg.o; then - - # Object file is ready and waiting. - dagreg_obj=$dag_lib_dir/dagreg.o - - elif test -r $dag_lib_dir/libdag.a; then - - # Extract from libdag.a. + AC_MSG_CHECKING([dagreg.o]) + dagreg_obj=no + if test -r $dag_lib_dir/dagreg.o; then + # Object file is ready and waiting. + dagreg_obj=$dag_lib_dir/dagreg.o + elif test -r $dag_lib_dir/libdag.a; then + # Extract from libdag.a. ar x $dag_lib_dir/libdag.a dagreg.o if test -r ./dagreg.o; then - dagreg_obj=./dagreg.o - fi + dagreg_obj=./dagreg.o + fi fi if test $dagreg_obj = no; then - AC_MSG_RESULT([no (checked $dag_lib_dir $dag_lib_dir/libdag.a)]) + AC_MSG_RESULT([no (checked $dag_lib_dir $dag_lib_dir/libdag.a)]) ac_cv_lbl_dag_api=no - else + else AC_MSG_RESULT([yes ($dagreg_obj)]) fi fi fi if test $ac_cv_lbl_dag_api = yes; then - V_INCLS="$V_INCLS -I$dag_include_dir" V_LIBS="$V_LIBS $dagapi_obj $dagopts_obj $dagreg_obj" if test $V_PCAP != dag ; then @@ -546,7 +562,8 @@ if test $ac_cv_lbl_dag_api = yes; then fi # See if we can find a general version string. - # Don't need to save and restore LIBS to prevent -ldag being included if there's a found-action (arg 3). + # Don't need to save and restore LIBS to prevent -ldag being + # included if there's a found-action (arg 3). saved_ldflags=$LDFLAGS LDFLAGS="-L$dag_lib_dir" AC_CHECK_LIB([dag], [dag_attach_stream], [dag_version="2.5.x"], [dag_version="2.4.x"]) @@ -557,20 +574,103 @@ if test $ac_cv_lbl_dag_api = yes; then if test -r "$dag_root/VERSION"; then dag_version="`cat $dag_root/VERSION`" fi - AC_MSG_RESULT([$dag_version]) + AC_MSG_RESULT([$dag_version]) AC_DEFINE(HAVE_DAG_API, 1, [define if you have the DAG API]) fi if test $ac_cv_lbl_dag_api = no; then if test "$want_dag" = yes; then - # User wanted DAG support but we couldn't find it. + # User wanted DAG support but we couldn't find it. AC_MSG_ERROR([DAG API requested, but not found at $dag_root: use --without-dag]) fi - if test "$V_PCAP" = dag; then - # User requested "dag" capture type but the DAG API wasn't found. - AC_MSG_ERROR([Specifying the capture type as "dag" requires the DAG API to be present; use the --with-dag options to specify the location. (Try "./configure --help" for more information.)]) - fi + if test "$V_PCAP" = dag; then + # User requested "dag" capture type but the DAG API wasn't + # found. + AC_MSG_ERROR([Specifying the capture type as "dag" requires the DAG API to be present; use the --with-dag options to specify the location. (Try "./configure --help" for more information.)]) + fi +fi + +AC_ARG_WITH(septel, [ --with-septel[[=DIR]] include Septel support (located in directory DIR, if supplied). [default=yes, on Linux, if present]], +[ + if test "$withval" = no + then + want_septel=no + elif test "$withval" = yes + then + want_septel=yes + septel_root= + else + want_septel=yes + septel_root=$withval + fi +],[ + # + # Use Septel API if present, otherwise don't + # + want_septel=ifpresent + septel_root=./../septel +]) +ac_cv_lbl_septel_api=no +case "$V_PCAP" in +linux|septel) + # + # We support the Septel API if we're on Linux, or if we're building + # a Septel-only libpcap. + # + ;; +*) + # + # If the user explicitly requested Septel, tell them it's not + # supported. + # + # If they expressed no preference, don't include it. + # + if test $want_septel = yes; then + AC_MSG_ERROR(Septel support only available with 'linux' and 'septel' packet capture types) + elif test $want_septel = yes; then + want_septel=no + fi + ;; +esac + +if test "$with_septel" != no; then + AC_MSG_CHECKING(whether we have Septel API) + + if test -z "$septel_root"; then + septel_root=$srcdir/../septel + + fi + + septel_tools_dir="$septel_root" + septel_include_dir="$septel_root/INC" + DEF="-DHAVE_SEPTEL_API" + + ac_cv_lbl_septel_api=no + if test -r "$septel_include_dir/msg.h"; then + V_INCLS="$V_INCLS -I$septel_include_dir" + V_DEFS="$V_DEFS $DEF" + V_LIBS="$V_LIBS $septel_tools_dir/asciibin.o $septel_tools_dir/bit2byte.o $septel_tools_dir/confirm.o $septel_tools_dir/fmtmsg.o $septel_tools_dir/gct_unix.o $septel_tools_dir/hqueue.o $septel_tools_dir/ident.o $septel_tools_dir/mem.o $septel_tools_dir/pack.o $septel_tools_dir/parse.o $septel_tools_dir/pool.o $septel_tools_dir/sdlsig.o $septel_tools_dir/strtonum.o $septel_tools_dir/timer.o $septel_tools_dir/trace.o " + + if test "$V_PCAP" != septel ; then + SSRC="pcap-septel.c" + + fi + ac_cv_lbl_septel_api=yes + fi + + AC_MSG_RESULT($ac_cv_lbl_septel_api) + if test $ac_cv_lbl_septel_api = no; then + if test "$want_septel" = yes; then + AC_MSG_ERROR(Septel API not found under directory $septel_root; use --without-septel) + fi + else + AC_DEFINE(HAVE_SEPTEL_API, 1, [define if you have a Septel API]) + fi +fi + +if test "$V_PCAP" = septel -a "$ac_cv_lbl_septel_api" = no; then + AC_MSG_ERROR(Specifying the capture type as 'septel' requires the Septel API to be present; use --with-septel=DIR) fi @@ -617,7 +717,7 @@ hpux*) dnl XXX - DYEXT should be set to "sl" if this is building dnl for 32-bit PA-RISC, but should be left as "so" for dnl 64-bit PA-RISC or, I suspect, IA-64. - AC_DEFINE(HAVE_HPUX10_20,1,[on HP-UX 10.20]) + AC_DEFINE(HAVE_HPUX10_20_OR_LATER,1,[on HP-UX 10.20 or later]) ;; sinix*) diff --git a/contrib/libpcap/fad-getad.c b/contrib/libpcap/fad-getad.c index e9ec409..58305d5 100644 --- a/contrib/libpcap/fad-getad.c +++ b/contrib/libpcap/fad-getad.c @@ -34,7 +34,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/fad-getad.c,v 1.10 2004/11/04 07:26:04 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/fad-getad.c,v 1.10.2.1 2005/04/10 18:04:49 hannes Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -47,9 +47,11 @@ static const char rcsid[] _U_ = #include <net/if.h> +#include <ctype.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <ifaddrs.h> #include "pcap-int.h" @@ -137,6 +139,7 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) struct sockaddr *addr, *netmask, *broadaddr, *dstaddr; size_t addr_size, broadaddr_size, dstaddr_size; int ret = 0; + char *p, *q; /* * Get the list of interface addresses. @@ -215,6 +218,35 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) } /* + * If this entry has a colon followed by a number at + * the end, we assume it's a logical interface. Those + * are just the way you assign multiple IP addresses to + * a real interface on Linux, so an entry for a logical + * interface should be treated like the entry for the + * real interface; we do that by stripping off the ":" + * and the number. + * + * XXX - should we do this only on Linux? + */ + p = strchr(ifa->ifa_name, ':'); + if (p != NULL) { + /* + * We have a ":"; is it followed by a number? + */ + q = p + 1; + while (isdigit((unsigned char)*q)) + q++; + if (*q == '\0') { + /* + * All digits after the ":" until the end. + * Strip off the ":" and everything after + * it. + */ + *p = '\0'; + } + } + + /* * Add information for this address to the list. */ if (add_addr_to_iflist(&devlist, ifa->ifa_name, diff --git a/contrib/libpcap/fad-gifc.c b/contrib/libpcap/fad-gifc.c index 4ed02f9..985d2c0 100644 --- a/contrib/libpcap/fad-gifc.c +++ b/contrib/libpcap/fad-gifc.c @@ -34,7 +34,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/fad-gifc.c,v 1.8 2005/01/29 10:34:04 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/fad-gifc.c,v 1.8.2.2 2005/06/29 06:43:31 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -102,6 +102,27 @@ struct rtentry; /* declarations in <net/if.h> */ #endif /* HAVE_SOCKADDR_SA_LEN */ #endif /* SA_LEN */ +/* + * This is also fun. + * + * There is no ioctl that returns the amount of space required for all + * the data that SIOCGIFCONF could return, and if a buffer is supplied + * that's not large enough for all the data SIOCGIFCONF could return, + * on at least some platforms it just returns the data that'd fit with + * no indication that there wasn't enough room for all the data, much + * less an indication of how much more room is required. + * + * The only way to ensure that we got all the data is to pass a buffer + * large enough that the amount of space in the buffer *not* filled in + * is greater than the largest possible entry. + * + * We assume that's "sizeof(ifreq.ifr_name)" plus 255, under the assumption + * that no address is more than 255 bytes (on systems where the "sa_len" + * field in a "struct sockaddr" is 1 byte, e.g. newer BSDs, that's the + * case, and addresses are unlikely to be bigger than that in any case). + */ +#define MAX_SA_LEN 255 + #ifdef HAVE_PROC_NET_DEV /* * Get from "/proc/net/dev" all interfaces listed there; if they're @@ -255,7 +276,7 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) struct ifconf ifc; char *buf = NULL; unsigned buf_size; -#ifdef HAVE_SOLARIS +#if defined (HAVE_SOLARIS) || defined (HAVE_HPUX10_20_OR_LATER) char *p, *q; #endif struct ifreq ifrflags, ifrnetmask, ifrbroadaddr, ifrdstaddr; @@ -275,9 +296,10 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) /* * Start with an 8K buffer, and keep growing the buffer until - * we get the entire interface list or fail to get it for some - * reason other than EINVAL (which is presumed here to mean - * "buffer is too small"). + * we have more than "sizeof(ifrp->ifr_name) + MAX_SA_LEN" + * bytes left over in the buffer or we fail to get the + * interface list for some reason other than EINVAL (which is + * presumed here to mean "buffer is too small"). */ buf_size = 8192; for (;;) { @@ -300,7 +322,8 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) free(buf); return (-1); } - if (ifc.ifc_len < buf_size) + if (ifc.ifc_len < buf_size && + (buf_size - ifc.ifc_len) > sizeof(ifrp->ifr_name) + MAX_SA_LEN) break; free(buf); buf_size *= 2; @@ -474,7 +497,7 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) dstaddr_size = 0; } -#ifdef HAVE_SOLARIS +#if defined (HAVE_SOLARIS) || defined (HAVE_HPUX10_20_OR_LATER) /* * If this entry has a colon followed by a number at * the end, it's a logical interface. Those are just diff --git a/contrib/libpcap/fad-glifc.c b/contrib/libpcap/fad-glifc.c index 8ad7a6c..8a86a3d 100644 --- a/contrib/libpcap/fad-glifc.c +++ b/contrib/libpcap/fad-glifc.c @@ -34,7 +34,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/fad-glifc.c,v 1.5 2005/01/29 10:34:04 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/fad-glifc.c,v 1.5.2.1 2005/04/19 00:54:16 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -326,7 +326,7 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) * be treated like the entry for the real interface; * we do that by stripping off the ":" and the number. */ - p = strchr(ifrp->ifr_name, ':'); + p = strchr(ifrp->lifr_name, ':'); if (p != NULL) { /* * We have a ":"; is it followed by a number? diff --git a/contrib/libpcap/gencode.c b/contrib/libpcap/gencode.c index 9fff3cb..33ad950 100644 --- a/contrib/libpcap/gencode.c +++ b/contrib/libpcap/gencode.c @@ -21,7 +21,7 @@ */ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221 2005/03/27 22:10:23 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221.2.24 2005/06/20 21:52:53 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -101,7 +101,7 @@ static jmp_buf top_ctx; static pcap_t *bpf_pcap; /* Hack for updating VLAN, MPLS offsets. */ -static u_int orig_linktype = -1U, orig_nl = -1U, orig_nl_nosnap = -1U; +static u_int orig_linktype = -1U, orig_nl = -1U; /* XXX */ #ifdef PCAP_FDDIPAD @@ -111,7 +111,6 @@ static int pcap_fddipad; /* VARARGS */ void bpf_error(const char *fmt, ...) - { va_list ap; @@ -132,6 +131,19 @@ static void free_reg(int); static struct block *root; /* + * Value passed to gen_load_a() to indicate what the offset argument + * is relative to. + */ +enum e_offrel { + OR_PACKET, /* relative to the beginning of the packet */ + OR_LINK, /* relative to the link-layer header */ + OR_NET, /* relative to the network-layer header */ + OR_NET_NOSNAP, /* relative to the network-layer header, with no SNAP header at the link layer */ + OR_TRAN_IPV4, /* relative to the transport-layer header, with IPv4 network layer */ + OR_TRAN_IPV6 /* relative to the transport-layer header, with IPv6 network layer */ +}; + +/* * We divy out chunks of memory rather than call malloc each time so * we don't have to worry about leaking memory. It's probably * not a big deal if all this memory was wasted but if this ever @@ -158,20 +170,30 @@ static inline void syntax(void); static void backpatch(struct block *, struct block *); static void merge(struct block *, struct block *); -static struct block *gen_cmp(u_int, u_int, bpf_int32); -static struct block *gen_cmp_gt(u_int, u_int, bpf_int32); -static struct block *gen_mcmp(u_int, u_int, bpf_int32, bpf_u_int32); -static struct block *gen_bcmp(u_int, u_int, const u_char *); -static struct block *gen_ncmp(bpf_u_int32, bpf_u_int32, bpf_u_int32, - bpf_u_int32, bpf_u_int32, int); +static struct block *gen_cmp(enum e_offrel, u_int, u_int, bpf_int32); +static struct block *gen_cmp_gt(enum e_offrel, u_int, u_int, bpf_int32); +static struct block *gen_cmp_ge(enum e_offrel, u_int, u_int, bpf_int32); +static struct block *gen_cmp_lt(enum e_offrel, u_int, u_int, bpf_int32); +static struct block *gen_cmp_le(enum e_offrel, u_int, u_int, bpf_int32); +static struct block *gen_mcmp(enum e_offrel, u_int, u_int, bpf_int32, + bpf_u_int32); +static struct block *gen_bcmp(enum e_offrel, u_int, u_int, const u_char *); +static struct block *gen_ncmp(enum e_offrel, bpf_u_int32, bpf_u_int32, + bpf_u_int32, bpf_u_int32, int, bpf_int32); +static struct slist *gen_load_llrel(u_int, u_int); +static struct slist *gen_load_a(enum e_offrel, u_int, u_int); +static struct slist *gen_loadx_iphdrlen(void); static struct block *gen_uncond(int); static inline struct block *gen_true(void); static inline struct block *gen_false(void); static struct block *gen_ether_linktype(int); static struct block *gen_linux_sll_linktype(int); +static void insert_radiotap_load_llprefixlen(struct block *); +static void insert_load_llprefixlen(struct block *); +static struct slist *gen_llprefixlen(void); static struct block *gen_linktype(int); static struct block *gen_snap(bpf_u_int32, bpf_u_int32, u_int); -static struct block *gen_llc(int); +static struct block *gen_llc_linktype(int); static struct block *gen_hostop(bpf_u_int32, bpf_u_int32, int, int, u_int, u_int); #ifdef INET6 static struct block *gen_hostop6(struct in6_addr *, struct in6_addr *, int, int, u_int, u_int); @@ -182,7 +204,7 @@ static struct block *gen_fhostop(const u_char *, int); static struct block *gen_thostop(const u_char *, int); static struct block *gen_wlanhostop(const u_char *, int); static struct block *gen_ipfchostop(const u_char *, int); -static struct block *gen_dnhostop(bpf_u_int32, int, u_int); +static struct block *gen_dnhostop(bpf_u_int32, int); static struct block *gen_host(bpf_u_int32, bpf_u_int32, int, int); #ifdef INET6 static struct block *gen_host6(struct in6_addr *, struct in6_addr *, int, int); @@ -192,14 +214,20 @@ static struct block *gen_gateway(const u_char *, bpf_u_int32 **, int, int); #endif static struct block *gen_ipfrag(void); static struct block *gen_portatom(int, bpf_int32); +static struct block *gen_portrangeatom(int, bpf_int32, bpf_int32); #ifdef INET6 static struct block *gen_portatom6(int, bpf_int32); +static struct block *gen_portrangeatom6(int, bpf_int32, bpf_int32); #endif struct block *gen_portop(int, int, int); static struct block *gen_port(int, int, int); +struct block *gen_portrangeop(int, int, int, int); +static struct block *gen_portrange(int, int, int, int); #ifdef INET6 struct block *gen_portop6(int, int, int); static struct block *gen_port6(int, int, int); +struct block *gen_portrangeop6(int, int, int, int); +static struct block *gen_portrange6(int, int, int, int); #endif static int lookup_proto(const char *, int); static struct block *gen_protochain(int, int, int); @@ -451,6 +479,23 @@ finish_parse(p) p->sense = !p->sense; backpatch(p, gen_retblk(0)); root = p->head; + + /* + * Insert before the statements of the first (root) block any + * statements needed to load the lengths of any variable-length + * headers into registers. + * + * XXX - a fancier strategy would be to insert those before the + * statements of all blocks that use those lengths and that + * have no predecessors that use them, so that we only compute + * the lengths if we need them. There might be even better + * approaches than that. However, 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. + */ + insert_load_llprefixlen(root); } void @@ -484,60 +529,63 @@ gen_not(b) } static struct block * -gen_cmp(offset, size, v) +gen_cmp(offrel, offset, size, v) + enum e_offrel offrel; u_int offset, size; bpf_int32 v; { - struct slist *s; - struct block *b; - - s = new_stmt(BPF_LD|BPF_ABS|size); - s->s.k = offset; - - b = new_block(JMP(BPF_JEQ)); - b->stmts = s; - b->s.k = v; - - return b; + return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JEQ, 0, v); } static struct block * -gen_cmp_gt(offset, size, v) +gen_cmp_gt(offrel, offset, size, v) + enum e_offrel offrel; u_int offset, size; bpf_int32 v; { - struct slist *s; - struct block *b; + return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGT, 0, v); +} - s = new_stmt(BPF_LD|BPF_ABS|size); - s->s.k = offset; +static struct block * +gen_cmp_ge(offrel, offset, size, v) + enum e_offrel offrel; + u_int offset, size; + bpf_int32 v; +{ + return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGE, 0, v); +} - b = new_block(JMP(BPF_JGT)); - b->stmts = s; - b->s.k = v; +static struct block * +gen_cmp_lt(offrel, offset, size, v) + enum e_offrel offrel; + u_int offset, size; + bpf_int32 v; +{ + return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGE, 1, v); +} - return b; +static struct block * +gen_cmp_le(offrel, offset, size, v) + enum e_offrel offrel; + u_int offset, size; + bpf_int32 v; +{ + return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGT, 1, v); } static struct block * -gen_mcmp(offset, size, v, mask) +gen_mcmp(offrel, offset, size, v, mask) + enum e_offrel offrel; u_int offset, size; bpf_int32 v; bpf_u_int32 mask; { - struct block *b = gen_cmp(offset, size, v); - struct slist *s; - - if (mask != 0xffffffff) { - s = new_stmt(BPF_ALU|BPF_AND|BPF_K); - s->s.k = mask; - b->stmts->next = s; - } - return b; + return gen_ncmp(offrel, offset, size, mask, BPF_JEQ, 0, v); } static struct block * -gen_bcmp(offset, size, v) +gen_bcmp(offrel, offset, size, v) + enum e_offrel offrel; register u_int offset, size; register const u_char *v; { @@ -549,7 +597,7 @@ gen_bcmp(offset, size, v) bpf_int32 w = ((bpf_int32)p[0] << 24) | ((bpf_int32)p[1] << 16) | ((bpf_int32)p[2] << 8) | p[3]; - tmp = gen_cmp(offset + size - 4, BPF_W, w); + tmp = gen_cmp(offrel, offset + size - 4, BPF_W, w); if (b != NULL) gen_and(b, tmp); b = tmp; @@ -559,14 +607,14 @@ gen_bcmp(offset, size, v) register const u_char *p = &v[size - 2]; bpf_int32 w = ((bpf_int32)p[0] << 8) | p[1]; - tmp = gen_cmp(offset + size - 2, BPF_H, w); + tmp = gen_cmp(offrel, offset + size - 2, BPF_H, w); if (b != NULL) gen_and(b, tmp); b = tmp; size -= 2; } if (size > 0) { - tmp = gen_cmp(offset, BPF_B, (bpf_int32)v[0]); + tmp = gen_cmp(offrel, offset, BPF_B, (bpf_int32)v[0]); if (b != NULL) gen_and(b, tmp); b = tmp; @@ -574,25 +622,33 @@ gen_bcmp(offset, size, v) return b; } +/* + * AND the field of size "size" at offset "offset" relative to the header + * specified by "offrel" with "mask", and compare it with the value "v" + * with the test specified by "jtype"; if "reverse" is true, the test + * should test the opposite of "jtype". + */ static struct block * -gen_ncmp(datasize, offset, mask, jtype, jvalue, reverse) - bpf_u_int32 datasize, offset, mask, jtype, jvalue; +gen_ncmp(offrel, offset, size, mask, jtype, reverse, v) + enum e_offrel offrel; + bpf_int32 v; + bpf_u_int32 offset, size, mask, jtype; int reverse; { - struct slist *s; + struct slist *s, *s2; struct block *b; - s = new_stmt(BPF_LD|datasize|BPF_ABS); - s->s.k = offset; + s = gen_load_a(offrel, offset, size); if (mask != 0xffffffff) { - s->next = new_stmt(BPF_ALU|BPF_AND|BPF_K); - s->next->s.k = mask; + s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K); + s2->s.k = mask; + sappend(s, s2); } b = new_block(JMP(jtype)); b->stmts = s; - b->s.k = jvalue; + b->s.k = v; if (reverse && (jtype == BPF_JGT || jtype == BPF_JGE)) gen_not(b); return b; @@ -600,8 +656,21 @@ gen_ncmp(datasize, offset, mask, jtype, jvalue, reverse) /* * Various code constructs need to know the layout of the data link - * layer. These variables give the necessary offsets. + * 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. + * It's usually 0, except for 802.11 with a fixed-length radio header. + */ +static u_int off_ll; /* * This is the offset of the beginning of the MAC-layer header. @@ -649,6 +718,14 @@ static u_int off_vci; static u_int off_proto; /* + * These are offsets for the MTP3 fields. + */ +static u_int off_sio; +static u_int off_opc; +static u_int off_dpc; +static u_int off_sls; + +/* * This is the offset of the first byte after the ATM pseudo_header, * or -1 if there is no ATM pseudo-header. */ @@ -701,9 +778,20 @@ init_linktype(p) off_proto = -1; off_payload = -1; + off_sio = -1; + off_opc = -1; + off_dpc = -1; + off_sls = -1; + + /* + * Also assume it's not 802.11 with a fixed-length radio header. + */ + off_ll = 0; + orig_linktype = -1; orig_nl = -1; - orig_nl_nosnap = -1; + + reg_ll_size = -1; switch (linktype) { @@ -862,6 +950,7 @@ init_linktype(p) * XXX - same variable-length header problem; at least * the Prism header is fixed-length. */ + off_ll = 144; off_linktype = 144+24; off_nl = 144+32; /* Prism+802.11+802.2+SNAP */ off_nl_nosnap = 144+27; /* Prism+802.11+802.2 */ @@ -882,6 +971,7 @@ init_linktype(p) * number at an offset of 4 from the beginning * of the radio header. */ + off_ll = 64; off_linktype = 64+24; off_nl = 64+32; /* Radio+802.11+802.2+SNAP */ off_nl_nosnap = 64+27; /* Radio+802.11+802.2 */ @@ -893,21 +983,14 @@ init_linktype(p) * the 802.11 header, containing a bunch of additional * information including radio-level information. * - * XXX - same variable-length header problem, only - * even *more* so; this header is also variable-length, - * with the length being the 16-bit number at an offset - * of 2 from the beginning of the radio header, and it's - * device-dependent (different devices might supply - * different amounts of information), so we can't even - * assume a fixed length for the current version of the - * header. - * - * Therefore, currently, only raw "link[N:M]" filtering is - * supported. + * 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. */ - off_linktype = -1; - off_nl = -1; - off_nl_nosnap = -1; + off_linktype = 24; + off_nl = 32; /* 802.11+802.2+SNAP */ + off_nl_nosnap = 27; /* 802.11+802.2 */ return; case DLT_ATM_RFC1483: @@ -915,6 +998,13 @@ init_linktype(p) /* * assume routed, non-ISO PDUs * (i.e., LLC = 0xAA-AA-03, OUT = 0x00-00-00) + * + * XXX - what about ISO PDUs, e.g. CLNP, ISIS, ESIS, + * or PPP with the PPP NLPID (e.g., PPPoA)? The + * latter would presumably be treated the way PPPoE + * should be, so you can do "pppoe and udp port 2049" + * or "pppoa and tcp port 80" and have it check for + * PPPo{A,E} and a PPP protocol of IP and.... */ off_linktype = 0; off_nl = 8; /* 802.2+SNAP */ @@ -989,7 +1079,7 @@ init_linktype(p) case DLT_APPLE_IP_OVER_IEEE1394: off_linktype = 16; off_nl = 18; - off_nl_nosnap = 0; /* no 802.2 LLC */ + off_nl_nosnap = 18; /* no 802.2 LLC */ return; case DLT_LINUX_IRDA: @@ -1018,16 +1108,16 @@ init_linktype(p) case DLT_PFLOG: off_linktype = 0; - /* XXX read from header? */ + /* XXX read this from pf.h? */ off_nl = PFLOG_HDRLEN; - off_nl_nosnap = PFLOG_HDRLEN; + off_nl_nosnap = PFLOG_HDRLEN; /* no 802.2 LLC */ return; case DLT_JUNIPER_MLFR: case DLT_JUNIPER_MLPPP: off_linktype = 4; off_nl = 4; - off_nl_nosnap = -1; + off_nl_nosnap = -1; /* no 802.2 LLC */ return; case DLT_JUNIPER_ATM1: @@ -1042,6 +1132,54 @@ init_linktype(p) off_nl_nosnap = 18; return; + /* frames captured on a Juniper PPPoE service PIC + * contain raw ethernet frames */ + case DLT_JUNIPER_PPPOE: + off_linktype = 16; + off_nl = 18; /* Ethernet II */ + off_nl_nosnap = 21; /* 802.3+802.2 */ + return; + + case DLT_JUNIPER_PPPOE_ATM: + off_linktype = 4; + off_nl = 6; + 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 */ + return; + + case DLT_JUNIPER_ES: + off_linktype = 6; + off_nl = -1; /* not really a network layer but raw IP adresses */ + off_nl_nosnap = -1; /* no 802.2 LLC */ + return; + + case DLT_JUNIPER_MONITOR: + off_linktype = 12; + off_nl = 12; /* raw IP/IP6 header */ + off_nl_nosnap = -1; /* no 802.2 LLC */ + return; + + case DLT_JUNIPER_SERVICES: + off_linktype = 12; + off_nl = -1; /* L3 proto location dep. on cookie type */ + off_nl_nosnap = -1; /* no 802.2 LLC */ + return; + + case DLT_MTP2: + off_sio = 3; + off_opc = 4; + off_dpc = 4; + off_sls = 7; + off_linktype = -1; + off_nl = -1; + off_nl_nosnap = -1; + return; + #ifdef DLT_PFSYNC case DLT_PFSYNC: off_linktype = -1; @@ -1049,11 +1187,158 @@ init_linktype(p) off_nl_nosnap = 4; return; #endif + + case DLT_LINUX_LAPD: + /* + * Currently, only raw "link[N:M]" filtering is supported. + */ + off_linktype = -1; + off_nl = -1; + off_nl_nosnap = -1; + return; } bpf_error("unknown data link type %d", linktype); /* NOTREACHED */ } +/* + * Load a value relative to the beginning of the link-layer header. + * The link-layer header doesn't necessarily begin at the beginning + * of the packet data; there might be a variable-length prefix containing + * radio information. + */ +static struct slist * +gen_load_llrel(offset, size) + u_int offset, size; +{ + struct slist *s, *s2; + + s = gen_llprefixlen(); + + /* + * If "s" is non-null, it has code to arrange that the X register + * contains the length of the prefix preceding the link-layer + * header. + */ + if (s != NULL) { + s2 = new_stmt(BPF_LD|BPF_IND|size); + s2->s.k = offset; + sappend(s, s2); + } else { + s = new_stmt(BPF_LD|BPF_ABS|size); + s->s.k = offset; + } + return s; +} + +/* + * Load a value relative to the beginning of the specified header. + */ +static struct slist * +gen_load_a(offrel, offset, size) + enum e_offrel offrel; + u_int offset, size; +{ + struct slist *s, *s2; + + switch (offrel) { + + case OR_PACKET: + s = gen_load_llrel(offset, size); + break; + + case OR_LINK: + s = gen_load_llrel(off_ll + offset, size); + break; + + case OR_NET: + s = gen_load_llrel(off_nl + offset, size); + break; + + case OR_NET_NOSNAP: + s = gen_load_llrel(off_nl_nosnap + offset, size); + break; + + case OR_TRAN_IPV4: + /* + * Load the X register with the length of the IPv4 header, + * in bytes. + */ + s = gen_loadx_iphdrlen(); + + /* + * Load the item at {length of the link-layer header} + + * {length of the IPv4 header} + {specified offset}. + */ + s2 = new_stmt(BPF_LD|BPF_IND|size); + s2->s.k = off_nl + offset; + sappend(s, s2); + break; + + case OR_TRAN_IPV6: + s = gen_load_llrel(off_nl + 40 + offset, size); + break; + + default: + abort(); + return NULL; + } + return s; +} + +/* + * Generate code to load into the X register the sum of the length of + * the IPv4 header and any variable-length header preceding the link-layer + * header. + */ +static struct slist * +gen_loadx_iphdrlen() +{ + struct slist *s, *s2; + + s = gen_llprefixlen(); + 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. + * The 4*([k]&0xf) addressing mode can't be used, as we + * don't have a constant offset, so we have to load the + * value in question into the A register and add to it + * the value from the X register. + */ + s2 = new_stmt(BPF_LD|BPF_IND|BPF_B); + s2->s.k = off_nl; + sappend(s, s2); + s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K); + s2->s.k = 0xf; + sappend(s, s2); + s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K); + s2->s.k = 2; + sappend(s, s2); + + /* + * The A register now contains the length of the + * IP header. We need to add to it the length + * of the prefix preceding the link-layer + * header, 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; if there's a fixed-length + * header preceding it, its length is included in + * the off_ variables, so it doesn't need to be added. + */ + s = new_stmt(BPF_LDX|BPF_MSH|BPF_B); + s->s.k = off_nl; + } + return s; +} + static struct block * gen_uncond(rsense) int rsense; @@ -1089,6 +1374,15 @@ gen_false() #define SWAPLONG(y) \ ((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff)) +/* + * Generate code to match a particular packet type. + * + * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP + * value, if <= ETHERMTU. We use that to determine whether to + * match the type/length field or to check the type/length field for + * a value <= ETHERMTU to see whether it's a type field and then do + * the appropriate test. + */ static struct block * gen_ether_linktype(proto) register int proto; @@ -1098,38 +1392,24 @@ gen_ether_linktype(proto) switch (proto) { case LLCSAP_ISONS: - /* - * OSI protocols always use 802.2 encapsulation. - * XXX - should we check both the DSAP and the - * SSAP, like this, or should we check just the - * DSAP? - */ - b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU); - gen_not(b0); - b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32) - ((LLCSAP_ISONS << 8) | LLCSAP_ISONS)); - gen_and(b0, b1); - return b1; - case LLCSAP_IP: - b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU); - gen_not(b0); - b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32) - ((LLCSAP_IP << 8) | LLCSAP_IP)); - gen_and(b0, b1); - return b1; - case LLCSAP_NETBEUI: /* - * NetBEUI always uses 802.2 encapsulation. + * OSI protocols and NetBEUI always use 802.2 encapsulation, + * so we check the DSAP and SSAP. + * + * LLCSAP_IP checks for IP-over-802.2, rather + * than IP-over-Ethernet or IP-over-SNAP. + * * XXX - should we check both the DSAP and the * SSAP, like this, or should we check just the - * DSAP? + * DSAP, as we do for other types <= ETHERMTU + * (i.e., other SAP values)? */ - b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU); + b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU); gen_not(b0); - b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32) - ((LLCSAP_NETBEUI << 8) | LLCSAP_NETBEUI)); + b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_H, (bpf_int32) + ((proto << 8) | proto)); gen_and(b0, b1); return b1; @@ -1166,8 +1446,10 @@ 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(off_linktype + 2, BPF_B, (bpf_int32)LLCSAP_IPX); - b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)0xFFFF); + 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); gen_or(b0, b1); /* @@ -1181,7 +1463,7 @@ gen_ether_linktype(proto) * Now we generate code to check for 802.3 * frames in general. */ - b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU); + b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU); gen_not(b0); /* @@ -1197,7 +1479,8 @@ gen_ether_linktype(proto) * do that before checking for the other frame * types. */ - b0 = gen_cmp(off_linktype, BPF_H, (bpf_int32)ETHERTYPE_IPX); + b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, + (bpf_int32)ETHERTYPE_IPX); gen_or(b0, b1); return b1; @@ -1213,7 +1496,7 @@ gen_ether_linktype(proto) * we check for an Ethernet type field less than * 1500, which means it's an 802.3 length field. */ - b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU); + b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU); gen_not(b0); /* @@ -1238,7 +1521,7 @@ gen_ether_linktype(proto) * phase 1?); we just check for the Ethernet * protocol type. */ - b0 = gen_cmp(off_linktype, BPF_H, (bpf_int32)proto); + b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); gen_or(b0, b1); return b1; @@ -1253,9 +1536,10 @@ gen_ether_linktype(proto) * a length field, <= ETHERMTU) and * then check the DSAP. */ - b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU); + b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU); gen_not(b0); - b1 = gen_cmp(off_linktype + 2, BPF_B, (bpf_int32)proto); + b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B, + (bpf_int32)proto); gen_and(b0, b1); return b1; } else { @@ -1268,11 +1552,20 @@ gen_ether_linktype(proto) * will fail and the frame won't match, * which is what we want). */ - return gen_cmp(off_linktype, BPF_H, (bpf_int32)proto); + return gen_cmp(OR_LINK, off_linktype, BPF_H, + (bpf_int32)proto); } } } +/* + * Generate code to match a particular packet type. + * + * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP + * value, if <= ETHERMTU. We use that to determine whether to + * match the type field or to check the type field for the special + * LINUX_SLL_P_802_2 value and then do the appropriate test. + */ static struct block * gen_linux_sll_linktype(proto) register int proto; @@ -1281,36 +1574,24 @@ gen_linux_sll_linktype(proto) switch (proto) { - case LLCSAP_IP: - b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2); - b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32) - ((LLCSAP_IP << 8) | LLCSAP_IP)); - gen_and(b0, b1); - return b1; - case LLCSAP_ISONS: - /* - * OSI protocols always use 802.2 encapsulation. - * XXX - should we check both the DSAP and the - * SSAP, like this, or should we check just the - * DSAP? - */ - b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2); - b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32) - ((LLCSAP_ISONS << 8) | LLCSAP_ISONS)); - gen_and(b0, b1); - return b1; - + case LLCSAP_IP: case LLCSAP_NETBEUI: /* - * NetBEUI always uses 802.2 encapsulation. + * OSI protocols and NetBEUI always use 802.2 encapsulation, + * so we check the DSAP and SSAP. + * + * LLCSAP_IP checks for IP-over-802.2, rather + * than IP-over-Ethernet or IP-over-SNAP. + * * XXX - should we check both the DSAP and the - * LSAP, like this, or should we check just the - * DSAP? + * SSAP, like this, or should we check just the + * DSAP, as we do for other types <= ETHERMTU + * (i.e., other SAP values)? */ - b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2); - b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32) - ((LLCSAP_NETBEUI << 8) | LLCSAP_NETBEUI)); + 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) + ((proto << 8) | proto)); gen_and(b0, b1); return b1; @@ -1340,19 +1621,19 @@ gen_linux_sll_linktype(proto) * then put a check for LINUX_SLL_P_802_2 frames * before it. */ - b0 = gen_cmp(off_linktype + 2, BPF_B, + b0 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B, (bpf_int32)LLCSAP_IPX); b1 = gen_snap(0x000000, ETHERTYPE_IPX, off_linktype + 2); gen_or(b0, b1); - b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2); + b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2); gen_and(b0, b1); /* * Now check for 802.3 frames and OR that with * the previous test. */ - b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_3); + b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_3); gen_or(b0, b1); /* @@ -1360,7 +1641,7 @@ gen_linux_sll_linktype(proto) * do that before checking for the other frame * types. */ - b0 = gen_cmp(off_linktype, BPF_H, + b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)ETHERTYPE_IPX); gen_or(b0, b1); return b1; @@ -1377,7 +1658,7 @@ gen_linux_sll_linktype(proto) * we check for the 802.2 protocol type in the * "Ethernet type" field. */ - b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2); + b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2); /* * 802.2-encapsulated ETHERTYPE_ATALK packets are @@ -1403,7 +1684,7 @@ gen_linux_sll_linktype(proto) * phase 1?); we just check for the Ethernet * protocol type. */ - b0 = gen_cmp(off_linktype, BPF_H, (bpf_int32)proto); + b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); gen_or(b0, b1); return b1; @@ -1417,9 +1698,9 @@ gen_linux_sll_linktype(proto) * in the "Ethernet type" field, and * then check the DSAP. */ - b0 = gen_cmp(off_linktype, BPF_H, + b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2); - b1 = gen_cmp(off_linktype + 2, BPF_B, + b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B, (bpf_int32)proto); gen_and(b0, b1); return b1; @@ -1433,12 +1714,137 @@ gen_linux_sll_linktype(proto) * will fail and the frame won't match, * which is what we want). */ - return gen_cmp(off_linktype, BPF_H, + return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); } } } +static void +insert_radiotap_load_llprefixlen(b) + struct block *b; +{ + 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. + */ + if (reg_ll_size != -1) { + /* + * The 2 bytes at offsets of 2 and 3 from the beginning + * of the radiotap header are the length of the radiotap + * header; unfortunately, it's little-endian, so we have + * to load it a byte at a time and construct the value. + */ + + /* + * Load the high-order byte, at an offset of 3, shift it + * left a byte, and put the result in the X register. + */ + s1 = new_stmt(BPF_LD|BPF_B|BPF_ABS); + s1->s.k = 3; + s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K); + sappend(s1, s2); + s2->s.k = 8; + s2 = new_stmt(BPF_MISC|BPF_TAX); + sappend(s1, s2); + + /* + * Load the next byte, at an offset of 2, and OR the + * value from the X register into it. + */ + s2 = new_stmt(BPF_LD|BPF_B|BPF_ABS); + sappend(s1, s2); + s2->s.k = 2; + s2 = new_stmt(BPF_ALU|BPF_OR|BPF_X); + sappend(s1, s2); + + /* + * Now allocate a register to hold that value and store + * it. + */ + s2 = new_stmt(BPF_ST); + s2->s.k = reg_ll_size; + sappend(s1, s2); + + /* + * Now move it into the X register. + */ + 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; + } +} + + +static void +insert_load_llprefixlen(b) + struct block *b; +{ + switch (linktype) { + + case DLT_IEEE802_11_RADIO: + insert_radiotap_load_llprefixlen(b); + } +} + + +static struct slist * +gen_radiotap_llprefixlen(void) +{ + struct slist *s; + + if (reg_ll_size == -1) { + /* + * We haven't yet assigned a register for the length + * of the radiotap header; allocate one. + */ + reg_ll_size = alloc_reg(); + } + + /* + * Load the register containing the radiotap length + * into the X register. + */ + s = new_stmt(BPF_LDX|BPF_MEM); + s->s.k = reg_ll_size; + return s; +} + +/* + * Generate code to compute the link-layer header length, if necessary, + * putting it into the X register, and to return either a pointer to a + * "struct slist" for the list of statements in that code, or NULL if + * no code is necessary. + */ +static struct slist * +gen_llprefixlen(void) +{ + switch (linktype) { + + case DLT_IEEE802_11_RADIO: + return gen_radiotap_llprefixlen(); + + default: + return NULL; + } +} + +/* + * Generate code to match a particular packet type by matching the + * link-layer type field or fields in the 802.2 LLC header. + * + * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP + * value, if <= ETHERMTU. + */ static struct block * gen_linktype(proto) register int proto; @@ -1460,21 +1866,23 @@ gen_linktype(proto) /* fall through */ default: - return gen_cmp(off_linktype, BPF_H, (bpf_int32)proto); + return gen_cmp(OR_LINK, off_linktype, BPF_H, + (bpf_int32)proto); /*NOTREACHED*/ break; } break; - case DLT_IEEE802_11: - case DLT_PRISM_HEADER: - case DLT_IEEE802_11_RADIO: case DLT_FDDI: case DLT_IEEE802: + case DLT_IEEE802_11: + case DLT_IEEE802_11_RADIO_AVS: + case DLT_IEEE802_11_RADIO: + case DLT_PRISM_HEADER: case DLT_ATM_RFC1483: case DLT_ATM_CLIP: case DLT_IP_OVER_FC: - return gen_llc(proto); + return gen_llc_linktype(proto); /*NOTREACHED*/ break; @@ -1492,7 +1900,8 @@ gen_linktype(proto) * LE Control marker. (We've already generated * a test for LANE.) */ - b0 = gen_cmp(SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00); + b0 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, + 0xFF00); gen_not(b0); /* @@ -1507,10 +1916,12 @@ gen_linktype(proto) * protocol. */ b0 = gen_atmfield_code(A_PROTOTYPE, PT_LLC, BPF_JEQ, 0); - b1 = gen_llc(proto); + b1 = gen_llc_linktype(proto); gen_and(b0, b1); return b1; } + /*NOTREACHED*/ + break; case DLT_LINUX_SLL: return gen_linux_sll_linktype(proto); @@ -1600,10 +2011,10 @@ gen_linktype(proto) switch (proto) { case ETHERTYPE_IP: - b0 = gen_cmp(off_linktype, BPF_H, PPP_IP); - b1 = gen_cmp(off_linktype, BPF_H, PPP_VJC); + b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_IP); + b1 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_VJC); gen_or(b0, b1); - b0 = gen_cmp(off_linktype, BPF_H, PPP_VJNC); + b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_VJNC); gen_or(b1, b0); return b0; @@ -1709,7 +2120,7 @@ gen_linktype(proto) proto = SWAPLONG(proto); proto = htonl(proto); } - return (gen_cmp(0, BPF_W, (bpf_int32)proto)); + return (gen_cmp(OR_LINK, 0, BPF_W, (bpf_int32)proto)); case DLT_PFLOG: /* @@ -1717,12 +2128,12 @@ gen_linktype(proto) * the packet. */ if (proto == ETHERTYPE_IP) - return (gen_cmp(offsetof(struct pfloghdr, af), BPF_B, - (bpf_int32)AF_INET)); + return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af), + BPF_B, (bpf_int32)AF_INET)); #ifdef INET6 else if (proto == ETHERTYPE_IPV6) - return (gen_cmp(offsetof(struct pfloghdr, af), BPF_B, - (bpf_int32)AF_INET6)); + return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af), + BPF_B, (bpf_int32)AF_INET6)); #endif /* INET6 */ else return gen_false(); @@ -1742,32 +2153,32 @@ gen_linktype(proto) #ifdef INET6 case ETHERTYPE_IPV6: - return (gen_cmp(off_linktype, BPF_B, + return (gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_INET6)); #endif /* INET6 */ case ETHERTYPE_IP: - b0 = gen_cmp(off_linktype, BPF_B, + b0 = gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_IP); - b1 = gen_cmp(off_linktype, BPF_B, + b1 = gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_IP_OLD); gen_or(b0, b1); return (b1); case ETHERTYPE_ARP: - b0 = gen_cmp(off_linktype, BPF_B, + b0 = gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_ARP); - b1 = gen_cmp(off_linktype, BPF_B, + b1 = gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_ARP_OLD); gen_or(b0, b1); return (b1); case ETHERTYPE_REVARP: - return (gen_cmp(off_linktype, BPF_B, + return (gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_REVARP)); case ETHERTYPE_ATALK: - return (gen_cmp(off_linktype, BPF_B, + return (gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_ATALK)); } /*NOTREACHED*/ @@ -1794,14 +2205,14 @@ gen_linktype(proto) /* * Check for the special NLPID for IP. */ - return gen_cmp(2, BPF_H, (0x03<<8) | 0xcc); + return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0xcc); #ifdef INET6 case ETHERTYPE_IPV6: /* * Check for the special NLPID for IPv6. */ - return gen_cmp(2, BPF_H, (0x03<<8) | 0x8e); + return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0x8e); #endif case LLCSAP_ISONS: @@ -1816,9 +2227,9 @@ gen_linktype(proto) * control field of UI, i.e. 0x03 followed * by the NLPID. */ - b0 = gen_cmp(2, BPF_H, (0x03<<8) | ISO8473_CLNP); - b1 = gen_cmp(2, BPF_H, (0x03<<8) | ISO9542_ESIS); - b2 = gen_cmp(2, BPF_H, (0x03<<8) | ISO10589_ISIS); + b0 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO8473_CLNP); + b1 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO9542_ESIS); + b2 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO10589_ISIS); gen_or(b1, b2); gen_or(b0, b2); return b2; @@ -1833,6 +2244,12 @@ gen_linktype(proto) case DLT_JUNIPER_MLPPP: case DLT_JUNIPER_ATM1: case DLT_JUNIPER_ATM2: + case DLT_JUNIPER_PPPOE: + case DLT_JUNIPER_PPPOE_ATM: + case DLT_JUNIPER_GGSN: + case DLT_JUNIPER_ES: + case DLT_JUNIPER_MONITOR: + case DLT_JUNIPER_SERVICES: /* 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 @@ -1840,13 +2257,16 @@ gen_linktype(proto) * * FIXME encapsulation specific BPF_ filters */ - return gen_mcmp(0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */ + return gen_mcmp(OR_LINK, 0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */ case DLT_LINUX_IRDA: bpf_error("IrDA link-layer type filtering not implemented"); case DLT_DOCSIS: bpf_error("DOCSIS link-layer type filtering not implemented"); + + case DLT_LINUX_LAPD: + bpf_error("LAPD link-layer type filtering not implemented"); } /* @@ -1871,7 +2291,7 @@ gen_linktype(proto) * at "off_linktype", so we don't have to do the code generation * above.) */ - return gen_cmp(off_linktype, BPF_H, (bpf_int32)proto); + return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); } /* @@ -1897,14 +2317,23 @@ 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(offset, 8, snapblock); + return gen_bcmp(OR_LINK, offset, 8, snapblock); } /* - * Check for a given protocol value assuming an 802.2 LLC header. + * Generate code to match a particular packet type, for link-layer types + * using 802.2 LLC headers. + * + * This is *NOT* used for Ethernet; "gen_ether_linktype()" is used + * for that - it handles the D/I/X Ethernet vs. 802.3+802.2 issues. + * + * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP + * value, if <= ETHERMTU. We use that to determine whether to + * match the DSAP or both DSAP and LSAP or to check the OUI and + * protocol ID in a SNAP header. */ static struct block * -gen_llc(proto) +gen_llc_linktype(proto) int proto; { /* @@ -1913,23 +2342,24 @@ gen_llc(proto) switch (proto) { case LLCSAP_IP: - return gen_cmp(off_linktype, BPF_H, (long) - ((LLCSAP_IP << 8) | LLCSAP_IP)); - case LLCSAP_ISONS: - return gen_cmp(off_linktype, BPF_H, (long) - ((LLCSAP_ISONS << 8) | LLCSAP_ISONS)); - case LLCSAP_NETBEUI: - return gen_cmp(off_linktype, BPF_H, (long) - ((LLCSAP_NETBEUI << 8) | LLCSAP_NETBEUI)); + /* + * XXX - should we check both the DSAP and the + * SSAP, like this, or should we check just the + * DSAP, as we do for other types <= ETHERMTU + * (i.e., other SAP values)? + */ + return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_u_int32) + ((proto << 8) | proto)); case LLCSAP_IPX: /* * XXX - are there ever SNAP frames for IPX on * non-Ethernet 802.x networks? */ - return gen_cmp(off_linktype, BPF_B, (bpf_int32)LLCSAP_IPX); + return gen_cmp(OR_LINK, off_linktype, BPF_B, + (bpf_int32)LLCSAP_IPX); case ETHERTYPE_ATALK: /* @@ -1953,7 +2383,8 @@ gen_llc(proto) * This is an LLC SAP value, so check * the DSAP. */ - return gen_cmp(off_linktype, BPF_B, (bpf_int32)proto); + return gen_cmp(OR_LINK, off_linktype, BPF_B, + (bpf_int32)proto); } else { /* * This is an Ethernet type; we assume that it's @@ -1975,7 +2406,8 @@ gen_llc(proto) * I don't know whether it's worth the extra CPU * time to do the right check or not. */ - return gen_cmp(off_linktype+6, BPF_H, (bpf_int32)proto); + return gen_cmp(OR_LINK, off_linktype+6, BPF_H, + (bpf_int32)proto); } } } @@ -2017,7 +2449,7 @@ gen_hostop(addr, mask, dir, proto, src_off, dst_off) abort(); } b0 = gen_linktype(proto); - b1 = gen_mcmp(offset, BPF_W, (bpf_int32)addr, mask); + b1 = gen_mcmp(OR_NET, offset, BPF_W, (bpf_int32)addr, mask); gen_and(b0, b1); return b1; } @@ -2063,12 +2495,12 @@ gen_hostop6(addr, mask, dir, proto, src_off, dst_off) /* this order is important */ a = (u_int32_t *)addr; m = (u_int32_t *)mask; - b1 = gen_mcmp(offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3])); - b0 = gen_mcmp(offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2])); + b1 = gen_mcmp(OR_NET, offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3])); + b0 = gen_mcmp(OR_NET, offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2])); gen_and(b0, b1); - b0 = gen_mcmp(offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1])); + b0 = gen_mcmp(OR_NET, offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1])); gen_and(b0, b1); - b0 = gen_mcmp(offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0])); + b0 = gen_mcmp(OR_NET, offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0])); gen_and(b0, b1); b0 = gen_linktype(proto); gen_and(b0, b1); @@ -2085,10 +2517,10 @@ gen_ehostop(eaddr, dir) switch (dir) { case Q_SRC: - return gen_bcmp(off_mac + 6, 6, eaddr); + return gen_bcmp(OR_LINK, off_mac + 6, 6, eaddr); case Q_DST: - return gen_bcmp(off_mac + 0, 6, eaddr); + return gen_bcmp(OR_LINK, off_mac + 0, 6, eaddr); case Q_AND: b0 = gen_ehostop(eaddr, Q_SRC); @@ -2120,16 +2552,16 @@ gen_fhostop(eaddr, dir) switch (dir) { case Q_SRC: #ifdef PCAP_FDDIPAD - return gen_bcmp(6 + 1 + pcap_fddipad, 6, eaddr); + return gen_bcmp(OR_LINK, 6 + 1 + pcap_fddipad, 6, eaddr); #else - return gen_bcmp(6 + 1, 6, eaddr); + return gen_bcmp(OR_LINK, 6 + 1, 6, eaddr); #endif case Q_DST: #ifdef PCAP_FDDIPAD - return gen_bcmp(0 + 1 + pcap_fddipad, 6, eaddr); + return gen_bcmp(OR_LINK, 0 + 1 + pcap_fddipad, 6, eaddr); #else - return gen_bcmp(0 + 1, 6, eaddr); + return gen_bcmp(OR_LINK, 0 + 1, 6, eaddr); #endif case Q_AND: @@ -2161,10 +2593,10 @@ gen_thostop(eaddr, dir) switch (dir) { case Q_SRC: - return gen_bcmp(8, 6, eaddr); + return gen_bcmp(OR_LINK, 8, 6, eaddr); case Q_DST: - return gen_bcmp(2, 6, eaddr); + return gen_bcmp(OR_LINK, 2, 6, eaddr); case Q_AND: b0 = gen_thostop(eaddr, Q_SRC); @@ -2221,8 +2653,7 @@ gen_wlanhostop(eaddr, dir) * * First, check for To DS set, i.e. check "link[1] & 0x01". */ - s = new_stmt(BPF_LD|BPF_B|BPF_ABS); - s->s.k = 1; + s = gen_load_a(OR_LINK, 1, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x01; /* To DS */ b1->stmts = s; @@ -2230,15 +2661,14 @@ gen_wlanhostop(eaddr, dir) /* * If To DS is set, the SA is at 24. */ - b0 = gen_bcmp(24, 6, eaddr); + b0 = gen_bcmp(OR_LINK, 24, 6, eaddr); gen_and(b1, b0); /* * Now, check for To DS not set, i.e. check * "!(link[1] & 0x01)". */ - s = new_stmt(BPF_LD|BPF_B|BPF_ABS); - s->s.k = 1; + s = gen_load_a(OR_LINK, 1, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x01; /* To DS */ b2->stmts = s; @@ -2247,7 +2677,7 @@ gen_wlanhostop(eaddr, dir) /* * If To DS is not set, the SA is at 16. */ - b1 = gen_bcmp(16, 6, eaddr); + b1 = gen_bcmp(OR_LINK, 16, 6, eaddr); gen_and(b2, b1); /* @@ -2261,8 +2691,7 @@ gen_wlanhostop(eaddr, dir) * Now check for From DS being set, and AND that with * the ORed-together checks. */ - s = new_stmt(BPF_LD|BPF_B|BPF_ABS); - s->s.k = 1; + s = gen_load_a(OR_LINK, 1, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x02; /* From DS */ b1->stmts = s; @@ -2271,8 +2700,7 @@ gen_wlanhostop(eaddr, dir) /* * Now check for data frames with From DS not set. */ - s = new_stmt(BPF_LD|BPF_B|BPF_ABS); - s->s.k = 1; + s = gen_load_a(OR_LINK, 1, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x02; /* From DS */ b2->stmts = s; @@ -2281,7 +2709,7 @@ gen_wlanhostop(eaddr, dir) /* * If From DS isn't set, the SA is at 10. */ - b1 = gen_bcmp(10, 6, eaddr); + b1 = gen_bcmp(OR_LINK, 10, 6, eaddr); gen_and(b2, b1); /* @@ -2295,8 +2723,7 @@ gen_wlanhostop(eaddr, dir) * Now check for a data frame. * I.e, check "link[0] & 0x08". */ - s = new_stmt(BPF_LD|BPF_B|BPF_ABS); - s->s.k = 0; + gen_load_a(OR_LINK, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x08; b1->stmts = s; @@ -2311,8 +2738,7 @@ gen_wlanhostop(eaddr, dir) * is a management frame. * I.e, check "!(link[0] & 0x08)". */ - s = new_stmt(BPF_LD|BPF_B|BPF_ABS); - s->s.k = 0; + s = gen_load_a(OR_LINK, 0, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x08; b2->stmts = s; @@ -2321,7 +2747,7 @@ gen_wlanhostop(eaddr, dir) /* * For management frames, the SA is at 10. */ - b1 = gen_bcmp(10, 6, eaddr); + b1 = gen_bcmp(OR_LINK, 10, 6, eaddr); gen_and(b2, b1); /* @@ -2339,8 +2765,7 @@ gen_wlanhostop(eaddr, dir) * * I.e., check "!(link[0] & 0x04)". */ - s = new_stmt(BPF_LD|BPF_B|BPF_ABS); - s->s.k = 0; + s = gen_load_a(OR_LINK, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x04; b1->stmts = s; @@ -2375,8 +2800,7 @@ gen_wlanhostop(eaddr, dir) * * First, check for To DS set, i.e. "link[1] & 0x01". */ - s = new_stmt(BPF_LD|BPF_B|BPF_ABS); - s->s.k = 1; + s = gen_load_a(OR_LINK, 1, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x01; /* To DS */ b1->stmts = s; @@ -2384,15 +2808,14 @@ gen_wlanhostop(eaddr, dir) /* * If To DS is set, the DA is at 16. */ - b0 = gen_bcmp(16, 6, eaddr); + b0 = gen_bcmp(OR_LINK, 16, 6, eaddr); gen_and(b1, b0); /* * Now, check for To DS not set, i.e. check * "!(link[1] & 0x01)". */ - s = new_stmt(BPF_LD|BPF_B|BPF_ABS); - s->s.k = 1; + s = gen_load_a(OR_LINK, 1, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x01; /* To DS */ b2->stmts = s; @@ -2401,7 +2824,7 @@ gen_wlanhostop(eaddr, dir) /* * If To DS is not set, the DA is at 4. */ - b1 = gen_bcmp(4, 6, eaddr); + b1 = gen_bcmp(OR_LINK, 4, 6, eaddr); gen_and(b2, b1); /* @@ -2414,8 +2837,7 @@ gen_wlanhostop(eaddr, dir) * Now check for a data frame. * I.e, check "link[0] & 0x08". */ - s = new_stmt(BPF_LD|BPF_B|BPF_ABS); - s->s.k = 0; + s = gen_load_a(OR_LINK, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x08; b1->stmts = s; @@ -2430,8 +2852,7 @@ gen_wlanhostop(eaddr, dir) * is a management frame. * I.e, check "!(link[0] & 0x08)". */ - s = new_stmt(BPF_LD|BPF_B|BPF_ABS); - s->s.k = 0; + s = gen_load_a(OR_LINK, 0, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x08; b2->stmts = s; @@ -2440,7 +2861,7 @@ gen_wlanhostop(eaddr, dir) /* * For management frames, the DA is at 4. */ - b1 = gen_bcmp(4, 6, eaddr); + b1 = gen_bcmp(OR_LINK, 4, 6, eaddr); gen_and(b2, b1); /* @@ -2458,8 +2879,7 @@ gen_wlanhostop(eaddr, dir) * * I.e., check "!(link[0] & 0x04)". */ - s = new_stmt(BPF_LD|BPF_B|BPF_ABS); - s->s.k = 0; + s = gen_load_a(OR_LINK, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x04; b1->stmts = s; @@ -2503,10 +2923,10 @@ gen_ipfchostop(eaddr, dir) switch (dir) { case Q_SRC: - return gen_bcmp(10, 6, eaddr); + return gen_bcmp(OR_LINK, 10, 6, eaddr); case Q_DST: - return gen_bcmp(2, 6, eaddr); + return gen_bcmp(OR_LINK, 2, 6, eaddr); case Q_AND: b0 = gen_ipfchostop(eaddr, Q_SRC); @@ -2544,10 +2964,9 @@ gen_ipfchostop(eaddr, dir) * and not generate masking instructions if the mask is 0xFFFF. */ static struct block * -gen_dnhostop(addr, dir, base_off) +gen_dnhostop(addr, dir) bpf_u_int32 addr; int dir; - u_int base_off; { struct block *b0, *b1, *b2, *tmp; u_int offset_lh; /* offset if long header is received */ @@ -2567,16 +2986,16 @@ gen_dnhostop(addr, dir, base_off) case Q_AND: /* Inefficient because we do our Calvinball dance twice */ - b0 = gen_dnhostop(addr, Q_SRC, base_off); - b1 = gen_dnhostop(addr, Q_DST, base_off); + b0 = gen_dnhostop(addr, Q_SRC); + b1 = gen_dnhostop(addr, Q_DST); gen_and(b0, b1); return b1; case Q_OR: case Q_DEFAULT: /* Inefficient because we do our Calvinball dance twice */ - b0 = gen_dnhostop(addr, Q_SRC, base_off); - b1 = gen_dnhostop(addr, Q_DST, base_off); + b0 = gen_dnhostop(addr, Q_SRC); + b1 = gen_dnhostop(addr, Q_DST); gen_or(b0, b1); return b1; @@ -2588,26 +3007,25 @@ gen_dnhostop(addr, dir, base_off) } b0 = gen_linktype(ETHERTYPE_DN); /* Check for pad = 1, long header case */ - tmp = gen_mcmp(base_off + 2, BPF_H, + tmp = gen_mcmp(OR_NET, 2, BPF_H, (bpf_int32)ntohs(0x0681), (bpf_int32)ntohs(0x07FF)); - b1 = gen_cmp(base_off + 2 + 1 + offset_lh, + b1 = gen_cmp(OR_NET, 2 + 1 + offset_lh, BPF_H, (bpf_int32)ntohs(addr)); gen_and(tmp, b1); /* Check for pad = 0, long header case */ - tmp = gen_mcmp(base_off + 2, BPF_B, (bpf_int32)0x06, (bpf_int32)0x7); - b2 = gen_cmp(base_off + 2 + offset_lh, BPF_H, (bpf_int32)ntohs(addr)); + tmp = gen_mcmp(OR_NET, 2, BPF_B, (bpf_int32)0x06, (bpf_int32)0x7); + b2 = gen_cmp(OR_NET, 2 + offset_lh, BPF_H, (bpf_int32)ntohs(addr)); gen_and(tmp, b2); gen_or(b2, b1); /* Check for pad = 1, short header case */ - tmp = gen_mcmp(base_off + 2, BPF_H, + tmp = gen_mcmp(OR_NET, 2, BPF_H, (bpf_int32)ntohs(0x0281), (bpf_int32)ntohs(0x07FF)); - b2 = gen_cmp(base_off + 2 + 1 + offset_sh, - BPF_H, (bpf_int32)ntohs(addr)); + b2 = gen_cmp(OR_NET, 2 + 1 + offset_sh, BPF_H, (bpf_int32)ntohs(addr)); gen_and(tmp, b2); gen_or(b2, b1); /* Check for pad = 0, short header case */ - tmp = gen_mcmp(base_off + 2, BPF_B, (bpf_int32)0x02, (bpf_int32)0x7); - b2 = gen_cmp(base_off + 2 + offset_sh, BPF_H, (bpf_int32)ntohs(addr)); + tmp = gen_mcmp(OR_NET, 2, BPF_B, (bpf_int32)0x02, (bpf_int32)0x7); + b2 = gen_cmp(OR_NET, 2 + offset_sh, BPF_H, (bpf_int32)ntohs(addr)); gen_and(tmp, b2); gen_or(b2, b1); @@ -2638,16 +3056,13 @@ gen_host(addr, mask, proto, dir) return b0; case Q_IP: - return gen_hostop(addr, mask, dir, ETHERTYPE_IP, - off_nl + 12, off_nl + 16); + return gen_hostop(addr, mask, dir, ETHERTYPE_IP, 12, 16); case Q_RARP: - return gen_hostop(addr, mask, dir, ETHERTYPE_REVARP, - off_nl + 14, off_nl + 24); + return gen_hostop(addr, mask, dir, ETHERTYPE_REVARP, 14, 24); case Q_ARP: - return gen_hostop(addr, mask, dir, ETHERTYPE_ARP, - off_nl + 14, off_nl + 24); + return gen_hostop(addr, mask, dir, ETHERTYPE_ARP, 14, 24); case Q_TCP: bpf_error("'tcp' modifier applied to host"); @@ -2680,7 +3095,7 @@ gen_host(addr, mask, proto, dir) bpf_error("AARP host filtering not implemented"); case Q_DECNET: - return gen_dnhostop(addr, dir, off_nl); + return gen_dnhostop(addr, dir); case Q_SCA: bpf_error("SCA host filtering not implemented"); @@ -2729,6 +3144,9 @@ gen_host(addr, mask, proto, dir) case Q_NETBEUI: bpf_error("'netbeui' modifier applied to host"); + case Q_RADIO: + bpf_error("'radio' modifier applied to host"); + default: abort(); } @@ -2803,8 +3221,7 @@ gen_host6(addr, mask, proto, dir) bpf_error("MOPRC host filtering not implemented"); case Q_IPV6: - return gen_hostop6(addr, mask, dir, ETHERTYPE_IPV6, - off_nl + 8, off_nl + 24); + return gen_hostop6(addr, mask, dir, ETHERTYPE_IPV6, 8, 24); case Q_ICMPV6: bpf_error("'icmp6' modifier applied to host"); @@ -2836,6 +3253,9 @@ gen_host6(addr, mask, proto, dir) case Q_NETBEUI: bpf_error("'netbeui' modifier applied to host"); + case Q_RADIO: + bpf_error("'radio' modifier applied to host"); + default: abort(); } @@ -2867,7 +3287,10 @@ gen_gateway(eaddr, alist, proto, dir) b0 = gen_fhostop(eaddr, Q_OR); else if (linktype == DLT_IEEE802) b0 = gen_thostop(eaddr, Q_OR); - else if (linktype == DLT_IEEE802_11) + else if (linktype == DLT_IEEE802_11 || + linktype == DLT_IEEE802_11_RADIO_AVS || + linktype == DLT_IEEE802_11_RADIO || + linktype == DLT_PRISM_HEADER) b0 = gen_wlanhostop(eaddr, Q_OR); else if (linktype == DLT_SUNATM && is_lane) { /* @@ -2875,7 +3298,8 @@ gen_gateway(eaddr, alist, proto, dir) * LE Control marker. (We've already generated * a test for LANE.) */ - b1 = gen_cmp(SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00); + b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, + 0xFF00); gen_not(b1); /* @@ -3142,6 +3566,9 @@ gen_proto_abbrev(proto) b1 = gen_linktype(LLCSAP_NETBEUI); break; + case Q_RADIO: + bpf_error("'radio' is not a valid protocol type"); + default: abort(); } @@ -3155,8 +3582,7 @@ gen_ipfrag() struct block *b; /* not ip frag */ - s = new_stmt(BPF_LD|BPF_H|BPF_ABS); - s->s.k = off_nl + 6; + s = gen_load_a(OR_NET, 6, BPF_H); b = new_block(JMP(BPF_JSET)); b->s.k = 0x1fff; b->stmts = s; @@ -3165,25 +3591,21 @@ gen_ipfrag() return b; } +/* + * Generate a comparison to a port value in the transport-layer header + * at the specified offset from the beginning of that header. + * + * XXX - this handles a variable-length prefix preceding the link-layer + * header, such as the radiotap or AVS radio prefix, but doesn't handle + * variable-length link-layer headers (such as Token Ring or 802.11 + * headers). + */ static struct block * gen_portatom(off, v) int off; bpf_int32 v; { - struct slist *s; - struct block *b; - - s = new_stmt(BPF_LDX|BPF_MSH|BPF_B); - s->s.k = off_nl; - - s->next = new_stmt(BPF_LD|BPF_IND|BPF_H); - s->next->s.k = off_nl + off; - - b = new_block(JMP(BPF_JEQ)); - b->stmts = s; - b->s.k = v; - - return b; + return gen_cmp(OR_TRAN_IPV4, off, BPF_H, v); } #ifdef INET6 @@ -3192,7 +3614,7 @@ gen_portatom6(off, v) int off; bpf_int32 v; { - return gen_cmp(off_nl + 40 + off, BPF_H, v); + return gen_cmp(OR_TRAN_IPV6, off, BPF_H, v); } #endif/*INET6*/ @@ -3203,7 +3625,7 @@ gen_portop(port, proto, dir) struct block *b0, *b1, *tmp; /* ip proto 'proto' */ - tmp = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)proto); + tmp = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)proto); b0 = gen_ipfrag(); gen_and(tmp, b0); @@ -3293,8 +3715,8 @@ gen_portop6(port, proto, dir) { struct block *b0, *b1, *tmp; - /* ip proto 'proto' */ - b0 = gen_cmp(off_nl + 6, BPF_B, (bpf_int32)proto); + /* ip6 proto 'proto' */ + b0 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)proto); switch (dir) { case Q_SRC: @@ -3334,7 +3756,7 @@ gen_port6(port, ip_proto, dir) { struct block *b0, *b1, *tmp; - /* ether proto ip */ + /* link proto ip6 */ b0 = gen_linktype(ETHERTYPE_IPV6); switch (ip_proto) { @@ -3360,6 +3782,211 @@ gen_port6(port, ip_proto, dir) } #endif /* INET6 */ +/* gen_portrange code */ +static struct block * +gen_portrangeatom(off, v1, v2) + int off; + bpf_int32 v1, v2; +{ + struct block *b1, *b2; + + if (v1 > v2) { + /* + * Reverse the order of the ports, so v1 is the lower one. + */ + bpf_int32 vtemp; + + vtemp = v1; + v1 = v2; + v2 = vtemp; + } + + b1 = gen_cmp_ge(OR_TRAN_IPV4, off, BPF_H, v1); + b2 = gen_cmp_le(OR_TRAN_IPV4, off, BPF_H, v2); + + gen_and(b1, b2); + + return b2; +} + +struct block * +gen_portrangeop(port1, port2, proto, dir) + int port1, port2; + int proto; + int dir; +{ + struct block *b0, *b1, *tmp; + + /* ip proto 'proto' */ + tmp = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)proto); + b0 = gen_ipfrag(); + gen_and(tmp, b0); + + switch (dir) { + case Q_SRC: + b1 = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2); + break; + + case Q_DST: + b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2); + break; + + case Q_OR: + case Q_DEFAULT: + tmp = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2); + b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2); + gen_or(tmp, b1); + break; + + case Q_AND: + tmp = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2); + b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2); + gen_and(tmp, b1); + break; + + default: + abort(); + } + gen_and(b0, b1); + + return b1; +} + +static struct block * +gen_portrange(port1, port2, ip_proto, dir) + int port1, port2; + int ip_proto; + int dir; +{ + struct block *b0, *b1, *tmp; + + /* link proto ip */ + b0 = gen_linktype(ETHERTYPE_IP); + + switch (ip_proto) { + case IPPROTO_UDP: + case IPPROTO_TCP: + case IPPROTO_SCTP: + b1 = gen_portrangeop(port1, port2, ip_proto, dir); + break; + + case PROTO_UNDEF: + tmp = gen_portrangeop(port1, port2, IPPROTO_TCP, dir); + b1 = gen_portrangeop(port1, port2, IPPROTO_UDP, dir); + gen_or(tmp, b1); + tmp = gen_portrangeop(port1, port2, IPPROTO_SCTP, dir); + gen_or(tmp, b1); + break; + + default: + abort(); + } + gen_and(b0, b1); + return b1; +} + +#ifdef INET6 +static struct block * +gen_portrangeatom6(off, v1, v2) + int off; + bpf_int32 v1, v2; +{ + struct block *b1, *b2; + + if (v1 > v2) { + /* + * Reverse the order of the ports, so v1 is the lower one. + */ + bpf_int32 vtemp; + + vtemp = v1; + v1 = v2; + v2 = vtemp; + } + + b1 = gen_cmp_ge(OR_TRAN_IPV6, off, BPF_H, v1); + b2 = gen_cmp_le(OR_TRAN_IPV6, off, BPF_H, v2); + + gen_and(b1, b2); + + return b2; +} + +struct block * +gen_portrangeop6(port1, port2, proto, dir) + int port1, port2; + int proto; + int dir; +{ + struct block *b0, *b1, *tmp; + + /* ip6 proto 'proto' */ + b0 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)proto); + + switch (dir) { + case Q_SRC: + b1 = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2); + break; + + case Q_DST: + b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2); + break; + + case Q_OR: + case Q_DEFAULT: + tmp = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2); + b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2); + gen_or(tmp, b1); + break; + + case Q_AND: + tmp = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2); + b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2); + gen_and(tmp, b1); + break; + + default: + abort(); + } + gen_and(b0, b1); + + return b1; +} + +static struct block * +gen_portrange6(port1, port2, ip_proto, dir) + int port1, port2; + int ip_proto; + int dir; +{ + struct block *b0, *b1, *tmp; + + /* link proto ip6 */ + b0 = gen_linktype(ETHERTYPE_IPV6); + + switch (ip_proto) { + case IPPROTO_UDP: + case IPPROTO_TCP: + case IPPROTO_SCTP: + b1 = gen_portrangeop6(port1, port2, ip_proto, dir); + break; + + case PROTO_UNDEF: + tmp = gen_portrangeop6(port1, port2, IPPROTO_TCP, dir); + b1 = gen_portrangeop6(port1, port2, IPPROTO_UDP, dir); + gen_or(tmp, b1); + tmp = gen_portrangeop6(port1, port2, IPPROTO_SCTP, dir); + gen_or(tmp, b1); + break; + + default: + abort(); + } + gen_and(b0, b1); + return b1; +} +#endif /* INET6 */ + static int lookup_proto(name, proto) register const char *name; @@ -3448,10 +4075,23 @@ gen_protochain(v, proto, dir) /*NOTREACHED*/ } + /* + * We don't handle variable-length radiotap here headers yet. + * We might want to add BPF instructions to do the protochain + * work, to simplify that and, on platforms that have a BPF + * interpreter with the new instructions, let the filtering + * be done in the kernel. (We already require a modified BPF + * engine to do the protochain stuff, to support backward + * branches, and backward branch support is unlikely to appear + * in kernel BPF engines.) + */ + if (linktype == DLT_IEEE802_11_RADIO) + bpf_error("'protochain' not supported with radiotap headers"); + no_optimize = 1; /*this code is not compatible with optimzer yet */ /* - * s[0] is a dummy entry to protect other BPF insn from damaged + * s[0] is a dummy entry to protect other BPF insn from damage * by s[fix] = foo with uninitialized variable "fix". It is somewhat * hard to find interdependency made by jump table fixup. */ @@ -3707,6 +4347,15 @@ gen_protochain(v, proto, dir) #endif } +/* + * Generate code that checks whether the packet is a packet for protocol + * <proto> and whether the type field in that protocol's header has + * the value <v>, e.g. if <proto> is Q_IP, it checks whether it's an + * IP packet and checks the protocol number in the IP header against <v>. + * + * If <proto> is Q_DEFAULT, i.e. just "proto" was specified, it checks + * against Q_IP and Q_IPV6. + */ static struct block * gen_proto(v, proto, dir) int v; @@ -3746,7 +4395,7 @@ gen_proto(v, proto, dir) */ b0 = gen_linktype(ETHERTYPE_IP); #ifndef CHASE_CHAIN - b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)v); + b1 = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)v); #else b1 = gen_protochain(v, Q_IP); #endif @@ -3775,7 +4424,7 @@ gen_proto(v, proto, dir) * * XXX - what about SNAP-encapsulated frames? */ - return gen_cmp(2, BPF_H, (0x03<<8) | v); + return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | v); /*NOTREACHED*/ break; @@ -3786,13 +4435,13 @@ gen_proto(v, proto, dir) */ b0 = gen_linktype(LLCSAP_ISONS<<8 | LLCSAP_ISONS); /* OSI in C-HDLC is stuffed with a fudge byte */ - b1 = gen_cmp(off_nl_nosnap+1, BPF_B, (long)v); + b1 = gen_cmp(OR_NET_NOSNAP, 1, BPF_B, (long)v); gen_and(b0, b1); return b1; default: b0 = gen_linktype(LLCSAP_ISONS); - b1 = gen_cmp(off_nl_nosnap, BPF_B, (long)v); + b1 = gen_cmp(OR_NET_NOSNAP, 0, BPF_B, (long)v); gen_and(b0, b1); return b1; } @@ -3803,7 +4452,7 @@ gen_proto(v, proto, dir) * 4 is the offset of the PDU type relative to the IS-IS * header. */ - b1 = gen_cmp(off_nl_nosnap+4, BPF_B, (long)v); + b1 = gen_cmp(OR_NET_NOSNAP, 4, BPF_B, (long)v); gen_and(b0, b1); return b1; @@ -3878,7 +4527,7 @@ gen_proto(v, proto, dir) case Q_IPV6: b0 = gen_linktype(ETHERTYPE_IPV6); #ifndef CHASE_CHAIN - b1 = gen_cmp(off_nl + 6, BPF_B, (bpf_int32)v); + b1 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)v); #else b1 = gen_protochain(v, Q_IPV6); #endif @@ -3904,6 +4553,9 @@ gen_proto(v, proto, dir) case Q_NETBEUI: bpf_error("'netbeui proto' is bogus"); + case Q_RADIO: + bpf_error("'radio proto' is bogus"); + default: abort(); /* NOTREACHED */ @@ -3932,6 +4584,7 @@ gen_scode(name, q) #endif /*INET6*/ struct block *b, *tmp; int port, real_proto; + int port1, port2; switch (q.addr) { @@ -3980,6 +4633,9 @@ gen_scode(name, q) return b; case DLT_IEEE802_11: + case DLT_IEEE802_11_RADIO_AVS: + case DLT_IEEE802_11_RADIO: + case DLT_PRISM_HEADER: eaddr = pcap_ether_hostton(name); if (eaddr == NULL) bpf_error( @@ -4006,8 +4662,8 @@ gen_scode(name, q) * with an LE Control marker. (We've * already generated a test for LANE.) */ - tmp = gen_cmp(SUNATM_PKT_BEGIN_POS, BPF_H, - 0xFF00); + tmp = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, + BPF_H, 0xFF00); gen_not(tmp); eaddr = pcap_ether_hostton(name); @@ -4139,6 +4795,50 @@ gen_scode(name, q) } #endif /* INET6 */ + case Q_PORTRANGE: + if (proto != Q_DEFAULT && + proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP) + bpf_error("illegal qualifier of 'portrange'"); + if (pcap_nametoportrange(name, &port1, &port2, &real_proto) == 0) + bpf_error("unknown port in range '%s'", name); + if (proto == Q_UDP) { + if (real_proto == IPPROTO_TCP) + bpf_error("port in range '%s' is tcp", name); + else if (real_proto == IPPROTO_SCTP) + bpf_error("port in range '%s' is sctp", name); + else + /* override PROTO_UNDEF */ + real_proto = IPPROTO_UDP; + } + if (proto == Q_TCP) { + if (real_proto == IPPROTO_UDP) + bpf_error("port in range '%s' is udp", name); + else if (real_proto == IPPROTO_SCTP) + bpf_error("port in range '%s' is sctp", name); + else + /* override PROTO_UNDEF */ + real_proto = IPPROTO_TCP; + } + if (proto == Q_SCTP) { + if (real_proto == IPPROTO_UDP) + bpf_error("port in range '%s' is udp", name); + else if (real_proto == IPPROTO_TCP) + bpf_error("port in range '%s' is tcp", name); + else + /* override PROTO_UNDEF */ + real_proto = IPPROTO_SCTP; + } +#ifndef INET6 + return gen_portrange(port1, port2, real_proto, dir); +#else + { + struct block *b; + b = gen_portrange(port1, port2, real_proto, dir); + gen_or(gen_portrange6(port1, port2, real_proto, dir), b); + return b; + } +#endif /* INET6 */ + case Q_GATEWAY: #ifndef INET6 eaddr = pcap_ether_hostton(name); @@ -4286,6 +4986,29 @@ gen_ncode(s, v, q) } #endif /* INET6 */ + case Q_PORTRANGE: + if (proto == Q_UDP) + proto = IPPROTO_UDP; + else if (proto == Q_TCP) + proto = IPPROTO_TCP; + else if (proto == Q_SCTP) + proto = IPPROTO_SCTP; + else if (proto == Q_DEFAULT) + proto = PROTO_UNDEF; + else + bpf_error("illegal qualifier of 'portrange'"); + +#ifndef INET6 + return gen_portrange((int)v, (int)v, proto, dir); +#else + { + struct block *b; + b = gen_portrange((int)v, (int)v, proto, dir); + gen_or(gen_portrange6((int)v, (int)v, proto, dir), b); + return b; + } +#endif /* INET6 */ + case Q_GATEWAY: bpf_error("'gateway' requires a name"); /* NOTREACHED */ @@ -4380,7 +5103,10 @@ gen_ecode(eaddr, q) return gen_fhostop(eaddr, (int)q.dir); if (linktype == DLT_IEEE802) return gen_thostop(eaddr, (int)q.dir); - if (linktype == DLT_IEEE802_11) + if (linktype == DLT_IEEE802_11 || + linktype == DLT_IEEE802_11_RADIO_AVS || + linktype == DLT_IEEE802_11_RADIO || + linktype == DLT_PRISM_HEADER) return gen_wlanhostop(eaddr, (int)q.dir); if (linktype == DLT_SUNATM && is_lane) { /* @@ -4388,7 +5114,8 @@ gen_ecode(eaddr, q) * LE Control marker. (We've already generated * a test for LANE.) */ - tmp = gen_cmp(SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00); + tmp = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, + 0xFF00); gen_not(tmp); /* @@ -4441,6 +5168,13 @@ xfer_to_a(a) return s; } +/* + * Modify "index" to use the value stored into its register as an + * offset relative to the beginning of the header for the protocol + * "proto", and allocate a register and put an item "size" bytes long + * (1, 2, or 4) at that offset into that register, making it the register + * for "index". + */ struct arth * gen_load(proto, index, size) int proto; @@ -4473,8 +5207,36 @@ gen_load(proto, index, size) default: bpf_error("unsupported index operation"); + case Q_RADIO: + /* + * The offset is relative to the beginning of the packet + * data, if we have a radio header. (If we don't, this + * is an error.) + */ + if (linktype != DLT_IEEE802_11_RADIO_AVS && + linktype != DLT_IEEE802_11_RADIO && + linktype != DLT_PRISM_HEADER) + bpf_error("radio information not present in capture"); + + /* + * Load into the X register the offset computed into the + * register specifed by "index". + */ + s = xfer_to_x(index); + + /* + * Load the item at that offset. + */ + tmp = new_stmt(BPF_LD|BPF_IND|size); + sappend(s, tmp); + sappend(index->s, s); + break; + case Q_LINK: /* + * The offset is relative to the beginning of + * the link-layer header. + * * XXX - what about ATM LANE? Should the index be * relative to the beginning of the AAL5 frame, so * that 0 refers to the beginning of the LE Control @@ -4482,8 +5244,33 @@ gen_load(proto, index, size) * frame, so that 0 refers, for Ethernet LANE, to * the beginning of the destination address? */ - s = xfer_to_x(index); + s = gen_llprefixlen(); + + /* + * If "s" is non-null, it has code to arrange that the + * X register contains the length of the prefix preceding + * the link-layer header. Add to it the offset computed + * into the register specified by "index", and move that + * into the X register. Otherwise, just load into the X + * register the offset computed into the register specifed + * by "index". + */ + if (s != NULL) { + sappend(s, xfer_to_a(index)); + sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X)); + sappend(s, new_stmt(BPF_MISC|BPF_TAX)); + } else + s = xfer_to_x(index); + + /* + * Load the item at the sum of the offset we've put in the + * X register and the offset of the start of the link + * layer header (which is 0 if the radio header is + * variable-length; that header length is what we put + * into the X register and then added to the index). + */ tmp = new_stmt(BPF_LD|BPF_IND|size); + tmp->s.k = off_ll; sappend(s, tmp); sappend(index->s, s); break; @@ -4500,13 +5287,44 @@ gen_load(proto, index, size) #ifdef INET6 case Q_IPV6: #endif - /* XXX Note that we assume a fixed link header here. */ - s = xfer_to_x(index); + /* + * The offset is relative to the beginning of + * the network-layer header. + * XXX - are there any cases where we want + * off_nl_nosnap? + */ + s = gen_llprefixlen(); + + /* + * If "s" is non-null, it has code to arrange that the + * X register contains the length of the prefix preceding + * the link-layer header. Add to it the offset computed + * into the register specified by "index", and move that + * into the X register. Otherwise, just load into the X + * register the offset computed into the register specifed + * by "index". + */ + if (s != NULL) { + sappend(s, xfer_to_a(index)); + sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X)); + sappend(s, new_stmt(BPF_MISC|BPF_TAX)); + } else + s = xfer_to_x(index); + + /* + * Load the item at the sum of the offset we've put in the + * X register and the offset of the start of the network + * layer header. + */ tmp = new_stmt(BPF_LD|BPF_IND|size); tmp->s.k = off_nl; sappend(s, tmp); sappend(index->s, s); + /* + * Do the computation only if the packet contains + * the protocol in question. + */ b = gen_proto_abbrev(proto); if (index->b) gen_and(index->b, b); @@ -4521,8 +5339,29 @@ gen_load(proto, index, size) case Q_IGRP: case Q_PIM: case Q_VRRP: - s = new_stmt(BPF_LDX|BPF_MSH|BPF_B); - s->s.k = off_nl; + /* + * The offset is relative to the beginning of + * the transport-layer header. + * XXX - are there any cases where we want + * off_nl_nosnap? + * XXX - we should, if we're built with + * IPv6 support, generate code to load either + * IPv4, IPv6, or both, as appropriate. + */ + s = gen_loadx_iphdrlen(); + + /* + * The X register now contains the sum of the offset + * of the beginning of the 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. + */ sappend(s, xfer_to_a(index)); sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X)); sappend(s, new_stmt(BPF_MISC|BPF_TAX)); @@ -4530,6 +5369,12 @@ gen_load(proto, index, size) tmp->s.k = off_nl; sappend(index->s, s); + /* + * Do the computation only if the packet contains + * the protocol in question - which is true only + * if this is an IP datagram and is the first or + * only fragment of that datagram. + */ gen_and(gen_proto_abbrev(proto), b = gen_ipfrag()); if (index->b) gen_and(index->b, b); @@ -4755,6 +5600,16 @@ gen_less(n) return b; } +/* + * This is for "byte {idx} {op} {val}"; "idx" is treated as relative to + * the beginning of the link-layer header. + * XXX - that means you can't test values in the radiotap header, but + * as that header is difficult if not impossible to parse generally + * without a loop, that might not be a severe problem. A new keyword + * "radio" could be added for that, although what you'd really want + * would be a way of testing particular radio header values, which + * would generate code appropriate to the radio header in question. + */ struct block * gen_byteop(op, idx, val) int op, idx, val; @@ -4767,17 +5622,14 @@ gen_byteop(op, idx, val) abort(); case '=': - return gen_cmp((u_int)idx, BPF_B, (bpf_int32)val); + return gen_cmp(OR_LINK, (u_int)idx, BPF_B, (bpf_int32)val); case '<': - b = gen_cmp((u_int)idx, BPF_B, (bpf_int32)val); - b->s.code = JMP(BPF_JGE); - gen_not(b); + b = gen_cmp_lt(OR_LINK, (u_int)idx, BPF_B, (bpf_int32)val); return b; case '>': - b = gen_cmp((u_int)idx, BPF_B, (bpf_int32)val); - b->s.code = JMP(BPF_JGT); + b = gen_cmp_gt(OR_LINK, (u_int)idx, BPF_B, (bpf_int32)val); return b; case '|': @@ -4818,7 +5670,10 @@ gen_broadcast(proto) return gen_fhostop(ebroadcast, Q_DST); if (linktype == DLT_IEEE802) return gen_thostop(ebroadcast, Q_DST); - if (linktype == DLT_IEEE802_11) + if (linktype == DLT_IEEE802_11 || + linktype == DLT_IEEE802_11_RADIO_AVS || + linktype == DLT_IEEE802_11_RADIO || + linktype == DLT_PRISM_HEADER) return gen_wlanhostop(ebroadcast, Q_DST); if (linktype == DLT_IP_OVER_FC) return gen_ipfchostop(ebroadcast, Q_DST); @@ -4828,7 +5683,8 @@ gen_broadcast(proto) * LE Control marker. (We've already generated * a test for LANE.) */ - b1 = gen_cmp(SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00); + b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, + 0xFF00); gen_not(b1); /* @@ -4844,8 +5700,8 @@ gen_broadcast(proto) case Q_IP: b0 = gen_linktype(ETHERTYPE_IP); hostmask = ~netmask; - b1 = gen_mcmp(off_nl + 16, BPF_W, (bpf_int32)0, hostmask); - b2 = gen_mcmp(off_nl + 16, BPF_W, + b1 = gen_mcmp(OR_NET, 16, BPF_W, (bpf_int32)0, hostmask); + b2 = gen_mcmp(OR_NET, 16, BPF_W, (bpf_int32)(~0 & hostmask), hostmask); gen_or(b1, b2); gen_and(b0, b2); @@ -4867,8 +5723,7 @@ gen_mac_multicast(offset) register struct slist *s; /* link[offset] & 1 != 0 */ - s = new_stmt(BPF_LD|BPF_B|BPF_ABS); - s->s.k = offset; + s = gen_load_a(OR_LINK, offset, BPF_B); b0 = new_block(JMP(BPF_JSET)); b0->s.k = 1; b0->stmts = s; @@ -4910,7 +5765,10 @@ gen_multicast(proto) return gen_mac_multicast(2); } - if (linktype == DLT_IEEE802_11) { + if (linktype == DLT_IEEE802_11 || + linktype == DLT_IEEE802_11_RADIO_AVS || + linktype == DLT_IEEE802_11_RADIO || + linktype == DLT_PRISM_HEADER) { /* * Oh, yuk. * @@ -4932,8 +5790,7 @@ gen_multicast(proto) * * First, check for To DS set, i.e. "link[1] & 0x01". */ - s = new_stmt(BPF_LD|BPF_B|BPF_ABS); - s->s.k = 1; + s = gen_load_a(OR_LINK, 1, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x01; /* To DS */ b1->stmts = s; @@ -4948,8 +5805,7 @@ gen_multicast(proto) * Now, check for To DS not set, i.e. check * "!(link[1] & 0x01)". */ - s = new_stmt(BPF_LD|BPF_B|BPF_ABS); - s->s.k = 1; + s = gen_load_a(OR_LINK, 1, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x01; /* To DS */ b2->stmts = s; @@ -4971,8 +5827,7 @@ gen_multicast(proto) * Now check for a data frame. * I.e, check "link[0] & 0x08". */ - s = new_stmt(BPF_LD|BPF_B|BPF_ABS); - s->s.k = 0; + s = gen_load_a(OR_LINK, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x08; b1->stmts = s; @@ -4987,8 +5842,7 @@ gen_multicast(proto) * is a management frame. * I.e, check "!(link[0] & 0x08)". */ - s = new_stmt(BPF_LD|BPF_B|BPF_ABS); - s->s.k = 0; + s = gen_load_a(OR_LINK, 0, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x08; b2->stmts = s; @@ -5015,8 +5869,7 @@ gen_multicast(proto) * * I.e., check "!(link[0] & 0x04)". */ - s = new_stmt(BPF_LD|BPF_B|BPF_ABS); - s->s.k = 0; + s = gen_load_a(OR_LINK, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x04; b1->stmts = s; @@ -5041,7 +5894,8 @@ gen_multicast(proto) * LE Control marker. (We've already generated * a test for LANE.) */ - b1 = gen_cmp(SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00); + b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, + 0xFF00); gen_not(b1); /* ether[off_mac] & 1 != 0 */ @@ -5055,15 +5909,14 @@ gen_multicast(proto) case Q_IP: b0 = gen_linktype(ETHERTYPE_IP); - b1 = gen_cmp(off_nl + 16, BPF_B, (bpf_int32)224); - b1->s.code = JMP(BPF_JGE); + b1 = gen_cmp_ge(OR_NET, 16, BPF_B, (bpf_int32)224); gen_and(b0, b1); return b1; #ifdef INET6 case Q_IPV6: b0 = gen_linktype(ETHERTYPE_IPV6); - b1 = gen_cmp(off_nl + 24, BPF_B, (bpf_int32)255); + b1 = gen_cmp(OR_NET, 24, BPF_B, (bpf_int32)255); gen_and(b0, b1); return b1; #endif /* INET6 */ @@ -5099,7 +5952,7 @@ gen_inbound(dir) /* * Match packets sent by this machine. */ - b0 = gen_cmp(0, BPF_H, LINUX_SLL_OUTGOING); + b0 = gen_cmp(OR_LINK, 0, BPF_H, LINUX_SLL_OUTGOING); } else { /* * Match packets sent to this machine. @@ -5111,22 +5964,22 @@ gen_inbound(dir) * shouldn't be matched, but what about broadcast * or multicast packets we received? */ - b0 = gen_cmp(0, BPF_H, LINUX_SLL_HOST); + b0 = gen_cmp(OR_LINK, 0, BPF_H, LINUX_SLL_HOST); } break; case DLT_PFLOG: - b0 = gen_cmp(offsetof(struct pfloghdr, dir), BPF_B, + b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, dir), BPF_B, (bpf_int32)((dir == 0) ? PF_IN : PF_OUT)); break; case DLT_PPP_PPPD: if (dir) { /* match outgoing packets */ - b0 = gen_cmp(0, BPF_B, PPP_PPPD_OUT); + b0 = gen_cmp(OR_LINK, 0, BPF_B, PPP_PPPD_OUT); } else { /* match incoming packets */ - b0 = gen_cmp(0, BPF_B, PPP_PPPD_IN); + b0 = gen_cmp(OR_LINK, 0, BPF_B, PPP_PPPD_IN); } break; @@ -5134,14 +5987,20 @@ gen_inbound(dir) case DLT_JUNIPER_MLPPP: case DLT_JUNIPER_ATM1: case DLT_JUNIPER_ATM2: + case DLT_JUNIPER_PPPOE: + case DLT_JUNIPER_PPPOE_ATM: + case DLT_JUNIPER_GGSN: + case DLT_JUNIPER_ES: + case DLT_JUNIPER_MONITOR: + case DLT_JUNIPER_SERVICES: /* juniper flags (including direction) are stored * the byte after the 3-byte magic number */ if (dir) { /* match outgoing packets */ - b0 = gen_mcmp(3, BPF_B, 0, 0x01); + b0 = gen_mcmp(OR_LINK, 3, BPF_B, 0, 0x01); } else { /* match incoming packets */ - b0 = gen_mcmp(3, BPF_B, 1, 0x01); + b0 = gen_mcmp(OR_LINK, 3, BPF_B, 1, 0x01); } break; @@ -5173,7 +6032,7 @@ gen_pf_ifname(const char *ifname) len-1); /* NOTREACHED */ } - b0 = gen_bcmp(off, strlen(ifname), (const u_char *)ifname); + b0 = gen_bcmp(OR_LINK, off, strlen(ifname), (const u_char *)ifname); return (b0); } @@ -5192,7 +6051,7 @@ gen_pf_ruleset(char *ruleset) (long)(sizeof(((struct pfloghdr *)0)->ruleset) - 1)); /* NOTREACHED */ } - b0 = gen_bcmp(offsetof(struct pfloghdr, ruleset), + b0 = gen_bcmp(OR_LINK, offsetof(struct pfloghdr, ruleset), strlen(ruleset), (const u_char *)ruleset); return (b0); } @@ -5204,7 +6063,7 @@ gen_pf_rnr(int rnr) struct block *b0; if (linktype == DLT_PFLOG) { - b0 = gen_cmp(offsetof(struct pfloghdr, rulenr), BPF_W, + 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); @@ -5225,7 +6084,7 @@ gen_pf_srnr(int srnr) /* NOTREACHED */ } - b0 = gen_cmp(offsetof(struct pfloghdr, subrulenr), BPF_W, + b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, subrulenr), BPF_W, (bpf_int32)srnr); return (b0); } @@ -5237,7 +6096,7 @@ gen_pf_reason(int reason) struct block *b0; if (linktype == DLT_PFLOG) { - b0 = gen_cmp(offsetof(struct pfloghdr, reason), BPF_B, + 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); @@ -5254,7 +6113,7 @@ gen_pf_action(int action) struct block *b0; if (linktype == DLT_PFLOG) { - b0 = gen_cmp(offsetof(struct pfloghdr, action), BPF_B, + 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); @@ -5287,10 +6146,10 @@ gen_ahostop(eaddr, dir) switch (dir) { /* src comes first, different from Ethernet */ case Q_SRC: - return gen_bcmp(0, 1, eaddr); + return gen_bcmp(OR_LINK, 0, 1, eaddr); case Q_DST: - return gen_bcmp(1, 1, eaddr); + return gen_bcmp(OR_LINK, 1, 1, eaddr); case Q_AND: b0 = gen_ahostop(eaddr, Q_SRC); @@ -5320,36 +6179,60 @@ gen_vlan(vlan_num) /* * Change the offsets to point to the type and data fields within - * the VLAN packet. This is somewhat of a kludge. + * the VLAN packet. Just increment the offsets, so that we + * can support a hierarchy, e.g. "vlan 300 && vlan 200" to + * capture VLAN 200 encapsulated within VLAN 100. + * + * XXX - this is a bit of a kludge. If we were to split the + * compiler into a parser that parses an expression and + * generates an expression tree, and a code generator that + * takes an expression tree (which could come from our + * parser or from some other parser) and generates BPF code, + * we could perhaps make the offsets parameters of routines + * and, in the handler for an "AND" node, pass to subnodes + * other than the VLAN node the adjusted offsets. + * + * This would mean that "vlan" would, instead of changing the + * behavior of *all* tests after it, change only the behavior + * of tests ANDed with it. That would change the documented + * semantics of "vlan", which might break some expressions. + * However, it would mean that "(vlan and ip) or ip" would check + * both for VLAN-encapsulated IP and IP-over-Ethernet, rather than + * checking only for VLAN-encapsulated IP, so that could still + * be considered worth doing; it wouldn't break expressions + * that are of the form "vlan and ..." or "vlan N and ...", + * which I suspect are the most common expressions involving + * "vlan". "vlan or ..." doesn't necessarily do what the user + * would really want, now, as all the "or ..." tests would + * be done assuming a VLAN, even though the "or" could be viewed + * as meaning "or, if this isn't a VLAN packet...". */ - if (orig_nl == (u_int)-1) { - orig_linktype = off_linktype; /* save original values */ - orig_nl = off_nl; - orig_nl_nosnap = off_nl_nosnap; + orig_linktype = off_linktype; /* save original values */ + orig_nl = off_nl; - switch (linktype) { + switch (linktype) { - case DLT_EN10MB: - off_linktype = 16; - off_nl_nosnap = 18; - off_nl = 18; - break; + case DLT_EN10MB: + off_linktype += 4; + off_nl_nosnap += 4; + off_nl += 4; + break; - default: - bpf_error("no VLAN support for data link type %d", - linktype); - /*NOTREACHED*/ - } - } + default: + bpf_error("no VLAN support for data link type %d", + linktype); + /*NOTREACHED*/ + } /* check for VLAN */ - b0 = gen_cmp(orig_linktype, BPF_H, (bpf_int32)ETHERTYPE_8021Q); + 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) { struct block *b1; - b1 = gen_mcmp(orig_nl, BPF_H, (bpf_int32)vlan_num, 0x0fff); + b1 = gen_mcmp(OR_LINK, orig_nl, BPF_H, (bpf_int32)vlan_num, + 0x0fff); gen_and(b0, b1); b0 = b1; } @@ -5368,61 +6251,54 @@ gen_mpls(label_num) /* * Change the offsets to point to the type and data fields within - * the MPLS packet. This is somewhat of a kludge. + * the MPLS packet. Just increment the offsets, so that we + * can support a hierarchy, e.g. "mpls 100000 && mpls 1024" to + * capture packets with an outer label of 100000 and an inner + * label of 1024. + * + * XXX - this is a bit of a kludge. See comments in gen_vlan(). */ - if (orig_nl == (u_int)-1) { - orig_linktype = off_linktype; /* save original values */ - orig_nl = off_nl; - orig_nl_nosnap = off_nl_nosnap; - - switch (linktype) { - - case DLT_EN10MB: - off_linktype = 16; - off_nl_nosnap = 18; - off_nl = 18; - - b0 = gen_cmp(orig_linktype, BPF_H, (bpf_int32)ETHERTYPE_MPLS); - break; - - case DLT_PPP: - off_linktype = 6; - off_nl_nosnap = 8; - off_nl = 8; - - b0 = gen_cmp(orig_linktype, BPF_H, (bpf_int32)PPP_MPLS_UCAST); - break; - - case DLT_C_HDLC: - off_linktype = 6; - off_nl_nosnap = 8; - off_nl = 8; - - b0 = gen_cmp(orig_linktype, BPF_H, (bpf_int32)ETHERTYPE_MPLS); - break; - - /* FIXME add other DLT_s ... - * for Frame-Relay/and ATM this may get messy due to SNAP headers - * leave it for now */ - - default: - bpf_error("no MPLS support for data link type %d", - linktype); - b0 = NULL; - /*NOTREACHED*/ - } - } else { - bpf_error("'mpls' can't be combined with 'vlan' or another 'mpls'"); - b0 = NULL; - /*NOTREACHED*/ - } + orig_linktype = off_linktype; /* save original values */ + orig_nl = off_nl; + + switch (linktype) { + + case DLT_C_HDLC: /* fall through */ + case DLT_EN10MB: + off_nl_nosnap += 4; + off_nl += 4; + + b0 = gen_cmp(OR_LINK, orig_linktype, BPF_H, + (bpf_int32)ETHERTYPE_MPLS); + break; + + case DLT_PPP: + off_nl_nosnap += 4; + off_nl += 4; + + b0 = gen_cmp(OR_LINK, orig_linktype, BPF_H, + (bpf_int32)PPP_MPLS_UCAST); + break; + + /* FIXME add other DLT_s ... + * for Frame-Relay/and ATM this may get messy due to SNAP headers + * leave it for now */ + + default: + bpf_error("no MPLS support for data link type %d", + linktype); + b0 = NULL; + /*NOTREACHED*/ + break; + } /* If a specific MPLS label is requested, check it */ if (label_num >= 0) { struct block *b1; label_num = label_num << 12; /* label is shifted 12 bits on the wire */ - b1 = gen_mcmp(orig_nl, BPF_W, (bpf_int32)label_num, 0xfffff000); /* only compare the first 20 bits */ + b1 = gen_mcmp(OR_LINK, orig_nl, BPF_W, (bpf_int32)label_num, + 0xfffff000); /* only compare the first 20 bits */ gen_and(b0, b1); b0 = b1; } @@ -5433,7 +6309,7 @@ gen_mpls(label_num) struct block * gen_atmfield_code(atmfield, jvalue, jtype, reverse) int atmfield; - bpf_u_int32 jvalue; + bpf_int32 jvalue; bpf_u_int32 jtype; int reverse; { @@ -5446,8 +6322,8 @@ gen_atmfield_code(atmfield, jvalue, jtype, reverse) bpf_error("'vpi' supported only on raw ATM"); if (off_vpi == (u_int)-1) abort(); - b0 = gen_ncmp(BPF_B, off_vpi, 0xffffffff, (u_int)jtype, - (u_int)jvalue, reverse); + b0 = gen_ncmp(OR_LINK, off_vpi, BPF_B, 0xffffffff, jtype, + reverse, jvalue); break; case A_VCI: @@ -5455,22 +6331,22 @@ gen_atmfield_code(atmfield, jvalue, jtype, reverse) bpf_error("'vci' supported only on raw ATM"); if (off_vci == (u_int)-1) abort(); - b0 = gen_ncmp(BPF_H, off_vci, 0xffffffff, (u_int)jtype, - (u_int)jvalue, reverse); + b0 = gen_ncmp(OR_LINK, off_vci, BPF_H, 0xffffffff, jtype, + reverse, jvalue); break; case A_PROTOTYPE: if (off_proto == (u_int)-1) abort(); /* XXX - this isn't on FreeBSD */ - b0 = gen_ncmp(BPF_B, off_proto, 0x0f, (u_int)jtype, - (u_int)jvalue, reverse); + b0 = gen_ncmp(OR_LINK, off_proto, BPF_B, 0x0f, jtype, + reverse, jvalue); break; case A_MSGTYPE: if (off_payload == (u_int)-1) abort(); - b0 = gen_ncmp(BPF_B, off_payload + MSG_TYPE_POS, 0xffffffff, - (u_int)jtype, (u_int)jvalue, reverse); + b0 = gen_ncmp(OR_LINK, off_payload + MSG_TYPE_POS, BPF_B, + 0xffffffff, jtype, reverse, jvalue); break; case A_CALLREFTYPE: @@ -5478,8 +6354,8 @@ gen_atmfield_code(atmfield, jvalue, jtype, reverse) bpf_error("'callref' supported only on raw ATM"); if (off_proto == (u_int)-1) abort(); - b0 = gen_ncmp(BPF_B, off_proto, 0xffffffff, (u_int)jtype, - (u_int)jvalue, reverse); + b0 = gen_ncmp(OR_LINK, off_proto, BPF_B, 0xffffffff, + jtype, reverse, jvalue); break; default: @@ -5589,6 +6465,86 @@ gen_atmtype_abbrev(type) return b1; } +struct block * +gen_mtp3field_code(mtp3field, jvalue, jtype, reverse) + int mtp3field; + bpf_u_int32 jvalue; + bpf_u_int32 jtype; + int reverse; +{ + struct block *b0; + bpf_u_int32 val1 , val2 , val3; + + switch (mtp3field) { + + case M_SIO: + if (off_sio == (u_int)-1) + bpf_error("'sio' supported only on SS7"); + /* sio coded on 1 byte so max value 255 */ + if(jvalue > 255) + bpf_error("sio value %u too big; max value = 255", + jvalue); + b0 = gen_ncmp(OR_PACKET, off_sio, BPF_B, 0xffffffff, + (u_int)jtype, reverse, (u_int)jvalue); + break; + + case M_OPC: + if (off_opc == (u_int)-1) + bpf_error("'opc' supported only on SS7"); + /* opc coded on 14 bits so max value 16383 */ + if (jvalue > 16383) + bpf_error("opc value %u too big; max value = 16383", + jvalue); + /* the following instructions are made to convert jvalue + * to the form used to write opc in an ss7 message*/ + val1 = jvalue & 0x00003c00; + val1 = val1 >>10; + val2 = jvalue & 0x000003fc; + val2 = val2 <<6; + val3 = jvalue & 0x00000003; + val3 = val3 <<22; + jvalue = val1 + val2 + val3; + b0 = gen_ncmp(OR_PACKET, off_opc, BPF_W, 0x00c0ff0f, + (u_int)jtype, reverse, (u_int)jvalue); + break; + + case M_DPC: + if (off_dpc == (u_int)-1) + bpf_error("'dpc' supported only on SS7"); + /* dpc coded on 14 bits so max value 16383 */ + if (jvalue > 16383) + bpf_error("dpc value %u too big; max value = 16383", + jvalue); + /* the following instructions are made to convert jvalue + * to the forme used to write dpc in an ss7 message*/ + val1 = jvalue & 0x000000ff; + val1 = val1 << 24; + val2 = jvalue & 0x00003f00; + val2 = val2 << 8; + jvalue = val1 + val2; + b0 = gen_ncmp(OR_PACKET, off_dpc, BPF_W, 0xff3f0000, + (u_int)jtype, reverse, (u_int)jvalue); + break; + + case M_SLS: + if (off_sls == (u_int)-1) + bpf_error("'sls' supported only on SS7"); + /* sls coded on 4 bits so max value 15 */ + if (jvalue > 15) + bpf_error("sls value %u too big; max value = 15", + jvalue); + /* the following instruction is made to convert jvalue + * to the forme used to write sls in an ss7 message*/ + jvalue = jvalue << 4; + b0 = gen_ncmp(OR_PACKET, off_sls, BPF_B, 0xf0, + (u_int)jtype,reverse, (u_int)jvalue); + break; + + default: + abort(); + } + return b0; +} static struct block * gen_msg_abbrev(type) diff --git a/contrib/libpcap/gencode.h b/contrib/libpcap/gencode.h index 83de011..56f3257 100644 --- a/contrib/libpcap/gencode.h +++ b/contrib/libpcap/gencode.h @@ -18,7 +18,7 @@ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * @(#) $Header: /tcpdump/master/libpcap/gencode.h,v 1.60 2004/06/16 08:20:30 hannes Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/gencode.h,v 1.60.2.5 2005/06/20 21:30:17 guy Exp $ (LBL) */ /* @@ -55,6 +55,10 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#ifndef HAVE___ATTRIBUTE__ +#define __attribute__(x) +#endif /* HAVE___ATTRIBUTE__ */ + /* Address qualifiers. */ #define Q_HOST 1 @@ -63,6 +67,7 @@ #define Q_GATEWAY 4 #define Q_PROTO 5 #define Q_PROTOCHAIN 6 +#define Q_PORTRANGE 7 /* Protocol qualifiers. */ @@ -119,6 +124,8 @@ #define Q_ISIS_PSNP 38 #define Q_ISIS_LSP 39 +#define Q_RADIO 40 + /* Directional qualifiers. */ #define Q_SRC 1 @@ -166,6 +173,13 @@ end-to-end circuits, ILMI circuits or connection signalling circuit. */ +/*MTP3 field types */ +#define M_SIO 1 +#define M_OPC 2 +#define M_DPC 3 +#define M_SLS 4 + + struct slist; struct stmt { @@ -275,10 +289,12 @@ struct block *gen_inbound(int); struct block *gen_vlan(int); struct block *gen_mpls(int); -struct block *gen_atmfield_code(int atmfield, bpf_u_int32 jvalue, bpf_u_int32 jtype, int reverse); +struct block *gen_atmfield_code(int atmfield, bpf_int32 jvalue, bpf_u_int32 jtype, int reverse); struct block *gen_atmtype_abbrev(int type); struct block *gen_atmmulti_abbrev(int type); +struct block *gen_mtp3field_code(int mtp3field, bpf_u_int32 jvalue, bpf_u_int32 jtype, int reverse); + struct block *gen_pf_ifname(const char *); struct block *gen_pf_rnr(int); struct block *gen_pf_srnr(int); @@ -289,10 +305,7 @@ struct block *gen_pf_dir(int); void bpf_optimize(struct block **); void bpf_error(const char *, ...) -#if HAVE___ATTRIBUTE__ - __attribute__((noreturn, format (printf, 1, 2))) -#endif -; + __attribute__((noreturn, format (printf, 1, 2))); void finish_parse(struct block *); char *sdup(const char *); diff --git a/contrib/libpcap/grammar.y b/contrib/libpcap/grammar.y index 4817181..1969186 100644 --- a/contrib/libpcap/grammar.y +++ b/contrib/libpcap/grammar.y @@ -22,7 +22,7 @@ */ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/grammar.y,v 1.86 2004/12/18 08:49:23 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/grammar.y,v 1.86.2.4 2005/06/20 21:30:17 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -97,6 +97,7 @@ pcap_parse() struct { struct qual q; int atmfieldtype; + int mtp3fieldtype; struct block *b; } blk; struct block *rblk; @@ -112,9 +113,12 @@ pcap_parse() %type <i> atmtype atmmultitype %type <blk> atmfield %type <blk> atmfieldvalue atmvalue atmlistvalue +%type <blk> mtp3field +%type <blk> mtp3fieldvalue mtp3value mtp3listvalue + %token DST SRC HOST GATEWAY -%token NET NETMASK PORT LESS GREATER PROTO PROTOCHAIN CBYTE +%token NET NETMASK PORT PORTRANGE LESS GREATER PROTO PROTOCHAIN CBYTE %token ARP RARP IP SCTP TCP UDP ICMP IGMP IGRP PIM VRRP %token ATALK AARP DECNET LAT SCA MOPRC MOPDL %token TK_BROADCAST TK_MULTICAST @@ -134,6 +138,8 @@ pcap_parse() %token LANE LLC METAC BCC SC ILMIC OAMF4EC OAMF4SC %token OAM OAMF4 CONNECTMSG METACONNECT %token VPI VCI +%token RADIO +%token SIO OPC DPC SLS %type <s> ID %type <e> EID @@ -254,6 +260,7 @@ rterm: head id { $$ = $2; } | atmtype { $$.b = gen_atmtype_abbrev($1); $$.q = qerr; } | atmmultitype { $$.b = gen_atmmulti_abbrev($1); $$.q = qerr; } | atmfield atmvalue { $$.b = $2.b; $$.q = qerr; } + | mtp3field mtp3value { $$.b = $2.b; $$.q = qerr; } ; /* protocol level qualifiers */ pqual: pname @@ -271,6 +278,7 @@ dqual: SRC { $$ = Q_SRC; } aqual: HOST { $$ = Q_HOST; } | NET { $$ = Q_NET; } | PORT { $$ = Q_PORT; } + | PORTRANGE { $$ = Q_PORTRANGE; } ; /* non-directional address type qualifiers */ ndaqual: GATEWAY { $$ = Q_GATEWAY; } @@ -312,6 +320,7 @@ pname: LINK { $$ = Q_LINK; } | STP { $$ = Q_STP; } | IPX { $$ = Q_IPX; } | NETBEUI { $$ = Q_NETBEUI; } + | RADIO { $$ = Q_RADIO; } ; other: pqual TK_BROADCAST { $$ = gen_broadcast($1); } | pqual TK_MULTICAST { $$ = gen_multicast($1); } @@ -413,18 +422,41 @@ atmfield: VPI { $$.atmfieldtype = A_VPI; } | VCI { $$.atmfieldtype = A_VCI; } ; atmvalue: atmfieldvalue - | relop NUM { $$.b = gen_atmfield_code($<blk>0.atmfieldtype, (u_int)$2, (u_int)$1, 0); } - | irelop NUM { $$.b = gen_atmfield_code($<blk>0.atmfieldtype, (u_int)$2, (u_int)$1, 1); } + | relop NUM { $$.b = gen_atmfield_code($<blk>0.atmfieldtype, (bpf_int32)$2, (bpf_u_int32)$1, 0); } + | irelop NUM { $$.b = gen_atmfield_code($<blk>0.atmfieldtype, (bpf_int32)$2, (bpf_u_int32)$1, 1); } | paren atmlistvalue ')' { $$.b = $2.b; $$.q = qerr; } ; atmfieldvalue: NUM { $$.atmfieldtype = $<blk>0.atmfieldtype; if ($$.atmfieldtype == A_VPI || $$.atmfieldtype == A_VCI) - $$.b = gen_atmfield_code($$.atmfieldtype, (u_int) $1, BPF_JEQ, 0); + $$.b = gen_atmfield_code($$.atmfieldtype, (bpf_int32) $1, BPF_JEQ, 0); } ; atmlistvalue: atmfieldvalue | atmlistvalue or atmfieldvalue { gen_or($1.b, $3.b); $$ = $3; } ; + /* MTP3 field types quantifier */ +mtp3field: SIO { $$.mtp3fieldtype = M_SIO; } + | OPC { $$.mtp3fieldtype = M_OPC; } + | DPC { $$.mtp3fieldtype = M_DPC; } + | SLS { $$.mtp3fieldtype = M_SLS; } + ; +mtp3value: mtp3fieldvalue + | relop NUM { $$.b = gen_mtp3field_code($<blk>0.mtp3fieldtype, (u_int)$2, (u_int)$1, 0); } + | irelop NUM { $$.b = gen_mtp3field_code($<blk>0.mtp3fieldtype, (u_int)$2, (u_int)$1, 1); } + | paren mtp3listvalue ')' { $$.b = $2.b; $$.q = qerr; } + ; +mtp3fieldvalue: NUM { + $$.mtp3fieldtype = $<blk>0.mtp3fieldtype; + if ($$.mtp3fieldtype == M_SIO || + $$.mtp3fieldtype == M_OPC || + $$.mtp3fieldtype == M_DPC || + $$.mtp3fieldtype == M_SLS ) + $$.b = gen_mtp3field_code($$.mtp3fieldtype, (u_int) $1, BPF_JEQ, 0); + } + ; +mtp3listvalue: mtp3fieldvalue + | mtp3listvalue or mtp3fieldvalue { gen_or($1.b, $3.b); $$ = $3; } + ; %% diff --git a/contrib/libpcap/inet.c b/contrib/libpcap/inet.c index 561781a..fb05b76 100644 --- a/contrib/libpcap/inet.c +++ b/contrib/libpcap/inet.c @@ -34,7 +34,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.66 2005/02/10 19:38:06 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.66.2.1 2005/06/20 21:30:17 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -539,6 +539,9 @@ pcap_lookupnet(device, netp, maskp, errbuf) #ifdef HAVE_DAG_API || strstr(device, "dag") != NULL #endif +#ifdef HAVE_SEPTEL_API + || strstr(device, "septel") != NULL +#endif ) { *netp = *maskp = 0; return 0; diff --git a/contrib/libpcap/nametoaddr.c b/contrib/libpcap/nametoaddr.c index ac56539..a795e49 100644 --- a/contrib/libpcap/nametoaddr.c +++ b/contrib/libpcap/nametoaddr.c @@ -24,7 +24,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/nametoaddr.c,v 1.77 2005/03/27 22:26:25 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/nametoaddr.c,v 1.77.2.3 2005/04/20 11:13:51 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -74,7 +74,7 @@ struct rtentry; /* declarations in <net/if.h> */ #include <ctype.h> #include <errno.h> #include <stdlib.h> -#include <memory.h> +#include <string.h> #include <stdio.h> #include "pcap-int.h" @@ -216,6 +216,51 @@ pcap_nametoport(const char *name, int *port, int *proto) return 0; } +/* + * Convert a string in the form PPP-PPP, where correspond to ports, to + * a starting and ending port in a port range. + * Return 0 on failure. + */ +int +pcap_nametoportrange(const char *name, int *port1, int *port2, int *proto) +{ + u_int p1, p2; + char *off, *cpy; + int save_proto; + + if (sscanf(name, "%d-%d", &p1, &p2) != 2) { + if ((cpy = strdup(name)) == NULL) + return 0; + + if ((off = strchr(cpy, '-')) == NULL) { + free(cpy); + return 0; + } + + *off = '\0'; + + if (pcap_nametoport(cpy, port1, proto) == 0) { + free(cpy); + return 0; + } + save_proto = *proto; + + if (pcap_nametoport(off + 1, port2, proto) == 0) { + free(cpy); + return 0; + } + + if (*proto != save_proto) + *proto = PROTO_UNDEF; + } else { + *port1 = p1; + *port2 = p2; + *proto = PROTO_UNDEF; + } + + return 1; +} + int pcap_nametoproto(const char *str) { @@ -413,6 +458,11 @@ pcap_ether_hostton(const char *name) #else #if !defined(HAVE_DECL_ETHER_HOSTTON) || !HAVE_DECL_ETHER_HOSTTON +#ifndef HAVE_STRUCT_ETHER_ADDR +struct ether_addr { + unsigned char ether_addr_octet[6]; +}; +#endif extern int ether_hostton(const char *, struct ether_addr *); #endif diff --git a/contrib/libpcap/pcap-bpf.c b/contrib/libpcap/pcap-bpf.c index 085f181..ccf9d73 100644 --- a/contrib/libpcap/pcap-bpf.c +++ b/contrib/libpcap/pcap-bpf.c @@ -20,7 +20,7 @@ */ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.86 2005/02/26 21:58:05 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.86.2.4 2005/06/04 02:53:16 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -59,7 +59,7 @@ static const char rcsid[] _U_ = #include <net/if_types.h> /* for IFT_ values */ #include <sys/sysconfig.h> #include <sys/device.h> -#include <odmi.h> +#include <sys/cfgodm.h> #include <cf.h> #ifdef __64BIT__ @@ -105,6 +105,7 @@ static int odmlockid = 0; #include "gencode.h" /* for "no_optimize" */ static int pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp); +static int pcap_setdirection_bpf(pcap_t *, direction_t); static int pcap_set_datalink_bpf(pcap_t *p, int dlt); static int @@ -729,7 +730,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, #endif #ifdef PCAP_FDDIPAD if (v == DLT_FDDI) - p->fddipad = PCAP_FDDIPAD: + p->fddipad = PCAP_FDDIPAD; else p->fddipad = 0; #endif @@ -996,29 +997,30 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, * there (and in sufficiently recent versions of OpenBSD * "select()" and "poll()" should work correctly). * + * In addition, in Mac OS X 10.4, "select()" and "poll()" don't + * work on *any* character devices, including BPF devices. + * * XXX - what about AIX? */ + p->selectable_fd = p->fd; /* assume select() works until we know otherwise */ if (uname(&osinfo) == 0) { /* * We can check what OS this is. */ - if (strcmp(osinfo.sysname, "FreeBSD") == 0 && - (strncmp(osinfo.release, "4.3-", 4) == 0 || - strncmp(osinfo.release, "4.4-", 4) == 0)) - p->selectable_fd = -1; - else - p->selectable_fd = p->fd; - } else { - /* - * We can't find out what OS this is, so assume we can - * do a "select()" or "poll()". - */ - p->selectable_fd = p->fd; + if (strcmp(osinfo.sysname, "FreeBSD") == 0) { + if (strncmp(osinfo.release, "4.3-", 4) == 0 || + strncmp(osinfo.release, "4.4-", 4) == 0) + p->selectable_fd = -1; + } else if (strcmp(osinfo.sysname, "Darwin") == 0) { + if (strncmp(osinfo.release, "8.", 2) == 0) + p->selectable_fd = -1; + } } p->read_op = pcap_read_bpf; p->inject_op = pcap_inject_bpf; p->setfilter_op = pcap_setfilter_bpf; + p->setdirection_op = pcap_setdirection_bpf; p->set_datalink_op = pcap_set_datalink_bpf; p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; @@ -1088,6 +1090,42 @@ pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp) return (0); } +/* + * Set direction flag: Which packets do we accept on a forwarding + * single device? IN, OUT or both? + */ +static int +pcap_setdirection_bpf(pcap_t *p, direction_t d) +{ +#ifdef BIOCSSEESENT + u_int seesent; +#endif + + /* + * We don't support D_OUT. + */ + if (d == D_OUT) { + snprintf(p->errbuf, sizeof(p->errbuf), + "Setting direction to D_OUT is not supported on BPF"); + return -1; + } +#ifdef BIOCSSEESENT + seesent = (d == D_INOUT); + if (ioctl(p->fd, BIOCSSEESENT, &seesent) == -1) { + (void) snprintf(p->errbuf, sizeof(p->errbuf), + "Cannot set direction to %s: %s", + (d == D_INOUT) ? "D_INOUT" : "D_IN", + strerror(errno)); + return (-1); + } + return (0); +#else + (void) snprintf(p->errbuf, sizeof(p->errbuf), + "This system doesn't support BIOCSSEESENT, so the direction can't be set"); + return (-1); +#endif +} + static int pcap_set_datalink_bpf(pcap_t *p, int dlt) { diff --git a/contrib/libpcap/pcap-bpf.h b/contrib/libpcap/pcap-bpf.h index deb15ac..9811613 100644 --- a/contrib/libpcap/pcap-bpf.h +++ b/contrib/libpcap/pcap-bpf.h @@ -37,7 +37,7 @@ * * @(#)bpf.h 7.1 (Berkeley) 5/7/91 * - * @(#) $Header: /tcpdump/master/libpcap/pcap-bpf.h,v 1.34 2005/02/08 20:03:15 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/pcap-bpf.h,v 1.34.2.5 2005/05/27 23:33:00 guy Exp $ (LBL) */ /* @@ -147,7 +147,7 @@ struct bpf_version { * 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/SNAP encapsulated atm */ +#define DLT_ATM_RFC1483 11 /* LLC-encapsulated ATM */ #ifdef __OpenBSD__ #define DLT_RAW 14 /* raw IP */ @@ -423,8 +423,13 @@ struct bpf_version { #define DLT_APPLE_IP_OVER_IEEE1394 138 /* - * 139 through 142 are reserved for SS7. + * Various SS7 encapsulations, as per a request from Jeff Morriss + * <jeff.morriss[AT]ulticom.com> 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. @@ -581,6 +586,14 @@ struct bpf_version { #define DLT_ERF_POS 176 /* Packet-over-SONET */ /* + * Requested by Daniele Orlandi <daniele@orlandi.com> 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 + +/* * The instruction encodings. */ /* instruction classes */ diff --git a/contrib/libpcap/pcap-dag.c b/contrib/libpcap/pcap-dag.c index a30f970..0587856 100644 --- a/contrib/libpcap/pcap-dag.c +++ b/contrib/libpcap/pcap-dag.c @@ -15,7 +15,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.21 2005/04/03 23:56:47 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.21.2.1 2005/05/03 18:54:35 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -507,6 +507,7 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu handle->read_op = dag_read; handle->inject_op = dag_inject; handle->setfilter_op = dag_setfilter; + handle->setdirection_op = NULL; /* Not implemented.*/ handle->set_datalink_op = dag_set_datalink; handle->getnonblock_op = pcap_getnonblock_fd; handle->setnonblock_op = dag_setnonblock; diff --git a/contrib/libpcap/pcap-dlpi.c b/contrib/libpcap/pcap-dlpi.c index c927629..a9a4dc3 100644 --- a/contrib/libpcap/pcap-dlpi.c +++ b/contrib/libpcap/pcap-dlpi.c @@ -20,8 +20,9 @@ * * This code contributed by Atanu Ghosh (atanu@cs.ucl.ac.uk), * University College London, and subsequently modified by - * Guy Harris (guy@alum.mit.edu) and Mark Pizzolato - * <List-tcpdump-workers@subscriptions.pizzolato.net>. + * Guy Harris (guy@alum.mit.edu), Mark Pizzolato + * <List-tcpdump-workers@subscriptions.pizzolato.net>, + * and Mark C. Brown (mbrown@hp.com). */ /* @@ -37,7 +38,8 @@ * - It might be desirable to use pfmod(7) to filter packets in the * kernel when possible. * - * - The HP-UX 10.20 DLPI Programmer's Guide used to be available + * - An older version of the HP-UX DLPI Programmer's Guide, which + * I think was advertised as the 10.20 version, used to be available * at * * http://docs.hp.com/hpux/onlinedocs/B2355-90093/B2355-90093.html @@ -48,21 +50,27 @@ * * in PDF form. * - * - The HP-UX 11.00 DLPI Programmer's Guide is available at + * - The HP-UX 10.x, 11.0, and 11i v1.6 version of the HP-UX DLPI + * Programmer's Guide, which I think was once advertised as the + * 11.00 version is available at * - * http://docs.hp.com/hpux/onlinedocs/B2355-90139/B2355-90139.html + * http://docs.hp.com/en/B2355-90139/index.html * - * and in PDF form at + * - The HP-UX 11i v2 version of the HP-UX DLPI Programmer's Guide + * is available at * - * http://h21007.www2.hp.com/dspp/files/unprotected/Drivers/Docs/Refs/B2355-90139.pdf + * http://docs.hp.com/en/B2355-90871/index.html * - * - Both of the HP documents describe raw-mode services, which are - * what we use if DL_HP_RAWDLS is defined. + * - All of the HP documents describe raw-mode services, which are + * what we use if DL_HP_RAWDLS is defined. XXX - we use __hpux + * in some places to test for HP-UX, but use DL_HP_RAWDLS in + * other places; do we support any versions of HP-UX without + * DL_HP_RAWDLS? */ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.108 2004/10/19 07:06:12 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.108.2.5 2005/05/03 18:54:35 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -158,9 +166,12 @@ static const char rcsid[] _U_ = /* Forwards */ static char *split_dname(char *, int *, char *); static int dl_doattach(int, int, char *); +#ifdef DL_HP_RAWDLS +static int dl_dohpuxbind(int, char *); +#endif static int dlattachreq(int, bpf_u_int32, char *); static int dlbindreq(int, bpf_u_int32, char *); -static int dlbindack(int, char *, char *); +static int dlbindack(int, char *, char *, int *); static int dlpromisconreq(int, bpf_u_int32, char *); static int dlokack(int, const char *, char *, char *); static int dlinforeq(int, char *); @@ -168,7 +179,7 @@ static int dlinfoack(int, char *, char *); #ifdef DL_HP_RAWDLS static int dlrawdatareq(int, const u_char *, int); #endif -static int recv_ack(int, int, const char *, char *, char *); +static int recv_ack(int, int, const char *, char *, char *, int *); static char *dlstrerror(bpf_u_int32); static char *dlprim(bpf_u_int32); #if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H) @@ -411,7 +422,7 @@ pcap_inject_dlpi(pcap_t *p, const void *buf, size_t size) ret = -1; #endif /* raw mode */ return (ret); -} +} #ifndef DL_IPATM #define DL_IPATM 0x12 /* ATM Classical IP interface */ @@ -510,9 +521,8 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, #ifdef DL_HP_RAWDLS /* * XXX - HP-UX 10.20 and 11.xx don't appear to support sending and - * receiving packets on the same descriptor - you have to bind the - * descriptor on which you receive to a SAP of 22 and bind the - * descriptor on which you send to a SAP of 24. + * receiving packets on the same descriptor - you need separate + * descriptors for sending and receiving, bound to different SAPs. * * If the open fails, we just leave -1 in "p->send_fd" and reject * attempts to send packets, just as if, in pcap-bpf.c, we fail @@ -622,12 +632,14 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, } /* - ** Bind (defer if using HP-UX 9 or HP-UX 10.20, totally skip if - ** using SINIX) + ** Bind (defer if using HP-UX 9 or HP-UX 10.20 or later, totally + ** skip if using SINIX) */ -#if !defined(HAVE_HPUX9) && !defined(HAVE_HPUX10_20) && !defined(sinix) +#if !defined(HAVE_HPUX9) && !defined(HAVE_HPUX10_20_OR_LATER) && !defined(sinix) #ifdef _AIX - /* According to IBM's AIX Support Line, the dl_sap value + /* + ** AIX. + ** According to IBM's AIX Support Line, the dl_sap value ** should not be less than 0x600 (1536) for standard Ethernet. ** However, we seem to get DL_BADADDR - "DLSAP addr in improper ** format or invalid" - errors if we use 1537 on the "tr0" @@ -645,34 +657,33 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, */ if ((dlbindreq(p->fd, 1537, ebuf) < 0 && dlbindreq(p->fd, 2, ebuf) < 0) || - dlbindack(p->fd, (char *)buf, ebuf) < 0) + dlbindack(p->fd, (char *)buf, ebuf, NULL) < 0) goto bad; #elif defined(DL_HP_RAWDLS) /* - ** This is the descriptor on which we receive packets; we - ** bind it to 22, as that's INSAP, as per the HP-UX DLPI - ** Programmer's Guide. + ** HP-UX 10.0x and 10.1x. */ - if (dlbindreq(p->fd, 22, ebuf) < 0 || - dlbindack(p->fd, (char *)buf, ebuf) < 0) + if (dl_dohpuxbind(p->fd, ebuf) < 0) goto bad; - if (p->send_fd >= 0) { /* - ** This is the descriptor on which we send packets; we - ** bind it to 24, as that's OUTSAP, as per the HP-UX - ** DLPI Programmer's Guide. + ** XXX - if this fails, just close send_fd and + ** set it to -1, so that you can't send but can + ** still receive? */ - if (dlbindreq(p->send_fd, 24, ebuf) < 0 || - dlbindack(p->send_fd, (char *)buf, ebuf) < 0) + if (dl_dohpuxbind(p->send_fd, ebuf) < 0) goto bad; } #else /* neither AIX nor HP-UX */ + /* + ** Not Sinix, and neither AIX nor HP-UX - Solaris, and any other + ** OS using DLPI. + **/ if (dlbindreq(p->fd, 0, ebuf) < 0 || - dlbindack(p->fd, (char *)buf, ebuf) < 0) + dlbindack(p->fd, (char *)buf, ebuf, NULL) < 0) goto bad; -#endif /* SAP to bind to */ -#endif /* HP-UX 9 or 10.20 or SINIX */ +#endif /* AIX vs. HP-UX vs. other */ +#endif /* !HP-UX 9 and !HP-UX 10.20 or later and !SINIX */ #ifdef HAVE_SOLARIS if (isatm) { @@ -710,8 +721,8 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, #endif } /* - ** Try to enable sap (when not in promiscuous mode when using - ** using HP-UX, when not doing SunATM on Solaris, and never + ** Try to enable SAP promiscuity (when not in promiscuous mode + ** when using HP-UX, when not doing SunATM on Solaris, and never ** under SINIX) (Not necessary on send FD) */ #ifndef sinix @@ -731,16 +742,29 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, else goto bad; } -#endif +#endif /* sinix */ /* - ** HP-UX 9 and HP-UX 10.20 must bind after setting promiscuous - ** options) + ** HP-UX 9, and HP-UX 10.20 or later, must bind after setting + ** promiscuous options. */ -#if defined(HAVE_HPUX9) || defined(HAVE_HPUX10_20) - if (dlbindreq(p->fd, 0, ebuf) < 0 || - dlbindack(p->fd, (char *)buf, ebuf) < 0) +#if defined(HAVE_HPUX9) || defined(HAVE_HPUX10_20_OR_LATER) + if (dl_dohpuxbind(p->fd, ebuf) < 0) goto bad; + /* + ** We don't set promiscuous mode on the send FD, but we'll defer + ** binding it anyway, just to keep the HP-UX 9/10.20 or later + ** code together. + */ + if (p->send_fd >= 0) { + /* + ** XXX - if this fails, just close send_fd and + ** set it to -1, so that you can't send but can + ** still receive? + */ + if (dl_dohpuxbind(p->send_fd, ebuf) < 0) + goto bad; + } #endif /* @@ -909,6 +933,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, p->read_op = pcap_read_dlpi; p->inject_op = pcap_inject_dlpi; p->setfilter_op = install_bpf_program; /* no kernel filtering */ + p->setdirection_op = NULL; /* Not implemented.*/ p->set_datalink_op = NULL; /* can't change data link type */ p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; @@ -990,6 +1015,47 @@ dl_doattach(int fd, int ppa, char *ebuf) return (0); } +#ifdef DL_HP_RAWDLS +static int +dl_dohpuxbind(int fd, char *ebuf) +{ + int hpsap; + int uerror; + bpf_u_int32 buf[MAXDLBUF]; + + /* + * XXX - we start at 22 because we used to use only 22, but + * that was just because that was the value used in some + * sample code from HP. With what value *should* we start? + * Does it matter, given that we're enabling SAP promiscuity + * on the input FD? + */ + hpsap = 22; + for (;;) { + if (dlbindreq(fd, hpsap, ebuf) < 0) + return (-1); + if (dlbindack(fd, (char *)buf, ebuf, &uerror) >= 0) + break; + /* + * For any error other than a UNIX EBUSY, give up. + */ + if (uerror != EBUSY) + return (-1); + + /* + * For EBUSY, try the next SAP value; that means that + * somebody else is using that SAP. Clear ebuf so + * that application doesn't report the "Device busy" + * error as a warning. + */ + *ebuf = '\0'; + hpsap++; + if (hpsap > 100) + return (-1); + } +} +#endif + int pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) { @@ -1054,7 +1120,7 @@ send_request(int fd, char *ptr, int len, char *what, char *ebuf) } static int -recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf) +recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf, int *uerror) { union DL_primitives *dlp; struct strbuf ctl; @@ -1087,12 +1153,16 @@ recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf) switch (dlp->error_ack.dl_errno) { case DL_SYSERR: + if (uerror != NULL) + *uerror = dlp->error_ack.dl_unix_errno; snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: UNIX error - %s", what, pcap_strerror(dlp->error_ack.dl_unix_errno)); break; default: + if (uerror != NULL) + *uerror = 0; snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: %s", what, dlstrerror(dlp->error_ack.dl_errno)); break; @@ -1100,6 +1170,8 @@ recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf) return (-1); default: + if (uerror != NULL) + *uerror = 0; snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: Unexpected primitive ack %s", what, dlprim(dlp->dl_primitive)); @@ -1107,6 +1179,8 @@ recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf) } if (ctl.len < size) { + if (uerror != NULL) + *uerror = 0; snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: Ack too small (%d < %d)", what, ctl.len, size); @@ -1338,26 +1412,23 @@ dlbindreq(int fd, bpf_u_int32 sap, char *ebuf) memset((char *)&req, 0, sizeof(req)); req.dl_primitive = DL_BIND_REQ; -#ifdef DL_HP_RAWDLS + /* XXX - what if neither of these are defined? */ +#if defined(DL_HP_RAWDLS) req.dl_max_conind = 1; /* XXX magic number */ - /* 22 is INSAP as per the HP-UX DLPI Programmer's Guide */ - req.dl_sap = 22; req.dl_service_mode = DL_HP_RAWDLS; -#else - req.dl_sap = sap; -#ifdef DL_CLDLS +#elif defined(DL_CLDLS) req.dl_service_mode = DL_CLDLS; #endif -#endif + req.dl_sap = sap; return (send_request(fd, (char *)&req, sizeof(req), "bind", ebuf)); } static int -dlbindack(int fd, char *bufp, char *ebuf) +dlbindack(int fd, char *bufp, char *ebuf, int *uerror) { - return (recv_ack(fd, DL_BIND_ACK_SIZE, "bind", bufp, ebuf)); + return (recv_ack(fd, DL_BIND_ACK_SIZE, "bind", bufp, ebuf, uerror)); } static int @@ -1375,7 +1446,7 @@ static int dlokack(int fd, const char *what, char *bufp, char *ebuf) { - return (recv_ack(fd, DL_OK_ACK_SIZE, what, bufp, ebuf)); + return (recv_ack(fd, DL_OK_ACK_SIZE, what, bufp, ebuf, NULL)); } @@ -1393,7 +1464,7 @@ static int dlinfoack(int fd, char *bufp, char *ebuf) { - return (recv_ack(fd, DL_INFO_ACK_SIZE, "info", bufp, ebuf)); + return (recv_ack(fd, DL_INFO_ACK_SIZE, "info", bufp, ebuf, NULL)); } #ifdef DL_HP_RAWDLS @@ -1674,20 +1745,20 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit, ip = (dl_hp_ppa_info_t *)((u_char *)ipstart + ip->dl_next_offset); } } - if (i == ap->dl_count) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, + if (i == ap->dl_count) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "can't find /dev/dlpi PPA for %s%d", device, unit); return (-1); - } - if (ip->dl_hdw_state == HDW_DEAD) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, + } + 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); - } - ppa = ip->dl_ppa; - free(ppa_data_buf); - return (ppa); + } + ppa = ip->dl_ppa; + free(ppa_data_buf); + return (ppa); } #endif diff --git a/contrib/libpcap/pcap-dos.c b/contrib/libpcap/pcap-dos.c index 21fd113..0700d6b 100644 --- a/contrib/libpcap/pcap-dos.c +++ b/contrib/libpcap/pcap-dos.c @@ -5,7 +5,7 @@ * pcap-dos.c: Interface to PKTDRVR, NDIS2 and 32-bit pmode * network drivers. * - * @(#) $Header: /tcpdump/master/libpcap/pcap-dos.c,v 1.1 2004/12/18 08:52:10 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/pcap-dos.c,v 1.1.2.1 2005/05/03 18:54:35 guy Exp $ (LBL) */ #include <stdio.h> @@ -172,6 +172,7 @@ pcap_t *pcap_open_live (const char *device_name, int snaplen, int promisc, 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->fd = ++ref_count; if (pcap->fd == 1) /* first time we're called */ diff --git a/contrib/libpcap/pcap-int.h b/contrib/libpcap/pcap-int.h index a64fc3c..7d3b763 100644 --- a/contrib/libpcap/pcap-int.h +++ b/contrib/libpcap/pcap-int.h @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.68 2004/12/18 08:52:10 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.68.2.2 2005/05/03 18:54:36 guy Exp $ (LBL) */ #ifndef pcap_int_h @@ -99,6 +99,14 @@ struct pcap_md { #endif }; +/* + * Ultrix, DEC OSF/1^H^H^H^H^H^H^H^H^HDigital UNIX^H^H^H^H^H^H^H^H^H^H^H^H + * Tru64 UNIX, and NetBSD pad to make everything line up on a nice boundary. + */ +#if defined(ultrix) || defined(__osf__) || (defined(__NetBSD__) && __NetBSD_Version__ > 106000000) +#define PCAP_FDDIPAD 3 +#endif + struct pcap { #ifdef WIN32 ADAPTER *adapter; @@ -142,12 +150,16 @@ struct pcap { */ u_char *pkt; + /* We're accepting only packets in this direction/these directions. */ + direction_t direction; + /* * 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 *, direction_t); int (*set_datalink_op)(pcap_t *, int); int (*getnonblock_op)(pcap_t *, char *); int (*setnonblock_op)(pcap_t *, int, char *); @@ -238,15 +250,6 @@ int yylex(void); int pcap_offline_read(pcap_t *, int, pcap_handler, u_char *); int pcap_read(pcap_t *, int cnt, pcap_handler, u_char *); - -/* - * Ultrix, DEC OSF/1^H^H^H^H^H^H^H^H^HDigital UNIX^H^H^H^H^H^H^H^H^H^H^H^H - * Tru64 UNIX, and NetBSD pad to make everything line up on a nice boundary. - */ -#if defined(ultrix) || defined(__osf__) || defined(__NetBSD__) -#define PCAP_FDDIPAD 3 -#endif - #ifndef HAVE_STRLCPY #define strlcpy(x, y, z) \ (strncpy((x), (y), (z)), \ diff --git a/contrib/libpcap/pcap-linux.c b/contrib/libpcap/pcap-linux.c index 89ad5c4..0cd6ca8 100644 --- a/contrib/libpcap/pcap-linux.c +++ b/contrib/libpcap/pcap-linux.c @@ -27,7 +27,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.110 2004/10/19 07:06:12 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.110.2.2 2005/06/20 21:30:18 guy Exp $ (LBL)"; #endif /* @@ -83,6 +83,10 @@ static const char rcsid[] _U_ = #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 <errno.h> #include <stdlib.h> @@ -191,6 +195,7 @@ 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 *, direction_t); static void pcap_close_linux(pcap_t *); /* @@ -244,7 +249,13 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, } #endif /* HAVE_DAG_API */ - /* Allocate a handle for this session. */ +#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) { @@ -407,6 +418,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, 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; @@ -504,19 +516,37 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) } #ifdef HAVE_PF_PACKET_SOCKETS - /* - * If this is from the loopback device, reject outgoing packets; - * we'll see the packet as an incoming packet as well, and - * we don't want to see it twice. - * - * We can only do this if we're using PF_PACKET; the address - * returned for SOCK_PACKET is a "sockaddr_pkt" which lacks - * the relevant packet type information. - */ - if (!handle->md.sock_packet && - from.sll_ifindex == handle->md.lo_ifindex && - from.sll_pkttype == PACKET_OUTGOING) - return 0; + if (!handle->md.sock_packet) { + /* + * Do checks based on packet direction. + * We can only do this if we're using PF_PACKET; the + * address returned for SOCK_PACKET is a "sockaddr_pkt" + * which lacks the relevant packet type information. + */ + if (from.sll_pkttype == PACKET_OUTGOING) { + /* + * Outgoing packet. + * If this is from the loopback device, reject it; + * we'll see the packet as an incoming packet as well, + * and we don't want to see it twice. + */ + if (from.sll_ifindex == handle->md.lo_ifindex) + return 0; + + /* + * If the user only wants incoming packets, reject it. + */ + if (handle->direction == D_IN) + return 0; + } else { + /* + * Incoming packet. + * If the user only wants outgoing packets, reject it. + */ + if (handle->direction == D_OUT) + return 0; + } + } #endif #ifdef HAVE_PF_PACKET_SOCKETS @@ -835,6 +865,11 @@ pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) return (-1); #endif /* HAVE_DAG_API */ +#ifdef HAVE_SEPTEL_API + if (septel_platform_finddevs(alldevsp, errbuf) < 0) + return (-1); +#endif /* HAVE_SEPTEL_API */ + return (0); } @@ -975,6 +1010,28 @@ pcap_setfilter_linux(pcap_t *handle, struct bpf_program *filter) } /* + * Set direction flag: Which packets do we accept on a forwarding + * single device? IN, OUT or both? + */ +static int +pcap_setdirection_linux(pcap_t *handle, direction_t d) +{ +#ifdef HAVE_PF_PACKET_SOCKETS + if (!handle->md.sock_packet) { + handle->direction = d; + return 0; + } +#endif + /* + * We're not using PF_PACKET sockets, so we can't determine + * the direction of the packet. + */ + snprintf(handle->errbuf, sizeof(handle->errbuf), + "Setting direction is not supported on SOCK_PACKET sockets"); + return -1; +} + +/* * Linux uses the ARP hardware type to identify the type of an * interface. pcap uses the DLT_xxx constants for this. This * function takes a pointer to a "pcap_t", and an ARPHRD_xxx diff --git a/contrib/libpcap/pcap-namedb.h b/contrib/libpcap/pcap-namedb.h index 29b217d..acaabd9 100644 --- a/contrib/libpcap/pcap-namedb.h +++ b/contrib/libpcap/pcap-namedb.h @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#) $Header: /tcpdump/master/libpcap/pcap-namedb.h,v 1.10 2005/03/17 07:02:32 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/pcap-namedb.h,v 1.10.2.1 2005/04/19 04:26:08 guy Exp $ (LBL) */ #ifndef lib_pcap_namedb_h @@ -65,6 +65,7 @@ struct addrinfo *pcap_nametoaddrinfo(const char *); 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 *); diff --git a/contrib/libpcap/pcap-nit.c b/contrib/libpcap/pcap-nit.c index 097c3be..94c4528 100644 --- a/contrib/libpcap/pcap-nit.c +++ b/contrib/libpcap/pcap-nit.c @@ -20,7 +20,7 @@ */ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.57 2004/10/19 07:06:13 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.57.2.1 2005/05/03 18:54:37 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -334,6 +334,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, p->read_op = pcap_read_nit; p->inject_op = pcap_inject_nit; p->setfilter_op = install_bpf_program; /* no kernel filtering */ + p->setdirection_op = NULL; /* Not implemented. */ p->set_datalink_op = NULL; /* can't change data link type */ p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; diff --git a/contrib/libpcap/pcap-pf.c b/contrib/libpcap/pcap-pf.c index 1c3158a..e733540 100644 --- a/contrib/libpcap/pcap-pf.c +++ b/contrib/libpcap/pcap-pf.c @@ -24,7 +24,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.91 2005/02/26 21:58:06 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.91.2.2 2005/05/03 18:54:37 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -129,7 +129,7 @@ pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user) */ n = 0; #ifdef PCAP_FDDIPAD - pad = p->fddipad; + pad = pc->fddipad; #endif while (cc > 0) { /* @@ -191,7 +191,7 @@ pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user) * #ifdef PCAP_FDDIPAD * Note: the filter code was generated assuming - * that p->fddipad was the amount of padding + * that pc->fddipad was the amount of padding * before the header, as that's what's required * in the kernel, so we run the filter before * skipping that padding. @@ -448,7 +448,7 @@ your system may not be properly configured; see the packetfilter(4) man page\n", /* set truncation */ #ifdef PCAP_FDDIPAD if (p->linktype == DLT_FDDI) { - p->fddipad = PCAP_FDDIPAD: + p->fddipad = PCAP_FDDIPAD; /* packetfilter includes the padding in the snapshot */ snaplen += PCAP_FDDIPAD; @@ -497,6 +497,7 @@ your system may not be properly configured; see the packetfilter(4) man page\n", p->read_op = pcap_read_pf; p->inject_op = pcap_inject_pf; p->setfilter_op = pcap_setfilter_pf; + p->setdirection_op = NULL; /* Not implemented. */ p->set_datalink_op = NULL; /* can't change data link type */ p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; diff --git a/contrib/libpcap/pcap-septel.c b/contrib/libpcap/pcap-septel.c new file mode 100644 index 0000000..5169ec0 --- /dev/null +++ b/contrib/libpcap/pcap-septel.c @@ -0,0 +1,307 @@ +/* + * pcap-septel.c: Packet capture interface for Intel/Septel card. + * + * The functionality of this code attempts to mimic that of pcap-linux as much + * as possible. This code is compiled in several different ways depending on + * whether SEPTEL_ONLY and HAVE_SEPTEL_API are defined. If HAVE_SEPTEL_API is + * not defined it should not get compiled in, otherwise if SEPTEL_ONLY is + * defined then the 'septel_' function calls are renamed to 'pcap_' + * equivalents. If SEPTEL_ONLY is not defined then nothing is altered - the + * septel_ functions will be called as required from their + * pcap-linux/equivalents. + * + * Authors: Gilbert HOYEK (gil_hoyek@hotmail.com), Elias M. KHOURY + * (+961 3 485243) + */ + +#ifndef lint +static const char rcsid[] _U_ = + "@(#) $Header: /tcpdump/master/libpcap/pcap-septel.c,v 1.1.2.2 2005/06/21 01:03:23 guy Exp $"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <sys/param.h> + +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include "pcap-int.h" + +#include <ctype.h> +#include <netinet/in.h> +#include <sys/mman.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <unistd.h> + +#ifdef HAVE_SEPTEL_API +#include <msg.h> +#include <ss7_inc.h> +#include <sysgct.h> +#include <pack.h> +#include <system.h> +#endif /* HAVE_SEPTEL_API */ + +#ifdef SEPTEL_ONLY +/* 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 +#define septel_platform_finddevs pcap_platform_finddevs +#endif /* SEPTEL_ONLY */ + +static int septel_setfilter(pcap_t *p, struct bpf_program *fp); +static int septel_stats(pcap_t *p, struct pcap_stat *ps); +static int septel_setnonblock(pcap_t *p, int nonblock, char *errbuf); + +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 + * error occured, or -2 if we were told to break out of the loop. + */ +static int septel_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { + + HDR *h; + MSG *m; + int processed = 0 ; + int t = 0 ; + + /* identifier for the message queue of the module(upe) from which we are capturing + * packets.These IDs are defined in system.txt . By default it is set to 0x2d + * so change it to 0xdd for technical reason and therefore the module id for upe becomes: + * LOCAL 0xdd * upe - Example user part task */ + unsigned int id = 0xdd; + + /* process the packets */ + do { + + unsigned short packet_len = 0; + int caplen = 0; + int counter = 0; + struct pcap_pkthdr pcap_header; + u_char *dp ; + + /* + * Has "pcap_breakloop()" been called? + */ +loop: + if (p->break_loop) { + /* + * Yes - clear the flag that indicates that + * it has, and return -2 to indicate that + * we were told to break out of the loop. + */ + p->break_loop = 0; + return -2; + } + + /*repeat until a packet is read + *a NULL message means : + * when no packet is in queue or all packets in queue already read */ + do { + /* receive packet in non-blocking mode + * GCT_grab is defined in the septel library software */ + h = GCT_grab(id); + + m = (MSG*)h; + /* a couter is added here to avoid an infinite loop + * that will cause our capture program GUI to freeze while waiting + * for a packet*/ + counter++ ; + + } + while ((m == NULL)&& (counter< 100)) ; + + if (m != NULL) { + + t = h->type ; + + /* catch only messages with type = 0xcf00 or 0x8f01 corrsponding to ss7 messages*/ + /* XXX = why not use API_MSG_TX_REQ for 0xcf00 and API_MSG_RX_IND + * for 0x8f01? */ + if ((t != 0xcf00) && (t != 0x8f01)) { + relm(h); + goto loop ; + } + + /* XXX - is API_MSG_RX_IND for an MTP2 or MTP3 message? */ + dp = get_param(m);/* get pointer to MSG parameter area (m->param) */ + packet_len = m->len; + caplen = p->snapshot ; + + + if (caplen > packet_len) { + + caplen = packet_len; + } + /* Run the packet filter if there is one. */ + if ((p->fcode.bf_insns == NULL) || bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen)) { + + + /* get a time stamp , consisting of : + * + * pcap_header.ts.tv_sec: + * ---------------------- + * a UNIX format time-in-seconds when he packet was captured, + * i.e. the number of seconds since Epoch time (January 1,1970, 00:00:00 GMT) + * + * pcap_header.ts.tv_usec : + * ------------------------ + * the number of microseconds since that second + * when the packet was captured + */ + + (void)gettimeofday(&pcap_header.ts, NULL); + + /* Fill in our own header data */ + pcap_header.caplen = caplen; + pcap_header.len = packet_len; + + /* Count the packet. */ + p->md.stat.ps_recv++; + + /* Call the user supplied callback function */ + callback(user, &pcap_header, dp); + + processed++ ; + + } + /* after being processed the packet must be + *released in order to receive another one */ + relm(h); + }else + processed++; + + } + while (processed < cnt) ; + + return processed ; +} + + +static int +septel_inject(pcap_t *handle, const void *buf _U_, size_t size _U_) +{ + strlcpy(handle->errbuf, "Sending packets isn't supported on Septel cards", + PCAP_ERRBUF_SIZE); + return (-1); +} + +/* + * Get 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. + * + * 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; + + handle->linktype = DLT_MTP2; + + handle->bufsize = 0; + + /* + * "select()" and "poll()" don't work on Septel queues + */ + handle->selectable_fd = -1; + + handle->read_op = septel_read; + handle->inject_op = septel_inject; + handle->setfilter_op = septel_setfilter; + handle->set_datalink_op = NULL; /* can't change data link type */ + handle->getnonblock_op = pcap_getnonblock_fd; + handle->setnonblock_op = septel_setnonblock; + handle->stats_op = septel_stats; + handle->close_op = septel_platform_close; + + return handle; + +fail: + if (handle != NULL) { + free(handle); + } + + return NULL; +} + +static int septel_stats(pcap_t *p, struct pcap_stat *ps) { + /*p->md.stat.ps_recv = 0;*/ + /*p->md.stat.ps_drop = 0;*/ + + *ps = p->md.stat; + + return 0; +} + + +int +septel_platform_finddevs(pcap_if_t **devlistp, char *errbuf) +{ +unsigned char *p; + const char description[512]= "Intel/Septel device"; + char name[512]="septel" ; + int ret = 0; + pcap_add_if(devlistp,name,0,description,errbuf); + + return (ret); +} + + +/* + * Installs the given bpf filter program in the given pcap structure. There is + * no attempt to store the filter in kernel memory as that is not supported + * with Septel cards. + */ +static int septel_setfilter(pcap_t *p, struct bpf_program *fp) { + if (!p) + return -1; + if (!fp) { + strncpy(p->errbuf, "setfilter: No filter specified", + sizeof(p->errbuf)); + return -1; + } + + /* Make our private copy of the filter */ + + if (install_bpf_program(p, fp) < 0) { + snprintf(p->errbuf, sizeof(p->errbuf), + "malloc: %s", pcap_strerror(errno)); + return -1; + } + + p->md.use_bpf = 0; + + return (0); +} + + +static int +septel_setnonblock(pcap_t *p, int nonblock, char *errbuf) +{ + return (0); +} diff --git a/contrib/libpcap/pcap-septel.h b/contrib/libpcap/pcap-septel.h new file mode 100644 index 0000000..1de6377 --- /dev/null +++ b/contrib/libpcap/pcap-septel.h @@ -0,0 +1,15 @@ +/* + * pcap-septel.c: Packet capture interface for Intel Septel card + * + * The functionality of this code attempts to mimic that of pcap-linux as much + * as possible. This code is only needed when compiling in the Intel/Septel + * card code at the same time as another type of device. + * + * Authors: Gilbert HOYEK (gil_hoyek@hotmail.com), Elias M. KHOURY + * (+961 3 485343); + * + * @(#) $Header: /tcpdump/master/libpcap/pcap-septel.h,v 1.1.2.1 2005/06/20 21:30:19 guy Exp $ + */ + +pcap_t *septel_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf); + diff --git a/contrib/libpcap/pcap-snit.c b/contrib/libpcap/pcap-snit.c index 47bf443..60abe64 100644 --- a/contrib/libpcap/pcap-snit.c +++ b/contrib/libpcap/pcap-snit.c @@ -25,7 +25,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.72 2004/10/19 07:06:13 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.72.2.1 2005/05/03 18:54:38 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -397,6 +397,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, p->read_op = pcap_read_snit; p->inject_op = pcap_inject_snit; p->setfilter_op = install_bpf_program; /* no kernel filtering */ + p->setdirection_op = NULL; /* Not implemented. */ p->set_datalink_op = NULL; /* can't change data link type */ p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; diff --git a/contrib/libpcap/pcap-snoop.c b/contrib/libpcap/pcap-snoop.c index acbe548..f6425f1 100644 --- a/contrib/libpcap/pcap-snoop.c +++ b/contrib/libpcap/pcap-snoop.c @@ -20,7 +20,7 @@ */ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.54 2004/10/19 07:06:14 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.54.2.1 2005/05/03 18:54:38 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -379,6 +379,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, p->read_op = pcap_read_snoop; p->inject_op = pcap_inject_snoop; p->setfilter_op = install_bpf_program; /* no kernel filtering */ + p->setdirection_op = NULL; /* Not implemented. */ p->set_datalink_op = NULL; /* can't change data link type */ p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; diff --git a/contrib/libpcap/pcap-win32.c b/contrib/libpcap/pcap-win32.c index cb6c696..5b814f0 100644 --- a/contrib/libpcap/pcap-win32.c +++ b/contrib/libpcap/pcap-win32.c @@ -32,7 +32,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.25 2005/02/26 21:58:06 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.25.2.2 2005/06/10 03:48:56 risso Exp $ (LBL)"; #endif #include <pcap-int.h> @@ -411,6 +411,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, 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; @@ -602,6 +603,8 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, #ifdef HAVE_DAG_API } #endif /* HAVE_DAG_API */ + p->setdirection_op = NULL; /* Not implemented. */ + /* XXX - can this be implemented on some versions of Windows? */ p->inject_op = pcap_inject_win32; p->set_datalink_op = NULL; /* can't change data link type */ p->getnonblock_op = pcap_getnonblock_win32; diff --git a/contrib/libpcap/pcap.3 b/contrib/libpcap/pcap.3 index 1e8e27e..69dde16 100644 --- a/contrib/libpcap/pcap.3 +++ b/contrib/libpcap/pcap.3 @@ -1,4 +1,4 @@ -.\" @(#) $Header: /tcpdump/master/libpcap/pcap.3,v 1.64 2004/12/17 21:27:54 guy Exp $ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap.3,v 1.64.2.4 2005/06/03 20:36:56 guy Exp $ .\" .\" Copyright (c) 1994, 1996, 1997 .\" The Regents of the University of California. All rights reserved. @@ -59,6 +59,10 @@ 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) @@ -75,7 +79,8 @@ int pcap_compile(pcap_t *p, struct bpf_program *fp, .ti +8 char *str, int optimize, bpf_u_int32 netmask) int pcap_setfilter(pcap_t *p, struct bpf_program *fp) -void pcap_freecode(struct bpf_program *); +void pcap_freecode(struct bpf_program *) +int pcap_setdirection(pcap_t *p, direction_t d) .ft .LP .ft B @@ -118,6 +123,7 @@ const char *pcap_lib_version(void) .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 @@ -773,6 +779,31 @@ 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 direction_t +is one of the constants +.BR D_IN , +.B D_OUT +or +.BR D_INOUT . +.B D_IN +will only capture packets received by the device, +.B D_OUT +will only capture packets sent by the device and +.B D_INOUT +will capture packets received by or sent by the device. +.B 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 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 @@ -1230,6 +1261,15 @@ 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 diff --git a/contrib/libpcap/pcap.c b/contrib/libpcap/pcap.c index 7cad9ea..e647dc5 100644 --- a/contrib/libpcap/pcap.c +++ b/contrib/libpcap/pcap.c @@ -33,7 +33,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.88 2005/02/08 20:03:15 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.88.2.3 2005/05/27 23:33:00 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -331,7 +331,7 @@ static struct dlt_choice dlt_choices[] = { DLT_CHOICE(DLT_SLIP, "SLIP"), DLT_CHOICE(DLT_PPP, "PPP"), DLT_CHOICE(DLT_FDDI, "FDDI"), - DLT_CHOICE(DLT_ATM_RFC1483, "RFC 1483 IP-over-ATM"), + DLT_CHOICE(DLT_ATM_RFC1483, "RFC 1483 LLC-encapsulated ATM"), DLT_CHOICE(DLT_RAW, "Raw IP"), DLT_CHOICE(DLT_SLIP_BSDOS, "BSD/OS SLIP"), DLT_CHOICE(DLT_PPP_BSDOS, "BSD/OS PPP"), @@ -369,6 +369,10 @@ static struct dlt_choice dlt_choices[] = { 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_SENTINEL }; @@ -685,6 +689,23 @@ pcap_setfilter(pcap_t *p, struct bpf_program *fp) return p->setfilter_op(p, fp); } +/* + * Set direction flag, which controls whether we accept only incoming + * packets, only outgoing packets, or both. + * Note that, depending on the platform, some or all direction arguments + * might not be supported. + */ +int +pcap_setdirection(pcap_t *p, direction_t d) +{ + if (p->setdirection_op == NULL) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "Setting direction is not implemented on this platform"); + return -1; + } else + return p->setdirection_op(p, d); +} + int pcap_stats(pcap_t *p, struct pcap_stat *ps) { diff --git a/contrib/libpcap/pcap.h b/contrib/libpcap/pcap.h index d3f1ba0..c8240ad 100644 --- a/contrib/libpcap/pcap.h +++ b/contrib/libpcap/pcap.h @@ -31,7 +31,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.52 2004/12/18 08:52:11 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.52.2.2 2005/06/03 20:36:56 guy Exp $ (LBL) */ #ifndef lib_pcap_h @@ -120,6 +120,12 @@ struct pcap_file_header { bpf_u_int32 linktype; /* data link type (LINKTYPE_*) */ }; +typedef enum { + D_INOUT = 0, + D_IN, + D_OUT +} direction_t; + /* * Each packet in the dump file is prepended with this generic header. * This gets around the problem of different headers for different @@ -218,6 +224,7 @@ 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 *, direction_t); int pcap_getnonblock(pcap_t *, char *); int pcap_setnonblock(pcap_t *, int, char *); void pcap_perror(pcap_t *, char *); @@ -247,10 +254,11 @@ 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 *); diff --git a/contrib/libpcap/savefile.c b/contrib/libpcap/savefile.c index 0a739fa..ec1088d 100644 --- a/contrib/libpcap/savefile.c +++ b/contrib/libpcap/savefile.c @@ -30,7 +30,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/savefile.c,v 1.126 2005/02/08 20:03:16 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/savefile.c,v 1.126.2.8 2005/06/03 20:36:57 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -98,7 +98,7 @@ static const char rcsid[] _U_ = * Setting O_BINARY on DOS/Windows is a bit tricky */ #if defined(WIN32) - #define SET_BINMODE(f) _setmode(fileno(f), O_BINARY) + #define SET_BINMODE(f) _setmode(_fileno(f), _O_BINARY) #elif defined(MSDOS) #if defined(__HIGHC__) #define SET_BINMODE(f) setmode(f, O_BINARY) @@ -269,10 +269,10 @@ static const char rcsid[] _U_ = #define LINKTYPE_APPLE_IP_OVER_IEEE1394 138 /* Apple IP-over-IEEE 1394 cooked header */ -#define LINKTYPE_RAWSS7 139 /* see rawss7.h for */ -#define LINKTYPE_RAWSS7_MTP2 140 /* information on these */ -#define LINKTYPE_RAWSS7_MTP3 141 /* definitions */ -#define LINKTYPE_RAWSS7_SCCP 142 +#define LINKTYPE_MTP2_WITH_PHDR 139 +#define LINKTYPE_MTP2 140 +#define LINKTYPE_MTP3 141 +#define LINKTYPE_SCCP 142 #define LINKTYPE_DOCSIS 143 /* DOCSIS MAC frames */ @@ -404,6 +404,14 @@ static const char rcsid[] _U_ = #define LINKTYPE_ERF_ETH 175 /* Ethernet */ #define LINKTYPE_ERF_POS 176 /* Packet-over-SONET */ +/* + * Requested by Daniele Orlandi <daniele@orlandi.com> for raw LAPD + * for vISDN (http://www.orlandi.com/visdn/). Its link-layer header + * includes additional information before the LAPD header, so it's + * not necessarily a generic LAPD header. + */ +#define LINKTYPE_LINUX_LAPD 177 + static struct linktype_map { int dlt; int linktype; @@ -530,6 +538,12 @@ static struct linktype_map { /* Apple IP-over-IEEE 1394 cooked header */ { DLT_APPLE_IP_OVER_IEEE1394, LINKTYPE_APPLE_IP_OVER_IEEE1394 }, + /* SS7 */ + { DLT_MTP2_WITH_PHDR, LINKTYPE_MTP2_WITH_PHDR }, + { DLT_MTP2, LINKTYPE_MTP2 }, + { DLT_MTP3, LINKTYPE_MTP3 }, + { DLT_SCCP, LINKTYPE_SCCP }, + /* DOCSIS MAC frames */ { DLT_DOCSIS, LINKTYPE_DOCSIS }, @@ -594,6 +608,9 @@ static struct linktype_map { { DLT_ERF_ETH, LINKTYPE_ERF_ETH }, { DLT_ERF_POS, LINKTYPE_ERF_POS }, + /* viSDN LAPD */ + { DLT_LINUX_LAPD, LINKTYPE_LINUX_LAPD }, + { -1, -1 } }; @@ -700,6 +717,18 @@ sf_inject(pcap_t *p, const void *buf _U_, size_t size _U_) return (-1); } +/* + * Set direction flag: Which packets do we accept on a forwarding + * single device? IN, OUT or both? + */ +static int +sf_setdirection(pcap_t *p, direction_t d) +{ + snprintf(p->errbuf, sizeof(p->errbuf), + "Setting direction is not supported on savefiles"); + return (-1); +} + static void sf_close(pcap_t *p) { @@ -716,7 +745,16 @@ pcap_open_offline(const char *fname, char *errbuf) pcap_t *p; if (fname[0] == '-' && fname[1] == '\0') + { fp = stdin; +#if defined(WIN32) || defined(MSDOS) + /* + * We're reading from the standard input, so put it in binary + * mode, as savefiles are binary files. + */ + SET_BINMODE(fp); +#endif + } else { #if !defined(WIN32) && !defined(MSDOS) fp = fopen(fname, "r"); @@ -892,21 +930,13 @@ pcap_fopen_offline(FILE *fp, char *errbuf) p->read_op = pcap_offline_read; p->inject_op = sf_inject; p->setfilter_op = install_bpf_program; + p->setdirection_op = sf_setdirection; p->set_datalink_op = NULL; /* we don't support munging link-layer headers */ p->getnonblock_op = sf_getnonblock; p->setnonblock_op = sf_setnonblock; p->stats_op = sf_stats; p->close_op = sf_close; -#if defined(WIN32) || defined(MSDOS) - /* - * If we're reading from the standard input, put it in binary - * mode, as savefiles are binary files. - */ - if (fp == stdin) - SET_BINMODE(fp); -#endif - return (p); bad: free(p); @@ -1212,6 +1242,12 @@ pcap_dump_file(pcap_dumper_t *p) return ((FILE *)p); } +long +pcap_dump_ftell(pcap_dumper_t *p) +{ + return (ftell((FILE *)p)); +} + int pcap_dump_flush(pcap_dumper_t *p) { diff --git a/contrib/libpcap/scanner.l b/contrib/libpcap/scanner.l index 73cb6d8..ab2b079 100644 --- a/contrib/libpcap/scanner.l +++ b/contrib/libpcap/scanner.l @@ -22,7 +22,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/scanner.l,v 1.99 2004/06/16 08:20:28 hannes Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/scanner.l,v 1.99.2.3 2005/06/20 21:30:19 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -183,6 +183,7 @@ igmp return IGMP; igrp return IGRP; pim return PIM; vrrp return VRRP; +radio return RADIO; ip6 { #ifdef INET6 @@ -234,6 +235,7 @@ host return HOST; net return NET; mask return NETMASK; port return PORT; +portrange return PORTRANGE; proto return PROTO; protochain { #ifdef NO_PROTOCHAIN @@ -284,6 +286,11 @@ srnr|subrulenum return PF_SRNR; reason return PF_REASON; action return PF_ACTION; +sio return SIO; +opc return OPC; +dpc return DPC; +sls return SLS; + [ \r\n\t] ; [+\-*/:\[\]!<>()&|=] return yytext[0]; ">=" return GEQ; |