From d90f47ef9c76fd76a74d38558a106a2ea202060f Mon Sep 17 00:00:00 2001 From: Urs Thuermann Date: Fri, 6 Jul 2007 15:50:55 +0000 Subject: [PATCH] Add a tool "vcan" to add/remove vcan interfaces. --- vcan.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 vcan.c diff --git a/vcan.c b/vcan.c new file mode 100644 index 0000000..1539458 --- /dev/null +++ b/vcan.c @@ -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 +#include +#include +#include +#include +#include + +#include +#include +#include + +//#include + +#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; +} -- 2.39.2