1 /** @file
2 * @brief DNS resolve API
3 *
4 * An API for applications to do DNS query.
5 */
6
7 /*
8 * Copyright (c) 2017 Intel Corporation
9 * Copyright (c) 2024 Nordic Semiconductor
10 *
11 * SPDX-License-Identifier: Apache-2.0
12 */
13
14 #include <zephyr/logging/log.h>
15 LOG_MODULE_REGISTER(net_dns_resolve, CONFIG_DNS_RESOLVER_LOG_LEVEL);
16
17 #include <zephyr/types.h>
18 #include <zephyr/random/random.h>
19 #include <string.h>
20 #include <errno.h>
21 #include <stdlib.h>
22 #include <ctype.h>
23
24 #include <zephyr/sys/crc.h>
25 #include <zephyr/net/net_ip.h>
26 #include <zephyr/net/net_pkt.h>
27 #include <zephyr/net/net_mgmt.h>
28 #include <zephyr/net/igmp.h>
29 #include <zephyr/net/mld.h>
30 #include <zephyr/net/dns_resolve.h>
31 #include <zephyr/net/socket_service.h>
32 #include "../../ip/net_private.h"
33 #include "dns_pack.h"
34 #include "dns_internal.h"
35 #include "dns_cache.h"
36 #include "../../ip/net_stats.h"
37
38 #define DNS_SERVER_COUNT CONFIG_DNS_RESOLVER_MAX_SERVERS
39 #define SERVER_COUNT (DNS_SERVER_COUNT + DNS_MAX_MCAST_SERVERS)
40
41 extern void dns_dispatcher_svc_handler(struct net_socket_service_event *pev);
42
43 NET_SOCKET_SERVICE_SYNC_DEFINE_STATIC(resolve_svc, dns_dispatcher_svc_handler,
44 DNS_RESOLVER_MAX_POLL);
45
46 #define MDNS_IPV4_ADDR "224.0.0.251:5353"
47 #define MDNS_IPV6_ADDR "[ff02::fb]:5353"
48
49 #define LLMNR_IPV4_ADDR "224.0.0.252:5355"
50 #define LLMNR_IPV6_ADDR "[ff02::1:3]:5355"
51
52 #define DNS_QUERY_MAX_SIZE (DNS_MSG_HEADER_SIZE + CONFIG_DNS_RESOLVER_MAX_QUERY_LEN + \
53 DNS_QTYPE_LEN + DNS_QCLASS_LEN)
54
55 /* Compressed RR uses a pointer to another RR. So, min size is 12 bytes without
56 * considering RR payload.
57 * See https://tools.ietf.org/html/rfc1035#section-4.1.4
58 */
59 #define DNS_ANSWER_PTR_LEN 12
60
61 /* See dns_unpack_answer, and also see:
62 * https://tools.ietf.org/html/rfc1035#section-4.1.2
63 */
64 #define DNS_QUERY_POS 0x0c
65
66 #define DNS_IPV4_LEN sizeof(struct in_addr)
67 #define DNS_IPV6_LEN sizeof(struct in6_addr)
68
69 #define DNS_RESOLVER_MIN_BUF 1
70 #define DNS_RESOLVER_BUF_CTR (DNS_RESOLVER_MIN_BUF + \
71 CONFIG_DNS_RESOLVER_ADDITIONAL_BUF_CTR)
72
73 NET_BUF_POOL_DEFINE(dns_msg_pool, DNS_RESOLVER_BUF_CTR,
74 DNS_RESOLVER_MAX_BUF_SIZE, 0, NULL);
75
76 NET_BUF_POOL_DEFINE(dns_qname_pool, DNS_RESOLVER_BUF_CTR,
77 CONFIG_DNS_RESOLVER_MAX_QUERY_LEN,
78 0, NULL);
79
80 #ifdef CONFIG_DNS_RESOLVER_CACHE
81 DNS_CACHE_DEFINE(dns_cache, CONFIG_DNS_RESOLVER_CACHE_MAX_ENTRIES);
82 #endif /* CONFIG_DNS_RESOLVER_CACHE */
83
84 static int init_called;
85 static struct dns_resolve_context dns_default_ctx;
86
87 /* Must be invoked with context lock held */
88 static int dns_write(struct dns_resolve_context *ctx,
89 int server_idx,
90 int query_idx,
91 uint8_t *buf, size_t buf_len, size_t max_len,
92 struct net_buf *dns_qname,
93 int hop_limit);
94 static int dns_read(struct dns_resolve_context *ctx,
95 struct net_buf *dns_data, size_t buf_len,
96 uint16_t *dns_id,
97 struct net_buf *dns_cname,
98 uint16_t *query_hash);
99 static inline int get_slot_by_id(struct dns_resolve_context *ctx,
100 uint16_t dns_id,
101 uint16_t query_hash);
102 static inline void invoke_query_callback(int status,
103 struct dns_addrinfo *info,
104 struct dns_pending_query *pending_query);
105 static void release_query(struct dns_pending_query *pending_query);
106
server_is_mdns(sa_family_t family,struct sockaddr * addr)107 static bool server_is_mdns(sa_family_t family, struct sockaddr *addr)
108 {
109 if (family == AF_INET) {
110 if (net_ipv4_is_addr_mcast(&net_sin(addr)->sin_addr) &&
111 net_sin(addr)->sin_addr.s4_addr[3] == 251U) {
112 return true;
113 }
114
115 return false;
116 }
117
118 if (family == AF_INET6) {
119 if (net_ipv6_is_addr_mcast(&net_sin6(addr)->sin6_addr) &&
120 net_sin6(addr)->sin6_addr.s6_addr[15] == 0xfb) {
121 return true;
122 }
123
124 return false;
125 }
126
127 return false;
128 }
129
server_is_llmnr(sa_family_t family,struct sockaddr * addr)130 static bool server_is_llmnr(sa_family_t family, struct sockaddr *addr)
131 {
132 if (family == AF_INET) {
133 if (net_ipv4_is_addr_mcast(&net_sin(addr)->sin_addr) &&
134 net_sin(addr)->sin_addr.s4_addr[3] == 252U) {
135 return true;
136 }
137
138 return false;
139 }
140
141 if (family == AF_INET6) {
142 if (net_ipv6_is_addr_mcast(&net_sin6(addr)->sin6_addr) &&
143 net_sin6(addr)->sin6_addr.s6_addr[15] == 0x03) {
144 return true;
145 }
146
147 return false;
148 }
149
150 return false;
151 }
152
join_ipv4_mcast_group(struct net_if * iface,void * user_data)153 static void join_ipv4_mcast_group(struct net_if *iface, void *user_data)
154 {
155 struct sockaddr *addr = user_data;
156 int ret;
157
158 ret = net_ipv4_igmp_join(iface, &net_sin(addr)->sin_addr, NULL);
159 if (ret < 0 && ret != -EALREADY) {
160 NET_DBG("Cannot join %s mDNS group (%d)", "IPv4", ret);
161 } else {
162 NET_DBG("Joined %s mDNS group %s", "IPv4",
163 net_sprint_ipv4_addr(&net_sin(addr)->sin_addr));
164 }
165 }
166
join_ipv6_mcast_group(struct net_if * iface,void * user_data)167 static void join_ipv6_mcast_group(struct net_if *iface, void *user_data)
168 {
169 struct sockaddr *addr = user_data;
170 int ret;
171
172 ret = net_ipv6_mld_join(iface, &net_sin6(addr)->sin6_addr);
173 if (ret < 0 && ret != -EALREADY) {
174 NET_DBG("Cannot join %s mDNS group (%d)", "IPv6", ret);
175 } else {
176 NET_DBG("Joined %s mDNS group %s", "IPv6",
177 net_sprint_ipv6_addr(&net_sin6(addr)->sin6_addr));
178 }
179 }
180
dns_postprocess_server(struct dns_resolve_context * ctx,int idx)181 static void dns_postprocess_server(struct dns_resolve_context *ctx, int idx)
182 {
183 struct sockaddr *addr = &ctx->servers[idx].dns_server;
184
185 if (addr->sa_family == AF_INET) {
186 ctx->servers[idx].is_mdns = server_is_mdns(AF_INET, addr);
187 if (!ctx->servers[idx].is_mdns) {
188 ctx->servers[idx].is_llmnr =
189 server_is_llmnr(AF_INET, addr);
190 }
191
192 if (net_sin(addr)->sin_port == 0U) {
193 if (IS_ENABLED(CONFIG_MDNS_RESOLVER) &&
194 ctx->servers[idx].is_mdns) {
195 /* We only use 5353 as a default port
196 * if mDNS support is enabled. User can
197 * override this by defining the port
198 * in config file.
199 */
200 net_sin(addr)->sin_port = htons(5353);
201 } else if (IS_ENABLED(CONFIG_LLMNR_RESOLVER) &&
202 ctx->servers[idx].is_llmnr) {
203 /* We only use 5355 as a default port
204 * if LLMNR support is enabled. User can
205 * override this by defining the port
206 * in config file.
207 */
208 net_sin(addr)->sin_port = htons(5355);
209 } else {
210 net_sin(addr)->sin_port = htons(53);
211 }
212 }
213
214 /* Join the mDNS multicast group if responder is not enabled,
215 * because it will join the group itself.
216 */
217 if (!IS_ENABLED(CONFIG_MDNS_RESPONDER) && ctx->servers[idx].is_mdns) {
218 struct in_addr mcast_addr = { { { 224, 0, 0, 251 } } };
219
220 if (net_sin(addr)->sin_addr.s_addr == mcast_addr.s_addr) {
221 struct net_if *iface;
222
223 iface = net_if_get_by_index(ctx->servers[idx].if_index);
224 if (iface == NULL) {
225 /* Join all interfaces */
226 net_if_foreach(join_ipv4_mcast_group, addr);
227 } else {
228 /* Join specific interface */
229 join_ipv4_mcast_group(iface, addr);
230 }
231 }
232 }
233 } else {
234 ctx->servers[idx].is_mdns = server_is_mdns(AF_INET6, addr);
235 if (!ctx->servers[idx].is_mdns) {
236 ctx->servers[idx].is_llmnr =
237 server_is_llmnr(AF_INET6, addr);
238 }
239
240 if (net_sin6(addr)->sin6_port == 0U) {
241 if (IS_ENABLED(CONFIG_MDNS_RESOLVER) &&
242 ctx->servers[idx].is_mdns) {
243 net_sin6(addr)->sin6_port = htons(5353);
244 } else if (IS_ENABLED(CONFIG_LLMNR_RESOLVER) &&
245 ctx->servers[idx].is_llmnr) {
246 net_sin6(addr)->sin6_port = htons(5355);
247 } else {
248 net_sin6(addr)->sin6_port = htons(53);
249 }
250 }
251
252 if (!IS_ENABLED(CONFIG_MDNS_RESPONDER) && ctx->servers[idx].is_mdns) {
253 struct in6_addr mcast_addr = { { { 0xff, 0x02, 0, 0, 0, 0, 0, 0,
254 0, 0, 0, 0, 0, 0, 0, 0xfb } } };
255
256 if (memcmp(&net_sin6(addr)->sin6_addr, &mcast_addr,
257 sizeof(struct in6_addr)) == 0) {
258 struct net_if *iface;
259
260 iface = net_if_get_by_index(ctx->servers[idx].if_index);
261 if (iface == NULL) {
262 /* Join all interfaces */
263 net_if_foreach(join_ipv6_mcast_group, addr);
264 } else {
265 /* Join specific interface */
266 join_ipv6_mcast_group(iface, addr);
267 }
268 }
269 }
270 }
271 }
272
dispatcher_cb(struct dns_socket_dispatcher * my_ctx,int sock,struct sockaddr * addr,size_t addrlen,struct net_buf * dns_data,size_t len)273 static int dispatcher_cb(struct dns_socket_dispatcher *my_ctx, int sock,
274 struct sockaddr *addr, size_t addrlen,
275 struct net_buf *dns_data, size_t len)
276 {
277 struct dns_resolve_context *ctx = my_ctx->resolve_ctx;
278 struct net_buf *dns_cname = NULL;
279 uint16_t query_hash = 0U;
280 uint16_t dns_id = 0U;
281 int ret = 0, i;
282
283 k_mutex_lock(&ctx->lock, K_FOREVER);
284
285 if (ctx->state != DNS_RESOLVE_CONTEXT_ACTIVE) {
286 goto unlock;
287 }
288
289 dns_cname = net_buf_alloc(&dns_qname_pool, ctx->buf_timeout);
290 if (!dns_cname) {
291 ret = DNS_EAI_MEMORY;
292 goto free_buf;
293 }
294
295 ret = dns_read(ctx, dns_data, len, &dns_id, dns_cname, &query_hash);
296 if (!ret) {
297 /* We called the callback already in dns_read() if there
298 * were no errors.
299 */
300 goto free_buf;
301 }
302
303 /* Query again if we got CNAME */
304 if (ret == DNS_EAI_AGAIN) {
305 int failure = 0;
306 int j;
307
308 i = get_slot_by_id(ctx, dns_id, query_hash);
309 if (i < 0) {
310 goto free_buf;
311 }
312
313 for (j = 0; j < SERVER_COUNT; j++) {
314 if (ctx->servers[j].sock < 0) {
315 continue;
316 }
317
318 ret = dns_write(ctx, j, i, dns_data->data, len,
319 net_buf_max_len(dns_data),
320 dns_cname, 0);
321 if (ret < 0) {
322 failure++;
323 }
324 }
325
326 if (failure) {
327 NET_DBG("DNS cname query failed %d times", failure);
328
329 if (failure == j) {
330 ret = DNS_EAI_SYSTEM;
331 goto quit;
332 }
333 }
334
335 goto free_buf;
336 }
337
338 quit:
339 i = get_slot_by_id(ctx, dns_id, query_hash);
340 if (i < 0) {
341 goto free_buf;
342 }
343
344 invoke_query_callback(ret, NULL, &ctx->queries[i]);
345
346 /* Marks the end of the results */
347 release_query(&ctx->queries[i]);
348
349 free_buf:
350 if (dns_cname) {
351 net_buf_unref(dns_cname);
352 }
353
354 unlock:
355 k_mutex_unlock(&ctx->lock);
356
357 return ret;
358 }
359
register_dispatcher(struct dns_resolve_context * ctx,const struct net_socket_service_desc * svc,struct dns_server * server,struct sockaddr * local,const struct in6_addr * addr6,const struct in_addr * addr4)360 static int register_dispatcher(struct dns_resolve_context *ctx,
361 const struct net_socket_service_desc *svc,
362 struct dns_server *server,
363 struct sockaddr *local,
364 const struct in6_addr *addr6,
365 const struct in_addr *addr4)
366 {
367 server->dispatcher.type = DNS_SOCKET_RESOLVER;
368 server->dispatcher.cb = dispatcher_cb;
369 server->dispatcher.fds = ctx->fds;
370 server->dispatcher.fds_len = ARRAY_SIZE(ctx->fds);
371 server->dispatcher.sock = server->sock;
372 server->dispatcher.svc = svc;
373 server->dispatcher.resolve_ctx = ctx;
374
375 if (IS_ENABLED(CONFIG_NET_IPV6) &&
376 server->dns_server.sa_family == AF_INET6) {
377 memcpy(&server->dispatcher.local_addr,
378 local,
379 sizeof(struct sockaddr_in6));
380 } else if (IS_ENABLED(CONFIG_NET_IPV4) &&
381 server->dns_server.sa_family == AF_INET) {
382 memcpy(&server->dispatcher.local_addr,
383 local,
384 sizeof(struct sockaddr_in));
385 } else {
386 return -ENOTSUP;
387 }
388
389 return dns_dispatcher_register(&server->dispatcher);
390 }
391
bind_to_iface(int sock,const struct sockaddr * addr,int if_index)392 static int bind_to_iface(int sock, const struct sockaddr *addr, int if_index)
393 {
394 struct ifreq ifreq = { 0 };
395 int ret;
396
397 ret = net_if_get_name(net_if_get_by_index(if_index), ifreq.ifr_name,
398 sizeof(ifreq.ifr_name));
399 if (ret < 0) {
400 LOG_DBG("Cannot get interface name for %d (%d)", if_index, ret);
401 return ret;
402 }
403
404 ret = zsock_setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE,
405 &ifreq, sizeof(ifreq));
406 if (ret < 0) {
407 ret = -errno;
408
409 NET_DBG("Cannot bind %s to %d (%d)",
410 net_sprint_addr(addr->sa_family, &net_sin(addr)->sin_addr),
411 if_index, ret);
412 }
413
414 return ret;
415 }
416
417 /* Must be invoked with context lock held */
dns_resolve_init_locked(struct dns_resolve_context * ctx,const char * servers[],const struct sockaddr * servers_sa[],const struct net_socket_service_desc * svc,uint16_t port,int interfaces[])418 static int dns_resolve_init_locked(struct dns_resolve_context *ctx,
419 const char *servers[],
420 const struct sockaddr *servers_sa[],
421 const struct net_socket_service_desc *svc,
422 uint16_t port, int interfaces[])
423 {
424 #if defined(CONFIG_NET_IPV6)
425 struct sockaddr_in6 local_addr6 = {
426 .sin6_family = AF_INET6,
427 .sin6_port = htons(port),
428 };
429 #endif
430 #if defined(CONFIG_NET_IPV4)
431 struct sockaddr_in local_addr4 = {
432 .sin_family = AF_INET,
433 .sin_port = htons(port),
434 };
435 #endif
436 struct sockaddr *local_addr = NULL;
437 socklen_t addr_len = 0;
438 int i = 0, idx = 0;
439 const struct in6_addr *addr6 = NULL;
440 const struct in_addr *addr4 = NULL;
441 struct net_if *iface;
442 int ret, count;
443
444 if (!ctx) {
445 return -ENOENT;
446 }
447
448 if (ctx->state != DNS_RESOLVE_CONTEXT_INACTIVE) {
449 ret = -ENOTEMPTY;
450 goto fail;
451 }
452
453 ARRAY_FOR_EACH(ctx->servers, j) {
454 ctx->servers[j].sock = -1;
455 }
456
457 ARRAY_FOR_EACH(ctx->fds, j) {
458 ctx->fds[j].fd = -1;
459 }
460
461 /* If user has provided a list of servers in string format, then
462 * figure out the network interface from that list. If user used
463 * list of sockaddr servers, then use the interfaces parameter.
464 * The interfaces parameter should point to an array that is the
465 * the same length as the servers_sa parameter array.
466 */
467 if (servers) {
468 for (i = 0; idx < SERVER_COUNT && servers[i]; i++) {
469 const char *iface_str;
470 size_t server_len;
471
472 struct sockaddr *addr = &ctx->servers[idx].dns_server;
473
474 iface_str = strstr(servers[i], "%");
475 if (iface_str) {
476 server_len = iface_str - servers[i];
477 iface_str++;
478
479 if (server_len == 0) {
480 NET_DBG("Empty server name");
481 continue;
482 }
483
484 /* Skip empty interface name */
485 if (iface_str[0] == '\0') {
486 ctx->servers[idx].if_index = 0;
487 iface_str = NULL;
488 } else {
489 ctx->servers[idx].if_index =
490 net_if_get_by_name(iface_str);
491 }
492
493 } else {
494 server_len = strlen(servers[i]);
495 ctx->servers[idx].if_index = 0;
496 }
497
498 (void)memset(addr, 0, sizeof(*addr));
499
500 ret = net_ipaddr_parse(servers[i], server_len, addr);
501 if (!ret) {
502 if (servers[i] != NULL && servers[i][0] != '\0') {
503 NET_DBG("Invalid server address %.*s",
504 (int)server_len, servers[i]);
505 }
506
507 continue;
508 }
509
510 dns_postprocess_server(ctx, idx);
511
512 NET_DBG("[%d] %.*s%s%s%s%s", i, (int)server_len, servers[i],
513 IS_ENABLED(CONFIG_MDNS_RESOLVER) ?
514 (ctx->servers[i].is_mdns ? " mDNS" : "") : "",
515 IS_ENABLED(CONFIG_LLMNR_RESOLVER) ?
516 (ctx->servers[i].is_llmnr ? " LLMNR" : "") : "",
517 iface_str != NULL ? " via " : "",
518 iface_str != NULL ? iface_str : "");
519 idx++;
520 }
521 }
522
523 if (servers_sa) {
524 for (i = 0; idx < SERVER_COUNT && servers_sa[i]; i++) {
525 memcpy(&ctx->servers[idx].dns_server, servers_sa[i],
526 sizeof(ctx->servers[idx].dns_server));
527
528 if (interfaces != NULL) {
529 ctx->servers[idx].if_index = interfaces[idx];
530 }
531
532 dns_postprocess_server(ctx, idx);
533 idx++;
534 }
535 }
536
537 for (i = 0, count = 0;
538 i < SERVER_COUNT && ctx->servers[i].dns_server.sa_family; i++) {
539
540 if (ctx->servers[i].dns_server.sa_family == AF_INET6) {
541 #if defined(CONFIG_NET_IPV6)
542 local_addr = (struct sockaddr *)&local_addr6;
543 addr_len = sizeof(struct sockaddr_in6);
544
545 if (IS_ENABLED(CONFIG_MDNS_RESOLVER) &&
546 ctx->servers[i].is_mdns && port == 0) {
547 local_addr6.sin6_port = htons(5353);
548 }
549 #else
550 continue;
551 #endif
552 }
553
554 if (ctx->servers[i].dns_server.sa_family == AF_INET) {
555 #if defined(CONFIG_NET_IPV4)
556 local_addr = (struct sockaddr *)&local_addr4;
557 addr_len = sizeof(struct sockaddr_in);
558
559 if (IS_ENABLED(CONFIG_MDNS_RESOLVER) &&
560 ctx->servers[i].is_mdns && port == 0) {
561 local_addr4.sin_port = htons(5353);
562 }
563 #else
564 continue;
565 #endif
566 }
567
568 if (!local_addr) {
569 NET_DBG("Local address not set");
570 ret = -EAFNOSUPPORT;
571 goto fail;
572 }
573
574 ret = zsock_socket(ctx->servers[i].dns_server.sa_family,
575 SOCK_DGRAM, IPPROTO_UDP);
576 if (ret < 0) {
577 ret = -errno;
578 NET_ERR("Cannot get socket (%d)", ret);
579 goto fail;
580 }
581
582 ctx->servers[i].sock = ret;
583
584 /* Try to bind to the interface if it is set */
585 if (ctx->servers[i].if_index > 0) {
586 ret = bind_to_iface(ctx->servers[i].sock,
587 &ctx->servers[i].dns_server,
588 ctx->servers[i].if_index);
589 if (ret < 0) {
590 zsock_close(ctx->servers[i].sock);
591 ctx->servers[i].sock = -1;
592 continue;
593 }
594
595 iface = net_if_get_by_index(ctx->servers[i].if_index);
596 NET_DBG("Binding %s to %d",
597 net_sprint_addr(ctx->servers[i].dns_server.sa_family,
598 &net_sin(&ctx->servers[i].dns_server)->sin_addr),
599 ctx->servers[i].if_index);
600 } else {
601 iface = NULL;
602 }
603
604 if (ctx->servers[i].dns_server.sa_family == AF_INET6) {
605 if (iface == NULL) {
606 iface = net_if_ipv6_select_src_iface(
607 &net_sin6(&ctx->servers[i].dns_server)->sin6_addr);
608 }
609
610 addr6 = net_if_ipv6_select_src_addr(iface,
611 &net_sin6(&ctx->servers[i].dns_server)->sin6_addr);
612 } else {
613 if (iface == NULL) {
614 iface = net_if_ipv4_select_src_iface(
615 &net_sin(&ctx->servers[i].dns_server)->sin_addr);
616 }
617
618 addr4 = net_if_ipv4_select_src_addr(iface,
619 &net_sin(&ctx->servers[i].dns_server)->sin_addr);
620 }
621
622 ARRAY_FOR_EACH(ctx->fds, j) {
623 if (ctx->fds[j].fd == ctx->servers[i].sock) {
624 /* There was query to this server already */
625 ret = 0;
626 break;
627 }
628
629 if (ctx->fds[j].fd < 0) {
630 ctx->fds[j].fd = ctx->servers[i].sock;
631 ctx->fds[j].events = ZSOCK_POLLIN;
632 ret = 0;
633 break;
634 }
635 }
636
637 if (ret < 0) {
638 NET_DBG("Cannot set %s to socket (%d)", "polling", ret);
639 zsock_close(ctx->servers[i].sock);
640 continue;
641 }
642
643 ret = register_dispatcher(ctx, svc, &ctx->servers[i], local_addr,
644 addr6, addr4);
645 if (ret < 0) {
646 if (ret == -EALREADY) {
647 goto skip_event;
648 }
649
650 NET_DBG("Cannot register dispatcher for %s (%d)",
651 ctx->servers[i].is_mdns ? "mDNS" : "DNS", ret);
652 goto fail;
653 }
654
655 if (IS_ENABLED(CONFIG_NET_MGMT_EVENT_INFO)) {
656 net_mgmt_event_notify_with_info(
657 NET_EVENT_DNS_SERVER_ADD,
658 iface, (void *)&ctx->servers[i].dns_server,
659 sizeof(struct sockaddr));
660 } else {
661 net_mgmt_event_notify(NET_EVENT_DNS_SERVER_ADD, iface);
662 }
663
664 skip_event:
665
666 #if defined(CONFIG_NET_IPV6)
667 local_addr6.sin6_port = htons(port);
668 #endif
669
670 #if defined(CONFIG_NET_IPV4)
671 local_addr4.sin_port = htons(port);
672 #endif
673
674 count++;
675 }
676
677 if (count == 0) {
678 /* No servers defined */
679 NET_DBG("No DNS servers defined.");
680 ret = -EINVAL;
681 goto fail;
682 }
683
684 init_called++;
685 ctx->state = DNS_RESOLVE_CONTEXT_ACTIVE;
686 ctx->buf_timeout = DNS_BUF_TIMEOUT;
687 ret = 0;
688
689 fail:
690 return ret;
691 }
692
dns_resolve_init_with_svc(struct dns_resolve_context * ctx,const char * servers[],const struct sockaddr * servers_sa[],const struct net_socket_service_desc * svc,uint16_t port,int interfaces[])693 int dns_resolve_init_with_svc(struct dns_resolve_context *ctx, const char *servers[],
694 const struct sockaddr *servers_sa[],
695 const struct net_socket_service_desc *svc,
696 uint16_t port, int interfaces[])
697 {
698 if (!ctx) {
699 return -ENOENT;
700 }
701
702 (void)memset(ctx, 0, sizeof(*ctx));
703
704 (void)k_mutex_init(&ctx->lock);
705 ctx->state = DNS_RESOLVE_CONTEXT_INACTIVE;
706
707 /* As this function is called only once during system init, there is no
708 * reason to acquire lock.
709 */
710 return dns_resolve_init_locked(ctx, servers, servers_sa, svc, port,
711 interfaces);
712 }
713
dns_resolve_init(struct dns_resolve_context * ctx,const char * servers[],const struct sockaddr * servers_sa[])714 int dns_resolve_init(struct dns_resolve_context *ctx, const char *servers[],
715 const struct sockaddr *servers_sa[])
716 {
717 return dns_resolve_init_with_svc(ctx, servers, servers_sa,
718 &resolve_svc, 0, NULL);
719 }
720
721 /* Check whether a slot is available for use, or optionally whether it can be
722 * reclaimed.
723 *
724 * @param pending_query the query slot in question
725 *
726 * @param reclaim_if_available if the slot is marked in use, but the query has
727 * been completed and the work item is no longer pending, complete the release
728 * of the slot.
729 *
730 * @return true if and only if the slot can be used for a new query.
731 */
check_query_active(struct dns_pending_query * pending_query,bool reclaim_if_available)732 static inline bool check_query_active(struct dns_pending_query *pending_query,
733 bool reclaim_if_available)
734 {
735 int ret = false;
736
737 if (pending_query->cb != NULL) {
738 ret = true;
739 if (reclaim_if_available
740 && pending_query->query == NULL
741 && k_work_delayable_busy_get(&pending_query->timer) == 0) {
742 pending_query->cb = NULL;
743 ret = false;
744 }
745 }
746
747 return ret;
748 }
749
750 /* Must be invoked with context lock held */
get_cb_slot(struct dns_resolve_context * ctx)751 static inline int get_cb_slot(struct dns_resolve_context *ctx)
752 {
753 int i;
754
755 for (i = 0; i < CONFIG_DNS_NUM_CONCUR_QUERIES; i++) {
756 if (!check_query_active(&ctx->queries[i], true)) {
757 return i;
758 }
759 }
760
761 return -ENOENT;
762 }
763
764 /* Invoke the callback associated with a query slot, if still relevant.
765 *
766 * Must be invoked with context lock held.
767 *
768 * @param status the query status value
769 * @param info the query result structure
770 * @param pending_query the query slot that will provide the callback
771 **/
invoke_query_callback(int status,struct dns_addrinfo * info,struct dns_pending_query * pending_query)772 static inline void invoke_query_callback(int status,
773 struct dns_addrinfo *info,
774 struct dns_pending_query *pending_query)
775 {
776 /* Only notify if the slot is neither released nor in the process of
777 * being released.
778 */
779 if (pending_query->query != NULL && pending_query->cb != NULL) {
780 pending_query->cb(status, info, pending_query->user_data);
781 }
782 }
783
784 /* Release a query slot reserved by get_cb_slot().
785 *
786 * Must be invoked with context lock held.
787 *
788 * @param pending_query the query slot to be released
789 */
release_query(struct dns_pending_query * pending_query)790 static void release_query(struct dns_pending_query *pending_query)
791 {
792 int busy = k_work_cancel_delayable(&pending_query->timer);
793
794 /* If the work item is no longer pending we're done. */
795 if (busy == 0) {
796 /* All done. */
797 pending_query->cb = NULL;
798 } else {
799 /* Work item is still pending. Set a secondary condition that
800 * can be checked by get_cb_slot() to complete release of the
801 * slot once the work item has been confirmed to be completed.
802 */
803 pending_query->query = NULL;
804 }
805 }
806
807 /* Must be invoked with context lock held */
get_slot_by_id(struct dns_resolve_context * ctx,uint16_t dns_id,uint16_t query_hash)808 static inline int get_slot_by_id(struct dns_resolve_context *ctx,
809 uint16_t dns_id,
810 uint16_t query_hash)
811 {
812 int i;
813
814 for (i = 0; i < CONFIG_DNS_NUM_CONCUR_QUERIES; i++) {
815 if (check_query_active(&ctx->queries[i], false) &&
816 ctx->queries[i].id == dns_id &&
817 (query_hash == 0 ||
818 ctx->queries[i].query_hash == query_hash)) {
819 return i;
820 }
821 }
822
823 return -ENOENT;
824 }
825
826 /* Unit test needs to be able to call this function */
827 #if !defined(CONFIG_NET_TEST)
828 static
829 #endif
dns_validate_msg(struct dns_resolve_context * ctx,struct dns_msg_t * dns_msg,uint16_t * dns_id,int * query_idx,struct net_buf * dns_cname,uint16_t * query_hash)830 int dns_validate_msg(struct dns_resolve_context *ctx,
831 struct dns_msg_t *dns_msg,
832 uint16_t *dns_id,
833 int *query_idx,
834 struct net_buf *dns_cname,
835 uint16_t *query_hash)
836 {
837 struct dns_addrinfo info = { 0 };
838 uint32_t ttl; /* RR ttl, so far it is not passed to caller */
839 uint8_t *src, *addr;
840 char *query_name;
841 int address_size;
842 /* index that points to the current answer being analyzed */
843 int answer_ptr;
844 int items;
845 int server_idx;
846 int ret = 0;
847
848 /* Make sure that we can read DNS id, flags and rcode */
849 if (dns_msg->msg_size < (sizeof(*dns_id) + sizeof(uint16_t))) {
850 ret = DNS_EAI_FAIL;
851 goto quit;
852 }
853
854 /* The dns_unpack_response_header() has design flaw as it expects
855 * dns id to be given instead of returning the id to the caller.
856 * In our case we would like to get it returned instead so that we
857 * can match the DNS query that we sent. When dns_read() is called,
858 * we do not know what the DNS id is yet.
859 */
860 *dns_id = dns_unpack_header_id(dns_msg->msg);
861
862 if (dns_header_rcode(dns_msg->msg) == DNS_HEADER_REFUSED) {
863 ret = DNS_EAI_FAIL;
864 goto quit;
865 }
866
867 /* We might receive a query while we are waiting for a response, in that
868 * case we just ignore the query instead of making the resolving fail.
869 */
870 if (dns_header_qr(dns_msg->msg) == DNS_QUERY) {
871 ret = 0;
872 goto quit;
873 }
874
875 ret = dns_unpack_response_header(dns_msg, *dns_id);
876 if (ret < 0) {
877 errno = -ret;
878 ret = DNS_EAI_SYSTEM;
879 goto quit;
880 }
881
882 if (dns_header_qdcount(dns_msg->msg) != 1) {
883 /* For mDNS (when dns_id == 0) the query count is 0 */
884 if (*dns_id > 0) {
885 ret = DNS_EAI_FAIL;
886 goto quit;
887 }
888 }
889
890 ret = dns_unpack_response_query(dns_msg);
891 if (ret < 0) {
892 if (ret == -ENOMEM) {
893 errno = -ret;
894 ret = DNS_EAI_SYSTEM;
895 goto quit;
896 }
897
898 /* Check mDNS like above */
899 if (*dns_id > 0) {
900 ret = DNS_EAI_FAIL;
901 goto quit;
902 }
903 }
904
905 if (dns_header_qdcount(dns_msg->msg) < 1 && *dns_id == 0) {
906 /* mDNS responses to do not have the query part so the
907 * answer starts immediately after the header.
908 */
909 dns_msg->answer_offset = dns_msg->query_offset;
910 }
911
912 /* Because in mDNS the DNS id is set to 0 and must be ignored
913 * on reply, we need to figure out the answer in order to find
914 * the proper query. To simplify things, the normal DNS responses
915 * are handled the same way.
916 */
917
918 answer_ptr = DNS_QUERY_POS;
919 items = 0;
920 server_idx = 0;
921 enum dns_rr_type answer_type = DNS_RR_TYPE_INVALID;
922
923 while (server_idx < dns_header_ancount(dns_msg->msg)) {
924 ret = dns_unpack_answer(dns_msg, answer_ptr, &ttl,
925 &answer_type);
926 if (ret < 0) {
927 errno = -ret;
928 ret = DNS_EAI_SYSTEM;
929 goto quit;
930 }
931
932 switch (dns_msg->response_type) {
933 case DNS_RESPONSE_IP: {
934 int query_name_len;
935
936 if (*query_idx >= 0) {
937 goto query_known;
938 }
939
940 query_name = dns_msg->msg + dns_msg->query_offset;
941
942 query_name_len = strlen(query_name);
943
944 /* Convert the query name to small case so that our
945 * hash checker can find it.
946 */
947 for (size_t i = 0, n = query_name_len; i < n; i++) {
948 query_name[i] = tolower(query_name[i]);
949 }
950
951 /* Add \0 and query type (A or AAAA) to the hash */
952 *query_hash = crc16_ansi(query_name,
953 query_name_len + 1 + 2);
954
955 *query_idx = get_slot_by_id(ctx, *dns_id, *query_hash);
956 if (*query_idx < 0) {
957 /* Re-check if this was a mDNS probe query */
958 if (IS_ENABLED(CONFIG_MDNS_RESPONDER_PROBE) && *dns_id == 0) {
959 uint16_t orig_qtype;
960
961 orig_qtype = sys_get_be16(&query_name[query_name_len + 1]);
962
963 /* Replace the query type with ANY as that was used
964 * when creating the hash.
965 */
966 sys_put_be16(DNS_RR_TYPE_ANY,
967 &query_name[query_name_len + 1]);
968
969 *query_hash = crc16_ansi(query_name,
970 query_name_len + 1 + 2);
971
972 sys_put_be16(orig_qtype, &query_name[query_name_len + 1]);
973
974 *query_idx = get_slot_by_id(ctx, *dns_id, *query_hash);
975 if (*query_idx < 0) {
976 errno = ENOENT;
977 ret = DNS_EAI_SYSTEM;
978 goto quit;
979 }
980 } else {
981 errno = ENOENT;
982 ret = DNS_EAI_SYSTEM;
983 goto quit;
984 }
985 }
986
987 query_known:
988 if (ctx->queries[*query_idx].query_type ==
989 DNS_QUERY_TYPE_A) {
990 if (answer_type != DNS_RR_TYPE_A) {
991 ret = DNS_EAI_ADDRFAMILY;
992 goto quit;
993 }
994
995 rr_qtype_a:
996 address_size = DNS_IPV4_LEN;
997 addr = (uint8_t *)&net_sin(&info.ai_addr)->
998 sin_addr;
999 info.ai_family = AF_INET;
1000 info.ai_addr.sa_family = AF_INET;
1001 info.ai_addrlen = sizeof(struct sockaddr_in);
1002
1003 } else if (ctx->queries[*query_idx].query_type ==
1004 DNS_QUERY_TYPE_AAAA) {
1005 if (answer_type != DNS_RR_TYPE_AAAA) {
1006 ret = DNS_EAI_ADDRFAMILY;
1007 goto quit;
1008 }
1009
1010 rr_qtype_aaaa:
1011 /* We cannot resolve IPv6 address if IPv6 is
1012 * disabled. The reason being that
1013 * "struct sockaddr" does not have enough space
1014 * for IPv6 address in that case.
1015 */
1016 #if defined(CONFIG_NET_IPV6)
1017 address_size = DNS_IPV6_LEN;
1018 addr = (uint8_t *)&net_sin6(&info.ai_addr)->
1019 sin6_addr;
1020 info.ai_family = AF_INET6;
1021 info.ai_addr.sa_family = AF_INET6;
1022 info.ai_addrlen = sizeof(struct sockaddr_in6);
1023 #else
1024 ret = DNS_EAI_FAMILY;
1025 goto quit;
1026 #endif
1027 } else if (ctx->queries[*query_idx].query_type ==
1028 (enum dns_query_type)DNS_RR_TYPE_ANY) {
1029 /* If we did ANY query, we need to check what
1030 * type of answer we got. Currently only A or AAAA
1031 * are supported.
1032 */
1033 if (answer_type == DNS_RR_TYPE_A) {
1034 goto rr_qtype_a;
1035 } else if (answer_type == DNS_RR_TYPE_AAAA) {
1036 goto rr_qtype_aaaa;
1037 } else {
1038 ret = DNS_EAI_ADDRFAMILY;
1039 goto quit;
1040 }
1041 } else {
1042 ret = DNS_EAI_FAMILY;
1043 goto quit;
1044 }
1045
1046 if (dns_msg->response_length < address_size) {
1047 /* it seems this is a malformed message */
1048 errno = EMSGSIZE;
1049 ret = DNS_EAI_SYSTEM;
1050 goto quit;
1051 }
1052
1053 if ((dns_msg->response_position + address_size) >
1054 dns_msg->msg_size) {
1055 /* Too short message */
1056 errno = EMSGSIZE;
1057 ret = DNS_EAI_SYSTEM;
1058 goto quit;
1059 }
1060
1061 src = dns_msg->msg + dns_msg->response_position;
1062 memcpy(addr, src, address_size);
1063
1064 invoke_query_callback(DNS_EAI_INPROGRESS, &info,
1065 &ctx->queries[*query_idx]);
1066 #ifdef CONFIG_DNS_RESOLVER_CACHE
1067 dns_cache_add(&dns_cache,
1068 ctx->queries[*query_idx].query, &info, ttl);
1069 #endif /* CONFIG_DNS_RESOLVER_CACHE */
1070 items++;
1071 break;
1072 }
1073 case DNS_RESPONSE_CNAME_NO_IP:
1074 /* Instead of using the QNAME at DNS_QUERY_POS,
1075 * we will use this CNAME
1076 */
1077 answer_ptr = dns_msg->response_position;
1078 break;
1079
1080 default:
1081 ret = DNS_EAI_FAIL;
1082 goto quit;
1083 }
1084
1085 /* Update the answer offset to point to the next RR (answer) */
1086 dns_msg->answer_offset += dns_msg->response_position -
1087 dns_msg->answer_offset;
1088 dns_msg->answer_offset += dns_msg->response_length;
1089
1090 server_idx++;
1091 }
1092
1093 if (*query_idx < 0) {
1094 /* If the query_idx is still unknown, try to get it here
1095 * and hope it is found.
1096 */
1097 query_name = dns_msg->msg + dns_msg->query_offset;
1098 *query_hash = crc16_ansi(query_name,
1099 strlen(query_name) + 1 + 2);
1100
1101 *query_idx = get_slot_by_id(ctx, *dns_id, *query_hash);
1102 if (*query_idx < 0) {
1103 errno = ENOENT;
1104 ret = DNS_EAI_SYSTEM;
1105 goto quit;
1106 }
1107 }
1108
1109 /* No IP addresses were found, so we take the last CNAME to generate
1110 * another query. Number of additional queries is controlled via Kconfig
1111 */
1112 if (items == 0) {
1113 if (dns_msg->response_type == DNS_RESPONSE_CNAME_NO_IP) {
1114 uint16_t pos = dns_msg->response_position;
1115
1116 /* The dns_cname should always be set. As a special
1117 * case, it might not be set for unit tests that call
1118 * this function directly.
1119 */
1120 if (dns_cname) {
1121 ret = dns_copy_qname(dns_cname->data,
1122 &dns_cname->len,
1123 net_buf_max_len(dns_cname),
1124 dns_msg, pos);
1125 if (ret < 0) {
1126 errno = -ret;
1127 ret = DNS_EAI_SYSTEM;
1128 goto quit;
1129 }
1130 }
1131
1132 ret = DNS_EAI_AGAIN;
1133 goto quit;
1134 }
1135 }
1136
1137 if (items == 0) {
1138 ret = DNS_EAI_NODATA;
1139 } else {
1140 ret = DNS_EAI_ALLDONE;
1141 }
1142
1143 quit:
1144 return ret;
1145 }
1146
1147 /* Must be invoked with context lock held */
dns_read(struct dns_resolve_context * ctx,struct net_buf * dns_data,size_t buf_len,uint16_t * dns_id,struct net_buf * dns_cname,uint16_t * query_hash)1148 static int dns_read(struct dns_resolve_context *ctx,
1149 struct net_buf *dns_data, size_t buf_len,
1150 uint16_t *dns_id,
1151 struct net_buf *dns_cname,
1152 uint16_t *query_hash)
1153 {
1154 /* Helper struct to track the dns msg received from the server */
1155 struct dns_msg_t dns_msg;
1156 int data_len;
1157 int ret;
1158 int query_idx = -1;
1159
1160 data_len = MIN(buf_len, DNS_RESOLVER_MAX_BUF_SIZE);
1161
1162 dns_msg.msg = dns_data->data;
1163 dns_msg.msg_size = data_len;
1164
1165 ret = dns_validate_msg(ctx, &dns_msg, dns_id, &query_idx,
1166 dns_cname, query_hash);
1167 if (ret == DNS_EAI_AGAIN) {
1168 goto finished;
1169 }
1170
1171 if ((ret < 0 && ret != DNS_EAI_ALLDONE) || query_idx < 0 ||
1172 query_idx > CONFIG_DNS_NUM_CONCUR_QUERIES) {
1173 goto quit;
1174 }
1175
1176 invoke_query_callback(ret, NULL, &ctx->queries[query_idx]);
1177
1178 /* Marks the end of the results */
1179 release_query(&ctx->queries[query_idx]);
1180
1181 return 0;
1182
1183 finished:
1184 dns_resolve_cancel_with_name(ctx, *dns_id,
1185 ctx->queries[query_idx].query,
1186 ctx->queries[query_idx].query_type);
1187 quit:
1188 return ret;
1189 }
1190
set_ttl_hop_limit(int sock,int level,int option,int new_limit)1191 static int set_ttl_hop_limit(int sock, int level, int option, int new_limit)
1192 {
1193 return zsock_setsockopt(sock, level, option, &new_limit, sizeof(new_limit));
1194 }
1195
1196 /* Must be invoked with context lock held */
dns_write(struct dns_resolve_context * ctx,int server_idx,int query_idx,uint8_t * buf,size_t buf_len,size_t max_len,struct net_buf * dns_qname,int hop_limit)1197 static int dns_write(struct dns_resolve_context *ctx,
1198 int server_idx,
1199 int query_idx,
1200 uint8_t *buf, size_t buf_len, size_t max_len,
1201 struct net_buf *dns_qname,
1202 int hop_limit)
1203 {
1204 enum dns_query_type query_type;
1205 struct sockaddr *server;
1206 int server_addr_len;
1207 uint16_t dns_id, len;
1208 int ret, sock, family;
1209 char *query_name;
1210
1211 sock = ctx->servers[server_idx].sock;
1212 family = ctx->servers[server_idx].dns_server.sa_family;
1213 server = &ctx->servers[server_idx].dns_server;
1214 dns_id = ctx->queries[query_idx].id;
1215 query_type = ctx->queries[query_idx].query_type;
1216
1217 len = buf_len;
1218
1219 ret = dns_msg_pack_query(buf, &len, (uint16_t)max_len,
1220 dns_qname->data, dns_qname->len, dns_id,
1221 (enum dns_rr_type)query_type);
1222 if (ret < 0) {
1223 return -EINVAL;
1224 }
1225
1226 query_name = buf + DNS_MSG_HEADER_SIZE;
1227
1228 /* Convert the query name to small case so that our
1229 * hash checker can find it later when we get the answer.
1230 */
1231 for (int i = 0; i < dns_qname->len; i++) {
1232 query_name[i] = tolower(query_name[i]);
1233 }
1234
1235 /* Add \0 and query type (A or AAAA) to the hash. Note that
1236 * the dns_qname->len contains the length of \0
1237 */
1238 ctx->queries[query_idx].query_hash =
1239 crc16_ansi(query_name, dns_qname->len + 2);
1240
1241 if (hop_limit > 0) {
1242 if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) {
1243 ret = set_ttl_hop_limit(sock, IPPROTO_IPV6,
1244 IPV6_UNICAST_HOPS,
1245 hop_limit);
1246 } else if (IS_ENABLED(CONFIG_NET_IPV4) && family == AF_INET) {
1247 ret = set_ttl_hop_limit(sock, IPPROTO_IP, IP_TTL,
1248 hop_limit);
1249 } else {
1250 ret = -ENOTSUP;
1251 }
1252
1253 if (ret < 0) {
1254 NET_DBG("Cannot set %s to socket (%d)",
1255 family == AF_INET6 ? "hop limit" :
1256 (family == AF_INET ? "TTL" : "<unknown>"),
1257 ret);
1258 return ret;
1259 }
1260 }
1261
1262 ret = -ENOENT;
1263
1264 ARRAY_FOR_EACH(ctx->fds, i) {
1265 if (ctx->fds[i].fd == sock) {
1266 /* There was query to this server already */
1267 ret = 0;
1268 break;
1269 }
1270
1271 if (ctx->fds[i].fd < 0) {
1272 ctx->fds[i].fd = sock;
1273 ctx->fds[i].events = ZSOCK_POLLIN;
1274 ret = 0;
1275 break;
1276 }
1277 }
1278
1279 if (ret < 0) {
1280 NET_DBG("Cannot set %s to socket (%d)", "polling", ret);
1281 return ret;
1282 }
1283
1284 if (family == AF_INET) {
1285 server_addr_len = sizeof(struct sockaddr_in);
1286 } else {
1287 server_addr_len = sizeof(struct sockaddr_in6);
1288 }
1289
1290 ret = k_work_reschedule(&ctx->queries[query_idx].timer,
1291 ctx->queries[query_idx].timeout);
1292 if (ret < 0) {
1293 NET_DBG("[%u] cannot submit work to server idx %d for id %u "
1294 "ret %d", query_idx, server_idx, dns_id, ret);
1295 return ret;
1296 }
1297
1298 NET_DBG("[%u] submitting work to server idx %d for id %u "
1299 "hash %u", query_idx, server_idx, dns_id,
1300 ctx->queries[query_idx].query_hash);
1301
1302 ret = zsock_sendto(sock, buf, len, 0, server, server_addr_len);
1303 if (ret < 0) {
1304 NET_DBG("Cannot send query (%d)", -errno);
1305 return ret;
1306 } else {
1307 if (IS_ENABLED(CONFIG_NET_STATISTICS_DNS)) {
1308 struct net_if *iface = NULL;
1309
1310 if (IS_ENABLED(CONFIG_NET_IPV6) && server->sa_family == AF_INET6) {
1311 iface = net_if_ipv6_select_src_iface(&net_sin6(server)->sin6_addr);
1312 } else if (IS_ENABLED(CONFIG_NET_IPV4) && server->sa_family == AF_INET) {
1313 iface = net_if_ipv4_select_src_iface(&net_sin(server)->sin_addr);
1314 }
1315
1316 if (iface != NULL) {
1317 net_stats_update_dns_sent(iface);
1318 }
1319 }
1320 }
1321
1322 return 0;
1323 }
1324
1325 /* Must be invoked with context lock held */
dns_resolve_cancel_slot(struct dns_resolve_context * ctx,int slot)1326 static void dns_resolve_cancel_slot(struct dns_resolve_context *ctx, int slot)
1327 {
1328 invoke_query_callback(DNS_EAI_CANCELED, NULL, &ctx->queries[slot]);
1329
1330 release_query(&ctx->queries[slot]);
1331 }
1332
1333 /* Must be invoked with context lock held */
dns_resolve_cancel_all(struct dns_resolve_context * ctx)1334 static void dns_resolve_cancel_all(struct dns_resolve_context *ctx)
1335 {
1336 int i;
1337
1338 for (i = 0; i < CONFIG_DNS_NUM_CONCUR_QUERIES; i++) {
1339 if (ctx->queries[i].cb && ctx->queries[i].query) {
1340 dns_resolve_cancel_slot(ctx, i);
1341 }
1342 }
1343 }
1344
dns_resolve_cancel_with_hash(struct dns_resolve_context * ctx,uint16_t dns_id,uint16_t query_hash,const char * query_name)1345 static int dns_resolve_cancel_with_hash(struct dns_resolve_context *ctx,
1346 uint16_t dns_id,
1347 uint16_t query_hash,
1348 const char *query_name)
1349 {
1350 int ret = 0;
1351 int i;
1352
1353 k_mutex_lock(&ctx->lock, K_FOREVER);
1354
1355 if (ctx->state == DNS_RESOLVE_CONTEXT_DEACTIVATING) {
1356 /*
1357 * Cancel is part of context "deactivating" process, so no need
1358 * to do anything more.
1359 */
1360 goto unlock;
1361 }
1362
1363 i = get_slot_by_id(ctx, dns_id, query_hash);
1364 if (i < 0) {
1365 ret = -ENOENT;
1366 goto unlock;
1367 }
1368
1369 NET_DBG("Cancelling DNS req %u (name %s type %d hash %u)", dns_id,
1370 query_name == NULL ? "<unknown>" : query_name,
1371 ctx->queries[i].query_type, query_hash);
1372
1373 dns_resolve_cancel_slot(ctx, i);
1374
1375 unlock:
1376 k_mutex_unlock(&ctx->lock);
1377
1378 return ret;
1379 }
1380
dns_resolve_cancel_with_name(struct dns_resolve_context * ctx,uint16_t dns_id,const char * query_name,enum dns_query_type query_type)1381 int dns_resolve_cancel_with_name(struct dns_resolve_context *ctx,
1382 uint16_t dns_id,
1383 const char *query_name,
1384 enum dns_query_type query_type)
1385 {
1386 uint16_t query_hash = 0;
1387
1388 if (query_name) {
1389 struct net_buf *buf;
1390 uint16_t len;
1391 int ret;
1392
1393 /* Use net_buf as a temporary buffer to store the packed
1394 * DNS name.
1395 */
1396 buf = net_buf_alloc(&dns_msg_pool, ctx->buf_timeout);
1397 if (!buf) {
1398 return -ENOMEM;
1399 }
1400
1401 ret = dns_msg_pack_qname(&len, buf->data,
1402 net_buf_max_len(buf),
1403 query_name);
1404 if (ret >= 0) {
1405 /* If the query string + \0 + query type (A or AAAA)
1406 * does not fit the tmp buf, then bail out
1407 */
1408 if ((len + 2) > net_buf_max_len(buf)) {
1409 net_buf_unref(buf);
1410 return -ENOMEM;
1411 }
1412
1413 net_buf_add(buf, len);
1414 net_buf_add_be16(buf, query_type);
1415
1416 query_hash = crc16_ansi(buf->data, len + 2);
1417 }
1418
1419 net_buf_unref(buf);
1420
1421 if (ret < 0) {
1422 return ret;
1423 }
1424 }
1425
1426 return dns_resolve_cancel_with_hash(ctx, dns_id, query_hash,
1427 query_name);
1428 }
1429
dns_resolve_cancel(struct dns_resolve_context * ctx,uint16_t dns_id)1430 int dns_resolve_cancel(struct dns_resolve_context *ctx, uint16_t dns_id)
1431 {
1432 return dns_resolve_cancel_with_name(ctx, dns_id, NULL, 0);
1433 }
1434
query_timeout(struct k_work * work)1435 static void query_timeout(struct k_work *work)
1436 {
1437 struct k_work_delayable *dwork = k_work_delayable_from_work(work);
1438 struct dns_pending_query *pending_query =
1439 CONTAINER_OF(dwork, struct dns_pending_query, timer);
1440 int ret;
1441
1442 /* We have to take the lock as we're inspecting protected content
1443 * associated with the query. But don't block the system work queue:
1444 * if the lock can't be taken immediately, reschedule the work item to
1445 * be run again after everything else has had a chance.
1446 *
1447 * Note that it's OK to use the k_work API on the delayable work
1448 * without holding the lock: it's only the associated state in the
1449 * containing structure that must be protected.
1450 */
1451 ret = k_mutex_lock(&pending_query->ctx->lock, K_NO_WAIT);
1452 if (ret != 0) {
1453 struct k_work_delayable *dwork2 = k_work_delayable_from_work(work);
1454
1455 /*
1456 * Reschedule query timeout handler with some delay, so that all
1457 * threads (including those with lower priorities) have a chance
1458 * to move forward and release DNS context lock.
1459 *
1460 * Timeout value was arbitrarily chosen and can be updated in
1461 * future if needed.
1462 */
1463 k_work_reschedule(dwork2, K_MSEC(10));
1464 return;
1465 }
1466
1467 NET_DBG("Query timeout DNS req %u type %d hash %u", pending_query->id,
1468 pending_query->query_type, pending_query->query_hash);
1469
1470 /* The resolve cancel will invoke release_query(), but release will
1471 * not be completed because the work item is still pending. Instead
1472 * the release will be completed when check_query_active() confirms
1473 * the work item is no longer active.
1474 */
1475 (void)dns_resolve_cancel_with_hash(pending_query->ctx,
1476 pending_query->id,
1477 pending_query->query_hash,
1478 pending_query->query);
1479
1480 k_mutex_unlock(&pending_query->ctx->lock);
1481 }
1482
dns_resolve_name_internal(struct dns_resolve_context * ctx,const char * query,enum dns_query_type type,uint16_t * dns_id,dns_resolve_cb_t cb,void * user_data,int32_t timeout,bool use_cache)1483 int dns_resolve_name_internal(struct dns_resolve_context *ctx,
1484 const char *query,
1485 enum dns_query_type type,
1486 uint16_t *dns_id,
1487 dns_resolve_cb_t cb,
1488 void *user_data,
1489 int32_t timeout,
1490 bool use_cache)
1491 {
1492 k_timeout_t tout;
1493 struct net_buf *dns_data = NULL;
1494 struct net_buf *dns_qname = NULL;
1495 struct sockaddr addr;
1496 int ret, i = -1, j = 0;
1497 int failure = 0;
1498 bool mdns_query = false;
1499 uint8_t hop_limit;
1500 #ifdef CONFIG_DNS_RESOLVER_CACHE
1501 struct dns_addrinfo cached_info[CONFIG_DNS_RESOLVER_AI_MAX_ENTRIES] = {0};
1502 #endif /* CONFIG_DNS_RESOLVER_CACHE */
1503
1504 if (!ctx || !query || !cb) {
1505 return -EINVAL;
1506 }
1507
1508 tout = SYS_TIMEOUT_MS(timeout);
1509
1510 /* Timeout cannot be 0 as we cannot resolve name that fast.
1511 */
1512 if (K_TIMEOUT_EQ(tout, K_NO_WAIT)) {
1513 return -EINVAL;
1514 }
1515
1516 ret = net_ipaddr_parse(query, strlen(query), &addr);
1517 if (ret) {
1518 /* The query name was already in numeric form, no
1519 * need to continue further.
1520 */
1521 struct dns_addrinfo info = { 0 };
1522
1523 if (type == DNS_QUERY_TYPE_A) {
1524 if (net_sin(&addr)->sin_family == AF_INET6) {
1525 return -EPFNOSUPPORT;
1526 }
1527
1528 memcpy(net_sin(&info.ai_addr), net_sin(&addr),
1529 sizeof(struct sockaddr_in));
1530 info.ai_family = AF_INET;
1531 info.ai_addr.sa_family = AF_INET;
1532 info.ai_addrlen = sizeof(struct sockaddr_in);
1533 } else if (type == DNS_QUERY_TYPE_AAAA) {
1534 /* We do not support AI_V4MAPPED atm, so if the user
1535 * asks an IPv6 address but it is an IPv4 one, then
1536 * return an error. Note that getaddrinfo() will swap
1537 * the error to EINVAL, the EPFNOSUPPORT is returned
1538 * here so that we can find it easily.
1539 */
1540 if (net_sin(&addr)->sin_family == AF_INET) {
1541 return -EPFNOSUPPORT;
1542 }
1543
1544 #if defined(CONFIG_NET_IPV6)
1545 memcpy(net_sin6(&info.ai_addr), net_sin6(&addr),
1546 sizeof(struct sockaddr_in6));
1547 info.ai_family = AF_INET6;
1548 info.ai_addr.sa_family = AF_INET6;
1549 info.ai_addrlen = sizeof(struct sockaddr_in6);
1550 #else
1551 return -EAFNOSUPPORT;
1552 #endif
1553 } else {
1554 goto try_resolve;
1555 }
1556
1557 cb(DNS_EAI_INPROGRESS, &info, user_data);
1558 cb(DNS_EAI_ALLDONE, NULL, user_data);
1559
1560 return 0;
1561 }
1562
1563 try_resolve:
1564 #ifdef CONFIG_DNS_RESOLVER_CACHE
1565 if (use_cache) {
1566 ret = dns_cache_find(&dns_cache, query, type, cached_info,
1567 ARRAY_SIZE(cached_info));
1568 if (ret > 0) {
1569 /* The query was cached, no
1570 * need to continue further.
1571 */
1572 for (size_t cache_index = 0; cache_index < ret; cache_index++) {
1573 cb(DNS_EAI_INPROGRESS, &cached_info[cache_index], user_data);
1574 }
1575
1576 cb(DNS_EAI_ALLDONE, NULL, user_data);
1577
1578 return 0;
1579 }
1580 }
1581 #else
1582 ARG_UNUSED(use_cache);
1583 #endif /* CONFIG_DNS_RESOLVER_CACHE */
1584
1585 k_mutex_lock(&ctx->lock, K_FOREVER);
1586
1587 if (ctx->state != DNS_RESOLVE_CONTEXT_ACTIVE) {
1588 ret = -EINVAL;
1589 goto fail;
1590 }
1591
1592 i = get_cb_slot(ctx);
1593 if (i < 0) {
1594 ret = -EAGAIN;
1595 goto fail;
1596 }
1597
1598 ctx->queries[i].cb = cb;
1599 ctx->queries[i].timeout = tout;
1600 ctx->queries[i].query = query;
1601 ctx->queries[i].query_type = type;
1602 ctx->queries[i].user_data = user_data;
1603 ctx->queries[i].ctx = ctx;
1604 ctx->queries[i].query_hash = 0;
1605
1606 k_work_init_delayable(&ctx->queries[i].timer, query_timeout);
1607
1608 dns_data = net_buf_alloc(&dns_msg_pool, ctx->buf_timeout);
1609 if (!dns_data) {
1610 ret = -ENOMEM;
1611 goto quit;
1612 }
1613
1614 dns_qname = net_buf_alloc(&dns_qname_pool, ctx->buf_timeout);
1615 if (!dns_qname) {
1616 ret = -ENOMEM;
1617 goto quit;
1618 }
1619
1620 ret = dns_msg_pack_qname(&dns_qname->len, dns_qname->data,
1621 CONFIG_DNS_RESOLVER_MAX_QUERY_LEN, ctx->queries[i].query);
1622 if (ret < 0) {
1623 goto quit;
1624 }
1625
1626 ctx->queries[i].id = sys_rand16_get();
1627
1628 /* If mDNS is enabled, then send .local queries only to multicast
1629 * address. For mDNS the id should be set to 0, see RFC 6762 ch. 18.1
1630 * for details.
1631 */
1632 if (IS_ENABLED(CONFIG_MDNS_RESOLVER)) {
1633 const char *ptr = strrchr(query, '.');
1634
1635 /* Note that we memcmp() the \0 here too */
1636 if (ptr && !memcmp(ptr, (const void *){ ".local" }, 7)) {
1637 mdns_query = true;
1638
1639 ctx->queries[i].id = 0;
1640 }
1641 }
1642
1643 /* Do this immediately after calculating the Id so that the unit
1644 * test will work properly.
1645 */
1646 if (dns_id) {
1647 *dns_id = ctx->queries[i].id;
1648
1649 NET_DBG("DNS id will be %u", *dns_id);
1650 }
1651
1652 for (j = 0; j < SERVER_COUNT; j++) {
1653 hop_limit = 0U;
1654
1655 if (ctx->servers[j].sock < 0) {
1656 continue;
1657 }
1658
1659 /* If mDNS is enabled, then send .local queries only to
1660 * a well known multicast mDNS server address.
1661 */
1662 if (IS_ENABLED(CONFIG_MDNS_RESOLVER) && mdns_query &&
1663 !ctx->servers[j].is_mdns) {
1664 continue;
1665 }
1666
1667 /* If llmnr is enabled, then all the queries are sent to
1668 * LLMNR multicast address unless it is a mDNS query.
1669 */
1670 if (!mdns_query && IS_ENABLED(CONFIG_LLMNR_RESOLVER)) {
1671 if (!ctx->servers[j].is_llmnr) {
1672 continue;
1673 }
1674
1675 hop_limit = 1U;
1676 }
1677
1678 ret = dns_write(ctx, j, i, dns_data->data,
1679 net_buf_max_len(dns_data),
1680 net_buf_max_len(dns_data),
1681 dns_qname, hop_limit);
1682 if (ret < 0) {
1683 failure++;
1684 continue;
1685 }
1686
1687 /* Do one concurrent query only for each name resolve.
1688 * TODO: Change the i (query index) to do multiple concurrent
1689 * to each server.
1690 */
1691 break;
1692 }
1693
1694 if (failure) {
1695 NET_DBG("DNS query failed %d times", failure);
1696
1697 if (failure == j) {
1698 ret = -ENOENT;
1699 goto quit;
1700 }
1701 }
1702
1703 ret = 0;
1704
1705 quit:
1706 if (ret < 0) {
1707 if (i >= 0) {
1708 release_query(&ctx->queries[i]);
1709 }
1710
1711 if (dns_id) {
1712 *dns_id = 0U;
1713 }
1714 }
1715
1716 if (dns_data) {
1717 net_buf_unref(dns_data);
1718 }
1719
1720 if (dns_qname) {
1721 net_buf_unref(dns_qname);
1722 }
1723
1724 fail:
1725 k_mutex_unlock(&ctx->lock);
1726
1727 return ret;
1728 }
1729
dns_resolve_name(struct dns_resolve_context * ctx,const char * query,enum dns_query_type type,uint16_t * dns_id,dns_resolve_cb_t cb,void * user_data,int32_t timeout)1730 int dns_resolve_name(struct dns_resolve_context *ctx,
1731 const char *query,
1732 enum dns_query_type type,
1733 uint16_t *dns_id,
1734 dns_resolve_cb_t cb,
1735 void *user_data,
1736 int32_t timeout)
1737 {
1738 return dns_resolve_name_internal(ctx, query, type, dns_id, cb,
1739 user_data, timeout, true);
1740 }
1741
1742 /* Must be invoked with context lock held */
dns_resolve_close_locked(struct dns_resolve_context * ctx)1743 static int dns_resolve_close_locked(struct dns_resolve_context *ctx)
1744 {
1745 int i;
1746
1747 if (ctx->state != DNS_RESOLVE_CONTEXT_ACTIVE) {
1748 return -ENOENT;
1749 }
1750
1751 ctx->state = DNS_RESOLVE_CONTEXT_DEACTIVATING;
1752
1753 /* ctx->net_ctx is never used in "deactivating" state. Additionally
1754 * following code is guaranteed to be executed only by one thread at a
1755 * time, due to required "active" -> "deactivating" state change. This
1756 * means that it is safe to put net_ctx with mutex released.
1757 *
1758 * Released mutex will prevent lower networking layers from deadlock
1759 * when calling cb_recv() (which acquires ctx->lock) just before closing
1760 * network context.
1761 */
1762 k_mutex_unlock(&ctx->lock);
1763
1764 for (i = 0; i < SERVER_COUNT; i++) {
1765 struct net_if *iface;
1766
1767 if (ctx->servers[i].sock < 0) {
1768 continue;
1769 }
1770
1771 (void)dns_dispatcher_unregister(&ctx->servers[i].dispatcher);
1772
1773 if (ctx->servers[i].dns_server.sa_family == AF_INET6) {
1774 iface = net_if_ipv6_select_src_iface(
1775 &net_sin6(&ctx->servers[i].dns_server)->sin6_addr);
1776 } else {
1777 iface = net_if_ipv4_select_src_iface(
1778 &net_sin(&ctx->servers[i].dns_server)->sin_addr);
1779 }
1780
1781 if (IS_ENABLED(CONFIG_NET_MGMT_EVENT_INFO)) {
1782 net_mgmt_event_notify_with_info(
1783 NET_EVENT_DNS_SERVER_DEL,
1784 iface,
1785 (void *)&ctx->servers[i].dns_server,
1786 sizeof(struct sockaddr));
1787 } else {
1788 net_mgmt_event_notify(NET_EVENT_DNS_SERVER_DEL,
1789 iface);
1790 }
1791
1792 zsock_close(ctx->servers[i].sock);
1793
1794 ARRAY_FOR_EACH(ctx->fds, j) {
1795 if (ctx->fds[j].fd == ctx->servers[i].sock) {
1796 ctx->fds[j].fd = -1;
1797 }
1798 }
1799
1800 (void)dns_dispatcher_unregister(&ctx->servers[i].dispatcher);
1801
1802 ctx->servers[i].sock = -1;
1803 }
1804
1805 if (--init_called <= 0) {
1806 init_called = 0;
1807 }
1808
1809 k_mutex_lock(&ctx->lock, K_FOREVER);
1810
1811 ctx->state = DNS_RESOLVE_CONTEXT_INACTIVE;
1812
1813 return 0;
1814 }
1815
dns_resolve_close(struct dns_resolve_context * ctx)1816 int dns_resolve_close(struct dns_resolve_context *ctx)
1817 {
1818 int ret;
1819
1820 k_mutex_lock(&ctx->lock, K_FOREVER);
1821 ret = dns_resolve_close_locked(ctx);
1822 k_mutex_unlock(&ctx->lock);
1823
1824 return ret;
1825 }
1826
dns_server_exists(struct dns_resolve_context * ctx,const struct sockaddr * addr)1827 static bool dns_server_exists(struct dns_resolve_context *ctx,
1828 const struct sockaddr *addr)
1829 {
1830 for (int i = 0; i < SERVER_COUNT; i++) {
1831 if (IS_ENABLED(CONFIG_NET_IPV4) && (addr->sa_family == AF_INET) &&
1832 (ctx->servers[i].dns_server.sa_family == AF_INET)) {
1833 if (net_ipv4_addr_cmp(&net_sin(addr)->sin_addr,
1834 &net_sin(&ctx->servers[i].dns_server)->sin_addr)) {
1835 return true;
1836 }
1837 }
1838
1839 if (IS_ENABLED(CONFIG_NET_IPV6) && (addr->sa_family == AF_INET6) &&
1840 (ctx->servers[i].dns_server.sa_family == AF_INET6)) {
1841 if (net_ipv6_addr_cmp(&net_sin6(addr)->sin6_addr,
1842 &net_sin6(&ctx->servers[i].dns_server)->sin6_addr)) {
1843 return true;
1844 }
1845 }
1846 }
1847
1848 return false;
1849 }
1850
dns_servers_exists(struct dns_resolve_context * ctx,const char * servers[],const struct sockaddr * servers_sa[])1851 static bool dns_servers_exists(struct dns_resolve_context *ctx,
1852 const char *servers[],
1853 const struct sockaddr *servers_sa[])
1854 {
1855 if (servers) {
1856 for (int i = 0; i < SERVER_COUNT && servers[i]; i++) {
1857 struct sockaddr addr;
1858
1859 if (!net_ipaddr_parse(servers[i], strlen(servers[i]), &addr)) {
1860 continue;
1861 }
1862
1863 if (!dns_server_exists(ctx, &addr)) {
1864 return false;
1865 }
1866 }
1867 }
1868
1869 if (servers_sa) {
1870 for (int i = 0; i < SERVER_COUNT && servers_sa[i]; i++) {
1871 if (!dns_server_exists(ctx, servers_sa[i])) {
1872 return false;
1873 }
1874 }
1875 }
1876
1877 return true;
1878 }
1879
dns_resolve_reconfigure(struct dns_resolve_context * ctx,const char * servers[],const struct sockaddr * servers_sa[])1880 int dns_resolve_reconfigure(struct dns_resolve_context *ctx,
1881 const char *servers[],
1882 const struct sockaddr *servers_sa[])
1883 {
1884 int err;
1885
1886 if (!ctx) {
1887 return -ENOENT;
1888 }
1889
1890 k_mutex_lock(&ctx->lock, K_FOREVER);
1891
1892 if (dns_servers_exists(ctx, servers, servers_sa)) {
1893 /* DNS servers did not change. */
1894 err = 0;
1895 goto unlock;
1896 }
1897
1898 if (ctx->state == DNS_RESOLVE_CONTEXT_DEACTIVATING) {
1899 err = -EBUSY;
1900 goto unlock;
1901 }
1902
1903 if (ctx->state == DNS_RESOLVE_CONTEXT_ACTIVE) {
1904 dns_resolve_cancel_all(ctx);
1905
1906 err = dns_resolve_close_locked(ctx);
1907 if (err) {
1908 goto unlock;
1909 }
1910 }
1911
1912 err = dns_resolve_init_locked(ctx, servers, servers_sa, &resolve_svc, 0, NULL);
1913
1914 unlock:
1915 k_mutex_unlock(&ctx->lock);
1916
1917 return err;
1918 }
1919
dns_resolve_get_default(void)1920 struct dns_resolve_context *dns_resolve_get_default(void)
1921 {
1922 return &dns_default_ctx;
1923 }
1924
dns_resolve_init_default(struct dns_resolve_context * ctx)1925 int dns_resolve_init_default(struct dns_resolve_context *ctx)
1926 {
1927 int ret = 0;
1928 #if defined(CONFIG_DNS_SERVER_IP_ADDRESSES)
1929 static const char *dns_servers[SERVER_COUNT + 1];
1930 int count = DNS_SERVER_COUNT;
1931
1932 if (count > 5) {
1933 count = 5;
1934 }
1935
1936 switch (count) {
1937 #if DNS_SERVER_COUNT > 4
1938 case 5:
1939 dns_servers[4] = CONFIG_DNS_SERVER5;
1940 __fallthrough;
1941 #endif
1942 #if DNS_SERVER_COUNT > 3
1943 case 4:
1944 dns_servers[3] = CONFIG_DNS_SERVER4;
1945 __fallthrough;
1946 #endif
1947 #if DNS_SERVER_COUNT > 2
1948 case 3:
1949 dns_servers[2] = CONFIG_DNS_SERVER3;
1950 __fallthrough;
1951 #endif
1952 #if DNS_SERVER_COUNT > 1
1953 case 2:
1954 dns_servers[1] = CONFIG_DNS_SERVER2;
1955 __fallthrough;
1956 #endif
1957 #if DNS_SERVER_COUNT > 0
1958 case 1:
1959 dns_servers[0] = CONFIG_DNS_SERVER1;
1960 __fallthrough;
1961 #endif
1962 case 0:
1963 break;
1964 }
1965
1966 #if defined(CONFIG_MDNS_RESOLVER) && (MDNS_SERVER_COUNT > 0)
1967 #if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_IPV4)
1968 dns_servers[DNS_SERVER_COUNT + 1] = MDNS_IPV6_ADDR;
1969 dns_servers[DNS_SERVER_COUNT] = MDNS_IPV4_ADDR;
1970 #else /* CONFIG_NET_IPV6 && CONFIG_NET_IPV4 */
1971 #if defined(CONFIG_NET_IPV6)
1972 dns_servers[DNS_SERVER_COUNT] = MDNS_IPV6_ADDR;
1973 #endif
1974 #if defined(CONFIG_NET_IPV4)
1975 dns_servers[DNS_SERVER_COUNT] = MDNS_IPV4_ADDR;
1976 #endif
1977 #endif /* CONFIG_NET_IPV6 && CONFIG_NET_IPV4 */
1978 #endif /* MDNS_RESOLVER && MDNS_SERVER_COUNT > 0 */
1979
1980 #if defined(CONFIG_LLMNR_RESOLVER) && (LLMNR_SERVER_COUNT > 0)
1981 #if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_IPV4)
1982 dns_servers[DNS_SERVER_COUNT + MDNS_SERVER_COUNT + 1] =
1983 LLMNR_IPV6_ADDR;
1984 dns_servers[DNS_SERVER_COUNT + MDNS_SERVER_COUNT] = LLMNR_IPV4_ADDR;
1985 #else /* CONFIG_NET_IPV6 && CONFIG_NET_IPV4 */
1986 #if defined(CONFIG_NET_IPV6)
1987 dns_servers[DNS_SERVER_COUNT + MDNS_SERVER_COUNT] = LLMNR_IPV6_ADDR;
1988 #endif
1989 #if defined(CONFIG_NET_IPV4)
1990 dns_servers[DNS_SERVER_COUNT + MDNS_SERVER_COUNT] = LLMNR_IPV4_ADDR;
1991 #endif
1992 #endif /* CONFIG_NET_IPV6 && CONFIG_NET_IPV4 */
1993 #endif /* LLMNR_RESOLVER && LLMNR_SERVER_COUNT > 0 */
1994
1995 dns_servers[SERVER_COUNT] = NULL;
1996
1997 ret = dns_resolve_init(ctx, dns_servers, NULL);
1998 if (ret < 0) {
1999 NET_WARN("Cannot initialize DNS resolver (%d)", ret);
2000 }
2001 #else
2002 /* We must always call init even if there are no servers configured so
2003 * that DNS mutex gets initialized properly.
2004 */
2005 (void)dns_resolve_init(dns_resolve_get_default(), NULL, NULL);
2006 #endif
2007 return ret;
2008 }
2009
2010 #ifdef CONFIG_DNS_RESOLVER_AUTO_INIT
dns_init_resolver(void)2011 void dns_init_resolver(void)
2012 {
2013 dns_resolve_init_default(dns_resolve_get_default());
2014 }
2015 #endif /* CONFIG_DNS_RESOLVER_AUTO_INIT */
2016