1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2008
4f08c3bdfSopenharmony_ci * Copyright (c) Linux Test Project, 2017-2019
5f08c3bdfSopenharmony_ci * Author: Rusty Russell <rusty@rustcorp.com.au>
6f08c3bdfSopenharmony_ci * Ported to LTP: subrata <subrata@linux.vnet.ibm.com>
7f08c3bdfSopenharmony_ci */
8f08c3bdfSopenharmony_ci
9f08c3bdfSopenharmony_ci/*
10f08c3bdfSopenharmony_ci * This program tests whether all the valid IFF flags are
11f08c3bdfSopenharmony_ci * returned properly by implementation of TUNGETFEATURES ioctl
12f08c3bdfSopenharmony_ci * on kernel 2.6.27
13f08c3bdfSopenharmony_ci */
14f08c3bdfSopenharmony_ci
15f08c3bdfSopenharmony_ci#include <sys/types.h>
16f08c3bdfSopenharmony_ci#include <sys/ioctl.h>
17f08c3bdfSopenharmony_ci#include <sys/stat.h>
18f08c3bdfSopenharmony_ci#include <fcntl.h>
19f08c3bdfSopenharmony_ci#include <errno.h>
20f08c3bdfSopenharmony_ci#include <linux/if_tun.h>
21f08c3bdfSopenharmony_ci#include "tst_test.h"
22f08c3bdfSopenharmony_ci
23f08c3bdfSopenharmony_ci#ifndef TUNGETFEATURES
24f08c3bdfSopenharmony_ci#define TUNGETFEATURES _IOR('T', 207, unsigned int)
25f08c3bdfSopenharmony_ci#endif
26f08c3bdfSopenharmony_ci
27f08c3bdfSopenharmony_ci#ifndef IFF_VNET_HDR
28f08c3bdfSopenharmony_ci#define IFF_VNET_HDR	0x4000
29f08c3bdfSopenharmony_ci#endif
30f08c3bdfSopenharmony_ci
31f08c3bdfSopenharmony_ci#ifndef IFF_MULTI_QUEUE
32f08c3bdfSopenharmony_ci#define IFF_MULTI_QUEUE	0x0100
33f08c3bdfSopenharmony_ci#endif
34f08c3bdfSopenharmony_ci
35f08c3bdfSopenharmony_ci#ifndef IFF_NAPI
36f08c3bdfSopenharmony_ci#define IFF_NAPI	0x0010
37f08c3bdfSopenharmony_ci#endif
38f08c3bdfSopenharmony_ci
39f08c3bdfSopenharmony_ci#ifndef IFF_NAPI_FRAGS
40f08c3bdfSopenharmony_ci#define IFF_NAPI_FRAGS	0x0020
41f08c3bdfSopenharmony_ci#endif
42f08c3bdfSopenharmony_ci
43f08c3bdfSopenharmony_ci#ifndef IFF_NO_CARRIER
44f08c3bdfSopenharmony_ci#define IFF_NO_CARRIER	0x0040
45f08c3bdfSopenharmony_ci#endif
46f08c3bdfSopenharmony_ci
47f08c3bdfSopenharmony_cistatic struct {
48f08c3bdfSopenharmony_ci	unsigned int flag;
49f08c3bdfSopenharmony_ci	const char *name;
50f08c3bdfSopenharmony_ci} known_flags[] = {
51f08c3bdfSopenharmony_ci	{IFF_TUN, "TUN"},
52f08c3bdfSopenharmony_ci	{IFF_TAP, "TAP"},
53f08c3bdfSopenharmony_ci	{IFF_NO_PI, "NO_PI"},
54f08c3bdfSopenharmony_ci	{IFF_ONE_QUEUE, "ONE_QUEUE"},
55f08c3bdfSopenharmony_ci	{IFF_VNET_HDR, "VNET_HDR"},
56f08c3bdfSopenharmony_ci	{IFF_MULTI_QUEUE, "MULTI_QUEUE"},
57f08c3bdfSopenharmony_ci	{IFF_NAPI, "IFF_NAPI"},
58f08c3bdfSopenharmony_ci	{IFF_NAPI_FRAGS, "IFF_NAPI_FRAGS"},
59f08c3bdfSopenharmony_ci	{IFF_NO_CARRIER, "IFF_NO_CARRIER"}
60f08c3bdfSopenharmony_ci};
61f08c3bdfSopenharmony_ci
62f08c3bdfSopenharmony_cistatic void verify_features(void)
63f08c3bdfSopenharmony_ci{
64f08c3bdfSopenharmony_ci	unsigned int features, i;
65f08c3bdfSopenharmony_ci
66f08c3bdfSopenharmony_ci	int netfd = open("/dev/net/tun", O_RDWR);
67f08c3bdfSopenharmony_ci
68f08c3bdfSopenharmony_ci	/* Android has tun at /dev/tun */
69f08c3bdfSopenharmony_ci	if (netfd == -1 && (errno == ENODEV || errno == ENOENT))
70f08c3bdfSopenharmony_ci		netfd = open("/dev/tun", O_RDWR);
71f08c3bdfSopenharmony_ci
72f08c3bdfSopenharmony_ci	if (netfd == -1) {
73f08c3bdfSopenharmony_ci		if (errno == ENODEV || errno == ENOENT)
74f08c3bdfSopenharmony_ci			tst_brk(TCONF, "TUN support is missing?");
75f08c3bdfSopenharmony_ci
76f08c3bdfSopenharmony_ci		tst_brk(TBROK | TERRNO, "opening /dev/net/tun failed");
77f08c3bdfSopenharmony_ci	}
78f08c3bdfSopenharmony_ci
79f08c3bdfSopenharmony_ci	SAFE_IOCTL(netfd, TUNGETFEATURES, &features);
80f08c3bdfSopenharmony_ci
81f08c3bdfSopenharmony_ci	tst_res(TINFO, "Available features are: %#x", features);
82f08c3bdfSopenharmony_ci	for (i = 0; i < ARRAY_SIZE(known_flags); i++) {
83f08c3bdfSopenharmony_ci		if (features & known_flags[i].flag) {
84f08c3bdfSopenharmony_ci			features &= ~known_flags[i].flag;
85f08c3bdfSopenharmony_ci			tst_res(TPASS, "%s %#x", known_flags[i].name,
86f08c3bdfSopenharmony_ci				 known_flags[i].flag);
87f08c3bdfSopenharmony_ci		}
88f08c3bdfSopenharmony_ci	}
89f08c3bdfSopenharmony_ci	if (features)
90f08c3bdfSopenharmony_ci		tst_res(TFAIL, "(UNKNOWN %#x)", features);
91f08c3bdfSopenharmony_ci
92f08c3bdfSopenharmony_ci	SAFE_CLOSE(netfd);
93f08c3bdfSopenharmony_ci}
94f08c3bdfSopenharmony_ci
95f08c3bdfSopenharmony_cistatic struct tst_test test = {
96f08c3bdfSopenharmony_ci	.test_all = verify_features,
97f08c3bdfSopenharmony_ci	.needs_root = 1,
98f08c3bdfSopenharmony_ci};
99