1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <iostream>
18 #include <string>
19 
20 #include <fcntl.h>
21 
22 #include <android-base/stringprintf.h>
23 #include <android-base/unique_fd.h>
24 #include <gtest/gtest.h>
25 #include <sys/ioctl.h>
26 #include <sys/socket.h>
27 #include <linux/if.h>
28 #include <linux/if_tun.h>
29 
30 using std::cout;
31 using std::endl;
32 using std::string;
33 using android::base::StringPrintf;
34 using android::base::unique_fd;
35 
36 static const short kTunModes[] = {
37   IFF_TUN,
38   IFF_TAP,
39 };
40 
41 class VtsKernelTunTest : public ::testing::TestWithParam<short> {
42  public:
SetUp()43   virtual void SetUp() override {
44     tun_device_ = "/dev/tun";
45     uint32_t num = arc4random_uniform(1000);
46     ifr_name_ = StringPrintf("tun%d", num);
47   }
48 
49   // Used to initialize tun device.
50   int TunInit(short flags);
51 
52   string tun_device_;
53   string ifr_name_;
54   unique_fd fd_;
55 };
56 
TunInit(short mode)57 int VtsKernelTunTest::TunInit(short mode) {
58   struct ifreq ifr = {
59     .ifr_flags = mode,
60   };
61   strncpy(ifr.ifr_name, ifr_name_.c_str(), IFNAMSIZ);
62   int fd = open(tun_device_.c_str(), O_RDWR | O_NONBLOCK);
63   if (fd < 0) {
64     return -1;
65   }
66   if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) {
67     close(fd);
68     return -1;
69   }
70   return fd;
71 }
72 
73 // Test opening and closing of a tun interface.
TEST_P(VtsKernelTunTest,OpenAndClose)74 TEST_P(VtsKernelTunTest, OpenAndClose) {
75   fd_ = unique_fd(TunInit(GetParam()));
76   ASSERT_TRUE(fd_ >= 0);
77 }
78 
79 // Test basic read functionality of a tuen interface.
TEST_P(VtsKernelTunTest,BasicRead)80 TEST_P(VtsKernelTunTest, BasicRead) {
81   fd_ = unique_fd(TunInit(GetParam()));
82   ASSERT_TRUE(fd_ >= 0);
83 
84   uint8_t test_output;
85   // Expect no packets available on this interface.
86   ASSERT_TRUE(read(fd_, &test_output, 1) < 0);
87 }
88 
89 INSTANTIATE_TEST_CASE_P(Basic, VtsKernelTunTest,
90                         ::testing::ValuesIn(kTunModes));
91 
main(int argc,char ** argv)92 int main(int argc, char **argv) {
93   ::testing::InitGoogleTest(&argc, argv);
94   return RUN_ALL_TESTS();
95 }
96