Skip to content

Commit

Permalink
[posix] update upstream DNS addresses after a few minutes (openthread…
Browse files Browse the repository at this point in the history
…#8972)

On some platforms, the /etc/resolv.conf might be a generated file, and
is not available at the first few minutes after boot.

This commit records the time when we read the DNS server addresses
from the upstream, and reload the server list when it expires.

We may want to use inotify or add a platform specific API to notify
the openthread about the change of DNS server list.
  • Loading branch information
erjiaqing authored May 5, 2023
1 parent 612f21e commit 96ea730
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 15 deletions.
42 changes: 27 additions & 15 deletions src/posix/platform/resolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <openthread/message.h>
#include <openthread/udp.h>
#include <openthread/platform/dns.h>
#include <openthread/platform/time.h>

#include "common/code_utils.hpp"

Expand All @@ -51,8 +52,8 @@
#if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE

namespace {
constexpr char kResolveConfLocation[] = "/etc/resolv.conf";
constexpr char kNameserverItem[] = "nameserver";
constexpr char kResolvConfFullPath[] = "/etc/resolv.conf";
constexpr char kNameserverItem[] = "nameserver";
} // namespace

extern ot::Posix::Resolver gResolver;
Expand All @@ -63,42 +64,51 @@ namespace Posix {
void Resolver::Init(void)
{
memset(mUpstreamTransaction, 0, sizeof(mUpstreamTransaction));

LoadDnsServerListFromConf();
}

void Resolver::TryRefreshDnsServerList(void)
{
uint64_t now = otPlatTimeGet();

if (now > mUpstreamDnsServerListFreshness + kDnsServerListCacheTimeoutMs ||
(mUpstreamDnsServerCount == 0 && now > mUpstreamDnsServerListFreshness + kDnsServerListNullCacheTimeoutMs))
{
LoadDnsServerListFromConf();
}
}

void Resolver::LoadDnsServerListFromConf(void)
{
std::string line;
std::ifstream fp;

fp.open(kResolveConfLocation);
if (fp.bad())
{
otLogCritPlat("Cannot read %s for domain name servers, default to 127.0.0.1", kResolveConfLocation);
mUpstreamDnsServerCount = 1;
assert(inet_pton(AF_INET, "127.0.0.1", &mUpstreamDnsServerList[0]) == 1);
ExitNow();
}
mUpstreamDnsServerCount = 0;

fp.open(kResolvConfFullPath);

while (std::getline(fp, line) && mUpstreamDnsServerCount < kMaxUpstreamServerCount)
while (fp.good() && std::getline(fp, line) && mUpstreamDnsServerCount < kMaxUpstreamServerCount)
{
if (line.find(kNameserverItem, 0) == 0)
{
in_addr_t addr;

if (inet_pton(AF_INET, &line.c_str()[sizeof(kNameserverItem)], &addr) == 1)
{
otLogCritPlat("Got nameserver #%d: %s", mUpstreamDnsServerCount,
otLogInfoPlat("Got nameserver #%d: %s", mUpstreamDnsServerCount,
&line.c_str()[sizeof(kNameserverItem)]);
mUpstreamDnsServerList[mUpstreamDnsServerCount] = addr;
mUpstreamDnsServerCount++;
}
}
}

exit:
return;
if (mUpstreamDnsServerCount == 0)
{
otLogCritPlat("No domain name servers found in %s, default to 127.0.0.1", kResolvConfFullPath);
}

mUpstreamDnsServerListFreshness = otPlatTimeGet();
}

void Resolver::Query(otPlatDnsUpstreamQuery *aTxn, const otMessage *aQuery)
Expand All @@ -116,6 +126,8 @@ void Resolver::Query(otPlatDnsUpstreamQuery *aTxn, const otMessage *aQuery)
txn = AllocateTransaction(aTxn);
VerifyOrExit(txn != nullptr, error = OT_ERROR_NO_BUFS);

TryRefreshDnsServerList();

serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(53);
for (int i = 0; i < mUpstreamDnsServerCount; i++)
Expand Down
5 changes: 5 additions & 0 deletions src/posix/platform/resolver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ class Resolver
void Process(const fd_set *aReadFdSet, const fd_set *aErrorFdSet);

private:
static constexpr uint64_t kDnsServerListNullCacheTimeoutMs = 1 * 60 * 1000; // 1 minute
static constexpr uint64_t kDnsServerListCacheTimeoutMs = 10 * 60 * 1000; // 10 minutes

struct Transaction
{
otPlatDnsUpstreamQuery *mThreadTxn;
Expand All @@ -103,10 +106,12 @@ class Resolver
void ForwardResponse(Transaction *aTxn);
void CloseTransaction(Transaction *aTxn);
void FinishTransaction(int aFd);
void TryRefreshDnsServerList(void);
void LoadDnsServerListFromConf(void);

int mUpstreamDnsServerCount = 0;
in_addr_t mUpstreamDnsServerList[kMaxUpstreamServerCount];
uint64_t mUpstreamDnsServerListFreshness = 0;

Transaction mUpstreamTransaction[kMaxUpstreamTransactionCount];
};
Expand Down

0 comments on commit 96ea730

Please sign in to comment.