1 /*
2  * Copyright (c) International Business Machines  Corp., 2008
3  * Copyright (c) Linux Test Project, 2017
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 /*
20  * File:        ioctl03.c
21  *
22  * Description: This program tests whether all the valid IFF flags are
23  *              returned properly by implementation of TUNGETFEATURES ioctl
24  *              on kernel 2.6.27
25  *
26  * Test Name:   ioctl03
27  *
28  * Author:      Rusty Russell <rusty@rustcorp.com.au>
29  *
30  * history:     created - nov 28 2008 - rusty russell <rusty@rustcorp.com.au>
31  *              ported to ltp
32  *                      - nov 28 2008 - subrata <subrata@linux.vnet.ibm.com>
33  */
34 
35 #include <sys/types.h>
36 #include <sys/ioctl.h>
37 #include <sys/stat.h>
38 #include <fcntl.h>
39 #include <errno.h>
40 #include <linux/if_tun.h>
41 #include "tst_test.h"
42 
43 #ifndef TUNGETFEATURES
44 #define TUNGETFEATURES _IOR('T', 207, unsigned int)
45 #endif
46 
47 #ifndef IFF_VNET_HDR
48 #define IFF_VNET_HDR	0x4000
49 #endif
50 
51 #ifndef IFF_MULTI_QUEUE
52 #define IFF_MULTI_QUEUE	0x0100
53 #endif
54 
55 #ifndef IFF_NAPI
56 #define IFF_NAPI	0x0010
57 #endif
58 
59 #ifndef IFF_NAPI_FRAGS
60 #define IFF_NAPI_FRAGS	0x0020
61 #endif
62 
63 static struct {
64 	unsigned int flag;
65 	const char *name;
66 } known_flags[] = {
67 	{IFF_TUN, "TUN"},
68 	{IFF_TAP, "TAP"},
69 	{IFF_NO_PI, "NO_PI"},
70 	{IFF_ONE_QUEUE, "ONE_QUEUE"},
71 	{IFF_VNET_HDR, "VNET_HDR"},
72 	{IFF_MULTI_QUEUE, "MULTI_QUEUE"},
73 	{IFF_NAPI, "IFF_NAPI"},
74 	{IFF_NAPI_FRAGS, "IFF_NAPI_FRAGS"}
75 };
76 
77 static void verify_features(void)
78 {
79 	unsigned int features, i;
80 
81 	int netfd = open("/dev/net/tun", O_RDWR);
82 	if (netfd == -1) {
83 		if (errno == ENODEV)
84 			tst_brk(TCONF, "TUN support is missing?");
85 
86 		tst_brk(TBROK | TERRNO, "opening /dev/net/tun failed");
87 	}
88 
89 	SAFE_IOCTL(netfd, TUNGETFEATURES, &features);
90 
91 	tst_res(TINFO, "Available features are: %#x", features);
92 	for (i = 0; i < ARRAY_SIZE(known_flags); i++) {
93 		if (features & known_flags[i].flag) {
94 			features &= ~known_flags[i].flag;
95 			tst_res(TPASS, "%s %#x", known_flags[i].name,
96 				 known_flags[i].flag);
97 		}
98 	}
99 	if (features)
100 		tst_res(TFAIL, "(UNKNOWN %#x)", features);
101 
102 	SAFE_CLOSE(netfd);
103 }
104 
105 static struct tst_test test = {
106 	.test_all = verify_features,
107 	.needs_root = 1,
108 };
109