1 /*
2 * Copyright (c) 2018, The OpenThread Authors.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the copyright holder nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /**
30 * @file
31 * This file implements mDNS publisher based on mDNSResponder.
32 */
33
34 #define OTBR_LOG_TAG "MDNS"
35
36 #include "mdns/mdns_mdnssd.hpp"
37
38 #include <algorithm>
39
40 #include <arpa/inet.h>
41 #include <assert.h>
42 #include <errno.h>
43 #include <inttypes.h>
44 #include <netinet/in.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48
49 #include "common/code_utils.hpp"
50 #include "common/dns_utils.hpp"
51 #include "common/logging.hpp"
52 #include "common/time.hpp"
53
54 namespace otbr {
55
56 namespace Mdns {
57
58 static const char kDomain[] = "local.";
59
DNSErrorToOtbrError(DNSServiceErrorType aError)60 static otbrError DNSErrorToOtbrError(DNSServiceErrorType aError)
61 {
62 otbrError error;
63
64 switch (aError)
65 {
66 case kDNSServiceErr_NoError:
67 error = OTBR_ERROR_NONE;
68 break;
69
70 case kDNSServiceErr_NoSuchKey:
71 case kDNSServiceErr_NoSuchName:
72 case kDNSServiceErr_NoSuchRecord:
73 error = OTBR_ERROR_NOT_FOUND;
74 break;
75
76 case kDNSServiceErr_Invalid:
77 case kDNSServiceErr_BadParam:
78 case kDNSServiceErr_BadFlags:
79 case kDNSServiceErr_BadInterfaceIndex:
80 error = OTBR_ERROR_INVALID_ARGS;
81 break;
82
83 case kDNSServiceErr_NameConflict:
84 error = OTBR_ERROR_DUPLICATED;
85 break;
86
87 case kDNSServiceErr_Unsupported:
88 error = OTBR_ERROR_NOT_IMPLEMENTED;
89 break;
90
91 case kDNSServiceErr_ServiceNotRunning:
92 error = OTBR_ERROR_INVALID_STATE;
93 break;
94
95 default:
96 error = OTBR_ERROR_MDNS;
97 break;
98 }
99
100 return error;
101 }
102
DNSErrorToString(DNSServiceErrorType aError)103 static const char *DNSErrorToString(DNSServiceErrorType aError)
104 {
105 switch (aError)
106 {
107 case kDNSServiceErr_NoError:
108 return "OK";
109
110 case kDNSServiceErr_Unknown:
111 // 0xFFFE FFFF
112 return "Unknown";
113
114 case kDNSServiceErr_NoSuchName:
115 return "No Such Name";
116
117 case kDNSServiceErr_NoMemory:
118 return "No Memory";
119
120 case kDNSServiceErr_BadParam:
121 return "Bad Param";
122
123 case kDNSServiceErr_BadReference:
124 return "Bad Reference";
125
126 case kDNSServiceErr_BadState:
127 return "Bad State";
128
129 case kDNSServiceErr_BadFlags:
130 return "Bad Flags";
131
132 case kDNSServiceErr_Unsupported:
133 return "Unsupported";
134
135 case kDNSServiceErr_NotInitialized:
136 return "Not Initialized";
137
138 case kDNSServiceErr_AlreadyRegistered:
139 return "Already Registered";
140
141 case kDNSServiceErr_NameConflict:
142 return "Name Conflict";
143
144 case kDNSServiceErr_Invalid:
145 return "Invalid";
146
147 case kDNSServiceErr_Firewall:
148 return "Firewall";
149
150 case kDNSServiceErr_Incompatible:
151 // client library incompatible with daemon
152 return "Incompatible";
153
154 case kDNSServiceErr_BadInterfaceIndex:
155 return "Bad Interface Index";
156
157 case kDNSServiceErr_Refused:
158 return "Refused";
159
160 case kDNSServiceErr_NoSuchRecord:
161 return "No Such Record";
162
163 case kDNSServiceErr_NoAuth:
164 return "No Auth";
165
166 case kDNSServiceErr_NoSuchKey:
167 return "No Such Key";
168
169 case kDNSServiceErr_NATTraversal:
170 return "NAT Traversal";
171
172 case kDNSServiceErr_DoubleNAT:
173 return "Double NAT";
174
175 case kDNSServiceErr_BadTime:
176 // Codes up to here existed in Tiger
177 return "Bad Time";
178
179 case kDNSServiceErr_BadSig:
180 return "Bad Sig";
181
182 case kDNSServiceErr_BadKey:
183 return "Bad Key";
184
185 case kDNSServiceErr_Transient:
186 return "Transient";
187
188 case kDNSServiceErr_ServiceNotRunning:
189 // Background daemon not running
190 return "Service Not Running";
191
192 case kDNSServiceErr_NATPortMappingUnsupported:
193 // NAT doesn't support NAT-PMP or UPnP
194 return "NAT Port Mapping Unsupported";
195
196 case kDNSServiceErr_NATPortMappingDisabled:
197 // NAT supports NAT-PMP or UPnP but it's disabled by the administrator
198 return "NAT Port Mapping Disabled";
199
200 case kDNSServiceErr_NoRouter:
201 // No router currently configured (probably no network connectivity)
202 return "No Router";
203
204 case kDNSServiceErr_PollingMode:
205 return "Polling Mode";
206
207 case kDNSServiceErr_Timeout:
208 return "Timeout";
209
210 default:
211 assert(false);
212 return nullptr;
213 }
214 }
215
PublisherMDnsSd(StateCallback aCallback)216 PublisherMDnsSd::PublisherMDnsSd(StateCallback aCallback)
217 : mHostsRef(nullptr)
218 , mState(State::kIdle)
219 , mStateCallback(std::move(aCallback))
220 {
221 }
222
~PublisherMDnsSd(void)223 PublisherMDnsSd::~PublisherMDnsSd(void)
224 {
225 Stop(kNormalStop);
226 }
227
Start(void)228 otbrError PublisherMDnsSd::Start(void)
229 {
230 mState = State::kReady;
231 mStateCallback(State::kReady);
232 return OTBR_ERROR_NONE;
233 }
234
IsStarted(void) const235 bool PublisherMDnsSd::IsStarted(void) const
236 {
237 return mState == State::kReady;
238 }
239
Stop(StopMode aStopMode)240 void PublisherMDnsSd::Stop(StopMode aStopMode)
241 {
242 VerifyOrExit(mState == State::kReady);
243
244 // If we get a `kDNSServiceErr_ServiceNotRunning` and need to
245 // restart the `Publisher`, we should immediately de-allocate
246 // all `ServiceRef`. Otherwise, we first clear the `Registrations`
247 // list so that `DnssdHostRegisteration` destructor gets the chance
248 // to update registered records if needed.
249
250 switch (aStopMode)
251 {
252 case kNormalStop:
253 break;
254
255 case kStopOnServiceNotRunningError:
256 DeallocateHostsRef();
257 break;
258 }
259
260 mServiceRegistrations.clear();
261 mHostRegistrations.clear();
262 mKeyRegistrations.clear();
263 DeallocateHostsRef();
264
265 mSubscribedServices.clear();
266 mSubscribedHosts.clear();
267
268 mState = State::kIdle;
269
270 exit:
271 return;
272 }
273
CreateSharedHostsRef(void)274 DNSServiceErrorType PublisherMDnsSd::CreateSharedHostsRef(void)
275 {
276 DNSServiceErrorType dnsError = kDNSServiceErr_NoError;
277
278 VerifyOrExit(mHostsRef == nullptr);
279
280 dnsError = DNSServiceCreateConnection(&mHostsRef);
281 otbrLogDebug("Created new shared DNSServiceRef: %p", mHostsRef);
282
283 exit:
284 return dnsError;
285 }
286
DeallocateHostsRef(void)287 void PublisherMDnsSd::DeallocateHostsRef(void)
288 {
289 VerifyOrExit(mHostsRef != nullptr);
290
291 HandleServiceRefDeallocating(mHostsRef);
292 DNSServiceRefDeallocate(mHostsRef);
293 otbrLogDebug("Deallocated DNSServiceRef for hosts: %p", mHostsRef);
294 mHostsRef = nullptr;
295
296 exit:
297 return;
298 }
299
Update(MainloopContext & aMainloop)300 void PublisherMDnsSd::Update(MainloopContext &aMainloop)
301 {
302 for (auto &kv : mServiceRegistrations)
303 {
304 auto &serviceReg = static_cast<DnssdServiceRegistration &>(*kv.second);
305
306 serviceReg.Update(aMainloop);
307 }
308
309 if (mHostsRef != nullptr)
310 {
311 int fd = DNSServiceRefSockFD(mHostsRef);
312
313 assert(fd != -1);
314
315 aMainloop.AddFdToReadSet(fd);
316 }
317
318 for (const auto &service : mSubscribedServices)
319 {
320 service->UpdateAll(aMainloop);
321 }
322
323 for (const auto &host : mSubscribedHosts)
324 {
325 host->Update(aMainloop);
326 }
327 }
328
Process(const MainloopContext & aMainloop)329 void PublisherMDnsSd::Process(const MainloopContext &aMainloop)
330 {
331 mServiceRefsToProcess.clear();
332
333 for (auto &kv : mServiceRegistrations)
334 {
335 auto &serviceReg = static_cast<DnssdServiceRegistration &>(*kv.second);
336
337 serviceReg.Process(aMainloop, mServiceRefsToProcess);
338 }
339
340 if (mHostsRef != nullptr)
341 {
342 int fd = DNSServiceRefSockFD(mHostsRef);
343
344 if (FD_ISSET(fd, &aMainloop.mReadFdSet))
345 {
346 mServiceRefsToProcess.push_back(mHostsRef);
347 }
348 }
349
350 for (const auto &service : mSubscribedServices)
351 {
352 service->ProcessAll(aMainloop, mServiceRefsToProcess);
353 }
354
355 for (const auto &host : mSubscribedHosts)
356 {
357 host->Process(aMainloop, mServiceRefsToProcess);
358 }
359
360 for (DNSServiceRef serviceRef : mServiceRefsToProcess)
361 {
362 DNSServiceErrorType error;
363
364 // As we go through the list of `mServiceRefsToProcess` the call
365 // to `DNSServiceProcessResult()` can itself invoke callbacks
366 // into `PublisherMDnsSd` and OT, which in turn, may change the
367 // state of `Publisher` and potentially trigger a previously
368 // valid `ServiceRef` in the list to be deallocated. We use
369 // `HandleServiceRefDeallocating()` which is called whenever a
370 // `ServiceRef` is being deallocated and from this we update
371 // the entry in `mServiceRefsToProcess` list to `nullptr` so to
372 // avoid calling `DNSServiceProcessResult()` on an already
373 // freed `ServiceRef`.
374
375 if (serviceRef == nullptr)
376 {
377 continue;
378 }
379
380 error = DNSServiceProcessResult(serviceRef);
381
382 if (error != kDNSServiceErr_NoError)
383 {
384 otbrLogLevel logLevel = (error == kDNSServiceErr_BadReference) ? OTBR_LOG_INFO : OTBR_LOG_WARNING;
385 otbrLog(logLevel, OTBR_LOG_TAG, "DNSServiceProcessResult failed: %s (serviceRef = %p)",
386 DNSErrorToString(error), serviceRef);
387 }
388 if (error == kDNSServiceErr_ServiceNotRunning)
389 {
390 otbrLogWarning("Need to reconnect to mdnsd");
391 Stop(kStopOnServiceNotRunningError);
392 Start();
393 ExitNow();
394 }
395 }
396 exit:
397 return;
398 }
399
HandleServiceRefDeallocating(const DNSServiceRef & aServiceRef)400 void PublisherMDnsSd::HandleServiceRefDeallocating(const DNSServiceRef &aServiceRef)
401 {
402 for (DNSServiceRef &entry : mServiceRefsToProcess)
403 {
404 if (entry == aServiceRef)
405 {
406 entry = nullptr;
407 }
408 }
409 }
410
Update(MainloopContext & aMainloop) const411 void PublisherMDnsSd::DnssdServiceRegistration::Update(MainloopContext &aMainloop) const
412 {
413 int fd;
414
415 VerifyOrExit(mServiceRef != nullptr);
416
417 fd = DNSServiceRefSockFD(mServiceRef);
418 VerifyOrExit(fd != -1);
419
420 aMainloop.AddFdToReadSet(fd);
421
422 exit:
423 return;
424 }
425
Process(const MainloopContext & aMainloop,std::vector<DNSServiceRef> & aReadyServices) const426 void PublisherMDnsSd::DnssdServiceRegistration::Process(const MainloopContext &aMainloop,
427 std::vector<DNSServiceRef> &aReadyServices) const
428 {
429 int fd;
430
431 VerifyOrExit(mServiceRef != nullptr);
432
433 fd = DNSServiceRefSockFD(mServiceRef);
434 VerifyOrExit(fd != -1);
435
436 VerifyOrExit(FD_ISSET(fd, &aMainloop.mReadFdSet));
437 aReadyServices.push_back(mServiceRef);
438
439 exit:
440 return;
441 }
442
Register(void)443 otbrError PublisherMDnsSd::DnssdServiceRegistration::Register(void)
444 {
445 std::string fullHostName;
446 std::string regType = MakeRegType(mType, mSubTypeList);
447 const char *hostNameCString = nullptr;
448 const char *serviceNameCString = nullptr;
449 DnssdKeyRegistration *keyReg;
450 DNSServiceErrorType dnsError;
451
452 if (!mHostName.empty())
453 {
454 fullHostName = MakeFullHostName(mHostName);
455 hostNameCString = fullHostName.c_str();
456 }
457
458 if (!mName.empty())
459 {
460 serviceNameCString = mName.c_str();
461 }
462
463 keyReg = static_cast<DnssdKeyRegistration *>(GetPublisher().FindKeyRegistration(mName, mType));
464
465 if (keyReg != nullptr)
466 {
467 keyReg->Unregister();
468 }
469
470 otbrLogInfo("Registering service %s.%s", mName.c_str(), regType.c_str());
471
472 VerifyOrExit(GetPublisher().IsStarted(), dnsError = kDNSServiceErr_ServiceNotRunning);
473
474 dnsError = DNSServiceRegister(&mServiceRef, kDNSServiceFlagsNoAutoRename, kDNSServiceInterfaceIndexAny,
475 serviceNameCString, regType.c_str(),
476 /* domain */ nullptr, hostNameCString, htons(mPort), mTxtData.size(), mTxtData.data(),
477 HandleRegisterResult, this);
478
479 if (dnsError != kDNSServiceErr_NoError)
480 {
481 HandleRegisterResult(/* aFlags */ 0, dnsError);
482 }
483
484 if (keyReg != nullptr)
485 {
486 keyReg->Register();
487 }
488
489 exit:
490 return GetPublisher().DnsErrorToOtbrError(dnsError);
491 }
492
Unregister(void)493 void PublisherMDnsSd::DnssdServiceRegistration::Unregister(void)
494 {
495 DnssdKeyRegistration *keyReg = mRelatedKeyReg;
496
497 VerifyOrExit(GetPublisher().IsStarted());
498 VerifyOrExit(mServiceRef != nullptr);
499
500 // If we have a related key registration associated with this
501 // service registration, we first unregister it and after we
502 // deallocated the `mServiceRef` try to register it again
503 // (which will add it as an individual record not tied to a
504 // service registration). Note that the `keyReg->Unregister()`
505 // will clear the `mRelatedKeyReg` field, so we need to keep
506 // a local copy to it in `keyReg`.
507
508 if (keyReg != nullptr)
509 {
510 keyReg->Unregister();
511 }
512
513 GetPublisher().HandleServiceRefDeallocating(mServiceRef);
514 DNSServiceRefDeallocate(mServiceRef);
515 mServiceRef = nullptr;
516
517 if (keyReg != nullptr)
518 {
519 keyReg->Register();
520 }
521
522 exit:
523 return;
524 }
525
HandleRegisterResult(DNSServiceRef aServiceRef,DNSServiceFlags aFlags,DNSServiceErrorType aError,const char * aName,const char * aType,const char * aDomain,void * aContext)526 void PublisherMDnsSd::DnssdServiceRegistration::HandleRegisterResult(DNSServiceRef aServiceRef,
527 DNSServiceFlags aFlags,
528 DNSServiceErrorType aError,
529 const char *aName,
530 const char *aType,
531 const char *aDomain,
532 void *aContext)
533 {
534 OTBR_UNUSED_VARIABLE(aServiceRef);
535 OTBR_UNUSED_VARIABLE(aName);
536 OTBR_UNUSED_VARIABLE(aType);
537 OTBR_UNUSED_VARIABLE(aDomain);
538
539 static_cast<DnssdServiceRegistration *>(aContext)->HandleRegisterResult(aFlags, aError);
540 }
541
HandleRegisterResult(DNSServiceFlags aFlags,DNSServiceErrorType aError)542 void PublisherMDnsSd::DnssdServiceRegistration::HandleRegisterResult(DNSServiceFlags aFlags, DNSServiceErrorType aError)
543 {
544 if (mRelatedKeyReg != nullptr)
545 {
546 mRelatedKeyReg->HandleRegisterResult(aError);
547 }
548
549 if ((aError == kDNSServiceErr_NoError) && (aFlags & kDNSServiceFlagsAdd))
550 {
551 otbrLogInfo("Successfully registered service %s.%s", mName.c_str(), mType.c_str());
552 Complete(OTBR_ERROR_NONE);
553 }
554 else
555 {
556 otbrLogErr("Failed to register service %s.%s: %s", mName.c_str(), mType.c_str(), DNSErrorToString(aError));
557 GetPublisher().RemoveServiceRegistration(mName, mType, DNSErrorToOtbrError(aError));
558 }
559 }
560
Register(void)561 otbrError PublisherMDnsSd::DnssdHostRegistration::Register(void)
562 {
563 DNSServiceErrorType dnsError = kDNSServiceErr_NoError;
564
565 otbrLogInfo("Registering new host %s", mName.c_str());
566
567 VerifyOrExit(GetPublisher().IsStarted(), dnsError = kDNSServiceErr_ServiceNotRunning);
568
569 for (const Ip6Address &address : mAddresses)
570 {
571 DNSRecordRef recordRef = nullptr;
572
573 dnsError = GetPublisher().CreateSharedHostsRef();
574 VerifyOrExit(dnsError == kDNSServiceErr_NoError);
575
576 dnsError = DNSServiceRegisterRecord(GetPublisher().mHostsRef, &recordRef, kDNSServiceFlagsShared,
577 kDNSServiceInterfaceIndexAny, MakeFullHostName(mName).c_str(),
578 kDNSServiceType_AAAA, kDNSServiceClass_IN, sizeof(address.m8), address.m8,
579 /* ttl */ 0, HandleRegisterResult, this);
580 VerifyOrExit(dnsError == kDNSServiceErr_NoError);
581
582 mAddrRecordRefs.push_back(recordRef);
583 mAddrRegistered.push_back(false);
584 }
585
586 exit:
587 if ((dnsError != kDNSServiceErr_NoError) || mAddresses.empty())
588 {
589 HandleRegisterResult(/* aRecordRef */ nullptr, dnsError);
590 }
591
592 return GetPublisher().DnsErrorToOtbrError(dnsError);
593 }
594
Unregister(void)595 void PublisherMDnsSd::DnssdHostRegistration::Unregister(void)
596 {
597 DNSServiceErrorType dnsError;
598
599 VerifyOrExit(GetPublisher().IsStarted());
600 VerifyOrExit(GetPublisher().mHostsRef != nullptr);
601
602 for (size_t index = 0; index < mAddrRecordRefs.size(); index++)
603 {
604 const Ip6Address &address = mAddresses[index];
605
606 if (mAddrRegistered[index])
607 {
608 // The Bonjour mDNSResponder somehow doesn't send goodbye message for the AAAA record when it is
609 // removed by `DNSServiceRemoveRecord`. Per RFC 6762, a goodbye message of a record sets its TTL
610 // to zero but the receiver should record the TTL of 1 and flushes the cache 1 second later. Here
611 // we remove the AAAA record after updating its TTL to 1 second. This has the same effect as
612 // sending a goodbye message.
613 // TODO: resolve the goodbye issue with Bonjour mDNSResponder.
614 dnsError = DNSServiceUpdateRecord(GetPublisher().mHostsRef, mAddrRecordRefs[index], kDNSServiceFlagsUnique,
615 sizeof(address.m8), address.m8, /* ttl */ 1);
616 otbrLogResult(DNSErrorToOtbrError(dnsError), "Send goodbye message for host %s address %s: %s",
617 MakeFullHostName(mName).c_str(), address.ToString().c_str(), DNSErrorToString(dnsError));
618 }
619
620 dnsError = DNSServiceRemoveRecord(GetPublisher().mHostsRef, mAddrRecordRefs[index], /* flags */ 0);
621
622 otbrLogResult(DNSErrorToOtbrError(dnsError), "Remove record for host %s address %s: %s",
623 MakeFullHostName(mName).c_str(), address.ToString().c_str(), DNSErrorToString(dnsError));
624 }
625
626 exit:
627 mAddrRegistered.clear();
628 mAddrRecordRefs.clear();
629 }
630
HandleRegisterResult(DNSServiceRef aServiceRef,DNSRecordRef aRecordRef,DNSServiceFlags aFlags,DNSServiceErrorType aError,void * aContext)631 void PublisherMDnsSd::DnssdHostRegistration::HandleRegisterResult(DNSServiceRef aServiceRef,
632 DNSRecordRef aRecordRef,
633 DNSServiceFlags aFlags,
634 DNSServiceErrorType aError,
635 void *aContext)
636 {
637 OTBR_UNUSED_VARIABLE(aServiceRef);
638 OTBR_UNUSED_VARIABLE(aFlags);
639
640 static_cast<DnssdHostRegistration *>(aContext)->HandleRegisterResult(aRecordRef, aError);
641 }
642
HandleRegisterResult(DNSRecordRef aRecordRef,DNSServiceErrorType aError)643 void PublisherMDnsSd::DnssdHostRegistration::HandleRegisterResult(DNSRecordRef aRecordRef, DNSServiceErrorType aError)
644 {
645 if (aError != kDNSServiceErr_NoError)
646 {
647 otbrLogErr("Failed to register host %s: %s", mName.c_str(), DNSErrorToString(aError));
648 GetPublisher().RemoveHostRegistration(mName, DNSErrorToOtbrError(aError));
649 }
650 else
651 {
652 bool shouldComplete = !IsCompleted();
653
654 for (size_t index = 0; index < mAddrRecordRefs.size(); index++)
655 {
656 if ((mAddrRecordRefs[index] == aRecordRef) && !mAddrRegistered[index])
657 {
658 mAddrRegistered[index] = true;
659 otbrLogInfo("Successfully registered host %s address %s", mName.c_str(),
660 mAddresses[index].ToString().c_str());
661 }
662
663 if (!mAddrRegistered[index])
664 {
665 shouldComplete = false;
666 }
667 }
668
669 if (shouldComplete)
670 {
671 otbrLogInfo("Successfully registered all host %s addresses", mName.c_str());
672 Complete(OTBR_ERROR_NONE);
673 }
674 }
675 }
676
Register(void)677 otbrError PublisherMDnsSd::DnssdKeyRegistration::Register(void)
678 {
679 DNSServiceErrorType dnsError = kDNSServiceErr_NoError;
680 DnssdServiceRegistration *serviceReg;
681
682 otbrLogInfo("Registering new key %s", mName.c_str());
683
684 VerifyOrExit(GetPublisher().IsStarted(), dnsError = kDNSServiceErr_ServiceNotRunning);
685
686 serviceReg = static_cast<DnssdServiceRegistration *>(GetPublisher().FindServiceRegistration(mName));
687
688 if ((serviceReg != nullptr) && (serviceReg->mServiceRef != nullptr))
689 {
690 otbrLogInfo("Key %s is being registered as a record of an existing service registration", mName.c_str());
691
692 dnsError = DNSServiceAddRecord(serviceReg->mServiceRef, &mRecordRef, kDNSServiceFlagsUnique,
693 kDNSServiceType_KEY, mKeyData.size(), mKeyData.data(), /* ttl */ 0);
694
695 VerifyOrExit(dnsError == kDNSServiceErr_NoError);
696
697 mRelatedServiceReg = serviceReg;
698 serviceReg->mRelatedKeyReg = this;
699
700 if (mRelatedServiceReg->IsCompleted())
701 {
702 HandleRegisterResult(kDNSServiceErr_NoError);
703 }
704
705 // If related service registration is not yet finished,
706 // we wait for service registration completion to signal
707 // key record registration as well.
708 }
709 else
710 {
711 otbrLogInfo("Key %s is being registered individually", mName.c_str());
712
713 dnsError = GetPublisher().CreateSharedHostsRef();
714 VerifyOrExit(dnsError == kDNSServiceErr_NoError);
715
716 dnsError = DNSServiceRegisterRecord(GetPublisher().mHostsRef, &mRecordRef, kDNSServiceFlagsUnique,
717 kDNSServiceInterfaceIndexAny, MakeFullKeyName(mName).c_str(),
718 kDNSServiceType_KEY, kDNSServiceClass_IN, mKeyData.size(), mKeyData.data(),
719 /* ttl */ 0, HandleRegisterResult, this);
720 VerifyOrExit(dnsError == kDNSServiceErr_NoError);
721 }
722
723 exit:
724 if (dnsError != kDNSServiceErr_NoError)
725 {
726 HandleRegisterResult(dnsError);
727 }
728
729 return GetPublisher().DnsErrorToOtbrError(dnsError);
730 }
731
Unregister(void)732 void PublisherMDnsSd::DnssdKeyRegistration::Unregister(void)
733 {
734 DNSServiceErrorType dnsError;
735 DNSServiceRef serviceRef;
736
737 VerifyOrExit(mRecordRef != nullptr);
738
739 if (mRelatedServiceReg != nullptr)
740 {
741 serviceRef = mRelatedServiceReg->mServiceRef;
742
743 mRelatedServiceReg->mRelatedKeyReg = nullptr;
744 mRelatedServiceReg = nullptr;
745
746 otbrLogInfo("Unregistering key %s (was registered as a record of a service)", mName.c_str());
747 }
748 else
749 {
750 serviceRef = GetPublisher().mHostsRef;
751
752 otbrLogInfo("Unregistering key %s (was registered individually)", mName.c_str());
753 }
754
755 VerifyOrExit(GetPublisher().IsStarted(), dnsError = kDNSServiceErr_ServiceNotRunning);
756
757 VerifyOrExit(serviceRef != nullptr);
758
759 dnsError = DNSServiceRemoveRecord(serviceRef, mRecordRef, /* flags */ 0);
760
761 otbrLogInfo("Unregistered key %s: error:%s", mName.c_str(), DNSErrorToString(dnsError));
762
763 exit:
764 return;
765 }
766
HandleRegisterResult(DNSServiceRef aServiceRef,DNSRecordRef aRecordRef,DNSServiceFlags aFlags,DNSServiceErrorType aError,void * aContext)767 void PublisherMDnsSd::DnssdKeyRegistration::HandleRegisterResult(DNSServiceRef aServiceRef,
768 DNSRecordRef aRecordRef,
769 DNSServiceFlags aFlags,
770 DNSServiceErrorType aError,
771 void *aContext)
772 {
773 OTBR_UNUSED_VARIABLE(aServiceRef);
774 OTBR_UNUSED_VARIABLE(aRecordRef);
775 OTBR_UNUSED_VARIABLE(aFlags);
776
777 static_cast<DnssdKeyRegistration *>(aContext)->HandleRegisterResult(aError);
778 }
779
HandleRegisterResult(DNSServiceErrorType aError)780 void PublisherMDnsSd::DnssdKeyRegistration::HandleRegisterResult(DNSServiceErrorType aError)
781 {
782 if (aError != kDNSServiceErr_NoError)
783 {
784 otbrLogErr("Failed to register key %s: %s", mName.c_str(), DNSErrorToString(aError));
785 GetPublisher().RemoveKeyRegistration(mName, DNSErrorToOtbrError(aError));
786 }
787 else
788 {
789 otbrLogInfo("Successfully registered key %s", mName.c_str());
790 Complete(OTBR_ERROR_NONE);
791 }
792 }
793
PublishServiceImpl(const std::string & aHostName,const std::string & aName,const std::string & aType,const SubTypeList & aSubTypeList,uint16_t aPort,const TxtData & aTxtData,ResultCallback && aCallback)794 otbrError PublisherMDnsSd::PublishServiceImpl(const std::string &aHostName,
795 const std::string &aName,
796 const std::string &aType,
797 const SubTypeList &aSubTypeList,
798 uint16_t aPort,
799 const TxtData &aTxtData,
800 ResultCallback &&aCallback)
801 {
802 otbrError error = OTBR_ERROR_NONE;
803 SubTypeList sortedSubTypeList = SortSubTypeList(aSubTypeList);
804 std::string regType = MakeRegType(aType, sortedSubTypeList);
805 DnssdServiceRegistration *serviceReg;
806
807 if (mState != State::kReady)
808 {
809 error = OTBR_ERROR_INVALID_STATE;
810 std::move(aCallback)(error);
811 ExitNow();
812 }
813
814 aCallback = HandleDuplicateServiceRegistration(aHostName, aName, aType, sortedSubTypeList, aPort, aTxtData,
815 std::move(aCallback));
816 VerifyOrExit(!aCallback.IsNull());
817
818 serviceReg = new DnssdServiceRegistration(aHostName, aName, aType, sortedSubTypeList, aPort, aTxtData,
819 std::move(aCallback), this);
820 AddServiceRegistration(std::unique_ptr<DnssdServiceRegistration>(serviceReg));
821
822 error = serviceReg->Register();
823
824 exit:
825 return error;
826 }
827
UnpublishService(const std::string & aName,const std::string & aType,ResultCallback && aCallback)828 void PublisherMDnsSd::UnpublishService(const std::string &aName, const std::string &aType, ResultCallback &&aCallback)
829 {
830 otbrError error = OTBR_ERROR_NONE;
831
832 VerifyOrExit(mState == Publisher::State::kReady, error = OTBR_ERROR_INVALID_STATE);
833 RemoveServiceRegistration(aName, aType, OTBR_ERROR_ABORTED);
834
835 exit:
836 std::move(aCallback)(error);
837 }
838
PublishHostImpl(const std::string & aName,const AddressList & aAddresses,ResultCallback && aCallback)839 otbrError PublisherMDnsSd::PublishHostImpl(const std::string &aName,
840 const AddressList &aAddresses,
841 ResultCallback &&aCallback)
842 {
843 otbrError error = OTBR_ERROR_NONE;
844 DnssdHostRegistration *hostReg;
845
846 if (mState != State::kReady)
847 {
848 error = OTBR_ERROR_INVALID_STATE;
849 std::move(aCallback)(error);
850 ExitNow();
851 }
852
853 aCallback = HandleDuplicateHostRegistration(aName, aAddresses, std::move(aCallback));
854 VerifyOrExit(!aCallback.IsNull());
855
856 hostReg = new DnssdHostRegistration(aName, aAddresses, std::move(aCallback), this);
857 AddHostRegistration(std::unique_ptr<DnssdHostRegistration>(hostReg));
858
859 error = hostReg->Register();
860
861 exit:
862 return error;
863 }
864
UnpublishHost(const std::string & aName,ResultCallback && aCallback)865 void PublisherMDnsSd::UnpublishHost(const std::string &aName, ResultCallback &&aCallback)
866 {
867 otbrError error = OTBR_ERROR_NONE;
868
869 VerifyOrExit(mState == Publisher::State::kReady, error = OTBR_ERROR_INVALID_STATE);
870 RemoveHostRegistration(aName, OTBR_ERROR_ABORTED);
871
872 exit:
873 // We may failed to unregister the host from underlying mDNS publishers, but
874 // it usually means that the mDNS publisher is already not functioning. So it's
875 // okay to return success directly since the service is not advertised anyway.
876 std::move(aCallback)(error);
877 }
878
PublishKeyImpl(const std::string & aName,const KeyData & aKeyData,ResultCallback && aCallback)879 otbrError PublisherMDnsSd::PublishKeyImpl(const std::string &aName, const KeyData &aKeyData, ResultCallback &&aCallback)
880 {
881 otbrError error = OTBR_ERROR_NONE;
882 DnssdKeyRegistration *keyReg;
883
884 if (mState != State::kReady)
885 {
886 error = OTBR_ERROR_INVALID_STATE;
887 std::move(aCallback)(error);
888 ExitNow();
889 }
890
891 aCallback = HandleDuplicateKeyRegistration(aName, aKeyData, std::move(aCallback));
892 VerifyOrExit(!aCallback.IsNull());
893
894 keyReg = new DnssdKeyRegistration(aName, aKeyData, std::move(aCallback), this);
895 AddKeyRegistration(std::unique_ptr<DnssdKeyRegistration>(keyReg));
896
897 error = keyReg->Register();
898
899 exit:
900 return error;
901 }
902
UnpublishKey(const std::string & aName,ResultCallback && aCallback)903 void PublisherMDnsSd::UnpublishKey(const std::string &aName, ResultCallback &&aCallback)
904 {
905 otbrError error = OTBR_ERROR_NONE;
906
907 VerifyOrExit(mState == Publisher::State::kReady, error = OTBR_ERROR_INVALID_STATE);
908 RemoveKeyRegistration(aName, OTBR_ERROR_ABORTED);
909
910 exit:
911 std::move(aCallback)(error);
912 }
913
914 // See `regtype` parameter of the DNSServiceRegister() function for more information.
MakeRegType(const std::string & aType,SubTypeList aSubTypeList)915 std::string PublisherMDnsSd::MakeRegType(const std::string &aType, SubTypeList aSubTypeList)
916 {
917 std::string regType = aType;
918
919 std::sort(aSubTypeList.begin(), aSubTypeList.end());
920
921 for (const auto &subType : aSubTypeList)
922 {
923 regType += "," + subType;
924 }
925
926 return regType;
927 }
928
SubscribeService(const std::string & aType,const std::string & aInstanceName)929 void PublisherMDnsSd::SubscribeService(const std::string &aType, const std::string &aInstanceName)
930 {
931 VerifyOrExit(mState == Publisher::State::kReady);
932 mSubscribedServices.push_back(MakeUnique<ServiceSubscription>(*this, aType, aInstanceName));
933
934 otbrLogInfo("Subscribe service %s.%s (total %zu)", aInstanceName.c_str(), aType.c_str(),
935 mSubscribedServices.size());
936
937 if (aInstanceName.empty())
938 {
939 mSubscribedServices.back()->Browse();
940 }
941 else
942 {
943 mSubscribedServices.back()->Resolve(kDNSServiceInterfaceIndexAny, aInstanceName, aType, kDomain);
944 }
945
946 exit:
947 return;
948 }
949
UnsubscribeService(const std::string & aType,const std::string & aInstanceName)950 void PublisherMDnsSd::UnsubscribeService(const std::string &aType, const std::string &aInstanceName)
951 {
952 ServiceSubscriptionList::iterator it;
953
954 VerifyOrExit(mState == Publisher::State::kReady);
955 it = std::find_if(mSubscribedServices.begin(), mSubscribedServices.end(),
956 [&aType, &aInstanceName](const std::unique_ptr<ServiceSubscription> &aService) {
957 return aService->mType == aType && aService->mInstanceName == aInstanceName;
958 });
959 VerifyOrExit(it != mSubscribedServices.end());
960
961 mSubscribedServices.erase(it);
962
963 otbrLogInfo("Unsubscribe service %s.%s (left %zu)", aInstanceName.c_str(), aType.c_str(),
964 mSubscribedServices.size());
965
966 exit:
967 return;
968 }
969
OnServiceResolveFailedImpl(const std::string & aType,const std::string & aInstanceName,int32_t aErrorCode)970 void PublisherMDnsSd::OnServiceResolveFailedImpl(const std::string &aType,
971 const std::string &aInstanceName,
972 int32_t aErrorCode)
973 {
974 otbrLogWarning("Resolve service %s.%s failed: code=%" PRId32, aInstanceName.c_str(), aType.c_str(), aErrorCode);
975 }
976
OnHostResolveFailedImpl(const std::string & aHostName,int32_t aErrorCode)977 void PublisherMDnsSd::OnHostResolveFailedImpl(const std::string &aHostName, int32_t aErrorCode)
978 {
979 otbrLogWarning("Resolve host %s failed: code=%" PRId32, aHostName.c_str(), aErrorCode);
980 }
981
DnsErrorToOtbrError(int32_t aErrorCode)982 otbrError PublisherMDnsSd::DnsErrorToOtbrError(int32_t aErrorCode)
983 {
984 return otbr::Mdns::DNSErrorToOtbrError(aErrorCode);
985 }
986
SubscribeHost(const std::string & aHostName)987 void PublisherMDnsSd::SubscribeHost(const std::string &aHostName)
988 {
989 VerifyOrExit(mState == State::kReady);
990 mSubscribedHosts.push_back(MakeUnique<HostSubscription>(*this, aHostName));
991
992 otbrLogInfo("Subscribe host %s (total %zu)", aHostName.c_str(), mSubscribedHosts.size());
993
994 mSubscribedHosts.back()->Resolve();
995
996 exit:
997 return;
998 }
999
UnsubscribeHost(const std::string & aHostName)1000 void PublisherMDnsSd::UnsubscribeHost(const std::string &aHostName)
1001 {
1002 HostSubscriptionList ::iterator it;
1003
1004 VerifyOrExit(mState == Publisher::State::kReady);
1005 it = std::find_if(
1006 mSubscribedHosts.begin(), mSubscribedHosts.end(),
1007 [&aHostName](const std::unique_ptr<HostSubscription> &aHost) { return aHost->mHostName == aHostName; });
1008
1009 VerifyOrExit(it != mSubscribedHosts.end());
1010
1011 mSubscribedHosts.erase(it);
1012
1013 otbrLogInfo("Unsubscribe host %s (remaining %d)", aHostName.c_str(), mSubscribedHosts.size());
1014
1015 exit:
1016 return;
1017 }
1018
Create(StateCallback aCallback)1019 Publisher *Publisher::Create(StateCallback aCallback)
1020 {
1021 return new PublisherMDnsSd(aCallback);
1022 }
1023
Destroy(Publisher * aPublisher)1024 void Publisher::Destroy(Publisher *aPublisher)
1025 {
1026 delete static_cast<PublisherMDnsSd *>(aPublisher);
1027 }
1028
Release(void)1029 void PublisherMDnsSd::ServiceRef::Release(void)
1030 {
1031 DeallocateServiceRef();
1032 }
1033
DeallocateServiceRef(void)1034 void PublisherMDnsSd::ServiceRef::DeallocateServiceRef(void)
1035 {
1036 if (mServiceRef != nullptr)
1037 {
1038 mPublisher.HandleServiceRefDeallocating(mServiceRef);
1039 DNSServiceRefDeallocate(mServiceRef);
1040 mServiceRef = nullptr;
1041 }
1042 }
1043
Update(MainloopContext & aMainloop) const1044 void PublisherMDnsSd::ServiceRef::Update(MainloopContext &aMainloop) const
1045 {
1046 int fd;
1047
1048 VerifyOrExit(mServiceRef != nullptr);
1049
1050 fd = DNSServiceRefSockFD(mServiceRef);
1051 assert(fd != -1);
1052 aMainloop.AddFdToReadSet(fd);
1053 exit:
1054 return;
1055 }
1056
Process(const MainloopContext & aMainloop,std::vector<DNSServiceRef> & aReadyServices) const1057 void PublisherMDnsSd::ServiceRef::Process(const MainloopContext &aMainloop,
1058 std::vector<DNSServiceRef> &aReadyServices) const
1059 {
1060 int fd;
1061
1062 VerifyOrExit(mServiceRef != nullptr);
1063
1064 fd = DNSServiceRefSockFD(mServiceRef);
1065 assert(fd != -1);
1066 if (FD_ISSET(fd, &aMainloop.mReadFdSet))
1067 {
1068 aReadyServices.push_back(mServiceRef);
1069 }
1070 exit:
1071 return;
1072 }
1073
Browse(void)1074 void PublisherMDnsSd::ServiceSubscription::Browse(void)
1075 {
1076 assert(mServiceRef == nullptr);
1077
1078 otbrLogInfo("DNSServiceBrowse %s", mType.c_str());
1079 DNSServiceBrowse(&mServiceRef, /* flags */ 0, kDNSServiceInterfaceIndexAny, mType.c_str(),
1080 /* domain */ nullptr, HandleBrowseResult, this);
1081 }
1082
HandleBrowseResult(DNSServiceRef aServiceRef,DNSServiceFlags aFlags,uint32_t aInterfaceIndex,DNSServiceErrorType aErrorCode,const char * aInstanceName,const char * aType,const char * aDomain,void * aContext)1083 void PublisherMDnsSd::ServiceSubscription::HandleBrowseResult(DNSServiceRef aServiceRef,
1084 DNSServiceFlags aFlags,
1085 uint32_t aInterfaceIndex,
1086 DNSServiceErrorType aErrorCode,
1087 const char *aInstanceName,
1088 const char *aType,
1089 const char *aDomain,
1090 void *aContext)
1091 {
1092 static_cast<ServiceSubscription *>(aContext)->HandleBrowseResult(aServiceRef, aFlags, aInterfaceIndex, aErrorCode,
1093 aInstanceName, aType, aDomain);
1094 }
1095
HandleBrowseResult(DNSServiceRef aServiceRef,DNSServiceFlags aFlags,uint32_t aInterfaceIndex,DNSServiceErrorType aErrorCode,const char * aInstanceName,const char * aType,const char * aDomain)1096 void PublisherMDnsSd::ServiceSubscription::HandleBrowseResult(DNSServiceRef aServiceRef,
1097 DNSServiceFlags aFlags,
1098 uint32_t aInterfaceIndex,
1099 DNSServiceErrorType aErrorCode,
1100 const char *aInstanceName,
1101 const char *aType,
1102 const char *aDomain)
1103 {
1104 OTBR_UNUSED_VARIABLE(aServiceRef);
1105 OTBR_UNUSED_VARIABLE(aDomain);
1106
1107 otbrLogInfo("DNSServiceBrowse reply: %s %s.%s inf %" PRIu32 ", flags=%" PRIu32 ", error=%" PRId32,
1108 aFlags & kDNSServiceFlagsAdd ? "add" : "remove", aInstanceName, aType, aInterfaceIndex, aFlags,
1109 aErrorCode);
1110
1111 VerifyOrExit(aErrorCode == kDNSServiceErr_NoError);
1112
1113 if (aFlags & kDNSServiceFlagsAdd)
1114 {
1115 Resolve(aInterfaceIndex, aInstanceName, aType, aDomain);
1116 }
1117 else
1118 {
1119 mPublisher.OnServiceRemoved(aInterfaceIndex, mType, aInstanceName);
1120 }
1121
1122 exit:
1123 if (aErrorCode != kDNSServiceErr_NoError)
1124 {
1125 mPublisher.OnServiceResolveFailed(mType, mInstanceName, aErrorCode);
1126 Release();
1127 }
1128 }
1129
Resolve(uint32_t aInterfaceIndex,const std::string & aInstanceName,const std::string & aType,const std::string & aDomain)1130 void PublisherMDnsSd::ServiceSubscription::Resolve(uint32_t aInterfaceIndex,
1131 const std::string &aInstanceName,
1132 const std::string &aType,
1133 const std::string &aDomain)
1134 {
1135 mResolvingInstances.push_back(
1136 MakeUnique<ServiceInstanceResolution>(*this, aInstanceName, aType, aDomain, aInterfaceIndex));
1137 mResolvingInstances.back()->Resolve();
1138 }
1139
UpdateAll(MainloopContext & aMainloop) const1140 void PublisherMDnsSd::ServiceSubscription::UpdateAll(MainloopContext &aMainloop) const
1141 {
1142 Update(aMainloop);
1143
1144 for (const auto &instance : mResolvingInstances)
1145 {
1146 instance->Update(aMainloop);
1147 }
1148 }
1149
ProcessAll(const MainloopContext & aMainloop,std::vector<DNSServiceRef> & aReadyServices) const1150 void PublisherMDnsSd::ServiceSubscription::ProcessAll(const MainloopContext &aMainloop,
1151 std::vector<DNSServiceRef> &aReadyServices) const
1152 {
1153 Process(aMainloop, aReadyServices);
1154
1155 for (const auto &instance : mResolvingInstances)
1156 {
1157 instance->Process(aMainloop, aReadyServices);
1158 }
1159 }
1160
Resolve(void)1161 void PublisherMDnsSd::ServiceInstanceResolution::Resolve(void)
1162 {
1163 assert(mServiceRef == nullptr);
1164
1165 mSubscription->mPublisher.mServiceInstanceResolutionBeginTime[std::make_pair(mInstanceName, mType)] = Clock::now();
1166
1167 otbrLogInfo("DNSServiceResolve %s %s inf %u", mInstanceName.c_str(), mType.c_str(), mNetifIndex);
1168 DNSServiceResolve(&mServiceRef, /* flags */ kDNSServiceFlagsTimeout, mNetifIndex, mInstanceName.c_str(),
1169 mType.c_str(), mDomain.c_str(), HandleResolveResult, this);
1170 }
1171
HandleResolveResult(DNSServiceRef aServiceRef,DNSServiceFlags aFlags,uint32_t aInterfaceIndex,DNSServiceErrorType aErrorCode,const char * aFullName,const char * aHostTarget,uint16_t aPort,uint16_t aTxtLen,const unsigned char * aTxtRecord,void * aContext)1172 void PublisherMDnsSd::ServiceInstanceResolution::HandleResolveResult(DNSServiceRef aServiceRef,
1173 DNSServiceFlags aFlags,
1174 uint32_t aInterfaceIndex,
1175 DNSServiceErrorType aErrorCode,
1176 const char *aFullName,
1177 const char *aHostTarget,
1178 uint16_t aPort,
1179 uint16_t aTxtLen,
1180 const unsigned char *aTxtRecord,
1181 void *aContext)
1182 {
1183 static_cast<ServiceInstanceResolution *>(aContext)->HandleResolveResult(
1184 aServiceRef, aFlags, aInterfaceIndex, aErrorCode, aFullName, aHostTarget, aPort, aTxtLen, aTxtRecord);
1185 }
1186
HandleResolveResult(DNSServiceRef aServiceRef,DNSServiceFlags aFlags,uint32_t aInterfaceIndex,DNSServiceErrorType aErrorCode,const char * aFullName,const char * aHostTarget,uint16_t aPort,uint16_t aTxtLen,const unsigned char * aTxtRecord)1187 void PublisherMDnsSd::ServiceInstanceResolution::HandleResolveResult(DNSServiceRef aServiceRef,
1188 DNSServiceFlags aFlags,
1189 uint32_t aInterfaceIndex,
1190 DNSServiceErrorType aErrorCode,
1191 const char *aFullName,
1192 const char *aHostTarget,
1193 uint16_t aPort,
1194 uint16_t aTxtLen,
1195 const unsigned char *aTxtRecord)
1196 {
1197 OTBR_UNUSED_VARIABLE(aServiceRef);
1198
1199 std::string instanceName, type, domain;
1200 otbrError error = OTBR_ERROR_NONE;
1201
1202 otbrLogInfo("DNSServiceResolve reply: %s host %s:%d, TXT=%dB inf %u, flags=%u", aFullName, aHostTarget, aPort,
1203 aTxtLen, aInterfaceIndex, aFlags);
1204
1205 VerifyOrExit(aErrorCode == kDNSServiceErr_NoError);
1206
1207 SuccessOrExit(error = SplitFullServiceInstanceName(aFullName, instanceName, type, domain));
1208
1209 mInstanceInfo.mNetifIndex = aInterfaceIndex;
1210 mInstanceInfo.mName = instanceName;
1211 mInstanceInfo.mHostName = aHostTarget;
1212 mInstanceInfo.mPort = ntohs(aPort);
1213 mInstanceInfo.mTxtData.assign(aTxtRecord, aTxtRecord + aTxtLen);
1214 // priority and weight are not given in the reply
1215 mInstanceInfo.mPriority = 0;
1216 mInstanceInfo.mWeight = 0;
1217
1218 DeallocateServiceRef();
1219 error = GetAddrInfo(aInterfaceIndex);
1220
1221 exit:
1222 if (error != OTBR_ERROR_NONE)
1223 {
1224 otbrLogWarning("Failed to resolve service instance %s", aFullName);
1225 }
1226
1227 if (aErrorCode != kDNSServiceErr_NoError || error != OTBR_ERROR_NONE)
1228 {
1229 mSubscription->mPublisher.OnServiceResolveFailed(mSubscription->mType, mInstanceName, aErrorCode);
1230 FinishResolution();
1231 }
1232 }
1233
GetAddrInfo(uint32_t aInterfaceIndex)1234 otbrError PublisherMDnsSd::ServiceInstanceResolution::GetAddrInfo(uint32_t aInterfaceIndex)
1235 {
1236 DNSServiceErrorType dnsError;
1237
1238 assert(mServiceRef == nullptr);
1239
1240 otbrLogInfo("DNSServiceGetAddrInfo %s inf %d", mInstanceInfo.mHostName.c_str(), aInterfaceIndex);
1241
1242 dnsError = DNSServiceGetAddrInfo(&mServiceRef, /* flags */ 0, aInterfaceIndex,
1243 kDNSServiceProtocol_IPv6 | kDNSServiceProtocol_IPv4,
1244 mInstanceInfo.mHostName.c_str(), HandleGetAddrInfoResult, this);
1245
1246 if (dnsError != kDNSServiceErr_NoError)
1247 {
1248 otbrLogWarning("DNSServiceGetAddrInfo failed: %s", DNSErrorToString(dnsError));
1249 }
1250
1251 return dnsError == kDNSServiceErr_NoError ? OTBR_ERROR_NONE : OTBR_ERROR_MDNS;
1252 }
1253
HandleGetAddrInfoResult(DNSServiceRef aServiceRef,DNSServiceFlags aFlags,uint32_t aInterfaceIndex,DNSServiceErrorType aErrorCode,const char * aHostName,const struct sockaddr * aAddress,uint32_t aTtl,void * aContext)1254 void PublisherMDnsSd::ServiceInstanceResolution::HandleGetAddrInfoResult(DNSServiceRef aServiceRef,
1255 DNSServiceFlags aFlags,
1256 uint32_t aInterfaceIndex,
1257 DNSServiceErrorType aErrorCode,
1258 const char *aHostName,
1259 const struct sockaddr *aAddress,
1260 uint32_t aTtl,
1261 void *aContext)
1262 {
1263 static_cast<ServiceInstanceResolution *>(aContext)->HandleGetAddrInfoResult(aServiceRef, aFlags, aInterfaceIndex,
1264 aErrorCode, aHostName, aAddress, aTtl);
1265 }
1266
HandleGetAddrInfoResult(DNSServiceRef aServiceRef,DNSServiceFlags aFlags,uint32_t aInterfaceIndex,DNSServiceErrorType aErrorCode,const char * aHostName,const struct sockaddr * aAddress,uint32_t aTtl)1267 void PublisherMDnsSd::ServiceInstanceResolution::HandleGetAddrInfoResult(DNSServiceRef aServiceRef,
1268 DNSServiceFlags aFlags,
1269 uint32_t aInterfaceIndex,
1270 DNSServiceErrorType aErrorCode,
1271 const char *aHostName,
1272 const struct sockaddr *aAddress,
1273 uint32_t aTtl)
1274 {
1275 OTBR_UNUSED_VARIABLE(aServiceRef);
1276 OTBR_UNUSED_VARIABLE(aInterfaceIndex);
1277
1278 Ip6Address address;
1279 bool isAdd = (aFlags & kDNSServiceFlagsAdd) != 0;
1280 bool moreComing = (aFlags & kDNSServiceFlagsMoreComing) != 0;
1281
1282 otbrLog(aErrorCode == kDNSServiceErr_NoError ? OTBR_LOG_INFO : OTBR_LOG_WARNING, OTBR_LOG_TAG,
1283 "DNSServiceGetAddrInfo reply: flags=%" PRIu32 ", host=%s, sa_family=%u, error=%" PRId32, aFlags, aHostName,
1284 static_cast<unsigned int>(aAddress->sa_family), aErrorCode);
1285
1286 VerifyOrExit(aErrorCode == kDNSServiceErr_NoError);
1287 VerifyOrExit(aAddress->sa_family == AF_INET6);
1288
1289 address.CopyFrom(*reinterpret_cast<const struct sockaddr_in6 *>(aAddress));
1290 VerifyOrExit(!address.IsUnspecified() && !address.IsMulticast() && !address.IsLoopback(),
1291 otbrLogDebug("DNSServiceGetAddrInfo ignores address %s", address.ToString().c_str()));
1292
1293 otbrLogInfo("DNSServiceGetAddrInfo reply: %s address=%s, ttl=%" PRIu32, isAdd ? "add" : "remove",
1294 address.ToString().c_str(), aTtl);
1295
1296 if (isAdd)
1297 {
1298 mInstanceInfo.AddAddress(address);
1299 }
1300 else
1301 {
1302 mInstanceInfo.RemoveAddress(address);
1303 }
1304 mInstanceInfo.mTtl = aTtl;
1305
1306 exit:
1307 if ((!mInstanceInfo.mAddresses.empty() && !moreComing) || aErrorCode != kDNSServiceErr_NoError)
1308 {
1309 FinishResolution();
1310 }
1311 }
1312
FinishResolution(void)1313 void PublisherMDnsSd::ServiceInstanceResolution::FinishResolution(void)
1314 {
1315 ServiceSubscription *subscription = mSubscription;
1316 std::string serviceName = mSubscription->mType;
1317 DiscoveredInstanceInfo instanceInfo = mInstanceInfo;
1318
1319 // NOTE: The `ServiceSubscription` object may be freed in `OnServiceResolved`.
1320 subscription->mPublisher.OnServiceResolved(serviceName, instanceInfo);
1321 }
1322
Resolve(void)1323 void PublisherMDnsSd::HostSubscription::Resolve(void)
1324 {
1325 std::string fullHostName = MakeFullHostName(mHostName);
1326
1327 assert(mServiceRef == nullptr);
1328
1329 mPublisher.mHostResolutionBeginTime[mHostName] = Clock::now();
1330
1331 otbrLogInfo("DNSServiceGetAddrInfo %s inf %d", fullHostName.c_str(), kDNSServiceInterfaceIndexAny);
1332
1333 DNSServiceGetAddrInfo(&mServiceRef, /* flags */ 0, kDNSServiceInterfaceIndexAny,
1334 kDNSServiceProtocol_IPv6 | kDNSServiceProtocol_IPv4, fullHostName.c_str(),
1335 HandleResolveResult, this);
1336 }
1337
HandleResolveResult(DNSServiceRef aServiceRef,DNSServiceFlags aFlags,uint32_t aInterfaceIndex,DNSServiceErrorType aErrorCode,const char * aHostName,const struct sockaddr * aAddress,uint32_t aTtl,void * aContext)1338 void PublisherMDnsSd::HostSubscription::HandleResolveResult(DNSServiceRef aServiceRef,
1339 DNSServiceFlags aFlags,
1340 uint32_t aInterfaceIndex,
1341 DNSServiceErrorType aErrorCode,
1342 const char *aHostName,
1343 const struct sockaddr *aAddress,
1344 uint32_t aTtl,
1345 void *aContext)
1346 {
1347 static_cast<HostSubscription *>(aContext)->HandleResolveResult(aServiceRef, aFlags, aInterfaceIndex, aErrorCode,
1348 aHostName, aAddress, aTtl);
1349 }
1350
HandleResolveResult(DNSServiceRef aServiceRef,DNSServiceFlags aFlags,uint32_t aInterfaceIndex,DNSServiceErrorType aErrorCode,const char * aHostName,const struct sockaddr * aAddress,uint32_t aTtl)1351 void PublisherMDnsSd::HostSubscription::HandleResolveResult(DNSServiceRef aServiceRef,
1352 DNSServiceFlags aFlags,
1353 uint32_t aInterfaceIndex,
1354 DNSServiceErrorType aErrorCode,
1355 const char *aHostName,
1356 const struct sockaddr *aAddress,
1357 uint32_t aTtl)
1358 {
1359 OTBR_UNUSED_VARIABLE(aServiceRef);
1360
1361 Ip6Address address;
1362 bool isAdd = (aFlags & kDNSServiceFlagsAdd) != 0;
1363 bool moreComing = (aFlags & kDNSServiceFlagsMoreComing) != 0;
1364
1365 otbrLog(aErrorCode == kDNSServiceErr_NoError ? OTBR_LOG_INFO : OTBR_LOG_WARNING, OTBR_LOG_TAG,
1366 "DNSServiceGetAddrInfo reply: flags=%" PRIu32 ", host=%s, sa_family=%u, error=%" PRId32, aFlags, aHostName,
1367 static_cast<unsigned int>(aAddress->sa_family), aErrorCode);
1368
1369 VerifyOrExit(aErrorCode == kDNSServiceErr_NoError);
1370 VerifyOrExit(aAddress->sa_family == AF_INET6);
1371
1372 address.CopyFrom(*reinterpret_cast<const struct sockaddr_in6 *>(aAddress));
1373
1374 otbrLogInfo("DNSServiceGetAddrInfo reply: %s address=%s, ttl=%" PRIu32, isAdd ? "add" : "remove",
1375 address.ToString().c_str(), aTtl);
1376
1377 if (isAdd)
1378 {
1379 mHostInfo.AddAddress(address);
1380 }
1381 else
1382 {
1383 mHostInfo.RemoveAddress(address);
1384 }
1385 mHostInfo.mHostName = aHostName;
1386 mHostInfo.mNetifIndex = aInterfaceIndex;
1387 mHostInfo.mTtl = aTtl;
1388
1389 exit:
1390 if (aErrorCode != kDNSServiceErr_NoError)
1391 {
1392 mPublisher.OnHostResolveFailed(aHostName, aErrorCode);
1393 }
1394 else if (!moreComing && !mHostInfo.mAddresses.empty())
1395 {
1396 mPublisher.OnHostResolved(mHostName, mHostInfo);
1397 }
1398 }
1399
1400 } // namespace Mdns
1401
1402 } // namespace otbr
1403