xref: /aosp_15_r20/external/openthread/src/posix/platform/resolver.cpp (revision cfb92d1480a9e65faed56933e9c12405f45898b4)
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