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