2 * a real quick'n'dirty hack to add/remove vcan interfaces.
3 * (also to have something to test the new RTNL API in vcan.)
4 * this will be added to ip(8) of the iproute package, making
7 * we don't check the return value of sendto() and don't wait for
8 * a reply using recvmsg(). We just hope everything works fine,
9 * otherwise use strace, or feel free to add the code before this
10 * whole thing is dumped to the bit bucket.
12 * Parts of this code were taken from the iproute source.
22 #include <sys/socket.h>
25 #include <asm/types.h>
26 #include <linux/netlink.h>
27 #include <linux/rtnetlink.h>
29 #include <linux/if_link.h>
32 #error Your kernel includes do not provide the needed netlink interface function.
33 #error This is a normal behaviour for Kernel versions below v2.6.24 .
34 #error You do not need this tool for Kernel versions below v2.6.24 anyway as
35 #error the number of vcan driver instances can be defined as a vcan.ko module
36 #error commandline parameter (default = 4) in older Kernels.
39 #define NLMSG_TAIL(nmsg) \
40 ((struct rtattr *)(((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
42 int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
47 fprintf(stderr, "Usage: vcan create\n"
48 " vcan delete iface\n");
52 int main(int argc, char **argv)
61 struct sockaddr_nl nladdr;
62 struct rtattr *linkinfo;
65 fprintf(stderr, "This program is a temporary hack and is now obsolete.\n"
66 "Please use ip(8) instead, i.e.\n"
67 " ip link add type vcan or\n"
68 " ip link delete iface\n");
75 s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
77 memset(&req, 0, sizeof(req));
79 if (strcmp(cmd, "create") == 0) {
80 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
81 req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
82 req.n.nlmsg_type = RTM_NEWLINK;
84 req.i.ifi_family = AF_UNSPEC;
86 linkinfo = NLMSG_TAIL(&req.n);
87 addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
88 addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, "vcan", strlen("vcan"));
89 linkinfo->rta_len = (void*)NLMSG_TAIL(&req.n) - (void*)linkinfo;
91 } else if (strcmp(cmd, "delete") == 0) {
95 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
96 req.n.nlmsg_flags = NLM_F_REQUEST;
97 req.n.nlmsg_type = RTM_DELLINK;
98 req.i.ifi_family = AF_UNSPEC;
99 req.i.ifi_index = if_nametoindex(dev);
103 memset(&nladdr, 0, sizeof(nladdr));
104 nladdr.nl_family = AF_NETLINK;
106 nladdr.nl_groups = 0;
108 sendto(s, &req, req.n.nlmsg_len, 0,
109 (struct sockaddr*)&nladdr, sizeof(nladdr));
114 for (i = 0; i < req.n.nlmsg_len; i++) {
115 printf(" %02x", ((unsigned char*)&req)[i]);
127 int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
130 int len = RTA_LENGTH(alen);
133 if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
134 fprintf(stderr, "addattr_l ERROR: message exceeded bound of %d\n",
139 rta->rta_type = type;
141 memcpy(RTA_DATA(rta), data, alen);
142 n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);