Loading adb/adb_mdns.h +66 −0 Original line number Original line Diff line number Diff line Loading @@ -17,6 +17,72 @@ #ifndef _ADB_MDNS_H_ #ifndef _ADB_MDNS_H_ #define _ADB_MDNS_H_ #define _ADB_MDNS_H_ #include <android-base/macros.h> const char* kADBServiceType = "_adb._tcp"; const char* kADBServiceType = "_adb._tcp"; const char* kADBSecurePairingServiceType = "_adb_secure_pairing._tcp"; const char* kADBSecureConnectServiceType = "_adb_secure_connect._tcp"; const int kADBTransportServiceRefIndex = 0; const int kADBSecurePairingServiceRefIndex = 1; const int kADBSecureConnectServiceRefIndex = 2; // Each ADB Secure service advertises with a TXT record indicating the version // using a key/value pair per RFC 6763 (https://tools.ietf.org/html/rfc6763). // // The first key/value pair is always the version of the protocol. // There may be more key/value pairs added after. // // The version is purposely represented as the single letter "v" due to the // need to minimize DNS traffic. The version starts at 1. With each breaking // protocol change, the version is incremented by 1. // // Newer adb clients/daemons need to recognize and either reject // or be backward-compatible with older verseions if there is a mismatch. // // Relevant sections: // // """ // 6.4. Rules for Keys in DNS-SD Key/Value Pairs // // The key MUST be at least one character. DNS-SD TXT record strings // beginning with an '=' character (i.e., the key is missing) MUST be // silently ignored. // // ... // // 6.5. Rules for Values in DNS-SD Key/Value Pairs // // If there is an '=' in a DNS-SD TXT record string, then everything // after the first '=' to the end of the string is the value. The value // can contain any eight-bit values including '='. // """ #define ADB_SECURE_SERVICE_VERSION_TXT_RECORD(ver) ("v=" #ver) // Client/service versions are initially defined to be matching, // but may go out of sync as different clients and services // try to talk to each other. #define ADB_SECURE_SERVICE_VERSION 1 #define ADB_SECURE_CLIENT_VERSION ADB_SECURE_SERVICE_VERSION const char* kADBSecurePairingServiceTxtRecord = ADB_SECURE_SERVICE_VERSION_TXT_RECORD(ADB_SECURE_SERVICE_VERSION); const char* kADBSecureConnectServiceTxtRecord = ADB_SECURE_SERVICE_VERSION_TXT_RECORD(ADB_SECURE_SERVICE_VERSION); const char* kADBDNSServices[] = { kADBServiceType, kADBSecurePairingServiceType, kADBSecureConnectServiceType, }; const char* kADBDNSServiceTxtRecords[] = { nullptr, kADBSecurePairingServiceTxtRecord, kADBSecureConnectServiceTxtRecord, }; const int kNumADBDNSServices = arraysize(kADBDNSServices); #endif #endif adb/client/adb_client.h +14 −0 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,7 @@ #pragma once #pragma once #include <functional> #include <optional> #include <optional> #include <string> #include <string> Loading Loading @@ -86,3 +87,16 @@ std::optional<std::string> adb_get_server_executable_path(); // Globally acccesible argv/envp, for the purpose of re-execing adb. // Globally acccesible argv/envp, for the purpose of re-execing adb. extern const char* _Nullable * _Nullable __adb_argv; extern const char* _Nullable * _Nullable __adb_argv; extern const char* _Nullable * _Nullable __adb_envp; extern const char* _Nullable * _Nullable __adb_envp; // ADB Secure DNS service interface. Used to query what ADB Secure DNS services have been // resolved, and to run some kind of callback for each one. using adb_secure_foreach_service_callback = std::function<void( const char* _Nonnull host_name, const char* _Nonnull ip_address, uint16_t port)>; // Queries pairing/connect services that have been discovered and resolved. // If |host_name| is not null, run |cb| only for services // matching |host_name|. Otherwise, run for all services. void adb_secure_foreach_pairing_service(const char* _Nullable host_name, adb_secure_foreach_service_callback cb); void adb_secure_foreach_connect_service(const char* _Nullable host_name, adb_secure_foreach_service_callback cb); adb/client/transport_mdns.cpp +237 −63 Original line number Original line Diff line number Diff line Loading @@ -25,17 +25,33 @@ #endif #endif #include <thread> #include <thread> #include <vector> #include <android-base/stringprintf.h> #include <android-base/stringprintf.h> #include <dns_sd.h> #include <dns_sd.h> #include "adb_client.h" #include "adb_mdns.h" #include "adb_mdns.h" #include "adb_trace.h" #include "adb_trace.h" #include "fdevent/fdevent.h" #include "fdevent/fdevent.h" #include "sysdeps.h" #include "sysdeps.h" static DNSServiceRef service_ref; static DNSServiceRef service_refs[kNumADBDNSServices]; static fdevent* service_ref_fde; static fdevent* service_ref_fdes[kNumADBDNSServices]; static int adb_DNSServiceIndexByName(const char* regType) { for (int i = 0; i < kNumADBDNSServices; ++i) { if (!strncmp(regType, kADBDNSServices[i], strlen(kADBDNSServices[i]))) { return i; } } return -1; } static bool adb_DNSServiceShouldConnect(const char* regType) { int index = adb_DNSServiceIndexByName(regType); return index == kADBTransportServiceRefIndex; } // Use adb_DNSServiceRefSockFD() instead of calling DNSServiceRefSockFD() // Use adb_DNSServiceRefSockFD() instead of calling DNSServiceRefSockFD() // directly so that the socket is put through the appropriate compatibility // directly so that the socket is put through the appropriate compatibility Loading Loading @@ -94,10 +110,16 @@ class ResolvedService : public AsyncServiceRef { public: public: virtual ~ResolvedService() = default; virtual ~ResolvedService() = default; ResolvedService(std::string name, uint32_t interfaceIndex, ResolvedService(std::string serviceName, std::string regType, uint32_t interfaceIndex, const char* hosttarget, uint16_t port) : const char* hosttarget, uint16_t port, int version) name_(name), : serviceName_(serviceName), port_(port) { regType_(regType), hosttarget_(hosttarget), port_(port), sa_family_(0), ip_addr_data_(NULL), serviceVersion_(version) { memset(ip_addr_, 0, sizeof(ip_addr_)); /* TODO: We should be able to get IPv6 support by adding /* TODO: We should be able to get IPv6 support by adding * kDNSServiceProtocol_IPv6 to the flags below. However, when we do * kDNSServiceProtocol_IPv6 to the flags below. However, when we do Loading @@ -116,20 +138,19 @@ class ResolvedService : public AsyncServiceRef { } else { } else { Initialize(); Initialize(); } } D("Client version: %d Service version: %d\n", clientVersion_, serviceVersion_); } } void Connect(const sockaddr* address) { void Connect(const sockaddr* address) { char ip_addr[INET6_ADDRSTRLEN]; sa_family_ = address->sa_family; const void* ip_addr_data; const char* addr_format; const char* addr_format; if (address->sa_family == AF_INET) { if (sa_family_ == AF_INET) { ip_addr_data = ip_addr_data_ = &reinterpret_cast<const sockaddr_in*>(address)->sin_addr; &reinterpret_cast<const sockaddr_in*>(address)->sin_addr; addr_format = "%s:%hu"; addr_format = "%s:%hu"; } else if (address->sa_family == AF_INET6) { } else if (sa_family_ == AF_INET6) { ip_addr_data = ip_addr_data_ = &reinterpret_cast<const sockaddr_in6*>(address)->sin6_addr; &reinterpret_cast<const sockaddr_in6*>(address)->sin6_addr; addr_format = "[%s]:%hu"; addr_format = "[%s]:%hu"; } else { // Should be impossible } else { // Should be impossible D("mDNS resolved non-IP address."); D("mDNS resolved non-IP address."); Loading @@ -137,24 +158,115 @@ class ResolvedService : public AsyncServiceRef { } } // Winsock version requires the const cast Because Microsoft. // Winsock version requires the const cast Because Microsoft. if (!inet_ntop(address->sa_family, const_cast<void*>(ip_addr_data), if (!inet_ntop(sa_family_, const_cast<void*>(ip_addr_data_), ip_addr_, sizeof(ip_addr_))) { ip_addr, INET6_ADDRSTRLEN)) { D("Could not convert IP address to string."); D("Could not convert IP address to string."); return; return; } } // adb secure service needs to do something different from just // connecting here. if (adb_DNSServiceShouldConnect(regType_.c_str())) { std::string response; std::string response; connect_device(android::base::StringPrintf(addr_format, ip_addr, port_), connect_device(android::base::StringPrintf(addr_format, ip_addr_, port_), &response); &response); D("Connect to %s regtype %s (%s:%hu) : %s", serviceName_.c_str(), regType_.c_str(), D("Connect to %s (%s:%hu) : %s", name_.c_str(), ip_addr, port_, ip_addr_, port_, response.c_str()); response.c_str()); } else { D("Not immediately connecting to serviceName=[%s], regtype=[%s] ipaddr=(%s:%hu)", serviceName_.c_str(), regType_.c_str(), ip_addr_, port_); } int adbSecureServiceType = serviceIndex(); switch (adbSecureServiceType) { case kADBSecurePairingServiceRefIndex: sAdbSecurePairingServices->push_back(this); break; case kADBSecureConnectServiceRefIndex: sAdbSecureConnectServices->push_back(this); break; default: break; } } } int serviceIndex() const { return adb_DNSServiceIndexByName(regType_.c_str()); } std::string hostTarget() const { return hosttarget_; } std::string ipAddress() const { return ip_addr_; } uint16_t port() const { return port_; } using ServiceRegistry = std::vector<ResolvedService*>; static ServiceRegistry* sAdbSecurePairingServices; static ServiceRegistry* sAdbSecureConnectServices; static void initAdbSecure(); static void forEachService(const ServiceRegistry& services, const std::string& hostname, adb_secure_foreach_service_callback cb); private: private: std::string name_; int clientVersion_ = ADB_SECURE_CLIENT_VERSION; std::string serviceName_; std::string regType_; std::string hosttarget_; const uint16_t port_; const uint16_t port_; int sa_family_; const void* ip_addr_data_; char ip_addr_[INET6_ADDRSTRLEN]; int serviceVersion_; }; }; // static std::vector<ResolvedService*>* ResolvedService::sAdbSecurePairingServices = NULL; // static std::vector<ResolvedService*>* ResolvedService::sAdbSecureConnectServices = NULL; // static void ResolvedService::initAdbSecure() { if (!sAdbSecurePairingServices) { sAdbSecurePairingServices = new ServiceRegistry; } if (!sAdbSecureConnectServices) { sAdbSecureConnectServices = new ServiceRegistry; } } // static void ResolvedService::forEachService(const ServiceRegistry& services, const std::string& wanted_host, adb_secure_foreach_service_callback cb) { initAdbSecure(); for (auto service : services) { auto hostname = service->hostTarget(); auto ip = service->ipAddress(); auto port = service->port(); if (wanted_host == "") { cb(hostname.c_str(), ip.c_str(), port); } else if (hostname == wanted_host) { cb(hostname.c_str(), ip.c_str(), port); } } } // static void adb_secure_foreach_pairing_service(const char* host_name, adb_secure_foreach_service_callback cb) { ResolvedService::forEachService(*ResolvedService::sAdbSecurePairingServices, host_name ? host_name : "", cb); } // static void adb_secure_foreach_connect_service(const char* host_name, adb_secure_foreach_service_callback cb) { ResolvedService::forEachService(*ResolvedService::sAdbSecureConnectServices, host_name ? host_name : "", cb); } static void DNSSD_API register_service_ip(DNSServiceRef /*sdRef*/, static void DNSSD_API register_service_ip(DNSServiceRef /*sdRef*/, DNSServiceFlags /*flags*/, DNSServiceFlags /*flags*/, uint32_t /*interfaceIndex*/, uint32_t /*interfaceIndex*/, Loading @@ -167,6 +279,12 @@ static void DNSSD_API register_service_ip(DNSServiceRef /*sdRef*/, std::unique_ptr<ResolvedService> data( std::unique_ptr<ResolvedService> data( reinterpret_cast<ResolvedService*>(context)); reinterpret_cast<ResolvedService*>(context)); data->Connect(address); data->Connect(address); // For ADB Secure services, keep those ResolvedService's around // for later processing with secure connection establishment. if (data->serviceIndex() != kADBTransportServiceRefIndex) { data.release(); } } } static void DNSSD_API register_resolved_mdns_service(DNSServiceRef sdRef, static void DNSSD_API register_resolved_mdns_service(DNSServiceRef sdRef, Loading @@ -182,18 +300,23 @@ static void DNSSD_API register_resolved_mdns_service(DNSServiceRef sdRef, class DiscoveredService : public AsyncServiceRef { class DiscoveredService : public AsyncServiceRef { public: public: DiscoveredService(uint32_t interfaceIndex, const char* serviceName, DiscoveredService(uint32_t interfaceIndex, const char* serviceName, const char* regtype, const char* regtype, const char* domain) const char* domain) : serviceName_(serviceName) { : serviceName_(serviceName), regType_(regtype) { DNSServiceErrorType ret = DNSServiceErrorType ret = DNSServiceResolve(&sdRef_, 0, interfaceIndex, serviceName, regtype, DNSServiceResolve(&sdRef_, 0, interfaceIndex, serviceName, regtype, domain, register_resolved_mdns_service, domain, register_resolved_mdns_service, reinterpret_cast<void*>(this)); reinterpret_cast<void*>(this)); if (ret != kDNSServiceErr_NoError) { D("DNSServiceResolve for " D("Got %d from DNSServiceResolve.", ret); "interfaceIndex %u " } else { "serviceName %s " "regtype %s " "domain %s " ": %d", interfaceIndex, serviceName, regtype, domain, ret); if (ret == kDNSServiceErr_NoError) { Initialize(); Initialize(); } } } } Loading @@ -202,20 +325,62 @@ class DiscoveredService : public AsyncServiceRef { return serviceName_.c_str(); return serviceName_.c_str(); } } const char* RegType() { return regType_.c_str(); } private: private: std::string serviceName_; std::string serviceName_; std::string regType_; }; }; static void DNSSD_API register_resolved_mdns_service(DNSServiceRef sdRef, // Returns the version the device wanted to advertise, DNSServiceFlags flags, // or -1 if parsing fails. uint32_t interfaceIndex, static int parse_version_from_txt_record(uint16_t txtLen, const unsigned char* txtRecord) { DNSServiceErrorType errorCode, if (!txtLen) return -1; const char* fullname, if (!txtRecord) return -1; const char* hosttarget, uint16_t port, // https://tools.ietf.org/html/rfc6763 uint16_t /*txtLen*/, // """ const unsigned char* /*txtRecord*/, // 6.1. General Format Rules for DNS TXT Records void* context) { // // A DNS TXT record can be up to 65535 (0xFFFF) bytes long. The total // length is indicated by the length given in the resource record header // in the DNS message. There is no way to tell directly from the data // alone how long it is (e.g., there is no length count at the start, or // terminating NULL byte at the end). // """ // Let's trust the TXT record's length byte // Worst case, it wastes 255 bytes std::vector<char> recordAsString(txtLen + 1, '\0'); char* str = recordAsString.data(); memcpy(str, txtRecord + 1 /* skip the length byte */, txtLen); // Check if it's the version key static const char* versionKey = "v="; size_t versionKeyLen = strlen(versionKey); if (strncmp(versionKey, str, versionKeyLen)) return -1; auto valueStart = str + versionKeyLen; long parsedNumber = strtol(valueStart, 0, 10); // No valid conversion. Also, 0 // is not a valid version. if (!parsedNumber) return -1; // Outside bounds of long. if (parsedNumber == LONG_MIN || parsedNumber == LONG_MAX) return -1; // Possibly valid version return static_cast<int>(parsedNumber); } static void DNSSD_API register_resolved_mdns_service( DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char* fullname, const char* hosttarget, uint16_t port, uint16_t txtLen, const unsigned char* txtRecord, void* context) { D("Resolved a service."); D("Resolved a service."); std::unique_ptr<DiscoveredService> discovered( std::unique_ptr<DiscoveredService> discovered( reinterpret_cast<DiscoveredService*>(context)); reinterpret_cast<DiscoveredService*>(context)); Loading @@ -225,10 +390,14 @@ static void DNSSD_API register_resolved_mdns_service(DNSServiceRef sdRef, return; return; } } // TODO: Reject certain combinations of invalid or mismatched client and // service versions here before creating anything. // At the moment, there is nothing to reject, so accept everything // as an optimistic default. auto serviceVersion = parse_version_from_txt_record(txtLen, txtRecord); auto resolved = auto resolved = new ResolvedService(discovered->ServiceName(), discovered->RegType(), new ResolvedService(discovered->ServiceName(), interfaceIndex, hosttarget, ntohs(port), serviceVersion); interfaceIndex, hosttarget, ntohs(port)); if (! resolved->Initialized()) { if (! resolved->Initialized()) { delete resolved; delete resolved; Loading @@ -239,19 +408,18 @@ static void DNSSD_API register_resolved_mdns_service(DNSServiceRef sdRef, } } } } static void DNSSD_API register_mdns_transport(DNSServiceRef sdRef, static void DNSSD_API on_service_browsed(DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, uint32_t interfaceIndex, const char* serviceName, const char* regtype, DNSServiceErrorType errorCode, const char* domain, void* /*context*/) { const char* serviceName, const char* regtype, const char* domain, void* /*context*/) { D("Registering a transport."); D("Registering a transport."); if (errorCode != kDNSServiceErr_NoError) { if (errorCode != kDNSServiceErr_NoError) { D("Got error %d during mDNS browse.", errorCode); D("Got error %d during mDNS browse.", errorCode); DNSServiceRefDeallocate(sdRef); DNSServiceRefDeallocate(sdRef); fdevent_destroy(service_ref_fde); int serviceIndex = adb_DNSServiceIndexByName(regtype); if (serviceIndex != -1) { fdevent_destroy(service_ref_fdes[serviceIndex]); } return; return; } } Loading @@ -262,21 +430,27 @@ static void DNSSD_API register_mdns_transport(DNSServiceRef sdRef, } } void init_mdns_transport_discovery_thread(void) { void init_mdns_transport_discovery_thread(void) { DNSServiceErrorType errorCode = DNSServiceBrowse(&service_ref, 0, 0, kADBServiceType, nullptr, int errorCodes[kNumADBDNSServices]; register_mdns_transport, nullptr); if (errorCode != kDNSServiceErr_NoError) { for (int i = 0; i < kNumADBDNSServices; ++i) { D("Got %d initiating mDNS browse.", errorCode); errorCodes[i] = DNSServiceBrowse(&service_refs[i], 0, 0, kADBDNSServices[i], nullptr, return; on_service_browsed, nullptr); if (errorCodes[i] != kDNSServiceErr_NoError) { D("Got %d browsing for mDNS service %s.", errorCodes[i], kADBDNSServices[i]); } } fdevent_run_on_main_thread([]() { if (errorCodes[i] == kDNSServiceErr_NoError) { service_ref_fde = fdevent_run_on_main_thread([i]() { fdevent_create(adb_DNSServiceRefSockFD(service_ref), pump_service_ref, &service_ref); service_ref_fdes[i] = fdevent_create(adb_DNSServiceRefSockFD(service_refs[i]), fdevent_set(service_ref_fde, FDE_READ); pump_service_ref, &service_refs[i]); fdevent_set(service_ref_fdes[i], FDE_READ); }); }); } } } } void init_mdns_transport_discovery(void) { void init_mdns_transport_discovery(void) { ResolvedService::initAdbSecure(); std::thread(init_mdns_transport_discovery_thread).detach(); std::thread(init_mdns_transport_discovery_thread).detach(); } } adb/daemon/mdns.cpp +97 −14 Original line number Original line Diff line number Diff line Loading @@ -14,6 +14,7 @@ * limitations under the License. * limitations under the License. */ */ #include "mdns.h" #include "adb_mdns.h" #include "adb_mdns.h" #include "sysdeps.h" #include "sysdeps.h" Loading @@ -32,8 +33,8 @@ using namespace std::chrono_literals; static std::mutex& mdns_lock = *new std::mutex(); static std::mutex& mdns_lock = *new std::mutex(); static int port; static int port; static DNSServiceRef mdns_ref; static DNSServiceRef mdns_refs[kNumADBDNSServices]; static bool mdns_registered = false; static bool mdns_registered[kNumADBDNSServices]; static void start_mdns() { static void start_mdns() { if (android::base::GetProperty("init.svc.mdnsd", "") == "running") { if (android::base::GetProperty("init.svc.mdnsd", "") == "running") { Loading @@ -60,34 +61,86 @@ static void mdns_callback(DNSServiceRef /*ref*/, } } } } static void setup_mdns_thread() { static void register_mdns_service(int index, int port) { start_mdns(); std::lock_guard<std::mutex> lock(mdns_lock); std::lock_guard<std::mutex> lock(mdns_lock); std::string hostname = "adb-"; std::string hostname = "adb-"; hostname += android::base::GetProperty("ro.serialno", "unidentified"); hostname += android::base::GetProperty("ro.serialno", "unidentified"); auto error = DNSServiceRegister(&mdns_ref, 0, 0, hostname.c_str(), // https://tools.ietf.org/html/rfc6763 kADBServiceType, nullptr, nullptr, // """ htobe16((uint16_t)port), 0, nullptr, // The format of the data within a DNS TXT record is one or more mdns_callback, nullptr); // strings, packed together in memory without any intervening gaps or // padding bytes for word alignment. // // The format of each constituent string within the DNS TXT record is a // single length byte, followed by 0-255 bytes of text data. // """ // // Therefore: // 1. Begin with the string length // 2. No null termination std::vector<char> txtRecord; if (kADBDNSServiceTxtRecords[index]) { size_t txtRecordStringLength = strlen(kADBDNSServiceTxtRecords[index]); txtRecord.resize(1 + // length byte txtRecordStringLength // string bytes ); txtRecord[0] = (char)txtRecordStringLength; memcpy(txtRecord.data() + 1, kADBDNSServiceTxtRecords[index], txtRecordStringLength); } auto error = DNSServiceRegister( &mdns_refs[index], 0, 0, hostname.c_str(), kADBDNSServices[index], nullptr, nullptr, htobe16((uint16_t)port), (uint16_t)txtRecord.size(), txtRecord.empty() ? nullptr : txtRecord.data(), mdns_callback, nullptr); if (error != kDNSServiceErr_NoError) { if (error != kDNSServiceErr_NoError) { LOG(ERROR) << "Could not register mDNS service (" << error << ")."; LOG(ERROR) << "Could not register mDNS service " << kADBDNSServices[index] << ", error (" return; << error << ")."; mdns_registered[index] = false; } } mdns_registered = true; mdns_registered[index] = true; LOG(INFO) << "adbd mDNS service " << kADBDNSServices[index] << " registered: " << mdns_registered[index]; } } static void teardown_mdns() { static void unregister_mdns_service(int index) { std::lock_guard<std::mutex> lock(mdns_lock); std::lock_guard<std::mutex> lock(mdns_lock); if (mdns_registered) { if (mdns_registered[index]) { DNSServiceRefDeallocate(mdns_ref); DNSServiceRefDeallocate(mdns_refs[index]); } } } } static void register_base_mdns_transport() { register_mdns_service(kADBTransportServiceRefIndex, port); } static void setup_mdns_thread() { start_mdns(); // We will now only set up the normal transport mDNS service // instead of registering all the adb secure mDNS services // in the beginning. This is to provide more privacy/security. register_base_mdns_transport(); } // This also tears down any adb secure mDNS services, if they exist. static void teardown_mdns() { for (int i = 0; i < kNumADBDNSServices; ++i) { unregister_mdns_service(i); } } // Public interface///////////////////////////////////////////////////////////// void setup_mdns(int port_in) { void setup_mdns(int port_in) { port = port_in; port = port_in; std::thread(setup_mdns_thread).detach(); std::thread(setup_mdns_thread).detach(); Loading @@ -95,3 +148,33 @@ void setup_mdns(int port_in) { // TODO: Make this more robust against a hard kill. // TODO: Make this more robust against a hard kill. atexit(teardown_mdns); atexit(teardown_mdns); } } void register_adb_secure_pairing_service(int port) { std::thread([port]() { register_mdns_service(kADBSecurePairingServiceRefIndex, port); }).detach(); } void unregister_adb_secure_pairing_service() { std::thread([]() { unregister_mdns_service(kADBSecurePairingServiceRefIndex); }).detach(); } bool is_adb_secure_pairing_service_registered() { std::lock_guard<std::mutex> lock(mdns_lock); return mdns_registered[kADBSecurePairingServiceRefIndex]; } void register_adb_secure_connect_service(int port) { std::thread([port]() { register_mdns_service(kADBSecureConnectServiceRefIndex, port); }).detach(); } void unregister_adb_secure_connect_service() { std::thread([]() { unregister_mdns_service(kADBSecureConnectServiceRefIndex); }).detach(); } bool is_adb_secure_connect_service_registered() { std::lock_guard<std::mutex> lock(mdns_lock); return mdns_registered[kADBSecureConnectServiceRefIndex]; } adb/daemon/mdns.h +8 −0 Original line number Original line Diff line number Diff line Loading @@ -19,4 +19,12 @@ void setup_mdns(int port); void setup_mdns(int port); void register_adb_secure_pairing_service(int port); void unregister_adb_secure_pairing_service(int port); bool is_adb_secure_pairing_service_registered(); void register_adb_secure_connect_service(int port); void unregister_adb_secure_connect_service(int port); bool is_adb_secure_connect_service_registered(); #endif // _DAEMON_MDNS_H_ #endif // _DAEMON_MDNS_H_ Loading
adb/adb_mdns.h +66 −0 Original line number Original line Diff line number Diff line Loading @@ -17,6 +17,72 @@ #ifndef _ADB_MDNS_H_ #ifndef _ADB_MDNS_H_ #define _ADB_MDNS_H_ #define _ADB_MDNS_H_ #include <android-base/macros.h> const char* kADBServiceType = "_adb._tcp"; const char* kADBServiceType = "_adb._tcp"; const char* kADBSecurePairingServiceType = "_adb_secure_pairing._tcp"; const char* kADBSecureConnectServiceType = "_adb_secure_connect._tcp"; const int kADBTransportServiceRefIndex = 0; const int kADBSecurePairingServiceRefIndex = 1; const int kADBSecureConnectServiceRefIndex = 2; // Each ADB Secure service advertises with a TXT record indicating the version // using a key/value pair per RFC 6763 (https://tools.ietf.org/html/rfc6763). // // The first key/value pair is always the version of the protocol. // There may be more key/value pairs added after. // // The version is purposely represented as the single letter "v" due to the // need to minimize DNS traffic. The version starts at 1. With each breaking // protocol change, the version is incremented by 1. // // Newer adb clients/daemons need to recognize and either reject // or be backward-compatible with older verseions if there is a mismatch. // // Relevant sections: // // """ // 6.4. Rules for Keys in DNS-SD Key/Value Pairs // // The key MUST be at least one character. DNS-SD TXT record strings // beginning with an '=' character (i.e., the key is missing) MUST be // silently ignored. // // ... // // 6.5. Rules for Values in DNS-SD Key/Value Pairs // // If there is an '=' in a DNS-SD TXT record string, then everything // after the first '=' to the end of the string is the value. The value // can contain any eight-bit values including '='. // """ #define ADB_SECURE_SERVICE_VERSION_TXT_RECORD(ver) ("v=" #ver) // Client/service versions are initially defined to be matching, // but may go out of sync as different clients and services // try to talk to each other. #define ADB_SECURE_SERVICE_VERSION 1 #define ADB_SECURE_CLIENT_VERSION ADB_SECURE_SERVICE_VERSION const char* kADBSecurePairingServiceTxtRecord = ADB_SECURE_SERVICE_VERSION_TXT_RECORD(ADB_SECURE_SERVICE_VERSION); const char* kADBSecureConnectServiceTxtRecord = ADB_SECURE_SERVICE_VERSION_TXT_RECORD(ADB_SECURE_SERVICE_VERSION); const char* kADBDNSServices[] = { kADBServiceType, kADBSecurePairingServiceType, kADBSecureConnectServiceType, }; const char* kADBDNSServiceTxtRecords[] = { nullptr, kADBSecurePairingServiceTxtRecord, kADBSecureConnectServiceTxtRecord, }; const int kNumADBDNSServices = arraysize(kADBDNSServices); #endif #endif
adb/client/adb_client.h +14 −0 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,7 @@ #pragma once #pragma once #include <functional> #include <optional> #include <optional> #include <string> #include <string> Loading Loading @@ -86,3 +87,16 @@ std::optional<std::string> adb_get_server_executable_path(); // Globally acccesible argv/envp, for the purpose of re-execing adb. // Globally acccesible argv/envp, for the purpose of re-execing adb. extern const char* _Nullable * _Nullable __adb_argv; extern const char* _Nullable * _Nullable __adb_argv; extern const char* _Nullable * _Nullable __adb_envp; extern const char* _Nullable * _Nullable __adb_envp; // ADB Secure DNS service interface. Used to query what ADB Secure DNS services have been // resolved, and to run some kind of callback for each one. using adb_secure_foreach_service_callback = std::function<void( const char* _Nonnull host_name, const char* _Nonnull ip_address, uint16_t port)>; // Queries pairing/connect services that have been discovered and resolved. // If |host_name| is not null, run |cb| only for services // matching |host_name|. Otherwise, run for all services. void adb_secure_foreach_pairing_service(const char* _Nullable host_name, adb_secure_foreach_service_callback cb); void adb_secure_foreach_connect_service(const char* _Nullable host_name, adb_secure_foreach_service_callback cb);
adb/client/transport_mdns.cpp +237 −63 Original line number Original line Diff line number Diff line Loading @@ -25,17 +25,33 @@ #endif #endif #include <thread> #include <thread> #include <vector> #include <android-base/stringprintf.h> #include <android-base/stringprintf.h> #include <dns_sd.h> #include <dns_sd.h> #include "adb_client.h" #include "adb_mdns.h" #include "adb_mdns.h" #include "adb_trace.h" #include "adb_trace.h" #include "fdevent/fdevent.h" #include "fdevent/fdevent.h" #include "sysdeps.h" #include "sysdeps.h" static DNSServiceRef service_ref; static DNSServiceRef service_refs[kNumADBDNSServices]; static fdevent* service_ref_fde; static fdevent* service_ref_fdes[kNumADBDNSServices]; static int adb_DNSServiceIndexByName(const char* regType) { for (int i = 0; i < kNumADBDNSServices; ++i) { if (!strncmp(regType, kADBDNSServices[i], strlen(kADBDNSServices[i]))) { return i; } } return -1; } static bool adb_DNSServiceShouldConnect(const char* regType) { int index = adb_DNSServiceIndexByName(regType); return index == kADBTransportServiceRefIndex; } // Use adb_DNSServiceRefSockFD() instead of calling DNSServiceRefSockFD() // Use adb_DNSServiceRefSockFD() instead of calling DNSServiceRefSockFD() // directly so that the socket is put through the appropriate compatibility // directly so that the socket is put through the appropriate compatibility Loading Loading @@ -94,10 +110,16 @@ class ResolvedService : public AsyncServiceRef { public: public: virtual ~ResolvedService() = default; virtual ~ResolvedService() = default; ResolvedService(std::string name, uint32_t interfaceIndex, ResolvedService(std::string serviceName, std::string regType, uint32_t interfaceIndex, const char* hosttarget, uint16_t port) : const char* hosttarget, uint16_t port, int version) name_(name), : serviceName_(serviceName), port_(port) { regType_(regType), hosttarget_(hosttarget), port_(port), sa_family_(0), ip_addr_data_(NULL), serviceVersion_(version) { memset(ip_addr_, 0, sizeof(ip_addr_)); /* TODO: We should be able to get IPv6 support by adding /* TODO: We should be able to get IPv6 support by adding * kDNSServiceProtocol_IPv6 to the flags below. However, when we do * kDNSServiceProtocol_IPv6 to the flags below. However, when we do Loading @@ -116,20 +138,19 @@ class ResolvedService : public AsyncServiceRef { } else { } else { Initialize(); Initialize(); } } D("Client version: %d Service version: %d\n", clientVersion_, serviceVersion_); } } void Connect(const sockaddr* address) { void Connect(const sockaddr* address) { char ip_addr[INET6_ADDRSTRLEN]; sa_family_ = address->sa_family; const void* ip_addr_data; const char* addr_format; const char* addr_format; if (address->sa_family == AF_INET) { if (sa_family_ == AF_INET) { ip_addr_data = ip_addr_data_ = &reinterpret_cast<const sockaddr_in*>(address)->sin_addr; &reinterpret_cast<const sockaddr_in*>(address)->sin_addr; addr_format = "%s:%hu"; addr_format = "%s:%hu"; } else if (address->sa_family == AF_INET6) { } else if (sa_family_ == AF_INET6) { ip_addr_data = ip_addr_data_ = &reinterpret_cast<const sockaddr_in6*>(address)->sin6_addr; &reinterpret_cast<const sockaddr_in6*>(address)->sin6_addr; addr_format = "[%s]:%hu"; addr_format = "[%s]:%hu"; } else { // Should be impossible } else { // Should be impossible D("mDNS resolved non-IP address."); D("mDNS resolved non-IP address."); Loading @@ -137,24 +158,115 @@ class ResolvedService : public AsyncServiceRef { } } // Winsock version requires the const cast Because Microsoft. // Winsock version requires the const cast Because Microsoft. if (!inet_ntop(address->sa_family, const_cast<void*>(ip_addr_data), if (!inet_ntop(sa_family_, const_cast<void*>(ip_addr_data_), ip_addr_, sizeof(ip_addr_))) { ip_addr, INET6_ADDRSTRLEN)) { D("Could not convert IP address to string."); D("Could not convert IP address to string."); return; return; } } // adb secure service needs to do something different from just // connecting here. if (adb_DNSServiceShouldConnect(regType_.c_str())) { std::string response; std::string response; connect_device(android::base::StringPrintf(addr_format, ip_addr, port_), connect_device(android::base::StringPrintf(addr_format, ip_addr_, port_), &response); &response); D("Connect to %s regtype %s (%s:%hu) : %s", serviceName_.c_str(), regType_.c_str(), D("Connect to %s (%s:%hu) : %s", name_.c_str(), ip_addr, port_, ip_addr_, port_, response.c_str()); response.c_str()); } else { D("Not immediately connecting to serviceName=[%s], regtype=[%s] ipaddr=(%s:%hu)", serviceName_.c_str(), regType_.c_str(), ip_addr_, port_); } int adbSecureServiceType = serviceIndex(); switch (adbSecureServiceType) { case kADBSecurePairingServiceRefIndex: sAdbSecurePairingServices->push_back(this); break; case kADBSecureConnectServiceRefIndex: sAdbSecureConnectServices->push_back(this); break; default: break; } } } int serviceIndex() const { return adb_DNSServiceIndexByName(regType_.c_str()); } std::string hostTarget() const { return hosttarget_; } std::string ipAddress() const { return ip_addr_; } uint16_t port() const { return port_; } using ServiceRegistry = std::vector<ResolvedService*>; static ServiceRegistry* sAdbSecurePairingServices; static ServiceRegistry* sAdbSecureConnectServices; static void initAdbSecure(); static void forEachService(const ServiceRegistry& services, const std::string& hostname, adb_secure_foreach_service_callback cb); private: private: std::string name_; int clientVersion_ = ADB_SECURE_CLIENT_VERSION; std::string serviceName_; std::string regType_; std::string hosttarget_; const uint16_t port_; const uint16_t port_; int sa_family_; const void* ip_addr_data_; char ip_addr_[INET6_ADDRSTRLEN]; int serviceVersion_; }; }; // static std::vector<ResolvedService*>* ResolvedService::sAdbSecurePairingServices = NULL; // static std::vector<ResolvedService*>* ResolvedService::sAdbSecureConnectServices = NULL; // static void ResolvedService::initAdbSecure() { if (!sAdbSecurePairingServices) { sAdbSecurePairingServices = new ServiceRegistry; } if (!sAdbSecureConnectServices) { sAdbSecureConnectServices = new ServiceRegistry; } } // static void ResolvedService::forEachService(const ServiceRegistry& services, const std::string& wanted_host, adb_secure_foreach_service_callback cb) { initAdbSecure(); for (auto service : services) { auto hostname = service->hostTarget(); auto ip = service->ipAddress(); auto port = service->port(); if (wanted_host == "") { cb(hostname.c_str(), ip.c_str(), port); } else if (hostname == wanted_host) { cb(hostname.c_str(), ip.c_str(), port); } } } // static void adb_secure_foreach_pairing_service(const char* host_name, adb_secure_foreach_service_callback cb) { ResolvedService::forEachService(*ResolvedService::sAdbSecurePairingServices, host_name ? host_name : "", cb); } // static void adb_secure_foreach_connect_service(const char* host_name, adb_secure_foreach_service_callback cb) { ResolvedService::forEachService(*ResolvedService::sAdbSecureConnectServices, host_name ? host_name : "", cb); } static void DNSSD_API register_service_ip(DNSServiceRef /*sdRef*/, static void DNSSD_API register_service_ip(DNSServiceRef /*sdRef*/, DNSServiceFlags /*flags*/, DNSServiceFlags /*flags*/, uint32_t /*interfaceIndex*/, uint32_t /*interfaceIndex*/, Loading @@ -167,6 +279,12 @@ static void DNSSD_API register_service_ip(DNSServiceRef /*sdRef*/, std::unique_ptr<ResolvedService> data( std::unique_ptr<ResolvedService> data( reinterpret_cast<ResolvedService*>(context)); reinterpret_cast<ResolvedService*>(context)); data->Connect(address); data->Connect(address); // For ADB Secure services, keep those ResolvedService's around // for later processing with secure connection establishment. if (data->serviceIndex() != kADBTransportServiceRefIndex) { data.release(); } } } static void DNSSD_API register_resolved_mdns_service(DNSServiceRef sdRef, static void DNSSD_API register_resolved_mdns_service(DNSServiceRef sdRef, Loading @@ -182,18 +300,23 @@ static void DNSSD_API register_resolved_mdns_service(DNSServiceRef sdRef, class DiscoveredService : public AsyncServiceRef { class DiscoveredService : public AsyncServiceRef { public: public: DiscoveredService(uint32_t interfaceIndex, const char* serviceName, DiscoveredService(uint32_t interfaceIndex, const char* serviceName, const char* regtype, const char* regtype, const char* domain) const char* domain) : serviceName_(serviceName) { : serviceName_(serviceName), regType_(regtype) { DNSServiceErrorType ret = DNSServiceErrorType ret = DNSServiceResolve(&sdRef_, 0, interfaceIndex, serviceName, regtype, DNSServiceResolve(&sdRef_, 0, interfaceIndex, serviceName, regtype, domain, register_resolved_mdns_service, domain, register_resolved_mdns_service, reinterpret_cast<void*>(this)); reinterpret_cast<void*>(this)); if (ret != kDNSServiceErr_NoError) { D("DNSServiceResolve for " D("Got %d from DNSServiceResolve.", ret); "interfaceIndex %u " } else { "serviceName %s " "regtype %s " "domain %s " ": %d", interfaceIndex, serviceName, regtype, domain, ret); if (ret == kDNSServiceErr_NoError) { Initialize(); Initialize(); } } } } Loading @@ -202,20 +325,62 @@ class DiscoveredService : public AsyncServiceRef { return serviceName_.c_str(); return serviceName_.c_str(); } } const char* RegType() { return regType_.c_str(); } private: private: std::string serviceName_; std::string serviceName_; std::string regType_; }; }; static void DNSSD_API register_resolved_mdns_service(DNSServiceRef sdRef, // Returns the version the device wanted to advertise, DNSServiceFlags flags, // or -1 if parsing fails. uint32_t interfaceIndex, static int parse_version_from_txt_record(uint16_t txtLen, const unsigned char* txtRecord) { DNSServiceErrorType errorCode, if (!txtLen) return -1; const char* fullname, if (!txtRecord) return -1; const char* hosttarget, uint16_t port, // https://tools.ietf.org/html/rfc6763 uint16_t /*txtLen*/, // """ const unsigned char* /*txtRecord*/, // 6.1. General Format Rules for DNS TXT Records void* context) { // // A DNS TXT record can be up to 65535 (0xFFFF) bytes long. The total // length is indicated by the length given in the resource record header // in the DNS message. There is no way to tell directly from the data // alone how long it is (e.g., there is no length count at the start, or // terminating NULL byte at the end). // """ // Let's trust the TXT record's length byte // Worst case, it wastes 255 bytes std::vector<char> recordAsString(txtLen + 1, '\0'); char* str = recordAsString.data(); memcpy(str, txtRecord + 1 /* skip the length byte */, txtLen); // Check if it's the version key static const char* versionKey = "v="; size_t versionKeyLen = strlen(versionKey); if (strncmp(versionKey, str, versionKeyLen)) return -1; auto valueStart = str + versionKeyLen; long parsedNumber = strtol(valueStart, 0, 10); // No valid conversion. Also, 0 // is not a valid version. if (!parsedNumber) return -1; // Outside bounds of long. if (parsedNumber == LONG_MIN || parsedNumber == LONG_MAX) return -1; // Possibly valid version return static_cast<int>(parsedNumber); } static void DNSSD_API register_resolved_mdns_service( DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char* fullname, const char* hosttarget, uint16_t port, uint16_t txtLen, const unsigned char* txtRecord, void* context) { D("Resolved a service."); D("Resolved a service."); std::unique_ptr<DiscoveredService> discovered( std::unique_ptr<DiscoveredService> discovered( reinterpret_cast<DiscoveredService*>(context)); reinterpret_cast<DiscoveredService*>(context)); Loading @@ -225,10 +390,14 @@ static void DNSSD_API register_resolved_mdns_service(DNSServiceRef sdRef, return; return; } } // TODO: Reject certain combinations of invalid or mismatched client and // service versions here before creating anything. // At the moment, there is nothing to reject, so accept everything // as an optimistic default. auto serviceVersion = parse_version_from_txt_record(txtLen, txtRecord); auto resolved = auto resolved = new ResolvedService(discovered->ServiceName(), discovered->RegType(), new ResolvedService(discovered->ServiceName(), interfaceIndex, hosttarget, ntohs(port), serviceVersion); interfaceIndex, hosttarget, ntohs(port)); if (! resolved->Initialized()) { if (! resolved->Initialized()) { delete resolved; delete resolved; Loading @@ -239,19 +408,18 @@ static void DNSSD_API register_resolved_mdns_service(DNSServiceRef sdRef, } } } } static void DNSSD_API register_mdns_transport(DNSServiceRef sdRef, static void DNSSD_API on_service_browsed(DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, uint32_t interfaceIndex, const char* serviceName, const char* regtype, DNSServiceErrorType errorCode, const char* domain, void* /*context*/) { const char* serviceName, const char* regtype, const char* domain, void* /*context*/) { D("Registering a transport."); D("Registering a transport."); if (errorCode != kDNSServiceErr_NoError) { if (errorCode != kDNSServiceErr_NoError) { D("Got error %d during mDNS browse.", errorCode); D("Got error %d during mDNS browse.", errorCode); DNSServiceRefDeallocate(sdRef); DNSServiceRefDeallocate(sdRef); fdevent_destroy(service_ref_fde); int serviceIndex = adb_DNSServiceIndexByName(regtype); if (serviceIndex != -1) { fdevent_destroy(service_ref_fdes[serviceIndex]); } return; return; } } Loading @@ -262,21 +430,27 @@ static void DNSSD_API register_mdns_transport(DNSServiceRef sdRef, } } void init_mdns_transport_discovery_thread(void) { void init_mdns_transport_discovery_thread(void) { DNSServiceErrorType errorCode = DNSServiceBrowse(&service_ref, 0, 0, kADBServiceType, nullptr, int errorCodes[kNumADBDNSServices]; register_mdns_transport, nullptr); if (errorCode != kDNSServiceErr_NoError) { for (int i = 0; i < kNumADBDNSServices; ++i) { D("Got %d initiating mDNS browse.", errorCode); errorCodes[i] = DNSServiceBrowse(&service_refs[i], 0, 0, kADBDNSServices[i], nullptr, return; on_service_browsed, nullptr); if (errorCodes[i] != kDNSServiceErr_NoError) { D("Got %d browsing for mDNS service %s.", errorCodes[i], kADBDNSServices[i]); } } fdevent_run_on_main_thread([]() { if (errorCodes[i] == kDNSServiceErr_NoError) { service_ref_fde = fdevent_run_on_main_thread([i]() { fdevent_create(adb_DNSServiceRefSockFD(service_ref), pump_service_ref, &service_ref); service_ref_fdes[i] = fdevent_create(adb_DNSServiceRefSockFD(service_refs[i]), fdevent_set(service_ref_fde, FDE_READ); pump_service_ref, &service_refs[i]); fdevent_set(service_ref_fdes[i], FDE_READ); }); }); } } } } void init_mdns_transport_discovery(void) { void init_mdns_transport_discovery(void) { ResolvedService::initAdbSecure(); std::thread(init_mdns_transport_discovery_thread).detach(); std::thread(init_mdns_transport_discovery_thread).detach(); } }
adb/daemon/mdns.cpp +97 −14 Original line number Original line Diff line number Diff line Loading @@ -14,6 +14,7 @@ * limitations under the License. * limitations under the License. */ */ #include "mdns.h" #include "adb_mdns.h" #include "adb_mdns.h" #include "sysdeps.h" #include "sysdeps.h" Loading @@ -32,8 +33,8 @@ using namespace std::chrono_literals; static std::mutex& mdns_lock = *new std::mutex(); static std::mutex& mdns_lock = *new std::mutex(); static int port; static int port; static DNSServiceRef mdns_ref; static DNSServiceRef mdns_refs[kNumADBDNSServices]; static bool mdns_registered = false; static bool mdns_registered[kNumADBDNSServices]; static void start_mdns() { static void start_mdns() { if (android::base::GetProperty("init.svc.mdnsd", "") == "running") { if (android::base::GetProperty("init.svc.mdnsd", "") == "running") { Loading @@ -60,34 +61,86 @@ static void mdns_callback(DNSServiceRef /*ref*/, } } } } static void setup_mdns_thread() { static void register_mdns_service(int index, int port) { start_mdns(); std::lock_guard<std::mutex> lock(mdns_lock); std::lock_guard<std::mutex> lock(mdns_lock); std::string hostname = "adb-"; std::string hostname = "adb-"; hostname += android::base::GetProperty("ro.serialno", "unidentified"); hostname += android::base::GetProperty("ro.serialno", "unidentified"); auto error = DNSServiceRegister(&mdns_ref, 0, 0, hostname.c_str(), // https://tools.ietf.org/html/rfc6763 kADBServiceType, nullptr, nullptr, // """ htobe16((uint16_t)port), 0, nullptr, // The format of the data within a DNS TXT record is one or more mdns_callback, nullptr); // strings, packed together in memory without any intervening gaps or // padding bytes for word alignment. // // The format of each constituent string within the DNS TXT record is a // single length byte, followed by 0-255 bytes of text data. // """ // // Therefore: // 1. Begin with the string length // 2. No null termination std::vector<char> txtRecord; if (kADBDNSServiceTxtRecords[index]) { size_t txtRecordStringLength = strlen(kADBDNSServiceTxtRecords[index]); txtRecord.resize(1 + // length byte txtRecordStringLength // string bytes ); txtRecord[0] = (char)txtRecordStringLength; memcpy(txtRecord.data() + 1, kADBDNSServiceTxtRecords[index], txtRecordStringLength); } auto error = DNSServiceRegister( &mdns_refs[index], 0, 0, hostname.c_str(), kADBDNSServices[index], nullptr, nullptr, htobe16((uint16_t)port), (uint16_t)txtRecord.size(), txtRecord.empty() ? nullptr : txtRecord.data(), mdns_callback, nullptr); if (error != kDNSServiceErr_NoError) { if (error != kDNSServiceErr_NoError) { LOG(ERROR) << "Could not register mDNS service (" << error << ")."; LOG(ERROR) << "Could not register mDNS service " << kADBDNSServices[index] << ", error (" return; << error << ")."; mdns_registered[index] = false; } } mdns_registered = true; mdns_registered[index] = true; LOG(INFO) << "adbd mDNS service " << kADBDNSServices[index] << " registered: " << mdns_registered[index]; } } static void teardown_mdns() { static void unregister_mdns_service(int index) { std::lock_guard<std::mutex> lock(mdns_lock); std::lock_guard<std::mutex> lock(mdns_lock); if (mdns_registered) { if (mdns_registered[index]) { DNSServiceRefDeallocate(mdns_ref); DNSServiceRefDeallocate(mdns_refs[index]); } } } } static void register_base_mdns_transport() { register_mdns_service(kADBTransportServiceRefIndex, port); } static void setup_mdns_thread() { start_mdns(); // We will now only set up the normal transport mDNS service // instead of registering all the adb secure mDNS services // in the beginning. This is to provide more privacy/security. register_base_mdns_transport(); } // This also tears down any adb secure mDNS services, if they exist. static void teardown_mdns() { for (int i = 0; i < kNumADBDNSServices; ++i) { unregister_mdns_service(i); } } // Public interface///////////////////////////////////////////////////////////// void setup_mdns(int port_in) { void setup_mdns(int port_in) { port = port_in; port = port_in; std::thread(setup_mdns_thread).detach(); std::thread(setup_mdns_thread).detach(); Loading @@ -95,3 +148,33 @@ void setup_mdns(int port_in) { // TODO: Make this more robust against a hard kill. // TODO: Make this more robust against a hard kill. atexit(teardown_mdns); atexit(teardown_mdns); } } void register_adb_secure_pairing_service(int port) { std::thread([port]() { register_mdns_service(kADBSecurePairingServiceRefIndex, port); }).detach(); } void unregister_adb_secure_pairing_service() { std::thread([]() { unregister_mdns_service(kADBSecurePairingServiceRefIndex); }).detach(); } bool is_adb_secure_pairing_service_registered() { std::lock_guard<std::mutex> lock(mdns_lock); return mdns_registered[kADBSecurePairingServiceRefIndex]; } void register_adb_secure_connect_service(int port) { std::thread([port]() { register_mdns_service(kADBSecureConnectServiceRefIndex, port); }).detach(); } void unregister_adb_secure_connect_service() { std::thread([]() { unregister_mdns_service(kADBSecureConnectServiceRefIndex); }).detach(); } bool is_adb_secure_connect_service_registered() { std::lock_guard<std::mutex> lock(mdns_lock); return mdns_registered[kADBSecureConnectServiceRefIndex]; }
adb/daemon/mdns.h +8 −0 Original line number Original line Diff line number Diff line Loading @@ -19,4 +19,12 @@ void setup_mdns(int port); void setup_mdns(int port); void register_adb_secure_pairing_service(int port); void unregister_adb_secure_pairing_service(int port); bool is_adb_secure_pairing_service_registered(); void register_adb_secure_connect_service(int port); void unregister_adb_secure_connect_service(int port); bool is_adb_secure_connect_service_registered(); #endif // _DAEMON_MDNS_H_ #endif // _DAEMON_MDNS_H_