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  * Copyright (c) 2025 SynchronicIT BV
12  *
13  * SPDX-License-Identifier: Apache-2.0
14  */
15 
16 #include <zephyr/logging/log.h>
17 LOG_MODULE_REGISTER(net_mdns_responder, CONFIG_MDNS_RESPONDER_LOG_LEVEL);
18 
19 #include <zephyr/kernel.h>
20 #include <zephyr/init.h>
21 #include <string.h>
22 #include <strings.h>
23 #include <errno.h>
24 #include <stdlib.h>
25 
26 #include <zephyr/random/random.h>
27 #include <zephyr/net/mld.h>
28 #include <zephyr/net/net_core.h>
29 #include <zephyr/net/net_ip.h>
30 #include <zephyr/net/net_pkt.h>
31 #include <zephyr/net/dns_resolve.h>
32 #include <zephyr/net/socket_service.h>
33 #include <zephyr/net/igmp.h>
34 
35 #include "dns_sd.h"
36 #include "dns_pack.h"
37 #include "ipv6.h"
38 #include "../../ip/net_stats.h"
39 
40 #include "net_private.h"
41 
42 /*
43  * GCC complains about struct sockaddr accesses due to the various
44  * address-family-specific variants being of differing sizes. Let's not
45  * mess with code (which looks correct), just silence the compiler.
46  */
47 #ifdef __GNUC__
48 #pragma GCC diagnostic ignored "-Wpragmas"
49 #pragma GCC diagnostic ignored "-Wunknown-warning-option"
50 #pragma GCC diagnostic ignored "-Warray-bounds"
51 #pragma GCC diagnostic ignored "-Wstringop-overread"
52 #endif
53 
54 extern void dns_dispatcher_svc_handler(struct net_socket_service_event *pev);
55 
56 #define MDNS_LISTEN_PORT 5353
57 
58 #define MDNS_TTL CONFIG_MDNS_RESPONDER_TTL /* In seconds */
59 
60 #if defined(CONFIG_NET_IPV4)
61 static struct mdns_responder_context v4_ctx[MAX_IPV4_IFACE_COUNT];
62 
63 NET_SOCKET_SERVICE_SYNC_DEFINE_STATIC(v4_svc, dns_dispatcher_svc_handler,
64 				      MDNS_MAX_IPV4_IFACE_COUNT);
65 #endif
66 
67 #if defined(CONFIG_NET_IPV6)
68 static struct mdns_responder_context v6_ctx[MAX_IPV6_IFACE_COUNT];
69 
70 NET_SOCKET_SERVICE_SYNC_DEFINE_STATIC(v6_svc, dns_dispatcher_svc_handler,
71 				      MDNS_MAX_IPV6_IFACE_COUNT);
72 #endif
73 
74 static struct net_mgmt_event_callback mgmt_iface_cb;
75 
76 #if defined(CONFIG_MDNS_RESPONDER_PROBE)
77 static void cancel_probes(struct mdns_responder_context *ctx);
78 static struct net_mgmt_event_callback mgmt_conn_cb;
79 #if defined(CONFIG_NET_IPV4)
80 static struct net_mgmt_event_callback mgmt4_addr_cb;
81 #endif
82 #if defined(CONFIG_NET_IPV6)
83 static struct net_mgmt_event_callback mgmt6_addr_cb;
84 #endif
85 static struct k_work_q mdns_work_q;
86 static K_KERNEL_STACK_DEFINE(mdns_work_q_stack, CONFIG_MDNS_WORKQ_STACK_SIZE);
87 struct k_work_delayable init_listener_timer;
88 static int failed_probes;
89 static int probe_count;
90 static int announce_count;
91 static bool do_announce;
92 static bool init_listener_done;
93 
94 /* Collect added/deleted IP addresses to announce them */
95 struct mdns_monitor_iface_addr {
96 	struct net_if *iface;
97 	struct net_addr addr;
98 	bool in_use : 1;
99 	bool needs_announce : 1;
100 };
101 
102 static struct mdns_monitor_iface_addr mon_if[
103 	MAX(MAX_IPV4_IFACE_COUNT, MAX_IPV4_IFACE_COUNT) *
104 	(NET_IF_MAX_IPV4_ADDR + NET_IF_MAX_IPV6_ADDR)];
105 #endif
106 
107 static const struct dns_sd_rec *external_records;
108 static size_t external_records_count;
109 
110 #define BUF_ALLOC_TIMEOUT K_MSEC(100)
111 
112 #ifndef CONFIG_NET_TEST
113 static int setup_dst_addr(int sock, sa_family_t family,
114 			  struct sockaddr *src, socklen_t src_len,
115 			  struct sockaddr *dst, socklen_t *dst_len);
116 #endif /* CONFIG_NET_TEST */
117 
118 #define DNS_RESOLVER_MIN_BUF		2
119 #define DNS_RESOLVER_BUF_CTR	(DNS_RESOLVER_MIN_BUF + \
120 				 CONFIG_MDNS_RESOLVER_ADDITIONAL_BUF_CTR)
121 
122 NET_BUF_POOL_DEFINE(mdns_msg_pool, DNS_RESOLVER_BUF_CTR,
123 		    DNS_RESOLVER_MAX_BUF_SIZE, 0, NULL);
124 
create_ipv6_addr(struct sockaddr_in6 * addr)125 static void create_ipv6_addr(struct sockaddr_in6 *addr)
126 {
127 	addr->sin6_family = AF_INET6;
128 	addr->sin6_port = htons(MDNS_LISTEN_PORT);
129 
130 	/* Well known IPv6 ff02::fb address */
131 	net_ipv6_addr_create(&addr->sin6_addr,
132 			     0xff02, 0, 0, 0, 0, 0, 0, 0x00fb);
133 }
134 
create_ipv4_addr(struct sockaddr_in * addr)135 static void create_ipv4_addr(struct sockaddr_in *addr)
136 {
137 	addr->sin_family = AF_INET;
138 	addr->sin_port = htons(MDNS_LISTEN_PORT);
139 
140 	/* Well known IPv4 224.0.0.251 address */
141 	addr->sin_addr.s_addr = htonl(0xE00000FB);
142 }
143 
144 #if defined(CONFIG_MDNS_RESPONDER_PROBE)
mark_needs_announce(struct net_if * iface,bool needs_announce)145 static void mark_needs_announce(struct net_if *iface, bool needs_announce)
146 {
147 	ARRAY_FOR_EACH(mon_if, i) {
148 		if (!mon_if[i].in_use) {
149 			continue;
150 		}
151 
152 		if (iface != NULL) {
153 			if (mon_if[i].iface != iface) {
154 				continue;
155 			}
156 		}
157 
158 		mon_if[i].needs_announce = needs_announce;
159 	}
160 }
161 #endif /* CONFIG_MDNS_RESPONDER_PROBE */
162 
mdns_iface_event_handler(struct net_mgmt_event_callback * cb,uint32_t mgmt_event,struct net_if * iface)163 static void mdns_iface_event_handler(struct net_mgmt_event_callback *cb,
164 				     uint32_t mgmt_event, struct net_if *iface)
165 
166 {
167 	if (mgmt_event == NET_EVENT_IF_UP) {
168 #if defined(CONFIG_NET_IPV4)
169 		ARRAY_FOR_EACH(v4_ctx, i) {
170 			int ret = net_ipv4_igmp_join(iface,
171 					&net_sin(&v4_ctx[i].dispatcher.local_addr)->sin_addr,
172 					NULL);
173 			if (ret < 0 && ret != -EALREADY) {
174 				NET_DBG("Cannot add IPv4 multicast address %s to iface %d (%d)",
175 					net_sprint_ipv4_addr(&net_sin(
176 						&v4_ctx[i].dispatcher.local_addr)->sin_addr),
177 					net_if_get_by_iface(iface), ret);
178 			}
179 		}
180 #endif /* defined(CONFIG_NET_IPV4) */
181 	}
182 
183 #if defined(CONFIG_MDNS_RESPONDER_PROBE)
184 	if (mgmt_event == NET_EVENT_IF_UP && init_listener_done) {
185 		do_announce = true;
186 		announce_count = 0;
187 
188 		mark_needs_announce(iface, true);
189 	}
190 #endif /* CONFIG_MDNS_RESPONDER_PROBE */
191 }
192 
set_ttl_hop_limit(int sock,int level,int option,int new_limit)193 static int set_ttl_hop_limit(int sock, int level, int option, int new_limit)
194 {
195 	return zsock_setsockopt(sock, level, option, &new_limit, sizeof(new_limit));
196 }
197 
setup_dst_addr(int sock,sa_family_t family,struct sockaddr * src,socklen_t src_len,struct sockaddr * dst,socklen_t * dst_len)198 int setup_dst_addr(int sock, sa_family_t family,
199 		   struct sockaddr *src, socklen_t src_len,
200 		   struct sockaddr *dst, socklen_t *dst_len)
201 {
202 	int ret;
203 
204 	if (IS_ENABLED(CONFIG_NET_IPV4) && family == AF_INET) {
205 		if ((src != NULL) && (net_sin(src)->sin_port != htons(MDNS_LISTEN_PORT))) {
206 			memcpy(dst, src, src_len);
207 			*dst_len = src_len;
208 		} else {
209 			create_ipv4_addr(net_sin(dst));
210 			*dst_len = sizeof(struct sockaddr_in);
211 
212 			ret = set_ttl_hop_limit(sock, IPPROTO_IP, IP_MULTICAST_TTL, 255);
213 			if (ret < 0) {
214 				NET_DBG("Cannot set %s multicast %s (%d)", "IPv4", "TTL", ret);
215 			}
216 		}
217 	} else if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) {
218 		if ((src != NULL) && (net_sin6(src)->sin6_port != htons(MDNS_LISTEN_PORT))) {
219 			memcpy(dst, src, src_len);
220 			*dst_len = src_len;
221 		} else {
222 			create_ipv6_addr(net_sin6(dst));
223 			*dst_len = sizeof(struct sockaddr_in6);
224 
225 			ret = set_ttl_hop_limit(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 255);
226 			if (ret < 0) {
227 				NET_DBG("Cannot set %s multicast %s (%d)", "IPv6", "hoplimit", ret);
228 			}
229 		}
230 	} else {
231 		return -EPFNOSUPPORT;
232 	}
233 
234 	return 0;
235 }
236 
get_socket(sa_family_t family)237 static int get_socket(sa_family_t family)
238 {
239 	int ret;
240 
241 	ret = zsock_socket(family, SOCK_DGRAM, IPPROTO_UDP);
242 	if (ret < 0) {
243 		ret = -errno;
244 		NET_DBG("Cannot get socket (%d)", ret);
245 	}
246 
247 	return ret;
248 }
249 
setup_dns_hdr(uint8_t * buf,uint16_t answers)250 static void setup_dns_hdr(uint8_t *buf, uint16_t answers)
251 {
252 	uint16_t offset;
253 	uint16_t flags;
254 
255 	/* See RFC 1035, ch 4.1.1 for header details */
256 
257 	flags = BIT(15);  /* This is response */
258 	flags |= BIT(10); /* Authoritative Answer */
259 
260 	UNALIGNED_PUT(0, (uint16_t *)(buf)); /* Identifier, RFC 6762 ch 18.1 */
261 	offset = DNS_HEADER_ID_LEN;
262 
263 	UNALIGNED_PUT(htons(flags), (uint16_t *)(buf+offset));
264 	offset += DNS_HEADER_FLAGS_LEN;
265 
266 	UNALIGNED_PUT(0, (uint16_t *)(buf + offset));
267 	offset += DNS_QDCOUNT_LEN;
268 
269 	UNALIGNED_PUT(htons(answers), (uint16_t *)(buf + offset));
270 	offset += DNS_ANCOUNT_LEN;
271 
272 	UNALIGNED_PUT(0, (uint16_t *)(buf + offset));
273 	offset += DNS_NSCOUNT_LEN;
274 
275 	UNALIGNED_PUT(0, (uint16_t *)(buf + offset));
276 }
277 
add_answer(struct net_buf * query,enum dns_rr_type qtype,uint32_t ttl,uint16_t addr_len,uint8_t * addr)278 static void add_answer(struct net_buf *query, enum dns_rr_type qtype,
279 		       uint32_t ttl, uint16_t addr_len, uint8_t *addr)
280 {
281 	char *dot = query->data + DNS_MSG_HEADER_SIZE;
282 	char *prev = NULL;
283 	uint16_t offset;
284 
285 	while ((dot = strchr(dot, '.'))) {
286 		if (!prev) {
287 			prev = dot++;
288 			continue;
289 		}
290 
291 		*prev = dot - prev - 1;
292 		prev = dot++;
293 	}
294 
295 	if (prev) {
296 		*prev = strlen(prev) - 1;
297 	}
298 
299 	/* terminator byte (0x00) */
300 	query->len += 1;
301 
302 	offset = DNS_MSG_HEADER_SIZE + query->len;
303 	UNALIGNED_PUT(htons(qtype), (uint16_t *)(query->data+offset));
304 
305 	/* Bit 15 tells to flush the cache */
306 	offset += DNS_QTYPE_LEN;
307 	UNALIGNED_PUT(htons(DNS_CLASS_IN | BIT(15)),
308 		      (uint16_t *)(query->data+offset));
309 
310 
311 	offset += DNS_QCLASS_LEN;
312 	UNALIGNED_PUT(htonl(ttl), query->data + offset);
313 
314 	offset += DNS_TTL_LEN;
315 	UNALIGNED_PUT(htons(addr_len), query->data + offset);
316 
317 	offset += DNS_RDLENGTH_LEN;
318 	memcpy(query->data + offset, addr, addr_len);
319 }
320 
create_answer(int sock,struct net_buf * query,enum dns_rr_type qtype,uint16_t addr_len,uint8_t * addr)321 static int create_answer(int sock,
322 			 struct net_buf *query,
323 			 enum dns_rr_type qtype,
324 			 uint16_t addr_len, uint8_t *addr)
325 {
326 	/* Prepare the response into the query buffer: move the name
327 	 * query buffer has to get enough free space: dns_hdr + answer
328 	 */
329 	if ((net_buf_max_len(query) - query->len) < (DNS_MSG_HEADER_SIZE +
330 					  DNS_QTYPE_LEN + DNS_QCLASS_LEN +
331 					  DNS_TTL_LEN + DNS_RDLENGTH_LEN +
332 					  addr_len)) {
333 		return -ENOBUFS;
334 	}
335 
336 	memmove(query->data + DNS_MSG_HEADER_SIZE, query->data, query->len);
337 
338 	setup_dns_hdr(query->data, 1);
339 
340 	add_answer(query, qtype, MDNS_TTL, addr_len, addr);
341 
342 	query->len += DNS_MSG_HEADER_SIZE +
343 		DNS_QTYPE_LEN + DNS_QCLASS_LEN +
344 		DNS_TTL_LEN + DNS_RDLENGTH_LEN + addr_len;
345 
346 	return 0;
347 }
348 
send_response(int sock,sa_family_t family,struct sockaddr * src_addr,size_t addrlen,struct net_buf * query,enum dns_rr_type qtype)349 static int send_response(int sock,
350 			 sa_family_t family,
351 			 struct sockaddr *src_addr,
352 			 size_t addrlen,
353 			 struct net_buf *query,
354 			 enum dns_rr_type qtype)
355 {
356 	struct net_if *iface;
357 	socklen_t dst_len;
358 	int ret;
359 	COND_CODE_1(IS_ENABLED(CONFIG_NET_IPV6),
360 		    (struct sockaddr_in6), (struct sockaddr_in)) dst;
361 
362 	ret = setup_dst_addr(sock, family, src_addr, addrlen, (struct sockaddr *)&dst, &dst_len);
363 	if (ret < 0) {
364 		NET_DBG("unable to set up the response address");
365 		return ret;
366 	}
367 
368 	if (family == AF_INET6) {
369 		iface = net_if_ipv6_select_src_iface(&net_sin6(src_addr)->sin6_addr);
370 	} else {
371 		iface = net_if_ipv4_select_src_iface(&net_sin(src_addr)->sin_addr);
372 	}
373 
374 	if (IS_ENABLED(CONFIG_NET_IPV4) && qtype == DNS_RR_TYPE_A) {
375 		const struct in_addr *addr;
376 
377 		if (family == AF_INET) {
378 			addr = net_if_ipv4_select_src_addr(iface,
379 							   &net_sin(src_addr)->sin_addr);
380 		} else {
381 			struct sockaddr_in tmp_addr;
382 
383 			create_ipv4_addr(&tmp_addr);
384 			addr = net_if_ipv4_select_src_addr(iface, &tmp_addr.sin_addr);
385 		}
386 
387 		ret = create_answer(sock, query, qtype, sizeof(struct in_addr), (uint8_t *)addr);
388 		if (ret != 0) {
389 			return ret;
390 		}
391 	} else if (IS_ENABLED(CONFIG_NET_IPV6) && qtype == DNS_RR_TYPE_AAAA) {
392 		const struct in6_addr *addr;
393 
394 		if (family == AF_INET6) {
395 			addr = net_if_ipv6_select_src_addr(iface,
396 							   &net_sin6(src_addr)->sin6_addr);
397 		} else {
398 			struct sockaddr_in6 tmp_addr;
399 
400 			create_ipv6_addr(&tmp_addr);
401 			addr = net_if_ipv6_select_src_addr(iface, &tmp_addr.sin6_addr);
402 		}
403 
404 		ret = create_answer(sock, query, qtype, sizeof(struct in6_addr), (uint8_t *)addr);
405 		if (ret != 0) {
406 			return -ENOMEM;
407 		}
408 	} else {
409 		/* TODO: support also service PTRs */
410 		return -EINVAL;
411 	}
412 
413 	ret = zsock_sendto(sock, query->data, query->len, 0,
414 			   (struct sockaddr *)&dst, dst_len);
415 	if (ret < 0) {
416 		ret = -errno;
417 		NET_DBG("Cannot send %s reply (%d)", "mDNS", ret);
418 	} else {
419 		net_stats_update_dns_sent(iface);
420 	}
421 
422 	return ret;
423 }
424 
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)425 static void send_sd_response(int sock,
426 			     sa_family_t family,
427 			     struct sockaddr *src_addr,
428 			     size_t addrlen,
429 			     struct dns_msg_t *dns_msg,
430 			     struct net_buf *result)
431 {
432 	struct net_if *iface;
433 	socklen_t dst_len;
434 	int ret;
435 	const struct dns_sd_rec *record;
436 	/* filter must be zero-initialized for "wildcard" port */
437 	struct dns_sd_rec filter = {0};
438 	bool service_type_enum = false;
439 	const struct in6_addr *addr6 = NULL;
440 	const struct in_addr *addr4 = NULL;
441 	char instance_buf[DNS_SD_INSTANCE_MAX_SIZE + 1];
442 	char service_buf[DNS_SD_SERVICE_MAX_SIZE + 1];
443 	/* Depending on segment count in the query, third buffer could hold
444 	 * either protocol or domain, use larger size.
445 	 */
446 	char proto_buf[DNS_SD_DOMAIN_MAX_SIZE + 1];
447 	char domain_buf[DNS_SD_DOMAIN_MAX_SIZE + 1];
448 	char *label[4];
449 	size_t size[] = {
450 		ARRAY_SIZE(instance_buf),
451 		ARRAY_SIZE(service_buf),
452 		ARRAY_SIZE(proto_buf),
453 		ARRAY_SIZE(domain_buf),
454 	};
455 	size_t n = ARRAY_SIZE(label);
456 	size_t rec_num;
457 	size_t ext_rec_num = external_records_count;
458 	COND_CODE_1(IS_ENABLED(CONFIG_NET_IPV6),
459 		    (struct sockaddr_in6), (struct sockaddr_in)) dst;
460 
461 	BUILD_ASSERT(ARRAY_SIZE(label) == ARRAY_SIZE(size), "");
462 
463 	/*
464 	 * work around for bug in compliance scripts which say that the array
465 	 * should be static const (incorrect)
466 	 */
467 	label[0] = instance_buf;
468 	label[1] = service_buf;
469 	label[2] = proto_buf;
470 	label[3] = domain_buf;
471 
472 	ret = setup_dst_addr(sock, family, src_addr, addrlen, (struct sockaddr *)&dst, &dst_len);
473 	if (ret < 0) {
474 		NET_DBG("unable to set up the response address");
475 		return;
476 	}
477 
478 	if (family == AF_INET6) {
479 		iface = net_if_ipv6_select_src_iface(&net_sin6(src_addr)->sin6_addr);
480 	} else {
481 		iface = net_if_ipv4_select_src_iface(&net_sin(src_addr)->sin_addr);
482 	}
483 
484 	if (IS_ENABLED(CONFIG_NET_IPV4)) {
485 		/* Look up the local IPv4 address */
486 		if (family == AF_INET) {
487 			addr4 = net_if_ipv4_select_src_addr(iface,
488 							    &net_sin(src_addr)->sin_addr);
489 		} else {
490 			struct sockaddr_in tmp_addr;
491 
492 			create_ipv4_addr(&tmp_addr);
493 			addr4 = net_if_ipv4_select_src_addr(iface, &tmp_addr.sin_addr);
494 		}
495 	}
496 
497 	if (IS_ENABLED(CONFIG_NET_IPV6)) {
498 		/* Look up the local IPv6 address */
499 		if (family == AF_INET6) {
500 			addr6 = net_if_ipv6_select_src_addr(iface,
501 							    &net_sin6(src_addr)->sin6_addr);
502 		} else {
503 			struct sockaddr_in6 tmp_addr;
504 
505 			create_ipv6_addr(&tmp_addr);
506 			addr6 = net_if_ipv6_select_src_addr(iface, &tmp_addr.sin6_addr);
507 		}
508 	}
509 
510 	ret = dns_sd_query_extract(dns_msg->msg,
511 		dns_msg->msg_size, &filter, label, size, &n);
512 	if (ret < 0) {
513 		NET_DBG("unable to extract query (%d)", ret);
514 		return;
515 	}
516 
517 	if (IS_ENABLED(CONFIG_MDNS_RESPONDER_DNS_SD_SERVICE_TYPE_ENUMERATION)
518 		&& dns_sd_is_service_type_enumeration(&filter)) {
519 
520 		/*
521 		 * RFC 6763, Section 9
522 		 *
523 		 * A DNS query for PTR records with the name
524 		 * "_services._dns-sd._udp.<Domain>" yields a set of PTR records,
525 		 * where the rdata of each PTR record is the two-label <Service> name,
526 		 * plus the same domain, e.g., "_http._tcp.<Domain>".
527 		 */
528 		dns_sd_create_wildcard_filter(&filter);
529 		service_type_enum = true;
530 	}
531 
532 	DNS_SD_COUNT(&rec_num);
533 
534 	while (rec_num > 0 || ext_rec_num > 0) {
535 		/*
536 		 * The loop will always iterate over all entries, it can be done
537 		 * backwards for simplicity
538 		 */
539 		if (rec_num > 0) {
540 			DNS_SD_GET(rec_num - 1, &record);
541 			rec_num--;
542 		} else {
543 			record = &external_records[ext_rec_num - 1];
544 			ext_rec_num--;
545 		}
546 
547 		/* Checks validity and then compare */
548 		if (dns_sd_rec_match(record, &filter)) {
549 			NET_DBG("matched query: %s.%s.%s.%s port: %u",
550 				record->instance, record->service,
551 				record->proto, record->domain,
552 				ntohs(*(record->port)));
553 
554 			/* Construct the response */
555 			if (service_type_enum) {
556 				ret = dns_sd_handle_service_type_enum(record, addr4, addr6,
557 						result->data, net_buf_max_len(result));
558 				if (ret < 0) {
559 					NET_DBG("dns_sd_handle_service_type_enum() failed (%d)",
560 						ret);
561 					continue;
562 				}
563 			} else {
564 				ret = dns_sd_handle_ptr_query(record, addr4, addr6,
565 						result->data, net_buf_max_len(result));
566 				if (ret < 0) {
567 					NET_DBG("dns_sd_handle_ptr_query() failed (%d)", ret);
568 					continue;
569 				}
570 			}
571 
572 			result->len = ret;
573 
574 			/* Send the response */
575 			ret = zsock_sendto(sock, result->data, result->len, 0,
576 					   (struct sockaddr *)&dst, dst_len);
577 			if (ret < 0) {
578 				NET_DBG("Cannot send %s reply (%d)", "mDNS", ret);
579 				continue;
580 			} else {
581 				net_stats_update_dns_sent(iface);
582 			}
583 		}
584 	}
585 }
586 
dns_read(int sock,struct net_buf * dns_data,size_t len,struct sockaddr * src_addr,size_t addrlen)587 static int dns_read(int sock,
588 		    struct net_buf *dns_data,
589 		    size_t len,
590 		    struct sockaddr *src_addr,
591 		    size_t addrlen)
592 {
593 	/* Helper struct to track the dns msg received from the server */
594 	const char *hostname = net_hostname_get();
595 	int hostname_len = strlen(hostname);
596 	int family = src_addr->sa_family;
597 	struct net_buf *result;
598 	struct dns_msg_t dns_msg;
599 	int data_len;
600 	int queries;
601 	int ret;
602 
603 	data_len = MIN(len, DNS_RESOLVER_MAX_BUF_SIZE);
604 
605 	/* Store the DNS query name into a temporary net_buf, which will be
606 	 * eventually used to send a response
607 	 */
608 	result = net_buf_alloc(&mdns_msg_pool, BUF_ALLOC_TIMEOUT);
609 	if (!result) {
610 		ret = -ENOMEM;
611 		goto quit;
612 	}
613 
614 	dns_msg.msg = dns_data->data;
615 	dns_msg.msg_size = data_len;
616 
617 	ret = mdns_unpack_query_header(&dns_msg, NULL);
618 	if (ret < 0) {
619 		goto quit;
620 	}
621 
622 	queries = ret;
623 
624 	NET_DBG("Received %d %s from %s:%u", queries,
625 		queries > 1 ? "queries" : "query",
626 		net_sprint_addr(family,
627 				family == AF_INET ?
628 				(const void *)&net_sin(src_addr)->sin_addr :
629 				(const void *)&net_sin6(src_addr)->sin6_addr),
630 				ntohs(family == AF_INET ?
631 				net_sin(src_addr)->sin_port :
632 				net_sin6(src_addr)->sin6_port));
633 
634 	do {
635 		enum dns_rr_type qtype;
636 		enum dns_class qclass;
637 		uint8_t *lquery;
638 
639 		(void)memset(result->data, 0, net_buf_tailroom(result));
640 		result->len = 0U;
641 
642 		ret = dns_unpack_query(&dns_msg, result, &qtype, &qclass);
643 		if (ret < 0) {
644 			goto quit;
645 		}
646 
647 		/* Handle only .local queries */
648 		lquery = strrchr(result->data + 1, '.');
649 		if (!lquery || memcmp(lquery, (const void *){ ".local" }, 7)) {
650 			continue;
651 		}
652 
653 		NET_DBG("[%d] query %s/%s label %s (%d bytes)", queries,
654 			dns_qtype_to_str(qtype), "IN",
655 			result->data, ret);
656 
657 		/* If the query matches to our hostname, then send reply.
658 		 * We skip the first dot, and make sure there is dot after
659 		 * matching hostname.
660 		 */
661 		if (!strncasecmp(hostname, result->data + 1, hostname_len) &&
662 		    (result->len - 1) >= hostname_len &&
663 		    &(result->data + 1)[hostname_len] == lquery) {
664 			NET_DBG("%s %s %s to our hostname %s%s", "mDNS",
665 				family == AF_INET ? "IPv4" : "IPv6", "query",
666 				hostname, ".local");
667 			send_response(sock, family, src_addr, addrlen,
668 				      result, qtype);
669 		} else if (IS_ENABLED(CONFIG_MDNS_RESPONDER_DNS_SD)
670 			&& qtype == DNS_RR_TYPE_PTR) {
671 			send_sd_response(sock, family, src_addr, addrlen,
672 					 &dns_msg, result);
673 		}
674 
675 	} while (--queries);
676 
677 	ret = 0;
678 
679 quit:
680 	if (result) {
681 		net_buf_unref(result);
682 	}
683 
684 	return ret;
685 }
686 
687 /* The probing sends mDNS query so in order that to work the mDNS resolver
688  * needs to be enabled.
689  */
690 #if defined(CONFIG_MDNS_RESPONDER_PROBE)
691 
add_address(struct net_if * iface,sa_family_t family,const void * address,size_t addrlen)692 static int add_address(struct net_if *iface, sa_family_t family,
693 		       const void *address, size_t addrlen)
694 {
695 	size_t expected_len;
696 	int first_free;
697 
698 	if (family != AF_INET && family != AF_INET6) {
699 		return -EINVAL;
700 	}
701 
702 	if (family == AF_INET) {
703 		expected_len = sizeof(struct in_addr);
704 	} else {
705 		expected_len = sizeof(struct in6_addr);
706 	}
707 
708 	if (addrlen != expected_len) {
709 		return -EINVAL;
710 	}
711 
712 	first_free = -1;
713 
714 	ARRAY_FOR_EACH(mon_if, j) {
715 		if (!mon_if[j].in_use) {
716 			if (first_free < 0) {
717 				first_free = j;
718 			}
719 		}
720 
721 		if (mon_if[j].iface != iface) {
722 			continue;
723 		}
724 
725 		if (mon_if[j].addr.family != family) {
726 			continue;
727 		}
728 
729 		if (memcmp(&mon_if[j].addr.in_addr, address, expected_len) == 0) {
730 			return -EALREADY;
731 		}
732 	}
733 
734 	if (first_free >= 0) {
735 		mon_if[first_free].in_use = true;
736 		mon_if[first_free].iface = iface;
737 		mon_if[first_free].addr.family = family;
738 
739 		memcpy(&mon_if[first_free].addr.in_addr, address, expected_len);
740 
741 		NET_DBG("%s added %s address %s to iface %d in slot %d",
742 			"mDNS", family == AF_INET ? "IPv4" : "IPv6",
743 			family == AF_INET ? net_sprint_ipv4_addr(address) :
744 					    net_sprint_ipv6_addr(address),
745 			net_if_get_by_iface(iface), first_free);
746 		return 0;
747 	}
748 
749 	return -ENOENT;
750 }
751 
del_address(struct net_if * iface,sa_family_t family,const void * address,size_t addrlen)752 static int del_address(struct net_if *iface, sa_family_t family,
753 		       const void *address, size_t addrlen)
754 {
755 	size_t expected_len;
756 
757 	if (family != AF_INET && family != AF_INET6) {
758 		return -EINVAL;
759 	}
760 
761 	if (family == AF_INET) {
762 		expected_len = sizeof(struct in_addr);
763 	} else {
764 		expected_len = sizeof(struct in6_addr);
765 	}
766 
767 	ARRAY_FOR_EACH(mon_if, j) {
768 		if (!mon_if[j].in_use) {
769 			continue;
770 		}
771 
772 		if (mon_if[j].iface != iface) {
773 			continue;
774 		}
775 
776 		if (mon_if[j].addr.family != family) {
777 			continue;
778 		}
779 
780 		if (memcmp(&mon_if[j].addr.in_addr, address, expected_len) == 0) {
781 			mon_if[j].in_use = false;
782 			return 0;
783 		}
784 	}
785 
786 	return -ENOENT;
787 }
788 
probe_cb(enum dns_resolve_status status,struct dns_addrinfo * info,void * user_data)789 static void probe_cb(enum dns_resolve_status status,
790 		     struct dns_addrinfo *info,
791 		     void *user_data)
792 {
793 	struct mdns_probe_user_data *ud = user_data;
794 
795 	NET_DBG("status %d", status);
796 
797 	if (status == DNS_EAI_ALLDONE) {
798 		/* We got a reply, so we can stop probing as there was reply
799 		 * to our query.
800 		 */
801 		cancel_probes(ud->ctx);
802 		failed_probes++;
803 
804 		NET_WARN("mDNS probe received data, will not use \"%s\" name.",
805 			 ud->query);
806 
807 		dns_resolve_close(&ud->ctx->probe_ctx);
808 
809 	} else if (status == DNS_EAI_CANCELED) {
810 		if (--probe_count <= 0) {
811 			int ret;
812 
813 			dns_resolve_close(&ud->ctx->probe_ctx);
814 
815 			/* Schedule a handler that will initialize the listener
816 			 * and start announcing the services.
817 			 */
818 			ret = k_work_reschedule_for_queue(&mdns_work_q,
819 							  &init_listener_timer,
820 							  K_NO_WAIT);
821 			if (ret < 0) {
822 				NET_DBG("Cannot schedule %s init work (%d)", "mDNS", ret);
823 			}
824 		}
825 	}
826 }
827 
828 #define PROBE_TIMEOUT 1750 /* in ms, see RFC 6762 ch 8.1 */
829 #define PORT_COUNT 5
830 
831 /* Sending unsolicited mDNS query when interface is up. RFC 6762 ch 8.1 */
send_probe(struct mdns_responder_context * ctx)832 static int send_probe(struct mdns_responder_context *ctx)
833 {
834 	const char *hostname = net_hostname_get();
835 	struct sockaddr *servers[2] = { 0 };
836 	struct sockaddr_in6 server = { 0 };
837 	int interfaces[ARRAY_SIZE(servers)] = { 0 };
838 	uint16_t local_port;
839 	int ret;
840 
841 	NET_DBG("%s %s %s to our hostname %s%s iface %d", "mDNS",
842 		ctx->dispatcher.local_addr.sa_family == AF_INET ? "IPv4" : "IPv6",
843 		"probe", hostname, ".local", net_if_get_by_iface(ctx->iface));
844 
845 	ret = 0;
846 	do {
847 		local_port = sys_rand16_get() | 0x8000;
848 		ret++;
849 	} while (net_context_port_in_use(IPPROTO_UDP, local_port,
850 					 &ctx->dispatcher.local_addr) && ret < PORT_COUNT);
851 	if (ret >= PORT_COUNT) {
852 		NET_ERR("No available port, %s probe fails!", "mDNS");
853 		ret = -EIO;
854 		goto out;
855 	}
856 
857 	if (ctx->dispatcher.local_addr.sa_family == AF_INET) {
858 		create_ipv4_addr((struct sockaddr_in *)&server);
859 	} else {
860 		create_ipv6_addr(&server);
861 	}
862 
863 	servers[0] = (struct sockaddr *)&server;
864 	interfaces[0] = net_if_get_by_iface(ctx->iface);
865 
866 	ret = dns_resolve_init_with_svc(&ctx->probe_ctx, NULL,
867 					(const struct sockaddr **)servers,
868 					ctx->dispatcher.svc, local_port,
869 					interfaces);
870 	if (ret < 0) {
871 		NET_DBG("Cannot initialize DNS resolver (%d)", ret);
872 		goto out;
873 	}
874 
875 	snprintk(ctx->probe_data.query, sizeof(ctx->probe_data.query),
876 		 "%s%s", hostname, ".local");
877 
878 	ctx->probe_data.dns_id = 0U;
879 	ctx->probe_data.ctx = ctx;
880 
881 	NET_DBG("Sending mDNS probe for %s to iface %d",
882 		ctx->probe_data.query, interfaces[0]);
883 
884 	/* Then the actual probe sending. RFC 6762 ch 8.1 says to use
885 	 * the ANY resource type. Use the internal resolve function that does
886 	 * not use cache.
887 	 */
888 	ret = dns_resolve_name_internal(&ctx->probe_ctx, ctx->probe_data.query,
889 					DNS_RR_TYPE_ANY,
890 					&ctx->probe_data.dns_id, probe_cb,
891 					&ctx->probe_data, PROBE_TIMEOUT,
892 					false);
893 	if (ret < 0) {
894 		NET_DBG("Cannot send mDNS probe (%d)", ret);
895 		goto fail;
896 	}
897 
898 	probe_count++;
899 
900 	return 0;
901 
902 fail:
903 	dns_resolve_close(&ctx->probe_ctx);
904 out:
905 	return ret;
906 }
907 
cancel_probes(struct mdns_responder_context * ctx)908 static void cancel_probes(struct mdns_responder_context *ctx)
909 {
910 #if defined(CONFIG_NET_IPV4)
911 	ARRAY_FOR_EACH(v4_ctx, i) {
912 		if (&v4_ctx[i] == ctx) {
913 			continue;
914 		}
915 
916 		NET_DBG("Cancel probe for %s mDNS ctx %p", "IPv4", ctx);
917 
918 		(void)k_work_cancel_delayable(&v4_ctx[i].probe_timer);
919 	}
920 #endif /* defined(CONFIG_NET_IPV4) */
921 
922 #if defined(CONFIG_NET_IPV6)
923 	ARRAY_FOR_EACH(v6_ctx, i) {
924 		if (&v6_ctx[i] == ctx) {
925 			continue;
926 		}
927 
928 		NET_DBG("Cancel probe for %s mDNS ctx %p", "IPv6", ctx);
929 
930 		(void)k_work_cancel_delayable(&v6_ctx[i].probe_timer);
931 	}
932 #endif /* defined(CONFIG_NET_IPV6) */
933 }
934 
probing(struct k_work * work)935 static void probing(struct k_work *work)
936 {
937 	struct k_work_delayable *dwork = k_work_delayable_from_work(work);
938 	struct mdns_responder_context *ctx =
939 		CONTAINER_OF(dwork, struct mdns_responder_context, probe_timer);
940 	int ret;
941 
942 	if (failed_probes > 0) {
943 		/* No point doing any new probe because one already failed */
944 		NET_DBG("Probe already failed, not sending any more probes.");
945 
946 		(void)k_work_cancel_delayable(&init_listener_timer);
947 		return;
948 	}
949 
950 	ret = send_probe(ctx);
951 	if (ret < 0) {
952 		if (errno == EEXIST) {
953 			/* Cancel the other possible probes */
954 			cancel_probes(ctx);
955 		}
956 
957 		NET_DBG("Cannot send %s mDNS probe (%d, errno %d)",
958 			ctx->dispatcher.local_addr.sa_family == AF_INET ? "IPv4" :
959 			(ctx->dispatcher.local_addr.sa_family == AF_INET6 ? "IPv6" :
960 			 ""),
961 			ret, errno);
962 	}
963 }
964 
mdns_addr_event_handler(struct net_mgmt_event_callback * cb,uint32_t mgmt_event,struct net_if * iface)965 static void mdns_addr_event_handler(struct net_mgmt_event_callback *cb,
966 				    uint32_t mgmt_event, struct net_if *iface)
967 {
968 	uint32_t probe_delay = sys_rand32_get() % 250;
969 	bool probe_started = false;
970 	int ret;
971 
972 #if defined(CONFIG_NET_IPV4)
973 	if (mgmt_event == NET_EVENT_IPV4_ADDR_ADD) {
974 		ARRAY_FOR_EACH(v4_ctx, i) {
975 			if (v4_ctx[i].iface != iface) {
976 				continue;
977 			}
978 
979 			ret = add_address(iface, AF_INET, cb->info, cb->info_length);
980 			if (ret < 0 && ret != -EALREADY) {
981 				NET_DBG("Cannot %s %s address (%d)", "add", "IPv4", ret);
982 				return;
983 			}
984 
985 			ret = k_work_reschedule_for_queue(&mdns_work_q,
986 							  &v4_ctx[i].probe_timer,
987 							  K_MSEC(probe_delay));
988 			if (ret < 0) {
989 				NET_DBG("Cannot schedule %s probe work (%d)", "IPv4", ret);
990 			} else {
991 				probe_started = true;
992 
993 				NET_DBG("%s %s probing scheduled for iface %d ctx %p",
994 					"IPv4", "add", net_if_get_by_iface(iface),
995 					&v4_ctx[i]);
996 			}
997 
998 			break;
999 		}
1000 
1001 		return;
1002 	}
1003 
1004 	if (mgmt_event == NET_EVENT_IPV4_ADDR_DEL) {
1005 		ARRAY_FOR_EACH(v4_ctx, i) {
1006 			if (v4_ctx[i].iface != iface) {
1007 				continue;
1008 			}
1009 
1010 			ret = del_address(iface, AF_INET, cb->info, cb->info_length);
1011 			if (ret < 0) {
1012 				if (ret == -ENOENT) {
1013 					continue;
1014 				}
1015 
1016 				NET_DBG("Cannot %s %s address (%d)", "del", "IPv4", ret);
1017 				return;
1018 			}
1019 
1020 			if (!net_if_is_up(iface)) {
1021 				continue;
1022 			}
1023 
1024 			ret = k_work_reschedule_for_queue(&mdns_work_q,
1025 							  &v4_ctx[i].probe_timer,
1026 							  K_MSEC(probe_delay));
1027 			if (ret < 0) {
1028 				NET_DBG("Cannot schedule %s probe work (%d)", "IPv4", ret);
1029 			} else {
1030 				probe_started = true;
1031 
1032 				NET_DBG("%s %s probing scheduled for iface %d ctx %p",
1033 					"IPv4", "del", net_if_get_by_iface(iface),
1034 					&v4_ctx[i]);
1035 			}
1036 
1037 			break;
1038 		}
1039 
1040 		return;
1041 	}
1042 #endif /* defined(CONFIG_NET_IPV4) */
1043 
1044 #if defined(CONFIG_NET_IPV6)
1045 	if (mgmt_event == NET_EVENT_IPV6_ADDR_ADD) {
1046 		ARRAY_FOR_EACH(v6_ctx, i) {
1047 			if (v6_ctx[i].iface != iface) {
1048 				continue;
1049 			}
1050 
1051 			ret = add_address(iface, AF_INET6, cb->info, cb->info_length);
1052 			if (ret < 0 && ret != -EALREADY) {
1053 				NET_DBG("Cannot %s %s address (%d)", "add", "IPv6", ret);
1054 				return;
1055 			}
1056 
1057 			ret = k_work_reschedule_for_queue(&mdns_work_q,
1058 							  &v6_ctx[i].probe_timer,
1059 							  K_MSEC(probe_delay));
1060 			if (ret < 0) {
1061 				NET_DBG("Cannot schedule %s probe work (%d)", "IPv6", ret);
1062 			} else {
1063 				probe_started = true;
1064 
1065 				NET_DBG("%s %s probing scheduled for iface %d ctx %p",
1066 					"IPv6", "add", net_if_get_by_iface(iface),
1067 					&v6_ctx[i]);
1068 			}
1069 
1070 			break;
1071 		}
1072 
1073 		return;
1074 	}
1075 
1076 	if (mgmt_event == NET_EVENT_IPV6_ADDR_DEL) {
1077 		ARRAY_FOR_EACH(v6_ctx, i) {
1078 			if (v6_ctx[i].iface != iface) {
1079 				continue;
1080 			}
1081 
1082 			ret = del_address(iface, AF_INET6, cb->info, cb->info_length);
1083 			if (ret < 0) {
1084 				if (ret == -ENOENT) {
1085 					continue;
1086 				}
1087 
1088 				NET_DBG("Cannot %s %s address (%d)", "del", "IPv6", ret);
1089 				return;
1090 			}
1091 
1092 			if (!net_if_is_up(iface)) {
1093 				continue;
1094 			}
1095 
1096 			ret = k_work_reschedule_for_queue(&mdns_work_q,
1097 							  &v4_ctx[i].probe_timer,
1098 							  K_MSEC(probe_delay));
1099 			if (ret < 0) {
1100 				NET_DBG("Cannot schedule %s probe work (%d)", "IPv6", ret);
1101 			} else {
1102 				probe_started = true;
1103 
1104 				NET_DBG("%s %s probing scheduled for iface %d ctx %p",
1105 					"IPv6", "del", net_if_get_by_iface(iface),
1106 					&v6_ctx[i]);
1107 			}
1108 
1109 			break;
1110 		}
1111 
1112 		return;
1113 	}
1114 #endif /* defined(CONFIG_NET_IPV6) */
1115 }
1116 
mdns_conn_event_handler(struct net_mgmt_event_callback * cb,uint32_t mgmt_event,struct net_if * iface)1117 static void mdns_conn_event_handler(struct net_mgmt_event_callback *cb,
1118 				    uint32_t mgmt_event, struct net_if *iface)
1119 {
1120 	if (mgmt_event == NET_EVENT_L4_DISCONNECTED) {
1121 		/* Clear the failed probes counter so that we can start
1122 		 * probing again.
1123 		 */
1124 		failed_probes = 0;
1125 	}
1126 }
1127 #endif /* CONFIG_MDNS_RESPONDER_PROBE */
1128 
1129 #if defined(CONFIG_NET_IPV6)
iface_ipv6_cb(struct net_if * iface,void * user_data)1130 static void iface_ipv6_cb(struct net_if *iface, void *user_data)
1131 {
1132 	struct in6_addr *addr = user_data;
1133 	int ret;
1134 
1135 	ret = net_ipv6_mld_join(iface, addr);
1136 	if (ret < 0) {
1137 		NET_DBG("Cannot join %s IPv6 multicast group (%d)",
1138 			net_sprint_ipv6_addr(addr), ret);
1139 	}
1140 }
1141 
setup_ipv6_addr(struct sockaddr_in6 * local_addr)1142 static void setup_ipv6_addr(struct sockaddr_in6 *local_addr)
1143 {
1144 	create_ipv6_addr(local_addr);
1145 
1146 	net_if_foreach(iface_ipv6_cb, &local_addr->sin6_addr);
1147 }
1148 #endif /* CONFIG_NET_IPV6 */
1149 
1150 #if defined(CONFIG_NET_IPV4)
iface_ipv4_cb(struct net_if * iface,void * user_data)1151 static void iface_ipv4_cb(struct net_if *iface, void *user_data)
1152 {
1153 	struct in_addr *addr = user_data;
1154 	int ret;
1155 
1156 	if (!net_if_is_up(iface)) {
1157 		struct net_if_mcast_addr *maddr;
1158 
1159 		NET_DBG("Interface %d is down, not joining mcast group yet",
1160 			net_if_get_by_iface(iface));
1161 
1162 		maddr = net_if_ipv4_maddr_add(iface, addr);
1163 		if (!maddr) {
1164 			NET_DBG("Cannot add multicast address %s",
1165 				net_sprint_ipv4_addr(addr));
1166 		}
1167 
1168 		return;
1169 	}
1170 
1171 	ret = net_ipv4_igmp_join(iface, addr, NULL);
1172 	if (ret < 0) {
1173 		NET_DBG("Cannot add IPv4 multicast address to iface %d",
1174 			net_if_get_by_iface(iface));
1175 	}
1176 }
1177 
setup_ipv4_addr(struct sockaddr_in * local_addr)1178 static void setup_ipv4_addr(struct sockaddr_in *local_addr)
1179 {
1180 	create_ipv4_addr(local_addr);
1181 
1182 	net_if_foreach(iface_ipv4_cb, &local_addr->sin_addr);
1183 }
1184 #endif /* CONFIG_NET_IPV4 */
1185 
1186 #if defined(CONFIG_NET_INTERFACE_NAME_LEN)
1187 #define INTERFACE_NAME_LEN CONFIG_NET_INTERFACE_NAME_LEN
1188 #else
1189 #define INTERFACE_NAME_LEN 0
1190 #endif
1191 
dispatcher_cb(struct dns_socket_dispatcher * ctx,int sock,struct sockaddr * addr,size_t addrlen,struct net_buf * dns_data,size_t len)1192 static int dispatcher_cb(struct dns_socket_dispatcher *ctx, int sock,
1193 			 struct sockaddr *addr, size_t addrlen,
1194 			 struct net_buf *dns_data, size_t len)
1195 {
1196 	int ret;
1197 
1198 	ret = dns_read(sock, dns_data, len, addr, addrlen);
1199 	if (ret < 0 && ret != -EINVAL && ret != -ENOENT) {
1200 		NET_DBG("%s read failed (%d)", "mDNS", ret);
1201 	}
1202 
1203 	return ret;
1204 }
1205 
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)1206 static int register_dispatcher(struct mdns_responder_context *ctx,
1207 			       const struct net_socket_service_desc *svc,
1208 			       struct sockaddr *local,
1209 			       int ifindex,
1210 			       struct zsock_pollfd *fds,
1211 			       size_t fds_len)
1212 {
1213 	ctx->dispatcher.type = DNS_SOCKET_RESPONDER;
1214 	ctx->dispatcher.cb = dispatcher_cb;
1215 	ctx->dispatcher.fds = fds;
1216 	ctx->dispatcher.fds_len = fds_len;
1217 	ctx->dispatcher.sock = ctx->sock;
1218 	ctx->dispatcher.svc = svc;
1219 	ctx->dispatcher.mdns_ctx = ctx;
1220 	ctx->dispatcher.pair = NULL;
1221 	ctx->dispatcher.ifindex = ifindex;
1222 
1223 	/* Mark the fd so that "net sockets" can show it. This is needed if there
1224 	 * is already a socket bound to same port and the dispatcher will mux
1225 	 * the connections. Without this, the FD in "net sockets" services list will
1226 	 * show the socket descriptor value as -1.
1227 	 */
1228 	svc->pev[0].event.fd = ctx->sock;
1229 
1230 	if (IS_ENABLED(CONFIG_NET_IPV6) && local->sa_family == AF_INET6) {
1231 		memcpy(&ctx->dispatcher.local_addr, local,
1232 		       sizeof(struct sockaddr_in6));
1233 	} else if (IS_ENABLED(CONFIG_NET_IPV4) && local->sa_family == AF_INET) {
1234 		memcpy(&ctx->dispatcher.local_addr, local,
1235 		       sizeof(struct sockaddr_in));
1236 	} else {
1237 		return -ENOTSUP;
1238 	}
1239 
1240 	return dns_dispatcher_register(&ctx->dispatcher);
1241 }
1242 
1243 #if defined(CONFIG_MDNS_RESPONDER_PROBE)
1244 /* Initialize things so that we can do probing before staring the listener */
pre_init_listener(void)1245 static int pre_init_listener(void)
1246 {
1247 	int ok = 0;
1248 	struct net_if *iface;
1249 	int iface_count;
1250 
1251 	NET_IFACE_COUNT(&iface_count);
1252 	NET_DBG("Pre-init %s for %d interface%s", "mDNS", iface_count,
1253 		iface_count > 1 ? "s" : "");
1254 
1255 #if defined(CONFIG_NET_IPV6)
1256 	if ((iface_count > MAX_IPV6_IFACE_COUNT && MAX_IPV6_IFACE_COUNT > 0)) {
1257 		NET_WARN("You have %d %s interfaces configured but there "
1258 			 "are %d network interfaces in the system.",
1259 			 MAX_IPV6_IFACE_COUNT, "IPv6", iface_count);
1260 	}
1261 
1262 	ARRAY_FOR_EACH(v6_ctx, i) {
1263 		iface = net_if_get_by_index(i + 1);
1264 		if (iface == NULL) {
1265 			continue;
1266 		}
1267 
1268 		v6_ctx[i].iface = iface;
1269 		v6_ctx[i].dispatcher.local_addr.sa_family = AF_INET6;
1270 		v6_ctx[i].dispatcher.svc = &v6_svc;
1271 
1272 		k_work_init_delayable(&v6_ctx[i].probe_timer, probing);
1273 
1274 		ok++;
1275 	}
1276 #endif /* CONFIG_NET_IPV6 */
1277 
1278 #if defined(CONFIG_NET_IPV4)
1279 	if ((iface_count > MAX_IPV4_IFACE_COUNT && MAX_IPV4_IFACE_COUNT > 0)) {
1280 		NET_WARN("You have %d %s interfaces configured but there "
1281 			 "are %d network interfaces in the system.",
1282 			 MAX_IPV4_IFACE_COUNT, "IPv4", iface_count);
1283 	}
1284 
1285 	ARRAY_FOR_EACH(v4_ctx, i) {
1286 		iface = net_if_get_by_index(i + 1);
1287 		if (iface == NULL) {
1288 			continue;
1289 		}
1290 
1291 		v4_ctx[i].iface = iface;
1292 		v4_ctx[i].dispatcher.local_addr.sa_family = AF_INET;
1293 		v4_ctx[i].dispatcher.svc = &v4_svc;
1294 
1295 		k_work_init_delayable(&v4_ctx[i].probe_timer, probing);
1296 
1297 		ok++;
1298 	}
1299 #endif /* CONFIG_NET_IPV4 */
1300 
1301 	if (ok == 0) {
1302 		NET_WARN("Cannot pre-init %s responder", "mDNS");
1303 		return -ENOENT;
1304 	}
1305 
1306 	return 0;
1307 }
1308 #endif /* CONFIG_MDNS_RESPONDER_PROBE */
1309 
init_listener(void)1310 static int init_listener(void)
1311 {
1312 	int ret, ok = 0, ifindex;
1313 	char name[INTERFACE_NAME_LEN + 1];
1314 	struct ifreq if_req;
1315 	struct net_if *iface;
1316 	int iface_count, fds_pos;
1317 
1318 	NET_IFACE_COUNT(&iface_count);
1319 	NET_DBG("Setting %s listener to %d interface%s", "mDNS", iface_count,
1320 		iface_count > 1 ? "s" : "");
1321 
1322 #if defined(CONFIG_NET_IPV6)
1323 	/* Because there is only one IPv6 socket service context for all
1324 	 * IPv6 sockets, we must collect the sockets in one place.
1325 	 */
1326 	struct zsock_pollfd ipv6_fds[MAX_IPV6_IFACE_COUNT];
1327 	struct sockaddr_in6 local_addr6;
1328 	int v6;
1329 
1330 	if ((iface_count > MAX_IPV6_IFACE_COUNT && MAX_IPV6_IFACE_COUNT > 0)) {
1331 		NET_WARN("You have %d %s interfaces configured but there "
1332 			 "are %d network interfaces in the system.",
1333 			 MAX_IPV6_IFACE_COUNT, "IPv6", iface_count);
1334 	}
1335 
1336 	setup_ipv6_addr(&local_addr6);
1337 
1338 	ARRAY_FOR_EACH(ipv6_fds, i) {
1339 		ipv6_fds[i].fd = -1;
1340 	}
1341 
1342 	fds_pos = 0;
1343 
1344 	ARRAY_FOR_EACH(v6_ctx, i) {
1345 		ARRAY_FOR_EACH(v6_ctx[i].fds, j) {
1346 			v6_ctx[i].fds[j].fd = -1;
1347 		}
1348 
1349 		v6 = get_socket(AF_INET6);
1350 		if (v6 < 0) {
1351 			NET_ERR("Cannot get %s socket (%d %s interfaces). Max sockets is %d",
1352 				"IPv6", MAX_IPV6_IFACE_COUNT,
1353 				"IPv6", CONFIG_NET_MAX_CONTEXTS);
1354 			continue;
1355 		}
1356 
1357 		iface = net_if_get_by_index(i + 1);
1358 		if (iface == NULL) {
1359 			zsock_close(v6);
1360 			continue;
1361 		}
1362 
1363 		ifindex = net_if_get_by_iface(iface);
1364 
1365 		ret = net_if_get_name(iface, name, INTERFACE_NAME_LEN);
1366 		if (ret < 0) {
1367 			NET_DBG("Cannot get interface name for %d (%d)",
1368 				ifindex, ret);
1369 		} else {
1370 			memset(&if_req, 0, sizeof(if_req));
1371 			strncpy(if_req.ifr_name, name, sizeof(if_req.ifr_name) - 1);
1372 
1373 			ret = zsock_setsockopt(v6, SOL_SOCKET, SO_BINDTODEVICE,
1374 					       &if_req, sizeof(if_req));
1375 			if (ret < 0) {
1376 				NET_DBG("Cannot bind sock %d to interface %d (%d)",
1377 					v6, ifindex, ret);
1378 			} else {
1379 				NET_DBG("Bound %s sock %d to interface %d",
1380 					"IPv6", v6, ifindex);
1381 			}
1382 		}
1383 
1384 		v6_ctx[i].sock = v6;
1385 		ret = -1;
1386 
1387 		ARRAY_FOR_EACH(v6_ctx[i].fds, j) {
1388 			if (v6_ctx[i].fds[j].fd == v6) {
1389 				ret = 0;
1390 				break;
1391 			}
1392 
1393 			if (v6_ctx[i].fds[j].fd < 0) {
1394 				v6_ctx[i].fds[j].fd = v6;
1395 				v6_ctx[i].fds[j].events = ZSOCK_POLLIN;
1396 				ipv6_fds[fds_pos].fd = v6;
1397 				ipv6_fds[fds_pos++].events = ZSOCK_POLLIN;
1398 				ret = 0;
1399 				break;
1400 			}
1401 		}
1402 
1403 		if (ret < 0) {
1404 			NET_DBG("Cannot set %s to socket (%d)", "polling", ret);
1405 			zsock_close(v6);
1406 			continue;
1407 		}
1408 
1409 		ret = register_dispatcher(&v6_ctx[i], &v6_svc, (struct sockaddr *)&local_addr6,
1410 					  ifindex, ipv6_fds, ARRAY_SIZE(ipv6_fds));
1411 		if (ret < 0 && ret != -EALREADY) {
1412 			NET_DBG("Cannot register %s %s socket service (%d)",
1413 				"IPv6", "mDNS", ret);
1414 			zsock_close(v6);
1415 		} else {
1416 			ok++;
1417 		}
1418 	}
1419 #endif /* CONFIG_NET_IPV6 */
1420 
1421 #if defined(CONFIG_NET_IPV4)
1422 	struct zsock_pollfd ipv4_fds[MAX_IPV4_IFACE_COUNT];
1423 	struct sockaddr_in local_addr4;
1424 	int v4;
1425 
1426 	if ((iface_count > MAX_IPV4_IFACE_COUNT && MAX_IPV4_IFACE_COUNT > 0)) {
1427 		NET_WARN("You have %d %s interfaces configured but there "
1428 			 "are %d network interfaces in the system.",
1429 			 MAX_IPV4_IFACE_COUNT, "IPv4", iface_count);
1430 	}
1431 
1432 	setup_ipv4_addr(&local_addr4);
1433 
1434 	ARRAY_FOR_EACH(ipv4_fds, i) {
1435 		ipv4_fds[i].fd = -1;
1436 	}
1437 
1438 	fds_pos = 0;
1439 
1440 	ARRAY_FOR_EACH(v4_ctx, i) {
1441 		ARRAY_FOR_EACH(v4_ctx[i].fds, j) {
1442 			v4_ctx[i].fds[j].fd = -1;
1443 		}
1444 
1445 		v4 = get_socket(AF_INET);
1446 		if (v4 < 0) {
1447 			NET_ERR("Cannot get %s socket (%d %s interfaces). Max sockets is %d",
1448 				"IPv4", MAX_IPV4_IFACE_COUNT,
1449 				"IPv4", CONFIG_NET_MAX_CONTEXTS);
1450 			continue;
1451 		}
1452 
1453 		iface = net_if_get_by_index(i + 1);
1454 		if (iface == NULL) {
1455 			zsock_close(v4);
1456 			continue;
1457 		}
1458 
1459 		ifindex = net_if_get_by_iface(iface);
1460 
1461 		ret = net_if_get_name(iface, name, INTERFACE_NAME_LEN);
1462 		if (ret < 0) {
1463 			NET_DBG("Cannot get interface name for %d (%d)",
1464 				ifindex, ret);
1465 		} else {
1466 			memset(&if_req, 0, sizeof(if_req));
1467 			strncpy(if_req.ifr_name, name, sizeof(if_req.ifr_name) - 1);
1468 
1469 			ret = zsock_setsockopt(v4, SOL_SOCKET, SO_BINDTODEVICE,
1470 					       &if_req, sizeof(if_req));
1471 			if (ret < 0) {
1472 				NET_DBG("Cannot bind sock %d to interface %d (%d)",
1473 					v4, ifindex, ret);
1474 			} else {
1475 				NET_DBG("Bound %s sock %d to interface %d",
1476 					"IPv4", v4, ifindex);
1477 			}
1478 		}
1479 
1480 		v4_ctx[i].sock = v4;
1481 		ret = -1;
1482 
1483 		ARRAY_FOR_EACH(v4_ctx[i].fds, j) {
1484 			if (v4_ctx[i].fds[j].fd == v4) {
1485 				ret = 0;
1486 				break;
1487 			}
1488 
1489 			if (v4_ctx[i].fds[j].fd < 0) {
1490 				v4_ctx[i].fds[j].fd = v4;
1491 				v4_ctx[i].fds[j].events = ZSOCK_POLLIN;
1492 				ipv4_fds[fds_pos].fd = v4;
1493 				ipv4_fds[fds_pos++].events = ZSOCK_POLLIN;
1494 				ret = 0;
1495 				break;
1496 			}
1497 		}
1498 
1499 		if (ret < 0) {
1500 			NET_DBG("Cannot set %s to socket (%d)", "polling", ret);
1501 			zsock_close(v4);
1502 			continue;
1503 		}
1504 
1505 		ret = register_dispatcher(&v4_ctx[i], &v4_svc, (struct sockaddr *)&local_addr4,
1506 					  ifindex, ipv4_fds, ARRAY_SIZE(ipv4_fds));
1507 		if (ret < 0 && ret != -EALREADY) {
1508 			NET_DBG("Cannot register %s %s socket service (%d)",
1509 				"IPv4", "mDNS", ret);
1510 			zsock_close(v4);
1511 		} else {
1512 			ok++;
1513 		}
1514 	}
1515 #endif /* CONFIG_NET_IPV4 */
1516 
1517 	if (ok == 0) {
1518 		NET_WARN("Cannot start %s responder", "mDNS");
1519 		return -ENOENT;
1520 	}
1521 
1522 	return 0;
1523 }
1524 
1525 #if defined(CONFIG_MDNS_RESPONDER_PROBE)
1526 
1527 #define ANNOUNCE_TIMEOUT 1 /* in seconds, RFC 6762 ch 8.3 */
1528 
1529 /* ATM we do only .local announcing, SD announcing is TODO */
1530 
send_unsolicited_response(struct net_if * iface,int sock,sa_family_t family,struct sockaddr * src_addr,size_t addrlen,struct net_buf * answer)1531 static int send_unsolicited_response(struct net_if *iface,
1532 				     int sock,
1533 				     sa_family_t family,
1534 				     struct sockaddr *src_addr,
1535 				     size_t addrlen,
1536 				     struct net_buf *answer)
1537 {
1538 	socklen_t dst_len;
1539 	int ret;
1540 
1541 	COND_CODE_1(IS_ENABLED(CONFIG_NET_IPV6),
1542 		    (struct sockaddr_in6), (struct sockaddr_in)) dst;
1543 
1544 	ret = setup_dst_addr(sock, family, NULL, 0, (struct sockaddr *)&dst, &dst_len);
1545 	if (ret < 0) {
1546 		NET_DBG("unable to set up the response address");
1547 		return ret;
1548 	}
1549 
1550 	ret = zsock_sendto(sock, answer->data, answer->len, 0,
1551 			   (struct sockaddr *)&dst, dst_len);
1552 	if (ret < 0) {
1553 		ret = -errno;
1554 	} else {
1555 		net_stats_update_dns_sent(iface);
1556 	}
1557 
1558 	return ret;
1559 }
1560 
create_unsolicited_mdns_answer(struct net_if * iface,const char * name,uint32_t ttl,struct mdns_monitor_iface_addr * addr_list,size_t addr_list_len)1561 static struct net_buf *create_unsolicited_mdns_answer(struct net_if *iface,
1562 						      const char *name,
1563 						      uint32_t ttl,
1564 						      struct mdns_monitor_iface_addr *addr_list,
1565 						      size_t addr_list_len)
1566 {
1567 	struct net_buf *answer;
1568 	uint16_t answer_count;
1569 	int len;
1570 
1571 	answer = net_buf_alloc(&mdns_msg_pool, BUF_ALLOC_TIMEOUT);
1572 	if (answer == NULL) {
1573 		return NULL;
1574 	}
1575 
1576 	setup_dns_hdr(answer->data, 1);
1577 	net_buf_add(answer, DNS_MSG_HEADER_SIZE);
1578 
1579 	answer_count = 0U;
1580 
1581 	for (size_t i = 0; i < addr_list_len; i++) {
1582 		uint16_t type;
1583 		size_t left;
1584 
1585 		if (!addr_list[i].in_use) {
1586 			continue;
1587 		}
1588 
1589 		if (iface != addr_list[i].iface) {
1590 			continue;
1591 		}
1592 
1593 		if (addr_list[i].addr.family == AF_INET) {
1594 			type = DNS_RR_TYPE_A;
1595 		} else if (addr_list[i].addr.family == AF_INET6) {
1596 			type = DNS_RR_TYPE_AAAA;
1597 		} else {
1598 			NET_DBG("Unknown family %d", addr_list[i].addr.family);
1599 
1600 			net_buf_unref(answer);
1601 			return NULL;
1602 		}
1603 
1604 		if (answer_count == 0) {
1605 			len = strlen(name);
1606 		}
1607 
1608 		left = net_buf_tailroom(answer);
1609 		if ((answer_count == 0 &&
1610 		     left < (1 + len + 1 + 5 + 1 + 2 + 2 + 4 + 4 +
1611 			     (type == DNS_RR_TYPE_A ? sizeof(struct in_addr) :
1612 			      sizeof(struct in6_addr)))) ||
1613 		    (answer_count > 0 &&
1614 		     left < (1 + 1 + 2 + 2 + 4 + 4 +
1615 			     (type == DNS_RR_TYPE_A ? sizeof(struct in_addr) :
1616 			      sizeof(struct in6_addr))))) {
1617 			NET_DBG("No more space (%u left)", left);
1618 			net_buf_unref(answer);
1619 			return NULL;
1620 		}
1621 
1622 		if (answer_count == 0) {
1623 			net_buf_add_u8(answer, len);
1624 			net_buf_add_mem(answer, name, len);
1625 			net_buf_add_u8(answer, sizeof(".local") - 2);
1626 			net_buf_add_mem(answer, &".local"[1], sizeof(".local") - 2);
1627 			net_buf_add_u8(answer, 0U);
1628 		} else {
1629 			/* Add pointer to the name (compression) */
1630 			net_buf_add_u8(answer, 0xc0);
1631 			net_buf_add_u8(answer, 0x0c);
1632 		}
1633 
1634 		net_buf_add_be16(answer, type);
1635 		net_buf_add_be16(answer, DNS_CLASS_IN);
1636 		net_buf_add_be32(answer, ttl);
1637 
1638 		if (type == DNS_RR_TYPE_A) {
1639 			net_buf_add_be16(answer, sizeof(struct in_addr));
1640 			net_buf_add_mem(answer, &addr_list[i].addr.in_addr,
1641 					sizeof(struct in_addr));
1642 		} else if (type == DNS_RR_TYPE_AAAA) {
1643 			net_buf_add_be16(answer, sizeof(struct in6_addr));
1644 			net_buf_add_mem(answer, &addr_list[i].addr.in6_addr,
1645 				sizeof(struct in6_addr));
1646 		}
1647 
1648 		answer_count++;
1649 	}
1650 
1651 	/* Adjust the answer count in the header */
1652 	if (answer_count > 1) {
1653 		UNALIGNED_PUT(htons(answer_count), (uint16_t *)&answer->data[6]);
1654 	}
1655 
1656 	return answer;
1657 }
1658 
check_if_needs_announce(struct net_if * iface)1659 static bool check_if_needs_announce(struct net_if *iface)
1660 {
1661 	ARRAY_FOR_EACH(mon_if, i) {
1662 		if (!mon_if[i].in_use) {
1663 			continue;
1664 		}
1665 
1666 		if (mon_if[i].iface != iface) {
1667 			continue;
1668 		}
1669 
1670 		if (mon_if[i].needs_announce) {
1671 			return true;
1672 		}
1673 	}
1674 
1675 	return false;
1676 }
1677 
send_announce(const char * name)1678 static int send_announce(const char *name)
1679 {
1680 	struct net_buf *answer;
1681 	int ret;
1682 
1683 #if defined(CONFIG_NET_IPV4)
1684 	struct sockaddr_in dst_addr4;
1685 
1686 	create_ipv4_addr(&dst_addr4);
1687 
1688 	ARRAY_FOR_EACH(v4_ctx, i) {
1689 		if (v4_ctx[i].sock < 0 || v4_ctx[i].iface == NULL ||
1690 		    !net_if_is_up(v4_ctx[i].iface)) {
1691 			continue;
1692 		}
1693 
1694 		if (!check_if_needs_announce(v4_ctx[i].iface)) {
1695 			continue;
1696 		}
1697 
1698 		answer = create_unsolicited_mdns_answer(v4_ctx[i].iface,
1699 							name,
1700 							MDNS_TTL,
1701 							mon_if,
1702 							ARRAY_SIZE(mon_if));
1703 		if (answer == NULL) {
1704 			continue;
1705 		}
1706 
1707 		ret = send_unsolicited_response(v4_ctx[i].iface,
1708 						v4_ctx[i].sock,
1709 						AF_INET,
1710 						(struct sockaddr *)&dst_addr4,
1711 						sizeof(dst_addr4),
1712 						answer);
1713 
1714 		net_buf_unref(answer);
1715 
1716 		if (ret < 0) {
1717 			NET_DBG("Cannot send %s announce (%d)", "mDNS", ret);
1718 			continue;
1719 		}
1720 
1721 		NET_DBG("Announcing %s responder for %s%s (iface %d)",
1722 			"mDNS", name, ".local", net_if_get_by_iface(v4_ctx[i].iface));
1723 	}
1724 #endif /* defined(CONFIG_NET_IPV4) */
1725 
1726 #if defined(CONFIG_NET_IPV6)
1727 	struct sockaddr_in6 dst_addr6;
1728 
1729 	create_ipv6_addr(&dst_addr6);
1730 
1731 	ARRAY_FOR_EACH(v6_ctx, i) {
1732 		if (v6_ctx[i].sock < 0 || v6_ctx[i].iface == NULL ||
1733 		    !net_if_is_up(v6_ctx[i].iface)) {
1734 			continue;
1735 		}
1736 
1737 		if (!check_if_needs_announce(v6_ctx[i].iface)) {
1738 			continue;
1739 		}
1740 
1741 		answer = create_unsolicited_mdns_answer(v6_ctx[i].iface,
1742 							name,
1743 							MDNS_TTL,
1744 							mon_if,
1745 							ARRAY_SIZE(mon_if));
1746 		if (answer == NULL) {
1747 			continue;
1748 		}
1749 
1750 		ret = send_unsolicited_response(v6_ctx[i].iface,
1751 						v6_ctx[i].sock,
1752 						AF_INET6,
1753 						(struct sockaddr *)&dst_addr6,
1754 						sizeof(dst_addr6),
1755 						answer);
1756 
1757 		net_buf_unref(answer);
1758 
1759 		if (ret < 0) {
1760 			NET_DBG("Cannot send %s announce (%d)", "mDNS", ret);
1761 			continue;
1762 		}
1763 
1764 		NET_DBG("Announcing %s responder for %s%s (iface %d)",
1765 			"mDNS", name, ".local", net_if_get_by_iface(v6_ctx[i].iface));
1766 	}
1767 #endif /* defined(CONFIG_NET_IPV6) */
1768 
1769 	return 0;
1770 }
1771 
announce_start(struct k_work * work)1772 static void announce_start(struct k_work *work)
1773 {
1774 	struct k_work_delayable *dwork = k_work_delayable_from_work(work);
1775 	char name[DNS_MAX_NAME_SIZE + 1];
1776 	int ret;
1777 
1778 	snprintk(name, sizeof(name), "%s", net_hostname_get());
1779 
1780 	ret = send_announce(name);
1781 	if (ret < 0) {
1782 		NET_DBG("Cannot send %s announce (%d)", "mDNS", ret);
1783 		return;
1784 	}
1785 
1786 	do_announce = true;
1787 	announce_count++;
1788 
1789 	ret = k_work_reschedule_for_queue(&mdns_work_q, dwork, K_SECONDS(ANNOUNCE_TIMEOUT));
1790 	if (ret < 0) {
1791 		NET_DBG("Cannot schedule %s work (%d)", "announce", ret);
1792 	}
1793 }
1794 
do_init_listener(struct k_work * work)1795 static void do_init_listener(struct k_work *work)
1796 {
1797 	int ret;
1798 
1799 	if (failed_probes) {
1800 		NET_DBG("Probing failed, will not init responder.");
1801 		return;
1802 	}
1803 
1804 	if (do_announce) {
1805 		if (announce_count < 1) {
1806 			announce_start(work);
1807 		} else {
1808 			mark_needs_announce(NULL, false);
1809 		}
1810 	} else {
1811 		NET_DBG("Probing done, starting %s responder", "mDNS");
1812 
1813 		ret = init_listener();
1814 		if (ret < 0) {
1815 			NET_ERR("Cannot start %s responder", "mDNS");
1816 		} else {
1817 			init_listener_done = true;
1818 		};
1819 
1820 		mark_needs_announce(NULL, true);
1821 		announce_count = 0;
1822 		announce_start(work);
1823 	}
1824 }
1825 #endif /* CONFIG_MDNS_RESPONDER_PROBE */
1826 
mdns_responder_init(void)1827 static int mdns_responder_init(void)
1828 {
1829 	uint32_t flags = NET_EVENT_IF_UP;
1830 	external_records = NULL;
1831 	external_records_count = 0;
1832 
1833 	net_mgmt_init_event_callback(&mgmt_iface_cb, mdns_iface_event_handler, flags);
1834 	net_mgmt_add_event_callback(&mgmt_iface_cb);
1835 
1836 #if defined(CONFIG_MDNS_RESPONDER_PROBE)
1837 	int ret;
1838 
1839 	net_mgmt_init_event_callback(&mgmt_conn_cb, mdns_conn_event_handler,
1840 				     NET_EVENT_L4_DISCONNECTED);
1841 	net_mgmt_add_event_callback(&mgmt_conn_cb);
1842 
1843 #if defined(CONFIG_NET_IPV4)
1844 	net_mgmt_init_event_callback(&mgmt4_addr_cb, mdns_addr_event_handler,
1845 				     NET_EVENT_IPV4_ADDR_ADD |
1846 				     NET_EVENT_IPV4_ADDR_DEL);
1847 	net_mgmt_add_event_callback(&mgmt4_addr_cb);
1848 #endif
1849 
1850 #if defined(CONFIG_NET_IPV6)
1851 	net_mgmt_init_event_callback(&mgmt6_addr_cb, mdns_addr_event_handler,
1852 				     NET_EVENT_IPV6_ADDR_ADD |
1853 				     NET_EVENT_IPV6_ADDR_DEL);
1854 	net_mgmt_add_event_callback(&mgmt6_addr_cb);
1855 #endif
1856 
1857 #if defined(CONFIG_NET_TC_THREAD_COOPERATIVE)
1858 #define THREAD_PRIORITY K_PRIO_COOP(CONFIG_MDNS_WORKER_PRIO)
1859 #else
1860 #define THREAD_PRIORITY K_PRIO_PREEMPT(CONFIG_MDNS_WORKER_PRIO)
1861 #endif
1862 
1863 	ret = pre_init_listener();
1864 	if (ret < 0) {
1865 		NET_ERR("Cannot start %s workq", "mDNS");
1866 	} else {
1867 		k_work_queue_start(&mdns_work_q, mdns_work_q_stack,
1868 				   K_KERNEL_STACK_SIZEOF(mdns_work_q_stack),
1869 				   THREAD_PRIORITY, NULL);
1870 
1871 		k_thread_name_set(&mdns_work_q.thread, "mdns_work");
1872 	}
1873 
1874 	k_work_init_delayable(&init_listener_timer, do_init_listener);
1875 
1876 	return ret;
1877 #else
1878 	return init_listener();
1879 #endif
1880 }
1881 
mdns_responder_set_ext_records(const struct dns_sd_rec * records,size_t count)1882 int mdns_responder_set_ext_records(const struct dns_sd_rec *records, size_t count)
1883 {
1884 	if (records == NULL || count == 0) {
1885 		return -EINVAL;
1886 	}
1887 
1888 	external_records = records;
1889 	external_records_count = count;
1890 
1891 	return 0;
1892 }
1893 
mdns_init_responder(void)1894 void mdns_init_responder(void)
1895 {
1896 	(void)mdns_responder_init();
1897 }
1898