2 * A real quick'n'dirty hack to add a netlink CAN gateway entry.
4 * Parts of this code were taken from the iproute source and the original
5 * vcan.c from Urs Thuermann.
7 * Oliver Hartkopp 2010-02-18
15 #include <sys/socket.h>
18 #include <asm/types.h>
19 #include <linux/netlink.h>
20 #include <linux/rtnetlink.h>
21 #include <socketcan/can/gw.h>
23 #include <linux/if_link.h>
25 #define NLMSG_TAIL(nmsg) \
26 ((struct rtattr *)(((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
28 int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
31 int len = RTA_LENGTH(alen);
34 if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
35 fprintf(stderr, "addattr_l: message exceeded bound of %d\n",
42 memcpy(RTA_DATA(rta), data, alen);
43 n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
47 int main(int argc, char **argv)
59 static struct can_frame modframe;
60 struct can_filter filter;
61 struct sockaddr_nl nladdr;
62 char modbuf[CGW_MODATTR_LEN];
64 s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
66 memset(&req, 0, sizeof(req));
68 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtcanmsg));
69 req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
70 req.n.nlmsg_type = RTM_NEWROUTE;
73 req.r.can_family = AF_CAN;
74 req.r.src_ifindex = if_nametoindex("vcan2");
75 req.r.dst_ifindex = if_nametoindex("vcan3");
76 req.r.can_txflags = CAN_GW_TXFLAGS_LOOPBACK;
78 /* add new attributes here */
80 filter.can_id = 0x400;
81 filter.can_mask = 0x700;
83 addattr_l(&req.n, sizeof(req), CGW_FILTER, &filter, sizeof(filter));
84 modframe.can_id = 0x555;
86 *(unsigned long long *)modframe.data = 0x5555555555555555ULL;
88 modbuf[0] = CGW_MOD_ID;
89 memcpy(&modbuf[1], &modframe, sizeof(struct can_frame));
91 addattr_l(&req.n, sizeof(req), CGW_MOD_SET, modbuf, CGW_MODATTR_LEN);
93 modbuf[0] = CGW_MOD_DLC;
94 memcpy(&modbuf[1], &modframe, sizeof(struct can_frame));
96 addattr_l(&req.n, sizeof(req), CGW_MOD_AND, modbuf, CGW_MODATTR_LEN);
98 modbuf[0] = CGW_MOD_DATA;
99 memcpy(&modbuf[1], &modframe, sizeof(struct can_frame));
101 addattr_l(&req.n, sizeof(req), CGW_MOD_XOR, modbuf, CGW_MODATTR_LEN);
104 memset(&nladdr, 0, sizeof(nladdr));
105 nladdr.nl_family = AF_NETLINK;
107 nladdr.nl_groups = 0;
109 err = sendto(s, &req, req.n.nlmsg_len, 0,
110 (struct sockaddr*)&nladdr, sizeof(nladdr));
112 perror("netlink says ");