initial create libsocketcan-nl project
Signed-off-by: Luotao Fu <l.fu@pengutronix.de>pull/106/head^2
commit
d9b6577d1a
|
|
@ -0,0 +1,34 @@
|
||||||
|
SUBDIRS = \
|
||||||
|
include \
|
||||||
|
config \
|
||||||
|
src \
|
||||||
|
tests
|
||||||
|
|
||||||
|
EXTRA_DIST = \
|
||||||
|
autogen.sh \
|
||||||
|
config/m4/.secret-world-domination-project
|
||||||
|
|
||||||
|
MAINTAINERCLEANFILES = \
|
||||||
|
configure \
|
||||||
|
GNUmakefile.in \
|
||||||
|
aclocal.m4 \
|
||||||
|
config/autoconf/compile \
|
||||||
|
config/autoconf/config.guess \
|
||||||
|
config/autoconf/config.sub \
|
||||||
|
config/autoconf/depcomp \
|
||||||
|
config/autoconf/install-sh \
|
||||||
|
config/autoconf/ltmain.sh \
|
||||||
|
config/autoconf/mdate-sh \
|
||||||
|
config/autoconf/missing \
|
||||||
|
config/autoconf/texinfo.tex \
|
||||||
|
config/m4/libtool.m4 \
|
||||||
|
config/m4/ltoptions.m4 \
|
||||||
|
config/m4/ltsugar.m4 \
|
||||||
|
config/m4/ltversion.m4 \
|
||||||
|
config/m4/lt~obsolete.m4 \
|
||||||
|
$(DIST_ARCHIVES)
|
||||||
|
|
||||||
|
maintainer-clean-local:
|
||||||
|
-chmod -R a+rw $(distdir)
|
||||||
|
-rm -fr $(distdir)
|
||||||
|
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
#
|
||||||
|
# usage:
|
||||||
|
#
|
||||||
|
# banner <target name>
|
||||||
|
#
|
||||||
|
banner() {
|
||||||
|
|
||||||
|
echo
|
||||||
|
TG=`echo $1 | sed -e "s,/.*/,,g"`
|
||||||
|
LINE=`echo $TG |sed -e "s/./-/g"`
|
||||||
|
echo $LINE
|
||||||
|
echo $TG
|
||||||
|
echo $LINE
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ACLOCAL=${ACLOCAL:=aclocal}
|
||||||
|
AUTOHEADER=${AUTOHEADER:=autoheader}
|
||||||
|
AUTOMAKE=${AUTOMAKE:=automake}
|
||||||
|
AUTOCONF=${AUTOCONF:=autoconf}
|
||||||
|
|
||||||
|
banner "running libtoolize"
|
||||||
|
libtoolize --force
|
||||||
|
[ $? != 0 ] && exit
|
||||||
|
|
||||||
|
banner "running aclocal"
|
||||||
|
$ACLOCAL -I config/m4
|
||||||
|
[ $? != 0 ] && exit
|
||||||
|
|
||||||
|
banner "running autoheader"
|
||||||
|
$AUTOHEADER
|
||||||
|
[ $? != 0 ] && exit
|
||||||
|
|
||||||
|
banner "running automake"
|
||||||
|
$AUTOMAKE --gnu --add-missing -Wall
|
||||||
|
[ $? != 0 ] && exit
|
||||||
|
|
||||||
|
banner "running autoconf"
|
||||||
|
$AUTOCONF -Wall
|
||||||
|
[ $? != 0 ] && exit
|
||||||
|
|
||||||
|
banner "Finished"
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
#
|
||||||
|
# usage:
|
||||||
|
#
|
||||||
|
# banner <target name>
|
||||||
|
#
|
||||||
|
banner() {
|
||||||
|
echo
|
||||||
|
TG=`echo $1 | sed -e "s,/.*/,,g"`
|
||||||
|
LINE=`echo $TG |sed -e "s/./-/g"`
|
||||||
|
echo $LINE
|
||||||
|
echo $TG
|
||||||
|
echo $LINE
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
banner "autoreconf"
|
||||||
|
|
||||||
|
autoreconf --force --install --symlink -Wall || exit $?
|
||||||
|
|
||||||
|
banner "Finished"
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
EXTRA_DIST = \
|
||||||
|
libsocketcan-nl.pc.in
|
||||||
|
|
||||||
|
pkgconfigdir = $(libdir)/pkgconfig
|
||||||
|
pkgconfig_DATA = libsocketcan-nl.pc
|
||||||
|
|
||||||
|
MAINTAINERCLEANFILES = \
|
||||||
|
GNUmakefile.in
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
prefix=@prefix@
|
||||||
|
exec_prefix=@exec_prefix@
|
||||||
|
libdir=@libdir@
|
||||||
|
includedir=@includedir@
|
||||||
|
|
||||||
|
Name: libsocketcan-nl
|
||||||
|
Description: provides access to socketcan netlink interface
|
||||||
|
Requires: @REQUIRES_LIBRN@
|
||||||
|
Version: @VERSION@
|
||||||
|
Libs: -L${libdir} -llibsocketcan-nl
|
||||||
|
#Libs.private: -lm -lpthread ...etc...
|
||||||
|
Cflags: -I${includedir}
|
||||||
|
|
@ -0,0 +1,238 @@
|
||||||
|
dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
|
||||||
|
dnl
|
||||||
|
dnl @summary figure out how to build C programs using POSIX threads
|
||||||
|
dnl
|
||||||
|
dnl This macro figures out how to build C programs using POSIX threads.
|
||||||
|
dnl It sets the PTHREAD_LIBS output variable to the threads library and
|
||||||
|
dnl linker flags, and the PTHREAD_CFLAGS output variable to any special
|
||||||
|
dnl C compiler flags that are needed. (The user can also force certain
|
||||||
|
dnl compiler flags/libs to be tested by setting these environment
|
||||||
|
dnl variables.)
|
||||||
|
dnl
|
||||||
|
dnl Also sets PTHREAD_CC to any special C compiler that is needed for
|
||||||
|
dnl multi-threaded programs (defaults to the value of CC otherwise).
|
||||||
|
dnl (This is necessary on AIX to use the special cc_r compiler alias.)
|
||||||
|
dnl
|
||||||
|
dnl NOTE: You are assumed to not only compile your program with these
|
||||||
|
dnl flags, but also link it with them as well. e.g. you should link
|
||||||
|
dnl with $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS
|
||||||
|
dnl $LIBS
|
||||||
|
dnl
|
||||||
|
dnl If you are only building threads programs, you may wish to use
|
||||||
|
dnl these variables in your default LIBS, CFLAGS, and CC:
|
||||||
|
dnl
|
||||||
|
dnl LIBS="$PTHREAD_LIBS $LIBS"
|
||||||
|
dnl CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||||
|
dnl CC="$PTHREAD_CC"
|
||||||
|
dnl
|
||||||
|
dnl In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute
|
||||||
|
dnl constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to
|
||||||
|
dnl that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
|
||||||
|
dnl
|
||||||
|
dnl ACTION-IF-FOUND is a list of shell commands to run if a threads
|
||||||
|
dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands to
|
||||||
|
dnl run it if it is not found. If ACTION-IF-FOUND is not specified, the
|
||||||
|
dnl default action will define HAVE_PTHREAD.
|
||||||
|
dnl
|
||||||
|
dnl Please let the authors know if this macro fails on any platform, or
|
||||||
|
dnl if you have any other suggestions or comments. This macro was based
|
||||||
|
dnl on work by SGJ on autoconf scripts for FFTW (www.fftw.org) (with
|
||||||
|
dnl help from M. Frigo), as well as ac_pthread and hb_pthread macros
|
||||||
|
dnl posted by Alejandro Forero Cuervo to the autoconf macro repository.
|
||||||
|
dnl We are also grateful for the helpful feedback of numerous users.
|
||||||
|
dnl
|
||||||
|
dnl @category InstalledPackages
|
||||||
|
dnl @author Steven G. Johnson <stevenj@alum.mit.edu>
|
||||||
|
dnl @version 2005-06-15
|
||||||
|
dnl @license GPLWithACException
|
||||||
|
|
||||||
|
AC_DEFUN([ACX_PTHREAD], [
|
||||||
|
AC_REQUIRE([AC_CANONICAL_HOST])
|
||||||
|
AC_LANG_SAVE
|
||||||
|
AC_LANG_C
|
||||||
|
acx_pthread_ok=no
|
||||||
|
|
||||||
|
# We used to check for pthread.h first, but this fails if pthread.h
|
||||||
|
# requires special compiler flags (e.g. on True64 or Sequent).
|
||||||
|
# It gets checked for in the link test anyway.
|
||||||
|
|
||||||
|
# First of all, check if the user has set any of the PTHREAD_LIBS,
|
||||||
|
# etcetera environment variables, and if threads linking works using
|
||||||
|
# them:
|
||||||
|
if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
|
||||||
|
save_CFLAGS="$CFLAGS"
|
||||||
|
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||||
|
save_LIBS="$LIBS"
|
||||||
|
LIBS="$PTHREAD_LIBS $LIBS"
|
||||||
|
AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
|
||||||
|
AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes)
|
||||||
|
AC_MSG_RESULT($acx_pthread_ok)
|
||||||
|
if test x"$acx_pthread_ok" = xno; then
|
||||||
|
PTHREAD_LIBS=""
|
||||||
|
PTHREAD_CFLAGS=""
|
||||||
|
fi
|
||||||
|
LIBS="$save_LIBS"
|
||||||
|
CFLAGS="$save_CFLAGS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# We must check for the threads library under a number of different
|
||||||
|
# names; the ordering is very important because some systems
|
||||||
|
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
|
||||||
|
# libraries is broken (non-POSIX).
|
||||||
|
|
||||||
|
# Create a list of thread flags to try. Items starting with a "-" are
|
||||||
|
# C compiler flags, and other items are library names, except for "none"
|
||||||
|
# which indicates that we try without any flags at all, and "pthread-config"
|
||||||
|
# which is a program returning the flags for the Pth emulation library.
|
||||||
|
|
||||||
|
acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
|
||||||
|
|
||||||
|
# The ordering *is* (sometimes) important. Some notes on the
|
||||||
|
# individual items follow:
|
||||||
|
|
||||||
|
# pthreads: AIX (must check this before -lpthread)
|
||||||
|
# none: in case threads are in libc; should be tried before -Kthread and
|
||||||
|
# other compiler flags to prevent continual compiler warnings
|
||||||
|
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
|
||||||
|
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
|
||||||
|
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
|
||||||
|
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
|
||||||
|
# -pthreads: Solaris/gcc
|
||||||
|
# -mthreads: Mingw32/gcc, Lynx/gcc
|
||||||
|
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
|
||||||
|
# doesn't hurt to check since this sometimes defines pthreads too;
|
||||||
|
# also defines -D_REENTRANT)
|
||||||
|
# ... -mt is also the pthreads flag for HP/aCC
|
||||||
|
# pthread: Linux, etcetera
|
||||||
|
# --thread-safe: KAI C++
|
||||||
|
# pthread-config: use pthread-config program (for GNU Pth library)
|
||||||
|
|
||||||
|
case "${host_cpu}-${host_os}" in
|
||||||
|
*solaris*)
|
||||||
|
|
||||||
|
# On Solaris (at least, for some versions), libc contains stubbed
|
||||||
|
# (non-functional) versions of the pthreads routines, so link-based
|
||||||
|
# tests will erroneously succeed. (We need to link with -pthreads/-mt/
|
||||||
|
# -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
|
||||||
|
# a function called by this macro, so we could check for that, but
|
||||||
|
# who knows whether they'll stub that too in a future libc.) So,
|
||||||
|
# we'll just look for -pthreads and -lpthread first:
|
||||||
|
|
||||||
|
acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if test x"$acx_pthread_ok" = xno; then
|
||||||
|
for flag in $acx_pthread_flags; do
|
||||||
|
|
||||||
|
case $flag in
|
||||||
|
none)
|
||||||
|
AC_MSG_CHECKING([whether pthreads work without any flags])
|
||||||
|
;;
|
||||||
|
|
||||||
|
-*)
|
||||||
|
AC_MSG_CHECKING([whether pthreads work with $flag])
|
||||||
|
PTHREAD_CFLAGS="$flag"
|
||||||
|
;;
|
||||||
|
|
||||||
|
pthread-config)
|
||||||
|
AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no)
|
||||||
|
if test x"$acx_pthread_config" = xno; then continue; fi
|
||||||
|
PTHREAD_CFLAGS="`pthread-config --cflags`"
|
||||||
|
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
AC_MSG_CHECKING([for the pthreads library -l$flag])
|
||||||
|
PTHREAD_LIBS="-l$flag"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
save_LIBS="$LIBS"
|
||||||
|
save_CFLAGS="$CFLAGS"
|
||||||
|
LIBS="$PTHREAD_LIBS $LIBS"
|
||||||
|
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||||
|
|
||||||
|
# Check for various functions. We must include pthread.h,
|
||||||
|
# since some functions may be macros. (On the Sequent, we
|
||||||
|
# need a special flag -Kthread to make this header compile.)
|
||||||
|
# We check for pthread_join because it is in -lpthread on IRIX
|
||||||
|
# while pthread_create is in libc. We check for pthread_attr_init
|
||||||
|
# due to DEC craziness with -lpthreads. We check for
|
||||||
|
# pthread_cleanup_push because it is one of the few pthread
|
||||||
|
# functions on Solaris that doesn't have a non-functional libc stub.
|
||||||
|
# We try pthread_create on general principles.
|
||||||
|
AC_TRY_LINK([#include <pthread.h>],
|
||||||
|
[pthread_t th; pthread_join(th, 0);
|
||||||
|
pthread_attr_init(0); pthread_cleanup_push(0, 0);
|
||||||
|
pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
|
||||||
|
[acx_pthread_ok=yes])
|
||||||
|
|
||||||
|
LIBS="$save_LIBS"
|
||||||
|
CFLAGS="$save_CFLAGS"
|
||||||
|
|
||||||
|
AC_MSG_RESULT($acx_pthread_ok)
|
||||||
|
if test "x$acx_pthread_ok" = xyes; then
|
||||||
|
break;
|
||||||
|
fi
|
||||||
|
|
||||||
|
PTHREAD_LIBS=""
|
||||||
|
PTHREAD_CFLAGS=""
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Various other checks:
|
||||||
|
if test "x$acx_pthread_ok" = xyes; then
|
||||||
|
save_LIBS="$LIBS"
|
||||||
|
LIBS="$PTHREAD_LIBS $LIBS"
|
||||||
|
save_CFLAGS="$CFLAGS"
|
||||||
|
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||||
|
|
||||||
|
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
|
||||||
|
AC_MSG_CHECKING([for joinable pthread attribute])
|
||||||
|
attr_name=unknown
|
||||||
|
for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
|
||||||
|
AC_TRY_LINK([#include <pthread.h>], [int attr=$attr; return attr;],
|
||||||
|
[attr_name=$attr; break])
|
||||||
|
done
|
||||||
|
AC_MSG_RESULT($attr_name)
|
||||||
|
if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
|
||||||
|
AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name,
|
||||||
|
[Define to necessary symbol if this constant
|
||||||
|
uses a non-standard name on your system.])
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([if more special flags are required for pthreads])
|
||||||
|
flag=no
|
||||||
|
case "${host_cpu}-${host_os}" in
|
||||||
|
*-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";;
|
||||||
|
*solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
|
||||||
|
esac
|
||||||
|
AC_MSG_RESULT(${flag})
|
||||||
|
if test "x$flag" != xno; then
|
||||||
|
PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
LIBS="$save_LIBS"
|
||||||
|
CFLAGS="$save_CFLAGS"
|
||||||
|
|
||||||
|
# More AIX lossage: must compile with cc_r
|
||||||
|
AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC})
|
||||||
|
else
|
||||||
|
PTHREAD_CC="$CC"
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_SUBST(PTHREAD_LIBS)
|
||||||
|
AC_SUBST(PTHREAD_CFLAGS)
|
||||||
|
AC_SUBST(PTHREAD_CC)
|
||||||
|
|
||||||
|
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
|
||||||
|
if test x"$acx_pthread_ok" = xyes; then
|
||||||
|
ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
|
||||||
|
:
|
||||||
|
else
|
||||||
|
acx_pthread_ok=no
|
||||||
|
$2
|
||||||
|
fi
|
||||||
|
AC_LANG_RESTORE
|
||||||
|
])dnl ACX_PTHREAD
|
||||||
|
|
@ -0,0 +1,122 @@
|
||||||
|
# -*- Autoconf -*-
|
||||||
|
# Process this file with autoconf to produce a configure script.
|
||||||
|
AC_PREREQ(2.59)
|
||||||
|
|
||||||
|
AC_INIT([libsocketcan-nl], [0.0.1], [bugs@pengutronix.de])
|
||||||
|
AC_CONFIG_HEADERS([include/libsocketcan-nl_config.h])
|
||||||
|
AC_CONFIG_SRCDIR([src/socketcan_netlink.c])
|
||||||
|
AC_CONFIG_MACRO_DIR([config/m4])
|
||||||
|
AC_CONFIG_AUX_DIR([config/autoconf])
|
||||||
|
AC_CANONICAL_BUILD
|
||||||
|
AC_CANONICAL_HOST
|
||||||
|
|
||||||
|
AM_MAINTAINER_MODE
|
||||||
|
|
||||||
|
CFLAGS="${CFLAGS} -Wall"
|
||||||
|
|
||||||
|
#
|
||||||
|
# libtool library versioning stuff
|
||||||
|
#
|
||||||
|
# Library code modified: REVISION++
|
||||||
|
# Interfaces changed/added/removed: CURRENT++ REVISION=0
|
||||||
|
# Interfaces added: AGE++
|
||||||
|
# Interfaces removed: AGE=0
|
||||||
|
LT_CURRENT=0
|
||||||
|
LT_REVISION=0
|
||||||
|
LT_AGE=0
|
||||||
|
AC_SUBST(LT_CURRENT)
|
||||||
|
AC_SUBST(LT_REVISION)
|
||||||
|
AC_SUBST(LT_AGE)
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Checks for programs.
|
||||||
|
#
|
||||||
|
AC_PROG_CC
|
||||||
|
#AM_MISSING_PROG(PERL, perl, $missing_dir)
|
||||||
|
# libtool, old:
|
||||||
|
AC_LIBTOOL_WIN32_DLL
|
||||||
|
#AC_LIBTOOL_TAGS([])
|
||||||
|
AC_PROG_LIBTOOL
|
||||||
|
# libtool, new:
|
||||||
|
# LT_INIT(win32-dll)
|
||||||
|
|
||||||
|
AM_INIT_AUTOMAKE([foreign no-exeext dist-bzip2])
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Checks for libraries.
|
||||||
|
#
|
||||||
|
|
||||||
|
AC_HEADER_DIRENT
|
||||||
|
AC_HEADER_STDC
|
||||||
|
AC_HEADER_SYS_WAIT
|
||||||
|
AC_CHECK_HEADERS([ \
|
||||||
|
arpa/inet.h \
|
||||||
|
limits.h \
|
||||||
|
netdb.h \
|
||||||
|
netinet/in.h \
|
||||||
|
stddef.h \
|
||||||
|
stdlib.h \
|
||||||
|
string.h \
|
||||||
|
sys/param.h \
|
||||||
|
sys/socket.h \
|
||||||
|
sys/time.h \
|
||||||
|
sys/un.h \
|
||||||
|
unistd.h \
|
||||||
|
utime.h \
|
||||||
|
net/if.h \
|
||||||
|
linux/netlink.h \
|
||||||
|
linux/rtnetlink.h \
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Checks for typedefs, structures, and compiler characteristics.
|
||||||
|
#
|
||||||
|
AC_C_CONST
|
||||||
|
AC_C_INLINE
|
||||||
|
AC_TYPE_SIZE_T
|
||||||
|
AC_HEADER_TIME
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Checks for library functions.
|
||||||
|
#
|
||||||
|
AC_FUNC_MEMCMP
|
||||||
|
AC_TYPE_SIGNAL
|
||||||
|
AC_FUNC_STAT
|
||||||
|
AC_FUNC_UTIME_NULL
|
||||||
|
AC_CHECK_FUNCS([gethostbyaddr gethostbyname gethostname gettimeofday memset mkdir socket utime])
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Debugging
|
||||||
|
#
|
||||||
|
AC_MSG_CHECKING([whether to enable debugging])
|
||||||
|
AC_ARG_ENABLE(debug,
|
||||||
|
AS_HELP_STRING([--enable-debug], [enable debugging @<:@default=yes@:>@]),
|
||||||
|
[case "$enableval" in
|
||||||
|
y | yes) CONFIG_DEBUG=yes ;;
|
||||||
|
*) CONFIG_DEBUG=no ;;
|
||||||
|
esac],
|
||||||
|
[CONFIG_DEBUG=yes])
|
||||||
|
AC_MSG_RESULT([${CONFIG_DEBUG}])
|
||||||
|
if test "${CONFIG_DEBUG}" = "yes"; then
|
||||||
|
CFLAGS="${CFLAGS} -Werror -Wsign-compare -Wfloat-equal -Wformat-security -g -O1"
|
||||||
|
AC_DEFINE(DEBUG, 1, [debugging])
|
||||||
|
else
|
||||||
|
CFLAGS="${CFLAGS} -O2"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
AC_CONFIG_FILES([
|
||||||
|
GNUmakefile
|
||||||
|
config/libsocketcan-nl.pc
|
||||||
|
config/GNUmakefile
|
||||||
|
include/GNUmakefile
|
||||||
|
src/GNUmakefile
|
||||||
|
tests/GNUmakefile
|
||||||
|
])
|
||||||
|
AC_OUTPUT
|
||||||
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
noinst_HEADERS = \
|
||||||
|
libsocketcan-nlstuff.h
|
||||||
|
|
||||||
|
nobase_include_HEADERS = \
|
||||||
|
socketcan_netlink.h
|
||||||
|
|
||||||
|
MAINTAINERCLEANFILES = \
|
||||||
|
libsocketcan-nl_config.h.in \
|
||||||
|
GNUmakefile.in
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
/*
|
||||||
|
* linux/can/netlink.h
|
||||||
|
*
|
||||||
|
* Definitions for the CAN netlink interface
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 Wolfgang Grandegger <wg@grandegger.com>
|
||||||
|
*
|
||||||
|
* Send feedback to <socketcan-users@lists.berlios.de>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CAN_NETLINK_H
|
||||||
|
#define CAN_NETLINK_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CAN bit-timing parameters
|
||||||
|
*
|
||||||
|
* For futher information, please read chapter "8 BIT TIMING
|
||||||
|
* REQUIREMENTS" of the "Bosch CAN Specification version 2.0"
|
||||||
|
* at http://www.semiconductors.bosch.de/pdf/can2spec.pdf.
|
||||||
|
*/
|
||||||
|
struct can_bittiming {
|
||||||
|
__u32 bitrate; /* Bit-rate in bits/second */
|
||||||
|
__u32 sample_point; /* Sample point in one-tenth of a percent */
|
||||||
|
__u32 tq; /* Time quanta (TQ) in nanoseconds */
|
||||||
|
__u32 prop_seg; /* Propagation segment in TQs */
|
||||||
|
__u32 phase_seg1; /* Phase buffer segment 1 in TQs */
|
||||||
|
__u32 phase_seg2; /* Phase buffer segment 2 in TQs */
|
||||||
|
__u32 sjw; /* Synchronisation jump width in TQs */
|
||||||
|
__u32 brp; /* Bit-rate prescaler */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CAN harware-dependent bit-timing constant
|
||||||
|
*
|
||||||
|
* Used for calculating and checking bit-timing parameters
|
||||||
|
*/
|
||||||
|
struct can_bittiming_const {
|
||||||
|
char name[16]; /* Name of the CAN controller hardware */
|
||||||
|
__u32 tseg1_min; /* Time segement 1 = prop_seg + phase_seg1 */
|
||||||
|
__u32 tseg1_max;
|
||||||
|
__u32 tseg2_min; /* Time segement 2 = phase_seg2 */
|
||||||
|
__u32 tseg2_max;
|
||||||
|
__u32 sjw_max; /* Synchronisation jump width */
|
||||||
|
__u32 brp_min; /* Bit-rate prescaler */
|
||||||
|
__u32 brp_max;
|
||||||
|
__u32 brp_inc;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CAN clock parameters
|
||||||
|
*/
|
||||||
|
struct can_clock {
|
||||||
|
__u32 freq; /* CAN system clock frequency in Hz */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CAN operational and error states
|
||||||
|
*/
|
||||||
|
enum can_state {
|
||||||
|
CAN_STATE_ERROR_ACTIVE = 0, /* RX/TX error count < 96 */
|
||||||
|
CAN_STATE_ERROR_WARNING, /* RX/TX error count < 128 */
|
||||||
|
CAN_STATE_ERROR_PASSIVE, /* RX/TX error count < 256 */
|
||||||
|
CAN_STATE_BUS_OFF, /* RX/TX error count >= 256 */
|
||||||
|
CAN_STATE_STOPPED, /* Device is stopped */
|
||||||
|
CAN_STATE_SLEEPING, /* Device is sleeping */
|
||||||
|
CAN_STATE_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CAN controller mode
|
||||||
|
*/
|
||||||
|
struct can_ctrlmode {
|
||||||
|
__u32 mask;
|
||||||
|
__u32 flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CAN_CTRLMODE_LOOPBACK 0x1 /* Loopback mode */
|
||||||
|
#define CAN_CTRLMODE_LISTENONLY 0x2 /* Listen-only mode */
|
||||||
|
#define CAN_CTRLMODE_3_SAMPLES 0x4 /* Triple sampling mode */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CAN device statistics
|
||||||
|
*/
|
||||||
|
struct can_device_stats {
|
||||||
|
__u32 bus_error; /* Bus errors */
|
||||||
|
__u32 error_warning; /* Changes to error warning state */
|
||||||
|
__u32 error_passive; /* Changes to error passive state */
|
||||||
|
__u32 bus_off; /* Changes to bus off state */
|
||||||
|
__u32 arbitration_lost; /* Arbitration lost errors */
|
||||||
|
__u32 restarts; /* CAN controller re-starts */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CAN netlink interface
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
IFLA_CAN_UNSPEC,
|
||||||
|
IFLA_CAN_BITTIMING,
|
||||||
|
IFLA_CAN_BITTIMING_CONST,
|
||||||
|
IFLA_CAN_CLOCK,
|
||||||
|
IFLA_CAN_STATE,
|
||||||
|
IFLA_CAN_CTRLMODE,
|
||||||
|
IFLA_CAN_RESTART_MS,
|
||||||
|
IFLA_CAN_RESTART,
|
||||||
|
__IFLA_CAN_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
#define IFLA_CAN_MAX (__IFLA_CAN_MAX - 1)
|
||||||
|
|
||||||
|
#endif /* CAN_NETLINK_H */
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
#ifndef LIBSOCKETCAN-NL_H
|
||||||
|
#define LIBSOCKETCAN-NL_H
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
#ifndef LIBSOCKETCAN-NL_H
|
||||||
|
#define LIBSOCKETCAN-NL_H
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Header file for CAN netlink support
|
||||||
|
* (C) 2009 Luotao Fu <l.fu@pengutronix.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _NMS_H
|
||||||
|
#define _NMS_H
|
||||||
|
|
||||||
|
#define IFLA_CAN_MAX (__IFLA_CAN_MAX - 1)
|
||||||
|
#define IF_UP 1
|
||||||
|
#define IF_DOWN 2
|
||||||
|
|
||||||
|
#define GET_STATE 1
|
||||||
|
#define GET_RESTART_MS 2
|
||||||
|
#define GET_BITTIMING 3
|
||||||
|
|
||||||
|
struct get_req {
|
||||||
|
struct nlmsghdr n;
|
||||||
|
struct rtgenmsg g;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct set_req {
|
||||||
|
struct nlmsghdr n;
|
||||||
|
struct ifinfomsg i;
|
||||||
|
char buf[1024];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct req_info {
|
||||||
|
__u8 restart;
|
||||||
|
__u8 disable_autorestart;
|
||||||
|
__u32 restart_ms;
|
||||||
|
__u32 bitrate;
|
||||||
|
__u32 ctrlmode;
|
||||||
|
__u32 flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
int if_down(int fd, const char *name);
|
||||||
|
int if_up(int fd, const char *name);
|
||||||
|
|
||||||
|
int set_link_can(const char *name, struct req_info *req_info);
|
||||||
|
int set_restart(const char *name);
|
||||||
|
int set_bitrate(const char *name, __u32 bitrate);
|
||||||
|
int set_restart_ms(const char *name, __u32 restart_ms);
|
||||||
|
|
||||||
|
int get_state(const char *name);
|
||||||
|
__u32 get_restart_ms(const char *name);
|
||||||
|
int get_bittiming(const char *name, struct can_bittiming *bt);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
lib_LTLIBRARIES = libsocketcan-nl.la
|
||||||
|
|
||||||
|
AM_CPPFLAGS = \
|
||||||
|
-I$(top_srcdir)/include \
|
||||||
|
-I$(top_builddir)/include
|
||||||
|
|
||||||
|
libsocketcan_nl_la_SOURCES = socketcan_netlink.c
|
||||||
|
|
||||||
|
libsocketcan_nl_la_LDFLAGS = \
|
||||||
|
-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
|
||||||
|
# -no-undefined # win32_dll stuff only
|
||||||
|
|
||||||
|
#libsocketcan-nl_LDADD = \
|
||||||
|
# $(librn_LIBS)
|
||||||
|
#
|
||||||
|
MAINTAINERCLEANFILES = \
|
||||||
|
GNUmakefile.in
|
||||||
|
|
@ -0,0 +1,554 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
|
||||||
|
#include <linux/rtnetlink.h>
|
||||||
|
#include <linux/netlink.h>
|
||||||
|
|
||||||
|
#include <can/netlink.h>
|
||||||
|
#include <socketcan_netlink.h>
|
||||||
|
|
||||||
|
#define parse_rtattr_nested(tb, max, rta) \
|
||||||
|
(parse_rtattr((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta)))
|
||||||
|
|
||||||
|
#define NLMSG_TAIL(nmsg) \
|
||||||
|
((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, int len)
|
||||||
|
{
|
||||||
|
memset(tb, 0, sizeof(*tb) * max);
|
||||||
|
while (RTA_OK(rta, len)) {
|
||||||
|
if (rta->rta_type <= max) {
|
||||||
|
tb[rta->rta_type] = rta;
|
||||||
|
}
|
||||||
|
|
||||||
|
rta = RTA_NEXT(rta, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int addattr32(struct nlmsghdr *n, size_t maxlen, int type, __u32 data)
|
||||||
|
{
|
||||||
|
int len = RTA_LENGTH(4);
|
||||||
|
struct rtattr *rta;
|
||||||
|
|
||||||
|
if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"addattr32: Error! max allowed bound %lu exceeded\n",
|
||||||
|
maxlen);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rta = NLMSG_TAIL(n);
|
||||||
|
rta->rta_type = type;
|
||||||
|
rta->rta_len = len;
|
||||||
|
memcpy(RTA_DATA(rta), &data, 4);
|
||||||
|
n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int addattr_l(struct nlmsghdr *n, size_t maxlen, int type, const void *data,
|
||||||
|
int alen)
|
||||||
|
{
|
||||||
|
int len = RTA_LENGTH(alen);
|
||||||
|
struct rtattr *rta;
|
||||||
|
|
||||||
|
if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"addattr_l ERROR: message exceeded bound of %lu\n",
|
||||||
|
maxlen);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rta = NLMSG_TAIL(n);
|
||||||
|
rta->rta_type = type;
|
||||||
|
rta->rta_len = len;
|
||||||
|
memcpy(RTA_DATA(rta), data, alen);
|
||||||
|
n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int send_mod_request(int fd, struct nlmsghdr *n)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
struct sockaddr_nl nladdr;
|
||||||
|
struct nlmsghdr *h;
|
||||||
|
|
||||||
|
struct iovec iov = {
|
||||||
|
.iov_base = (void *)n,
|
||||||
|
.iov_len = n->nlmsg_len
|
||||||
|
};
|
||||||
|
struct msghdr msg = {
|
||||||
|
.msg_name = &nladdr,
|
||||||
|
.msg_namelen = sizeof(nladdr),
|
||||||
|
.msg_iov = &iov,
|
||||||
|
.msg_iovlen = 1,
|
||||||
|
};
|
||||||
|
char buf[16384];
|
||||||
|
|
||||||
|
memset(&nladdr, 0, sizeof(nladdr));
|
||||||
|
|
||||||
|
nladdr.nl_family = AF_NETLINK;
|
||||||
|
nladdr.nl_pid = 0;
|
||||||
|
nladdr.nl_groups = 0;
|
||||||
|
|
||||||
|
n->nlmsg_seq = 0;
|
||||||
|
n->nlmsg_flags |= NLM_F_ACK;
|
||||||
|
|
||||||
|
status = sendmsg(fd, &msg, 0);
|
||||||
|
|
||||||
|
if (status < 0) {
|
||||||
|
perror("Cannot talk to rtnetlink");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
//printf("stat sent: %d\n", status);
|
||||||
|
|
||||||
|
iov.iov_base = buf;
|
||||||
|
while (1) {
|
||||||
|
iov.iov_len = sizeof(buf);
|
||||||
|
status = recvmsg(fd, &msg, 0);
|
||||||
|
//printf("stat rcv: %d\n", status);
|
||||||
|
for (h = (struct nlmsghdr *)buf;
|
||||||
|
(size_t)status >= sizeof(*h);) {
|
||||||
|
int len = h->nlmsg_len;
|
||||||
|
int l = len - sizeof(*h);
|
||||||
|
//printf("msgtype: %d, len %d, l %d\n", h->nlmsg_type, len, l);
|
||||||
|
if (l < 0 || len > status) {
|
||||||
|
if (msg.msg_flags & MSG_TRUNC) {
|
||||||
|
fprintf(stderr, "Truncated message\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fprintf(stderr,
|
||||||
|
"!!!malformed message: len=%d\n", len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h->nlmsg_type == NLMSG_ERROR) {
|
||||||
|
struct nlmsgerr *err =
|
||||||
|
(struct nlmsgerr *)NLMSG_DATA(h);
|
||||||
|
if ((size_t)l < sizeof(struct nlmsgerr)) {
|
||||||
|
fprintf(stderr, "ERROR truncated\n");
|
||||||
|
} else {
|
||||||
|
errno = -err->error;
|
||||||
|
if (errno == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
perror("RTNETLINK answers");
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
status -= NLMSG_ALIGN(len);
|
||||||
|
h = (struct nlmsghdr *)((char *)h + NLMSG_ALIGN(len));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int send_dump_request(int fd, int family, int type)
|
||||||
|
{
|
||||||
|
struct get_req req;
|
||||||
|
|
||||||
|
memset(&req, 0, sizeof(req));
|
||||||
|
|
||||||
|
req.n.nlmsg_len = sizeof(req);
|
||||||
|
req.n.nlmsg_type = type;
|
||||||
|
req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT | NLM_F_MATCH;
|
||||||
|
req.n.nlmsg_pid = 0;
|
||||||
|
req.n.nlmsg_seq = 0;
|
||||||
|
|
||||||
|
req.g.rtgen_family = family;
|
||||||
|
|
||||||
|
return send(fd, (void *)&req, sizeof(req), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int open_nl_sock()
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
int sndbuf = 32768;
|
||||||
|
int rcvbuf = 32768;
|
||||||
|
unsigned int addr_len;
|
||||||
|
struct sockaddr_nl local;
|
||||||
|
|
||||||
|
fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||||
|
if (fd < 0) {
|
||||||
|
perror("Cannot open netlink socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (void *)&sndbuf, sizeof(sndbuf));
|
||||||
|
|
||||||
|
setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void *)&rcvbuf, sizeof(rcvbuf));
|
||||||
|
|
||||||
|
memset(&local, 0, sizeof(local));
|
||||||
|
local.nl_family = AF_NETLINK;
|
||||||
|
local.nl_groups = 0;
|
||||||
|
|
||||||
|
if (bind(fd, (struct sockaddr *)&local, sizeof(local)) < 0) {
|
||||||
|
perror("Cannot bind netlink socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr_len = sizeof(local);
|
||||||
|
if (getsockname(fd, (struct sockaddr *)&local, &addr_len) < 0) {
|
||||||
|
perror("Cannot getsockname");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (addr_len != sizeof(local)) {
|
||||||
|
fprintf(stderr, "Wrong address length %d\n", addr_len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (local.nl_family != AF_NETLINK) {
|
||||||
|
fprintf(stderr, "Wrong address family %d\n", local.nl_family);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int do_get_nl_link(int fd, __u8 acquire, const char *name, void *res)
|
||||||
|
{
|
||||||
|
struct sockaddr_nl peer;
|
||||||
|
|
||||||
|
char cbuf[64];
|
||||||
|
char nlbuf[1024 * 8];
|
||||||
|
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
struct iovec iov = {
|
||||||
|
.iov_base = (void *)nlbuf,
|
||||||
|
.iov_len = sizeof(nlbuf),
|
||||||
|
};
|
||||||
|
|
||||||
|
struct msghdr msg = {
|
||||||
|
.msg_name = (void *)&peer,
|
||||||
|
.msg_namelen = sizeof(peer),
|
||||||
|
.msg_iov = &iov,
|
||||||
|
.msg_iovlen = 1,
|
||||||
|
.msg_control = &cbuf,
|
||||||
|
.msg_controllen = sizeof(cbuf),
|
||||||
|
.msg_flags = 0,
|
||||||
|
};
|
||||||
|
struct nlmsghdr *nl_msg;
|
||||||
|
ssize_t msglen;
|
||||||
|
|
||||||
|
struct rtattr *linkinfo[IFLA_INFO_MAX + 1];
|
||||||
|
struct rtattr *can_attr[IFLA_CAN_MAX + 1];
|
||||||
|
|
||||||
|
if (send_dump_request(fd, AF_PACKET, RTM_GETLINK) < 0) {
|
||||||
|
perror("Cannot send dump request");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((msglen = recvmsg(fd, &msg, 0)) <= 0) {
|
||||||
|
perror("Receive error");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
size_t u_msglen = (size_t)msglen;
|
||||||
|
/* Check to see if the buffers in msg get truncated */
|
||||||
|
if (msg.msg_namelen != sizeof(peer) ||
|
||||||
|
(msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC))) {
|
||||||
|
fprintf(stderr, "Uhoh... truncated message.\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (nl_msg = (struct nlmsghdr *)nlbuf;
|
||||||
|
NLMSG_OK(nl_msg, u_msglen); nl_msg = NLMSG_NEXT(nl_msg, u_msglen)) {
|
||||||
|
int type = nl_msg->nlmsg_type;
|
||||||
|
int len;
|
||||||
|
if (type != RTM_NEWLINK)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
struct ifinfomsg *ifi = NLMSG_DATA(nl_msg);
|
||||||
|
struct rtattr *tb[IFLA_MAX + 1];
|
||||||
|
|
||||||
|
len =
|
||||||
|
nl_msg->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifaddrmsg));
|
||||||
|
parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
|
||||||
|
|
||||||
|
if (strncmp((char *)RTA_DATA(tb[IFLA_IFNAME]), name, 4) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (tb[IFLA_LINKINFO])
|
||||||
|
parse_rtattr_nested(linkinfo,
|
||||||
|
IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!linkinfo[IFLA_INFO_DATA]) {
|
||||||
|
fprintf(stderr, "no link data found\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_rtattr_nested(can_attr, IFLA_CAN_MAX,
|
||||||
|
linkinfo[IFLA_INFO_DATA]);
|
||||||
|
|
||||||
|
switch (acquire) {
|
||||||
|
case GET_STATE:
|
||||||
|
if (can_attr[IFLA_CAN_STATE]) {
|
||||||
|
*((int *)res) =
|
||||||
|
*((__u32 *)
|
||||||
|
RTA_DATA(can_attr[IFLA_CAN_STATE]));
|
||||||
|
ret = 0;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "no state data found\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case GET_RESTART_MS:
|
||||||
|
if (can_attr[IFLA_CAN_RESTART_MS]) {
|
||||||
|
*((__u32 *) res) =
|
||||||
|
*((__u32 *)
|
||||||
|
RTA_DATA(can_attr[IFLA_CAN_RESTART_MS]));
|
||||||
|
ret = 0;
|
||||||
|
} else
|
||||||
|
fprintf(stderr, "no restart_ms data found\n");
|
||||||
|
|
||||||
|
break;
|
||||||
|
case GET_BITTIMING:
|
||||||
|
if (can_attr[IFLA_CAN_BITTIMING]) {
|
||||||
|
memcpy(res, RTA_DATA(can_attr[IFLA_CAN_BITTIMING]),
|
||||||
|
sizeof(struct can_bittiming));
|
||||||
|
ret = 0;
|
||||||
|
} else
|
||||||
|
fprintf(stderr, "no bittiming data found\n");
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "unknown acquire mode\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int do_set_nl_link(int fd, __u8 if_state, const char* name, struct req_info *req_info)
|
||||||
|
{
|
||||||
|
struct set_req req;
|
||||||
|
|
||||||
|
struct can_bittiming bt;
|
||||||
|
struct can_ctrlmode cm;
|
||||||
|
|
||||||
|
const char* type="can";
|
||||||
|
|
||||||
|
memset(&req, 0, sizeof(req));
|
||||||
|
|
||||||
|
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
|
||||||
|
req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||||
|
req.n.nlmsg_type = RTM_NEWLINK;
|
||||||
|
req.i.ifi_family = 0;
|
||||||
|
|
||||||
|
req.i.ifi_index = if_nametoindex(name);
|
||||||
|
if (req.i.ifi_index == 0) {
|
||||||
|
fprintf(stderr, "Cannot find device \"%s\"\n", name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (if_state) {
|
||||||
|
switch (if_state) {
|
||||||
|
case IF_DOWN:
|
||||||
|
req.i.ifi_change |= IFF_UP;
|
||||||
|
req.i.ifi_flags &= ~IFF_UP;
|
||||||
|
break;
|
||||||
|
case IF_UP:
|
||||||
|
req.i.ifi_change |= IFF_UP;
|
||||||
|
req.i.ifi_flags |= IFF_UP;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "unknown state\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req_info != NULL) {
|
||||||
|
/* setup linkinfo section */
|
||||||
|
struct rtattr *linkinfo = NLMSG_TAIL(&req.n);
|
||||||
|
addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
|
||||||
|
addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, type,
|
||||||
|
strlen(type));
|
||||||
|
/* setup data section */
|
||||||
|
struct rtattr *data = NLMSG_TAIL(&req.n);
|
||||||
|
addattr_l(&req.n, sizeof(req), IFLA_INFO_DATA, NULL, 0);
|
||||||
|
|
||||||
|
if (req_info->restart_ms > 0 || req_info->disable_autorestart)
|
||||||
|
addattr32(&req.n, 1024, IFLA_CAN_RESTART_MS,
|
||||||
|
req_info->restart_ms);
|
||||||
|
|
||||||
|
if (req_info->bitrate > 0) {
|
||||||
|
memset(&bt, 0, sizeof(bt));
|
||||||
|
bt.bitrate = req_info->bitrate;
|
||||||
|
addattr_l(&req.n, 1024, IFLA_CAN_BITTIMING,
|
||||||
|
&bt, sizeof(bt));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req_info->restart)
|
||||||
|
addattr32(&req.n, 1024, IFLA_CAN_RESTART, 1);
|
||||||
|
|
||||||
|
if (req_info->ctrlmode) {
|
||||||
|
memset(&cm, 0, sizeof(cm));
|
||||||
|
cm.mask = req_info->ctrlmode;
|
||||||
|
cm.flags = req_info->flags;
|
||||||
|
addattr_l(&req.n, 1024, IFLA_CAN_CTRLMODE, &cm, sizeof(cm));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mark end of data section */
|
||||||
|
data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data;
|
||||||
|
|
||||||
|
/* mark end of link info section */
|
||||||
|
linkinfo->rta_len =
|
||||||
|
(void *)NLMSG_TAIL(&req.n) - (void *)linkinfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
return send_mod_request(fd, &req.n);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_link(const char *name, struct req_info *req_info)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
fd = open_nl_sock();
|
||||||
|
if (fd < 0)
|
||||||
|
goto err_out;
|
||||||
|
|
||||||
|
err = if_down(fd, name);
|
||||||
|
if (err < 0)
|
||||||
|
goto close_out;
|
||||||
|
|
||||||
|
err = do_set_nl_link(fd, 0, name, req_info);
|
||||||
|
if (err < 0)
|
||||||
|
goto close_out;
|
||||||
|
|
||||||
|
err = if_up(fd, name);
|
||||||
|
if (err < 0)
|
||||||
|
goto close_out;
|
||||||
|
|
||||||
|
close_out:
|
||||||
|
close(fd);
|
||||||
|
err_out:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
int if_up(int fd, const char *name)
|
||||||
|
{
|
||||||
|
return do_set_nl_link(fd, IF_UP, name, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int if_down(int fd, const char *name)
|
||||||
|
{
|
||||||
|
return do_set_nl_link(fd, IF_DOWN, name, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int set_bitrate(const char *name, __u32 bitrate)
|
||||||
|
{
|
||||||
|
struct req_info req_info = {
|
||||||
|
.bitrate = bitrate,
|
||||||
|
};
|
||||||
|
|
||||||
|
return set_link(name, &req_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
int set_restart(const char *name)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
int err = -1;
|
||||||
|
int state;
|
||||||
|
|
||||||
|
state = get_state(name);
|
||||||
|
|
||||||
|
if (state != CAN_STATE_BUS_OFF) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Device %s is not in BUS_OFF,"
|
||||||
|
" no use to restart it\n",
|
||||||
|
name);
|
||||||
|
err = 0;
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct req_info req_info = {
|
||||||
|
.restart = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
fd = open_nl_sock();
|
||||||
|
if (fd < 0)
|
||||||
|
goto err_out;
|
||||||
|
|
||||||
|
err = do_set_nl_link(fd, 0, name, &req_info);
|
||||||
|
if (err < 0)
|
||||||
|
goto close_out;
|
||||||
|
|
||||||
|
close_out:
|
||||||
|
close(fd);
|
||||||
|
err_out:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
int set_restart_ms(const char *name, __u32 restart_ms)
|
||||||
|
{
|
||||||
|
struct req_info req_info = {
|
||||||
|
.restart_ms = restart_ms,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (restart_ms == 0)
|
||||||
|
req_info.disable_autorestart = 1;
|
||||||
|
|
||||||
|
return set_link(name, &req_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_state(const char *name)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
int state;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
fd = open_nl_sock();
|
||||||
|
if (fd < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
err = do_get_nl_link(fd, GET_STATE, name, &state);
|
||||||
|
if (err < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
__u32 get_restart_ms(const char *name)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
int err;
|
||||||
|
__u32 restart_ms;
|
||||||
|
|
||||||
|
fd = open_nl_sock();
|
||||||
|
if (fd < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
err = do_get_nl_link(fd, GET_RESTART_MS, name, &restart_ms);
|
||||||
|
if (err < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
return restart_ms;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_bittiming(const char *name, struct can_bittiming *bt)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
fd = open_nl_sock();
|
||||||
|
if (fd < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
err = do_get_nl_link(fd, GET_BITTIMING, name, bt);
|
||||||
|
if (err < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
TESTS = \
|
||||||
|
test
|
||||||
|
|
||||||
|
noinst_PROGRAMS = \
|
||||||
|
test
|
||||||
|
|
||||||
|
test_SOURCES = \
|
||||||
|
test.c
|
||||||
|
test_LDADD = \
|
||||||
|
$(top_builddir)/src/libsocketcan-nl.la
|
||||||
|
|
||||||
|
AM_CPPFLAGS = \
|
||||||
|
-I$(top_srcdir)/include \
|
||||||
|
-I$(top_builddir)/include
|
||||||
|
|
||||||
|
MAINTAINERCLEANFILES = \
|
||||||
|
GNUmakefile.in
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
printf("hallo\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue