• 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     default:
92         error = OTBR_ERROR_MDNS;
93         break;
94     }
95 
96     return error;
97 }
98 
DNSErrorToString(DNSServiceErrorType aError)99 static const char *DNSErrorToString(DNSServiceErrorType aError)
100 {
101     switch (aError)
102     {
103     case kDNSServiceErr_NoError:
104         return "OK";
105 
106     case kDNSServiceErr_Unknown:
107         // 0xFFFE FFFF
108         return "Unknown";
109 
110     case kDNSServiceErr_NoSuchName:
111         return "No Such Name";
112 
113     case kDNSServiceErr_NoMemory:
114         return "No Memory";
115 
116     case kDNSServiceErr_BadParam:
117         return "Bad Param";
118 
119     case kDNSServiceErr_BadReference:
120         return "Bad Reference";
121 
122     case kDNSServiceErr_BadState:
123         return "Bad State";
124 
125     case kDNSServiceErr_BadFlags:
126         return "Bad Flags";
127 
128     case kDNSServiceErr_Unsupported:
129         return "Unsupported";
130 
131     case kDNSServiceErr_NotInitialized:
132         return "Not Initialized";
133 
134     case kDNSServiceErr_AlreadyRegistered:
135         return "Already Registered";
136 
137     case kDNSServiceErr_NameConflict:
138         return "Name Conflict";
139 
140     case kDNSServiceErr_Invalid:
141         return "Invalid";
142 
143     case kDNSServiceErr_Firewall:
144         return "Firewall";
145 
146     case kDNSServiceErr_Incompatible:
147         // client library incompatible with daemon
148         return "Incompatible";
149 
150     case kDNSServiceErr_BadInterfaceIndex:
151         return "Bad Interface Index";
152 
153     case kDNSServiceErr_Refused:
154         return "Refused";
155 
156     case kDNSServiceErr_NoSuchRecord:
157         return "No Such Record";
158 
159     case kDNSServiceErr_NoAuth:
160         return "No Auth";
161 
162     case kDNSServiceErr_NoSuchKey:
163         return "No Such Key";
164 
165     case kDNSServiceErr_NATTraversal:
166         return "NAT Traversal";
167 
168     case kDNSServiceErr_DoubleNAT:
169         return "Double NAT";
170 
171     case kDNSServiceErr_BadTime:
172         // Codes up to here existed in Tiger
173         return "Bad Time";
174 
175     case kDNSServiceErr_BadSig:
176         return "Bad Sig";
177 
178     case kDNSServiceErr_BadKey:
179         return "Bad Key";
180 
181     case kDNSServiceErr_Transient:
182         return "Transient";
183 
184     case kDNSServiceErr_ServiceNotRunning:
185         // Background daemon not running
186         return "Service Not Running";
187 
188     case kDNSServiceErr_NATPortMappingUnsupported:
189         // NAT doesn't support NAT-PMP or UPnP
190         return "NAT Port Mapping Unsupported";
191 
192     case kDNSServiceErr_NATPortMappingDisabled:
193         // NAT supports NAT-PMP or UPnP but it's disabled by the administrator
194         return "NAT Port Mapping Disabled";
195 
196     case kDNSServiceErr_NoRouter:
197         // No router currently configured (probably no network connectivity)
198         return "No Router";
199 
200     case kDNSServiceErr_PollingMode:
201         return "Polling Mode";
202 
203     case kDNSServiceErr_Timeout:
204         return "Timeout";
205 
206     default:
207         assert(false);
208         return nullptr;
209     }
210 }
211 
PublisherMDnsSd(StateCallback aCallback)212 PublisherMDnsSd::PublisherMDnsSd(StateCallback aCallback)
213     : mHostsRef(nullptr)
214     , mState(State::kIdle)
215     , mStateCallback(std::move(aCallback))
216 {
217 }
218 
~PublisherMDnsSd(void)219 PublisherMDnsSd::~PublisherMDnsSd(void)
220 {
221     Stop();
222 }
223 
Start(void)224 otbrError PublisherMDnsSd::Start(void)
225 {
226     mState = State::kReady;
227     mStateCallback(State::kReady);
228     return OTBR_ERROR_NONE;
229 }
230 
IsStarted(void) const231 bool PublisherMDnsSd::IsStarted(void) const
232 {
233     return mState == State::kReady;
234 }
235 
Stop(void)236 void PublisherMDnsSd::Stop(void)
237 {
238     ServiceRegistrationMap serviceRegistrations;
239     HostRegistrationMap    hostRegistrations;
240 
241     VerifyOrExit(mState == State::kReady);
242 
243     std::swap(mServiceRegistrations, serviceRegistrations);
244     std::swap(mHostRegistrations, hostRegistrations);
245 
246     if (mHostsRef != nullptr)
247     {
248         DNSServiceRefDeallocate(mHostsRef);
249         otbrLogDebug("Deallocated DNSServiceRef for hosts: %p", mHostsRef);
250         mHostsRef = nullptr;
251     }
252 
253     mSubscribedServices.clear();
254 
255     mSubscribedHosts.clear();
256 
257     mState = State::kIdle;
258 
259 exit:
260     return;
261 }
262 
Update(MainloopContext & aMainloop)263 void PublisherMDnsSd::Update(MainloopContext &aMainloop)
264 {
265     for (auto &kv : mServiceRegistrations)
266     {
267         auto &serviceReg = static_cast<DnssdServiceRegistration &>(*kv.second);
268 
269         assert(serviceReg.GetServiceRef() != nullptr);
270 
271         int fd = DNSServiceRefSockFD(serviceReg.GetServiceRef());
272 
273         if (fd != -1)
274         {
275             FD_SET(fd, &aMainloop.mReadFdSet);
276             aMainloop.mMaxFd = std::max(aMainloop.mMaxFd, fd);
277         }
278     }
279 
280     if (mHostsRef != nullptr)
281     {
282         int fd = DNSServiceRefSockFD(mHostsRef);
283 
284         assert(fd != -1);
285 
286         FD_SET(fd, &aMainloop.mReadFdSet);
287 
288         aMainloop.mMaxFd = std::max(aMainloop.mMaxFd, fd);
289     }
290 
291     for (const auto &service : mSubscribedServices)
292     {
293         service->UpdateAll(aMainloop);
294     }
295 
296     for (const auto &host : mSubscribedHosts)
297     {
298         host->Update(aMainloop);
299     }
300 }
301 
Process(const MainloopContext & aMainloop)302 void PublisherMDnsSd::Process(const MainloopContext &aMainloop)
303 {
304     std::vector<DNSServiceRef> readyServices;
305 
306     for (auto &kv : mServiceRegistrations)
307     {
308         auto &serviceReg = static_cast<DnssdServiceRegistration &>(*kv.second);
309         int   fd         = DNSServiceRefSockFD(serviceReg.GetServiceRef());
310 
311         if (FD_ISSET(fd, &aMainloop.mReadFdSet))
312         {
313             readyServices.push_back(serviceReg.GetServiceRef());
314         }
315     }
316 
317     if (mHostsRef != nullptr)
318     {
319         int fd = DNSServiceRefSockFD(mHostsRef);
320 
321         if (FD_ISSET(fd, &aMainloop.mReadFdSet))
322         {
323             readyServices.push_back(mHostsRef);
324         }
325     }
326 
327     for (const auto &service : mSubscribedServices)
328     {
329         service->ProcessAll(aMainloop, readyServices);
330     }
331 
332     for (const auto &host : mSubscribedHosts)
333     {
334         host->Process(aMainloop, readyServices);
335     }
336 
337     for (DNSServiceRef serviceRef : readyServices)
338     {
339         DNSServiceErrorType error = DNSServiceProcessResult(serviceRef);
340 
341         if (error != kDNSServiceErr_NoError)
342         {
343             otbrLogLevel logLevel = (error == kDNSServiceErr_BadReference) ? OTBR_LOG_INFO : OTBR_LOG_WARNING;
344             otbrLog(logLevel, OTBR_LOG_TAG, "DNSServiceProcessResult failed: %s (serviceRef = %p)",
345                     DNSErrorToString(error), serviceRef);
346         }
347         if (error == kDNSServiceErr_ServiceNotRunning)
348         {
349             otbrLogWarning("Need to reconnect to mdnsd");
350             Stop();
351             Start();
352             ExitNow();
353         }
354     }
355 exit:
356     return;
357 }
358 
~DnssdServiceRegistration(void)359 PublisherMDnsSd::DnssdServiceRegistration::~DnssdServiceRegistration(void)
360 {
361     if (mServiceRef != nullptr)
362     {
363         DNSServiceRefDeallocate(mServiceRef);
364     }
365 }
366 
~DnssdHostRegistration(void)367 PublisherMDnsSd::DnssdHostRegistration::~DnssdHostRegistration(void)
368 {
369     VerifyOrExit(mServiceRef != nullptr && mRecordRef != nullptr);
370 
371     if (IsCompleted())
372     {
373         // The Bonjour mDNSResponder somehow doesn't send goodbye message for the AAAA record when it is
374         // removed by `DNSServiceRemoveRecord`. Per RFC 6762, a goodbye message of a record sets its TTL
375         // to zero but the receiver should record the TTL of 1 and flushes the cache 1 second later. Here
376         // we remove the AAAA record after updating its TTL to 1 second. This has the same effect as
377         // sending a goodbye message.
378         // TODO: resolve the goodbye issue with Bonjour mDNSResponder.
379         int dnsError = DNSServiceUpdateRecord(mServiceRef, mRecordRef, kDNSServiceFlagsUnique, mAddress.size(),
380                                               mAddress.data(), /* ttl */ 1);
381         otbrLogWarning("Failed to send goodbye message for host %s: %s", MakeFullHostName(mName).c_str(),
382                        DNSErrorToString(dnsError));
383     }
384 
385     DNSServiceRemoveRecord(mServiceRef, mRecordRef, /* flags */ 0);
386     // TODO: ?
387     // DNSRecordRefDeallocate(mRecordRef);
388 
389 exit:
390     return;
391 }
392 
FindServiceRegistration(const DNSServiceRef & aServiceRef)393 Publisher::ServiceRegistration *PublisherMDnsSd::FindServiceRegistration(const DNSServiceRef &aServiceRef)
394 {
395     ServiceRegistration *result = nullptr;
396 
397     for (auto &kv : mServiceRegistrations)
398     {
399         // We are sure that the service registrations must be instances of `DnssdServiceRegistration`.
400         auto &serviceReg = static_cast<DnssdServiceRegistration &>(*kv.second);
401 
402         if (serviceReg.GetServiceRef() == aServiceRef)
403         {
404             result = kv.second.get();
405             break;
406         }
407     }
408 
409     return result;
410 }
411 
FindHostRegistration(const DNSServiceRef & aServiceRef,const DNSRecordRef & aRecordRef)412 Publisher::HostRegistration *PublisherMDnsSd::FindHostRegistration(const DNSServiceRef &aServiceRef,
413                                                                    const DNSRecordRef & aRecordRef)
414 {
415     HostRegistration *result = nullptr;
416 
417     for (auto &kv : mHostRegistrations)
418     {
419         // We are sure that the host registrations must be instances of `DnssdHostRegistration`.
420         auto &hostReg = static_cast<DnssdHostRegistration &>(*kv.second);
421 
422         if (hostReg.GetServiceRef() == aServiceRef && hostReg.GetRecordRef() == aRecordRef)
423         {
424             result = kv.second.get();
425             break;
426         }
427     }
428 
429     return result;
430 }
431 
HandleServiceRegisterResult(DNSServiceRef aService,const DNSServiceFlags aFlags,DNSServiceErrorType aError,const char * aName,const char * aType,const char * aDomain,void * aContext)432 void PublisherMDnsSd::HandleServiceRegisterResult(DNSServiceRef         aService,
433                                                   const DNSServiceFlags aFlags,
434                                                   DNSServiceErrorType   aError,
435                                                   const char *          aName,
436                                                   const char *          aType,
437                                                   const char *          aDomain,
438                                                   void *                aContext)
439 {
440     static_cast<PublisherMDnsSd *>(aContext)->HandleServiceRegisterResult(aService, aFlags, aError, aName, aType,
441                                                                           aDomain);
442 }
443 
HandleServiceRegisterResult(DNSServiceRef aServiceRef,const DNSServiceFlags aFlags,DNSServiceErrorType aError,const char * aName,const char * aType,const char * aDomain)444 void PublisherMDnsSd::HandleServiceRegisterResult(DNSServiceRef         aServiceRef,
445                                                   const DNSServiceFlags aFlags,
446                                                   DNSServiceErrorType   aError,
447                                                   const char *          aName,
448                                                   const char *          aType,
449                                                   const char *          aDomain)
450 {
451     OTBR_UNUSED_VARIABLE(aDomain);
452 
453     otbrError            error = DNSErrorToOtbrError(aError);
454     std::string          originalInstanceName;
455     ServiceRegistration *serviceReg = FindServiceRegistration(aServiceRef);
456 
457     otbrLogInfo("Received reply for service %s.%s, serviceRef = %p", aName, aType, aServiceRef);
458 
459     VerifyOrExit(serviceReg != nullptr);
460 
461     if (aError == kDNSServiceErr_NoError && (aFlags & kDNSServiceFlagsAdd))
462     {
463         otbrLogInfo("Successfully registered service %s.%s", aName, aType);
464         serviceReg->Complete(OTBR_ERROR_NONE);
465     }
466     else
467     {
468         otbrLogErr("Failed to register service %s.%s: %s", aName, aType, DNSErrorToString(aError));
469         RemoveServiceRegistration(serviceReg->mName, serviceReg->mType, error);
470     }
471 
472 exit:
473     return;
474 }
475 
PublishServiceImpl(const std::string & aHostName,const std::string & aName,const std::string & aType,const SubTypeList & aSubTypeList,uint16_t aPort,const TxtList & aTxtList,ResultCallback && aCallback)476 void PublisherMDnsSd::PublishServiceImpl(const std::string &aHostName,
477                                          const std::string &aName,
478                                          const std::string &aType,
479                                          const SubTypeList &aSubTypeList,
480                                          uint16_t           aPort,
481                                          const TxtList &    aTxtList,
482                                          ResultCallback &&  aCallback)
483 {
484     otbrError            ret   = OTBR_ERROR_NONE;
485     int                  error = 0;
486     std::vector<uint8_t> txt;
487     SubTypeList          sortedSubTypeList = SortSubTypeList(aSubTypeList);
488     TxtList              sortedTxtList     = SortTxtList(aTxtList);
489     std::string          regType           = MakeRegType(aType, sortedSubTypeList);
490     DNSServiceRef        serviceRef        = nullptr;
491     std::string          fullHostName;
492 
493     VerifyOrExit(mState == State::kReady, ret = OTBR_ERROR_INVALID_STATE);
494 
495     if (!aHostName.empty())
496     {
497         fullHostName = MakeFullHostName(aHostName);
498     }
499 
500     aCallback = HandleDuplicateServiceRegistration(aHostName, aName, aType, sortedSubTypeList, aPort, sortedTxtList,
501                                                    std::move(aCallback));
502     VerifyOrExit(!aCallback.IsNull());
503 
504     SuccessOrExit(ret = EncodeTxtData(aTxtList, txt));
505     otbrLogInfo("Registering new service %s.%s.local, serviceRef = %p", aName.c_str(), regType.c_str(), serviceRef);
506     SuccessOrExit(error = DNSServiceRegister(&serviceRef, kDNSServiceFlagsNoAutoRename, kDNSServiceInterfaceIndexAny,
507                                              aName.c_str(), regType.c_str(), /* domain */ nullptr,
508                                              !aHostName.empty() ? fullHostName.c_str() : nullptr, htons(aPort),
509                                              txt.size(), txt.data(), HandleServiceRegisterResult, this));
510     AddServiceRegistration(std::unique_ptr<DnssdServiceRegistration>(new DnssdServiceRegistration(
511         aHostName, aName, aType, sortedSubTypeList, aPort, sortedTxtList, std::move(aCallback), serviceRef, this)));
512 
513 exit:
514     if (error != kDNSServiceErr_NoError || ret != OTBR_ERROR_NONE)
515     {
516         if (error != kDNSServiceErr_NoError)
517         {
518             ret = DNSErrorToOtbrError(error);
519             otbrLogErr("Failed to publish service %s.%s for mdnssd error: %s!", aName.c_str(), aType.c_str(),
520                        DNSErrorToString(error));
521         }
522 
523         if (serviceRef != nullptr)
524         {
525             DNSServiceRefDeallocate(serviceRef);
526         }
527         std::move(aCallback)(ret);
528     }
529 }
530 
UnpublishService(const std::string & aName,const std::string & aType,ResultCallback && aCallback)531 void PublisherMDnsSd::UnpublishService(const std::string &aName, const std::string &aType, ResultCallback &&aCallback)
532 {
533     otbrError error = OTBR_ERROR_NONE;
534 
535     VerifyOrExit(mState == Publisher::State::kReady, error = OTBR_ERROR_INVALID_STATE);
536     RemoveServiceRegistration(aName, aType, OTBR_ERROR_ABORTED);
537 
538 exit:
539     std::move(aCallback)(error);
540 }
541 
PublishHostImpl(const std::string & aName,const std::vector<uint8_t> & aAddress,ResultCallback && aCallback)542 void PublisherMDnsSd::PublishHostImpl(const std::string &         aName,
543                                       const std::vector<uint8_t> &aAddress,
544                                       ResultCallback &&           aCallback)
545 {
546     otbrError    ret   = OTBR_ERROR_NONE;
547     int          error = 0;
548     std::string  fullName;
549     DNSRecordRef recordRef = nullptr;
550 
551     VerifyOrExit(mState == Publisher::State::kReady, ret = OTBR_ERROR_INVALID_STATE);
552 
553     // Supports only IPv6 for now, may support IPv4 in the future.
554     VerifyOrExit(aAddress.size() == OTBR_IP6_ADDRESS_SIZE, error = OTBR_ERROR_INVALID_ARGS);
555 
556     fullName = MakeFullHostName(aName);
557 
558     if (mHostsRef == nullptr)
559     {
560         SuccessOrExit(error = DNSServiceCreateConnection(&mHostsRef));
561         otbrLogDebug("Created new DNSServiceRef for hosts: %p", mHostsRef);
562     }
563 
564     aCallback = HandleDuplicateHostRegistration(aName, aAddress, std::move(aCallback));
565     VerifyOrExit(!aCallback.IsNull());
566 
567     otbrLogInfo("Registering new host %s", aName.c_str());
568     SuccessOrExit(error = DNSServiceRegisterRecord(mHostsRef, &recordRef, kDNSServiceFlagsUnique,
569                                                    kDNSServiceInterfaceIndexAny, fullName.c_str(), kDNSServiceType_AAAA,
570                                                    kDNSServiceClass_IN, aAddress.size(), aAddress.data(), /* ttl */ 0,
571                                                    HandleRegisterHostResult, this));
572     AddHostRegistration(std::unique_ptr<DnssdHostRegistration>(
573         new DnssdHostRegistration(aName, aAddress, std::move(aCallback), mHostsRef, recordRef, this)));
574 
575 exit:
576     if (error != kDNSServiceErr_NoError || ret != OTBR_ERROR_NONE)
577     {
578         if (error != kDNSServiceErr_NoError)
579         {
580             ret = DNSErrorToOtbrError(error);
581             otbrLogErr("Failed to publish/update host %s for mdnssd error: %s!", aName.c_str(),
582                        DNSErrorToString(error));
583         }
584 
585         std::move(aCallback)(ret);
586     }
587 }
588 
UnpublishHost(const std::string & aName,ResultCallback && aCallback)589 void PublisherMDnsSd::UnpublishHost(const std::string &aName, ResultCallback &&aCallback)
590 {
591     otbrError error = OTBR_ERROR_NONE;
592 
593     VerifyOrExit(mState == Publisher::State::kReady, error = OTBR_ERROR_INVALID_STATE);
594     RemoveHostRegistration(aName, OTBR_ERROR_ABORTED);
595 
596 exit:
597     // We may failed to unregister the host from underlying mDNS publishers, but
598     // it usually means that the mDNS publisher is already not functioning. So it's
599     // okay to return success directly since the service is not advertised anyway.
600     std::move(aCallback)(error);
601 }
602 
HandleRegisterHostResult(DNSServiceRef aServiceRef,DNSRecordRef aRecordRef,DNSServiceFlags aFlags,DNSServiceErrorType aError,void * aContext)603 void PublisherMDnsSd::HandleRegisterHostResult(DNSServiceRef       aServiceRef,
604                                                DNSRecordRef        aRecordRef,
605                                                DNSServiceFlags     aFlags,
606                                                DNSServiceErrorType aError,
607                                                void *              aContext)
608 {
609     static_cast<PublisherMDnsSd *>(aContext)->HandleRegisterHostResult(aServiceRef, aRecordRef, aFlags, aError);
610 }
611 
HandleRegisterHostResult(DNSServiceRef aServiceRef,DNSRecordRef aRecordRef,DNSServiceFlags aFlags,DNSServiceErrorType aError)612 void PublisherMDnsSd::HandleRegisterHostResult(DNSServiceRef       aServiceRef,
613                                                DNSRecordRef        aRecordRef,
614                                                DNSServiceFlags     aFlags,
615                                                DNSServiceErrorType aError)
616 {
617     OTBR_UNUSED_VARIABLE(aFlags);
618 
619     otbrError         error   = DNSErrorToOtbrError(aError);
620     HostRegistration *hostReg = FindHostRegistration(aServiceRef, aRecordRef);
621 
622     std::string hostName;
623 
624     VerifyOrExit(hostReg != nullptr);
625 
626     hostName = MakeFullHostName(hostReg->mName);
627 
628     otbrLogInfo("Received reply for host %s", hostName.c_str());
629 
630     if (error == OTBR_ERROR_NONE)
631     {
632         otbrLogInfo("Successfully registered host %s", hostName.c_str());
633         hostReg->Complete(OTBR_ERROR_NONE);
634     }
635     else
636     {
637         otbrLogWarning("Failed to register host %s for mdnssd error: %s", hostName.c_str(), DNSErrorToString(aError));
638         RemoveHostRegistration(hostReg->mName, error);
639     }
640 
641 exit:
642     return;
643 }
644 
645 // See `regtype` parameter of the DNSServiceRegister() function for more information.
MakeRegType(const std::string & aType,SubTypeList aSubTypeList)646 std::string PublisherMDnsSd::MakeRegType(const std::string &aType, SubTypeList aSubTypeList)
647 {
648     std::string regType = aType;
649 
650     std::sort(aSubTypeList.begin(), aSubTypeList.end());
651 
652     for (const auto &subType : aSubTypeList)
653     {
654         regType += "," + subType;
655     }
656 
657     return regType;
658 }
659 
SubscribeService(const std::string & aType,const std::string & aInstanceName)660 void PublisherMDnsSd::SubscribeService(const std::string &aType, const std::string &aInstanceName)
661 {
662     VerifyOrExit(mState == Publisher::State::kReady);
663     mSubscribedServices.push_back(MakeUnique<ServiceSubscription>(*this, aType, aInstanceName));
664 
665     otbrLogInfo("Subscribe service %s.%s (total %zu)", aInstanceName.c_str(), aType.c_str(),
666                 mSubscribedServices.size());
667 
668     if (aInstanceName.empty())
669     {
670         mSubscribedServices.back()->Browse();
671     }
672     else
673     {
674         mSubscribedServices.back()->Resolve(kDNSServiceInterfaceIndexAny, aInstanceName, aType, kDomain);
675     }
676 
677 exit:
678     return;
679 }
680 
UnsubscribeService(const std::string & aType,const std::string & aInstanceName)681 void PublisherMDnsSd::UnsubscribeService(const std::string &aType, const std::string &aInstanceName)
682 {
683     ServiceSubscriptionList::iterator it;
684 
685     VerifyOrExit(mState == Publisher::State::kReady);
686     it = std::find_if(mSubscribedServices.begin(), mSubscribedServices.end(),
687                       [&aType, &aInstanceName](const std::unique_ptr<ServiceSubscription> &aService) {
688                           return aService->mType == aType && aService->mInstanceName == aInstanceName;
689                       });
690     assert(it != mSubscribedServices.end());
691 
692     mSubscribedServices.erase(it);
693 
694     otbrLogInfo("Unsubscribe service %s.%s (left %zu)", aInstanceName.c_str(), aType.c_str(),
695                 mSubscribedServices.size());
696 
697 exit:
698     return;
699 }
700 
OnServiceResolveFailedImpl(const std::string & aType,const std::string & aInstanceName,int32_t aErrorCode)701 void PublisherMDnsSd::OnServiceResolveFailedImpl(const std::string &aType,
702                                                  const std::string &aInstanceName,
703                                                  int32_t            aErrorCode)
704 {
705     otbrLogWarning("Resolve service %s.%s failed: code=%" PRId32, aInstanceName.c_str(), aType.c_str(), aErrorCode);
706 }
707 
OnHostResolveFailedImpl(const std::string & aHostName,int32_t aErrorCode)708 void PublisherMDnsSd::OnHostResolveFailedImpl(const std::string &aHostName, int32_t aErrorCode)
709 {
710     otbrLogWarning("Resolve host %s failed: code=%" PRId32, aHostName.c_str(), aErrorCode);
711 }
712 
DnsErrorToOtbrError(int32_t aErrorCode)713 otbrError PublisherMDnsSd::DnsErrorToOtbrError(int32_t aErrorCode)
714 {
715     return otbr::Mdns::DNSErrorToOtbrError(aErrorCode);
716 }
717 
SubscribeHost(const std::string & aHostName)718 void PublisherMDnsSd::SubscribeHost(const std::string &aHostName)
719 {
720     VerifyOrExit(mState == State::kReady);
721     mSubscribedHosts.push_back(MakeUnique<HostSubscription>(*this, aHostName));
722 
723     otbrLogInfo("Subscribe host %s (total %zu)", aHostName.c_str(), mSubscribedHosts.size());
724 
725     mSubscribedHosts.back()->Resolve();
726 
727 exit:
728     return;
729 }
730 
UnsubscribeHost(const std::string & aHostName)731 void PublisherMDnsSd::UnsubscribeHost(const std::string &aHostName)
732 {
733     HostSubscriptionList ::iterator it;
734 
735     VerifyOrExit(mState == Publisher::State::kReady);
736     it = std::find_if(
737         mSubscribedHosts.begin(), mSubscribedHosts.end(),
738         [&aHostName](const std::unique_ptr<HostSubscription> &aHost) { return aHost->mHostName == aHostName; });
739 
740     assert(it != mSubscribedHosts.end());
741 
742     mSubscribedHosts.erase(it);
743 
744     otbrLogInfo("Unsubscribe host %s (remaining %d)", aHostName.c_str(), mSubscribedHosts.size());
745 
746 exit:
747     return;
748 }
749 
Create(StateCallback aCallback)750 Publisher *Publisher::Create(StateCallback aCallback)
751 {
752     return new PublisherMDnsSd(aCallback);
753 }
754 
Destroy(Publisher * aPublisher)755 void Publisher::Destroy(Publisher *aPublisher)
756 {
757     delete static_cast<PublisherMDnsSd *>(aPublisher);
758 }
759 
Release(void)760 void PublisherMDnsSd::ServiceRef::Release(void)
761 {
762     DeallocateServiceRef();
763 }
764 
DeallocateServiceRef(void)765 void PublisherMDnsSd::ServiceRef::DeallocateServiceRef(void)
766 {
767     if (mServiceRef != nullptr)
768     {
769         DNSServiceRefDeallocate(mServiceRef);
770         mServiceRef = nullptr;
771     }
772 }
773 
Update(MainloopContext & aMainloop) const774 void PublisherMDnsSd::ServiceRef::Update(MainloopContext &aMainloop) const
775 {
776     int fd;
777 
778     VerifyOrExit(mServiceRef != nullptr);
779 
780     fd = DNSServiceRefSockFD(mServiceRef);
781     assert(fd != -1);
782     FD_SET(fd, &aMainloop.mReadFdSet);
783     aMainloop.mMaxFd = std::max(aMainloop.mMaxFd, fd);
784 exit:
785     return;
786 }
787 
Process(const MainloopContext & aMainloop,std::vector<DNSServiceRef> & aReadyServices) const788 void PublisherMDnsSd::ServiceRef::Process(const MainloopContext &     aMainloop,
789                                           std::vector<DNSServiceRef> &aReadyServices) const
790 {
791     int fd;
792 
793     VerifyOrExit(mServiceRef != nullptr);
794 
795     fd = DNSServiceRefSockFD(mServiceRef);
796     assert(fd != -1);
797     if (FD_ISSET(fd, &aMainloop.mReadFdSet))
798     {
799         aReadyServices.push_back(mServiceRef);
800     }
801 exit:
802     return;
803 }
804 
Browse(void)805 void PublisherMDnsSd::ServiceSubscription::Browse(void)
806 {
807     assert(mServiceRef == nullptr);
808 
809     otbrLogInfo("DNSServiceBrowse %s", mType.c_str());
810     DNSServiceBrowse(&mServiceRef, /* flags */ 0, kDNSServiceInterfaceIndexAny, mType.c_str(),
811                      /* domain */ nullptr, HandleBrowseResult, this);
812 }
813 
HandleBrowseResult(DNSServiceRef aServiceRef,DNSServiceFlags aFlags,uint32_t aInterfaceIndex,DNSServiceErrorType aErrorCode,const char * aInstanceName,const char * aType,const char * aDomain,void * aContext)814 void PublisherMDnsSd::ServiceSubscription::HandleBrowseResult(DNSServiceRef       aServiceRef,
815                                                               DNSServiceFlags     aFlags,
816                                                               uint32_t            aInterfaceIndex,
817                                                               DNSServiceErrorType aErrorCode,
818                                                               const char *        aInstanceName,
819                                                               const char *        aType,
820                                                               const char *        aDomain,
821                                                               void *              aContext)
822 {
823     static_cast<ServiceSubscription *>(aContext)->HandleBrowseResult(aServiceRef, aFlags, aInterfaceIndex, aErrorCode,
824                                                                      aInstanceName, aType, aDomain);
825 }
826 
HandleBrowseResult(DNSServiceRef aServiceRef,DNSServiceFlags aFlags,uint32_t aInterfaceIndex,DNSServiceErrorType aErrorCode,const char * aInstanceName,const char * aType,const char * aDomain)827 void PublisherMDnsSd::ServiceSubscription::HandleBrowseResult(DNSServiceRef       aServiceRef,
828                                                               DNSServiceFlags     aFlags,
829                                                               uint32_t            aInterfaceIndex,
830                                                               DNSServiceErrorType aErrorCode,
831                                                               const char *        aInstanceName,
832                                                               const char *        aType,
833                                                               const char *        aDomain)
834 {
835     OTBR_UNUSED_VARIABLE(aServiceRef);
836     OTBR_UNUSED_VARIABLE(aDomain);
837 
838     otbrLogInfo("DNSServiceBrowse reply: %s %s.%s inf %" PRIu32 ", flags=%" PRIu32 ", error=%" PRId32,
839                 aFlags & kDNSServiceFlagsAdd ? "add" : "remove", aInstanceName, aType, aInterfaceIndex, aFlags,
840                 aErrorCode);
841 
842     VerifyOrExit(aErrorCode == kDNSServiceErr_NoError);
843 
844     if (aFlags & kDNSServiceFlagsAdd)
845     {
846         Resolve(aInterfaceIndex, aInstanceName, aType, aDomain);
847     }
848     else
849     {
850         mMDnsSd->OnServiceRemoved(aInterfaceIndex, mType, aInstanceName);
851     }
852 
853 exit:
854     if (aErrorCode != kDNSServiceErr_NoError)
855     {
856         mMDnsSd->OnServiceResolveFailed(mType, mInstanceName, aErrorCode);
857         Release();
858     }
859 }
860 
Resolve(uint32_t aInterfaceIndex,const std::string & aInstanceName,const std::string & aType,const std::string & aDomain)861 void PublisherMDnsSd::ServiceSubscription::Resolve(uint32_t           aInterfaceIndex,
862                                                    const std::string &aInstanceName,
863                                                    const std::string &aType,
864                                                    const std::string &aDomain)
865 {
866     mResolvingInstances.push_back(
867         MakeUnique<ServiceInstanceResolution>(*this, aInstanceName, aType, aDomain, aInterfaceIndex));
868     mResolvingInstances.back()->Resolve();
869 }
870 
RemoveInstanceResolution(PublisherMDnsSd::ServiceInstanceResolution & aInstanceResolution)871 void PublisherMDnsSd::ServiceSubscription::RemoveInstanceResolution(
872     PublisherMDnsSd::ServiceInstanceResolution &aInstanceResolution)
873 {
874     auto it = std::find_if(mResolvingInstances.begin(), mResolvingInstances.end(),
875                            [&aInstanceResolution](const std::unique_ptr<ServiceInstanceResolution> &aElem) {
876                                return &aInstanceResolution == aElem.get();
877                            });
878 
879     assert(it != mResolvingInstances.end());
880 
881     mResolvingInstances.erase(it);
882 }
883 
UpdateAll(MainloopContext & aMainloop) const884 void PublisherMDnsSd::ServiceSubscription::UpdateAll(MainloopContext &aMainloop) const
885 {
886     Update(aMainloop);
887 
888     for (const auto &instance : mResolvingInstances)
889     {
890         instance->Update(aMainloop);
891     }
892 }
893 
ProcessAll(const MainloopContext & aMainloop,std::vector<DNSServiceRef> & aReadyServices) const894 void PublisherMDnsSd::ServiceSubscription::ProcessAll(const MainloopContext &     aMainloop,
895                                                       std::vector<DNSServiceRef> &aReadyServices) const
896 {
897     Process(aMainloop, aReadyServices);
898 
899     for (const auto &instance : mResolvingInstances)
900     {
901         instance->Process(aMainloop, aReadyServices);
902     }
903 }
904 
Resolve(void)905 void PublisherMDnsSd::ServiceInstanceResolution::Resolve(void)
906 {
907     assert(mServiceRef == nullptr);
908 
909     mSubscription->mMDnsSd->mServiceInstanceResolutionBeginTime[std::make_pair(mInstanceName, mTypeEndWithDot)] =
910         Clock::now();
911 
912     otbrLogInfo("DNSServiceResolve %s %s inf %u", mInstanceName.c_str(), mTypeEndWithDot.c_str(), mNetifIndex);
913     DNSServiceResolve(&mServiceRef, /* flags */ kDNSServiceFlagsTimeout, mNetifIndex, mInstanceName.c_str(),
914                       mTypeEndWithDot.c_str(), mDomain.c_str(), HandleResolveResult, this);
915 }
916 
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)917 void PublisherMDnsSd::ServiceInstanceResolution::HandleResolveResult(DNSServiceRef        aServiceRef,
918                                                                      DNSServiceFlags      aFlags,
919                                                                      uint32_t             aInterfaceIndex,
920                                                                      DNSServiceErrorType  aErrorCode,
921                                                                      const char *         aFullName,
922                                                                      const char *         aHostTarget,
923                                                                      uint16_t             aPort,
924                                                                      uint16_t             aTxtLen,
925                                                                      const unsigned char *aTxtRecord,
926                                                                      void *               aContext)
927 {
928     static_cast<ServiceInstanceResolution *>(aContext)->HandleResolveResult(
929         aServiceRef, aFlags, aInterfaceIndex, aErrorCode, aFullName, aHostTarget, aPort, aTxtLen, aTxtRecord);
930 }
931 
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)932 void PublisherMDnsSd::ServiceInstanceResolution::HandleResolveResult(DNSServiceRef        aServiceRef,
933                                                                      DNSServiceFlags      aFlags,
934                                                                      uint32_t             aInterfaceIndex,
935                                                                      DNSServiceErrorType  aErrorCode,
936                                                                      const char *         aFullName,
937                                                                      const char *         aHostTarget,
938                                                                      uint16_t             aPort,
939                                                                      uint16_t             aTxtLen,
940                                                                      const unsigned char *aTxtRecord)
941 {
942     OTBR_UNUSED_VARIABLE(aServiceRef);
943 
944     std::string instanceName, type, domain;
945     otbrError   error = OTBR_ERROR_NONE;
946 
947     otbrLogInfo("DNSServiceResolve reply: %s host %s:%d, TXT=%dB inf %u, flags=%u", aFullName, aHostTarget, aPort,
948                 aTxtLen, aInterfaceIndex, aFlags);
949 
950     VerifyOrExit(aErrorCode == kDNSServiceErr_NoError);
951 
952     SuccessOrExit(error = SplitFullServiceInstanceName(aFullName, instanceName, type, domain));
953 
954     mInstanceInfo.mNetifIndex = aInterfaceIndex;
955     mInstanceInfo.mName       = instanceName;
956     mInstanceInfo.mHostName   = aHostTarget;
957     mInstanceInfo.mPort       = ntohs(aPort);
958     mInstanceInfo.mTxtData.assign(aTxtRecord, aTxtRecord + aTxtLen);
959     // priority and weight are not given in the reply
960     mInstanceInfo.mPriority = 0;
961     mInstanceInfo.mWeight   = 0;
962 
963     DeallocateServiceRef();
964     error = GetAddrInfo(aInterfaceIndex);
965 
966 exit:
967     if (error != OTBR_ERROR_NONE)
968     {
969         otbrLogWarning("Failed to resolve service instance %s", aFullName);
970     }
971 
972     if (aErrorCode != kDNSServiceErr_NoError || error != OTBR_ERROR_NONE)
973     {
974         mSubscription->mMDnsSd->OnServiceResolveFailed(mSubscription->mType, mInstanceName, aErrorCode);
975         FinishResolution();
976     }
977 }
978 
GetAddrInfo(uint32_t aInterfaceIndex)979 otbrError PublisherMDnsSd::ServiceInstanceResolution::GetAddrInfo(uint32_t aInterfaceIndex)
980 {
981     DNSServiceErrorType dnsError;
982 
983     assert(mServiceRef == nullptr);
984 
985     otbrLogInfo("DNSServiceGetAddrInfo %s inf %d", mInstanceInfo.mHostName.c_str(), aInterfaceIndex);
986 
987     dnsError = DNSServiceGetAddrInfo(&mServiceRef, kDNSServiceFlagsTimeout, aInterfaceIndex,
988                                      kDNSServiceProtocol_IPv6 | kDNSServiceProtocol_IPv4,
989                                      mInstanceInfo.mHostName.c_str(), HandleGetAddrInfoResult, this);
990 
991     if (dnsError != kDNSServiceErr_NoError)
992     {
993         otbrLogWarning("DNSServiceGetAddrInfo failed: %s", DNSErrorToString(dnsError));
994     }
995 
996     return dnsError == kDNSServiceErr_NoError ? OTBR_ERROR_NONE : OTBR_ERROR_MDNS;
997 }
998 
HandleGetAddrInfoResult(DNSServiceRef aServiceRef,DNSServiceFlags aFlags,uint32_t aInterfaceIndex,DNSServiceErrorType aErrorCode,const char * aHostName,const struct sockaddr * aAddress,uint32_t aTtl,void * aContext)999 void PublisherMDnsSd::ServiceInstanceResolution::HandleGetAddrInfoResult(DNSServiceRef          aServiceRef,
1000                                                                          DNSServiceFlags        aFlags,
1001                                                                          uint32_t               aInterfaceIndex,
1002                                                                          DNSServiceErrorType    aErrorCode,
1003                                                                          const char *           aHostName,
1004                                                                          const struct sockaddr *aAddress,
1005                                                                          uint32_t               aTtl,
1006                                                                          void *                 aContext)
1007 {
1008     static_cast<ServiceInstanceResolution *>(aContext)->HandleGetAddrInfoResult(aServiceRef, aFlags, aInterfaceIndex,
1009                                                                                 aErrorCode, aHostName, aAddress, aTtl);
1010 }
1011 
HandleGetAddrInfoResult(DNSServiceRef aServiceRef,DNSServiceFlags aFlags,uint32_t aInterfaceIndex,DNSServiceErrorType aErrorCode,const char * aHostName,const struct sockaddr * aAddress,uint32_t aTtl)1012 void PublisherMDnsSd::ServiceInstanceResolution::HandleGetAddrInfoResult(DNSServiceRef          aServiceRef,
1013                                                                          DNSServiceFlags        aFlags,
1014                                                                          uint32_t               aInterfaceIndex,
1015                                                                          DNSServiceErrorType    aErrorCode,
1016                                                                          const char *           aHostName,
1017                                                                          const struct sockaddr *aAddress,
1018                                                                          uint32_t               aTtl)
1019 {
1020     OTBR_UNUSED_VARIABLE(aServiceRef);
1021     OTBR_UNUSED_VARIABLE(aInterfaceIndex);
1022 
1023     Ip6Address address;
1024 
1025     otbrLog(aErrorCode == kDNSServiceErr_NoError ? OTBR_LOG_INFO : OTBR_LOG_WARNING, OTBR_LOG_TAG,
1026             "DNSServiceGetAddrInfo reply: flags=%" PRIu32 ", host=%s, sa_family=%u, error=%" PRId32, aFlags, aHostName,
1027             static_cast<unsigned int>(aAddress->sa_family), aErrorCode);
1028 
1029     VerifyOrExit(aErrorCode == kDNSServiceErr_NoError);
1030     VerifyOrExit((aFlags & kDNSServiceFlagsAdd) && aAddress->sa_family == AF_INET6);
1031 
1032     address.CopyFrom(*reinterpret_cast<const struct sockaddr_in6 *>(aAddress));
1033     VerifyOrExit(!address.IsUnspecified() && !address.IsLinkLocal() && !address.IsMulticast() && !address.IsLoopback(),
1034                  otbrLogDebug("DNSServiceGetAddrInfo ignores address %s", address.ToString().c_str()));
1035 
1036     mInstanceInfo.mAddresses.push_back(address);
1037     mInstanceInfo.mTtl = aTtl;
1038 
1039     otbrLogInfo("DNSServiceGetAddrInfo reply: address=%s, ttl=%" PRIu32, address.ToString().c_str(), aTtl);
1040 
1041 exit:
1042     if (!mInstanceInfo.mAddresses.empty() || aErrorCode != kDNSServiceErr_NoError)
1043     {
1044         FinishResolution();
1045     }
1046 }
1047 
FinishResolution(void)1048 void PublisherMDnsSd::ServiceInstanceResolution::FinishResolution(void)
1049 {
1050     ServiceSubscription *  subscription = mSubscription;
1051     std::string            serviceName  = mSubscription->mType;
1052     DiscoveredInstanceInfo instanceInfo = mInstanceInfo;
1053 
1054     // NOTE: `RemoveInstanceResolution` will free this `ServiceInstanceResolution` object.
1055     //       So, We can't access `mSubscription` after `RemoveInstanceResolution`.
1056     subscription->RemoveInstanceResolution(*this);
1057 
1058     // NOTE: The `ServiceSubscription` object may be freed in `OnServiceResolved`.
1059     subscription->mMDnsSd->OnServiceResolved(serviceName, instanceInfo);
1060 }
1061 
Resolve(void)1062 void PublisherMDnsSd::HostSubscription::Resolve(void)
1063 {
1064     std::string fullHostName = MakeFullHostName(mHostName);
1065 
1066     assert(mServiceRef == nullptr);
1067 
1068     mMDnsSd->mHostResolutionBeginTime[mHostName] = Clock::now();
1069 
1070     otbrLogInfo("DNSServiceGetAddrInfo %s inf %d", fullHostName.c_str(), kDNSServiceInterfaceIndexAny);
1071 
1072     DNSServiceGetAddrInfo(&mServiceRef, /* flags */ 0, kDNSServiceInterfaceIndexAny,
1073                           kDNSServiceProtocol_IPv6 | kDNSServiceProtocol_IPv4, fullHostName.c_str(),
1074                           HandleResolveResult, this);
1075 }
1076 
HandleResolveResult(DNSServiceRef aServiceRef,DNSServiceFlags aFlags,uint32_t aInterfaceIndex,DNSServiceErrorType aErrorCode,const char * aHostName,const struct sockaddr * aAddress,uint32_t aTtl,void * aContext)1077 void PublisherMDnsSd::HostSubscription::HandleResolveResult(DNSServiceRef          aServiceRef,
1078                                                             DNSServiceFlags        aFlags,
1079                                                             uint32_t               aInterfaceIndex,
1080                                                             DNSServiceErrorType    aErrorCode,
1081                                                             const char *           aHostName,
1082                                                             const struct sockaddr *aAddress,
1083                                                             uint32_t               aTtl,
1084                                                             void *                 aContext)
1085 {
1086     static_cast<HostSubscription *>(aContext)->HandleResolveResult(aServiceRef, aFlags, aInterfaceIndex, aErrorCode,
1087                                                                    aHostName, aAddress, aTtl);
1088 }
1089 
HandleResolveResult(DNSServiceRef aServiceRef,DNSServiceFlags aFlags,uint32_t aInterfaceIndex,DNSServiceErrorType aErrorCode,const char * aHostName,const struct sockaddr * aAddress,uint32_t aTtl)1090 void PublisherMDnsSd::HostSubscription::HandleResolveResult(DNSServiceRef          aServiceRef,
1091                                                             DNSServiceFlags        aFlags,
1092                                                             uint32_t               aInterfaceIndex,
1093                                                             DNSServiceErrorType    aErrorCode,
1094                                                             const char *           aHostName,
1095                                                             const struct sockaddr *aAddress,
1096                                                             uint32_t               aTtl)
1097 {
1098     OTBR_UNUSED_VARIABLE(aServiceRef);
1099     OTBR_UNUSED_VARIABLE(aInterfaceIndex);
1100 
1101     Ip6Address address;
1102 
1103     otbrLog(aErrorCode == kDNSServiceErr_NoError ? OTBR_LOG_INFO : OTBR_LOG_WARNING, OTBR_LOG_TAG,
1104             "DNSServiceGetAddrInfo reply: flags=%" PRIu32 ", host=%s, sa_family=%u, error=%" PRId32, aFlags, aHostName,
1105             static_cast<unsigned int>(aAddress->sa_family), aErrorCode);
1106 
1107     VerifyOrExit(aErrorCode == kDNSServiceErr_NoError);
1108     VerifyOrExit((aFlags & kDNSServiceFlagsAdd) && aAddress->sa_family == AF_INET6);
1109 
1110     address.CopyFrom(*reinterpret_cast<const struct sockaddr_in6 *>(aAddress));
1111     VerifyOrExit(!address.IsLinkLocal(),
1112                  otbrLogDebug("DNSServiceGetAddrInfo ignore link-local address %s", address.ToString().c_str()));
1113 
1114     mHostInfo.mHostName = aHostName;
1115     mHostInfo.mAddresses.push_back(address);
1116     mHostInfo.mTtl = aTtl;
1117 
1118     otbrLogInfo("DNSServiceGetAddrInfo reply: address=%s, ttl=%" PRIu32, address.ToString().c_str(), aTtl);
1119 
1120     // NOTE: This `HostSubscription` object may be freed in `OnHostResolved`.
1121     mMDnsSd->OnHostResolved(mHostName, mHostInfo);
1122 
1123 exit:
1124     if (aErrorCode != kDNSServiceErr_NoError)
1125     {
1126         mMDnsSd->OnHostResolveFailed(aHostName, aErrorCode);
1127     }
1128 }
1129 
1130 } // namespace Mdns
1131 
1132 } // namespace otbr
1133