/* libsocketcan.c
*
* (C) 2009 Luotao Fu <l.fu@pengutronix.de>
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* @file
* @brief library code
*/
#ifdef HAVE_CONFIG_H
#include "libsocketcan_config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <net/if.h>
#include <linux/if_link.h>
#include <linux/rtnetlink.h>
#include <linux/netlink.h>
#include <libsocketcan.h>
/* Define DISABLE_ERROR_LOG to disable printing of error messages to stderr. */
#ifdef DISABLE_ERROR_LOG
#define perror(x)
#define fprintf(...)
#endif
#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)))
#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
#define GET_CTRLMODE 4
#define GET_CLOCK 5
#define GET_BITTIMING_CONST 6
#define GET_BERR_COUNTER 7
#define GET_XSTATS 8
#define GET_LINK_STATS 9
struct get_req {
struct nlmsghdr n;
struct ifinfomsg i;
};
struct set_req {
struct nlmsghdr n;
struct ifinfomsg i;
char buf[1024];
};
struct req_info {
__u8 restart;
__u8 disable_autorestart;
__u32 restart_ms;
struct can_ctrlmode *ctrlmode;
struct can_bittiming *bittiming;
};
/**
* @brief this method parse attributions of link info
*
* @param tb: point array of struct rtattr point
* @param max: index of the last element in array tb
* @param rtattr: point of link info data
* @param len: length of link info data
*/
static void
parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, int len)
{
memset(tb, 0, sizeof(*tb) * (max + 1));
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 %zu 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 %zu\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;
}
/**
* @ingroup intern
* @brief send_mod_request - send a linkinfo modification request
*
* @param fd decriptor to a priorly opened netlink socket
* @param n netlink message containing the request
*
* sends a request to setup the the linkinfo to netlink layer and awaits the
* status.
*
* @return 0 if success
* @return negativ if failed
*/
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;
}
iov.iov_base = buf;
while (1) {
iov.iov_len = sizeof(buf);
status = recvmsg(fd, &msg, 0);
for (h = (struct nlmsghdr *)buf; (size_t) status >= sizeof(*h);) {
int len = h->nlmsg_len;
int l = len - sizeof(*h);
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;
}
/**
* @ingroup intern
* @brief send_dump_request - send a dump linkinfo request
*
* @param fd decriptor to a priorly opened netlink socket
* @param name network interface name, null means all interfaces
* @param family rt_gen message family
* @param type netlink message header type
*
* @return 0 if success
* @return negativ if failed
*/
static int send_dump_request(int fd, const char *name, 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;
req.n.nlmsg_pid = 0;
req.n.nlmsg_seq = 0;
req.i.ifi_family = family;
/*
* If name is null, set flag to dump link information from all
* interfaces otherwise, just dump specified interface's link
* information.
*/
if (name == NULL) {
req.n.nlmsg_flags |= NLM_F_DUMP;
} else {
req.i.ifi_index = if_nametoindex(name);
if (req.i.ifi_index == 0) {
fprintf(stderr, "Cannot find device \"%s\"\n", name);
return -1;
}
}
return send(fd, (void *)&req, sizeof(req), 0);
}
/**
* @ingroup intern
* @brief open_nl_sock - open a netlink socket
*
* opens a netlink socket and returns the socket descriptor
*
* @return 0 if success
* @return negativ if failed
*/
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 %u\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;
}
/**
* @ingroup intern
* @brief do_get_nl_link - get linkinfo
*
* @param fd socket file descriptor to a priorly opened netlink socket
* @param acquire which parameter we want to get
* @param name name of the can device. This is the netdev name, as ifconfig -a
* shows in your system. usually it contains prefix "can" and the numer of the
* can
没有合适的资源?快使用搜索试试~ 我知道了~
canutils工具移植 Android 下 编译好的
需积分: 3 0 下载量 159 浏览量
2024-09-19
18:29:08
上传
评论
收藏 1.63MB GZ 举报
温馨提示
canutils工具移植 Android 下 编译好的
资源推荐
资源详情
资源评论
收起资源包目录
canutils工具移植 Android 下 编译好的 (149个子文件)
libsocketcan.so.2.3.1 18KB
libsocketcan.so.2.3.1 18KB
libsocketcan.so.2.3.1 18KB
libsocketcan.so.2 18KB
libsocketcan.so.2 18KB
libsocketcan.so.2 18KB
canconfig.8 2KB
canconfig.8 2KB
canecho.8 1KB
canecho.8 1KB
cansend.8 990B
cansend.8 990B
candump.8 988B
candump.8 988B
libsocketcan.a 12KB
libsocketcan.a 12KB
libsocketcan.a 12KB
configure.ac 2KB
configure.ac 2KB
GNUmakefile.am 806B
GNUmakefile.am 537B
GNUmakefile.am 353B
GNUmakefile.am 284B
GNUmakefile.am 175B
GNUmakefile.am 146B
GNUmakefile.am 135B
GNUmakefile.am 130B
GNUmakefile.am 61B
AUTHORS 213B
libsocketcan-0.0.12.tar.bz2 287KB
canutils-4.0.6.tar.bz2 242KB
libsocketcan.c 31KB
canconfig.c 14KB
cansequence.c 6KB
candump.c 5KB
cansend.c 4KB
canecho.c 3KB
canconfig 55KB
canconfig 55KB
candump 30KB
candump 30KB
canecho 26KB
canecho 26KB
cansend 26KB
cansend 26KB
cansequence 30KB
cansequence 30KB
ChangeLog 480B
compile 7KB
configure 450KB
configure 399KB
COPYING 18KB
depcomp 23KB
depcomp 18KB
GNUmakefile 29KB
GNUmakefile 23KB
GNUmakefile 21KB
GNUmakefile 20KB
GNUmakefile 18KB
GNUmakefile 16KB
GNUmakefile 14KB
GNUmakefile 13KB
GNUmakefile 11KB
config.guess 44KB
config.guess 43KB
libsocketcan_config.h 5KB
can_netlink.h 4KB
can_netlink.h 4KB
can_netlink.h 4KB
can_config.h 3KB
libsocketcan.h 2KB
libsocketcan.h 2KB
libsocketcan.h 2KB
GNUmakefile.in 28KB
GNUmakefile.in 22KB
GNUmakefile.in 20KB
GNUmakefile.in 19KB
GNUmakefile.in 17KB
GNUmakefile.in 15KB
GNUmakefile.in 13KB
GNUmakefile.in 12KB
GNUmakefile.in 10KB
libsocketcan_config.h.in 4KB
can_config.h.in 3KB
libsocketcan.pc.in 241B
canutils.pc.in 189B
INSTALL 9KB
INSTALL 9KB
INSTALL 9KB
install-sh 15KB
install-sh 13KB
libsocketcan.la 1KB
libsocketcan.la 1KB
libsocketcan.la 1KB
libsocketcan.la 1015B
libsocketcan.lai 1KB
libtool 336KB
libtool 253KB
LICENSE 26KB
LICENSE 26KB
共 149 条
- 1
- 2
资源评论
龙德施泰.冯.置
- 粉丝: 90
- 资源: 66
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功