brintos

brintos / linux-shallow public Read only

0
0
Text · 3.4 KiB · fa83918 Raw
163 lines · c
1// SPDX-License-Identifier: GPL-2.02 3#define _GNU_SOURCE4 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_MAIN163