Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
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