1 /*
2  * Copyright 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  * tun_interface.cpp - creates tun interfaces for testing purposes
17  */
18 
19 #include <fcntl.h>
20 #include <netdb.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <sys/ioctl.h>
24 #include <sys/socket.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <linux/if.h>
28 #include <linux/if_tun.h>
29 
30 #include <android-base/stringprintf.h>
31 #include <android-base/strings.h>
32 #include <netutils/ifc.h>
33 
34 #include "tun_interface.h"
35 
36 #define TUN_DEV "/dev/tun"
37 
38 using android::base::StringPrintf;
39 
40 namespace android {
41 namespace net {
42 
init()43 int TunInterface::init() {
44     // Generate a random ULA address pair.
45     arc4random_buf(&mSrcAddr, sizeof(mSrcAddr));
46     mSrcAddr.s6_addr[0] = 0xfd;
47     memcpy(&mDstAddr, &mSrcAddr, sizeof(mDstAddr));
48     mDstAddr.s6_addr[15] ^= 1;
49 
50     // Convert the addresses to strings because that's what ifc_add_address takes.
51     char srcStr[INET6_ADDRSTRLEN], dstStr[INET6_ADDRSTRLEN];
52     sockaddr_in6 src6 = { .sin6_family = AF_INET6, .sin6_addr = mSrcAddr, };
53     sockaddr_in6 dst6 = { .sin6_family = AF_INET6, .sin6_addr = mDstAddr, };
54     int flags = NI_NUMERICHOST;
55     if (getnameinfo((sockaddr *) &src6, sizeof(src6), srcStr, sizeof(srcStr), NULL, 0, flags) ||
56         getnameinfo((sockaddr *) &dst6, sizeof(dst6), dstStr, sizeof(dstStr), NULL, 0, flags)) {
57         return -EINVAL;
58     }
59 
60     // Create a tun interface with a name based on our PID.
61     mIfName = StringPrintf("netdtest%u", getpid());
62     struct ifreq ifr = {
63         .ifr_ifru = { .ifru_flags = IFF_TUN },
64     };
65     snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", mIfName.c_str());
66 
67     mFd = open(TUN_DEV, O_RDWR | O_NONBLOCK | O_CLOEXEC);
68     if (mFd == -1) return -errno;
69 
70     int ret = ioctl(mFd, TUNSETIFF, &ifr, sizeof(ifr));
71     if (ret == -1) {
72         ret = -errno;
73         close(mFd);
74         return ret;
75     }
76 
77     if (ifc_add_address(ifr.ifr_name, srcStr, 64) ||
78         ifc_add_address(ifr.ifr_name, dstStr, 64)) {
79         ret = -errno;
80         close(mFd);
81         return ret;
82     }
83 
84     return 0;
85 }
86 
destroy()87 void TunInterface::destroy() {
88     if (mFd != -1) {
89         close(mFd);
90         mFd = -1;
91     }
92 }
93 
94 }  // namespace net
95 }  // namespace android
96