1 /*
2 * Copyright (C) 2019 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
18 #include "resolv_test_utils.h"
19
20 #include <arpa/inet.h>
21
22 #include <android-base/chrono_utils.h>
23 #include <android-base/logging.h>
24 #include <firewall.h>
25
26 using android::netdutils::ScopedAddrinfo;
27
ToString(const hostent * he)28 std::string ToString(const hostent* he) {
29 if (he == nullptr) return "<null>";
30 char buffer[INET6_ADDRSTRLEN];
31 if (!inet_ntop(he->h_addrtype, he->h_addr_list[0], buffer, sizeof(buffer))) {
32 return "<invalid>";
33 }
34 return buffer;
35 }
36
ToString(const addrinfo * ai)37 std::string ToString(const addrinfo* ai) {
38 if (!ai) return "<null>";
39
40 const sockaddr* ai_addr = ai->ai_addr;
41 char host[NI_MAXHOST];
42 const int rv =
43 getnameinfo(ai_addr, ai->ai_addrlen, host, sizeof(host), nullptr, 0, NI_NUMERICHOST);
44 if (rv != 0) return gai_strerror(rv);
45 return host;
46 }
47
ToString(const ScopedAddrinfo & ai)48 std::string ToString(const ScopedAddrinfo& ai) {
49 return ToString(ai.get());
50 }
51
ToString(const sockaddr_storage * addr)52 std::string ToString(const sockaddr_storage* addr) {
53 if (!addr) return "<null>";
54 char host[NI_MAXHOST];
55 int rv = getnameinfo((const sockaddr*)addr, sizeof(sockaddr_storage), host, sizeof(host),
56 nullptr, 0, NI_NUMERICHOST);
57 if (rv != 0) return gai_strerror(rv);
58 return host;
59 }
60
ToStrings(const hostent * he)61 std::vector<std::string> ToStrings(const hostent* he) {
62 std::vector<std::string> hosts;
63 if (he == nullptr) {
64 hosts.push_back("<null>");
65 return hosts;
66 }
67 uint32_t i = 0;
68 while (he->h_addr_list[i] != nullptr) {
69 char host[INET6_ADDRSTRLEN];
70 if (!inet_ntop(he->h_addrtype, he->h_addr_list[i], host, sizeof(host))) {
71 hosts.push_back("<invalid>");
72 return hosts;
73 } else {
74 hosts.push_back(host);
75 }
76 i++;
77 }
78 if (hosts.empty()) hosts.push_back("<invalid>");
79 return hosts;
80 }
81
ToStrings(const addrinfo * ai)82 std::vector<std::string> ToStrings(const addrinfo* ai) {
83 std::vector<std::string> hosts;
84 if (!ai) {
85 hosts.push_back("<null>");
86 return hosts;
87 }
88 for (const auto* aip = ai; aip != nullptr; aip = aip->ai_next) {
89 const sockaddr* ai_addr = aip->ai_addr;
90 char host[NI_MAXHOST];
91 const int rv = getnameinfo(ai_addr, aip->ai_addrlen, host, sizeof(host), nullptr, 0,
92 NI_NUMERICHOST);
93 if (rv != 0) {
94 hosts.clear();
95 hosts.push_back(gai_strerror(rv));
96 return hosts;
97 } else {
98 hosts.push_back(host);
99 }
100 }
101 if (hosts.empty()) hosts.push_back("<invalid>");
102 return hosts;
103 }
104
ToStrings(const ScopedAddrinfo & ai)105 std::vector<std::string> ToStrings(const ScopedAddrinfo& ai) {
106 return ToStrings(ai.get());
107 }
108
GetNumQueries(const test::DNSResponder & dns,const char * name)109 size_t GetNumQueries(const test::DNSResponder& dns, const char* name) {
110 std::vector<test::DNSResponder::QueryInfo> queries = dns.queries();
111 size_t found = 0;
112 for (const auto& p : queries) {
113 if (p.name == name) {
114 ++found;
115 }
116 }
117 return found;
118 }
119
GetNumQueriesForProtocol(const test::DNSResponder & dns,const int protocol,const char * name)120 size_t GetNumQueriesForProtocol(const test::DNSResponder& dns, const int protocol,
121 const char* name) {
122 std::vector<test::DNSResponder::QueryInfo> queries = dns.queries();
123 size_t found = 0;
124 for (const auto& p : queries) {
125 if (p.protocol == protocol && p.name == name) {
126 ++found;
127 }
128 }
129 return found;
130 }
131
GetNumQueriesForType(const test::DNSResponder & dns,ns_type type,const char * name)132 size_t GetNumQueriesForType(const test::DNSResponder& dns, ns_type type, const char* name) {
133 std::vector<test::DNSResponder::QueryInfo> queries = dns.queries();
134 size_t found = 0;
135 for (const auto& p : queries) {
136 if (p.type == type && p.name == name) {
137 ++found;
138 }
139 }
140 return found;
141 }
142
PollForCondition(const std::function<bool ()> & condition,std::chrono::milliseconds timeout)143 bool PollForCondition(const std::function<bool()>& condition, std::chrono::milliseconds timeout) {
144 constexpr std::chrono::milliseconds retryIntervalMs{5};
145 android::base::Timer t;
146 while (t.duration() < timeout) {
147 if (condition()) return true;
148 std::this_thread::sleep_for(retryIntervalMs);
149 }
150 return false;
151 }
152
safe_getaddrinfo(const char * node,const char * service,const struct addrinfo * hints)153 ScopedAddrinfo safe_getaddrinfo(const char* node, const char* service,
154 const struct addrinfo* hints) {
155 addrinfo* result = nullptr;
156 if (getaddrinfo(node, service, hints, &result) != 0) {
157 result = nullptr; // Should already be the case, but...
158 }
159 return ScopedAddrinfo(result);
160 }
161
WaitChild(pid_t pid)162 int WaitChild(pid_t pid) {
163 int status;
164 const pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
165
166 if (got_pid != pid) {
167 PLOG(WARNING) << __func__ << ": waitpid failed: wanted " << pid << ", got " << got_pid;
168 return 1;
169 }
170
171 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
172 return 0;
173 } else {
174 return status;
175 }
176 }
177
ForkAndRun(const std::vector<std::string> & args)178 int ForkAndRun(const std::vector<std::string>& args) {
179 std::vector<const char*> argv;
180 argv.resize(args.size() + 1, nullptr);
181 std::transform(args.begin(), args.end(), argv.begin(),
182 [](const std::string& in) { return in.c_str(); });
183
184 pid_t pid = fork();
185 if (pid == -1) {
186 // Fork failed.
187 PLOG(ERROR) << __func__ << ": Unable to fork";
188 return -1;
189 }
190
191 if (pid == 0) {
192 execv(argv[0], const_cast<char**>(argv.data()));
193 PLOG(ERROR) << __func__ << ": execv failed";
194 _exit(1);
195 }
196
197 int rc = WaitChild(pid);
198 if (rc != 0) {
199 PLOG(ERROR) << __func__ << ": Failed run: status=" << rc;
200 }
201 return rc;
202 }
203
204 // Add routing rules for MDNS packets, or MDNS packets won't know the destination is MDNS
205 // muticast address "224.0.0.251".
SetMdnsRoute()206 void SetMdnsRoute() {
207 const std::vector<std::string> args = {
208 "system/bin/ip", "route", "add", "local", "224.0.0.251", "dev", "lo",
209 "proto", "static", "scope", "host", "src", "127.0.0.1",
210 };
211 EXPECT_EQ(0, ForkAndRun(args));
212
213 const std::vector<std::string> args_v6 = {
214 "system/bin/ip", "-6", "route", "add", "local", "ff02::fb",
215 "dev", "lo", "proto", "static", "src", "::1",
216 };
217 EXPECT_EQ(0, ForkAndRun(args_v6));
218 }
219
RemoveMdnsRoute()220 void RemoveMdnsRoute() {
221 const std::vector<std::string> args = {
222 "system/bin/ip", "route", "del", "local", "224.0.0.251", "dev", "lo",
223 "proto", "static", "scope", "host", "src", "127.0.0.1",
224 };
225 EXPECT_EQ(0, ForkAndRun(args));
226
227 const std::vector<std::string> args_v6 = {
228 "system/bin/ip", "-6", "route", "del", "local", "ff02::fb",
229 "dev", "lo", "proto", "static", "src", "::1",
230 };
231 EXPECT_EQ(0, ForkAndRun(args_v6));
232 }
233
AllowNetworkInBackground(int uid,bool allow)234 void AllowNetworkInBackground(int uid, bool allow) {
235 if (android::modules::sdklevel::IsAtLeastV()) {
236 // Background networking is always allowed on earlier versions.
237 Firewall* firewall = Firewall::getInstance();
238 if (allow) {
239 firewall->addRule(uid, BACKGROUND_MATCH);
240 } else {
241 firewall->removeRule(uid, BACKGROUND_MATCH);
242 }
243 }
244 }
245
is64bitAbi()246 bool is64bitAbi() {
247 return android::base::GetProperty("ro.product.cpu.abi", "").find("64") != std::string::npos;
248 }
249