/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <iostream>
#include <string>
#include <fcntl.h>
#include <android-base/stringprintf.h>
#include <android-base/unique_fd.h>
#include <gtest/gtest.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/if.h>
#include <linux/if_tun.h>
using std::cout;
using std::endl;
using std::string;
using android::base::StringPrintf;
using android::base::unique_fd;
static const short kTunModes[] = {
IFF_TUN,
IFF_TAP,
};
class VtsKernelTunTest : public ::testing::TestWithParam<short> {
public:
virtual void SetUp() override {
tun_device_ = "/dev/tun";
uint32_t num = arc4random_uniform(1000);
ifr_name_ = StringPrintf("tun%d", num);
}
// Used to initialize tun device.
int TunInit(short flags);
string tun_device_;
string ifr_name_;
unique_fd fd_;
};
int VtsKernelTunTest::TunInit(short mode) {
struct ifreq ifr = {
.ifr_flags = mode,
};
strncpy(ifr.ifr_name, ifr_name_.c_str(), IFNAMSIZ);
int fd = open(tun_device_.c_str(), O_RDWR | O_NONBLOCK);
if (fd < 0) {
return -1;
}
if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) {
close(fd);
return -1;
}
return fd;
}
// Test opening and closing of a tun interface.
TEST_P(VtsKernelTunTest, OpenAndClose) {
fd_ = unique_fd(TunInit(GetParam()));
ASSERT_TRUE(fd_ >= 0);
}
// Test basic read functionality of a tuen interface.
TEST_P(VtsKernelTunTest, BasicRead) {
fd_ = unique_fd(TunInit(GetParam()));
ASSERT_TRUE(fd_ >= 0);
uint8_t test_output;
// Expect no packets available on this interface.
ASSERT_TRUE(read(fd_, &test_output, 1) < 0);
}
INSTANTIATE_TEST_CASE_P(Basic, VtsKernelTunTest,
::testing::ValuesIn(kTunModes));
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}