blob: fa98340b5ecbf80cb8a68855819f5cb85e59ed78 [file] [log] [blame]
Casey Dahlin6cd5e0b2016-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 Yang615036f2018-11-28 16:38:36 -080017#include "mdns.h"
Casey Dahlin13a269e2016-06-23 14:19:37 -070018#include "adb_mdns.h"
Casey Dahlin6cd5e0b2016-05-06 16:19:13 -070019#include "sysdeps.h"
20
Casey Dahlin6cd5e0b2016-05-06 16:19:13 -070021#include <dns_sd.h>
22#include <endian.h>
Casey Dahlin6cd5e0b2016-05-06 16:19:13 -070023#include <unistd.h>
24
Josh Gaoe1dacfc2017-04-12 17:00:49 -070025#include <chrono>
26#include <mutex>
27#include <thread>
28
Casey Dahlin6cd5e0b2016-05-06 16:19:13 -070029#include <android-base/logging.h>
30#include <android-base/properties.h>
31
32using namespace std::chrono_literals;
33
34static std::mutex& mdns_lock = *new std::mutex();
35static int port;
Lingfeng Yangbe49d8a2018-11-16 22:47:31 -080036static DNSServiceRef mdns_refs[kNumADBDNSServices];
37static bool mdns_registered[kNumADBDNSServices];
Casey Dahlin6cd5e0b2016-05-06 16:19:13 -070038
39static void start_mdns() {
40 if (android::base::GetProperty("init.svc.mdnsd", "") == "running") {
41 return;
42 }
43
44 android::base::SetProperty("ctl.start", "mdnsd");
45
46 if (! android::base::WaitForProperty("init.svc.mdnsd", "running", 5s)) {
47 LOG(ERROR) << "Could not start mdnsd.";
48 }
49}
50
51static void mdns_callback(DNSServiceRef /*ref*/,
52 DNSServiceFlags /*flags*/,
53 DNSServiceErrorType errorCode,
54 const char* /*name*/,
55 const char* /*regtype*/,
56 const char* /*domain*/,
57 void* /*context*/) {
58 if (errorCode != kDNSServiceErr_NoError) {
59 LOG(ERROR) << "Encountered mDNS registration error ("
60 << errorCode << ").";
61 }
62}
63
Lingfeng Yang615036f2018-11-28 16:38:36 -080064static void register_mdns_service(int index, int port) {
Casey Dahlin6cd5e0b2016-05-06 16:19:13 -070065 std::lock_guard<std::mutex> lock(mdns_lock);
66
Casey Dahlin1fe3cae2016-05-20 16:34:51 -070067 std::string hostname = "adb-";
68 hostname += android::base::GetProperty("ro.serialno", "unidentified");
69
Lingfeng Yang39e54b82019-10-24 22:30:11 -070070 // https://tools.ietf.org/html/rfc6763
71 // """
72 // The format of the data within a DNS TXT record is one or more
73 // strings, packed together in memory without any intervening gaps or
74 // padding bytes for word alignment.
75 //
76 // The format of each constituent string within the DNS TXT record is a
77 // single length byte, followed by 0-255 bytes of text data.
78 // """
79 //
80 // Therefore:
81 // 1. Begin with the string length
82 // 2. No null termination
83
84 std::vector<char> txtRecord;
85
86 if (kADBDNSServiceTxtRecords[index]) {
87 size_t txtRecordStringLength = strlen(kADBDNSServiceTxtRecords[index]);
88
89 txtRecord.resize(1 + // length byte
90 txtRecordStringLength // string bytes
91 );
92
93 txtRecord[0] = (char)txtRecordStringLength;
94 memcpy(txtRecord.data() + 1, kADBDNSServiceTxtRecords[index], txtRecordStringLength);
95 }
96
97 auto error = DNSServiceRegister(
98 &mdns_refs[index], 0, 0, hostname.c_str(), kADBDNSServices[index], nullptr, nullptr,
99 htobe16((uint16_t)port), (uint16_t)txtRecord.size(),
100 txtRecord.empty() ? nullptr : txtRecord.data(), mdns_callback, nullptr);
Casey Dahlin6cd5e0b2016-05-06 16:19:13 -0700101
Lingfeng Yang615036f2018-11-28 16:38:36 -0800102 if (error != kDNSServiceErr_NoError) {
103 LOG(ERROR) << "Could not register mDNS service " << kADBDNSServices[index] << ", error ("
104 << error << ").";
105 mdns_registered[index] = false;
Casey Dahlin6cd5e0b2016-05-06 16:19:13 -0700106 }
107
Lingfeng Yang615036f2018-11-28 16:38:36 -0800108 mdns_registered[index] = true;
109
110 LOG(INFO) << "adbd mDNS service " << kADBDNSServices[index]
111 << " registered: " << mdns_registered[index];
Casey Dahlin6cd5e0b2016-05-06 16:19:13 -0700112}
113
Lingfeng Yang615036f2018-11-28 16:38:36 -0800114static void unregister_mdns_service(int index) {
Casey Dahlin6cd5e0b2016-05-06 16:19:13 -0700115 std::lock_guard<std::mutex> lock(mdns_lock);
116
Lingfeng Yang615036f2018-11-28 16:38:36 -0800117 if (mdns_registered[index]) {
118 DNSServiceRefDeallocate(mdns_refs[index]);
Casey Dahlin6cd5e0b2016-05-06 16:19:13 -0700119 }
120}
121
Lingfeng Yang615036f2018-11-28 16:38:36 -0800122static void register_base_mdns_transport() {
123 register_mdns_service(kADBTransportServiceRefIndex, port);
124}
125
126static void setup_mdns_thread() {
127 start_mdns();
128
129 // We will now only set up the normal transport mDNS service
130 // instead of registering all the adb secure mDNS services
131 // in the beginning. This is to provide more privacy/security.
132 register_base_mdns_transport();
133}
134
135// This also tears down any adb secure mDNS services, if they exist.
136static void teardown_mdns() {
137 for (int i = 0; i < kNumADBDNSServices; ++i) {
138 unregister_mdns_service(i);
139 }
140}
141
142// Public interface/////////////////////////////////////////////////////////////
143
Casey Dahlin6cd5e0b2016-05-06 16:19:13 -0700144void setup_mdns(int port_in) {
145 port = port_in;
Josh Gaoe1dacfc2017-04-12 17:00:49 -0700146 std::thread(setup_mdns_thread).detach();
Casey Dahlin6cd5e0b2016-05-06 16:19:13 -0700147
148 // TODO: Make this more robust against a hard kill.
149 atexit(teardown_mdns);
150}
Lingfeng Yang615036f2018-11-28 16:38:36 -0800151
152void register_adb_secure_pairing_service(int port) {
153 std::thread([port]() {
154 register_mdns_service(kADBSecurePairingServiceRefIndex, port);
155 }).detach();
156}
157
158void unregister_adb_secure_pairing_service() {
159 std::thread([]() { unregister_mdns_service(kADBSecurePairingServiceRefIndex); }).detach();
160}
161
162bool is_adb_secure_pairing_service_registered() {
163 std::lock_guard<std::mutex> lock(mdns_lock);
164 return mdns_registered[kADBSecurePairingServiceRefIndex];
165}
166
167void register_adb_secure_connect_service(int port) {
168 std::thread([port]() {
169 register_mdns_service(kADBSecureConnectServiceRefIndex, port);
170 }).detach();
171}
172
173void unregister_adb_secure_connect_service() {
174 std::thread([]() { unregister_mdns_service(kADBSecureConnectServiceRefIndex); }).detach();
175}
176
177bool is_adb_secure_connect_service_registered() {
178 std::lock_guard<std::mutex> lock(mdns_lock);
179 return mdns_registered[kADBSecureConnectServiceRefIndex];
180}