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 #define USE_PACKED_STRUCT
49 int main(int argc, char **argv)
61 struct can_filter filter;
62 struct sockaddr_nl nladdr;
64 #ifdef USE_PACKED_STRUCT
68 } __attribute__((packed));
70 struct modattr modmsg;
72 static struct can_frame modframe;
73 char modbuf[CGW_MODATTR_LEN];
76 s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
78 memset(&req, 0, sizeof(req));
80 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtcanmsg));
81 req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
82 req.n.nlmsg_type = RTM_NEWROUTE;
85 req.r.can_family = AF_CAN;
86 req.r.src_ifindex = if_nametoindex("vcan2");
87 req.r.dst_ifindex = if_nametoindex("vcan3");
88 req.r.can_txflags = CAN_GW_TXFLAGS_ECHO;
90 /* add new attributes here */
92 filter.can_id = 0x400;
93 filter.can_mask = 0x700;
95 addattr_l(&req.n, sizeof(req), CGW_FILTER, &filter, sizeof(filter));
97 #ifdef USE_PACKED_STRUCT
99 if (sizeof(modmsg) != CGW_MODATTR_LEN) {
100 printf("Problem with packed msg. Use linear copy instead.\n");
104 modmsg.cf.can_id = 0x555;
105 modmsg.cf.can_dlc = 5;
106 *(unsigned long long *)modmsg.cf.data = 0x5555555555555555ULL;
108 modmsg.modtype = CGW_MOD_ID;
109 addattr_l(&req.n, sizeof(req), CGW_MOD_SET, &modmsg, CGW_MODATTR_LEN);
111 modmsg.modtype = CGW_MOD_DLC;
112 addattr_l(&req.n, sizeof(req), CGW_MOD_AND, &modmsg, CGW_MODATTR_LEN);
114 modmsg.modtype = CGW_MOD_DATA;
115 addattr_l(&req.n, sizeof(req), CGW_MOD_XOR, &modmsg, CGW_MODATTR_LEN);
119 modframe.can_id = 0x555;
120 modframe.can_dlc = 5;
121 *(unsigned long long *)modframe.data = 0x5555555555555555ULL;
123 memcpy(modbuf, &modframe, sizeof(struct can_frame));
125 modbuf[sizeof(struct can_frame)] = CGW_MOD_ID;
126 addattr_l(&req.n, sizeof(req), CGW_MOD_SET, modbuf, CGW_MODATTR_LEN);
128 modbuf[sizeof(struct can_frame)] = CGW_MOD_DLC;
129 addattr_l(&req.n, sizeof(req), CGW_MOD_AND, modbuf, CGW_MODATTR_LEN);
131 modbuf[sizeof(struct can_frame)] = CGW_MOD_DATA;
132 addattr_l(&req.n, sizeof(req), CGW_MOD_XOR, modbuf, CGW_MODATTR_LEN);
136 memset(&nladdr, 0, sizeof(nladdr));
137 nladdr.nl_family = AF_NETLINK;
139 nladdr.nl_groups = 0;
141 err = sendto(s, &req, req.n.nlmsg_len, 0,
142 (struct sockaddr*)&nladdr, sizeof(nladdr));
144 perror("netlink says ");