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 #define TRACE_TAG TRANSPORT
18 
19 #include "transport.h"
20 
21 #ifdef _WIN32
22 #include <winsock2.h>
23 #else
24 #include <arpa/inet.h>
25 #endif
26 
27 #include <memory>
28 #include <thread>
29 #include <unordered_set>
30 #include <vector>
31 
32 #include <android-base/stringprintf.h>
33 #include <android-base/strings.h>
34 
35 #include <discovery/common/config.h>
36 #include <discovery/common/reporting_client.h>
37 #include <discovery/public/dns_sd_service_factory.h>
38 #include <platform/api/network_interface.h>
39 #include <platform/api/serial_delete_ptr.h>
40 #include <platform/base/error.h>
41 #include <platform/base/interface_info.h>
42 
43 #include "adb_client.h"
44 #include "adb_mdns.h"
45 #include "adb_trace.h"
46 #include "adb_utils.h"
47 #include "adb_wifi.h"
48 #include "client/mdns_utils.h"
49 #include "client/openscreen/mdns_service_watcher.h"
50 #include "client/openscreen/platform/task_runner.h"
51 #include "fdevent/fdevent.h"
52 #include "sysdeps.h"
53 
54 namespace {
55 
56 using namespace mdns;
57 using namespace openscreen;
58 using ServicesUpdatedState = mdns::ServiceReceiver::ServicesUpdatedState;
59 
60 struct DiscoveryState;
61 DiscoveryState* g_state = nullptr;
62 // TODO: remove once openscreen has bonjour client APIs.
63 bool g_using_bonjour = false;
64 AdbMdnsResponderFuncs g_adb_mdnsresponder_funcs;
65 
66 class DiscoveryReportingClient : public discovery::ReportingClient {
67   public:
68     void OnFatalError(Error error) override {
69         // The multicast port 5353 may fail to bind because of another process already binding
70         // to it (bonjour). So let's fallback to bonjour client APIs.
71         // TODO: Remove this once openscreen implements the bonjour client APIs.
72         LOG(ERROR) << "Encountered fatal discovery error: " << error;
73         got_fatal_ = true;
74     }
75 
76     void OnRecoverableError(Error error) override {
77         LOG(ERROR) << "Encountered recoverable discovery error: " << error;
78     }
79 
80     bool GotFatalError() const { return got_fatal_; }
81 
82   private:
83     std::atomic<bool> got_fatal_{false};
84 };
85 
86 struct DiscoveryState {
87     SerialDeletePtr<discovery::DnsSdService> service;
88     std::unique_ptr<DiscoveryReportingClient> reporting_client;
89     std::unique_ptr<AdbOspTaskRunner> task_runner;
90     std::vector<std::unique_ptr<ServiceReceiver>> receivers;
91     InterfaceInfo interface_info;
92 };
93 
94 // Callback provided to service receiver for updates.
95 void OnServiceReceiverResult(std::vector<std::reference_wrapper<const ServiceInfo>> infos,
96                              std::reference_wrapper<const ServiceInfo> info,
97                              ServicesUpdatedState state) {
98     LOG(INFO) << "Endpoint state=" << static_cast<int>(state)
99               << " instance_name=" << info.get().instance_name
100               << " service_name=" << info.get().service_name << " addr=" << info.get().v4_address
101               << " addrv6=" << info.get().v6_address << " total_serv=" << infos.size();
102 
103     switch (state) {
104         case ServicesUpdatedState::EndpointCreated:
105         case ServicesUpdatedState::EndpointUpdated:
106             if (adb_DNSServiceShouldAutoConnect(info.get().service_name,
107                                                 info.get().instance_name) &&
108                 info.get().v4_address) {
109                 auto index = adb_DNSServiceIndexByName(info.get().service_name);
110                 if (!index) {
111                     return;
112                 }
113 
114                 // Don't try to auto-connect if not in the keystore.
115                 if (*index == kADBSecureConnectServiceRefIndex &&
116                     !adb_wifi_is_known_host(info.get().instance_name)) {
117                     LOG(INFO) << "instance_name=" << info.get().instance_name << " not in keystore";
118                     return;
119                 }
120                 std::string response;
121                 LOG(INFO) << "Attempting to auto-connect to instance=" << info.get().instance_name
122                           << " service=" << info.get().service_name << " addr4=%s"
123                           << info.get().v4_address << ":" << info.get().port;
124                 connect_device(
125                         android::base::StringPrintf("%s.%s", info.get().instance_name.c_str(),
126                                                     info.get().service_name.c_str()),
127                         &response);
128             }
129             break;
130         default:
131             break;
132     }
133 }
134 
135 std::optional<discovery::Config> GetConfigForAllInterfaces() {
136     auto interface_infos = GetNetworkInterfaces();
137 
138     discovery::Config config;
139     for (const auto interface : interface_infos) {
140         discovery::Config::NetworkInfo::AddressFamilies supported_address_families =
141                 discovery::Config::NetworkInfo::kNoAddressFamily;
142         if (interface.GetIpAddressV4()) {
143             supported_address_families |= discovery::Config::NetworkInfo::kUseIpV4;
144         }
145         if (interface.GetIpAddressV6()) {
146             supported_address_families |= discovery::Config::NetworkInfo::kUseIpV6;
147         }
148         if (supported_address_families == discovery::Config::NetworkInfo::kNoAddressFamily) {
149             LOG(INFO) << "Interface [" << interface << "] doesn't support ipv4 or ipv6."
150                       << " Ignoring interface.";
151             continue;
152         }
153         config.network_info.push_back({interface, supported_address_families});
154         LOG(VERBOSE) << "Listening on interface [" << interface << "]";
155     }
156 
157     if (config.network_info.empty()) {
158         LOG(INFO) << "No available network interfaces for mDNS discovery";
159         return std::nullopt;
160     }
161 
162     return config;
163 }
164 
165 void StartDiscovery() {
166     CHECK(!g_state);
167     g_state = new DiscoveryState();
168     g_state->task_runner = std::make_unique<AdbOspTaskRunner>();
169     g_state->reporting_client = std::make_unique<DiscoveryReportingClient>();
170 
171     g_state->task_runner->PostTask([]() {
172         auto config = GetConfigForAllInterfaces();
173         if (!config) {
174             return;
175         }
176 
177         g_state->service = discovery::CreateDnsSdService(g_state->task_runner.get(),
178                                                          g_state->reporting_client.get(), *config);
179         // Register a receiver for each service type
180         for (int i = 0; i < kNumADBDNSServices; ++i) {
181             auto receiver = std::make_unique<ServiceReceiver>(
182                     g_state->service.get(), kADBDNSServices[i], OnServiceReceiverResult);
183             receiver->StartDiscovery();
184             g_state->receivers.push_back(std::move(receiver));
185 
186             if (g_state->reporting_client->GotFatalError()) {
187                 for (auto& r : g_state->receivers) {
188                     if (r->is_running()) {
189                         r->StopDiscovery();
190                     }
191                 }
192                 g_using_bonjour = true;
193                 break;
194             }
195         }
196 
197         if (g_using_bonjour) {
198             LOG(INFO) << "Fallback to MdnsResponder client for discovery";
199             g_adb_mdnsresponder_funcs = StartMdnsResponderDiscovery();
200         }
201     });
202 }
203 
204 void ForEachService(const std::unique_ptr<ServiceReceiver>& receiver,
205                     std::string_view wanted_instance_name, adb_secure_foreach_service_callback cb) {
206     if (!receiver->is_running()) {
207         return;
208     }
209     auto services = receiver->GetServices();
210     for (const auto& s : services) {
211         if (wanted_instance_name.empty() || s.get().instance_name == wanted_instance_name) {
212             std::stringstream ss;
213             ss << s.get().v4_address;
214             cb(s.get().instance_name.c_str(), s.get().service_name.c_str(), ss.str().c_str(),
215                s.get().port);
216         }
217     }
218 }
219 
220 bool ConnectAdbSecureDevice(const MdnsInfo& info) {
221     if (!adb_wifi_is_known_host(info.service_name)) {
222         LOG(INFO) << "serviceName=" << info.service_name << " not in keystore";
223         return false;
224     }
225 
226     std::string response;
227     connect_device(android::base::StringPrintf("%s.%s", info.service_name.c_str(),
228                                                info.service_type.c_str()),
229                    &response);
230     D("Secure connect to %s regtype %s (%s:%hu) : %s", info.service_name.c_str(),
231       info.service_type.c_str(), info.addr.c_str(), info.port, response.c_str());
232     return true;
233 }
234 
235 }  // namespace
236 
237 /////////////////////////////////////////////////////////////////////////////////
238 void mdns_cleanup() {
239     if (g_using_bonjour) {
240         return g_adb_mdnsresponder_funcs.mdns_cleanup();
241     }
242 }
243 
244 void init_mdns_transport_discovery(void) {
245     // TODO(joshuaduong): Use openscreen discovery by default for all platforms.
246     const char* mdns_osp = getenv("ADB_MDNS_OPENSCREEN");
247     if (mdns_osp && strcmp(mdns_osp, "1") == 0) {
248         LOG(INFO) << "Openscreen mdns discovery enabled";
249         StartDiscovery();
250     } else {
251         // Original behavior is to use Bonjour client.
252         g_using_bonjour = true;
253         g_adb_mdnsresponder_funcs = StartMdnsResponderDiscovery();
254     }
255 }
256 
257 bool adb_secure_connect_by_service_name(const std::string& instance_name) {
258     if (g_using_bonjour) {
259         return g_adb_mdnsresponder_funcs.adb_secure_connect_by_service_name(instance_name);
260     }
261 
262     if (!g_state || g_state->receivers.empty()) {
263         LOG(INFO) << "Mdns not enabled";
264         return false;
265     }
266 
267     std::optional<MdnsInfo> info;
268     auto cb = [&](const std::string& instance_name, const std::string& service_name,
269                   const std::string& ip_addr,
270                   uint16_t port) { info.emplace(instance_name, service_name, ip_addr, port); };
271     ForEachService(g_state->receivers[kADBSecureConnectServiceRefIndex], instance_name, cb);
272     if (info.has_value()) {
273         return ConnectAdbSecureDevice(*info);
274     }
275     return false;
276 }
277 
278 std::string mdns_check() {
279     if (!g_state && !g_using_bonjour) {
280         return "ERROR: mdns discovery disabled";
281     }
282 
283     if (g_using_bonjour) {
284         return g_adb_mdnsresponder_funcs.mdns_check();
285     }
286 
287     return "mdns daemon version [Openscreen discovery 0.0.0]";
288 }
289 
290 std::string mdns_list_discovered_services() {
291     if (g_using_bonjour) {
292         return g_adb_mdnsresponder_funcs.mdns_list_discovered_services();
293     }
294 
295     if (!g_state || g_state->receivers.empty()) {
296         return "";
297     }
298 
299     std::string result;
300     auto cb = [&](const std::string& instance_name, const std::string& service_name,
301                   const std::string& ip_addr, uint16_t port) {
302         result += android::base::StringPrintf("%s\t%s\t%s:%u\n", instance_name.data(),
303                                               service_name.data(), ip_addr.data(), port);
304     };
305 
306     for (const auto& receiver : g_state->receivers) {
307         ForEachService(receiver, "", cb);
308     }
309     return result;
310 }
311 
312 std::optional<MdnsInfo> mdns_get_connect_service_info(const std::string& name) {
313     CHECK(!name.empty());
314 
315     if (g_using_bonjour) {
316         return g_adb_mdnsresponder_funcs.mdns_get_connect_service_info(name);
317     }
318 
319     if (!g_state || g_state->receivers.empty()) {
320         return std::nullopt;
321     }
322 
323     auto mdns_instance = mdns::mdns_parse_instance_name(name);
324     if (!mdns_instance.has_value()) {
325         D("Failed to parse mDNS name [%s]", name.data());
326         return std::nullopt;
327     }
328 
329     std::optional<MdnsInfo> info;
330     auto cb = [&](const std::string& instance_name, const std::string& service_name,
331                   const std::string& ip_addr,
332                   uint16_t port) { info.emplace(instance_name, service_name, ip_addr, port); };
333 
334     std::string reg_type;
335     // Service name was provided.
336     if (!mdns_instance->service_name.empty()) {
337         reg_type = android::base::StringPrintf("%s.%s", mdns_instance->service_name.data(),
338                                                mdns_instance->transport_type.data());
339         const auto index = adb_DNSServiceIndexByName(reg_type);
340         if (!index) {
341             return std::nullopt;
342         }
343         switch (*index) {
344             case kADBTransportServiceRefIndex:
345             case kADBSecureConnectServiceRefIndex:
346                 ForEachService(g_state->receivers[*index], mdns_instance->instance_name, cb);
347                 break;
348             default:
349                 D("Not a connectable service name [%s]", reg_type.data());
350                 return std::nullopt;
351         }
352         return info;
353     }
354 
355     // No mdns service name provided. Just search for the instance name in all adb connect services.
356     // Prefer the secured connect service over the other.
357     ForEachService(g_state->receivers[kADBSecureConnectServiceRefIndex], name, cb);
358     if (!info.has_value()) {
359         ForEachService(g_state->receivers[kADBTransportServiceRefIndex], name, cb);
360     }
361 
362     return info;
363 }
364 
365 std::optional<MdnsInfo> mdns_get_pairing_service_info(const std::string& name) {
366     CHECK(!name.empty());
367 
368     if (g_using_bonjour) {
369         return g_adb_mdnsresponder_funcs.mdns_get_pairing_service_info(name);
370     }
371 
372     if (!g_state || g_state->receivers.empty()) {
373         return std::nullopt;
374     }
375 
376     auto mdns_instance = mdns::mdns_parse_instance_name(name);
377     if (!mdns_instance.has_value()) {
378         D("Failed to parse mDNS name [%s]", name.data());
379         return std::nullopt;
380     }
381 
382     std::optional<MdnsInfo> info;
383     auto cb = [&](const std::string& instance_name, const std::string& service_name,
384                   const std::string& ip_addr,
385                   uint16_t port) { info.emplace(instance_name, service_name, ip_addr, port); };
386 
387     std::string reg_type;
388     // Verify it's a pairing service if user explicitly inputs it.
389     if (!mdns_instance->service_name.empty()) {
390         reg_type = android::base::StringPrintf("%s.%s", mdns_instance->service_name.data(),
391                                                mdns_instance->transport_type.data());
392         const auto index = adb_DNSServiceIndexByName(reg_type);
393         if (!index) {
394             return std::nullopt;
395         }
396         switch (*index) {
397             case kADBSecurePairingServiceRefIndex:
398                 break;
399             default:
400                 D("Not an adb pairing reg_type [%s]", reg_type.data());
401                 return std::nullopt;
402         }
403         return info;
404     }
405 
406     ForEachService(g_state->receivers[kADBSecurePairingServiceRefIndex], name, cb);
407 
408     return info;
409 }
410