Added tiny tool to measure CAN busload.
[profile/ivi/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 #if 0
32 #define IFLA_LINKINFO 18
33
34 enum
35 {
36     IFLA_INFO_UNSPEC,
37     IFLA_INFO_NAME,
38     IFLA_INFO_DATA,
39     IFLA_INFO_XSTATS,
40     __IFLA_INFO_MAX,
41 };
42 #endif
43
44 #define NLMSG_TAIL(nmsg) \
45         ((struct rtattr *)(((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
46
47 int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
48               int alen);
49
50 void usage()
51 {
52     fprintf(stderr, "Usage: vcan create\n"
53                     "       vcan delete iface\n");
54     exit(1);
55 }
56
57 int main(int argc, char **argv)
58 {
59     int s;
60     char *cmd, *dev;
61     struct {
62         struct nlmsghdr  n;
63         struct ifinfomsg i;
64         char             buf[1024];
65     } req;
66     struct sockaddr_nl nladdr;
67     struct rtattr *linkinfo;
68
69 #ifdef OBSOLETE
70     fprintf(stderr, "This program is a temporary hack and is now obsolete.\n"
71             "Please use ip(8) instead, i.e.\n"
72             "    ip link add type vcan       or\n"
73             "    ip link delete iface\n");
74     exit(1);
75 #endif
76     if (argc < 2)
77         usage();
78     cmd = argv[1];
79
80     s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
81
82     memset(&req, 0, sizeof(req));
83
84     if (strcmp(cmd, "create") == 0) {
85         req.n.nlmsg_len   = NLMSG_LENGTH(sizeof(struct ifinfomsg));
86         req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
87         req.n.nlmsg_type  = RTM_NEWLINK;
88         req.n.nlmsg_seq   = 0;
89         req.i.ifi_family  = AF_UNSPEC;
90
91         linkinfo = NLMSG_TAIL(&req.n);
92         addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
93         addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, "vcan", strlen("vcan"));
94         linkinfo->rta_len = (void*)NLMSG_TAIL(&req.n) - (void*)linkinfo;
95
96     } else if (strcmp(cmd, "delete") == 0) {
97         if (argc < 3)
98             usage();
99         dev = argv[2];
100         req.n.nlmsg_len   = NLMSG_LENGTH(sizeof(struct ifinfomsg));
101         req.n.nlmsg_flags = NLM_F_REQUEST;
102         req.n.nlmsg_type  = RTM_DELLINK;
103         req.i.ifi_family  = AF_UNSPEC;
104         req.i.ifi_index   = if_nametoindex(dev);
105     } else
106         usage();
107
108     memset(&nladdr, 0, sizeof(nladdr));
109     nladdr.nl_family = AF_NETLINK;
110     nladdr.nl_pid    = 0;
111     nladdr.nl_groups = 0;
112 #if 1
113     sendto(s, &req, req.n.nlmsg_len, 0,
114            (struct sockaddr*)&nladdr, sizeof(nladdr));
115 #else
116     {
117         int i;
118
119         for (i = 0; i < req.n.nlmsg_len; i++) {
120             printf(" %02x", ((unsigned char*)&req)[i]);
121             if (i % 16 == 15)
122                 putchar('\n');
123         }
124         putchar('\n');
125     }
126 #endif
127     close(s);
128
129     return 0;
130 }
131
132 int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
133               int alen)
134 {
135     int len = RTA_LENGTH(alen);
136     struct rtattr *rta;
137
138     if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
139         fprintf(stderr, "addattr_l ERROR: message exceeded bound of %d\n",
140                 maxlen);
141         return -1;
142     }
143     rta = NLMSG_TAIL(n);
144     rta->rta_type = type;
145     rta->rta_len = len;
146     memcpy(RTA_DATA(rta), data, alen);
147     n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
148     return 0;
149 }