From: Guy Harris Date: Sat, 4 Apr 2009 19:30:27 +0000 (-0700) Subject: From Bert Vermeulen: add a USB printer, and fix the error message X-Git-Tag: tcpdump-4.1.0~128 X-Git-Url: https://git.tcpdump.org/tcpdump/commitdiff_plain/2c28d8f466181bed668e9fa6dc8ed5d4821d159a From Bert Vermeulen: add a USB printer, and fix the error message printed when trying to print packets for a DLT_ for which we don't have a printer to indicate that you can still save to a capture file in that case. (Slightly changed not to require DLT_USB_LINUX_MMAPPED to be defined, for older libpcaps that only define DLT_USB_LINUX.) --- diff --git a/CREDITS b/CREDITS index ed82f792..fa62fe3e 100644 --- a/CREDITS +++ b/CREDITS @@ -27,6 +27,7 @@ Additional people who have contributed patches: Ben Byer Atsushi Onoe Ben Smithurst + Bert Vermeulen Bjoern A. Zeeb Brent L. Bates Brian Ginsbach diff --git a/INSTALL.txt b/INSTALL.txt index 3f845c05..a03e2c00 100644 --- a/INSTALL.txt +++ b/INSTALL.txt @@ -221,6 +221,7 @@ print-tftp.c - Trivial File Transfer Protocol printer routines print-timed.c - BSD time daemon protocol printer routines print-token.c - Token Ring printer routines print-udp.c - UDP printer routines +print-usb.c - USB printer routines print-vjc.c - PPP Van Jacobson compression (RFC1144) printer routines print-vrrp.c - Virtual Router Redundancy Protocol print-wb.c - White Board printer routines diff --git a/Makefile.in b/Makefile.in index 0496a827..be3d8c21 100644 --- a/Makefile.in +++ b/Makefile.in @@ -88,7 +88,7 @@ CSRC = addrtoname.c af.c checksum.c cpack.c gmpls.c oui.c gmt2local.c ipproto.c print-rx.c print-sctp.c print-sflow.c print-sip.c print-sl.c print-sll.c \ print-slow.c print-snmp.c print-stp.c print-sunatm.c print-sunrpc.c \ print-symantec.c print-syslog.c print-tcp.c print-telnet.c print-tftp.c \ - print-timed.c print-token.c print-udld.c print-udp.c \ + print-timed.c print-token.c print-udld.c print-udp.c print-usb.c \ print-vjc.c print-vqp.c print-vrrp.c print-vtp.c \ print-wb.c print-zephyr.c signature.h signature.c setsignal.c tcpdump.c util.c diff --git a/config.h.in b/config.h.in index 085cc936..f2d13014 100644 --- a/config.h.in +++ b/config.h.in @@ -208,6 +208,9 @@ /* Define to 1 if you have the `pcap_lib_version' function. */ #undef HAVE_PCAP_LIB_VERSION +/* Define to 1 if you have the header file. */ +#undef HAVE_PCAP_USB_H + /* Define to 1 if you have the `pfopen' function. */ #undef HAVE_PFOPEN diff --git a/configure b/configure index 8bea34ed..b661289b 100755 --- a/configure +++ b/configure @@ -11664,6 +11664,146 @@ fi done + +for ac_header in pcap/usb.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + CPPFLAGS="$savedcppflags" @@ -13348,6 +13488,16 @@ echo $ECHO_N "checking where SSLeay is located... $ECHO_C" >&6; } fi for dir in $dirs; do + # + # Find the last component of $libdir; it's not necessarily + # "lib" - it might be "lib64" on, for example, x86-64 + # Linux systems. + # + # We assume the directory in which we're looking for + # libcrypto has a subdirectory with that as its name. + # + tmplib=`echo "$libdir" | sed 's,.*/,,'` + # # XXX - is there a better way to check if a given library is # in a given directory than checking each of the possible @@ -13358,10 +13508,10 @@ echo $ECHO_N "checking where SSLeay is located... $ECHO_C" >&6; } # # Or should we just look for "libcrypto.*"? # - if test -d "$dir/lib" -a \( -f "$dir/lib/libcrypto.a" -o \ - -f "$dir/lib/libcrypto.so" -o \ - -f "$dir/lib/libcrypto.sl" -o \ - -f "$dir/lib/libcrypto.dylib" \); then + if test -d "$dir/$tmplib" -a \( -f "$dir/$tmplib/libcrypto.a" -o \ + -f "$dir/$tmplib/libcrypto.so" -o \ + -f "$dir/$tmplib/libcrypto.sl" -o \ + -f "$dir/$tmplib/libcrypto.dylib" \); then ac_cv_ssleay_path="$dir" fi @@ -13388,6 +13538,16 @@ echo "${ECHO_T}$ac_cv_ssleay_path" >&6; } { echo "$as_me:$LINENO: checking for SSLeay in $crypto_dir" >&5 echo $ECHO_N "checking for SSLeay in $crypto_dir... $ECHO_C" >&6; } + # + # Find the last component of $libdir; it's not necessarily + # "lib" - it might be "lib64" on, for example, x86-64 + # Linux systems. + # + # We assume the directory in which we're looking for + # libcrypto has a subdirectory with that as its name. + # + tmplib=`echo "$libdir" | sed 's,.*/,,'` + # # XXX - is there a better way to check if a given library is # in a given directory than checking each of the possible @@ -13398,10 +13558,10 @@ echo $ECHO_N "checking for SSLeay in $crypto_dir... $ECHO_C" >&6; } # # Or should we just look for "libcrypto.*"? # - if test -d "$crypto_dir/lib" -a \( -f "$crypto_dir/lib/libcrypto.a" -o \ - -f "$crypto_dir/lib/libcrypto.so" -o \ - -f "$crypto_dir/lib/libcrypto.sl" -o \ - -f "$crypto_dir/lib/libcrypto.dylib" \); then + if test -d "$crypto_dir/$tmplib" -a \( -f "$crypto_dir/$tmplib/libcrypto.a" -o \ + -f "$crypto_dir/$tmplib/libcrypto.so" -o \ + -f "$crypto_dir/$tmplib/libcrypto.sl" -o \ + -f "$crypto_dir/$tmplib/libcrypto.dylib" \); then ac_cv_ssleay_path="$crypto_dir" fi diff --git a/configure.in b/configure.in index 6b617e37..11f2c762 100644 --- a/configure.in +++ b/configure.in @@ -849,6 +849,7 @@ fi savedcppflags="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $V_INCLS" AC_CHECK_HEADERS(pcap/bluetooth.h) +AC_CHECK_HEADERS(pcap/usb.h) CPPFLAGS="$savedcppflags" AC_CHECK_HEADERS(sys/bitypes.h) diff --git a/interface.h b/interface.h index b8e2001c..688a2ac9 100644 --- a/interface.h +++ b/interface.h @@ -322,6 +322,7 @@ extern void bfd_print(const u_char *, u_int, u_int); extern void sip_print(const u_char *, u_int); extern void syslog_print(const u_char *, u_int); extern u_int bt_if_print(const struct pcap_pkthdr *, const u_char *); +extern u_int usb_linux_print(const struct pcap_pkthdr *, const u_char *); #ifdef INET6 extern void ip6_print(const u_char *, u_int); diff --git a/print-usb.c b/print-usb.c new file mode 100644 index 00000000..61f38ec0 --- /dev/null +++ b/print-usb.c @@ -0,0 +1,133 @@ +/* + * Copyright 2009 Bert Vermeulen + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by Paolo Abeni.'' + * The name of author may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Support for USB packets + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include +#include + +#include "interface.h" + + +#if defined(HAVE_PCAP_USB_H) && defined(DLT_USB_LINUX) +#include + +/* returns direction: 1=inbound 2=outbound -1=invalid */ +static int get_direction(int transfer_type, int event_type) +{ + int direction; + + direction = -1; + switch(transfer_type){ + case URB_BULK: + case URB_CONTROL: + case URB_ISOCHRONOUS: + switch(event_type) + { + case URB_SUBMIT: + direction = 2; + break; + case URB_COMPLETE: + case URB_ERROR: + direction = 1; + break; + default: + direction = -1; + } + break; + case URB_INTERRUPT: + switch(event_type) + { + case URB_SUBMIT: + direction = 1; + break; + case URB_COMPLETE: + case URB_ERROR: + direction = 2; + break; + default: + direction = -1; + } + break; + default: + direction = -1; + } + + return direction; +} + + +u_int usb_linux_print(const struct pcap_pkthdr *h, register const u_char *p) +{ + const pcap_usb_header *uh; + int direction; + + uh = (const pcap_usb_header *) p; + switch(uh->transfer_type) + { + case URB_ISOCHRONOUS: + printf("ISOCHRONOUS"); + break; + case URB_INTERRUPT: + printf("INTERRUPT"); + break; + case URB_CONTROL: + printf("CONTROL"); + break; + case URB_BULK: + printf("BULK"); + break; + default: + printf(" ?"); + } + + switch(uh->event_type) + { + case URB_SUBMIT: + printf(" SUBMIT"); + break; + case URB_COMPLETE: + printf(" COMPLETE"); + break; + case URB_ERROR: + printf(" ERROR"); + break; + default: + printf(" ?"); + } + + direction = get_direction(uh->transfer_type, uh->event_type); + if(direction == 1) + printf(" from"); + else if(direction == 2) + printf(" to"); + printf(" %d:%d:%d", uh->bus_id, uh->device_address, uh->endpoint_number & 0x7f); + + return(sizeof(pcap_usb_header)); +} + +#endif + diff --git a/tcpdump.c b/tcpdump.c index d524b016..18914d4b 100644 --- a/tcpdump.c +++ b/tcpdump.c @@ -275,6 +275,12 @@ static struct printer printers[] = { #endif #if defined(DLT_BLUETOOTH_HCI_H4_WITH_PHDR) && defined(HAVE_PCAP_BLUETOOTH_H) { bt_if_print, DLT_BLUETOOTH_HCI_H4_WITH_PHDR}, +#endif +#if defined(HAVE_PCAP_USB_H) && defined(DLT_USB_LINUX) + { usb_linux_print, DLT_USB_LINUX}, +#endif +#if defined(HAVE_PCAP_USB_H) && defined(DLT_USB_LINUX_MMAPPED) + { usb_linux_print, DLT_USB_LINUX_MMAPPED}, #endif { NULL, 0 }, }; @@ -1131,10 +1137,10 @@ main(int argc, char **argv) if (printinfo.printer == NULL) { gndo->ndo_dltname = pcap_datalink_val_to_name(type); if (gndo->ndo_dltname != NULL) - error("unsupported data link type %s", + error("packet printing is not supported for link type %s: use -w", gndo->ndo_dltname); else - error("unsupported data link type %d", type); + error("packet printing is not supported for link type %d: use -w", type); } callback = print_packet; pcap_userdata = (u_char *)&printinfo;