cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

tun.c (3440B)


      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