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