blob: c1e766eba424a2487867010f8846780ba975acef [file] [log] [blame]
Casey Dahlin10ad15f2016-05-06 16:19:13 -07001/*
2 * Copyright (C) 2016 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
Lingfeng Yang8447ed92018-11-28 16:38:36 -080017#include "mdns.h"
Casey Dahlin3122cdf2016-06-23 14:19:37 -070018#include "adb_mdns.h"
Casey Dahlin10ad15f2016-05-06 16:19:13 -070019#include "sysdeps.h"
20
Casey Dahlin10ad15f2016-05-06 16:19:13 -070021#include <dns_sd.h>
22#include <endian.h>
Casey Dahlin10ad15f2016-05-06 16:19:13 -070023#include <unistd.h>
24
Josh Gao0f3312a2017-04-12 17:00:49 -070025#include <chrono>
26#include <mutex>
Joshua Duong290ccb52019-11-20 14:18:43 -080027#include <random>
Josh Gao0f3312a2017-04-12 17:00:49 -070028#include <thread>
29
Casey Dahlin10ad15f2016-05-06 16:19:13 -070030#include <android-base/logging.h>
31#include <android-base/properties.h>
32
33using namespace std::chrono_literals;
34
35static std::mutex& mdns_lock = *new std::mutex();
36static int port;
Lingfeng Yangf44871a2018-11-16 22:47:31 -080037static DNSServiceRef mdns_refs[kNumADBDNSServices];
38static bool mdns_registered[kNumADBDNSServices];
Casey Dahlin10ad15f2016-05-06 16:19:13 -070039
Joshua Duong290ccb52019-11-20 14:18:43 -080040void start_mdnsd() {
Casey Dahlin10ad15f2016-05-06 16:19:13 -070041 if (android::base::GetProperty("init.svc.mdnsd", "") == "running") {
42 return;
43 }
44
45 android::base::SetProperty("ctl.start", "mdnsd");
46
47 if (! android::base::WaitForProperty("init.svc.mdnsd", "running", 5s)) {
48 LOG(ERROR) << "Could not start mdnsd.";
49 }
50}
51
52static void mdns_callback(DNSServiceRef /*ref*/,
53 DNSServiceFlags /*flags*/,
54 DNSServiceErrorType errorCode,
55 const char* /*name*/,
56 const char* /*regtype*/,
57 const char* /*domain*/,
58 void* /*context*/) {
59 if (errorCode != kDNSServiceErr_NoError) {
60 LOG(ERROR) << "Encountered mDNS registration error ("
61 << errorCode << ").";
62 }
63}
64
Joshua Duong290ccb52019-11-20 14:18:43 -080065static void register_mdns_service(int index, int port, const std::string service_name) {
Casey Dahlin10ad15f2016-05-06 16:19:13 -070066 std::lock_guard<std::mutex> lock(mdns_lock);
67
Casey Dahlin50b39b42016-05-20 16:34:51 -070068
Lingfeng Yang48bdec72019-10-24 22:30:11 -070069 // https://tools.ietf.org/html/rfc6763
70 // """
71 // The format of the data within a DNS TXT record is one or more
72 // strings, packed together in memory without any intervening gaps or
73 // padding bytes for word alignment.
74 //
75 // The format of each constituent string within the DNS TXT record is a
76 // single length byte, followed by 0-255 bytes of text data.
77 // """
78 //
79 // Therefore:
80 // 1. Begin with the string length
81 // 2. No null termination
82
83 std::vector<char> txtRecord;
84
85 if (kADBDNSServiceTxtRecords[index]) {
86 size_t txtRecordStringLength = strlen(kADBDNSServiceTxtRecords[index]);
87
88 txtRecord.resize(1 + // length byte
89 txtRecordStringLength // string bytes
90 );
91
92 txtRecord[0] = (char)txtRecordStringLength;
93 memcpy(txtRecord.data() + 1, kADBDNSServiceTxtRecords[index], txtRecordStringLength);
94 }
95
96 auto error = DNSServiceRegister(
Joshua Duong290ccb52019-11-20 14:18:43 -080097 &mdns_refs[index], 0, 0, service_name.c_str(), kADBDNSServices[index], nullptr, nullptr,
Lingfeng Yang48bdec72019-10-24 22:30:11 -070098 htobe16((uint16_t)port), (uint16_t)txtRecord.size(),
99 txtRecord.empty() ? nullptr : txtRecord.data(), mdns_callback, nullptr);
Casey Dahlin10ad15f2016-05-06 16:19:13 -0700100
Lingfeng Yang8447ed92018-11-28 16:38:36 -0800101 if (error != kDNSServiceErr_NoError) {
102 LOG(ERROR) << "Could not register mDNS service " << kADBDNSServices[index] << ", error ("
103 << error << ").";
104 mdns_registered[index] = false;
Casey Dahlin10ad15f2016-05-06 16:19:13 -0700105 }
106
Lingfeng Yang8447ed92018-11-28 16:38:36 -0800107 mdns_registered[index] = true;
108
109 LOG(INFO) << "adbd mDNS service " << kADBDNSServices[index]
110 << " registered: " << mdns_registered[index];
Casey Dahlin10ad15f2016-05-06 16:19:13 -0700111}
112
Lingfeng Yang8447ed92018-11-28 16:38:36 -0800113static void unregister_mdns_service(int index) {
Casey Dahlin10ad15f2016-05-06 16:19:13 -0700114 std::lock_guard<std::mutex> lock(mdns_lock);
115
Lingfeng Yang8447ed92018-11-28 16:38:36 -0800116 if (mdns_registered[index]) {
117 DNSServiceRefDeallocate(mdns_refs[index]);
Casey Dahlin10ad15f2016-05-06 16:19:13 -0700118 }
119}
120
Lingfeng Yang8447ed92018-11-28 16:38:36 -0800121static void register_base_mdns_transport() {
Joshua Duong290ccb52019-11-20 14:18:43 -0800122 std::string hostname = "adb-";
123 hostname += android::base::GetProperty("ro.serialno", "unidentified");
124 register_mdns_service(kADBTransportServiceRefIndex, port, hostname);
Lingfeng Yang8447ed92018-11-28 16:38:36 -0800125}
126
127static void setup_mdns_thread() {
Joshua Duong290ccb52019-11-20 14:18:43 -0800128 start_mdnsd();
Lingfeng Yang8447ed92018-11-28 16:38:36 -0800129
130 // We will now only set up the normal transport mDNS service
131 // instead of registering all the adb secure mDNS services
132 // in the beginning. This is to provide more privacy/security.
133 register_base_mdns_transport();
134}
135
136// This also tears down any adb secure mDNS services, if they exist.
137static void teardown_mdns() {
138 for (int i = 0; i < kNumADBDNSServices; ++i) {
139 unregister_mdns_service(i);
140 }
141}
142
Joshua Duong290ccb52019-11-20 14:18:43 -0800143static std::string RandomAlphaNumString(size_t len) {
144 std::string ret;
145 std::random_device rd;
146 std::mt19937 mt(rd());
147 // Generate values starting with zero and then up to enough to cover numeric
148 // digits, small letters and capital letters (26 each).
149 std::uniform_int_distribution<uint8_t> dist(0, 61);
150 for (size_t i = 0; i < len; ++i) {
151 uint8_t val = dist(mt);
152 if (val < 10) {
Chih-Hung Hsieh2e8962b2020-03-09 14:22:16 -0700153 ret += static_cast<char>('0' + val);
Joshua Duong290ccb52019-11-20 14:18:43 -0800154 } else if (val < 36) {
Chih-Hung Hsieh2e8962b2020-03-09 14:22:16 -0700155 ret += static_cast<char>('A' + (val - 10));
Joshua Duong290ccb52019-11-20 14:18:43 -0800156 } else {
Chih-Hung Hsieh2e8962b2020-03-09 14:22:16 -0700157 ret += static_cast<char>('a' + (val - 36));
Joshua Duong290ccb52019-11-20 14:18:43 -0800158 }
159 }
160 return ret;
161}
162
163static std::string GenerateDeviceGuid() {
164 // The format is adb-<serial_no>-<six-random-alphanum>
165 std::string guid = "adb-";
166
167 std::string serial = android::base::GetProperty("ro.serialno", "");
168 if (serial.empty()) {
169 // Generate 16-bytes of random alphanum string
170 serial = RandomAlphaNumString(16);
171 }
172 guid += serial + '-';
173 // Random six-char suffix
174 guid += RandomAlphaNumString(6);
175 return guid;
176}
177
178static std::string ReadDeviceGuid() {
179 std::string guid = android::base::GetProperty("persist.adb.wifi.guid", "");
180 if (guid.empty()) {
181 guid = GenerateDeviceGuid();
182 CHECK(!guid.empty());
183 android::base::SetProperty("persist.adb.wifi.guid", guid);
184 }
185 return guid;
186}
187
Lingfeng Yang8447ed92018-11-28 16:38:36 -0800188// Public interface/////////////////////////////////////////////////////////////
189
Casey Dahlin10ad15f2016-05-06 16:19:13 -0700190void setup_mdns(int port_in) {
Joshua Duong290ccb52019-11-20 14:18:43 -0800191 // Make sure the adb wifi guid is generated.
192 std::string guid = ReadDeviceGuid();
193 CHECK(!guid.empty());
Casey Dahlin10ad15f2016-05-06 16:19:13 -0700194 port = port_in;
Josh Gao0f3312a2017-04-12 17:00:49 -0700195 std::thread(setup_mdns_thread).detach();
Casey Dahlin10ad15f2016-05-06 16:19:13 -0700196
197 // TODO: Make this more robust against a hard kill.
198 atexit(teardown_mdns);
199}
Lingfeng Yang8447ed92018-11-28 16:38:36 -0800200
Lingfeng Yang8447ed92018-11-28 16:38:36 -0800201void register_adb_secure_connect_service(int port) {
202 std::thread([port]() {
Joshua Duong290ccb52019-11-20 14:18:43 -0800203 auto service_name = ReadDeviceGuid();
204 if (service_name.empty()) {
205 return;
206 }
207 LOG(INFO) << "Registering secure_connect service (" << service_name << ")";
208 register_mdns_service(kADBSecureConnectServiceRefIndex, port, service_name);
Lingfeng Yang8447ed92018-11-28 16:38:36 -0800209 }).detach();
210}
211
212void unregister_adb_secure_connect_service() {
213 std::thread([]() { unregister_mdns_service(kADBSecureConnectServiceRefIndex); }).detach();
214}
215
216bool is_adb_secure_connect_service_registered() {
217 std::lock_guard<std::mutex> lock(mdns_lock);
218 return mdns_registered[kADBSecureConnectServiceRefIndex];
219}