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