]> rtime.felk.cvut.cz Git - sojka/can-utils.git/blob - vcan.c
Add vcan config tool to Makefile.
[sojka/can-utils.git] / vcan.c
1 /*
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
5  * this hack obsolete.
6  * 
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.
11  *
12  * Parts of this code were taken from the iproute source.
13  *
14  * urs
15  */
16
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <unistd.h>
22 #include <sys/socket.h>
23 #include <net/if.h>
24
25 #include <asm/types.h>
26 #include <linux/netlink.h>
27 #include <linux/rtnetlink.h>
28
29 //#include <linux/if_link.h>
30
31 #define IFLA_LINKINFO 18
32
33 enum
34 {
35     IFLA_INFO_UNSPEC,
36     IFLA_INFO_NAME,
37     IFLA_INFO_DATA,
38     IFLA_INFO_XSTATS,
39     __IFLA_INFO_MAX,
40 };
41
42 #define NLMSG_TAIL(nmsg) \
43         ((struct rtattr *)(((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
44
45 int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
46               int alen);
47
48 void usage()
49 {
50     fprintf(stderr, "Usage: vcan create\n"
51                     "       vcan delete iface\n");
52     exit(1);
53 }
54
55 int main(int argc, char **argv)
56 {
57     int s;
58     char *cmd, *dev;
59     struct {
60         struct nlmsghdr  n;
61         struct ifinfomsg i;
62         char             buf[1024];
63     } req;
64     struct sockaddr_nl nladdr;
65     struct rtattr *linkinfo;
66     int i;
67
68 #ifdef OBSOLETE
69     fprintf(stderr, "This program is a temporary hack and is now obsolete.\n"
70             "Please use ip(8) instead, i.e.\n"
71             "    ip link add type vcan       or\n"
72             "    ip link delete iface\n");
73     exit(1);
74 #endif
75     if (argc < 2)
76         usage();
77     cmd = argv[1];
78
79     s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
80
81     memset(&req, 0, sizeof(req));
82
83     if (strcmp(cmd, "create") == 0) {
84         req.n.nlmsg_len   = NLMSG_LENGTH(sizeof(struct ifinfomsg));
85         req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
86         req.n.nlmsg_type  = RTM_NEWLINK;
87         req.n.nlmsg_seq   = 0;
88         req.i.ifi_family  = AF_UNSPEC;
89
90         linkinfo = NLMSG_TAIL(&req.n);
91         addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
92         addattr_l(&req.n, sizeof(req), IFLA_INFO_NAME, "vcan", strlen("vcan"));
93         linkinfo->rta_len = (void*)NLMSG_TAIL(&req.n) - (void*)linkinfo;
94
95     } else if (strcmp(cmd, "delete") == 0) {
96         if (argc < 3)
97             usage();
98         dev = argv[2];
99         req.n.nlmsg_len   = NLMSG_LENGTH(sizeof(struct ifinfomsg));
100         req.n.nlmsg_flags = NLM_F_REQUEST;
101         req.n.nlmsg_type  = RTM_DELLINK;
102         req.i.ifi_family  = AF_UNSPEC;
103         req.i.ifi_index   = if_nametoindex(dev);
104     } else
105         usage();
106
107     memset(&nladdr, 0, sizeof(nladdr));
108     nladdr.nl_family = AF_NETLINK;
109     nladdr.nl_pid    = 0;
110     nladdr.nl_groups = 0;
111 #if 1
112     sendto(s, &req, req.n.nlmsg_len, 0,
113            (struct sockaddr*)&nladdr, sizeof(nladdr));
114 #else
115     for (i = 0; i < req.n.nlmsg_len; i++) {
116         printf(" %02x", ((unsigned char*)&req)[i]);
117         if (i % 16 == 15)
118             putchar('\n');
119     }
120     putchar('\n');
121 #endif
122     close(s);
123
124     return 0;
125 }
126
127 int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
128               int alen)
129 {
130     int len = RTA_LENGTH(alen);
131     struct rtattr *rta;
132
133     if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
134         fprintf(stderr, "addattr_l ERROR: message exceeded bound of %d\n",
135                 maxlen);
136         return -1;
137     }
138     rta = NLMSG_TAIL(n);
139     rta->rta_type = type;
140     rta->rta_len = len;
141     memcpy(RTA_DATA(rta), data, alen);
142     n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
143     return 0;
144 }