Add support for CANbus capture.
Signed-off-by: Guy Harris <guy@alum.mit.edu>
This commit is contained in:
parent
d32a10c10d
commit
1c1816f670
1
CREDITS
1
CREDITS
|
@ -35,6 +35,7 @@ Additional people who have contributed patches:
|
||||||
Dustin Spicuzza <dustin at virtualroadside dot com>
|
Dustin Spicuzza <dustin at virtualroadside dot com>
|
||||||
Eric Anderson <anderse at hpl dot hp dot com>
|
Eric Anderson <anderse at hpl dot hp dot com>
|
||||||
Erik de Castro Lopo <erik dot de dot castro dot lopo at sensorynetworks dot com>
|
Erik de Castro Lopo <erik dot de dot castro dot lopo at sensorynetworks dot com>
|
||||||
|
Felix Obenhuber <felix at obenhuber dot de>
|
||||||
Florent Drouin <Florent dot Drouin at alcatel-lucent dot fr>
|
Florent Drouin <Florent dot Drouin at alcatel-lucent dot fr>
|
||||||
Franz Schaefer <schaefer at mond dot at>
|
Franz Schaefer <schaefer at mond dot at>
|
||||||
Fulko Hew <fulko dot hew at gmail dot com>
|
Fulko Hew <fulko dot hew at gmail dot com>
|
||||||
|
|
|
@ -80,7 +80,7 @@ YACC = @V_YACC@
|
||||||
@rm -f $@
|
@rm -f $@
|
||||||
$(CC) $(CFLAGS) -c $(srcdir)/$*.c
|
$(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
|
FSRC = fad-@V_FINDALLDEVS@.c
|
||||||
SSRC = @SSRC@
|
SSRC = @SSRC@
|
||||||
CSRC = pcap.c inet.c gencode.c optimize.c nametoaddr.c \
|
CSRC = pcap.c inet.c gencode.c optimize.c nametoaddr.c \
|
||||||
|
@ -264,6 +264,8 @@ EXTRA_DIST = \
|
||||||
pcap-bpf.c \
|
pcap-bpf.c \
|
||||||
pcap-bt-linux.c \
|
pcap-bt-linux.c \
|
||||||
pcap-bt-linux.h \
|
pcap-bt-linux.h \
|
||||||
|
pcap-can-linux.c \
|
||||||
|
pcap-can-linux.h \
|
||||||
pcap-config.in \
|
pcap-config.in \
|
||||||
pcap-dag.c \
|
pcap-dag.c \
|
||||||
pcap-dag.h \
|
pcap-dag.h \
|
||||||
|
|
|
@ -214,6 +214,9 @@
|
||||||
/* target host supports Bluetooth sniffing */
|
/* target host supports Bluetooth sniffing */
|
||||||
#undef PCAP_SUPPORT_BT
|
#undef PCAP_SUPPORT_BT
|
||||||
|
|
||||||
|
/* target host supports CAN sniffing */
|
||||||
|
#undef PCAP_SUPPORT_CAN
|
||||||
|
|
||||||
/* target host supports USB sniffing */
|
/* target host supports USB sniffing */
|
||||||
#undef PCAP_SUPPORT_USB
|
#undef PCAP_SUPPORT_USB
|
||||||
|
|
||||||
|
|
|
@ -698,6 +698,8 @@ PCAP_SUPPORT_USB
|
||||||
USB_SRC
|
USB_SRC
|
||||||
PCAP_SUPPORT_BT
|
PCAP_SUPPORT_BT
|
||||||
BT_SRC
|
BT_SRC
|
||||||
|
PCAP_SUPPORT_CAN
|
||||||
|
CAN_SRC
|
||||||
INSTALL_PROGRAM
|
INSTALL_PROGRAM
|
||||||
INSTALL_SCRIPT
|
INSTALL_SCRIPT
|
||||||
INSTALL_DATA
|
INSTALL_DATA
|
||||||
|
@ -1293,6 +1295,8 @@ Optional Features:
|
||||||
--enable-yydebug build parser debugging code
|
--enable-yydebug build parser debugging code
|
||||||
--enable-bluetooth enable bluetooth support [default=yes, if support
|
--enable-bluetooth enable bluetooth support [default=yes, if support
|
||||||
available]
|
available]
|
||||||
|
--enable-can enable can support [default=yes, if support
|
||||||
|
available]
|
||||||
|
|
||||||
Optional Packages:
|
Optional Packages:
|
||||||
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
|
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
|
||||||
|
@ -3926,7 +3930,7 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
|
||||||
else
|
else
|
||||||
ac_cv_header_stdc=no
|
ac_cv_header_stdc=no
|
||||||
fi
|
fi
|
||||||
rm -f conftest*
|
rm -f -r conftest*
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -3947,7 +3951,7 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
|
||||||
else
|
else
|
||||||
ac_cv_header_stdc=no
|
ac_cv_header_stdc=no
|
||||||
fi
|
fi
|
||||||
rm -f conftest*
|
rm -f -r conftest*
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -5007,7 +5011,7 @@ cat >>confdefs.h <<_ACEOF
|
||||||
_ACEOF
|
_ACEOF
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
rm -f conftest*
|
rm -f -r conftest*
|
||||||
if test $ac_cv_sys_file_offset_bits = unknown; then
|
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 "$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; }
|
echo $ECHO_N "checking for _LARGE_FILES value needed for large files... $ECHO_C" >&6; }
|
||||||
|
@ -5128,7 +5132,7 @@ cat >>confdefs.h <<_ACEOF
|
||||||
_ACEOF
|
_ACEOF
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
rm -f conftest*
|
rm -f -r conftest*
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -5239,7 +5243,7 @@ cat >>confdefs.h <<_ACEOF
|
||||||
_ACEOF
|
_ACEOF
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
rm -f conftest*
|
rm -f -r conftest*
|
||||||
|
|
||||||
# We used to try defining _XOPEN_SOURCE=500 too, to work around a bug
|
# 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.
|
# 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
|
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 <linux/can/version.h>
|
||||||
|
_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 <linux/can/version.h>
|
||||||
|
_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
|
fi
|
||||||
|
|
||||||
# Find a good install program. We prefer a C program (faster),
|
# 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
|
USB_SRC!$USB_SRC$ac_delim
|
||||||
PCAP_SUPPORT_BT!$PCAP_SUPPORT_BT$ac_delim
|
PCAP_SUPPORT_BT!$PCAP_SUPPORT_BT$ac_delim
|
||||||
BT_SRC!$BT_SRC$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_PROGRAM!$INSTALL_PROGRAM$ac_delim
|
||||||
INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim
|
INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim
|
||||||
INSTALL_DATA!$INSTALL_DATA$ac_delim
|
INSTALL_DATA!$INSTALL_DATA$ac_delim
|
||||||
LTLIBOBJS!$LTLIBOBJS$ac_delim
|
LTLIBOBJS!$LTLIBOBJS$ac_delim
|
||||||
_ACEOF
|
_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
|
break
|
||||||
elif $ac_last_try; then
|
elif $ac_last_try; then
|
||||||
{ { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
|
{ { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
|
||||||
|
|
22
configure.in
22
configure.in
|
@ -1283,6 +1283,28 @@ if test "x$enable_bluetooth" != "xno" ; then
|
||||||
AC_SUBST(BT_SRC)
|
AC_SUBST(BT_SRC)
|
||||||
fi
|
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_PROG_INSTALL
|
||||||
|
|
||||||
AC_CONFIG_HEADER(config.h)
|
AC_CONFIG_HEADER(config.h)
|
||||||
|
|
|
@ -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 <felix@obenhuber.de>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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 <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
|
||||||
|
#include <linux/can.h>
|
||||||
|
#include <linux/can/raw.h>
|
||||||
|
|
||||||
|
/* 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 */
|
|
@ -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);
|
16
pcap-linux.c
16
pcap-linux.c
|
@ -176,6 +176,10 @@ static const char rcsid[] _U_ =
|
||||||
#include "pcap-bt-linux.h"
|
#include "pcap-bt-linux.h"
|
||||||
#endif
|
#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
|
* If PF_PACKET is defined, we can use {SOCK_RAW,SOCK_DGRAM}/PF_PACKET
|
||||||
* sockets rather than SOCK_PACKET sockets.
|
* sockets rather than SOCK_PACKET sockets.
|
||||||
|
@ -376,6 +380,12 @@ pcap_create(const char *device, char *ebuf)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef PCAP_SUPPORT_CAN
|
||||||
|
if (strstr(device, "can") || strstr(device, "vcan")) {
|
||||||
|
return can_create(device, ebuf);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef PCAP_SUPPORT_USB
|
#ifdef PCAP_SUPPORT_USB
|
||||||
if (strstr(device, "usbmon")) {
|
if (strstr(device, "usbmon")) {
|
||||||
return usb_create(device, ebuf);
|
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:
|
case ARPHRD_CHAOS:
|
||||||
handle->linktype = DLT_CHAOS;
|
handle->linktype = DLT_CHAOS;
|
||||||
break;
|
break;
|
||||||
|
#ifndef ARPHRD_CAN
|
||||||
|
#define ARPHRD_CAN 280
|
||||||
|
#endif
|
||||||
|
case ARPHRD_CAN:
|
||||||
|
handle->linktype = DLT_CAN_SOCKETCAN;
|
||||||
|
break;
|
||||||
|
|
||||||
#ifndef ARPHRD_IEEE802_TR
|
#ifndef ARPHRD_IEEE802_TR
|
||||||
#define ARPHRD_IEEE802_TR 800 /* From Linux 2.4 */
|
#define ARPHRD_IEEE802_TR 800 /* From Linux 2.4 */
|
||||||
|
|
Reference in New Issue