1 /*
2  * Copyright (C) 2020 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 <netdb.h>
18 #include <netinet/in.h>
19 #include <poll.h> /* poll */
20 #include <sys/socket.h>
21 #include <sys/types.h>
22 
23 #include <android-base/unique_fd.h>
24 #include <gtest/gtest.h>
25 
26 #include "NetdClient.h"
27 
28 #define SKIP_IF_NO_NETWORK_CONNECTIVITY                                                          \
29     do {                                                                                         \
30         if (!checkNetworkConnectivity()) GTEST_SKIP() << "Skip. Requires Network Connectivity."; \
31     } while (0)
32 
33 namespace {
34 
35 constexpr char TEST_DOMAIN[] = "www.google.com";
36 
checkNetworkConnectivity()37 bool checkNetworkConnectivity() {
38     android::base::unique_fd sock(socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP));
39     if (sock == -1) return false;
40     static const sockaddr_in6 server6 = {
41             .sin6_family = AF_INET6,
42             .sin6_addr.s6_addr = {// 2000::
43                                   0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
44     int ret = connect(sock, reinterpret_cast<const sockaddr*>(&server6), sizeof(server6));
45     if (ret == 0) return true;
46     sock.reset(socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP));
47     if (sock == -1) return false;
48     static const sockaddr_in server4 = {
49             .sin_family = AF_INET,
50             .sin_addr.s_addr = __constant_htonl(0x08080808L)  // 8.8.8.8
51     };
52     ret = connect(sock, reinterpret_cast<const sockaddr*>(&server4), sizeof(server4));
53     return !ret;
54 }
55 
expectHasNetworking()56 void expectHasNetworking() {
57     // Socket
58     android::base::unique_fd ipv4(socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0)),
59             ipv6(socket(AF_INET6, SOCK_STREAM | SOCK_CLOEXEC, 0));
60     EXPECT_LE(3, ipv4);
61     EXPECT_LE(3, ipv6);
62 
63     // DNS
64     addrinfo* result = nullptr;
65     errno = 0;
66     const addrinfo hints = {
67             .ai_family = AF_UNSPEC,
68             .ai_socktype = SOCK_DGRAM,
69     };
70     EXPECT_EQ(0, getaddrinfo(TEST_DOMAIN, nullptr, &hints, &result));
71     EXPECT_EQ(0, errno);
72     freeaddrinfo(result);
73 }
74 
expectNoNetworking()75 void expectNoNetworking() {
76     // Socket
77     android::base::unique_fd unixSocket(socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0));
78     EXPECT_LE(3, unixSocket);
79     android::base::unique_fd ipv4(socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0));
80     EXPECT_EQ(-1, ipv4);
81     EXPECT_EQ(EPERM, errno);
82     android::base::unique_fd ipv6(socket(AF_INET6, SOCK_STREAM | SOCK_CLOEXEC, 0));
83     EXPECT_EQ(-1, ipv6);
84     EXPECT_EQ(EPERM, errno);
85 
86     // DNS
87     addrinfo* result = nullptr;
88     errno = 0;
89     const addrinfo hints = {
90             .ai_family = AF_UNSPEC,
91             .ai_socktype = SOCK_DGRAM,
92     };
93     EXPECT_EQ(EAI_NODATA, getaddrinfo(TEST_DOMAIN, nullptr, &hints, &result));
94     EXPECT_EQ(EPERM, errno);
95     freeaddrinfo(result);
96 }
97 
98 }  // namespace
99 
TEST(NetdClientIntegrationTest,setAllowNetworkingForProcess)100 TEST(NetdClientIntegrationTest, setAllowNetworkingForProcess) {
101     SKIP_IF_NO_NETWORK_CONNECTIVITY;
102     // At the beginning, we should be able to use socket since the default setting is allowing.
103     expectHasNetworking();
104     // Disable
105     setAllowNetworkingForProcess(false);
106     expectNoNetworking();
107     // Reset
108     setAllowNetworkingForProcess(true);
109     expectHasNetworking();
110 }
111