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