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 MDNS
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:
OnFatalError(Error error)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 
OnRecoverableError(Error error)76     void OnRecoverableError(Error error) override {
77         LOG(ERROR) << "Encountered recoverable discovery error: " << error;
78     }
79 
GotFatalError() const80     bool GotFatalError() const { return got_fatal_; }
81 
82   private:
83     std::atomic<bool> got_fatal_{false};
84 };
85 
86 struct DiscoveryState {
87     std::optional<discovery::Config> config;
88     SerialDeletePtr<discovery::DnsSdService> service;
89     std::unique_ptr<DiscoveryReportingClient> reporting_client;
90     std::unique_ptr<AdbOspTaskRunner> task_runner;
91     std::vector<std::unique_ptr<ServiceReceiver>> receivers;
92     InterfaceInfo interface_info;
93 };
94 
95 // Callback provided to service receiver for updates.
OnServiceReceiverResult(std::vector<std::reference_wrapper<const ServiceInfo>> infos,std::reference_wrapper<const ServiceInfo> info,ServicesUpdatedState state)96 void OnServiceReceiverResult(std::vector<std::reference_wrapper<const ServiceInfo>> infos,
97                              std::reference_wrapper<const ServiceInfo> info,
98                              ServicesUpdatedState state) {
99     VLOG(MDNS) << "Endpoint state=" << static_cast<int>(state)
100                << " instance_name=" << info.get().instance_name
101                << " service_name=" << info.get().service_name << " addr=" << info.get().v4_address
102                << " addrv6=" << info.get().v6_address << " total_serv=" << infos.size();
103 
104     switch (state) {
105         case ServicesUpdatedState::EndpointCreated:
106         case ServicesUpdatedState::EndpointUpdated:
107             if (adb_DNSServiceShouldAutoConnect(info.get().service_name,
108                                                 info.get().instance_name) &&
109                 info.get().v4_address) {
110                 auto index = adb_DNSServiceIndexByName(info.get().service_name);
111                 if (!index) {
112                     return;
113                 }
114 
115                 // Don't try to auto-connect if not in the keystore.
116                 if (*index == kADBSecureConnectServiceRefIndex &&
117                     !adb_wifi_is_known_host(info.get().instance_name)) {
118                     VLOG(MDNS) << "instance_name=" << info.get().instance_name
119                                << " not in keystore";
120                     return;
121                 }
122                 std::string response;
123                 VLOG(MDNS) << "Attempting to auto-connect to instance=" << info.get().instance_name
124                            << " service=" << info.get().service_name << " addr4=%s"
125                            << info.get().v4_address << ":" << info.get().port;
126                 connect_device(
127                         android::base::StringPrintf("%s.%s", info.get().instance_name.c_str(),
128                                                     info.get().service_name.c_str()),
129                         &response);
130             }
131             break;
132         default:
133             break;
134     }
135 }
136 
GetConfigForAllInterfaces()137 std::optional<discovery::Config> GetConfigForAllInterfaces() {
138     auto interface_infos = GetNetworkInterfaces();
139 
140     discovery::Config config;
141 
142     // The host only consumes mDNS traffic. It doesn't publish anything.
143     // Avoid creating an mDNSResponder that will listen with authority
144     // to answer over no domain.
145     config.enable_publication = false;
146 
147     for (const auto interface : interface_infos) {
148         if (interface.GetIpAddressV4() || interface.GetIpAddressV6()) {
149             config.network_info.push_back({interface});
150             VLOG(MDNS) << "Listening on interface [" << interface << "]";
151         }
152     }
153 
154     if (config.network_info.empty()) {
155         VLOG(MDNS) << "No available network interfaces for mDNS discovery";
156         return std::nullopt;
157     }
158 
159     return config;
160 }
161 
StartDiscovery()162 void StartDiscovery() {
163     CHECK(!g_state);
164     g_state = new DiscoveryState();
165     g_state->task_runner = std::make_unique<AdbOspTaskRunner>();
166     g_state->reporting_client = std::make_unique<DiscoveryReportingClient>();
167 
168     g_state->task_runner->PostTask([]() {
169         g_state->config = GetConfigForAllInterfaces();
170         if (!g_state->config) {
171             VLOG(MDNS) << "No mDNS config. Aborting StartDiscovery()";
172             return;
173         }
174 
175         VLOG(MDNS) << "Starting discovery on " << (*g_state->config).network_info.size()
176                    << " interfaces";
177 
178         g_state->service = discovery::CreateDnsSdService(
179                 g_state->task_runner.get(), g_state->reporting_client.get(), *g_state->config);
180         // Register a receiver for each service type
181         for (int i = 0; i < kNumADBDNSServices; ++i) {
182             auto receiver = std::make_unique<ServiceReceiver>(
183                     g_state->service.get(), kADBDNSServices[i], OnServiceReceiverResult);
184             receiver->StartDiscovery();
185             g_state->receivers.push_back(std::move(receiver));
186 
187             if (g_state->reporting_client->GotFatalError()) {
188                 for (auto& r : g_state->receivers) {
189                     if (r->is_running()) {
190                         r->StopDiscovery();
191                     }
192                 }
193                 g_using_bonjour = true;
194                 break;
195             }
196         }
197 
198         if (g_using_bonjour) {
199             VLOG(MDNS) << "Fallback to MdnsResponder client for discovery";
200             g_adb_mdnsresponder_funcs = StartMdnsResponderDiscovery();
201         }
202     });
203 }
204 
ForEachService(const std::unique_ptr<ServiceReceiver> & receiver,std::string_view wanted_instance_name,adb_secure_foreach_service_callback cb)205 void ForEachService(const std::unique_ptr<ServiceReceiver>& receiver,
206                     std::string_view wanted_instance_name, adb_secure_foreach_service_callback cb) {
207     if (!receiver->is_running()) {
208         return;
209     }
210     auto services = receiver->GetServices();
211     for (const auto& s : services) {
212         if (wanted_instance_name.empty() || s.get().instance_name == wanted_instance_name) {
213             std::stringstream ss;
214             ss << s.get().v4_address;
215             cb(s.get().instance_name.c_str(), s.get().service_name.c_str(), ss.str().c_str(),
216                s.get().port);
217         }
218     }
219 }
220 
ConnectAdbSecureDevice(const MdnsInfo & info)221 bool ConnectAdbSecureDevice(const MdnsInfo& info) {
222     if (!adb_wifi_is_known_host(info.service_name)) {
223         VLOG(MDNS) << "serviceName=" << info.service_name << " not in keystore";
224         return false;
225     }
226 
227     std::string response;
228     connect_device(android::base::StringPrintf("%s.%s", info.service_name.c_str(),
229                                                info.service_type.c_str()),
230                    &response);
231     D("Secure connect to %s regtype %s (%s:%hu) : %s", info.service_name.c_str(),
232       info.service_type.c_str(), info.addr.c_str(), info.port, response.c_str());
233     return true;
234 }
235 
236 }  // namespace
237 
238 /////////////////////////////////////////////////////////////////////////////////
239 
using_bonjour(void)240 bool using_bonjour(void) {
241     return g_using_bonjour;
242 }
243 
mdns_cleanup()244 void mdns_cleanup() {
245     if (g_using_bonjour) {
246         return g_adb_mdnsresponder_funcs.mdns_cleanup();
247     }
248 }
249 
init_mdns_transport_discovery()250 void init_mdns_transport_discovery() {
251     const char* mdns_osp = getenv("ADB_MDNS_OPENSCREEN");
252     if (mdns_osp && strcmp(mdns_osp, "0") == 0) {
253         g_using_bonjour = true;
254         g_adb_mdnsresponder_funcs = StartMdnsResponderDiscovery();
255     } else {
256         VLOG(MDNS) << "Openscreen mdns discovery enabled";
257         StartDiscovery();
258     }
259 }
260 
adb_secure_connect_by_service_name(const std::string & instance_name)261 bool adb_secure_connect_by_service_name(const std::string& instance_name) {
262     if (g_using_bonjour) {
263         return g_adb_mdnsresponder_funcs.adb_secure_connect_by_service_name(instance_name);
264     }
265 
266     if (!g_state || g_state->receivers.empty()) {
267         VLOG(MDNS) << "Mdns not enabled";
268         return false;
269     }
270 
271     std::optional<MdnsInfo> info;
272     auto cb = [&](const std::string& instance_name, const std::string& service_name,
273                   const std::string& ip_addr,
274                   uint16_t port) { info.emplace(instance_name, service_name, ip_addr, port); };
275     ForEachService(g_state->receivers[kADBSecureConnectServiceRefIndex], instance_name, cb);
276     if (info.has_value()) {
277         return ConnectAdbSecureDevice(*info);
278     }
279     return false;
280 }
281 
mdns_check()282 std::string mdns_check() {
283     if (!g_state && !g_using_bonjour) {
284         return "ERROR: mdns discovery disabled";
285     }
286 
287     if (g_using_bonjour) {
288         return g_adb_mdnsresponder_funcs.mdns_check();
289     }
290 
291     return "mdns daemon version [Openscreen discovery 0.0.0]";
292 }
293 
mdns_list_discovered_services()294 std::string mdns_list_discovered_services() {
295     if (g_using_bonjour) {
296         return g_adb_mdnsresponder_funcs.mdns_list_discovered_services();
297     }
298 
299     if (!g_state || g_state->receivers.empty()) {
300         return "";
301     }
302 
303     std::string result;
304     auto cb = [&](const std::string& instance_name, const std::string& service_name,
305                   const std::string& ip_addr, uint16_t port) {
306         result += android::base::StringPrintf("%s\t%s\t%s:%u\n", instance_name.data(),
307                                               service_name.data(), ip_addr.data(), port);
308     };
309 
310     for (const auto& receiver : g_state->receivers) {
311         ForEachService(receiver, "", cb);
312     }
313     return result;
314 }
315 
mdns_get_connect_service_info(const std::string & name)316 std::optional<MdnsInfo> mdns_get_connect_service_info(const std::string& name) {
317     CHECK(!name.empty());
318 
319     if (g_using_bonjour) {
320         return g_adb_mdnsresponder_funcs.mdns_get_connect_service_info(name);
321     }
322 
323     if (!g_state || g_state->receivers.empty()) {
324         return std::nullopt;
325     }
326 
327     auto mdns_instance = mdns::mdns_parse_instance_name(name);
328     if (!mdns_instance.has_value()) {
329         D("Failed to parse mDNS name [%s]", name.data());
330         return std::nullopt;
331     }
332 
333     std::optional<MdnsInfo> info;
334     auto cb = [&](const std::string& instance_name, const std::string& service_name,
335                   const std::string& ip_addr,
336                   uint16_t port) { info.emplace(instance_name, service_name, ip_addr, port); };
337 
338     std::string reg_type;
339     // Service name was provided.
340     if (!mdns_instance->service_name.empty()) {
341         reg_type = android::base::StringPrintf("%s.%s", mdns_instance->service_name.data(),
342                                                mdns_instance->transport_type.data());
343         const auto index = adb_DNSServiceIndexByName(reg_type);
344         if (!index) {
345             return std::nullopt;
346         }
347         switch (*index) {
348             case kADBTransportServiceRefIndex:
349             case kADBSecureConnectServiceRefIndex:
350                 ForEachService(g_state->receivers[*index], mdns_instance->instance_name, cb);
351                 break;
352             default:
353                 D("Not a connectable service name [%s]", reg_type.data());
354                 return std::nullopt;
355         }
356         return info;
357     }
358 
359     // No mdns service name provided. Just search for the instance name in all adb connect services.
360     // Prefer the secured connect service over the other.
361     ForEachService(g_state->receivers[kADBSecureConnectServiceRefIndex], name, cb);
362     if (!info.has_value()) {
363         ForEachService(g_state->receivers[kADBTransportServiceRefIndex], name, cb);
364     }
365 
366     return info;
367 }
368 
mdns_get_pairing_service_info(const std::string & name)369 std::optional<MdnsInfo> mdns_get_pairing_service_info(const std::string& name) {
370     CHECK(!name.empty());
371 
372     if (g_using_bonjour) {
373         return g_adb_mdnsresponder_funcs.mdns_get_pairing_service_info(name);
374     }
375 
376     if (!g_state || g_state->receivers.empty()) {
377         return std::nullopt;
378     }
379 
380     auto mdns_instance = mdns::mdns_parse_instance_name(name);
381     if (!mdns_instance.has_value()) {
382         D("Failed to parse mDNS name [%s]", name.data());
383         return std::nullopt;
384     }
385 
386     std::optional<MdnsInfo> info;
387     auto cb = [&](const std::string& instance_name, const std::string& service_name,
388                   const std::string& ip_addr,
389                   uint16_t port) { info.emplace(instance_name, service_name, ip_addr, port); };
390 
391     std::string reg_type;
392     // Verify it's a pairing service if user explicitly inputs it.
393     if (!mdns_instance->service_name.empty()) {
394         reg_type = android::base::StringPrintf("%s.%s", mdns_instance->service_name.data(),
395                                                mdns_instance->transport_type.data());
396         const auto index = adb_DNSServiceIndexByName(reg_type);
397         if (!index) {
398             return std::nullopt;
399         }
400         switch (*index) {
401             case kADBSecurePairingServiceRefIndex:
402                 break;
403             default:
404                 D("Not an adb pairing reg_type [%s]", reg_type.data());
405                 return std::nullopt;
406         }
407         return info;
408     }
409 
410     ForEachService(g_state->receivers[kADBSecurePairingServiceRefIndex], name, cb);
411 
412     return info;
413 }
414