From 50ce2663e80dab3e650826fdc391b80a20bda1e7 Mon Sep 17 00:00:00 2001 From: guy Date: Fri, 13 Oct 2006 17:34:53 +0000 Subject: [PATCH] From Paolo Abeni: Bluetooth support. --- FILES | 1 + INSTALL.txt | 3 +- Makefile.in | 4 +- config.h.in | 3 + configure | 172 +++++++++++++++++++++++- configure.in | 23 +++- inet.c | 5 +- pcap-bt-linux.c | 342 +++++++++++++++++++++++++++++++++++++++++++++++ pcap-linux.c | 34 ++++- pcap-usb-linux.c | 6 +- 10 files changed, 578 insertions(+), 15 deletions(-) create mode 100644 pcap-bt-linux.c diff --git a/FILES b/FILES index f3ebdac..102b34f 100644 --- a/FILES +++ b/FILES @@ -81,6 +81,7 @@ pcap/sll.h pcap/usb.h pcap-bpf.c pcap-bpf.h +pcap-bt-linux.c pcap-dag.c pcap-dag.h pcap-dlpi.c diff --git a/INSTALL.txt b/INSTALL.txt index e022b7e..5f40c13 100644 --- a/INSTALL.txt +++ b/INSTALL.txt @@ -1,4 +1,4 @@ -@(#) $Header: /tcpdump/master/libpcap/INSTALL.txt,v 1.16 2006-10-04 18:09:22 guy Exp $ (LBL) +@(#) $Header: /tcpdump/master/libpcap/INSTALL.txt,v 1.17 2006-10-13 17:36:41 guy Exp $ (LBL) To build libpcap, run "./configure" (a shell script). The configure script will determine your system attributes and generate an @@ -357,6 +357,7 @@ pcap/sll.h - public definition of DLT_LINUX_SLL header pcap/usb.h - public definition of DLT_USB headeer pcap-bpf.c - BSD Packet Filter support pcap-bpf.h - header for backwards compatibility +pcap-bt-linux.c - Bluetooth capture support for Linux pcap-dag.c - Endace DAG device capture support pcap-dag.h - Endace DAG device capture support pcap-dlpi.c - Data Link Provider Interface support diff --git a/Makefile.in b/Makefile.in index 98334f2..f15025d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -17,7 +17,7 @@ # WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. # -# @(#) $Header: /tcpdump/master/libpcap/Makefile.in,v 1.104 2006-10-04 18:09:22 guy Exp $ (LBL) +# @(#) $Header: /tcpdump/master/libpcap/Makefile.in,v 1.105 2006-10-13 17:34:53 guy Exp $ (LBL) # # Various configurable paths (remember to edit Makefile.in, not Makefile) @@ -72,7 +72,7 @@ YACC = @V_YACC@ @rm -f $@ $(CC) $(CFLAGS) -c $(srcdir)/$*.c -PSRC = pcap-@V_PCAP@.c @USB_SRC@ +PSRC = pcap-@V_PCAP@.c @USB_SRC@ @BT_SRC@ FSRC = fad-@V_FINDALLDEVS@.c SSRC = @SSRC@ CSRC = pcap.c inet.c gencode.c optimize.c nametoaddr.c \ diff --git a/config.h.in b/config.h.in index 22b23c6..0b11f3c 100644 --- a/config.h.in +++ b/config.h.in @@ -161,6 +161,9 @@ /* /dev/dlpi directory */ #undef PCAP_DEV_PREFIX +/* target host supports Bluetooth sniffing */ +#undef PCAP_SUPPORT_BT + /* target host supports USB sniffing */ #undef PCAP_SUPPORT_USB diff --git a/configure b/configure index 5c7df41..356a93e 100755 --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 1.131 . +# From configure.in Revision: 1.132 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.59. # @@ -310,7 +310,7 @@ ac_includes_default="\ # include #endif" -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os SHLICC2 CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP LIBOBJS V_LEX V_YACC RANLIB ac_ct_RANLIB V_CCOPT V_DEFS V_INCLS V_LIBS V_PCAP V_FINDALLDEVS V_RANLIB SSRC DYEXT DAGLIBS PCAP_SUPPORT_USB USB_SRC INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LTLIBOBJS' +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os SHLICC2 CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP LIBOBJS V_LEX V_YACC RANLIB ac_ct_RANLIB V_CCOPT V_DEFS V_INCLS V_LIBS V_PCAP V_FINDALLDEVS V_RANLIB SSRC DYEXT DAGLIBS PCAP_SUPPORT_USB USB_SRC PCAP_SUPPORT_BT BT_SRC INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. @@ -7204,6 +7204,172 @@ esac +case "$host_os" in +linux*) + if test "${ac_cv_header_bluetooth_bluetooth_h+set}" = set; then + echo "$as_me:$LINENO: checking for bluetooth/bluetooth.h" >&5 +echo $ECHO_N "checking for bluetooth/bluetooth.h... $ECHO_C" >&6 +if test "${ac_cv_header_bluetooth_bluetooth_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_bluetooth_bluetooth_h" >&5 +echo "${ECHO_T}$ac_cv_header_bluetooth_bluetooth_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking bluetooth/bluetooth.h usability" >&5 +echo $ECHO_N "checking bluetooth/bluetooth.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&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); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (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); }; } && + { 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_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking bluetooth/bluetooth.h presence" >&5 +echo $ECHO_N "checking bluetooth/bluetooth.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&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; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: bluetooth/bluetooth.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: bluetooth/bluetooth.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: bluetooth/bluetooth.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: bluetooth/bluetooth.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: bluetooth/bluetooth.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: bluetooth/bluetooth.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: bluetooth/bluetooth.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: bluetooth/bluetooth.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: bluetooth/bluetooth.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: bluetooth/bluetooth.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: bluetooth/bluetooth.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: bluetooth/bluetooth.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: bluetooth/bluetooth.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: bluetooth/bluetooth.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: bluetooth/bluetooth.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: bluetooth/bluetooth.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for bluetooth/bluetooth.h" >&5 +echo $ECHO_N "checking for bluetooth/bluetooth.h... $ECHO_C" >&6 +if test "${ac_cv_header_bluetooth_bluetooth_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_bluetooth_bluetooth_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_bluetooth_bluetooth_h" >&5 +echo "${ECHO_T}$ac_cv_header_bluetooth_bluetooth_h" >&6 + +fi +if test $ac_cv_header_bluetooth_bluetooth_h = yes; then + + +cat >>confdefs.h <<\_ACEOF +#define PCAP_SUPPORT_BT 1 +_ACEOF + + BT_SRC=pcap-bt-linux.c + { echo "$as_me:$LINENO: Bluetooth sniffing is supported" >&5 +echo "$as_me: Bluetooth sniffing is supported" >&6;} + +else + { echo "$as_me:$LINENO: Bluetooth sniffing is not supported; install bluez-lib devel to enable it" >&5 +echo "$as_me: Bluetooth sniffing is not supported; install bluez-lib devel to enable it" >&6;} + +fi + + + ;; +*) + { echo "$as_me:$LINENO: no Bluetooth sniffing support" >&5 +echo "$as_me: no Bluetooth sniffing support" >&6;} + ;; +esac + + + # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: @@ -7938,6 +8104,8 @@ s,@DYEXT@,$DYEXT,;t t s,@DAGLIBS@,$DAGLIBS,;t t s,@PCAP_SUPPORT_USB@,$PCAP_SUPPORT_USB,;t t s,@USB_SRC@,$USB_SRC,;t t +s,@PCAP_SUPPORT_BT@,$PCAP_SUPPORT_BT,;t t +s,@BT_SRC@,$BT_SRC,;t t s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t s,@INSTALL_DATA@,$INSTALL_DATA,;t t diff --git a/configure.in b/configure.in index 1142e98..19fd523 100644 --- a/configure.in +++ b/configure.in @@ -1,4 +1,4 @@ -dnl @(#) $Header: /tcpdump/master/libpcap/configure.in,v 1.131 2006-10-04 16:46:31 guy Exp $ (LBL) +dnl @(#) $Header: /tcpdump/master/libpcap/configure.in,v 1.132 2006-10-13 17:34:53 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.131 $) +AC_REVISION($Revision: 1.132 $) AC_PREREQ(2.50) AC_INIT(pcap.c) @@ -806,6 +806,25 @@ esac AC_SUBST(PCAP_SUPPORT_USB) AC_SUBST(USB_SRC) +dnl check for bluetooth sniffing support +case "$host_os" in +linux*) + AC_CHECK_HEADER(bluetooth/bluetooth.h, + [ + AC_DEFINE(PCAP_SUPPORT_BT, 1, [target host supports Bluetooth sniffing]) + BT_SRC=pcap-bt-linux.c + AC_MSG_NOTICE(Bluetooth sniffing is supported) + ], + AC_MSG_NOTICE(Bluetooth sniffing is not supported; install bluez-lib devel to enable it) + ) + ;; +*) + AC_MSG_NOTICE(no Bluetooth sniffing support) + ;; +esac +AC_SUBST(PCAP_SUPPORT_BT) +AC_SUBST(BT_SRC) + AC_PROG_INSTALL AC_CONFIG_HEADER(config.h) diff --git a/inet.c b/inet.c index fa1571b..7c2e024 100644 --- a/inet.c +++ b/inet.c @@ -34,7 +34,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.71 2006-10-13 09:06:05 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.72 2006-10-13 17:34:53 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -582,6 +582,9 @@ pcap_lookupnet(device, netp, maskp, errbuf) #ifdef HAVE_SEPTEL_API || strstr(device, "septel") != NULL #endif +#ifdef PCAP_SUPPORT_BT + || strstr(device, "bluetooth") != NULL +#endif #ifdef PCAP_SUPPORT_USB || strstr(device, "usb") != NULL #endif diff --git a/pcap-bt-linux.c b/pcap-bt-linux.c new file mode 100644 index 0000000..d1c07fd --- /dev/null +++ b/pcap-bt-linux.c @@ -0,0 +1,342 @@ +/* + * Copyright (c) 2006 Paolo Abeni (Italy) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Politecnico di Torino, CACE Technologies + * nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * USB sniffig API implementation for linux platform + * By Paolo Abeni + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcap-int.h" + +#ifdef NEED_STRERROR_H +#include "strerror.h" +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define BT_IFACE "bluetooth" +#define BT_CTRL_SIZE 128 + +/* forward declaration */ +static int bt_read_linux(pcap_t *, int , pcap_handler , u_char *); +static int bt_inject_linux(pcap_t *, const void *, size_t); +static int bt_setfilter_linux(pcap_t *, struct bpf_program *); +static int bt_setdirection_linux(pcap_t *, pcap_direction_t); +static int bt_stats_linux(pcap_t *, struct pcap_stat *); +static void bt_close_linux(pcap_t *); + +int +bt_platform_finddevs(pcap_if_t **alldevsp, char *err_str) +{ + pcap_if_t *found_dev = *alldevsp; + struct hci_dev_list_req *dev_list; + struct hci_dev_req *dev_req; + int i, sock; + int ret = 0; + + sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); + if (sock < 0) + { + snprintf(err_str, PCAP_ERRBUF_SIZE, "can't open raw by socket %d:%s", + errno, strerror(errno)); + return -1; + } + + dev_list = malloc(HCI_MAX_DEV * sizeof(*dev_req) + sizeof(*dev_list)); + if (!dev_list) + { + snprintf(err_str, PCAP_ERRBUF_SIZE, "can't allocate %d bytes for dev cache", + HCI_MAX_DEV * sizeof(*dev_req) + sizeof(*dev_list)); + ret = -1; + goto done; + } + + dev_list->dev_num = HCI_MAX_DEV; + + if (ioctl(sock, HCIGETDEVLIST, (void *) dev_list) < 0) + { + snprintf(err_str, PCAP_ERRBUF_SIZE, "can't get dev list via ioctl %d:%s", + errno, strerror(errno)); + ret = -1; + goto free; + } + + dev_req = dev_list->dev_req; + for (i = 0; i < dev_list->dev_num; i++, dev_req++) { + char dev_name[20], dev_descr[30]; + + snprintf(dev_name, 20, BT_IFACE"%d", dev_req->dev_id); + snprintf(dev_descr, 30, "bluetooth adapter number %d", i); + + if (pcap_add_if(&found_dev, dev_name, 0, + dev_descr, err_str) < 0) + { + ret = -1; + break; + } + + } + +free: + free(dev_list); + +done: + close(sock); + return ret; +} + +pcap_t* +bt_open_live(const char* bus, int snaplen, int promisc , int to_ms, char* errmsg) +{ + struct sockaddr_hci addr; + int opt; + pcap_t *handle; + int dev_id; + struct hci_filter flt; + + /* get bt interface id */ + if (sscanf(bus, BT_IFACE"%d", &dev_id) != 1) + { + snprintf(errmsg, PCAP_ERRBUF_SIZE, + "Can't get usb bus index from %s", bus); + return NULL; + } + + /* Allocate a handle for this session. */ + handle = malloc(sizeof(*handle)); + if (handle == NULL) { + snprintf(errmsg, PCAP_ERRBUF_SIZE, "malloc: %s", + pcap_strerror(errno)); + return NULL; + } + + /* Initialize some components of the pcap structure. */ + memset(handle, 0, sizeof(*handle)); + handle->snapshot = snaplen; + handle->md.timeout = to_ms; + handle->bufsize = snaplen+BT_CTRL_SIZE; + handle->offset = BT_CTRL_SIZE; + handle->linktype = DLT_BLUETOOTH_HCI_H4; + + handle->read_op = bt_read_linux; + handle->inject_op = bt_inject_linux; + handle->setfilter_op = bt_setfilter_linux; + handle->setdirection_op = bt_setdirection_linux; + handle->set_datalink_op = NULL; /* can't change data link type */ + handle->getnonblock_op = pcap_getnonblock_fd; + handle->setnonblock_op = pcap_setnonblock_fd; + handle->stats_op = bt_stats_linux; + handle->close_op = bt_close_linux; + handle->md.ifindex = dev_id; + + /* Create HCI socket */ + handle->fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); + if (handle->fd < 0) { + snprintf(errmsg, PCAP_ERRBUF_SIZE, "Can't create raw socket %d:%s", + errno, strerror(errno)); + free(handle); + return NULL; + } + + handle->buffer = malloc(snaplen+BT_CTRL_SIZE); + if (!handle->buffer) { + snprintf(errmsg, PCAP_ERRBUF_SIZE, "Can't allocate dump buffer: %s", + pcap_strerror(errno)); + pcap_close(handle); + return NULL; + } + + opt = 1; + if (setsockopt(handle->fd, SOL_HCI, HCI_DATA_DIR, &opt, sizeof(opt)) < 0) { + snprintf(errmsg, PCAP_ERRBUF_SIZE, "Can't enable data direction info %d:%s", + errno, strerror(errno)); + pcap_close(handle); + return NULL; + } + + opt = 1; + if (setsockopt(handle->fd, SOL_HCI, HCI_TIME_STAMP, &opt, sizeof(opt)) < 0) { + snprintf(errmsg, PCAP_ERRBUF_SIZE, "Can't enable time stamp %d:%s", + errno, strerror(errno)); + pcap_close(handle); + return NULL; + } + + /* Setup filter, do not call hci function to avoid dependence on + * external libs */ + memset(&flt, 0, sizeof(flt)); + memset((void *) &flt.type_mask, 0xff, sizeof(flt.type_mask)); + memset((void *) &flt.event_mask, 0xff, sizeof(flt.event_mask)); + if (setsockopt(handle->fd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { + snprintf(errmsg, PCAP_ERRBUF_SIZE, "Can't set filter %d:%s", + errno, strerror(errno)); + pcap_close(handle); + return NULL; + } + + + /* Bind socket to the HCI device */ + addr.hci_family = AF_BLUETOOTH; + addr.hci_dev = handle->md.ifindex; + if (bind(handle->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + snprintf(errmsg, PCAP_ERRBUF_SIZE, "Can't attach to device %d %d:%s", + handle->md.ifindex, errno, strerror(errno)); + pcap_close(handle); + return NULL; + } + handle->selectable_fd = handle->fd; + + return handle; +} + +static int +bt_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) +{ + struct cmsghdr *cmsg; + struct msghdr msg; + struct iovec iv; + struct pcap_pkthdr pkth; + + iv.iov_base = &handle->buffer[handle->offset]; + iv.iov_len = handle->snapshot; + + memset(&msg, 0, sizeof(msg)); + msg.msg_iov = &iv; + msg.msg_iovlen = 1; + msg.msg_control = handle->buffer; + msg.msg_controllen = handle->offset; + + /* ignore interrupt system call error */ + do { + pkth.caplen = recvmsg(handle->fd, &msg, 0); + if (handle->break_loop) + { + handle->break_loop = 0; + return -2; + } + } while ((pkth.caplen == -1) && (errno == EINTR)); + + + if (pkth.caplen < 0) { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't receive packet %d:%s", + handle->md.ifindex, errno, strerror(errno)); + return -1; + } + + /* get direction and timestamp*/ + cmsg = CMSG_FIRSTHDR(&msg); + while (cmsg) { + int in; + switch (cmsg->cmsg_type) { + case HCI_CMSG_DIR: + in = *((int *) CMSG_DATA(cmsg)); + break; + case HCI_CMSG_TSTAMP: + pkth.ts = *((struct timeval *) CMSG_DATA(cmsg)); + break; + } + cmsg = CMSG_NXTHDR(&msg, cmsg); + } + pkth.len = pkth.caplen; + callback(user, &pkth, iv.iov_base); + return 1; +} + +static int +bt_inject_linux(pcap_t *handle, const void *buf, size_t size) +{ + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on " + "bluetooth devices"); + return (-1); +} + + +static void +bt_close_linux(pcap_t* handle) +{ + close(handle->fd); + free(handle->buffer); +} + + +static int +bt_stats_linux(pcap_t *handle, struct pcap_stat *stats) +{ + int ret; + struct hci_dev_info dev_info; + struct hci_dev_stats * s = &dev_info.stat; + dev_info.dev_id = handle->md.ifindex; + + /* ingnore eintr */ + do { + ret = ioctl(handle->fd, HCIGETDEVINFO, (void *)&dev_info); + } while ((ret == -1) && (errno == EINTR)); + + if (ret < 0) { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "can get stats" + " via ioctl %d:%s", errno, strerror(errno)); + return (-1); + + } + + /* we receive both rx and tx frames, so comulate all stats */ + stats->ps_recv = s->evt_rx + s->acl_rx + s->sco_rx + s->cmd_tx + + s->acl_tx +s->sco_tx; + stats->ps_drop = s->err_rx + s->err_tx; + stats->ps_ifdrop = 0; + return 0; +} + +static int +bt_setfilter_linux(pcap_t *p, struct bpf_program *fp) +{ + return 0; +} + + +static int +bt_setdirection_linux(pcap_t *p, pcap_direction_t d) +{ + p->direction = d; + return 0; +} diff --git a/pcap-linux.c b/pcap-linux.c index b2da550..d011358 100644 --- a/pcap-linux.c +++ b/pcap-linux.c @@ -27,7 +27,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.126 2006-10-12 17:26:06 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.127 2006-10-13 17:34:53 guy Exp $ (LBL)"; #endif /* @@ -184,11 +184,21 @@ typedef int socklen_t; */ #define BIGGER_THAN_ALL_MTUS (64*1024) +#ifdef PCAP_SUPPORT_USB /* - * Prototypes for usb related functions + * Prototypes for USB-related functions */ int usb_platform_finddevs(pcap_if_t **alldevsp, char *err_str); pcap_t* usb_open_live(const char* bus, int snaplen, int promisc , int to_ms, char* errmsg); +#endif + +#ifdef PCAP_SUPPORT_BT +/* + * Prototypes for Bluetooth-related functions + */ +int bt_platform_finddevs(pcap_if_t **alldevsp, char *err_str); +pcap_t* bt_open_live(const char* bus, int snaplen, int promisc , int to_ms, char* errmsg); +#endif /* @@ -262,9 +272,16 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, } #endif /* HAVE_SEPTEL_API */ - if (strstr(device, "usb")) { - return usb_open_live(device, snaplen, promisc, to_ms, ebuf); - } +#ifdef PCAP_SUPPORT_BT + if (strstr(device, "bluetooth")) { + return bt_open_live(device, snaplen, promisc, to_ms, ebuf); + } +#endif + + if (strstr(device, "usb")) { + return usb_open_live(device, snaplen, promisc, to_ms, ebuf); + } + /* Allocate a handle for this session. */ @@ -926,8 +943,15 @@ pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) return (-1); #endif /* HAVE_SEPTEL_API */ +#ifdef PCAP_SUPPORT_BT + if (bt_platform_finddevs(alldevsp, errbuf) < 0) + return (-1); +#endif + +#ifdef PCAP_SUPPORT_USB if (usb_platform_finddevs(alldevsp, errbuf) < 0) return (-1); +#endif return (0); } diff --git a/pcap-usb-linux.c b/pcap-usb-linux.c index 7094c2c..0a4d581 100644 --- a/pcap-usb-linux.c +++ b/pcap-usb-linux.c @@ -406,7 +406,8 @@ usb_stats_linux(pcap_t *handle, struct pcap_stat *stats) if (fd < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, - "Can't open usb stats file %s: %s", string, strerror(errno)); + "Can't open usb stats file %s: %s", + string, strerror(errno)); return -1; } @@ -429,7 +430,8 @@ usb_stats_linux(pcap_t *handle, struct pcap_stat *stats) if (ret != 2) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, - "Can't parse stat line '%s' expected 2 token got %d", string, ret); + "Can't parse stat line '%s' expected 2 token got %d", + string, ret); return -1; }