aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.in4
-rw-r--r--config.h.in2
-rwxr-xr-xconfigure114
-rw-r--r--configure.in15
-rw-r--r--gencode.c10
-rw-r--r--inet.c3
-rw-r--r--pcap-dect-linux.c256
-rw-r--r--pcap-dect-linux.h2
-rw-r--r--pcap-linux.c14
-rw-r--r--pcap.c1
-rw-r--r--pcap/bpf.h5
11 files changed, 415 insertions, 11 deletions
diff --git a/Makefile.in b/Makefile.in
index ae2e4a3..5fcfb78 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -82,7 +82,7 @@ YACC = @V_YACC@
@rm -f $@
$(CC) $(FULL_CFLAGS) -c $(srcdir)/$*.c
-PSRC = pcap-@V_PCAP@.c @USB_SRC@ @BT_SRC@ @CAN_SRC@
+PSRC = pcap-@V_PCAP@.c @USB_SRC@ @BT_SRC@ @CAN_SRC@ @DECT_SRC@
FSRC = fad-@V_FINDALLDEVS@.c
SSRC = @SSRC@
CSRC = pcap.c inet.c gencode.c optimize.c nametoaddr.c etherent.c \
@@ -313,6 +313,8 @@ EXTRA_DIST = \
pcap-snoop.c \
pcap-usb-linux.c \
pcap-usb-linux.h \
+ pcap-dect-linux.c \
+ pcap-dect-linux.h \
pcap-win32.c \
runlex.sh \
scanner.l \
diff --git a/config.h.in b/config.h.in
index f988e8f..688f596 100644
--- a/config.h.in
+++ b/config.h.in
@@ -223,6 +223,8 @@
/* target host supports USB sniffing */
#undef PCAP_SUPPORT_USB
+#undef PCAP_SUPPORT_DECT
+
/* include ACN support */
#undef SITA
diff --git a/configure b/configure
index e85d87e..bd78b34 100755
--- a/configure
+++ b/configure
@@ -697,6 +697,8 @@ MAN_FILE_FORMATS
MAN_MISC_INFO
PCAP_SUPPORT_USB
USB_SRC
+PCAP_SUPPORT_DECT
+DECT_SRC
PCAP_SUPPORT_BT
BT_SRC
PCAP_SUPPORT_CAN
@@ -3973,7 +3975,7 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
else
ac_cv_header_stdc=no
fi
-rm -f -r conftest*
+rm -f conftest*
fi
@@ -3994,7 +3996,7 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
else
ac_cv_header_stdc=no
fi
-rm -f -r conftest*
+rm -f conftest*
fi
@@ -5054,7 +5056,7 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
;;
esac
-rm -f -r conftest*
+rm -f conftest*
if test $ac_cv_sys_file_offset_bits = unknown; then
{ echo "$as_me:$LINENO: checking for _LARGE_FILES value needed for large files" >&5
echo $ECHO_N "checking for _LARGE_FILES value needed for large files... $ECHO_C" >&6; }
@@ -5175,7 +5177,7 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
;;
esac
-rm -f -r conftest*
+rm -f conftest*
fi
fi
@@ -5191,11 +5193,13 @@ _ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
-#include <stdio.h>
+#include <sys/types.h> /* for off_t */
+ #include <stdio.h>
int
main ()
{
-return fseeko (stdin, 0, 0) && (fseeko) (stdin, 0, 0);
+int (*fp) (FILE *, off_t, int) = fseeko;
+ return fseeko (stdin, 0, 0) && fp (stdin, 0, 0);
;
return 0;
}
@@ -5235,11 +5239,13 @@ cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#define _LARGEFILE_SOURCE 1
-#include <stdio.h>
+#include <sys/types.h> /* for off_t */
+ #include <stdio.h>
int
main ()
{
-return fseeko (stdin, 0, 0) && (fseeko) (stdin, 0, 0);
+int (*fp) (FILE *, off_t, int) = fseeko;
+ return fseeko (stdin, 0, 0) && fp (stdin, 0, 0);
;
return 0;
}
@@ -5286,7 +5292,7 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
;;
esac
-rm -f -r conftest*
+rm -f conftest*
# We used to try defining _XOPEN_SOURCE=500 too, to work around a bug
# in glibc 2.1.3, but that breaks too many other things.
@@ -10542,6 +10548,92 @@ esac
+{ echo "$as_me:$LINENO: checking for DECT sniffing support" >&5
+echo $ECHO_N "checking for DECT sniffing support... $ECHO_C" >&6; }
+case "$host_os" in
+linux*)
+ { echo "$as_me:$LINENO: checking for nl_dect_cluster_alloc_cache in -lnl-dect" >&5
+echo $ECHO_N "checking for nl_dect_cluster_alloc_cache in -lnl-dect... $ECHO_C" >&6; }
+if test "${ac_cv_lib_nl_dect_nl_dect_cluster_alloc_cache+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnl-dect $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char nl_dect_cluster_alloc_cache ();
+int
+main ()
+{
+return nl_dect_cluster_alloc_cache ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_nl_dect_nl_dect_cluster_alloc_cache=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_nl_dect_nl_dect_cluster_alloc_cache=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_nl_dect_nl_dect_cluster_alloc_cache" >&5
+echo "${ECHO_T}$ac_cv_lib_nl_dect_nl_dect_cluster_alloc_cache" >&6; }
+if test $ac_cv_lib_nl_dect_nl_dect_cluster_alloc_cache = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define PCAP_SUPPORT_DECT 1
+_ACEOF
+
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ DECT_SRC=pcap-dect-linux.c
+ ;;
+*)
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ;;
+esac
+
+
+
# Check whether --enable-bluetooth was given.
if test "${enable_bluetooth+set}" = set; then
enableval=$enable_bluetooth;
@@ -11734,6 +11826,8 @@ MAN_FILE_FORMATS!$MAN_FILE_FORMATS$ac_delim
MAN_MISC_INFO!$MAN_MISC_INFO$ac_delim
PCAP_SUPPORT_USB!$PCAP_SUPPORT_USB$ac_delim
USB_SRC!$USB_SRC$ac_delim
+PCAP_SUPPORT_DECT!$PCAP_SUPPORT_DECT$ac_delim
+DECT_SRC!$DECT_SRC$ac_delim
PCAP_SUPPORT_BT!$PCAP_SUPPORT_BT$ac_delim
BT_SRC!$BT_SRC$ac_delim
PCAP_SUPPORT_CAN!$PCAP_SUPPORT_CAN$ac_delim
@@ -11744,7 +11838,7 @@ INSTALL_DATA!$INSTALL_DATA$ac_delim
LTLIBOBJS!$LTLIBOBJS$ac_delim
_ACEOF
- if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 91; then
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 93; then
break
elif $ac_last_try; then
{ { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
diff --git a/configure.in b/configure.in
index d71d3fd..16e0299 100644
--- a/configure.in
+++ b/configure.in
@@ -1398,6 +1398,21 @@ esac
AC_SUBST(PCAP_SUPPORT_USB)
AC_SUBST(USB_SRC)
+AC_MSG_CHECKING(for DECT sniffing support)
+case "$host_os" in
+linux*)
+ AC_CHECK_LIB([nl-dect],[nl_dect_cluster_alloc_cache],
+ AC_DEFINE(PCAP_SUPPORT_DECT, 1, [target host supports DECT sniffing]),
+ AC_MSG_RESULT([no]))
+ DECT_SRC=pcap-dect-linux.c
+ ;;
+*)
+ AC_MSG_RESULT(no)
+ ;;
+esac
+AC_SUBST(PCAP_SUPPORT_DECT)
+AC_SUBST(DECT_SRC)
+
AC_ARG_ENABLE([bluetooth],
[AC_HELP_STRING([--enable-bluetooth],[enable Bluetooth support @<:@default=yes, if support available@:>@])],
,enable_bluetooth=yes)
diff --git a/gencode.c b/gencode.c
index f66492e..5b113cf 100644
--- a/gencode.c
+++ b/gencode.c
@@ -1451,6 +1451,16 @@ init_linktype(p)
off_nl_nosnap = -1;
return;
+ case DLT_DECT_LINUX:
+ /*
+ * Currently, only raw "link[N:M]" filtering is supported.
+ */
+ off_linktype = -1;
+ off_macpl = -1;
+ off_nl = -1;
+ off_nl_nosnap = -1;
+ return;
+
case DLT_CAN20B:
/*
* Currently, only raw "link[N:M]" filtering is supported.
diff --git a/inet.c b/inet.c
index 178eb81..642ffb0 100644
--- a/inet.c
+++ b/inet.c
@@ -740,6 +740,9 @@ pcap_lookupnet(device, netp, maskp, errbuf)
#ifdef HAVE_SNF_API
|| strstr(device, "snf") != NULL
#endif
+#ifdef PCAP_SUPPORT_DECT
+ || strstr(device, "dect") != NULL
+#endif
) {
*netp = *maskp = 0;
return 0;
diff --git a/pcap-dect-linux.c b/pcap-dect-linux.c
new file mode 100644
index 0000000..4207868
--- /dev/null
+++ b/pcap-dect-linux.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2009 Patrick McHardy <kaber@trash.net>
+ *
+ * Licensed under the same license as libpcap itself.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcap-int.h"
+#include "pcap-dect-linux.h"
+
+#ifdef NEED_STRERROR_H
+#include "strerror.h"
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <linux/types.h>
+#include <linux/dect.h>
+#include <linux/netlink.h>
+#include <netlink/cache.h>
+#include <netlink/dect/cell.h>
+
+#define PF_DECT 38
+#define AF_DECT PF_DECT
+#define SOL_DECT 279
+
+struct cb_args {
+ pcap_if_t **alldevsp;
+ char *err_str;
+ bool err;
+};
+
+static void add_cell_cb(struct nl_object *obj, void *arg)
+{
+ struct cb_args *args = arg;
+ char dev_name[32];
+
+ if (args->err)
+ return;
+
+ snprintf(dev_name, sizeof(dev_name), "dect-%s",
+ nl_dect_cell_get_name((struct nl_dect_cell *)obj));
+
+ if (pcap_add_if(args->alldevsp, dev_name, 0, NULL, args->err_str) < 0)
+ args->err = true;
+}
+
+int dect_platform_finddevs(pcap_if_t **alldevsp, char *err_str)
+{
+ struct nl_sock *sock;
+ struct nl_cache *cell_cache;
+ struct cb_args args = {
+ .alldevsp = alldevsp,
+ .err_str = err_str,
+ };
+
+ sock = nl_socket_alloc();
+ if (sock == NULL) {
+ snprintf(err_str, PCAP_ERRBUF_SIZE, "socket: %s",
+ pcap_strerror(errno));
+ return -1;
+ }
+ if (nl_connect(sock, NETLINK_DECT) < 0) {
+ snprintf(err_str, PCAP_ERRBUF_SIZE, "connect: %s",
+ pcap_strerror(errno));
+ return -1;
+ }
+ if (nl_dect_cell_alloc_cache(sock, &cell_cache) < 0) {
+ snprintf(err_str, PCAP_ERRBUF_SIZE, "cache: %s",
+ pcap_strerror(errno));
+ return -1;
+ }
+
+ nl_cache_foreach(cell_cache, add_cell_cb, &args);
+ nl_socket_free(sock);
+
+ return args.err ? -1 : 0;
+}
+
+/*
+ * compatible header to what wireshark is expecting from the CoA
+ * character device for now.
+ */
+struct dect_dummy_hdr {
+ uint8_t etheraddrs[2 * 6];
+ uint16_t ethertype;
+
+ uint8_t trxmode;
+ uint8_t channel;
+ uint16_t slot;
+ uint8_t frame;
+ uint8_t rssi;
+ uint8_t preamble[3];
+ uint16_t packettype;
+} __attribute__((packed));
+
+static int dect_read_linux(pcap_t *handle, int max_packets,
+ pcap_handler callback, u_char *user)
+{
+ struct pcap_pkthdr hdr;
+ struct dect_dummy_hdr *dhdr;
+ struct iovec iov;
+ struct msghdr msg;
+ struct dect_raw_auxdata *aux;
+ struct cmsghdr *cmsg;
+ union {
+ struct cmsghdr cmsg;
+ char buf[CMSG_SPACE(sizeof(*aux))];
+ } cmsg_buf;
+ ssize_t len;
+
+ /* refuse anything below dummy header size for simplicity */
+ if (handle->bufsize < sizeof(*dhdr))
+ return -1;
+
+ dhdr = (struct dect_dummy_hdr *)handle->buffer;
+ memset(dhdr, 0, sizeof(*dhdr));
+ dhdr->ethertype = 0x2323;
+ dhdr->trxmode = 0;
+ dhdr->channel = 0;
+
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = &cmsg_buf;
+ msg.msg_controllen = sizeof(cmsg_buf);
+ msg.msg_flags = 0;
+
+ iov.iov_len = handle->bufsize - sizeof(*dhdr);
+ iov.iov_base = handle->buffer + sizeof(*dhdr);
+
+ do {
+ if (handle->break_loop) {
+ handle->break_loop = 0;
+ return -2;
+ }
+
+ len = recvmsg(handle->fd, &msg, 0);
+ } while (len == -1 && (errno == EINTR || errno == ENETDOWN));
+
+ if (len == -1) {
+ if (errno == EAGAIN)
+ return 0;
+ else {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "recvfrom: %s", pcap_strerror(errno));
+ return -1;
+ }
+ }
+
+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
+ cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+ if (cmsg->cmsg_level != SOL_DECT ||
+ cmsg->cmsg_type != DECT_RAW_AUXDATA ||
+ cmsg->cmsg_len < CMSG_LEN(sizeof(*aux)))
+ continue;
+
+ aux = (struct dect_raw_auxdata *)CMSG_DATA(cmsg);
+ dhdr->slot = htons(aux->slot);
+ dhdr->rssi = aux->rssi;
+ dhdr->frame = aux->frame;
+ if (aux->slot < 12)
+ dhdr->packettype = htons(0xe98a);
+ else
+ dhdr->packettype = htons(0x1675);
+ }
+
+ gettimeofday(&hdr.ts, NULL);
+ hdr.caplen = len + sizeof(*dhdr);
+ hdr.len = len + sizeof(*dhdr);
+ callback(user, &hdr, handle->buffer);
+ return 1;
+}
+
+static int dect_setfilter_linux(pcap_t *handle, struct bpf_program *fp)
+{
+ return 0;
+}
+
+static int dect_setdirection_linux(pcap_t *handle, pcap_direction_t d)
+{
+ handle->direction = d;
+ return 0;
+}
+
+static int dect_activate(pcap_t *handle)
+{
+ struct sockaddr_dect da;
+
+ handle->bufsize = handle->snapshot;
+ handle->offset = 0;
+#if 0
+ handle->linktype = DLT_DECT_LINUX;
+#else
+ handle->linktype = DLT_EN10MB;
+#endif
+
+ handle->inject_op = NULL;
+ handle->setfilter_op = dect_setfilter_linux;
+ handle->setdirection_op = dect_setdirection_linux;
+ handle->set_datalink_op = NULL;
+ handle->getnonblock_op = pcap_getnonblock_fd;
+ handle->setnonblock_op = pcap_setnonblock_fd;
+ handle->read_op = dect_read_linux;
+
+ handle->fd = socket(PF_DECT, SOCK_RAW, 0);
+ if (handle->fd < 0) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't open PF_DECT socket: %s",
+ pcap_strerror(errno));
+ return PCAP_ERROR;
+ }
+
+ memset(&da, 0, sizeof(da));
+ da.dect_family = AF_DECT;
+ if (bind(handle->fd, (struct sockaddr *)&da, sizeof(da)) < 0) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't bind PF_DECT socket: %s",
+ pcap_strerror(errno));
+ return PCAP_ERROR;
+ }
+
+ handle->selectable_fd = handle->fd;
+ handle->buffer = malloc(handle->bufsize);
+ if (!handle->buffer) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't allocate packet buffer: %s",
+ pcap_strerror(errno));
+ return PCAP_ERROR;
+ }
+ return 0;
+}
+
+pcap_t *dect_create(const char *device, char *ebuf)
+{
+ pcap_t *p;
+
+ p = pcap_create_common(device, ebuf);
+ if (p == NULL)
+ return NULL;
+
+ p->activate_op = dect_activate;
+ return p;
+}
diff --git a/pcap-dect-linux.h b/pcap-dect-linux.h
new file mode 100644
index 0000000..f8d1546
--- /dev/null
+++ b/pcap-dect-linux.h
@@ -0,0 +1,2 @@
+int dect_platform_finddevs(pcap_if_t **alldevsp, char *err_str);
+pcap_t *dect_create(const char *device, char *ebuf);
diff --git a/pcap-linux.c b/pcap-linux.c
index f8b3f10..9cdc0bf 100644
--- a/pcap-linux.c
+++ b/pcap-linux.c
@@ -191,6 +191,10 @@ static const char rcsid[] _U_ =
#include "pcap-can-linux.h"
#endif
+#ifdef PCAP_SUPPORT_DECT
+#include "pcap-dect-linux.h"
+#endif
+
/*
* If PF_PACKET is defined, we can use {SOCK_RAW,SOCK_DGRAM}/PF_PACKET
* sockets rather than SOCK_PACKET sockets.
@@ -410,6 +414,12 @@ pcap_create(const char *device, char *ebuf)
}
#endif
+#ifdef PCAP_SUPPORT_DECT
+ if (strstr(device, "dect")) {
+ return dect_create(device, ebuf);
+ }
+#endif
+
handle = pcap_create_common(device, ebuf);
if (handle == NULL)
return NULL;
@@ -2164,6 +2174,10 @@ pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
return (-1);
#endif
+#ifdef PCAP_SUPPORT_DECT
+ if (dect_platform_finddevs(alldevsp, errbuf) < 0)
+ return (-1);
+#endif
return (0);
}
diff --git a/pcap.c b/pcap.c
index 4b64a38..3db3320 100644
--- a/pcap.c
+++ b/pcap.c
@@ -820,6 +820,7 @@ static struct dlt_choice dlt_choices[] = {
DLT_CHOICE(DLT_BLUETOOTH_HCI_H4, "Bluetooth HCI UART transport layer"),
DLT_CHOICE(DLT_IEEE802_16_MAC_CPS, "IEEE 802.16 MAC Common Part Sublayer"),
DLT_CHOICE(DLT_USB_LINUX, "USB with Linux header"),
+ DLT_CHOICE(DLT_DECT_LINUX, "DECT with Linux header"),
DLT_CHOICE(DLT_CAN20B, "Controller Area Network (CAN) v. 2.0B"),
DLT_CHOICE(DLT_IEEE802_15_4_LINUX, "IEEE 802.15.4 with Linux padding"),
DLT_CHOICE(DLT_PPI, "Per-Packet Information"),
diff --git a/pcap/bpf.h b/pcap/bpf.h
index 6048fff..938a62a 100644
--- a/pcap/bpf.h
+++ b/pcap/bpf.h
@@ -970,6 +970,11 @@ struct bpf_version {
#define DLT_IEEE802_15_4_NOFCS 230
/*
+ * DECT
+ */
+#define DLT_DECT_LINUX 231
+
+/*
* DLT and savefile link type values are split into a class and
* a member of that class. A class value of 0 indicates a regular
* DLT_/LINKTYPE_ value.