Skip to content

Commit

Permalink
Remove the kDNSServiceInterfaceIndexLocalOnly special-case on Darwin. (
Browse files Browse the repository at this point in the history
…#26287)

Interface kDNSServiceInterfaceIndexLocalOnly means the _registration_ is
local-only, not that the registered host is localhost and has a loopback
address.  There can be local-only registrations for other hosts, and we need to
do actual address resolution.

To make this work right in our unit test setup, fix our registration code for
the local-only case (which tests use) to register hostname -> IP mappings, which
it was not doing before.
  • Loading branch information
bzbarsky-apple authored and pull[bot] committed Dec 21, 2023
1 parent 9a98e95 commit 1145900
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 31 deletions.
22 changes: 10 additions & 12 deletions src/platform/Darwin/DnssdContexts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,27 +420,25 @@ CHIP_ERROR ResolveContext::OnNewAddress(uint32_t interfaceId, const struct socka

chip::Inet::IPAddress ip;
ReturnErrorOnFailure(chip::Inet::IPAddress::GetIPAddressFromSockAddr(*address, ip));
interfaces[interfaceId].addresses.push_back(ip);

#ifdef CHIP_PROGRESS_LOGGING
char addrStr[INET6_ADDRSTRLEN];
ip.ToString(addrStr, sizeof(addrStr));
ChipLogProgress(Discovery, "Mdns: %s interface: %" PRIu32 " ip:%s", __func__, interfaceId, addrStr);
#endif // CHIP_PROGRESS_LOGGING

return CHIP_NO_ERROR;
}
if (ip.IsIPv6LinkLocal() && interfaceId == kDNSServiceInterfaceIndexLocalOnly)
{
// We need a real interface to use a link-local address. Just ignore
// this one, because trying to use it will simply lead to "No route to
// host" errors.
ChipLogProgress(Discovery, "Mdns: Ignoring link-local address with no usable interface");
return CHIP_NO_ERROR;
}

CHIP_ERROR ResolveContext::OnNewLocalOnlyAddress()
{
sockaddr_in6 sockaddr;
memset(&sockaddr, 0, sizeof(sockaddr));
sockaddr.sin6_len = sizeof(sockaddr);
sockaddr.sin6_family = AF_INET6;
sockaddr.sin6_addr = in6addr_loopback;
sockaddr.sin6_port = htons((unsigned short) interfaces[kDNSServiceInterfaceIndexLocalOnly].service.mPort);
interfaces[interfaceId].addresses.push_back(ip);

return OnNewAddress(kDNSServiceInterfaceIndexLocalOnly, reinterpret_cast<struct sockaddr *>(&sockaddr));
return CHIP_NO_ERROR;
}

bool ResolveContext::HasAddress()
Expand Down
37 changes: 29 additions & 8 deletions src/platform/Darwin/DnssdHostNameRegistrar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,9 +284,31 @@ DNSServiceErrorType HostNameRegistrar::Init(const char * hostname, Inet::IPAddre

CHIP_ERROR HostNameRegistrar::Register()
{
// If the target interface is kDNSServiceInterfaceIndexLocalOnly, there are no interfaces to register against
// the dns daemon.
VerifyOrReturnError(!IsLocalOnly(), CHIP_NO_ERROR);
// If the target interface is kDNSServiceInterfaceIndexLocalOnly, just
// register the loopback addresses.
if (IsLocalOnly())
{
ReturnErrorOnFailure(ResetSharedConnection());

InetInterfacesVector inetInterfaces;
Inet6InterfacesVector inet6Interfaces;
// Instead of mInterfaceId (which will not match any actual interface),
// use kDNSServiceInterfaceIndexAny and restrict to loopback interfaces.
GetInterfaceAddresses(kDNSServiceInterfaceIndexAny, mAddressType, inetInterfaces, inet6Interfaces,
true /* searchLoopbackOnly */);

// But we register the IPs with mInterfaceId, not the actual interface
// IDs, so that resolution code that is grouping addresses by interface
// ends up doing the right thing, since we registered our SRV record on
// mInterfaceId.
//
// And only register the IPv6 ones, for simplicity.
for (auto & interface : inet6Interfaces)
{
ReturnErrorOnFailure(RegisterInterface(mInterfaceId, interface.second, kDNSServiceType_AAAA));
}
return CHIP_NO_ERROR;
}

return StartMonitorInterfaces(^(InetInterfacesVector inetInterfaces, Inet6InterfacesVector inet6Interfaces) {
ReturnOnFailure(ResetSharedConnection());
Expand All @@ -305,11 +327,10 @@ CHIP_ERROR HostNameRegistrar::RegisterInterface(uint32_t interfaceId, uint16_t r

void HostNameRegistrar::Unregister()
{
// If the target interface is kDNSServiceInterfaceIndexLocalOnly, there are no interfaces to register against
// the dns daemon.
VerifyOrReturn(!IsLocalOnly());

StopMonitorInterfaces();
if (!IsLocalOnly())
{
StopMonitorInterfaces();
}
StopSharedConnection();
}

Expand Down
12 changes: 8 additions & 4 deletions src/platform/Darwin/DnssdHostNameRegistrar.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,18 @@ namespace Dnssd {
{
for (auto & interface : interfaces) {
auto interfaceId = interface.first;
auto interfaceAddress = static_cast<const void *>(&interface.second);
auto interfaceAddressLen = sizeof(interface.second);

LogErrorOnFailure(
RegisterInterface(interfaceId, type, interfaceAddress, static_cast<uint16_t>(interfaceAddressLen)));
LogErrorOnFailure(RegisterInterface(interfaceId, interface.second, type));
}
}

template <typename T> CHIP_ERROR RegisterInterface(uint32_t interfaceId, const T & interfaceAddress, uint16_t type)
{
auto interfaceAddressLen = sizeof(interfaceAddress);

return RegisterInterface(interfaceId, type, &interfaceAddress, static_cast<uint16_t>(interfaceAddressLen));
}

CHIP_ERROR RegisterInterface(uint32_t interfaceId, uint16_t rtype, const void * rdata, uint16_t rdlen);

CHIP_ERROR StartSharedConnection();
Expand Down
6 changes: 0 additions & 6 deletions src/platform/Darwin/DnssdImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,12 +328,6 @@ static void OnResolve(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t inter
if (kDNSServiceErr_NoError == err)
{
sdCtx->OnNewInterface(interfaceId, fullname, hostname, port, txtLen, txtRecord);
if (kDNSServiceInterfaceIndexLocalOnly == interfaceId)
{
sdCtx->OnNewLocalOnlyAddress();
sdCtx->Finalize();
return;
}
}

if (!(flags & kDNSServiceFlagsMoreComing))
Expand Down
1 change: 0 additions & 1 deletion src/platform/Darwin/DnssdImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,6 @@ struct ResolveContext : public GenericContext
void DispatchSuccess() override;

CHIP_ERROR OnNewAddress(uint32_t interfaceId, const struct sockaddr * address);
CHIP_ERROR OnNewLocalOnlyAddress();
bool HasAddress();

void OnNewInterface(uint32_t interfaceId, const char * fullname, const char * hostname, uint16_t port, uint16_t txtLen,
Expand Down

0 comments on commit 1145900

Please sign in to comment.