drm/atomic-helper: document drm_atomic_helper_check() restrictions
[drm/drm-misc.git] / tools / testing / selftests / net / tun.c
blobfa83918b62d1be1c93adcd6c2f07654893cf97f8
1 // SPDX-License-Identifier: GPL-2.0
3 #define _GNU_SOURCE
5 #include <errno.h>
6 #include <fcntl.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include <linux/if.h>
12 #include <linux/if_tun.h>
13 #include <linux/netlink.h>
14 #include <linux/rtnetlink.h>
15 #include <sys/ioctl.h>
16 #include <sys/socket.h>
18 #include "../kselftest_harness.h"
20 static int tun_attach(int fd, char *dev)
22 struct ifreq ifr;
24 memset(&ifr, 0, sizeof(ifr));
25 strcpy(ifr.ifr_name, dev);
26 ifr.ifr_flags = IFF_ATTACH_QUEUE;
28 return ioctl(fd, TUNSETQUEUE, (void *) &ifr);
31 static int tun_detach(int fd, char *dev)
33 struct ifreq ifr;
35 memset(&ifr, 0, sizeof(ifr));
36 strcpy(ifr.ifr_name, dev);
37 ifr.ifr_flags = IFF_DETACH_QUEUE;
39 return ioctl(fd, TUNSETQUEUE, (void *) &ifr);
42 static int tun_alloc(char *dev)
44 struct ifreq ifr;
45 int fd, err;
47 fd = open("/dev/net/tun", O_RDWR);
48 if (fd < 0) {
49 fprintf(stderr, "can't open tun: %s\n", strerror(errno));
50 return fd;
53 memset(&ifr, 0, sizeof(ifr));
54 strcpy(ifr.ifr_name, dev);
55 ifr.ifr_flags = IFF_TAP | IFF_NAPI | IFF_MULTI_QUEUE;
57 err = ioctl(fd, TUNSETIFF, (void *) &ifr);
58 if (err < 0) {
59 fprintf(stderr, "can't TUNSETIFF: %s\n", strerror(errno));
60 close(fd);
61 return err;
63 strcpy(dev, ifr.ifr_name);
64 return fd;
67 static int tun_delete(char *dev)
69 struct {
70 struct nlmsghdr nh;
71 struct ifinfomsg ifm;
72 unsigned char data[64];
73 } req;
74 struct rtattr *rta;
75 int ret, rtnl;
77 rtnl = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
78 if (rtnl < 0) {
79 fprintf(stderr, "can't open rtnl: %s\n", strerror(errno));
80 return 1;
83 memset(&req, 0, sizeof(req));
84 req.nh.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.ifm)));
85 req.nh.nlmsg_flags = NLM_F_REQUEST;
86 req.nh.nlmsg_type = RTM_DELLINK;
88 req.ifm.ifi_family = AF_UNSPEC;
90 rta = (struct rtattr *)(((char *)&req) + NLMSG_ALIGN(req.nh.nlmsg_len));
91 rta->rta_type = IFLA_IFNAME;
92 rta->rta_len = RTA_LENGTH(IFNAMSIZ);
93 req.nh.nlmsg_len += rta->rta_len;
94 memcpy(RTA_DATA(rta), dev, IFNAMSIZ);
96 ret = send(rtnl, &req, req.nh.nlmsg_len, 0);
97 if (ret < 0)
98 fprintf(stderr, "can't send: %s\n", strerror(errno));
99 ret = (unsigned int)ret != req.nh.nlmsg_len;
101 close(rtnl);
102 return ret;
105 FIXTURE(tun)
107 char ifname[IFNAMSIZ];
108 int fd, fd2;
111 FIXTURE_SETUP(tun)
113 memset(self->ifname, 0, sizeof(self->ifname));
115 self->fd = tun_alloc(self->ifname);
116 ASSERT_GE(self->fd, 0);
118 self->fd2 = tun_alloc(self->ifname);
119 ASSERT_GE(self->fd2, 0);
122 FIXTURE_TEARDOWN(tun)
124 if (self->fd >= 0)
125 close(self->fd);
126 if (self->fd2 >= 0)
127 close(self->fd2);
130 TEST_F(tun, delete_detach_close) {
131 EXPECT_EQ(tun_delete(self->ifname), 0);
132 EXPECT_EQ(tun_detach(self->fd, self->ifname), -1);
133 EXPECT_EQ(errno, 22);
136 TEST_F(tun, detach_delete_close) {
137 EXPECT_EQ(tun_detach(self->fd, self->ifname), 0);
138 EXPECT_EQ(tun_delete(self->ifname), 0);
141 TEST_F(tun, detach_close_delete) {
142 EXPECT_EQ(tun_detach(self->fd, self->ifname), 0);
143 close(self->fd);
144 self->fd = -1;
145 EXPECT_EQ(tun_delete(self->ifname), 0);
148 TEST_F(tun, reattach_delete_close) {
149 EXPECT_EQ(tun_detach(self->fd, self->ifname), 0);
150 EXPECT_EQ(tun_attach(self->fd, self->ifname), 0);
151 EXPECT_EQ(tun_delete(self->ifname), 0);
154 TEST_F(tun, reattach_close_delete) {
155 EXPECT_EQ(tun_detach(self->fd, self->ifname), 0);
156 EXPECT_EQ(tun_attach(self->fd, self->ifname), 0);
157 close(self->fd);
158 self->fd = -1;
159 EXPECT_EQ(tun_delete(self->ifname), 0);
162 TEST_HARNESS_MAIN