]> rtime.felk.cvut.cz Git - socketcan-devel.git/blob - can-utils/vcan.c
disable default receive filter on the write-only bridge socket.
[socketcan-devel.git] / can-utils / 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 #ifndef IFLA_LINKINFO
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.
37 #endif
38
39 #define NLMSG_TAIL(nmsg)                                                \
40         ((struct rtattr *)(((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
41
42 int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
43               int alen);
44
45 void usage()
46 {
47         fprintf(stderr, "Usage: vcan create\n"
48                 "       vcan delete iface\n");
49         exit(1);
50 }
51
52 int main(int argc, char **argv)
53 {
54         int s;
55         char *cmd, *dev;
56         struct {
57                 struct nlmsghdr  n;
58                 struct ifinfomsg i;
59                 char             buf[1024];
60         } req;
61         struct sockaddr_nl nladdr;
62         struct rtattr *linkinfo;
63
64 #ifdef OBSOLETE
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");
69         exit(1);
70 #endif
71         if (argc < 2)
72                 usage();
73         cmd = argv[1];
74
75         s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
76
77         memset(&req, 0, sizeof(req));
78
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;
83                 req.n.nlmsg_seq   = 0;
84                 req.i.ifi_family  = AF_UNSPEC;
85
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;
90
91         } else if (strcmp(cmd, "delete") == 0) {
92                 if (argc < 3)
93                         usage();
94                 dev = argv[2];
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);
100         } else
101                 usage();
102
103         memset(&nladdr, 0, sizeof(nladdr));
104         nladdr.nl_family = AF_NETLINK;
105         nladdr.nl_pid    = 0;
106         nladdr.nl_groups = 0;
107 #if 1
108         sendto(s, &req, req.n.nlmsg_len, 0,
109                (struct sockaddr*)&nladdr, sizeof(nladdr));
110 #else
111         {
112                 int i;
113
114                 for (i = 0; i < req.n.nlmsg_len; i++) {
115                         printf(" %02x", ((unsigned char*)&req)[i]);
116                         if (i % 16 == 15)
117                                 putchar('\n');
118                 }
119                 putchar('\n');
120         }
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 }