• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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