Add a tool "vcan" to add/remove vcan interfaces.

pull/7/head
Urs Thuermann 2007-07-06 15:50:55 +00:00
parent 47ca8b7900
commit d90f47ef9c
1 changed files with 142 additions and 0 deletions

142
vcan.c 100644
View File

@ -0,0 +1,142 @@
/*
* a real quick'n'dirty hack to add/remove vcan interfaces.
* (also to have something to test the new RTNL API in vcan.)
* this will be added to ip(8) of the iproute package, making
* this hack obsolete.
*
* we don't check the return value of sendto() and don't wait for
* a reply using recvmsg(). We just hope everything works fine,
* otherwise use strace, or feel free to add the code before this
* whole thing is dumped to the bit bucket.
*
* urs
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <net/if.h>
#include <asm/types.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
//#include <linux/if_link.h>
#define IFLA_LINKINFO 18
enum
{
IFLA_INFO_UNSPEC,
IFLA_INFO_NAME,
IFLA_INFO_DATA,
IFLA_INFO_XSTATS,
__IFLA_INFO_MAX,
};
#define NLMSG_TAIL(nmsg) \
((struct rtattr *)(((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
int alen);
void usage()
{
fprintf(stderr, "Usage: vcan create\n"
" vcan delete iface\n");
exit(1);
}
int main(int argc, char **argv)
{
int s;
char *cmd, *dev;
struct {
struct nlmsghdr n;
struct ifinfomsg i;
char buf[1024];
} req;
struct sockaddr_nl nladdr;
struct rtattr *linkinfo;
int i;
#ifdef OBSOLETE
fprintf(stderr, "This program is a temporary hack and is now obsolete.\n"
"Please use ip(8) instead, i.e.\n"
" ip link add type vcan or\n"
" ip link delete iface\n");
exit(1);
#endif
if (argc < 2)
usage();
cmd = argv[1];
s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
memset(&req, 0, sizeof(req));
if (strcmp(cmd, "create") == 0) {
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
req.n.nlmsg_type = RTM_NEWLINK;
req.n.nlmsg_seq = 0;
req.i.ifi_family = AF_UNSPEC;
linkinfo = NLMSG_TAIL(&req.n);
addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
addattr_l(&req.n, sizeof(req), IFLA_INFO_NAME, "vcan", strlen("vcan"));
linkinfo->rta_len = (void*)NLMSG_TAIL(&req.n) - (void*)linkinfo;
} else if (strcmp(cmd, "delete") == 0) {
if (argc < 3)
usage();
dev = argv[2];
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
req.n.nlmsg_flags = NLM_F_REQUEST;
req.n.nlmsg_type = RTM_DELLINK;
req.i.ifi_family = AF_UNSPEC;
req.i.ifi_index = if_nametoindex(dev);
} else
usage();
memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK;
nladdr.nl_pid = 0;
nladdr.nl_groups = 0;
#if 1
sendto(s, &req, req.n.nlmsg_len, 0,
(struct sockaddr*)&nladdr, sizeof(nladdr));
#else
for (i = 0; i < req.n.nlmsg_len; i++) {
printf(" %02x", ((unsigned char*)&req)[i]);
if (i % 16 == 15)
putchar('\n');
}
putchar('\n');
#endif
close(s);
return 0;
}
int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
int alen)
{
int len = RTA_LENGTH(alen);
struct rtattr *rta;
if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
fprintf(stderr, "addattr_l ERROR: message exceeded bound of %d\n",
maxlen);
return -1;
}
rta = NLMSG_TAIL(n);
rta->rta_type = type;
rta->rta_len = len;
memcpy(RTA_DATA(rta), data, alen);
n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
return 0;
}