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