/src/openweave-core/src/inet/DNSResolver.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * |
3 | | * Copyright (c) 2013-2017 Nest Labs, Inc. |
4 | | * All rights reserved. |
5 | | * |
6 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
7 | | * you may not use this file except in compliance with the License. |
8 | | * You may obtain a copy of the License at |
9 | | * |
10 | | * http://www.apache.org/licenses/LICENSE-2.0 |
11 | | * |
12 | | * Unless required by applicable law or agreed to in writing, software |
13 | | * distributed under the License is distributed on an "AS IS" BASIS, |
14 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
15 | | * See the License for the specific language governing permissions and |
16 | | * limitations under the License. |
17 | | */ |
18 | | |
19 | | /** |
20 | | * @file |
21 | | * This file implements DNSResolver, the object that abstracts |
22 | | * Domain Name System (DNS) resolution in InetLayer. |
23 | | * |
24 | | */ |
25 | | |
26 | | #include <InetLayer/InetLayer.h> |
27 | | #include <InetLayer/DNSResolver.h> |
28 | | #include <InetLayer/InetLayerEvents.h> |
29 | | |
30 | | #include <Weave/Support/CodeUtils.h> |
31 | | |
32 | | #include <string.h> |
33 | | |
34 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
35 | | #include <lwip/init.h> |
36 | | #include <lwip/dns.h> |
37 | | #include <lwip/tcpip.h> |
38 | | |
39 | | #ifndef LWIP_DNS_FOUND_CALLBACK_TYPE |
40 | | #define LWIP_DNS_FOUND_CALLBACK_TYPE dns_found_callback |
41 | | #endif |
42 | | #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP |
43 | | |
44 | | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
45 | | #include <netdb.h> |
46 | | #include <errno.h> |
47 | | #include <stdlib.h> |
48 | | #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
49 | | |
50 | | namespace nl { |
51 | | namespace Inet { |
52 | | |
53 | | Weave::System::ObjectPool<DNSResolver, INET_CONFIG_NUM_DNS_RESOLVERS> DNSResolver::sPool; |
54 | | |
55 | | /** |
56 | | * This method revolves a host name into a list of IP addresses. |
57 | | * |
58 | | * @note |
59 | | * Even if the operation completes successfully, |
60 | | * the result might be a zero-length list of IP addresses. |
61 | | * Most of the error generated are returned via the |
62 | | * application callback. |
63 | | * |
64 | | * @param[in] hostName A pointer to a C string representing the host name |
65 | | * to be queried. |
66 | | * @param[in] hostNameLen The string length of host name. |
67 | | * @param[in] maxAddrs The maximum number of addresses to store in the DNS |
68 | | * table. |
69 | | * @param[in] options An integer value controlling how host name address |
70 | | * resolution is performed. Values are from the #DNSOptions |
71 | | * enumeration. |
72 | | * @param[in] addrArray A pointer to the DNS table. |
73 | | * @param[in] onComplete A pointer to the callback function when a DNS |
74 | | * request is complete. |
75 | | * @param[in] appState A pointer to the application state to be passed to |
76 | | * onComplete when a DNS request is complete. |
77 | | * |
78 | | * @retval INET_NO_ERROR if a DNS request is handled |
79 | | * successfully. |
80 | | * |
81 | | * @retval INET_ERROR_NOT_IMPLEMENTED if DNS resolution is not enabled on |
82 | | * the underlying platform. |
83 | | * |
84 | | * @retval _other_ if other POSIX network or OS error |
85 | | * was returned by the underlying DNS |
86 | | * resolver implementation. |
87 | | * |
88 | | */ |
89 | | INET_ERROR DNSResolver::Resolve(const char *hostName, uint16_t hostNameLen, uint8_t options, |
90 | | uint8_t maxAddrs, IPAddress *addrArray, |
91 | | DNSResolver::OnResolveCompleteFunct onComplete, void *appState) |
92 | 0 | { |
93 | 0 | INET_ERROR res = INET_NO_ERROR; |
94 | |
|
95 | | #if !WEAVE_SYSTEM_CONFIG_USE_SOCKETS && !LWIP_DNS |
96 | | Release(); |
97 | | return INET_ERROR_NOT_IMPLEMENTED; |
98 | | #endif // !WEAVE_SYSTEM_CONFIG_USE_SOCKETS && !LWIP_DNS |
99 | |
|
100 | 0 | uint8_t addrFamilyOption = (options & kDNSOption_AddrFamily_Mask); |
101 | 0 | uint8_t optionFlags = (options & kDNSOption_Flags_Mask); |
102 | | |
103 | | // Check that the supplied options are valid. |
104 | 0 | if ((addrFamilyOption != kDNSOption_AddrFamily_Any && |
105 | 0 | addrFamilyOption != kDNSOption_AddrFamily_IPv4Only && |
106 | 0 | addrFamilyOption != kDNSOption_AddrFamily_IPv4Preferred && |
107 | 0 | addrFamilyOption != kDNSOption_AddrFamily_IPv6Only && |
108 | 0 | addrFamilyOption != kDNSOption_AddrFamily_IPv6Preferred) || |
109 | 0 | (optionFlags & ~kDNSOption_ValidFlags) != 0) |
110 | 0 | { |
111 | 0 | Release(); |
112 | 0 | return INET_ERROR_BAD_ARGS; |
113 | 0 | } |
114 | | |
115 | 0 | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS || (WEAVE_SYSTEM_CONFIG_USE_LWIP && LWIP_DNS) |
116 | | |
117 | | // TODO: Eliminate the need for a local buffer when running on LwIP by changing |
118 | | // the LwIP DNS interface to support non-nul terminated strings. |
119 | | |
120 | 0 | char hostNameBuf[NL_DNS_HOSTNAME_MAX_LEN + 1]; // DNS limits hostnames to 253 max characters. |
121 | |
|
122 | 0 | memcpy(hostNameBuf, hostName, hostNameLen); |
123 | 0 | hostNameBuf[hostNameLen] = 0; |
124 | |
|
125 | 0 | AppState = appState; |
126 | 0 | AddrArray = addrArray; |
127 | 0 | MaxAddrs = maxAddrs; |
128 | 0 | NumAddrs = 0; |
129 | 0 | DNSOptions = options; |
130 | 0 | OnComplete = onComplete; |
131 | |
|
132 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
133 | | |
134 | | #if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 |
135 | | |
136 | | u8_t lwipAddrType; |
137 | | |
138 | | #if INET_CONFIG_ENABLE_IPV4 |
139 | | switch (addrFamilyOption) |
140 | | { |
141 | | case kDNSOption_AddrFamily_IPv4Only: |
142 | | lwipAddrType = LWIP_DNS_ADDRTYPE_IPV4; |
143 | | break; |
144 | | case kDNSOption_AddrFamily_Any: |
145 | | case kDNSOption_AddrFamily_IPv4Preferred: |
146 | | lwipAddrType = LWIP_DNS_ADDRTYPE_IPV4_IPV6; |
147 | | break; |
148 | | case kDNSOption_AddrFamily_IPv6Only: |
149 | | lwipAddrType = LWIP_DNS_ADDRTYPE_IPV6; |
150 | | break; |
151 | | case kDNSOption_AddrFamily_IPv6Preferred: |
152 | | lwipAddrType = LWIP_DNS_ADDRTYPE_IPV6_IPV4; |
153 | | break; |
154 | | default: |
155 | | WeaveDie(); |
156 | | } |
157 | | #else // INET_CONFIG_ENABLE_IPV4 |
158 | | lwipAddrType = LWIP_DNS_ADDRTYPE_IPV6; |
159 | | #endif // INET_CONFIG_ENABLE_IPV4 |
160 | | |
161 | | #else // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR < 5 |
162 | | |
163 | | #if INET_CONFIG_ENABLE_IPV4 |
164 | | if (addrFamilyOption == kDNSOption_AddrFamily_IPv6Only) |
165 | | #endif |
166 | | { |
167 | | Release(); |
168 | | return INET_ERROR_NOT_IMPLEMENTED; |
169 | | } |
170 | | |
171 | | #endif // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR < 5 |
172 | | |
173 | | // Lock LwIP stack |
174 | | LOCK_TCPIP_CORE(); |
175 | | |
176 | | ip_addr_t lwipAddr; |
177 | | LWIP_DNS_FOUND_CALLBACK_TYPE lwipCallback = reinterpret_cast<LWIP_DNS_FOUND_CALLBACK_TYPE>(LwIPHandleResolveComplete); |
178 | | |
179 | | err_t lwipErr = |
180 | | #if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 |
181 | | dns_gethostbyname_addrtype(hostNameBuf, &lwipAddr, lwipCallback, this, lwipAddrType); |
182 | | #else |
183 | | dns_gethostbyname(hostNameBuf, &lwipAddr, lwipCallback, this); |
184 | | #endif |
185 | | |
186 | | // Unlock LwIP stack |
187 | | UNLOCK_TCPIP_CORE(); |
188 | | |
189 | | if (lwipErr == ERR_OK) |
190 | | { |
191 | | Weave::System::Layer& lSystemLayer = SystemLayer(); |
192 | | |
193 | | #if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 |
194 | | AddrArray[0] = IPAddress::FromLwIPAddr(lwipAddr); |
195 | | #else |
196 | | AddrArray[0] = IPAddress::FromIPv4(lwipAddr); |
197 | | #endif |
198 | | NumAddrs = 1; |
199 | | |
200 | | lSystemLayer.PostEvent(*this, kInetEvent_DNSResolveComplete, 0); |
201 | | } |
202 | | else if (lwipErr != ERR_INPROGRESS) |
203 | | { |
204 | | res = Weave::System::MapErrorLwIP(lwipErr); |
205 | | Release(); |
206 | | } |
207 | | |
208 | | return res; |
209 | | |
210 | | #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP |
211 | |
|
212 | 0 | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
213 | |
|
214 | 0 | struct addrinfo gaiHints; |
215 | 0 | struct addrinfo * gaiResults = NULL; |
216 | 0 | int gaiReturnCode; |
217 | | |
218 | | // Configure the hints argument for getaddrinfo() |
219 | 0 | InitAddrInfoHints(gaiHints); |
220 | | |
221 | | // Call getaddrinfo() to perform the name resolution. |
222 | 0 | gaiReturnCode = getaddrinfo(hostNameBuf, NULL, &gaiHints, &gaiResults); |
223 | | |
224 | | // Process the return code and results list returned by getaddrinfo(). If the call |
225 | | // was successful this will copy the resultant addresses into the caller's array. |
226 | 0 | res = ProcessGetAddrInfoResult(gaiReturnCode, gaiResults); |
227 | | |
228 | | // Invoke the caller's completion function. |
229 | 0 | onComplete(appState, res, NumAddrs, addrArray); |
230 | | |
231 | | // Release DNSResolver object. |
232 | 0 | Release(); |
233 | |
|
234 | 0 | return INET_NO_ERROR; |
235 | |
|
236 | 0 | #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
237 | 0 | #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS || (WEAVE_SYSTEM_CONFIG_USE_LWIP && LWIP_DNS) |
238 | 0 | } |
239 | | |
240 | | |
241 | | /** |
242 | | * This method cancels DNS requests that are in progress. |
243 | | * |
244 | | * @retval INET_NO_ERROR. |
245 | | * |
246 | | */ |
247 | | INET_ERROR DNSResolver::Cancel() |
248 | 0 | { |
249 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
250 | | |
251 | | // NOTE: LwIP does not support canceling DNS requests that are in progress. As a consequence, |
252 | | // we can't release the DNSResolver object until LwIP calls us back (because LwIP retains a |
253 | | // pointer to the DNSResolver object while the request is active). However, now that the |
254 | | // application has called Cancel() we have to make sure to NOT call their OnComplete function |
255 | | // when the request completes. |
256 | | // |
257 | | // To ensure the right thing happens, we NULL the OnComplete pointer here, which signals the |
258 | | // code in HandleResolveComplete() and LwIPHandleResolveComplete() to not interact with the |
259 | | // application's state data (AddrArray) and to not call the application's callback. This has |
260 | | // to happen with the LwIP lock held, since LwIPHandleResolveComplete() runs on LwIP's thread. |
261 | | |
262 | | // Lock LwIP stack |
263 | | LOCK_TCPIP_CORE(); |
264 | | |
265 | | // Signal that the request has been canceled by clearing the state of the resolver object. |
266 | | OnComplete = NULL; |
267 | | AddrArray = NULL; |
268 | | MaxAddrs = 0; |
269 | | NumAddrs = 0; |
270 | | |
271 | | // Unlock LwIP stack |
272 | | UNLOCK_TCPIP_CORE(); |
273 | | |
274 | | #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP |
275 | |
|
276 | 0 | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
277 | 0 | #if INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS |
278 | | // NOTE: DNS lookups can be canceled only when using the asynchronous mode. |
279 | |
|
280 | 0 | InetLayer& inet = Layer(); |
281 | |
|
282 | 0 | OnComplete = NULL; |
283 | 0 | AppState = NULL; |
284 | 0 | inet.mAsyncDNSResolver.Cancel(*this); |
285 | |
|
286 | 0 | #endif // INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS |
287 | 0 | #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
288 | |
|
289 | 0 | return INET_NO_ERROR; |
290 | 0 | } |
291 | | |
292 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
293 | | |
294 | | /** |
295 | | * This method is called by InetLayer on success, failure, or timeout of a |
296 | | * DNS request. |
297 | | * |
298 | | */ |
299 | | void DNSResolver::HandleResolveComplete() |
300 | | { |
301 | | // Call the application's completion handler if the request hasn't been canceled. |
302 | | if (OnComplete != NULL) |
303 | | OnComplete(AppState, (NumAddrs > 0) ? INET_NO_ERROR : INET_ERROR_HOST_NOT_FOUND, NumAddrs, AddrArray); |
304 | | |
305 | | // Release the resolver object. |
306 | | Release(); |
307 | | } |
308 | | |
309 | | |
310 | | /** |
311 | | * This method is called by LwIP network stack on success, failure, or timeout |
312 | | * of a DNS request. |
313 | | * |
314 | | * @param[in] name A pointer to a NULL-terminated C string |
315 | | * representing the host name that is queried. |
316 | | * @param[in] ipaddr A pointer to a list of resolved IP addresses. |
317 | | * @param[in] callback_arg A pointer to the arguments that are passed to |
318 | | * the callback function. |
319 | | * |
320 | | */ |
321 | | #if LWIP_VERSION_MAJOR > 1 |
322 | | void DNSResolver::LwIPHandleResolveComplete(const char *name, const ip_addr_t *ipaddr, void *callback_arg) |
323 | | #else // LWIP_VERSION_MAJOR <= 1 |
324 | | void DNSResolver::LwIPHandleResolveComplete(const char *name, ip_addr_t *ipaddr, void *callback_arg) |
325 | | #endif // LWIP_VERSION_MAJOR <= 1 |
326 | | { |
327 | | DNSResolver *resolver = (DNSResolver *)callback_arg; |
328 | | |
329 | | if (resolver != NULL) |
330 | | { |
331 | | Weave::System::Layer& lSystemLayer = resolver->SystemLayer(); |
332 | | |
333 | | // Copy the resolved address to the application supplied buffer, but only if the request hasn't been canceled. |
334 | | if (resolver->OnComplete != NULL && ipaddr != NULL) |
335 | | { |
336 | | #if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 |
337 | | resolver->AddrArray[0] = IPAddress::FromLwIPAddr(*ipaddr); |
338 | | #else |
339 | | resolver->AddrArray[0] = IPAddress::FromIPv4(*ipaddr); |
340 | | #endif |
341 | | resolver->NumAddrs = 1; |
342 | | } |
343 | | |
344 | | lSystemLayer.PostEvent(*resolver, kInetEvent_DNSResolveComplete, 0); |
345 | | } |
346 | | } |
347 | | |
348 | | #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP |
349 | | |
350 | | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
351 | | |
352 | | void DNSResolver::InitAddrInfoHints(struct addrinfo & hints) |
353 | 0 | { |
354 | 0 | uint8_t addrFamilyOption = (DNSOptions & kDNSOption_AddrFamily_Mask); |
355 | |
|
356 | 0 | memset(&hints, 0, sizeof(hints)); |
357 | 0 | #if INET_CONFIG_ENABLE_IPV4 |
358 | 0 | if (addrFamilyOption == kDNSOption_AddrFamily_IPv4Only) |
359 | 0 | { |
360 | 0 | hints.ai_family = AF_INET; |
361 | 0 | } |
362 | 0 | else if (addrFamilyOption == kDNSOption_AddrFamily_IPv6Only) |
363 | 0 | { |
364 | 0 | hints.ai_family = AF_INET6; |
365 | 0 | } |
366 | 0 | else |
367 | 0 | { |
368 | 0 | hints.ai_family = AF_UNSPEC; |
369 | 0 | } |
370 | | #else // INET_CONFIG_ENABLE_IPV4 |
371 | | hints.ai_family = AF_INET6; |
372 | | #endif // INET_CONFIG_ENABLE_IPV4 |
373 | 0 | hints.ai_flags = AI_ADDRCONFIG; |
374 | 0 | } |
375 | | |
376 | | INET_ERROR DNSResolver::ProcessGetAddrInfoResult(int returnCode, struct addrinfo * results) |
377 | 0 | { |
378 | 0 | INET_ERROR err = INET_NO_ERROR; |
379 | | |
380 | | // If getaddrinfo() succeeded, copy addresses in the returned addrinfo structures into the |
381 | | // application's output array... |
382 | 0 | if (returnCode == 0) |
383 | 0 | { |
384 | 0 | NumAddrs = 0; |
385 | |
|
386 | 0 | #if INET_CONFIG_ENABLE_IPV4 |
387 | | |
388 | | // Based on the address family option specified by the application, determine which |
389 | | // types of addresses should be returned and the order in which they should appear. |
390 | 0 | uint8_t addrFamilyOption = (DNSOptions & kDNSOption_AddrFamily_Mask); |
391 | 0 | int primaryFamily, secondaryFamily; |
392 | 0 | switch (addrFamilyOption) |
393 | 0 | { |
394 | 0 | case kDNSOption_AddrFamily_Any: |
395 | 0 | primaryFamily = AF_UNSPEC; |
396 | 0 | secondaryFamily = AF_UNSPEC; |
397 | 0 | break; |
398 | 0 | case kDNSOption_AddrFamily_IPv4Only: |
399 | 0 | primaryFamily = AF_INET; |
400 | 0 | secondaryFamily = AF_UNSPEC; |
401 | 0 | break; |
402 | 0 | case kDNSOption_AddrFamily_IPv4Preferred: |
403 | 0 | primaryFamily = AF_INET; |
404 | 0 | secondaryFamily = AF_INET6; |
405 | 0 | break; |
406 | 0 | case kDNSOption_AddrFamily_IPv6Only: |
407 | 0 | primaryFamily = AF_INET6; |
408 | 0 | secondaryFamily = AF_UNSPEC; |
409 | 0 | break; |
410 | 0 | case kDNSOption_AddrFamily_IPv6Preferred: |
411 | 0 | primaryFamily = AF_INET6; |
412 | 0 | secondaryFamily = AF_INET; |
413 | 0 | break; |
414 | 0 | default: |
415 | 0 | WeaveDie(); |
416 | 0 | } |
417 | | |
418 | | // Determine the number of addresses of each family present in the results. |
419 | | // In the case of the secondary address family, only count these if they are |
420 | | // to be returned in the results. |
421 | 0 | uint8_t numPrimaryAddrs = CountAddresses(primaryFamily, results); |
422 | 0 | uint8_t numSecondaryAddrs = (secondaryFamily != AF_UNSPEC) ? CountAddresses(secondaryFamily, results) : 0; |
423 | 0 | uint8_t numAddrs = numPrimaryAddrs + numSecondaryAddrs; |
424 | | |
425 | | // If the total number of addresses to be returned exceeds the application |
426 | | // specified max, ensure that at least 1 address from the secondary family |
427 | | // appears in the result (unless of course there are no such addresses or |
428 | | // the max is set to 1). |
429 | | // This ensures the application will try at least one secondary address |
430 | | // when attempting to communicate with the host. |
431 | 0 | if (numAddrs > MaxAddrs && MaxAddrs > 1 && numPrimaryAddrs > 0 && numSecondaryAddrs > 0) |
432 | 0 | { |
433 | 0 | numPrimaryAddrs = ::nl::Weave::min(numPrimaryAddrs, (uint8_t)(MaxAddrs - 1)); |
434 | 0 | } |
435 | | |
436 | | // Copy the primary addresses into the beginning of the application's output array, |
437 | | // up to the limit determined above. |
438 | 0 | CopyAddresses(primaryFamily, numPrimaryAddrs, results); |
439 | | |
440 | | // If secondary addresses are being returned, copy them into the output array after |
441 | | // the primary addresses. |
442 | 0 | if (numSecondaryAddrs != 0) |
443 | 0 | { |
444 | 0 | CopyAddresses(secondaryFamily, numSecondaryAddrs, results); |
445 | 0 | } |
446 | |
|
447 | | #else // INET_CONFIG_ENABLE_IPV4 |
448 | | |
449 | | // Copy IPv6 addresses into the application's output array. |
450 | | CopyAddresses(AF_INET6, UINT8_MAX, results); |
451 | | |
452 | | #endif // INET_CONFIG_ENABLE_IPV4 |
453 | | |
454 | | // If in the end no addresses were returned, treat this as a "host not found" error. |
455 | 0 | if (NumAddrs == 0) |
456 | 0 | { |
457 | 0 | err = INET_ERROR_HOST_NOT_FOUND; |
458 | 0 | } |
459 | 0 | } |
460 | | |
461 | | // Otherwise, getaddrinfo() failed, so translate the return code to an appropriate |
462 | | // Inet error... |
463 | 0 | else |
464 | 0 | { |
465 | 0 | switch (returnCode) |
466 | 0 | { |
467 | 0 | case EAI_NONAME: |
468 | 0 | case EAI_NODATA: |
469 | 0 | case EAI_ADDRFAMILY: |
470 | | // Each of these errors is translated to "host not found" for simplicity at the |
471 | | // application layer. On most systems, the errors have the following meanings: |
472 | | // EAI_NONAME is returned when there are no DNS records for the requested host name. |
473 | | // EAI_NODATA is returned when there are no host records (A or AAAA) for the requested |
474 | | // name, but other records do exist (e.g. MX or TXT). |
475 | | // EAI_ADDRFAMILY is returned when a text-form address is given as the name, but its |
476 | | // address family (IPv4 or IPv6) does not match the value specified in hints.ai_family. |
477 | 0 | err = INET_ERROR_HOST_NOT_FOUND; |
478 | 0 | break; |
479 | 0 | case EAI_AGAIN: |
480 | 0 | err = INET_ERROR_DNS_TRY_AGAIN; |
481 | 0 | break; |
482 | 0 | case EAI_SYSTEM: |
483 | 0 | err = Weave::System::MapErrorPOSIX(errno); |
484 | 0 | break; |
485 | 0 | default: |
486 | 0 | err = INET_ERROR_DNS_NO_RECOVERY; |
487 | 0 | break; |
488 | 0 | } |
489 | 0 | } |
490 | | |
491 | | // Free the results structure. |
492 | 0 | if (results != NULL) |
493 | 0 | freeaddrinfo(results); |
494 | |
|
495 | 0 | return err; |
496 | 0 | } |
497 | | |
498 | | void DNSResolver::CopyAddresses(int family, uint8_t count, const struct addrinfo * addrs) |
499 | 0 | { |
500 | 0 | for (const struct addrinfo *addr = addrs; |
501 | 0 | addr != NULL && NumAddrs < MaxAddrs && count > 0; |
502 | 0 | addr = addr->ai_next) |
503 | 0 | { |
504 | 0 | if (family == AF_UNSPEC || addr->ai_addr->sa_family == family) |
505 | 0 | { |
506 | 0 | AddrArray[NumAddrs++] = IPAddress::FromSockAddr(*addr->ai_addr); |
507 | 0 | count--; |
508 | 0 | } |
509 | 0 | } |
510 | 0 | } |
511 | | |
512 | | uint8_t DNSResolver::CountAddresses(int family, const struct addrinfo * addrs) |
513 | 0 | { |
514 | 0 | uint8_t count = 0; |
515 | |
|
516 | 0 | for (const struct addrinfo *addr = addrs; |
517 | 0 | addr != NULL && count < UINT8_MAX; |
518 | 0 | addr = addr->ai_next) |
519 | 0 | { |
520 | 0 | if (family == AF_UNSPEC || addr->ai_addr->sa_family == family) |
521 | 0 | { |
522 | 0 | count++; |
523 | 0 | } |
524 | 0 | } |
525 | |
|
526 | 0 | return count; |
527 | 0 | } |
528 | | |
529 | | #if INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS |
530 | | |
531 | | void DNSResolver::HandleAsyncResolveComplete(void) |
532 | 0 | { |
533 | | // Copy the resolved address to the application supplied buffer, but only if the request hasn't been canceled. |
534 | 0 | if (OnComplete && mState != kState_Canceled) |
535 | 0 | { |
536 | 0 | OnComplete(AppState, asyncDNSResolveResult, NumAddrs, AddrArray); |
537 | 0 | } |
538 | |
|
539 | 0 | Release(); |
540 | 0 | } |
541 | | #endif // INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS |
542 | | #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
543 | | |
544 | | } // namespace Inet |
545 | | } // namespace nl |