MDnsSdListener.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756
  1. /*
  2. * Copyright (C) 2010 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. #include "MDnsSdListener.h"
  17. #include <arpa/inet.h>
  18. #include <dirent.h>
  19. #include <errno.h>
  20. #include <linux/if.h>
  21. #include <netdb.h>
  22. #include <netinet/in.h>
  23. #include <pthread.h>
  24. #include <resolv.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <sys/poll.h>
  28. #include <sys/socket.h>
  29. #include <sys/types.h>
  30. #define LOG_TAG "MDnsDS"
  31. #define DBG 1
  32. #define VDBG 1
  33. #include <cutils/properties.h>
  34. #include <log/log.h>
  35. #include <netdutils/ResponseCode.h>
  36. #include <netdutils/ThreadUtil.h>
  37. #include <sysutils/SocketClient.h>
  38. #define MDNS_SERVICE_NAME "mdnsd"
  39. #define MDNS_SERVICE_STATUS "init.svc.mdnsd"
  40. #define CEIL(x, y) (((x) + (y) - 1) / (y))
  41. constexpr char RESCAN[] = "1";
  42. using android::netdutils::ResponseCode;
  43. MDnsSdListener::MDnsSdListener() : FrameworkListener(SOCKET_NAME, true) {
  44. Monitor *m = new Monitor();
  45. registerCmd(new Handler(m, this));
  46. }
  47. MDnsSdListener::Handler::Handler(Monitor *m, MDnsSdListener *listener) :
  48. NetdCommand("mdnssd") {
  49. if (DBG) ALOGD("MDnsSdListener::Hander starting up");
  50. mMonitor = m;
  51. mListener = listener;
  52. }
  53. MDnsSdListener::Handler::~Handler() {}
  54. void MDnsSdListener::Handler::discover(SocketClient *cli,
  55. const char *iface,
  56. const char *regType,
  57. const char *domain,
  58. const int requestId,
  59. const int requestFlags) {
  60. if (VDBG) {
  61. ALOGD("discover(%s, %s, %s, %d, %d)", iface, regType, domain, requestId,
  62. requestFlags);
  63. }
  64. Context *context = new Context(requestId, mListener);
  65. DNSServiceRef *ref = mMonitor->allocateServiceRef(requestId, context);
  66. if (ref == nullptr) {
  67. ALOGE("requestId %d already in use during discover call", requestId);
  68. cli->sendMsg(ResponseCode::CommandParameterError,
  69. "RequestId already in use during discover call", false);
  70. return;
  71. }
  72. if (VDBG) ALOGD("using ref %p", ref);
  73. DNSServiceFlags nativeFlags = iToFlags(requestFlags);
  74. int interfaceInt = ifaceNameToI(iface);
  75. DNSServiceErrorType result = DNSServiceBrowse(ref, nativeFlags, interfaceInt, regType,
  76. domain, &MDnsSdListenerDiscoverCallback, context);
  77. if (result != kDNSServiceErr_NoError) {
  78. ALOGE("Discover request %d got an error from DNSServiceBrowse %d", requestId, result);
  79. mMonitor->freeServiceRef(requestId);
  80. cli->sendMsg(ResponseCode::CommandParameterError,
  81. "Discover request got an error from DNSServiceBrowse", false);
  82. return;
  83. }
  84. mMonitor->startMonitoring(requestId);
  85. if (VDBG) ALOGD("discover successful");
  86. cli->sendMsg(ResponseCode::CommandOkay, "Discover operation started", false);
  87. return;
  88. }
  89. void MDnsSdListenerDiscoverCallback(DNSServiceRef /* sdRef */, DNSServiceFlags flags,
  90. uint32_t /* interfaceIndex */, DNSServiceErrorType errorCode, const char *serviceName,
  91. const char *regType, const char *replyDomain, void *inContext) {
  92. MDnsSdListener::Context *context = reinterpret_cast<MDnsSdListener::Context *>(inContext);
  93. char *msg;
  94. int refNumber = context->mRefNumber;
  95. if (errorCode != kDNSServiceErr_NoError) {
  96. asprintf(&msg, "%d %d", refNumber, errorCode);
  97. context->mListener->sendBroadcast(ResponseCode::ServiceDiscoveryFailed, msg, false);
  98. if (DBG) ALOGE("discover failure for %d, error= %d", refNumber, errorCode);
  99. } else {
  100. int respCode;
  101. char *quotedServiceName = SocketClient::quoteArg(serviceName);
  102. if (flags & kDNSServiceFlagsAdd) {
  103. if (VDBG) {
  104. ALOGD("Discover found new serviceName %s, regType %s and domain %s for %d",
  105. serviceName, regType, replyDomain, refNumber);
  106. }
  107. respCode = ResponseCode::ServiceDiscoveryServiceAdded;
  108. } else {
  109. if (VDBG) {
  110. ALOGD("Discover lost serviceName %s, regType %s and domain %s for %d",
  111. serviceName, regType, replyDomain, refNumber);
  112. }
  113. respCode = ResponseCode::ServiceDiscoveryServiceRemoved;
  114. }
  115. asprintf(&msg, "%d %s %s %s", refNumber, quotedServiceName, regType, replyDomain);
  116. free(quotedServiceName);
  117. context->mListener->sendBroadcast(respCode, msg, false);
  118. }
  119. free(msg);
  120. }
  121. void MDnsSdListener::Handler::stop(SocketClient *cli, int argc, char **argv, const char *str) {
  122. if (argc != 3) {
  123. char *msg;
  124. asprintf(&msg, "Invalid number of arguments to %s", str);
  125. cli->sendMsg(ResponseCode::CommandParameterError, msg, false);
  126. free(msg);
  127. return;
  128. }
  129. int requestId = strtol(argv[2], nullptr, 10);
  130. DNSServiceRef *ref = mMonitor->lookupServiceRef(requestId);
  131. if (ref == nullptr) {
  132. if (DBG) ALOGE("%s stop used unknown requestId %d", str, requestId);
  133. cli->sendMsg(ResponseCode::CommandParameterError, "Unknown requestId", false);
  134. return;
  135. }
  136. if (VDBG) ALOGD("Stopping %s with ref %p", str, ref);
  137. mMonitor->deallocateServiceRef(ref);
  138. mMonitor->freeServiceRef(requestId);
  139. char *msg;
  140. asprintf(&msg, "%s stopped", str);
  141. cli->sendMsg(ResponseCode::CommandOkay, msg, false);
  142. free(msg);
  143. }
  144. void MDnsSdListener::Handler::serviceRegister(SocketClient *cli, int requestId,
  145. const char *interfaceName, const char *serviceName, const char *serviceType,
  146. const char *domain, const char *host, int port, int txtLen, void *txtRecord) {
  147. if (VDBG) {
  148. ALOGD("serviceRegister(%d, %s, %s, %s, %s, %s, %d, %d, <binary>)", requestId,
  149. interfaceName, serviceName, serviceType, domain, host, port, txtLen);
  150. }
  151. Context *context = new Context(requestId, mListener);
  152. DNSServiceRef *ref = mMonitor->allocateServiceRef(requestId, context);
  153. port = htons(port);
  154. if (ref == nullptr) {
  155. ALOGE("requestId %d already in use during register call", requestId);
  156. cli->sendMsg(ResponseCode::CommandParameterError,
  157. "RequestId already in use during register call", false);
  158. return;
  159. }
  160. DNSServiceFlags nativeFlags = 0;
  161. int interfaceInt = ifaceNameToI(interfaceName);
  162. DNSServiceErrorType result = DNSServiceRegister(ref, interfaceInt, nativeFlags, serviceName,
  163. serviceType, domain, host, port, txtLen, txtRecord, &MDnsSdListenerRegisterCallback,
  164. context);
  165. if (result != kDNSServiceErr_NoError) {
  166. ALOGE("service register request %d got an error from DNSServiceRegister %d", requestId,
  167. result);
  168. mMonitor->freeServiceRef(requestId);
  169. cli->sendMsg(ResponseCode::CommandParameterError,
  170. "serviceRegister request got an error from DNSServiceRegister", false);
  171. return;
  172. }
  173. mMonitor->startMonitoring(requestId);
  174. if (VDBG) ALOGD("serviceRegister successful");
  175. cli->sendMsg(ResponseCode::CommandOkay, "serviceRegister started", false);
  176. return;
  177. }
  178. void MDnsSdListenerRegisterCallback(DNSServiceRef /* sdRef */, DNSServiceFlags /* flags */,
  179. DNSServiceErrorType errorCode, const char *serviceName, const char * /* regType */,
  180. const char * /* domain */, void *inContext) {
  181. MDnsSdListener::Context *context = reinterpret_cast<MDnsSdListener::Context *>(inContext);
  182. char *msg;
  183. int refNumber = context->mRefNumber;
  184. if (errorCode != kDNSServiceErr_NoError) {
  185. asprintf(&msg, "%d %d", refNumber, errorCode);
  186. context->mListener->sendBroadcast(ResponseCode::ServiceRegistrationFailed, msg, false);
  187. if (DBG) ALOGE("register failure for %d, error= %d", refNumber, errorCode);
  188. } else {
  189. char *quotedServiceName = SocketClient::quoteArg(serviceName);
  190. asprintf(&msg, "%d %s", refNumber, quotedServiceName);
  191. free(quotedServiceName);
  192. context->mListener->sendBroadcast(ResponseCode::ServiceRegistrationSucceeded, msg, false);
  193. if (VDBG) ALOGD("register succeeded for %d as %s", refNumber, serviceName);
  194. }
  195. free(msg);
  196. }
  197. void MDnsSdListener::Handler::resolveService(SocketClient *cli, int requestId,
  198. const char *interfaceName, const char *serviceName, const char *regType,
  199. const char *domain) {
  200. if (VDBG) {
  201. ALOGD("resolveService(%d, %s, %s, %s, %s)", requestId, interfaceName,
  202. serviceName, regType, domain);
  203. }
  204. Context *context = new Context(requestId, mListener);
  205. DNSServiceRef *ref = mMonitor->allocateServiceRef(requestId, context);
  206. if (ref == nullptr) {
  207. ALOGE("request Id %d already in use during resolve call", requestId);
  208. cli->sendMsg(ResponseCode::CommandParameterError,
  209. "RequestId already in use during resolve call", false);
  210. return;
  211. }
  212. DNSServiceFlags nativeFlags = 0;
  213. int interfaceInt = ifaceNameToI(interfaceName);
  214. DNSServiceErrorType result = DNSServiceResolve(ref, nativeFlags, interfaceInt, serviceName,
  215. regType, domain, &MDnsSdListenerResolveCallback, context);
  216. if (result != kDNSServiceErr_NoError) {
  217. ALOGE("service resolve request %d got an error from DNSServiceResolve %d", requestId,
  218. result);
  219. mMonitor->freeServiceRef(requestId);
  220. cli->sendMsg(ResponseCode::CommandParameterError,
  221. "resolveService got an error from DNSServiceResolve", false);
  222. return;
  223. }
  224. mMonitor->startMonitoring(requestId);
  225. if (VDBG) ALOGD("resolveService successful");
  226. cli->sendMsg(ResponseCode::CommandOkay, "resolveService started", false);
  227. return;
  228. }
  229. void MDnsSdListenerResolveCallback(DNSServiceRef /* sdRef */, DNSServiceFlags /* flags */,
  230. uint32_t /* interface */, DNSServiceErrorType errorCode, const char *fullname,
  231. const char *hosttarget, uint16_t port, uint16_t txtLen,
  232. const unsigned char *txtRecord , void *inContext) {
  233. MDnsSdListener::Context *context = reinterpret_cast<MDnsSdListener::Context *>(inContext);
  234. char *msg;
  235. int refNumber = context->mRefNumber;
  236. port = ntohs(port);
  237. if (errorCode != kDNSServiceErr_NoError) {
  238. asprintf(&msg, "%d %d", refNumber, errorCode);
  239. context->mListener->sendBroadcast(ResponseCode::ServiceResolveFailed, msg, false);
  240. if (DBG) ALOGE("resolve failure for %d, error= %d", refNumber, errorCode);
  241. } else {
  242. char *quotedFullName = SocketClient::quoteArg(fullname);
  243. char *quotedHostTarget = SocketClient::quoteArg(hosttarget);
  244. // Base 64 encodes every 3 bytes into 4 characters, but then adds padding to the next
  245. // multiple of 4 and a \0
  246. size_t dstLength = CEIL(CEIL(txtLen * 4, 3), 4) * 4 + 1;
  247. char *dst = (char *)malloc(dstLength);
  248. b64_ntop(txtRecord, txtLen, dst, dstLength);
  249. asprintf(&msg, "%d %s %s %d %d \"%s\"", refNumber, quotedFullName, quotedHostTarget, port,
  250. txtLen, dst);
  251. free(quotedFullName);
  252. free(quotedHostTarget);
  253. free(dst);
  254. context->mListener->sendBroadcast(ResponseCode::ServiceResolveSuccess, msg, false);
  255. if (VDBG) {
  256. ALOGD("resolve succeeded for %d finding %s at %s:%d with txtLen %d",
  257. refNumber, fullname, hosttarget, port, txtLen);
  258. }
  259. }
  260. free(msg);
  261. }
  262. void MDnsSdListener::Handler::getAddrInfo(SocketClient *cli, int requestId,
  263. const char *interfaceName, uint32_t protocol, const char *hostname) {
  264. if (VDBG) ALOGD("getAddrInfo(%d, %s %d, %s)", requestId, interfaceName, protocol, hostname);
  265. Context *context = new Context(requestId, mListener);
  266. DNSServiceRef *ref = mMonitor->allocateServiceRef(requestId, context);
  267. if (ref == nullptr) {
  268. ALOGE("request ID %d already in use during getAddrInfo call", requestId);
  269. cli->sendMsg(ResponseCode::CommandParameterError,
  270. "RequestId already in use during getAddrInfo call", false);
  271. return;
  272. }
  273. DNSServiceFlags nativeFlags = 0;
  274. int interfaceInt = ifaceNameToI(interfaceName);
  275. DNSServiceErrorType result = DNSServiceGetAddrInfo(ref, nativeFlags, interfaceInt, protocol,
  276. hostname, &MDnsSdListenerGetAddrInfoCallback, context);
  277. if (result != kDNSServiceErr_NoError) {
  278. ALOGE("getAddrInfo request %d got an error from DNSServiceGetAddrInfo %d", requestId,
  279. result);
  280. mMonitor->freeServiceRef(requestId);
  281. cli->sendMsg(ResponseCode::CommandParameterError,
  282. "getAddrInfo request got an error from DNSServiceGetAddrInfo", false);
  283. return;
  284. }
  285. mMonitor->startMonitoring(requestId);
  286. if (VDBG) ALOGD("getAddrInfo successful");
  287. cli->sendMsg(ResponseCode::CommandOkay, "getAddrInfo started", false);
  288. return;
  289. }
  290. void MDnsSdListenerGetAddrInfoCallback(DNSServiceRef /* sdRef */, DNSServiceFlags /* flags */,
  291. uint32_t /* interface */, DNSServiceErrorType errorCode, const char *hostname,
  292. const struct sockaddr *const sa, uint32_t ttl, void *inContext) {
  293. MDnsSdListener::Context *context = reinterpret_cast<MDnsSdListener::Context *>(inContext);
  294. int refNumber = context->mRefNumber;
  295. if (errorCode != kDNSServiceErr_NoError) {
  296. char *msg;
  297. asprintf(&msg, "%d %d", refNumber, errorCode);
  298. context->mListener->sendBroadcast(ResponseCode::ServiceGetAddrInfoFailed, msg, false);
  299. if (DBG) ALOGE("getAddrInfo failure for %d, error= %d", refNumber, errorCode);
  300. free(msg);
  301. } else {
  302. char addr[INET6_ADDRSTRLEN];
  303. char *msg;
  304. char *quotedHostname = SocketClient::quoteArg(hostname);
  305. if (sa->sa_family == AF_INET) {
  306. inet_ntop(sa->sa_family, &(((struct sockaddr_in *)sa)->sin_addr), addr, sizeof(addr));
  307. } else {
  308. inet_ntop(sa->sa_family, &(((struct sockaddr_in6 *)sa)->sin6_addr), addr, sizeof(addr));
  309. }
  310. asprintf(&msg, "%d %s %d %s", refNumber, quotedHostname, ttl, addr);
  311. free(quotedHostname);
  312. context->mListener->sendBroadcast(ResponseCode::ServiceGetAddrInfoSuccess, msg, false);
  313. if (VDBG) {
  314. ALOGD("getAddrInfo succeeded for %d: %s", refNumber, msg);
  315. }
  316. free(msg);
  317. }
  318. }
  319. void MDnsSdListener::Handler::setHostname(SocketClient *cli, int requestId,
  320. const char *hostname) {
  321. if (VDBG) ALOGD("setHostname(%d, %s)", requestId, hostname);
  322. Context *context = new Context(requestId, mListener);
  323. DNSServiceRef *ref = mMonitor->allocateServiceRef(requestId, context);
  324. if (ref == nullptr) {
  325. ALOGE("request Id %d already in use during setHostname call", requestId);
  326. cli->sendMsg(ResponseCode::CommandParameterError,
  327. "RequestId already in use during setHostname call", false);
  328. return;
  329. }
  330. DNSServiceFlags nativeFlags = 0;
  331. DNSServiceErrorType result = DNSSetHostname(ref, nativeFlags, hostname,
  332. &MDnsSdListenerSetHostnameCallback, context);
  333. if (result != kDNSServiceErr_NoError) {
  334. ALOGE("setHostname request %d got an error from DNSSetHostname %d", requestId, result);
  335. mMonitor->freeServiceRef(requestId);
  336. cli->sendMsg(ResponseCode::CommandParameterError,
  337. "setHostname got an error from DNSSetHostname", false);
  338. return;
  339. }
  340. mMonitor->startMonitoring(requestId);
  341. if (VDBG) ALOGD("setHostname successful");
  342. cli->sendMsg(ResponseCode::CommandOkay, "setHostname started", false);
  343. return;
  344. }
  345. void MDnsSdListenerSetHostnameCallback(DNSServiceRef /* sdRef */, DNSServiceFlags /* flags */,
  346. DNSServiceErrorType errorCode, const char *hostname, void *inContext) {
  347. MDnsSdListener::Context *context = reinterpret_cast<MDnsSdListener::Context *>(inContext);
  348. char *msg;
  349. int refNumber = context->mRefNumber;
  350. if (errorCode != kDNSServiceErr_NoError) {
  351. asprintf(&msg, "%d %d", refNumber, errorCode);
  352. context->mListener->sendBroadcast(ResponseCode::ServiceSetHostnameFailed, msg, false);
  353. if (DBG) ALOGE("setHostname failure for %d, error= %d", refNumber, errorCode);
  354. } else {
  355. char *quotedHostname = SocketClient::quoteArg(hostname);
  356. asprintf(&msg, "%d %s", refNumber, quotedHostname);
  357. free(quotedHostname);
  358. context->mListener->sendBroadcast(ResponseCode::ServiceSetHostnameSuccess, msg, false);
  359. if (VDBG) ALOGD("setHostname succeeded for %d. Set to %s", refNumber, hostname);
  360. }
  361. free(msg);
  362. }
  363. int MDnsSdListener::Handler::ifaceNameToI(const char * /* iface */) {
  364. return 0;
  365. }
  366. const char *MDnsSdListener::Handler::iToIfaceName(int /* i */) {
  367. return nullptr;
  368. }
  369. DNSServiceFlags MDnsSdListener::Handler::iToFlags(int /* i */) {
  370. return 0;
  371. }
  372. int MDnsSdListener::Handler::flagsToI(DNSServiceFlags /* flags */) {
  373. return 0;
  374. }
  375. int MDnsSdListener::Handler::runCommand(SocketClient *cli,
  376. int argc, char **argv) {
  377. if (argc < 2) {
  378. char* msg = nullptr;
  379. asprintf( &msg, "Invalid number of arguments to mdnssd: %i", argc);
  380. ALOGW("%s", msg);
  381. cli->sendMsg(ResponseCode::CommandParameterError, msg, false);
  382. free(msg);
  383. return -1;
  384. }
  385. char* cmd = argv[1];
  386. if (strcmp(cmd, "discover") == 0) {
  387. if (argc != 4) {
  388. cli->sendMsg(ResponseCode::CommandParameterError,
  389. "Invalid number of arguments to mdnssd discover", false);
  390. return 0;
  391. }
  392. int requestId = strtol(argv[2], nullptr, 10);
  393. char *serviceType = argv[3];
  394. discover(cli, nullptr, serviceType, nullptr, requestId, 0);
  395. } else if (strcmp(cmd, "stop-discover") == 0) {
  396. stop(cli, argc, argv, "discover");
  397. } else if (strcmp(cmd, "register") == 0) {
  398. if (argc != 7) {
  399. cli->sendMsg(ResponseCode::CommandParameterError,
  400. "Invalid number of arguments to mdnssd register", false);
  401. return 0;
  402. }
  403. int requestId = atoi(argv[2]);
  404. char *serviceName = argv[3];
  405. char *serviceType = argv[4];
  406. int port = strtol(argv[5], nullptr, 10);
  407. char *interfaceName = nullptr; // will use all
  408. char *domain = nullptr; // will use default
  409. char *host = nullptr; // will use default hostname
  410. // TXT record length is <= 1300, see NsdServiceInfo.setAttribute
  411. char dst[1300];
  412. int length = b64_pton(argv[6], (u_char *)dst, 1300);
  413. if (length < 0) {
  414. cli->sendMsg(ResponseCode::CommandParameterError,
  415. "Could not decode txtRecord", false);
  416. return 0;
  417. }
  418. serviceRegister(cli, requestId, interfaceName, serviceName,
  419. serviceType, domain, host, port, length, dst);
  420. } else if (strcmp(cmd, "stop-register") == 0) {
  421. stop(cli, argc, argv, "register");
  422. } else if (strcmp(cmd, "resolve") == 0) {
  423. if (argc != 6) {
  424. cli->sendMsg(ResponseCode::CommandParameterError,
  425. "Invalid number of arguments to mdnssd resolve", false);
  426. return 0;
  427. }
  428. int requestId = atoi(argv[2]);
  429. char *interfaceName = nullptr; // will use all
  430. char *serviceName = argv[3];
  431. char *regType = argv[4];
  432. char *domain = argv[5];
  433. resolveService(cli, requestId, interfaceName, serviceName, regType, domain);
  434. } else if (strcmp(cmd, "stop-resolve") == 0) {
  435. stop(cli, argc, argv, "resolve");
  436. } else if (strcmp(cmd, "start-service") == 0) {
  437. if (mMonitor->startService()) {
  438. cli->sendMsg(ResponseCode::CommandOkay, "Service Started", false);
  439. } else {
  440. cli->sendMsg(ResponseCode::ServiceStartFailed, "Service already running", false);
  441. }
  442. } else if (strcmp(cmd, "stop-service") == 0) {
  443. if (mMonitor->stopService()) {
  444. cli->sendMsg(ResponseCode::CommandOkay, "Service Stopped", false);
  445. } else {
  446. cli->sendMsg(ResponseCode::ServiceStopFailed, "Service still in use", false);
  447. }
  448. } else if (strcmp(cmd, "sethostname") == 0) {
  449. if (argc != 4) {
  450. cli->sendMsg(ResponseCode::CommandParameterError,
  451. "Invalid number of arguments to mdnssd sethostname", false);
  452. return 0;
  453. }
  454. int requestId = strtol(argv[2], nullptr, 10);
  455. char *hostname = argv[3];
  456. setHostname(cli, requestId, hostname);
  457. } else if (strcmp(cmd, "stop-sethostname") == 0) {
  458. stop(cli, argc, argv, "sethostname");
  459. } else if (strcmp(cmd, "getaddrinfo") == 0) {
  460. if (argc != 4) {
  461. cli->sendMsg(ResponseCode::CommandParameterError,
  462. "Invalid number of arguments to mdnssd getaddrinfo", false);
  463. return 0;
  464. }
  465. int requestId = atoi(argv[2]);
  466. char *hostname = argv[3];
  467. char *interfaceName = nullptr; // default
  468. int protocol = 0; // intelligient heuristic (both v4 + v6)
  469. getAddrInfo(cli, requestId, interfaceName, protocol, hostname);
  470. } else if (strcmp(cmd, "stop-getaddrinfo") == 0) {
  471. stop(cli, argc, argv, "getaddrinfo");
  472. } else {
  473. if (VDBG) ALOGE("Unknown cmd %s", cmd);
  474. cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown mdnssd cmd", false);
  475. return 0;
  476. }
  477. return 0;
  478. }
  479. MDnsSdListener::Monitor::Monitor() {
  480. mHead = nullptr;
  481. mLiveCount = 0;
  482. mPollFds = nullptr;
  483. mPollRefs = nullptr;
  484. mPollSize = 10;
  485. socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, mCtrlSocketPair);
  486. const int rval = ::android::netdutils::threadLaunch(this);
  487. if (rval != 0) {
  488. ALOGW("Error spawning monitor thread: %s (%d)", strerror(-rval), -rval);
  489. }
  490. }
  491. #define NAP_TIME 200 // 200 ms between polls
  492. static int wait_for_property(const char *name, const char *desired_value, int maxwait)
  493. {
  494. char value[PROPERTY_VALUE_MAX] = {'\0'};
  495. int maxnaps = (maxwait * 1000) / NAP_TIME;
  496. if (maxnaps < 1) {
  497. maxnaps = 1;
  498. }
  499. while (maxnaps-- > 0) {
  500. usleep(NAP_TIME * 1000);
  501. if (property_get(name, value, nullptr)) {
  502. if (desired_value == nullptr || strcmp(value, desired_value) == 0) {
  503. return 0;
  504. }
  505. }
  506. }
  507. return -1; /* failure */
  508. }
  509. int MDnsSdListener::Monitor::startService() {
  510. char property_value[PROPERTY_VALUE_MAX];
  511. std::lock_guard guard(mMutex);
  512. property_get(MDNS_SERVICE_STATUS, property_value, "");
  513. if (strcmp("running", property_value) != 0) {
  514. ALOGD("Starting MDNSD");
  515. property_set("ctl.start", MDNS_SERVICE_NAME);
  516. wait_for_property(MDNS_SERVICE_STATUS, "running", 5);
  517. return -1;
  518. }
  519. return 0;
  520. }
  521. int MDnsSdListener::Monitor::stopService() {
  522. std::lock_guard guard(mMutex);
  523. if (mHead == nullptr) {
  524. ALOGD("Stopping MDNSD");
  525. property_set("ctl.stop", MDNS_SERVICE_NAME);
  526. wait_for_property(MDNS_SERVICE_STATUS, "stopped", 5);
  527. return -1;
  528. }
  529. return 0;
  530. }
  531. void MDnsSdListener::Monitor::run() {
  532. int pollCount = 1;
  533. mPollFds = (struct pollfd *)calloc(sizeof(struct pollfd), mPollSize);
  534. mPollRefs = (DNSServiceRef **)calloc(sizeof(DNSServiceRef *), mPollSize);
  535. LOG_ALWAYS_FATAL_IF((mPollFds == nullptr), "initial calloc failed on mPollFds with a size of %d",
  536. ((int)sizeof(struct pollfd)) * mPollSize);
  537. LOG_ALWAYS_FATAL_IF((mPollRefs == nullptr), "initial calloc failed on mPollRefs with a size of %d",
  538. ((int)sizeof(DNSServiceRef *)) * mPollSize);
  539. mPollFds[0].fd = mCtrlSocketPair[0];
  540. mPollFds[0].events = POLLIN;
  541. if (VDBG) ALOGD("MDnsSdListener starting to monitor");
  542. while (1) {
  543. if (VDBG) ALOGD("Going to poll with pollCount %d", pollCount);
  544. int pollResults = poll(mPollFds, pollCount, 10000000);
  545. if (pollResults < 0) {
  546. ALOGE("Error in poll - got %d", errno);
  547. } else if (pollResults > 0) {
  548. if (VDBG) ALOGD("Monitor poll got data pollCount = %d, %d", pollCount, pollResults);
  549. for(int i = 1; i < pollCount; i++) {
  550. if (mPollFds[i].revents != 0) {
  551. if (VDBG) {
  552. ALOGD("Monitor found [%d].revents = %d - calling ProcessResults",
  553. i, mPollFds[i].revents);
  554. }
  555. std::lock_guard guard(mMutex);
  556. DNSServiceProcessResult(*(mPollRefs[i]));
  557. mPollFds[i].revents = 0;
  558. }
  559. }
  560. if (VDBG) ALOGD("controlSocket shows revent= %d", mPollFds[0].revents);
  561. switch (mPollFds[0].revents) {
  562. case POLLIN: {
  563. char readBuf[2];
  564. read(mCtrlSocketPair[0], &readBuf, 1);
  565. if (DBG) ALOGD("MDnsSdListener::Monitor got %c", readBuf[0]);
  566. if (memcmp(RESCAN, readBuf, 1) == 0) {
  567. pollCount = rescan();
  568. }
  569. }
  570. }
  571. mPollFds[0].revents = 0;
  572. } else {
  573. if (VDBG) ALOGD("MDnsSdListener::Monitor poll timed out");
  574. }
  575. }
  576. free(mPollFds);
  577. free(mPollRefs);
  578. }
  579. #define DBG_RESCAN 0
  580. int MDnsSdListener::Monitor::rescan() {
  581. // rescan the list from mHead and make new pollfds and serviceRefs
  582. if (VDBG) {
  583. ALOGD("MDnsSdListener::Monitor poll rescanning - size=%d, live=%d", mPollSize, mLiveCount);
  584. }
  585. std::lock_guard guard(mMutex);
  586. Element **prevPtr = &mHead;
  587. int i = 1;
  588. if (mPollSize <= mLiveCount) {
  589. mPollSize = mLiveCount + 5;
  590. free(mPollFds);
  591. free(mPollRefs);
  592. mPollFds = (struct pollfd *)calloc(sizeof(struct pollfd), mPollSize);
  593. mPollRefs = (DNSServiceRef **)calloc(sizeof(DNSServiceRef *), mPollSize);
  594. LOG_ALWAYS_FATAL_IF((mPollFds == nullptr), "calloc failed on mPollFds with a size of %d",
  595. ((int)sizeof(struct pollfd)) * mPollSize);
  596. LOG_ALWAYS_FATAL_IF((mPollRefs == nullptr), "calloc failed on mPollRefs with a size of %d",
  597. ((int)sizeof(DNSServiceRef *)) * mPollSize);
  598. } else {
  599. memset(mPollFds, 0, sizeof(struct pollfd) * mPollSize);
  600. memset(mPollRefs, 0, sizeof(DNSServiceRef *) * mPollSize);
  601. }
  602. mPollFds[0].fd = mCtrlSocketPair[0];
  603. mPollFds[0].events = POLLIN;
  604. if (DBG_RESCAN) ALOGD("mHead = %p", mHead);
  605. while (*prevPtr != nullptr) {
  606. if (DBG_RESCAN) ALOGD("checking %p, mReady = %d", *prevPtr, (*prevPtr)->mReady);
  607. if ((*prevPtr)->mReady == 1) {
  608. int fd = DNSServiceRefSockFD((*prevPtr)->mRef);
  609. if (fd != -1) {
  610. if (DBG_RESCAN) ALOGD(" adding FD %d", fd);
  611. mPollFds[i].fd = fd;
  612. mPollFds[i].events = POLLIN;
  613. mPollRefs[i] = &((*prevPtr)->mRef);
  614. i++;
  615. } else {
  616. ALOGE("Error retreving socket FD for live ServiceRef");
  617. }
  618. prevPtr = &((*prevPtr)->mNext); // advance to the next element
  619. } else if ((*prevPtr)->mReady == -1) {
  620. if (DBG_RESCAN) ALOGD(" removing %p from play", *prevPtr);
  621. Element *cur = *prevPtr;
  622. *prevPtr = (cur)->mNext; // change our notion of this element and don't advance
  623. delete cur;
  624. } else if ((*prevPtr)->mReady == 0) {
  625. // Not ready so just skip this node and continue on
  626. if (DBG_RESCAN) ALOGD("%p not ready. Continuing.", *prevPtr);
  627. prevPtr = &((*prevPtr)->mNext);
  628. }
  629. }
  630. return i;
  631. }
  632. DNSServiceRef *MDnsSdListener::Monitor::allocateServiceRef(int id, Context *context) {
  633. if (lookupServiceRef(id) != nullptr) {
  634. delete(context);
  635. return nullptr;
  636. }
  637. Element *e = new Element(id, context);
  638. std::lock_guard guard(mMutex);
  639. e->mNext = mHead;
  640. mHead = e;
  641. return &(e->mRef);
  642. }
  643. DNSServiceRef *MDnsSdListener::Monitor::lookupServiceRef(int id) {
  644. std::lock_guard guard(mMutex);
  645. Element *cur = mHead;
  646. while (cur != nullptr) {
  647. if (cur->mId == id) {
  648. DNSServiceRef *result = &(cur->mRef);
  649. return result;
  650. }
  651. cur = cur->mNext;
  652. }
  653. return nullptr;
  654. }
  655. void MDnsSdListener::Monitor::startMonitoring(int id) {
  656. if (VDBG) ALOGD("startMonitoring %d", id);
  657. std::lock_guard guard(mMutex);
  658. for (Element* cur = mHead; cur != nullptr; cur = cur->mNext) {
  659. if (cur->mId == id) {
  660. if (DBG_RESCAN) ALOGD("marking %p as ready to be added", cur);
  661. mLiveCount++;
  662. cur->mReady = 1;
  663. write(mCtrlSocketPair[1], RESCAN, 1); // trigger a rescan for a fresh poll
  664. if (VDBG) ALOGD("triggering rescan");
  665. return;
  666. }
  667. }
  668. }
  669. void MDnsSdListener::Monitor::freeServiceRef(int id) {
  670. if (VDBG) ALOGD("freeServiceRef %d", id);
  671. std::lock_guard guard(mMutex);
  672. Element* cur;
  673. for (Element** prevPtr = &mHead; *prevPtr != nullptr; prevPtr = &(cur->mNext)) {
  674. cur = *prevPtr;
  675. if (cur->mId == id) {
  676. if (DBG_RESCAN) ALOGD("marking %p as ready to be removed", cur);
  677. mLiveCount--;
  678. if (cur->mReady == 1) {
  679. cur->mReady = -1; // tell poll thread to delete
  680. cur->mRef = nullptr; // do not process further results
  681. write(mCtrlSocketPair[1], RESCAN, 1); // trigger a rescan for a fresh poll
  682. if (VDBG) ALOGD("triggering rescan");
  683. } else {
  684. *prevPtr = cur->mNext;
  685. delete cur;
  686. }
  687. return;
  688. }
  689. }
  690. }
  691. void MDnsSdListener::Monitor::deallocateServiceRef(DNSServiceRef* ref) {
  692. std::lock_guard guard(mMutex);
  693. DNSServiceRefDeallocate(*ref);
  694. *ref = nullptr;
  695. }