1*cfb92d14SAndroid Build Coastguard Worker /*
2*cfb92d14SAndroid Build Coastguard Worker * Copyright (c) 2023, The OpenThread Authors.
3*cfb92d14SAndroid Build Coastguard Worker * All rights reserved.
4*cfb92d14SAndroid Build Coastguard Worker *
5*cfb92d14SAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
6*cfb92d14SAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions are met:
7*cfb92d14SAndroid Build Coastguard Worker * 1. Redistributions of source code must retain the above copyright
8*cfb92d14SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer.
9*cfb92d14SAndroid Build Coastguard Worker * 2. Redistributions in binary form must reproduce the above copyright
10*cfb92d14SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer in the
11*cfb92d14SAndroid Build Coastguard Worker * documentation and/or other materials provided with the distribution.
12*cfb92d14SAndroid Build Coastguard Worker * 3. Neither the name of the copyright holder nor the
13*cfb92d14SAndroid Build Coastguard Worker * names of its contributors may be used to endorse or promote products
14*cfb92d14SAndroid Build Coastguard Worker * derived from this software without specific prior written permission.
15*cfb92d14SAndroid Build Coastguard Worker *
16*cfb92d14SAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17*cfb92d14SAndroid Build Coastguard Worker * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*cfb92d14SAndroid Build Coastguard Worker * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*cfb92d14SAndroid Build Coastguard Worker * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20*cfb92d14SAndroid Build Coastguard Worker * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21*cfb92d14SAndroid Build Coastguard Worker * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22*cfb92d14SAndroid Build Coastguard Worker * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23*cfb92d14SAndroid Build Coastguard Worker * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24*cfb92d14SAndroid Build Coastguard Worker * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25*cfb92d14SAndroid Build Coastguard Worker * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26*cfb92d14SAndroid Build Coastguard Worker * POSSIBILITY OF SUCH DAMAGE.
27*cfb92d14SAndroid Build Coastguard Worker */
28*cfb92d14SAndroid Build Coastguard Worker
29*cfb92d14SAndroid Build Coastguard Worker #include "resolver.hpp"
30*cfb92d14SAndroid Build Coastguard Worker
31*cfb92d14SAndroid Build Coastguard Worker #include "platform-posix.h"
32*cfb92d14SAndroid Build Coastguard Worker
33*cfb92d14SAndroid Build Coastguard Worker #include <openthread/logging.h>
34*cfb92d14SAndroid Build Coastguard Worker #include <openthread/message.h>
35*cfb92d14SAndroid Build Coastguard Worker #include <openthread/nat64.h>
36*cfb92d14SAndroid Build Coastguard Worker #include <openthread/openthread-system.h>
37*cfb92d14SAndroid Build Coastguard Worker #include <openthread/udp.h>
38*cfb92d14SAndroid Build Coastguard Worker #include <openthread/platform/dns.h>
39*cfb92d14SAndroid Build Coastguard Worker #include <openthread/platform/time.h>
40*cfb92d14SAndroid Build Coastguard Worker
41*cfb92d14SAndroid Build Coastguard Worker #include "common/code_utils.hpp"
42*cfb92d14SAndroid Build Coastguard Worker
43*cfb92d14SAndroid Build Coastguard Worker #include <arpa/inet.h>
44*cfb92d14SAndroid Build Coastguard Worker #include <arpa/nameser.h>
45*cfb92d14SAndroid Build Coastguard Worker #include <cassert>
46*cfb92d14SAndroid Build Coastguard Worker #include <netinet/in.h>
47*cfb92d14SAndroid Build Coastguard Worker #include <sys/select.h>
48*cfb92d14SAndroid Build Coastguard Worker #include <sys/socket.h>
49*cfb92d14SAndroid Build Coastguard Worker #include <unistd.h>
50*cfb92d14SAndroid Build Coastguard Worker
51*cfb92d14SAndroid Build Coastguard Worker #include <fstream>
52*cfb92d14SAndroid Build Coastguard Worker #include <string>
53*cfb92d14SAndroid Build Coastguard Worker
54*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
55*cfb92d14SAndroid Build Coastguard Worker
56*cfb92d14SAndroid Build Coastguard Worker namespace {
57*cfb92d14SAndroid Build Coastguard Worker constexpr char kResolvConfFullPath[] = "/etc/resolv.conf";
58*cfb92d14SAndroid Build Coastguard Worker constexpr char kNameserverItem[] = "nameserver";
59*cfb92d14SAndroid Build Coastguard Worker } // namespace
60*cfb92d14SAndroid Build Coastguard Worker
61*cfb92d14SAndroid Build Coastguard Worker ot::Posix::Resolver gResolver;
62*cfb92d14SAndroid Build Coastguard Worker
63*cfb92d14SAndroid Build Coastguard Worker namespace ot {
64*cfb92d14SAndroid Build Coastguard Worker namespace Posix {
65*cfb92d14SAndroid Build Coastguard Worker
66*cfb92d14SAndroid Build Coastguard Worker const char Resolver::kLogModuleName[] = "Resolver";
67*cfb92d14SAndroid Build Coastguard Worker
Init(void)68*cfb92d14SAndroid Build Coastguard Worker void Resolver::Init(void)
69*cfb92d14SAndroid Build Coastguard Worker {
70*cfb92d14SAndroid Build Coastguard Worker memset(mUpstreamTransaction, 0, sizeof(mUpstreamTransaction));
71*cfb92d14SAndroid Build Coastguard Worker LoadDnsServerListFromConf();
72*cfb92d14SAndroid Build Coastguard Worker }
73*cfb92d14SAndroid Build Coastguard Worker
TryRefreshDnsServerList(void)74*cfb92d14SAndroid Build Coastguard Worker void Resolver::TryRefreshDnsServerList(void)
75*cfb92d14SAndroid Build Coastguard Worker {
76*cfb92d14SAndroid Build Coastguard Worker uint64_t now = otPlatTimeGet();
77*cfb92d14SAndroid Build Coastguard Worker
78*cfb92d14SAndroid Build Coastguard Worker if (now > mUpstreamDnsServerListFreshness + kDnsServerListCacheTimeoutMs ||
79*cfb92d14SAndroid Build Coastguard Worker (mUpstreamDnsServerCount == 0 && now > mUpstreamDnsServerListFreshness + kDnsServerListNullCacheTimeoutMs))
80*cfb92d14SAndroid Build Coastguard Worker {
81*cfb92d14SAndroid Build Coastguard Worker LoadDnsServerListFromConf();
82*cfb92d14SAndroid Build Coastguard Worker }
83*cfb92d14SAndroid Build Coastguard Worker }
84*cfb92d14SAndroid Build Coastguard Worker
LoadDnsServerListFromConf(void)85*cfb92d14SAndroid Build Coastguard Worker void Resolver::LoadDnsServerListFromConf(void)
86*cfb92d14SAndroid Build Coastguard Worker {
87*cfb92d14SAndroid Build Coastguard Worker std::string line;
88*cfb92d14SAndroid Build Coastguard Worker std::ifstream fp;
89*cfb92d14SAndroid Build Coastguard Worker
90*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(mIsResolvConfEnabled);
91*cfb92d14SAndroid Build Coastguard Worker
92*cfb92d14SAndroid Build Coastguard Worker mUpstreamDnsServerCount = 0;
93*cfb92d14SAndroid Build Coastguard Worker
94*cfb92d14SAndroid Build Coastguard Worker fp.open(kResolvConfFullPath);
95*cfb92d14SAndroid Build Coastguard Worker
96*cfb92d14SAndroid Build Coastguard Worker while (fp.good() && std::getline(fp, line) && mUpstreamDnsServerCount < kMaxUpstreamServerCount)
97*cfb92d14SAndroid Build Coastguard Worker {
98*cfb92d14SAndroid Build Coastguard Worker if (line.find(kNameserverItem, 0) == 0)
99*cfb92d14SAndroid Build Coastguard Worker {
100*cfb92d14SAndroid Build Coastguard Worker in_addr_t addr;
101*cfb92d14SAndroid Build Coastguard Worker
102*cfb92d14SAndroid Build Coastguard Worker if (inet_pton(AF_INET, &line.c_str()[sizeof(kNameserverItem)], &addr) == 1)
103*cfb92d14SAndroid Build Coastguard Worker {
104*cfb92d14SAndroid Build Coastguard Worker LogInfo("Got nameserver #%d: %s", mUpstreamDnsServerCount, &line.c_str()[sizeof(kNameserverItem)]);
105*cfb92d14SAndroid Build Coastguard Worker mUpstreamDnsServerList[mUpstreamDnsServerCount] = addr;
106*cfb92d14SAndroid Build Coastguard Worker mUpstreamDnsServerCount++;
107*cfb92d14SAndroid Build Coastguard Worker }
108*cfb92d14SAndroid Build Coastguard Worker }
109*cfb92d14SAndroid Build Coastguard Worker }
110*cfb92d14SAndroid Build Coastguard Worker
111*cfb92d14SAndroid Build Coastguard Worker if (mUpstreamDnsServerCount == 0)
112*cfb92d14SAndroid Build Coastguard Worker {
113*cfb92d14SAndroid Build Coastguard Worker LogCrit("No domain name servers found in %s, default to 127.0.0.1", kResolvConfFullPath);
114*cfb92d14SAndroid Build Coastguard Worker }
115*cfb92d14SAndroid Build Coastguard Worker
116*cfb92d14SAndroid Build Coastguard Worker mUpstreamDnsServerListFreshness = otPlatTimeGet();
117*cfb92d14SAndroid Build Coastguard Worker exit:
118*cfb92d14SAndroid Build Coastguard Worker return;
119*cfb92d14SAndroid Build Coastguard Worker }
120*cfb92d14SAndroid Build Coastguard Worker
Query(otPlatDnsUpstreamQuery * aTxn,const otMessage * aQuery)121*cfb92d14SAndroid Build Coastguard Worker void Resolver::Query(otPlatDnsUpstreamQuery *aTxn, const otMessage *aQuery)
122*cfb92d14SAndroid Build Coastguard Worker {
123*cfb92d14SAndroid Build Coastguard Worker char packet[kMaxDnsMessageSize];
124*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
125*cfb92d14SAndroid Build Coastguard Worker uint16_t length = otMessageGetLength(aQuery);
126*cfb92d14SAndroid Build Coastguard Worker sockaddr_in serverAddr;
127*cfb92d14SAndroid Build Coastguard Worker
128*cfb92d14SAndroid Build Coastguard Worker Transaction *txn = nullptr;
129*cfb92d14SAndroid Build Coastguard Worker
130*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(length <= kMaxDnsMessageSize, error = OT_ERROR_NO_BUFS);
131*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(otMessageRead(aQuery, 0, &packet, sizeof(packet)) == length, error = OT_ERROR_NO_BUFS);
132*cfb92d14SAndroid Build Coastguard Worker
133*cfb92d14SAndroid Build Coastguard Worker txn = AllocateTransaction(aTxn);
134*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(txn != nullptr, error = OT_ERROR_NO_BUFS);
135*cfb92d14SAndroid Build Coastguard Worker
136*cfb92d14SAndroid Build Coastguard Worker TryRefreshDnsServerList();
137*cfb92d14SAndroid Build Coastguard Worker
138*cfb92d14SAndroid Build Coastguard Worker serverAddr.sin_family = AF_INET;
139*cfb92d14SAndroid Build Coastguard Worker serverAddr.sin_port = htons(53);
140*cfb92d14SAndroid Build Coastguard Worker for (int i = 0; i < mUpstreamDnsServerCount; i++)
141*cfb92d14SAndroid Build Coastguard Worker {
142*cfb92d14SAndroid Build Coastguard Worker serverAddr.sin_addr.s_addr = mUpstreamDnsServerList[i];
143*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(
144*cfb92d14SAndroid Build Coastguard Worker sendto(txn->mUdpFd, packet, length, MSG_DONTWAIT, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) > 0,
145*cfb92d14SAndroid Build Coastguard Worker error = OT_ERROR_NO_ROUTE);
146*cfb92d14SAndroid Build Coastguard Worker }
147*cfb92d14SAndroid Build Coastguard Worker LogInfo("Forwarded DNS query %p to %d server(s).", static_cast<void *>(aTxn), mUpstreamDnsServerCount);
148*cfb92d14SAndroid Build Coastguard Worker
149*cfb92d14SAndroid Build Coastguard Worker exit:
150*cfb92d14SAndroid Build Coastguard Worker if (error != OT_ERROR_NONE)
151*cfb92d14SAndroid Build Coastguard Worker {
152*cfb92d14SAndroid Build Coastguard Worker LogCrit("Failed to forward DNS query %p to server: %d", static_cast<void *>(aTxn), error);
153*cfb92d14SAndroid Build Coastguard Worker }
154*cfb92d14SAndroid Build Coastguard Worker return;
155*cfb92d14SAndroid Build Coastguard Worker }
156*cfb92d14SAndroid Build Coastguard Worker
Cancel(otPlatDnsUpstreamQuery * aTxn)157*cfb92d14SAndroid Build Coastguard Worker void Resolver::Cancel(otPlatDnsUpstreamQuery *aTxn)
158*cfb92d14SAndroid Build Coastguard Worker {
159*cfb92d14SAndroid Build Coastguard Worker Transaction *txn = GetTransaction(aTxn);
160*cfb92d14SAndroid Build Coastguard Worker
161*cfb92d14SAndroid Build Coastguard Worker if (txn != nullptr)
162*cfb92d14SAndroid Build Coastguard Worker {
163*cfb92d14SAndroid Build Coastguard Worker CloseTransaction(txn);
164*cfb92d14SAndroid Build Coastguard Worker }
165*cfb92d14SAndroid Build Coastguard Worker
166*cfb92d14SAndroid Build Coastguard Worker otPlatDnsUpstreamQueryDone(gInstance, aTxn, nullptr);
167*cfb92d14SAndroid Build Coastguard Worker }
168*cfb92d14SAndroid Build Coastguard Worker
AllocateTransaction(otPlatDnsUpstreamQuery * aThreadTxn)169*cfb92d14SAndroid Build Coastguard Worker Resolver::Transaction *Resolver::AllocateTransaction(otPlatDnsUpstreamQuery *aThreadTxn)
170*cfb92d14SAndroid Build Coastguard Worker {
171*cfb92d14SAndroid Build Coastguard Worker int fdOrError = 0;
172*cfb92d14SAndroid Build Coastguard Worker Transaction *ret = nullptr;
173*cfb92d14SAndroid Build Coastguard Worker
174*cfb92d14SAndroid Build Coastguard Worker for (Transaction &txn : mUpstreamTransaction)
175*cfb92d14SAndroid Build Coastguard Worker {
176*cfb92d14SAndroid Build Coastguard Worker if (txn.mThreadTxn == nullptr)
177*cfb92d14SAndroid Build Coastguard Worker {
178*cfb92d14SAndroid Build Coastguard Worker fdOrError = CreateUdpSocket();
179*cfb92d14SAndroid Build Coastguard Worker if (fdOrError < 0)
180*cfb92d14SAndroid Build Coastguard Worker {
181*cfb92d14SAndroid Build Coastguard Worker LogInfo("Failed to create socket for upstream resolver: %d", fdOrError);
182*cfb92d14SAndroid Build Coastguard Worker break;
183*cfb92d14SAndroid Build Coastguard Worker }
184*cfb92d14SAndroid Build Coastguard Worker ret = &txn;
185*cfb92d14SAndroid Build Coastguard Worker ret->mUdpFd = fdOrError;
186*cfb92d14SAndroid Build Coastguard Worker ret->mThreadTxn = aThreadTxn;
187*cfb92d14SAndroid Build Coastguard Worker break;
188*cfb92d14SAndroid Build Coastguard Worker }
189*cfb92d14SAndroid Build Coastguard Worker }
190*cfb92d14SAndroid Build Coastguard Worker
191*cfb92d14SAndroid Build Coastguard Worker return ret;
192*cfb92d14SAndroid Build Coastguard Worker }
193*cfb92d14SAndroid Build Coastguard Worker
ForwardResponse(Transaction * aTxn)194*cfb92d14SAndroid Build Coastguard Worker void Resolver::ForwardResponse(Transaction *aTxn)
195*cfb92d14SAndroid Build Coastguard Worker {
196*cfb92d14SAndroid Build Coastguard Worker char response[kMaxDnsMessageSize];
197*cfb92d14SAndroid Build Coastguard Worker ssize_t readSize;
198*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
199*cfb92d14SAndroid Build Coastguard Worker otMessage *message = nullptr;
200*cfb92d14SAndroid Build Coastguard Worker
201*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit((readSize = read(aTxn->mUdpFd, response, sizeof(response))) > 0);
202*cfb92d14SAndroid Build Coastguard Worker
203*cfb92d14SAndroid Build Coastguard Worker message = otUdpNewMessage(gInstance, nullptr);
204*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(message != nullptr, error = OT_ERROR_NO_BUFS);
205*cfb92d14SAndroid Build Coastguard Worker SuccessOrExit(error = otMessageAppend(message, response, readSize));
206*cfb92d14SAndroid Build Coastguard Worker
207*cfb92d14SAndroid Build Coastguard Worker otPlatDnsUpstreamQueryDone(gInstance, aTxn->mThreadTxn, message);
208*cfb92d14SAndroid Build Coastguard Worker message = nullptr;
209*cfb92d14SAndroid Build Coastguard Worker
210*cfb92d14SAndroid Build Coastguard Worker exit:
211*cfb92d14SAndroid Build Coastguard Worker if (readSize < 0)
212*cfb92d14SAndroid Build Coastguard Worker {
213*cfb92d14SAndroid Build Coastguard Worker LogInfo("Failed to read response from upstream resolver socket: %d", errno);
214*cfb92d14SAndroid Build Coastguard Worker }
215*cfb92d14SAndroid Build Coastguard Worker if (error != OT_ERROR_NONE)
216*cfb92d14SAndroid Build Coastguard Worker {
217*cfb92d14SAndroid Build Coastguard Worker LogInfo("Failed to forward upstream DNS response: %s", otThreadErrorToString(error));
218*cfb92d14SAndroid Build Coastguard Worker }
219*cfb92d14SAndroid Build Coastguard Worker if (message != nullptr)
220*cfb92d14SAndroid Build Coastguard Worker {
221*cfb92d14SAndroid Build Coastguard Worker otMessageFree(message);
222*cfb92d14SAndroid Build Coastguard Worker }
223*cfb92d14SAndroid Build Coastguard Worker }
224*cfb92d14SAndroid Build Coastguard Worker
GetTransaction(int aFd)225*cfb92d14SAndroid Build Coastguard Worker Resolver::Transaction *Resolver::GetTransaction(int aFd)
226*cfb92d14SAndroid Build Coastguard Worker {
227*cfb92d14SAndroid Build Coastguard Worker Transaction *ret = nullptr;
228*cfb92d14SAndroid Build Coastguard Worker
229*cfb92d14SAndroid Build Coastguard Worker for (Transaction &txn : mUpstreamTransaction)
230*cfb92d14SAndroid Build Coastguard Worker {
231*cfb92d14SAndroid Build Coastguard Worker if (txn.mThreadTxn != nullptr && txn.mUdpFd == aFd)
232*cfb92d14SAndroid Build Coastguard Worker {
233*cfb92d14SAndroid Build Coastguard Worker ret = &txn;
234*cfb92d14SAndroid Build Coastguard Worker break;
235*cfb92d14SAndroid Build Coastguard Worker }
236*cfb92d14SAndroid Build Coastguard Worker }
237*cfb92d14SAndroid Build Coastguard Worker
238*cfb92d14SAndroid Build Coastguard Worker return ret;
239*cfb92d14SAndroid Build Coastguard Worker }
240*cfb92d14SAndroid Build Coastguard Worker
GetTransaction(otPlatDnsUpstreamQuery * aThreadTxn)241*cfb92d14SAndroid Build Coastguard Worker Resolver::Transaction *Resolver::GetTransaction(otPlatDnsUpstreamQuery *aThreadTxn)
242*cfb92d14SAndroid Build Coastguard Worker {
243*cfb92d14SAndroid Build Coastguard Worker Transaction *ret = nullptr;
244*cfb92d14SAndroid Build Coastguard Worker
245*cfb92d14SAndroid Build Coastguard Worker for (Transaction &txn : mUpstreamTransaction)
246*cfb92d14SAndroid Build Coastguard Worker {
247*cfb92d14SAndroid Build Coastguard Worker if (txn.mThreadTxn == aThreadTxn)
248*cfb92d14SAndroid Build Coastguard Worker {
249*cfb92d14SAndroid Build Coastguard Worker ret = &txn;
250*cfb92d14SAndroid Build Coastguard Worker break;
251*cfb92d14SAndroid Build Coastguard Worker }
252*cfb92d14SAndroid Build Coastguard Worker }
253*cfb92d14SAndroid Build Coastguard Worker
254*cfb92d14SAndroid Build Coastguard Worker return ret;
255*cfb92d14SAndroid Build Coastguard Worker }
256*cfb92d14SAndroid Build Coastguard Worker
CloseTransaction(Transaction * aTxn)257*cfb92d14SAndroid Build Coastguard Worker void Resolver::CloseTransaction(Transaction *aTxn)
258*cfb92d14SAndroid Build Coastguard Worker {
259*cfb92d14SAndroid Build Coastguard Worker if (aTxn->mUdpFd >= 0)
260*cfb92d14SAndroid Build Coastguard Worker {
261*cfb92d14SAndroid Build Coastguard Worker close(aTxn->mUdpFd);
262*cfb92d14SAndroid Build Coastguard Worker aTxn->mUdpFd = -1;
263*cfb92d14SAndroid Build Coastguard Worker }
264*cfb92d14SAndroid Build Coastguard Worker aTxn->mThreadTxn = nullptr;
265*cfb92d14SAndroid Build Coastguard Worker }
266*cfb92d14SAndroid Build Coastguard Worker
UpdateFdSet(otSysMainloopContext & aContext)267*cfb92d14SAndroid Build Coastguard Worker void Resolver::UpdateFdSet(otSysMainloopContext &aContext)
268*cfb92d14SAndroid Build Coastguard Worker {
269*cfb92d14SAndroid Build Coastguard Worker for (Transaction &txn : mUpstreamTransaction)
270*cfb92d14SAndroid Build Coastguard Worker {
271*cfb92d14SAndroid Build Coastguard Worker if (txn.mThreadTxn != nullptr)
272*cfb92d14SAndroid Build Coastguard Worker {
273*cfb92d14SAndroid Build Coastguard Worker FD_SET(txn.mUdpFd, &aContext.mReadFdSet);
274*cfb92d14SAndroid Build Coastguard Worker FD_SET(txn.mUdpFd, &aContext.mErrorFdSet);
275*cfb92d14SAndroid Build Coastguard Worker if (txn.mUdpFd > aContext.mMaxFd)
276*cfb92d14SAndroid Build Coastguard Worker {
277*cfb92d14SAndroid Build Coastguard Worker aContext.mMaxFd = txn.mUdpFd;
278*cfb92d14SAndroid Build Coastguard Worker }
279*cfb92d14SAndroid Build Coastguard Worker }
280*cfb92d14SAndroid Build Coastguard Worker }
281*cfb92d14SAndroid Build Coastguard Worker }
282*cfb92d14SAndroid Build Coastguard Worker
Process(const otSysMainloopContext & aContext)283*cfb92d14SAndroid Build Coastguard Worker void Resolver::Process(const otSysMainloopContext &aContext)
284*cfb92d14SAndroid Build Coastguard Worker {
285*cfb92d14SAndroid Build Coastguard Worker for (Transaction &txn : mUpstreamTransaction)
286*cfb92d14SAndroid Build Coastguard Worker {
287*cfb92d14SAndroid Build Coastguard Worker if (txn.mThreadTxn != nullptr)
288*cfb92d14SAndroid Build Coastguard Worker {
289*cfb92d14SAndroid Build Coastguard Worker // Note: On Linux, we can only get the error via read, so they should share the same logic.
290*cfb92d14SAndroid Build Coastguard Worker if (FD_ISSET(txn.mUdpFd, &aContext.mErrorFdSet) || FD_ISSET(txn.mUdpFd, &aContext.mReadFdSet))
291*cfb92d14SAndroid Build Coastguard Worker {
292*cfb92d14SAndroid Build Coastguard Worker ForwardResponse(&txn);
293*cfb92d14SAndroid Build Coastguard Worker CloseTransaction(&txn);
294*cfb92d14SAndroid Build Coastguard Worker }
295*cfb92d14SAndroid Build Coastguard Worker }
296*cfb92d14SAndroid Build Coastguard Worker }
297*cfb92d14SAndroid Build Coastguard Worker }
298*cfb92d14SAndroid Build Coastguard Worker
SetUpstreamDnsServers(const otIp6Address * aUpstreamDnsServers,int aNumServers)299*cfb92d14SAndroid Build Coastguard Worker void Resolver::SetUpstreamDnsServers(const otIp6Address *aUpstreamDnsServers, int aNumServers)
300*cfb92d14SAndroid Build Coastguard Worker {
301*cfb92d14SAndroid Build Coastguard Worker mUpstreamDnsServerCount = 0;
302*cfb92d14SAndroid Build Coastguard Worker
303*cfb92d14SAndroid Build Coastguard Worker for (int i = 0; i < aNumServers && i < kMaxUpstreamServerCount; ++i)
304*cfb92d14SAndroid Build Coastguard Worker {
305*cfb92d14SAndroid Build Coastguard Worker otIp4Address ip4Address;
306*cfb92d14SAndroid Build Coastguard Worker
307*cfb92d14SAndroid Build Coastguard Worker // TODO: support DNS servers with IPv6 addresses
308*cfb92d14SAndroid Build Coastguard Worker if (otIp4FromIp4MappedIp6Address(&aUpstreamDnsServers[i], &ip4Address) == OT_ERROR_NONE)
309*cfb92d14SAndroid Build Coastguard Worker {
310*cfb92d14SAndroid Build Coastguard Worker mUpstreamDnsServerList[mUpstreamDnsServerCount] = ip4Address.mFields.m32;
311*cfb92d14SAndroid Build Coastguard Worker mUpstreamDnsServerCount++;
312*cfb92d14SAndroid Build Coastguard Worker }
313*cfb92d14SAndroid Build Coastguard Worker }
314*cfb92d14SAndroid Build Coastguard Worker }
315*cfb92d14SAndroid Build Coastguard Worker
CreateUdpSocket(void)316*cfb92d14SAndroid Build Coastguard Worker int Resolver::CreateUdpSocket(void)
317*cfb92d14SAndroid Build Coastguard Worker {
318*cfb92d14SAndroid Build Coastguard Worker int fd = -1;
319*cfb92d14SAndroid Build Coastguard Worker
320*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(otSysGetInfraNetifName() != nullptr, LogDebg("No infra network interface available"));
321*cfb92d14SAndroid Build Coastguard Worker fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
322*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(fd >= 0, LogDebg("Failed to create the UDP socket: %s", strerror(errno)));
323*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_CONFIG_UPSTREAM_DNS_BIND_TO_INFRA_NETIF
324*cfb92d14SAndroid Build Coastguard Worker if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, otSysGetInfraNetifName(), strlen(otSysGetInfraNetifName())) < 0)
325*cfb92d14SAndroid Build Coastguard Worker {
326*cfb92d14SAndroid Build Coastguard Worker LogDebg("Failed to bind the UDP socket to infra interface %s: %s", otSysGetInfraNetifName(), strerror(errno));
327*cfb92d14SAndroid Build Coastguard Worker close(fd);
328*cfb92d14SAndroid Build Coastguard Worker fd = -1;
329*cfb92d14SAndroid Build Coastguard Worker ExitNow();
330*cfb92d14SAndroid Build Coastguard Worker }
331*cfb92d14SAndroid Build Coastguard Worker #endif
332*cfb92d14SAndroid Build Coastguard Worker
333*cfb92d14SAndroid Build Coastguard Worker exit:
334*cfb92d14SAndroid Build Coastguard Worker return fd;
335*cfb92d14SAndroid Build Coastguard Worker }
336*cfb92d14SAndroid Build Coastguard Worker
337*cfb92d14SAndroid Build Coastguard Worker } // namespace Posix
338*cfb92d14SAndroid Build Coastguard Worker } // namespace ot
339*cfb92d14SAndroid Build Coastguard Worker
platformResolverProcess(const otSysMainloopContext * aContext)340*cfb92d14SAndroid Build Coastguard Worker void platformResolverProcess(const otSysMainloopContext *aContext) { gResolver.Process(*aContext); }
341*cfb92d14SAndroid Build Coastguard Worker
platformResolverUpdateFdSet(otSysMainloopContext * aContext)342*cfb92d14SAndroid Build Coastguard Worker void platformResolverUpdateFdSet(otSysMainloopContext *aContext) { gResolver.UpdateFdSet(*aContext); }
343*cfb92d14SAndroid Build Coastguard Worker
platformResolverInit(void)344*cfb92d14SAndroid Build Coastguard Worker void platformResolverInit(void) { gResolver.Init(); }
345*cfb92d14SAndroid Build Coastguard Worker
otPlatDnsStartUpstreamQuery(otInstance * aInstance,otPlatDnsUpstreamQuery * aTxn,const otMessage * aQuery)346*cfb92d14SAndroid Build Coastguard Worker void otPlatDnsStartUpstreamQuery(otInstance *aInstance, otPlatDnsUpstreamQuery *aTxn, const otMessage *aQuery)
347*cfb92d14SAndroid Build Coastguard Worker {
348*cfb92d14SAndroid Build Coastguard Worker OT_UNUSED_VARIABLE(aInstance);
349*cfb92d14SAndroid Build Coastguard Worker
350*cfb92d14SAndroid Build Coastguard Worker gResolver.Query(aTxn, aQuery);
351*cfb92d14SAndroid Build Coastguard Worker }
352*cfb92d14SAndroid Build Coastguard Worker
otPlatDnsCancelUpstreamQuery(otInstance * aInstance,otPlatDnsUpstreamQuery * aTxn)353*cfb92d14SAndroid Build Coastguard Worker void otPlatDnsCancelUpstreamQuery(otInstance *aInstance, otPlatDnsUpstreamQuery *aTxn)
354*cfb92d14SAndroid Build Coastguard Worker {
355*cfb92d14SAndroid Build Coastguard Worker OT_UNUSED_VARIABLE(aInstance);
356*cfb92d14SAndroid Build Coastguard Worker
357*cfb92d14SAndroid Build Coastguard Worker gResolver.Cancel(aTxn);
358*cfb92d14SAndroid Build Coastguard Worker }
359*cfb92d14SAndroid Build Coastguard Worker
otSysUpstreamDnsServerSetResolvConfEnabled(bool aEnabled)360*cfb92d14SAndroid Build Coastguard Worker void otSysUpstreamDnsServerSetResolvConfEnabled(bool aEnabled) { gResolver.SetResolvConfEnabled(aEnabled); }
361*cfb92d14SAndroid Build Coastguard Worker
otSysUpstreamDnsSetServerList(const otIp6Address * aUpstreamDnsServers,int aNumServers)362*cfb92d14SAndroid Build Coastguard Worker void otSysUpstreamDnsSetServerList(const otIp6Address *aUpstreamDnsServers, int aNumServers)
363*cfb92d14SAndroid Build Coastguard Worker {
364*cfb92d14SAndroid Build Coastguard Worker gResolver.SetUpstreamDnsServers(aUpstreamDnsServers, aNumServers);
365*cfb92d14SAndroid Build Coastguard Worker }
366*cfb92d14SAndroid Build Coastguard Worker
367*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
368