Linux Audio

Check our new training course

Loading...
v6.8
  1// SPDX-License-Identifier: GPL-2.0
  2
  3#define _GNU_SOURCE
  4
  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>
 17
 18#include "../kselftest_harness.h"
 19
 20static int tun_attach(int fd, char *dev)
 21{
 22	struct ifreq ifr;
 23
 24	memset(&ifr, 0, sizeof(ifr));
 25	strcpy(ifr.ifr_name, dev);
 26	ifr.ifr_flags = IFF_ATTACH_QUEUE;
 27
 28	return ioctl(fd, TUNSETQUEUE, (void *) &ifr);
 29}
 30
 31static int tun_detach(int fd, char *dev)
 32{
 33	struct ifreq ifr;
 34
 35	memset(&ifr, 0, sizeof(ifr));
 36	strcpy(ifr.ifr_name, dev);
 37	ifr.ifr_flags = IFF_DETACH_QUEUE;
 38
 39	return ioctl(fd, TUNSETQUEUE, (void *) &ifr);
 40}
 41
 42static int tun_alloc(char *dev)
 43{
 44	struct ifreq ifr;
 45	int fd, err;
 46
 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;
 51	}
 52
 53	memset(&ifr, 0, sizeof(ifr));
 54	strcpy(ifr.ifr_name, dev);
 55	ifr.ifr_flags = IFF_TAP | IFF_NAPI | IFF_MULTI_QUEUE;
 56
 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;
 62	}
 63	strcpy(dev, ifr.ifr_name);
 64	return fd;
 65}
 66
 67static int tun_delete(char *dev)
 68{
 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;
 76
 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;
 81	}
 82
 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;
 87
 88	req.ifm.ifi_family = AF_UNSPEC;
 89
 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);
 95
 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;
100
101	close(rtnl);
102	return ret;
103}
104
105FIXTURE(tun)
106{
107	char ifname[IFNAMSIZ];
108	int fd, fd2;
109};
110
111FIXTURE_SETUP(tun)
112{
113	memset(self->ifname, 0, sizeof(self->ifname));
114
115	self->fd = tun_alloc(self->ifname);
116	ASSERT_GE(self->fd, 0);
117
118	self->fd2 = tun_alloc(self->ifname);
119	ASSERT_GE(self->fd2, 0);
120}
121
122FIXTURE_TEARDOWN(tun)
123{
124	if (self->fd >= 0)
125		close(self->fd);
126	if (self->fd2 >= 0)
127		close(self->fd2);
128}
129
130TEST_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);
134}
135
136TEST_F(tun, detach_delete_close) {
137	EXPECT_EQ(tun_detach(self->fd, self->ifname), 0);
138	EXPECT_EQ(tun_delete(self->ifname), 0);
139}
140
141TEST_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);
146}
147
148TEST_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);
152}
153
154TEST_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);
160}
161
162TEST_HARNESS_MAIN
v6.9.4
  1// SPDX-License-Identifier: GPL-2.0
  2
  3#define _GNU_SOURCE
  4
  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>
 17
 18#include "../kselftest_harness.h"
 19
 20static int tun_attach(int fd, char *dev)
 21{
 22	struct ifreq ifr;
 23
 24	memset(&ifr, 0, sizeof(ifr));
 25	strcpy(ifr.ifr_name, dev);
 26	ifr.ifr_flags = IFF_ATTACH_QUEUE;
 27
 28	return ioctl(fd, TUNSETQUEUE, (void *) &ifr);
 29}
 30
 31static int tun_detach(int fd, char *dev)
 32{
 33	struct ifreq ifr;
 34
 35	memset(&ifr, 0, sizeof(ifr));
 36	strcpy(ifr.ifr_name, dev);
 37	ifr.ifr_flags = IFF_DETACH_QUEUE;
 38
 39	return ioctl(fd, TUNSETQUEUE, (void *) &ifr);
 40}
 41
 42static int tun_alloc(char *dev)
 43{
 44	struct ifreq ifr;
 45	int fd, err;
 46
 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;
 51	}
 52
 53	memset(&ifr, 0, sizeof(ifr));
 54	strcpy(ifr.ifr_name, dev);
 55	ifr.ifr_flags = IFF_TAP | IFF_NAPI | IFF_MULTI_QUEUE;
 56
 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;
 62	}
 63	strcpy(dev, ifr.ifr_name);
 64	return fd;
 65}
 66
 67static int tun_delete(char *dev)
 68{
 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;
 76
 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;
 81	}
 82
 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;
 87
 88	req.ifm.ifi_family = AF_UNSPEC;
 89
 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);
 95
 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;
100
101	close(rtnl);
102	return ret;
103}
104
105FIXTURE(tun)
106{
107	char ifname[IFNAMSIZ];
108	int fd, fd2;
109};
110
111FIXTURE_SETUP(tun)
112{
113	memset(self->ifname, 0, sizeof(self->ifname));
114
115	self->fd = tun_alloc(self->ifname);
116	ASSERT_GE(self->fd, 0);
117
118	self->fd2 = tun_alloc(self->ifname);
119	ASSERT_GE(self->fd2, 0);
120}
121
122FIXTURE_TEARDOWN(tun)
123{
124	if (self->fd >= 0)
125		close(self->fd);
126	if (self->fd2 >= 0)
127		close(self->fd2);
128}
129
130TEST_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);
134}
135
136TEST_F(tun, detach_delete_close) {
137	EXPECT_EQ(tun_detach(self->fd, self->ifname), 0);
138	EXPECT_EQ(tun_delete(self->ifname), 0);
139}
140
141TEST_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);
146}
147
148TEST_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);
152}
153
154TEST_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);
160}
161
162TEST_HARNESS_MAIN