1 /** @file
2  * @brief mDNS responder
3  *
4  * This listens to mDNS queries and responds to them.
5  */
6 
7 /*
8  * Copyright (c) 2017 Intel Corporation
9  * Copyright (c) 2020 Friedt Professional Engineering Services, Inc
10  * Copyright (c) 2024 Nordic Semiconductor ASA
11  *
12  * SPDX-License-Identifier: Apache-2.0
13  */
14 
15 #include <zephyr/logging/log.h>
16 LOG_MODULE_REGISTER(net_mdns_responder, CONFIG_MDNS_RESPONDER_LOG_LEVEL);
17 
18 #include <zephyr/kernel.h>
19 #include <zephyr/init.h>
20 #include <string.h>
21 #include <strings.h>
22 #include <errno.h>
23 #include <stdlib.h>
24 
25 #include <zephyr/net/mld.h>
26 #include <zephyr/net/net_core.h>
27 #include <zephyr/net/net_ip.h>
28 #include <zephyr/net/net_pkt.h>
29 #include <zephyr/net/dns_resolve.h>
30 #include <zephyr/net/socket_service.h>
31 #include <zephyr/net/igmp.h>
32 
33 #include "dns_sd.h"
34 #include "dns_pack.h"
35 #include "ipv6.h"
36 #include "../../ip/net_stats.h"
37 
38 #include "net_private.h"
39 
40 /*
41  * GCC complains about struct sockaddr accesses due to the various
42  * address-family-specific variants being of differing sizes. Let's not
43  * mess with code (which looks correct), just silence the compiler.
44  */
45 #ifdef __GNUC__
46 #pragma GCC diagnostic ignored "-Wpragmas"
47 #pragma GCC diagnostic ignored "-Wunknown-warning-option"
48 #pragma GCC diagnostic ignored "-Warray-bounds"
49 #pragma GCC diagnostic ignored "-Wstringop-overread"
50 #endif
51 
52 extern void dns_dispatcher_svc_handler(struct net_socket_service_event *pev);
53 
54 #define MDNS_LISTEN_PORT 5353
55 
56 #define MDNS_TTL CONFIG_MDNS_RESPONDER_TTL /* In seconds */
57 
58 #if defined(CONFIG_NET_IPV4)
59 static struct mdns_responder_context v4_ctx[MAX_IPV4_IFACE_COUNT];
60 
61 NET_SOCKET_SERVICE_SYNC_DEFINE_STATIC(v4_svc, dns_dispatcher_svc_handler,
62 				      MDNS_MAX_IPV4_IFACE_COUNT);
63 #endif
64 
65 #if defined(CONFIG_NET_IPV6)
66 static struct mdns_responder_context v6_ctx[MAX_IPV6_IFACE_COUNT];
67 
68 NET_SOCKET_SERVICE_SYNC_DEFINE_STATIC(v6_svc, dns_dispatcher_svc_handler,
69 				      MDNS_MAX_IPV6_IFACE_COUNT);
70 #endif
71 
72 static struct net_mgmt_event_callback mgmt_cb;
73 static const struct dns_sd_rec *external_records;
74 static size_t external_records_count;
75 
76 #define BUF_ALLOC_TIMEOUT K_MSEC(100)
77 
78 #ifndef CONFIG_NET_TEST
79 static int setup_dst_addr(int sock, sa_family_t family,
80 			  struct sockaddr *dst, socklen_t *dst_len);
81 #endif /* CONFIG_NET_TEST */
82 
83 #define DNS_RESOLVER_MIN_BUF		2
84 #define DNS_RESOLVER_BUF_CTR	(DNS_RESOLVER_MIN_BUF + \
85 				 CONFIG_MDNS_RESOLVER_ADDITIONAL_BUF_CTR)
86 
87 NET_BUF_POOL_DEFINE(mdns_msg_pool, DNS_RESOLVER_BUF_CTR,
88 		    DNS_RESOLVER_MAX_BUF_SIZE, 0, NULL);
89 
create_ipv6_addr(struct sockaddr_in6 * addr)90 static void create_ipv6_addr(struct sockaddr_in6 *addr)
91 {
92 	addr->sin6_family = AF_INET6;
93 	addr->sin6_port = htons(MDNS_LISTEN_PORT);
94 
95 	/* Well known IPv6 ff02::fb address */
96 	net_ipv6_addr_create(&addr->sin6_addr,
97 			     0xff02, 0, 0, 0, 0, 0, 0, 0x00fb);
98 }
99 
create_ipv4_addr(struct sockaddr_in * addr)100 static void create_ipv4_addr(struct sockaddr_in *addr)
101 {
102 	addr->sin_family = AF_INET;
103 	addr->sin_port = htons(MDNS_LISTEN_PORT);
104 
105 	/* Well known IPv4 224.0.0.251 address */
106 	addr->sin_addr.s_addr = htonl(0xE00000FB);
107 }
108 
mdns_iface_event_handler(struct net_mgmt_event_callback * cb,uint32_t mgmt_event,struct net_if * iface)109 static void mdns_iface_event_handler(struct net_mgmt_event_callback *cb,
110 				     uint32_t mgmt_event, struct net_if *iface)
111 
112 {
113 	if (mgmt_event == NET_EVENT_IF_UP) {
114 #if defined(CONFIG_NET_IPV4)
115 		ARRAY_FOR_EACH(v4_ctx, i) {
116 			int ret = net_ipv4_igmp_join(iface,
117 					&net_sin(&v4_ctx[i].dispatcher.local_addr)->sin_addr,
118 					NULL);
119 			if (ret < 0) {
120 				NET_DBG("Cannot add IPv4 multicast address to iface %d",
121 					net_if_get_by_iface(iface));
122 			}
123 		}
124 #endif /* defined(CONFIG_NET_IPV4) */
125 	}
126 }
127 
set_ttl_hop_limit(int sock,int level,int option,int new_limit)128 static int set_ttl_hop_limit(int sock, int level, int option, int new_limit)
129 {
130 	return zsock_setsockopt(sock, level, option, &new_limit, sizeof(new_limit));
131 }
132 
setup_dst_addr(int sock,sa_family_t family,struct sockaddr * dst,socklen_t * dst_len)133 int setup_dst_addr(int sock, sa_family_t family,
134 		   struct sockaddr *dst, socklen_t *dst_len)
135 {
136 	int ret;
137 
138 	if (IS_ENABLED(CONFIG_NET_IPV4) && family == AF_INET) {
139 		create_ipv4_addr(net_sin(dst));
140 		*dst_len = sizeof(struct sockaddr_in);
141 
142 		ret = set_ttl_hop_limit(sock, IPPROTO_IP, IP_MULTICAST_TTL, 255);
143 		if (ret < 0) {
144 			NET_DBG("Cannot set %s multicast %s (%d)", "IPv4", "TTL", ret);
145 		}
146 	} else if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) {
147 		create_ipv6_addr(net_sin6(dst));
148 		*dst_len = sizeof(struct sockaddr_in6);
149 
150 		ret = set_ttl_hop_limit(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 255);
151 		if (ret < 0) {
152 			NET_DBG("Cannot set %s multicast %s (%d)", "IPv6", "hoplimit", ret);
153 		}
154 	} else {
155 		return -EPFNOSUPPORT;
156 	}
157 
158 	return 0;
159 }
160 
get_socket(sa_family_t family)161 static int get_socket(sa_family_t family)
162 {
163 	int ret;
164 
165 	ret = zsock_socket(family, SOCK_DGRAM, IPPROTO_UDP);
166 	if (ret < 0) {
167 		ret = -errno;
168 		NET_DBG("Cannot get socket (%d)", ret);
169 	}
170 
171 	return ret;
172 }
173 
setup_dns_hdr(uint8_t * buf,uint16_t answers)174 static void setup_dns_hdr(uint8_t *buf, uint16_t answers)
175 {
176 	uint16_t offset;
177 	uint16_t flags;
178 
179 	/* See RFC 1035, ch 4.1.1 for header details */
180 
181 	flags = BIT(15);  /* This is response */
182 	flags |= BIT(10); /* Authoritative Answer */
183 
184 	UNALIGNED_PUT(0, (uint16_t *)(buf)); /* Identifier, RFC 6762 ch 18.1 */
185 	offset = DNS_HEADER_ID_LEN;
186 
187 	UNALIGNED_PUT(htons(flags), (uint16_t *)(buf+offset));
188 	offset += DNS_HEADER_FLAGS_LEN;
189 
190 	UNALIGNED_PUT(0, (uint16_t *)(buf + offset));
191 	offset += DNS_QDCOUNT_LEN;
192 
193 	UNALIGNED_PUT(htons(answers), (uint16_t *)(buf + offset));
194 	offset += DNS_ANCOUNT_LEN;
195 
196 	UNALIGNED_PUT(0, (uint16_t *)(buf + offset));
197 	offset += DNS_NSCOUNT_LEN;
198 
199 	UNALIGNED_PUT(0, (uint16_t *)(buf + offset));
200 }
201 
add_answer(struct net_buf * query,enum dns_rr_type qtype,uint32_t ttl,uint16_t addr_len,uint8_t * addr)202 static void add_answer(struct net_buf *query, enum dns_rr_type qtype,
203 		       uint32_t ttl, uint16_t addr_len, uint8_t *addr)
204 {
205 	char *dot = query->data + DNS_MSG_HEADER_SIZE;
206 	char *prev = NULL;
207 	uint16_t offset;
208 
209 	while ((dot = strchr(dot, '.'))) {
210 		if (!prev) {
211 			prev = dot++;
212 			continue;
213 		}
214 
215 		*prev = dot - prev - 1;
216 		prev = dot++;
217 	}
218 
219 	if (prev) {
220 		*prev = strlen(prev) - 1;
221 	}
222 
223 	/* terminator byte (0x00) */
224 	query->len += 1;
225 
226 	offset = DNS_MSG_HEADER_SIZE + query->len;
227 	UNALIGNED_PUT(htons(qtype), (uint16_t *)(query->data+offset));
228 
229 	/* Bit 15 tells to flush the cache */
230 	offset += DNS_QTYPE_LEN;
231 	UNALIGNED_PUT(htons(DNS_CLASS_IN | BIT(15)),
232 		      (uint16_t *)(query->data+offset));
233 
234 
235 	offset += DNS_QCLASS_LEN;
236 	UNALIGNED_PUT(htonl(ttl), query->data + offset);
237 
238 	offset += DNS_TTL_LEN;
239 	UNALIGNED_PUT(htons(addr_len), query->data + offset);
240 
241 	offset += DNS_RDLENGTH_LEN;
242 	memcpy(query->data + offset, addr, addr_len);
243 }
244 
create_answer(int sock,struct net_buf * query,enum dns_rr_type qtype,uint16_t addr_len,uint8_t * addr)245 static int create_answer(int sock,
246 			 struct net_buf *query,
247 			 enum dns_rr_type qtype,
248 			 uint16_t addr_len, uint8_t *addr)
249 {
250 	/* Prepare the response into the query buffer: move the name
251 	 * query buffer has to get enough free space: dns_hdr + answer
252 	 */
253 	if ((net_buf_max_len(query) - query->len) < (DNS_MSG_HEADER_SIZE +
254 					  DNS_QTYPE_LEN + DNS_QCLASS_LEN +
255 					  DNS_TTL_LEN + DNS_RDLENGTH_LEN +
256 					  addr_len)) {
257 		return -ENOBUFS;
258 	}
259 
260 	memmove(query->data + DNS_MSG_HEADER_SIZE, query->data, query->len);
261 
262 	setup_dns_hdr(query->data, 1);
263 
264 	add_answer(query, qtype, MDNS_TTL, addr_len, addr);
265 
266 	query->len += DNS_MSG_HEADER_SIZE +
267 		DNS_QTYPE_LEN + DNS_QCLASS_LEN +
268 		DNS_TTL_LEN + DNS_RDLENGTH_LEN + addr_len;
269 
270 	return 0;
271 }
272 
send_response(int sock,sa_family_t family,struct sockaddr * src_addr,size_t addrlen,struct net_buf * query,enum dns_rr_type qtype)273 static int send_response(int sock,
274 			 sa_family_t family,
275 			 struct sockaddr *src_addr,
276 			 size_t addrlen,
277 			 struct net_buf *query,
278 			 enum dns_rr_type qtype)
279 {
280 	struct net_if *iface;
281 	socklen_t dst_len;
282 	int ret;
283 	COND_CODE_1(IS_ENABLED(CONFIG_NET_IPV6),
284 		    (struct sockaddr_in6), (struct sockaddr_in)) dst;
285 
286 	ret = setup_dst_addr(sock, family, (struct sockaddr *)&dst, &dst_len);
287 	if (ret < 0) {
288 		NET_DBG("unable to set up the response address");
289 		return ret;
290 	}
291 
292 	if (family == AF_INET6) {
293 		iface = net_if_ipv6_select_src_iface(&net_sin6(src_addr)->sin6_addr);
294 	} else {
295 		iface = net_if_ipv4_select_src_iface(&net_sin(src_addr)->sin_addr);
296 	}
297 
298 	if (IS_ENABLED(CONFIG_NET_IPV4) && qtype == DNS_RR_TYPE_A) {
299 		const struct in_addr *addr;
300 
301 		if (family == AF_INET) {
302 			addr = net_if_ipv4_select_src_addr(iface,
303 							   &net_sin(src_addr)->sin_addr);
304 		} else {
305 			struct sockaddr_in tmp_addr;
306 
307 			create_ipv4_addr(&tmp_addr);
308 			addr = net_if_ipv4_select_src_addr(iface, &tmp_addr.sin_addr);
309 		}
310 
311 		ret = create_answer(sock, query, qtype, sizeof(struct in_addr), (uint8_t *)addr);
312 		if (ret != 0) {
313 			return ret;
314 		}
315 	} else if (IS_ENABLED(CONFIG_NET_IPV6) && qtype == DNS_RR_TYPE_AAAA) {
316 		const struct in6_addr *addr;
317 
318 		if (family == AF_INET6) {
319 			addr = net_if_ipv6_select_src_addr(iface,
320 							   &net_sin6(src_addr)->sin6_addr);
321 		} else {
322 			struct sockaddr_in6 tmp_addr;
323 
324 			create_ipv6_addr(&tmp_addr);
325 			addr = net_if_ipv6_select_src_addr(iface, &tmp_addr.sin6_addr);
326 		}
327 
328 		ret = create_answer(sock, query, qtype, sizeof(struct in6_addr), (uint8_t *)addr);
329 		if (ret != 0) {
330 			return -ENOMEM;
331 		}
332 	} else {
333 		/* TODO: support also service PTRs */
334 		return -EINVAL;
335 	}
336 
337 	ret = zsock_sendto(sock, query->data, query->len, 0,
338 			   (struct sockaddr *)&dst, dst_len);
339 	if (ret < 0) {
340 		NET_DBG("Cannot send %s reply (%d)", "mDNS", ret);
341 	} else {
342 		net_stats_update_dns_sent(iface);
343 	}
344 
345 	return ret;
346 }
347 
send_sd_response(int sock,sa_family_t family,struct sockaddr * src_addr,size_t addrlen,struct dns_msg_t * dns_msg,struct net_buf * result)348 static void send_sd_response(int sock,
349 			     sa_family_t family,
350 			     struct sockaddr *src_addr,
351 			     size_t addrlen,
352 			     struct dns_msg_t *dns_msg,
353 			     struct net_buf *result)
354 {
355 	struct net_if *iface;
356 	socklen_t dst_len;
357 	int ret;
358 	const struct dns_sd_rec *record;
359 	/* filter must be zero-initialized for "wildcard" port */
360 	struct dns_sd_rec filter = {0};
361 	bool service_type_enum = false;
362 	const struct in6_addr *addr6 = NULL;
363 	const struct in_addr *addr4 = NULL;
364 	char instance_buf[DNS_SD_INSTANCE_MAX_SIZE + 1];
365 	char service_buf[DNS_SD_SERVICE_MAX_SIZE + 1];
366 	/* Depending on segment count in the query, third buffer could hold
367 	 * either protocol or domain, use larger size.
368 	 */
369 	char proto_buf[DNS_SD_DOMAIN_MAX_SIZE + 1];
370 	char domain_buf[DNS_SD_DOMAIN_MAX_SIZE + 1];
371 	char *label[4];
372 	size_t size[] = {
373 		ARRAY_SIZE(instance_buf),
374 		ARRAY_SIZE(service_buf),
375 		ARRAY_SIZE(proto_buf),
376 		ARRAY_SIZE(domain_buf),
377 	};
378 	size_t n = ARRAY_SIZE(label);
379 	size_t rec_num;
380 	size_t ext_rec_num = external_records_count;
381 	COND_CODE_1(IS_ENABLED(CONFIG_NET_IPV6),
382 		    (struct sockaddr_in6), (struct sockaddr_in)) dst;
383 
384 	BUILD_ASSERT(ARRAY_SIZE(label) == ARRAY_SIZE(size), "");
385 
386 	/*
387 	 * work around for bug in compliance scripts which say that the array
388 	 * should be static const (incorrect)
389 	 */
390 	label[0] = instance_buf;
391 	label[1] = service_buf;
392 	label[2] = proto_buf;
393 	label[3] = domain_buf;
394 
395 	ret = setup_dst_addr(sock, family, (struct sockaddr *)&dst, &dst_len);
396 	if (ret < 0) {
397 		NET_DBG("unable to set up the response address");
398 		return;
399 	}
400 
401 	if (family == AF_INET6) {
402 		iface = net_if_ipv6_select_src_iface(&net_sin6(src_addr)->sin6_addr);
403 	} else {
404 		iface = net_if_ipv4_select_src_iface(&net_sin(src_addr)->sin_addr);
405 	}
406 
407 	if (IS_ENABLED(CONFIG_NET_IPV4)) {
408 		/* Look up the local IPv4 address */
409 		if (family == AF_INET) {
410 			addr4 = net_if_ipv4_select_src_addr(iface,
411 							    &net_sin(src_addr)->sin_addr);
412 		} else {
413 			struct sockaddr_in tmp_addr;
414 
415 			create_ipv4_addr(&tmp_addr);
416 			addr4 = net_if_ipv4_select_src_addr(iface, &tmp_addr.sin_addr);
417 		}
418 	}
419 
420 	if (IS_ENABLED(CONFIG_NET_IPV6)) {
421 		/* Look up the local IPv6 address */
422 		if (family == AF_INET6) {
423 			addr6 = net_if_ipv6_select_src_addr(iface,
424 							    &net_sin6(src_addr)->sin6_addr);
425 		} else {
426 			struct sockaddr_in6 tmp_addr;
427 
428 			create_ipv6_addr(&tmp_addr);
429 			addr6 = net_if_ipv6_select_src_addr(iface, &tmp_addr.sin6_addr);
430 		}
431 	}
432 
433 	ret = dns_sd_query_extract(dns_msg->msg,
434 		dns_msg->msg_size, &filter, label, size, &n);
435 	if (ret < 0) {
436 		NET_DBG("unable to extract query (%d)", ret);
437 		return;
438 	}
439 
440 	if (IS_ENABLED(CONFIG_MDNS_RESPONDER_DNS_SD_SERVICE_TYPE_ENUMERATION)
441 		&& dns_sd_is_service_type_enumeration(&filter)) {
442 
443 		/*
444 		 * RFC 6763, Section 9
445 		 *
446 		 * A DNS query for PTR records with the name
447 		 * "_services._dns-sd._udp.<Domain>" yields a set of PTR records,
448 		 * where the rdata of each PTR record is the two-label <Service> name,
449 		 * plus the same domain, e.g., "_http._tcp.<Domain>".
450 		 */
451 		dns_sd_create_wildcard_filter(&filter);
452 		service_type_enum = true;
453 	}
454 
455 	DNS_SD_COUNT(&rec_num);
456 
457 	while (rec_num > 0 || ext_rec_num > 0) {
458 		/*
459 		 * The loop will always iterate over all entries, it can be done
460 		 * backwards for simplicity
461 		 */
462 		if (rec_num > 0) {
463 			DNS_SD_GET(rec_num - 1, &record);
464 			rec_num--;
465 		} else {
466 			record = &external_records[ext_rec_num - 1];
467 			ext_rec_num--;
468 		}
469 
470 		/* Checks validity and then compare */
471 		if (dns_sd_rec_match(record, &filter)) {
472 			NET_DBG("matched query: %s.%s.%s.%s port: %u",
473 				record->instance, record->service,
474 				record->proto, record->domain,
475 				ntohs(*(record->port)));
476 
477 			/* Construct the response */
478 			if (service_type_enum) {
479 				ret = dns_sd_handle_service_type_enum(record, addr4, addr6,
480 						result->data, net_buf_max_len(result));
481 				if (ret < 0) {
482 					NET_DBG("dns_sd_handle_service_type_enum() failed (%d)",
483 						ret);
484 					continue;
485 				}
486 			} else {
487 				ret = dns_sd_handle_ptr_query(record, addr4, addr6,
488 						result->data, net_buf_max_len(result));
489 				if (ret < 0) {
490 					NET_DBG("dns_sd_handle_ptr_query() failed (%d)", ret);
491 					continue;
492 				}
493 			}
494 
495 			result->len = ret;
496 
497 			/* Send the response */
498 			ret = zsock_sendto(sock, result->data, result->len, 0,
499 					   (struct sockaddr *)&dst, dst_len);
500 			if (ret < 0) {
501 				NET_DBG("Cannot send %s reply (%d)", "mDNS", ret);
502 				continue;
503 			} else {
504 				net_stats_update_dns_sent(iface);
505 			}
506 		}
507 	}
508 }
509 
dns_read(int sock,struct net_buf * dns_data,size_t len,struct sockaddr * src_addr,size_t addrlen)510 static int dns_read(int sock,
511 		    struct net_buf *dns_data,
512 		    size_t len,
513 		    struct sockaddr *src_addr,
514 		    size_t addrlen)
515 {
516 	/* Helper struct to track the dns msg received from the server */
517 	const char *hostname = net_hostname_get();
518 	int hostname_len = strlen(hostname);
519 	int family = src_addr->sa_family;
520 	struct net_buf *result;
521 	struct dns_msg_t dns_msg;
522 	int data_len;
523 	int queries;
524 	int ret;
525 
526 	data_len = MIN(len, DNS_RESOLVER_MAX_BUF_SIZE);
527 
528 	/* Store the DNS query name into a temporary net_buf, which will be
529 	 * eventually used to send a response
530 	 */
531 	result = net_buf_alloc(&mdns_msg_pool, BUF_ALLOC_TIMEOUT);
532 	if (!result) {
533 		ret = -ENOMEM;
534 		goto quit;
535 	}
536 
537 	dns_msg.msg = dns_data->data;
538 	dns_msg.msg_size = data_len;
539 
540 	ret = mdns_unpack_query_header(&dns_msg, NULL);
541 	if (ret < 0) {
542 		goto quit;
543 	}
544 
545 	queries = ret;
546 
547 	NET_DBG("Received %d %s from %s", queries,
548 		queries > 1 ? "queries" : "query",
549 		net_sprint_addr(family,
550 				family == AF_INET ?
551 				(const void *)&net_sin(src_addr)->sin_addr :
552 				(const void *)&net_sin6(src_addr)->sin6_addr));
553 
554 	do {
555 		enum dns_rr_type qtype;
556 		enum dns_class qclass;
557 		uint8_t *lquery;
558 
559 		(void)memset(result->data, 0, net_buf_tailroom(result));
560 		result->len = 0U;
561 
562 		ret = dns_unpack_query(&dns_msg, result, &qtype, &qclass);
563 		if (ret < 0) {
564 			goto quit;
565 		}
566 
567 		/* Handle only .local queries */
568 		lquery = strrchr(result->data + 1, '.');
569 		if (!lquery || memcmp(lquery, (const void *){ ".local" }, 7)) {
570 			continue;
571 		}
572 
573 		NET_DBG("[%d] query %s/%s label %s (%d bytes)", queries,
574 			dns_qtype_to_str(qtype), "IN",
575 			result->data, ret);
576 
577 		/* If the query matches to our hostname, then send reply.
578 		 * We skip the first dot, and make sure there is dot after
579 		 * matching hostname.
580 		 */
581 		if (!strncasecmp(hostname, result->data + 1, hostname_len) &&
582 		    (result->len - 1) >= hostname_len &&
583 		    &(result->data + 1)[hostname_len] == lquery) {
584 			NET_DBG("%s query to our hostname %s.local", "mDNS",
585 				hostname);
586 			send_response(sock, family, src_addr, addrlen,
587 				      result, qtype);
588 		} else if (IS_ENABLED(CONFIG_MDNS_RESPONDER_DNS_SD)
589 			&& qtype == DNS_RR_TYPE_PTR) {
590 			send_sd_response(sock, family, src_addr, addrlen,
591 					 &dns_msg, result);
592 		}
593 
594 	} while (--queries);
595 
596 	ret = 0;
597 
598 quit:
599 	if (result) {
600 		net_buf_unref(result);
601 	}
602 
603 	return ret;
604 }
605 
606 #if defined(CONFIG_NET_IPV6)
iface_ipv6_cb(struct net_if * iface,void * user_data)607 static void iface_ipv6_cb(struct net_if *iface, void *user_data)
608 {
609 	struct in6_addr *addr = user_data;
610 	int ret;
611 
612 	ret = net_ipv6_mld_join(iface, addr);
613 	if (ret < 0) {
614 		NET_DBG("Cannot join %s IPv6 multicast group (%d)",
615 			net_sprint_ipv6_addr(addr), ret);
616 	}
617 }
618 
setup_ipv6_addr(struct sockaddr_in6 * local_addr)619 static void setup_ipv6_addr(struct sockaddr_in6 *local_addr)
620 {
621 	create_ipv6_addr(local_addr);
622 
623 	net_if_foreach(iface_ipv6_cb, &local_addr->sin6_addr);
624 }
625 #endif /* CONFIG_NET_IPV6 */
626 
627 #if defined(CONFIG_NET_IPV4)
iface_ipv4_cb(struct net_if * iface,void * user_data)628 static void iface_ipv4_cb(struct net_if *iface, void *user_data)
629 {
630 	struct in_addr *addr = user_data;
631 	int ret;
632 
633 	if (!net_if_is_up(iface)) {
634 		struct net_if_mcast_addr *maddr;
635 
636 		NET_DBG("Interface %d is down, not joining mcast group yet",
637 			net_if_get_by_iface(iface));
638 
639 		maddr = net_if_ipv4_maddr_add(iface, addr);
640 		if (!maddr) {
641 			NET_DBG("Cannot add multicast address %s",
642 				net_sprint_ipv4_addr(addr));
643 		}
644 
645 		return;
646 	}
647 
648 	ret = net_ipv4_igmp_join(iface, addr, NULL);
649 	if (ret < 0) {
650 		NET_DBG("Cannot add IPv4 multicast address to iface %d",
651 			net_if_get_by_iface(iface));
652 	}
653 }
654 
setup_ipv4_addr(struct sockaddr_in * local_addr)655 static void setup_ipv4_addr(struct sockaddr_in *local_addr)
656 {
657 	create_ipv4_addr(local_addr);
658 
659 	net_if_foreach(iface_ipv4_cb, &local_addr->sin_addr);
660 }
661 #endif /* CONFIG_NET_IPV4 */
662 
663 #if defined(CONFIG_NET_INTERFACE_NAME_LEN)
664 #define INTERFACE_NAME_LEN CONFIG_NET_INTERFACE_NAME_LEN
665 #else
666 #define INTERFACE_NAME_LEN 0
667 #endif
668 
dispatcher_cb(void * my_ctx,int sock,struct sockaddr * addr,size_t addrlen,struct net_buf * dns_data,size_t len)669 static int dispatcher_cb(void *my_ctx, int sock,
670 			 struct sockaddr *addr, size_t addrlen,
671 			 struct net_buf *dns_data, size_t len)
672 {
673 	int ret;
674 
675 	ARG_UNUSED(my_ctx);
676 
677 	ret = dns_read(sock, dns_data, len, addr, addrlen);
678 	if (ret < 0 && ret != -EINVAL && ret != -ENOENT) {
679 		NET_DBG("%s read failed (%d)", "mDNS", ret);
680 	}
681 
682 	return ret;
683 }
684 
register_dispatcher(struct mdns_responder_context * ctx,const struct net_socket_service_desc * svc,struct sockaddr * local,int ifindex,struct zsock_pollfd * fds,size_t fds_len)685 static int register_dispatcher(struct mdns_responder_context *ctx,
686 			       const struct net_socket_service_desc *svc,
687 			       struct sockaddr *local,
688 			       int ifindex,
689 			       struct zsock_pollfd *fds,
690 			       size_t fds_len)
691 {
692 	ctx->dispatcher.type = DNS_SOCKET_RESPONDER;
693 	ctx->dispatcher.cb = dispatcher_cb;
694 	ctx->dispatcher.fds = fds;
695 	ctx->dispatcher.fds_len = fds_len;
696 	ctx->dispatcher.sock = ctx->sock;
697 	ctx->dispatcher.svc = svc;
698 	ctx->dispatcher.mdns_ctx = ctx;
699 	ctx->dispatcher.pair = NULL;
700 	ctx->dispatcher.ifindex = ifindex;
701 
702 	/* Mark the fd so that "net sockets" can show it. This is needed if there
703 	 * is already a socket bound to same port and the dispatcher will mux
704 	 * the connections. Without this, the FD in "net sockets" services list will
705 	 * show the socket descriptor value as -1.
706 	 */
707 	svc->pev[0].event.fd = ctx->sock;
708 
709 	if (IS_ENABLED(CONFIG_NET_IPV6) && local->sa_family == AF_INET6) {
710 		memcpy(&ctx->dispatcher.local_addr, local,
711 		       sizeof(struct sockaddr_in6));
712 	} else if (IS_ENABLED(CONFIG_NET_IPV4) && local->sa_family == AF_INET) {
713 		memcpy(&ctx->dispatcher.local_addr, local,
714 		       sizeof(struct sockaddr_in));
715 	} else {
716 		return -ENOTSUP;
717 	}
718 
719 	return dns_dispatcher_register(&ctx->dispatcher);
720 }
721 
init_listener(void)722 static int init_listener(void)
723 {
724 	int ret, ok = 0, ifindex;
725 	char name[INTERFACE_NAME_LEN + 1];
726 	struct ifreq if_req;
727 	struct net_if *iface;
728 	int iface_count, fds_pos;
729 
730 	NET_IFACE_COUNT(&iface_count);
731 	NET_DBG("Setting %s listener to %d interface%s", "mDNS", iface_count,
732 		iface_count > 1 ? "s" : "");
733 
734 #if defined(CONFIG_NET_IPV6)
735 	/* Because there is only one IPv6 socket service context for all
736 	 * IPv6 sockets, we must collect the sockets in one place.
737 	 */
738 	struct zsock_pollfd ipv6_fds[MAX_IPV6_IFACE_COUNT];
739 	struct sockaddr_in6 local_addr6;
740 	int v6;
741 
742 	if ((iface_count > MAX_IPV6_IFACE_COUNT && MAX_IPV6_IFACE_COUNT > 0)) {
743 		NET_WARN("You have %d %s interfaces configured but there "
744 			 "are %d network interfaces in the system.",
745 			 MAX_IPV6_IFACE_COUNT, "IPv6", iface_count);
746 	}
747 
748 	setup_ipv6_addr(&local_addr6);
749 
750 	ARRAY_FOR_EACH(ipv6_fds, i) {
751 		ipv6_fds[i].fd = -1;
752 	}
753 
754 	fds_pos = 0;
755 
756 	ARRAY_FOR_EACH(v6_ctx, i) {
757 		ARRAY_FOR_EACH(v6_ctx[i].fds, j) {
758 			v6_ctx[i].fds[j].fd = -1;
759 		}
760 
761 		v6 = get_socket(AF_INET6);
762 		if (v6 < 0) {
763 			NET_ERR("Cannot get %s socket (%d %s interfaces). Max sockets is %d",
764 				"IPv6", MAX_IPV6_IFACE_COUNT,
765 				"IPv6", CONFIG_NET_MAX_CONTEXTS);
766 			continue;
767 		}
768 
769 		iface = net_if_get_by_index(i + 1);
770 		if (iface == NULL) {
771 			zsock_close(v6);
772 			continue;
773 		}
774 
775 		ifindex = net_if_get_by_iface(iface);
776 
777 		ret = net_if_get_name(iface, name, INTERFACE_NAME_LEN);
778 		if (ret < 0) {
779 			NET_DBG("Cannot get interface name for %d (%d)",
780 				ifindex, ret);
781 		} else {
782 			memset(&if_req, 0, sizeof(if_req));
783 			strncpy(if_req.ifr_name, name, sizeof(if_req.ifr_name) - 1);
784 
785 			ret = zsock_setsockopt(v6, SOL_SOCKET, SO_BINDTODEVICE,
786 					       &if_req, sizeof(if_req));
787 			if (ret < 0) {
788 				NET_DBG("Cannot bind sock %d to interface %d (%d)",
789 					v6, ifindex, ret);
790 			}
791 		}
792 
793 		v6_ctx[i].sock = v6;
794 		ret = -1;
795 
796 		ARRAY_FOR_EACH(v6_ctx[i].fds, j) {
797 			if (v6_ctx[i].fds[j].fd == v6) {
798 				ret = 0;
799 				break;
800 			}
801 
802 			if (v6_ctx[i].fds[j].fd < 0) {
803 				v6_ctx[i].fds[j].fd = v6;
804 				v6_ctx[i].fds[j].events = ZSOCK_POLLIN;
805 				ipv6_fds[fds_pos].fd = v6;
806 				ipv6_fds[fds_pos++].events = ZSOCK_POLLIN;
807 				ret = 0;
808 				break;
809 			}
810 		}
811 
812 		if (ret < 0) {
813 			NET_DBG("Cannot set %s to socket (%d)", "polling", ret);
814 			zsock_close(v6);
815 			continue;
816 		}
817 
818 		ret = register_dispatcher(&v6_ctx[i], &v6_svc, (struct sockaddr *)&local_addr6,
819 					  ifindex, ipv6_fds, ARRAY_SIZE(ipv6_fds));
820 		if (ret < 0) {
821 			NET_DBG("Cannot register %s %s socket service (%d)",
822 				"IPv6", "mDNS", ret);
823 			zsock_close(v6);
824 		} else {
825 			ok++;
826 		}
827 	}
828 #endif /* CONFIG_NET_IPV6 */
829 
830 #if defined(CONFIG_NET_IPV4)
831 	struct zsock_pollfd ipv4_fds[MAX_IPV4_IFACE_COUNT];
832 	struct sockaddr_in local_addr4;
833 	int v4;
834 
835 	if ((iface_count > MAX_IPV4_IFACE_COUNT && MAX_IPV4_IFACE_COUNT > 0)) {
836 		NET_WARN("You have %d %s interfaces configured but there "
837 			 "are %d network interfaces in the system.",
838 			 MAX_IPV4_IFACE_COUNT, "IPv4", iface_count);
839 	}
840 
841 	setup_ipv4_addr(&local_addr4);
842 
843 	ARRAY_FOR_EACH(ipv4_fds, i) {
844 		ipv4_fds[i].fd = -1;
845 	}
846 
847 	fds_pos = 0;
848 
849 	ARRAY_FOR_EACH(v4_ctx, i) {
850 		ARRAY_FOR_EACH(v4_ctx[i].fds, j) {
851 			v4_ctx[i].fds[j].fd = -1;
852 		}
853 
854 		v4 = get_socket(AF_INET);
855 		if (v4 < 0) {
856 			NET_ERR("Cannot get %s socket (%d %s interfaces). Max sockets is %d",
857 				"IPv4", MAX_IPV4_IFACE_COUNT,
858 				"IPv4", CONFIG_NET_MAX_CONTEXTS);
859 			continue;
860 		}
861 
862 		iface = net_if_get_by_index(i + 1);
863 		if (iface == NULL) {
864 			zsock_close(v4);
865 			continue;
866 		}
867 
868 		ifindex = net_if_get_by_iface(iface);
869 
870 		ret = net_if_get_name(iface, name, INTERFACE_NAME_LEN);
871 		if (ret < 0) {
872 			NET_DBG("Cannot get interface name for %d (%d)",
873 				ifindex, ret);
874 		} else {
875 			memset(&if_req, 0, sizeof(if_req));
876 			strncpy(if_req.ifr_name, name, sizeof(if_req.ifr_name) - 1);
877 
878 			ret = zsock_setsockopt(v4, SOL_SOCKET, SO_BINDTODEVICE,
879 					       &if_req, sizeof(if_req));
880 			if (ret < 0) {
881 				NET_DBG("Cannot bind sock %d to interface %d (%d)",
882 					v4, ifindex, ret);
883 			}
884 		}
885 
886 		v4_ctx[i].sock = v4;
887 		ret = -1;
888 
889 		ARRAY_FOR_EACH(v4_ctx[i].fds, j) {
890 			if (v4_ctx[i].fds[j].fd == v4) {
891 				ret = 0;
892 				break;
893 			}
894 
895 			if (v4_ctx[i].fds[j].fd < 0) {
896 				v4_ctx[i].fds[j].fd = v4;
897 				v4_ctx[i].fds[j].events = ZSOCK_POLLIN;
898 				ipv4_fds[fds_pos].fd = v4;
899 				ipv4_fds[fds_pos++].events = ZSOCK_POLLIN;
900 				ret = 0;
901 				break;
902 			}
903 		}
904 
905 		if (ret < 0) {
906 			NET_DBG("Cannot set %s to socket (%d)", "polling", ret);
907 			zsock_close(v4);
908 			continue;
909 		}
910 
911 		ret = register_dispatcher(&v4_ctx[i], &v4_svc, (struct sockaddr *)&local_addr4,
912 					  ifindex, ipv4_fds, ARRAY_SIZE(ipv4_fds));
913 		if (ret < 0) {
914 			NET_DBG("Cannot register %s %s socket service (%d)",
915 				"IPv4", "mDNS", ret);
916 			zsock_close(v4);
917 		} else {
918 			ok++;
919 		}
920 	}
921 #endif /* CONFIG_NET_IPV4 */
922 
923 	if (!ok) {
924 		NET_WARN("Cannot start %s responder", "mDNS");
925 	}
926 
927 	return !ok;
928 }
929 
mdns_responder_init(void)930 static int mdns_responder_init(void)
931 {
932 	external_records = NULL;
933 	external_records_count = 0;
934 
935 	net_mgmt_init_event_callback(&mgmt_cb, mdns_iface_event_handler,
936 				     NET_EVENT_IF_UP);
937 
938 	net_mgmt_add_event_callback(&mgmt_cb);
939 
940 	return init_listener();
941 }
942 
mdns_responder_set_ext_records(const struct dns_sd_rec * records,size_t count)943 int mdns_responder_set_ext_records(const struct dns_sd_rec *records, size_t count)
944 {
945 	if (records == NULL || count == 0) {
946 		return -EINVAL;
947 	}
948 
949 	external_records = records;
950 	external_records_count = count;
951 
952 	return 0;
953 }
954 
mdns_init_responder(void)955 void mdns_init_responder(void)
956 {
957 	(void)mdns_responder_init();
958 }
959