From 1c1816f670c9015ba97fa6b9780355c787920d67 Mon Sep 17 00:00:00 2001 From: Felix Obenhuber Date: Tue, 29 Dec 2009 01:04:20 -0800 Subject: [PATCH] Add support for CANbus capture. Signed-off-by: Guy Harris --- CREDITS | 1 + Makefile.in | 4 +- config.h.in | 3 + configure | 179 ++++++++++++++++++++++++++++++-- configure.in | 22 ++++ pcap-can-linux.c | 265 +++++++++++++++++++++++++++++++++++++++++++++++ pcap-can-linux.h | 35 +++++++ pcap-linux.c | 16 +++ 8 files changed, 518 insertions(+), 7 deletions(-) create mode 100644 pcap-can-linux.c create mode 100644 pcap-can-linux.h diff --git a/CREDITS b/CREDITS index 182389b..bbe3039 100644 --- a/CREDITS +++ b/CREDITS @@ -35,6 +35,7 @@ Additional people who have contributed patches: Dustin Spicuzza Eric Anderson Erik de Castro Lopo + Felix Obenhuber Florent Drouin Franz Schaefer Fulko Hew diff --git a/Makefile.in b/Makefile.in index 24dc74d..993aa3c 100644 --- a/Makefile.in +++ b/Makefile.in @@ -80,7 +80,7 @@ YACC = @V_YACC@ @rm -f $@ $(CC) $(CFLAGS) -c $(srcdir)/$*.c -PSRC = pcap-@V_PCAP@.c @USB_SRC@ @BT_SRC@ +PSRC = pcap-@V_PCAP@.c @USB_SRC@ @BT_SRC@ @CAN_SRC@ FSRC = fad-@V_FINDALLDEVS@.c SSRC = @SSRC@ CSRC = pcap.c inet.c gencode.c optimize.c nametoaddr.c \ @@ -264,6 +264,8 @@ EXTRA_DIST = \ pcap-bpf.c \ pcap-bt-linux.c \ pcap-bt-linux.h \ + pcap-can-linux.c \ + pcap-can-linux.h \ pcap-config.in \ pcap-dag.c \ pcap-dag.h \ diff --git a/config.h.in b/config.h.in index 46a725d..3a8a2a7 100644 --- a/config.h.in +++ b/config.h.in @@ -214,6 +214,9 @@ /* target host supports Bluetooth sniffing */ #undef PCAP_SUPPORT_BT +/* target host supports CAN sniffing */ +#undef PCAP_SUPPORT_CAN + /* target host supports USB sniffing */ #undef PCAP_SUPPORT_USB diff --git a/configure b/configure index 0cbb36e..c05a72d 100755 --- a/configure +++ b/configure @@ -698,6 +698,8 @@ PCAP_SUPPORT_USB USB_SRC PCAP_SUPPORT_BT BT_SRC +PCAP_SUPPORT_CAN +CAN_SRC INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA @@ -1293,6 +1295,8 @@ Optional Features: --enable-yydebug build parser debugging code --enable-bluetooth enable bluetooth support [default=yes, if support available] + --enable-can enable can support [default=yes, if support + available] Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -3926,7 +3930,7 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | else ac_cv_header_stdc=no fi -rm -f conftest* +rm -f -r conftest* fi @@ -3947,7 +3951,7 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | else ac_cv_header_stdc=no fi -rm -f conftest* +rm -f -r conftest* fi @@ -5007,7 +5011,7 @@ cat >>confdefs.h <<_ACEOF _ACEOF ;; esac -rm -f conftest* +rm -f -r 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; } @@ -5128,7 +5132,7 @@ cat >>confdefs.h <<_ACEOF _ACEOF ;; esac -rm -f conftest* +rm -f -r conftest* fi fi @@ -5239,7 +5243,7 @@ cat >>confdefs.h <<_ACEOF _ACEOF ;; esac -rm -f conftest* +rm -f -r 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. @@ -10337,6 +10341,167 @@ echo "$as_me: no Bluetooth sniffing support" >&6;} esac +fi + +# Check whether --enable-can was given. +if test "${enable_can+set}" = set; then + enableval=$enable_can; +else + enable_can=yes +fi + + +if test "x$enable_can" != "xno" ; then + case "$host_os" in + linux*) + if test "${ac_cv_header_linux_can_version_h+set}" = set; then + { echo "$as_me:$LINENO: checking for linux/can/version.h" >&5 +echo $ECHO_N "checking for linux/can/version.h... $ECHO_C" >&6; } +if test "${ac_cv_header_linux_can_version_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_linux_can_version_h" >&5 +echo "${ECHO_T}$ac_cv_header_linux_can_version_h" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking linux/can/version.h usability" >&5 +echo $ECHO_N "checking linux/can/version.h usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking linux/can/version.h presence" >&5 +echo $ECHO_N "checking linux/can/version.h presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: linux/can/version.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: linux/can/version.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: linux/can/version.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: linux/can/version.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: linux/can/version.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: linux/can/version.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: linux/can/version.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: linux/can/version.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: linux/can/version.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: linux/can/version.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: linux/can/version.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: linux/can/version.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: linux/can/version.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: linux/can/version.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: linux/can/version.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: linux/can/version.h: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for linux/can/version.h" >&5 +echo $ECHO_N "checking for linux/can/version.h... $ECHO_C" >&6; } +if test "${ac_cv_header_linux_can_version_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_linux_can_version_h=$ac_header_preproc +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_linux_can_version_h" >&5 +echo "${ECHO_T}$ac_cv_header_linux_can_version_h" >&6; } + +fi +if test $ac_cv_header_linux_can_version_h = yes; then + +cat >>confdefs.h <<\_ACEOF +#define PCAP_SUPPORT_CAN 1 +_ACEOF + + CAN_SRC=pcap-can-linux.c + { echo "$as_me:$LINENO: CAN sniffing is supported" >&5 +echo "$as_me: CAN sniffing is supported" >&6;} +else + { echo "$as_me:$LINENO: CAN sniffing is not supported" >&5 +echo "$as_me: CAN sniffing is not supported" >&6;} +fi + + + ;; + *) + { echo "$as_me:$LINENO: no CAN sniffing support implemented for $host_os" >&5 +echo "$as_me: no CAN sniffing support implemented for $host_os" >&6;} + ;; + esac + + fi # Find a good install program. We prefer a C program (faster), @@ -11135,13 +11300,15 @@ PCAP_SUPPORT_USB!$PCAP_SUPPORT_USB$ac_delim USB_SRC!$USB_SRC$ac_delim PCAP_SUPPORT_BT!$PCAP_SUPPORT_BT$ac_delim BT_SRC!$BT_SRC$ac_delim +PCAP_SUPPORT_CAN!$PCAP_SUPPORT_CAN$ac_delim +CAN_SRC!$CAN_SRC$ac_delim INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim INSTALL_DATA!$INSTALL_DATA$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 88; then + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 90; 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 e444291..e5cbdc0 100644 --- a/configure.in +++ b/configure.in @@ -1283,6 +1283,28 @@ if test "x$enable_bluetooth" != "xno" ; then AC_SUBST(BT_SRC) fi +AC_ARG_ENABLE([can], +[AC_HELP_STRING([--enable-can],[enable can support @<:@default=yes, if support available@:>@])], +,enable_can=yes) + +if test "x$enable_can" != "xno" ; then + dnl check for CAN sniffing support + case "$host_os" in + linux*) + AC_CHECK_HEADER(linux/can/version.h, + [ AC_DEFINE(PCAP_SUPPORT_CAN, 1, [target host supports CAN sniffing]) + CAN_SRC=pcap-can-linux.c + AC_MSG_NOTICE(CAN sniffing is supported)], + AC_MSG_NOTICE(CAN sniffing is not supported) ) + ;; + *) + AC_MSG_NOTICE(no CAN sniffing support implemented for $host_os) + ;; + esac + AC_SUBST(PCAP_SUPPORT_CAN) + AC_SUBST(CAN_SRC) +fi + AC_PROG_INSTALL AC_CONFIG_HEADER(config.h) diff --git a/pcap-can-linux.c b/pcap-can-linux.c new file mode 100644 index 0000000..8210663 --- /dev/null +++ b/pcap-can-linux.c @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2009 Felix Obenhuber + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * SocketCan sniffing API implementation for Linux platform + * By Felix Obenhuber + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcap-int.h" +#include "pcap-can-linux.h" + +#ifdef NEED_STRERROR_H +#include "strerror.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* not yet defined anywhere */ +#ifndef PF_CAN +#define PF_CAN 29 +#endif +#ifndef AF_CAN +#define AF_CAN PF_CAN +#endif + +/* forward declaration */ +static int can_activate(pcap_t *); +static int can_read_linux(pcap_t *, int , pcap_handler , u_char *); +static int can_inject_linux(pcap_t *, const void *, size_t); +static int can_setfilter_linux(pcap_t *, struct bpf_program *); +static int can_setdirection_linux(pcap_t *, pcap_direction_t); +static int can_stats_linux(pcap_t *, struct pcap_stat *); + +pcap_t * +can_create(const char *device, char *ebuf) +{ + pcap_t* p; + + p = pcap_create_common(device, ebuf); + if (p == NULL) + return (NULL); + + p->activate_op = can_activate; + return (p); +} + + +static int +can_activate(pcap_t* handle) +{ + int err = PCAP_ERROR; + struct sockaddr_can addr; + struct ifreq ifr; + + /* Initialize some components of the pcap structure. */ + handle->bufsize = 24; + handle->offset = 8; + handle->linktype = DLT_CAN_SOCKETCAN; + handle->read_op = can_read_linux; + handle->inject_op = can_inject_linux; + handle->setfilter_op = can_setfilter_linux; + handle->setdirection_op = can_setdirection_linux; + handle->set_datalink_op = NULL; + handle->getnonblock_op = pcap_getnonblock_fd; + handle->setnonblock_op = pcap_setnonblock_fd; + handle->stats_op = can_stats_linux; + + /* Create socket */ + handle->fd = socket(PF_CAN, SOCK_RAW, CAN_RAW); + if (handle->fd < 0) + { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't create raw socket %d:%s", + errno, strerror(errno)); + return PCAP_ERROR; + } + + /* get interface index */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, handle->opt.source, sizeof(ifr.ifr_name)); + if ((handle->fd, SIOCGIFINDEX, &ifr) < 0) + { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, + "Unable to get interface index: %s", + pcap_strerror(errno)); + pcap_cleanup_live_common(handle); + return PCAP_ERROR; + } + handle->md.ifindex = ifr.ifr_ifindex; + + /* allocate butter */ + handle->buffer = malloc(handle->bufsize); + if (!handle->buffer) + { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate dump buffer: %s", + pcap_strerror(errno)); + pcap_cleanup_live_common(handle); + return PCAP_ERROR; + } + + /* Bind to the socket */ + addr.can_family = AF_CAN; + addr.can_ifindex = handle->md.ifindex; + if( bind( handle->fd, (struct sockaddr*)&addr, sizeof(addr) ) < 0 ) + { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't attach to device %d %d:%s", + handle->md.ifindex, errno, strerror(errno)); + pcap_cleanup_live_common(handle); + return PCAP_ERROR; + } + + if (handle->opt.rfmon) + { + /* Monitor mode doesn't apply to CAN devices. */ + pcap_cleanup_live_common(handle); + return PCAP_ERROR; + } + + handle->selectable_fd = handle->fd; + return 0; + +} + + +static int +can_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) +{ + struct msghdr msg; + struct pcap_pkthdr pkth; + struct timeval tv; + struct iovec iv; + struct can_frame* cf; + + 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; + + do + { + pkth.caplen = recvmsg(handle->fd, &msg, 0); + if (handle->break_loop) + { + handle->break_loop = 0; + return -2; + } + } while ((pkth.caplen == -1) && (errno == EINTR)); + + if (pkth.caplen < 0) + { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't receive packet %d:%s", + errno, strerror(errno)); + return -1; + } + + /* adjust capture len according to frame len */ + cf = (struct can_frame*)&handle->buffer[8]; + pkth.caplen -= 8 - cf->can_dlc; + pkth.len = pkth.caplen; + + cf->can_id = htonl( cf->can_id ); + + if( -1 == gettimeofday(&pkth.ts, NULL) ) + { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't get time of day %d:%s", + errno, strerror(errno)); + return -1; + } + + callback(user, &pkth, &handle->buffer[8]); + + return 1; +} + + +static int +can_inject_linux(pcap_t *handle, const void *buf, size_t size) +{ + /* not yet implemented */ + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on " + "can devices"); + return (-1); +} + + +static int +can_stats_linux(pcap_t *handle, struct pcap_stat *stats) +{ + /* not yet implemented */ + stats->ps_recv = 0; /* number of packets received */ + stats->ps_drop = 0; /* number of packets dropped */ + stats->ps_ifdrop = 0; /* drops by interface -- only supported on some platforms */ + return 0; +} + + +static int +can_setfilter_linux(pcap_t *p, struct bpf_program *fp) +{ + /* not yet implemented */ + return 0; +} + + +static int +can_setdirection_linux(pcap_t *p, pcap_direction_t d) +{ + /* no support for PCAP_D_OUT */ + if (d == PCAP_D_OUT) + { + snprintf(p->errbuf, sizeof(p->errbuf), + "Setting direction to PCAP_D_OUT is not supported on can"); + return -1; + } + + p->direction = d; + + return 0; +} + + +/* eof */ diff --git a/pcap-can-linux.h b/pcap-can-linux.h new file mode 100644 index 0000000..0c8f3b5 --- /dev/null +++ b/pcap-can-linux.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2009 Felix Obenhuber + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* + * Prototypes for SocketCAN related functions + */ +pcap_t* can_create(const char *device, char *ebuf); diff --git a/pcap-linux.c b/pcap-linux.c index 9703040..22339d6 100644 --- a/pcap-linux.c +++ b/pcap-linux.c @@ -176,6 +176,10 @@ static const char rcsid[] _U_ = #include "pcap-bt-linux.h" #endif +#ifdef PCAP_SUPPORT_CAN +#include "pcap-can-linux.h" +#endif + /* * If PF_PACKET is defined, we can use {SOCK_RAW,SOCK_DGRAM}/PF_PACKET * sockets rather than SOCK_PACKET sockets. @@ -376,6 +380,12 @@ pcap_create(const char *device, char *ebuf) } #endif +#ifdef PCAP_SUPPORT_CAN + if (strstr(device, "can") || strstr(device, "vcan")) { + return can_create(device, ebuf); + } +#endif + #ifdef PCAP_SUPPORT_USB if (strstr(device, "usbmon")) { return usb_create(device, ebuf); @@ -2073,6 +2083,12 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, int cooked_ok) case ARPHRD_CHAOS: handle->linktype = DLT_CHAOS; break; +#ifndef ARPHRD_CAN +#define ARPHRD_CAN 280 +#endif + case ARPHRD_CAN: + handle->linktype = DLT_CAN_SOCKETCAN; + break; #ifndef ARPHRD_IEEE802_TR #define ARPHRD_IEEE802_TR 800 /* From Linux 2.4 */