0001
0002
0003 #define _GNU_SOURCE
0004
0005 #include <errno.h>
0006 #include <fcntl.h>
0007 #include <stdio.h>
0008 #include <stdlib.h>
0009 #include <string.h>
0010 #include <unistd.h>
0011 #include <linux/if.h>
0012 #include <linux/if_tun.h>
0013 #include <linux/netlink.h>
0014 #include <linux/rtnetlink.h>
0015 #include <sys/ioctl.h>
0016 #include <sys/socket.h>
0017
0018 #include "../kselftest_harness.h"
0019
0020 static int tun_attach(int fd, char *dev)
0021 {
0022 struct ifreq ifr;
0023
0024 memset(&ifr, 0, sizeof(ifr));
0025 strcpy(ifr.ifr_name, dev);
0026 ifr.ifr_flags = IFF_ATTACH_QUEUE;
0027
0028 return ioctl(fd, TUNSETQUEUE, (void *) &ifr);
0029 }
0030
0031 static int tun_detach(int fd, char *dev)
0032 {
0033 struct ifreq ifr;
0034
0035 memset(&ifr, 0, sizeof(ifr));
0036 strcpy(ifr.ifr_name, dev);
0037 ifr.ifr_flags = IFF_DETACH_QUEUE;
0038
0039 return ioctl(fd, TUNSETQUEUE, (void *) &ifr);
0040 }
0041
0042 static int tun_alloc(char *dev)
0043 {
0044 struct ifreq ifr;
0045 int fd, err;
0046
0047 fd = open("/dev/net/tun", O_RDWR);
0048 if (fd < 0) {
0049 fprintf(stderr, "can't open tun: %s\n", strerror(errno));
0050 return fd;
0051 }
0052
0053 memset(&ifr, 0, sizeof(ifr));
0054 strcpy(ifr.ifr_name, dev);
0055 ifr.ifr_flags = IFF_TAP | IFF_NAPI | IFF_MULTI_QUEUE;
0056
0057 err = ioctl(fd, TUNSETIFF, (void *) &ifr);
0058 if (err < 0) {
0059 fprintf(stderr, "can't TUNSETIFF: %s\n", strerror(errno));
0060 close(fd);
0061 return err;
0062 }
0063 strcpy(dev, ifr.ifr_name);
0064 return fd;
0065 }
0066
0067 static int tun_delete(char *dev)
0068 {
0069 struct {
0070 struct nlmsghdr nh;
0071 struct ifinfomsg ifm;
0072 unsigned char data[64];
0073 } req;
0074 struct rtattr *rta;
0075 int ret, rtnl;
0076
0077 rtnl = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
0078 if (rtnl < 0) {
0079 fprintf(stderr, "can't open rtnl: %s\n", strerror(errno));
0080 return 1;
0081 }
0082
0083 memset(&req, 0, sizeof(req));
0084 req.nh.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.ifm)));
0085 req.nh.nlmsg_flags = NLM_F_REQUEST;
0086 req.nh.nlmsg_type = RTM_DELLINK;
0087
0088 req.ifm.ifi_family = AF_UNSPEC;
0089
0090 rta = (struct rtattr *)(((char *)&req) + NLMSG_ALIGN(req.nh.nlmsg_len));
0091 rta->rta_type = IFLA_IFNAME;
0092 rta->rta_len = RTA_LENGTH(IFNAMSIZ);
0093 req.nh.nlmsg_len += rta->rta_len;
0094 memcpy(RTA_DATA(rta), dev, IFNAMSIZ);
0095
0096 ret = send(rtnl, &req, req.nh.nlmsg_len, 0);
0097 if (ret < 0)
0098 fprintf(stderr, "can't send: %s\n", strerror(errno));
0099 ret = (unsigned int)ret != req.nh.nlmsg_len;
0100
0101 close(rtnl);
0102 return ret;
0103 }
0104
0105 FIXTURE(tun)
0106 {
0107 char ifname[IFNAMSIZ];
0108 int fd, fd2;
0109 };
0110
0111 FIXTURE_SETUP(tun)
0112 {
0113 memset(self->ifname, 0, sizeof(self->ifname));
0114
0115 self->fd = tun_alloc(self->ifname);
0116 ASSERT_GE(self->fd, 0);
0117
0118 self->fd2 = tun_alloc(self->ifname);
0119 ASSERT_GE(self->fd2, 0);
0120 }
0121
0122 FIXTURE_TEARDOWN(tun)
0123 {
0124 if (self->fd >= 0)
0125 close(self->fd);
0126 if (self->fd2 >= 0)
0127 close(self->fd2);
0128 }
0129
0130 TEST_F(tun, delete_detach_close) {
0131 EXPECT_EQ(tun_delete(self->ifname), 0);
0132 EXPECT_EQ(tun_detach(self->fd, self->ifname), -1);
0133 EXPECT_EQ(errno, 22);
0134 }
0135
0136 TEST_F(tun, detach_delete_close) {
0137 EXPECT_EQ(tun_detach(self->fd, self->ifname), 0);
0138 EXPECT_EQ(tun_delete(self->ifname), 0);
0139 }
0140
0141 TEST_F(tun, detach_close_delete) {
0142 EXPECT_EQ(tun_detach(self->fd, self->ifname), 0);
0143 close(self->fd);
0144 self->fd = -1;
0145 EXPECT_EQ(tun_delete(self->ifname), 0);
0146 }
0147
0148 TEST_F(tun, reattach_delete_close) {
0149 EXPECT_EQ(tun_detach(self->fd, self->ifname), 0);
0150 EXPECT_EQ(tun_attach(self->fd, self->ifname), 0);
0151 EXPECT_EQ(tun_delete(self->ifname), 0);
0152 }
0153
0154 TEST_F(tun, reattach_close_delete) {
0155 EXPECT_EQ(tun_detach(self->fd, self->ifname), 0);
0156 EXPECT_EQ(tun_attach(self->fd, self->ifname), 0);
0157 close(self->fd);
0158 self->fd = -1;
0159 EXPECT_EQ(tun_delete(self->ifname), 0);
0160 }
0161
0162 TEST_HARNESS_MAIN