criu/test/zdtm/static/tun.c
Adrian Reber 93dd984ca0 Run 'make indent' on all C files
Acked-by: Mike Rapoport <rppt@linux.ibm.com>
Signed-off-by: Adrian Reber <areber@redhat.com>
2021-09-03 10:31:00 -07:00

240 lines
4.7 KiB
C

#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <sched.h>
#include "zdtmtst.h"
const char *test_doc = "Test TUN/TAP devices\n";
const char *test_author = "Pavel Emelianov <xemul@parallels.com>";
#define TUN_DEVICE "/dev/net/tun"
#ifndef IFF_MULTI_QUEUE
#define IFF_MULTI_QUEUE 0x0100
#define IFF_ATTACH_QUEUE 0x0200
#define IFF_DETACH_QUEUE 0x0400
#define IFF_PERSIST 0x0800
#endif
#ifndef TUNSETQUEUE
#define TUNSETQUEUE _IOW('T', 217, int)
#endif
static int any_fail = 0;
static int __open_tun(void)
{
int fd;
fd = open(TUN_DEVICE, O_RDWR);
if (fd < 0)
pr_perror("Can't open tun file %s", TUN_DEVICE);
return fd;
}
static int set_tun_queue(int fd, const char *name, unsigned flags)
{
struct ifreq ifr = {
.ifr_flags = flags,
};
if (ioctl(fd, TUNSETQUEUE, &ifr) < 0) {
pr_perror("Can't set queue on %s", name);
return -1;
}
return 0;
}
static int __attach_tun(int fd, const char *name, unsigned flags)
{
struct ifreq ifr = {
.ifr_flags = flags,
};
strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name) - 1);
if (ioctl(fd, TUNSETIFF, &ifr) < 0) {
if (!(flags & IFF_TUN_EXCL))
pr_perror("Can't attach iff %s", name);
return -1;
}
return fd;
}
static int open_tun(const char *name, unsigned flags)
{
int fd;
fd = __open_tun();
if (fd < 0)
return -1;
return __attach_tun(fd, name, flags);
}
static void check_tun(int fd, const char *name, unsigned flags)
{
struct ifreq ifr = {};
if (ioctl(fd, TUNGETIFF, &ifr) > 0) {
any_fail = 1;
fail("Attached tun %s file lost device", name);
}
if (strcmp(ifr.ifr_name, name)) {
any_fail = 1;
fail("Attached tun %s wrong device", name);
}
if ((ifr.ifr_flags & flags) != flags) {
any_fail = 1;
fail("Attached tun %s wrong device type", name);
}
}
static int dev_get_hwaddr(int fd, const char *name, char *a)
{
struct ifreq ifr = {};
if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
pr_perror("Can't get hwaddr on %s", name);
return -1;
}
memcpy(a, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
return 0;
}
int main(int argc, char **argv)
{
int fds[5], ret;
char addr[ETH_ALEN], a2[ETH_ALEN];
test_init(argc, argv);
#ifdef TUN_NS
if (unshare(CLONE_NEWNET)) {
pr_perror("unshare");
return 1;
}
system("ip link set up dev lo");
#endif
/* fd[0] -- opened file */
fds[0] = __open_tun();
if (fds[0] < 0) {
pr_perror("No file 0");
return 1;
}
/* fd[1] -- opened file with tun device */
fds[1] = open_tun("tunx0", IFF_TUN);
if (fds[1] < 0) {
pr_perror("No file 1");
return 1;
}
/* fd[2] and [3] -- two-queued device, with 3 detached */
fds[2] = open_tun("tunx1", IFF_TUN | IFF_MULTI_QUEUE);
if (fds[2] < 0) {
pr_perror("No file 2");
return 1;
}
fds[3] = open_tun("tunx1", IFF_TUN | IFF_MULTI_QUEUE);
if (fds[3] < 0) {
pr_perror("No file 3");
return 1;
}
ret = set_tun_queue(fds[3], "tunx1", IFF_DETACH_QUEUE);
if (ret < 0)
return 1;
/* special case -- persistent device */
ret = open_tun("tunx2", IFF_TUN);
if (ret < 0) {
pr_perror("No persistent device");
return 1;
}
if (ioctl(ret, TUNSETPERSIST, 1) < 0) {
pr_perror("Can't make persistent");
return 1;
}
/* and one tap in fd[4] */
fds[4] = open_tun("tapx0", IFF_TAP);
if (fds[4] < 0) {
pr_perror("No tap");
return 1;
}
if (dev_get_hwaddr(fds[4], "tapx0", addr) < 0) {
pr_perror("No hwaddr for tap?");
return 1;
}
close(ret);
test_daemon();
test_waitsig();
/* check fds[0] is not attached to device */
ret = __attach_tun(fds[0], "tunx3", IFF_TUN);
if (ret < 0) {
any_fail = 1;
fail("Opened tun file broken");
}
/* check that fds[1] has device */
check_tun(fds[1], "tunx0", IFF_TUN);
/* check that fds[2] and [3] are at MQ device with */
check_tun(fds[2], "tunx1", IFF_TUN | IFF_MULTI_QUEUE);
check_tun(fds[3], "tunx1", IFF_TUN | IFF_MULTI_QUEUE);
ret = set_tun_queue(fds[2], "tunx1", IFF_DETACH_QUEUE);
if (ret < 0) {
any_fail = 1;
fail("Queue not attached");
}
ret = set_tun_queue(fds[3], "tunx1", IFF_ATTACH_QUEUE);
if (ret < 0) {
any_fail = 1;
fail("Queue not detached");
}
/* check persistent device */
ret = open_tun("tunx2", IFF_TUN | IFF_TUN_EXCL);
if (ret >= 0) {
any_fail = 1;
fail("Persistent device lost");
} else {
ret = open_tun("tunx2", IFF_TUN);
if (ret < 0)
pr_perror("Can't attach tun2");
else
ioctl(ret, TUNSETPERSIST, 0);
}
check_tun(fds[4], "tapx0", IFF_TAP);
if (dev_get_hwaddr(fds[4], "tapx0", a2) < 0) {
pr_perror("No hwaddr for tap? (2)");
any_fail = 1;
} else if (memcmp(addr, a2, sizeof(addr))) {
fail("Address mismatch on tap %x:%x -> %x:%x", (int)addr[0], (int)addr[1], (int)a2[0], (int)a2[1]);
any_fail = 1;
}
if (!any_fail)
pass();
return 0;
}