1 /** @file
2  * @brief LLMNR responder
3  *
4  * This listens to LLMNR queries and responds to them.
5  */
6 
7 /*
8  * Copyright (c) 2018 Intel Corporation
9  * Copyright (c) 2024 Nordic Semiconductor ASA
10  *
11  * SPDX-License-Identifier: Apache-2.0
12  */
13 
14 #include <zephyr/logging/log.h>
15 LOG_MODULE_REGISTER(net_llmnr_responder, CONFIG_LLMNR_RESPONDER_LOG_LEVEL);
16 
17 #include <zephyr/kernel.h>
18 #include <zephyr/init.h>
19 #include <string.h>
20 #include <strings.h>
21 #include <errno.h>
22 #include <stdlib.h>
23 
24 #include <zephyr/net/mld.h>
25 #include <zephyr/net/net_ip.h>
26 #include <zephyr/net/net_pkt.h>
27 #include <zephyr/net/dns_resolve.h>
28 #include <zephyr/net/socket_service.h>
29 #include <zephyr/net/udp.h>
30 #include <zephyr/net/igmp.h>
31 
32 #include "dns_pack.h"
33 #include "ipv6.h"
34 #include "../../ip/net_stats.h"
35 
36 #include "net_private.h"
37 
38 #define LLMNR_LISTEN_PORT 5355
39 
40 #define LLMNR_TTL CONFIG_LLMNR_RESPONDER_TTL /* In seconds */
41 
42 #if defined(CONFIG_NET_IPV4)
43 static int ipv4;
44 static struct sockaddr_in local_addr4;
45 #endif
46 
47 #if defined(CONFIG_NET_IPV6)
48 static int ipv6;
49 #endif
50 
51 static struct net_mgmt_event_callback mgmt_cb;
52 
53 #define BUF_ALLOC_TIMEOUT K_MSEC(100)
54 
55 /* This value is recommended by RFC 1035 */
56 #define DNS_RESOLVER_MIN_BUF		2
57 #define DNS_RESOLVER_BUF_CTR	(DNS_RESOLVER_MIN_BUF + \
58 				 CONFIG_LLMNR_RESOLVER_ADDITIONAL_BUF_CTR)
59 
60 #if (IS_ENABLED(CONFIG_NET_IPV6) && IS_ENABLED(CONFIG_NET_IPV4))
61 #define LLMNR_MAX_POLL 2
62 #else
63 #define LLMNR_MAX_POLL 1
64 #endif
65 
66 /* Socket polling for each server connection */
67 static struct zsock_pollfd fds[LLMNR_MAX_POLL];
68 
69 static void svc_handler(struct net_socket_service_event *pev);
70 NET_SOCKET_SERVICE_SYNC_DEFINE_STATIC(svc_llmnr, svc_handler, LLMNR_MAX_POLL);
71 
72 NET_BUF_POOL_DEFINE(llmnr_msg_pool, DNS_RESOLVER_BUF_CTR,
73 		    DNS_RESOLVER_MAX_BUF_SIZE, 0, NULL);
74 
75 #if defined(CONFIG_NET_IPV6)
create_ipv6_addr(struct sockaddr_in6 * addr)76 static void create_ipv6_addr(struct sockaddr_in6 *addr)
77 {
78 	addr->sin6_family = AF_INET6;
79 	addr->sin6_port = htons(LLMNR_LISTEN_PORT);
80 
81 	/* Well known IPv6 ff02::1:3 address */
82 	net_ipv6_addr_create(&addr->sin6_addr,
83 			     0xff02, 0, 0, 0, 0, 0, 0x01, 0x03);
84 }
85 
create_ipv6_dst_addr(struct sockaddr_in6 * src_addr,struct sockaddr_in6 * addr)86 static void create_ipv6_dst_addr(struct sockaddr_in6 *src_addr,
87 				 struct sockaddr_in6 *addr)
88 {
89 	addr->sin6_family = AF_INET6;
90 	addr->sin6_port = src_addr->sin6_port;
91 
92 	net_ipv6_addr_copy_raw((uint8_t *)&addr->sin6_addr,
93 			       (uint8_t *)&src_addr->sin6_addr);
94 }
95 #endif
96 
97 #if defined(CONFIG_NET_IPV4)
create_ipv4_addr(struct sockaddr_in * addr)98 static void create_ipv4_addr(struct sockaddr_in *addr)
99 {
100 	addr->sin_family = AF_INET;
101 	addr->sin_port = htons(LLMNR_LISTEN_PORT);
102 
103 	/* Well known IPv4 224.0.0.252 address */
104 	addr->sin_addr.s_addr = htonl(0xE00000FC);
105 }
106 
create_ipv4_dst_addr(struct sockaddr_in * src_addr,struct sockaddr_in * addr)107 static void create_ipv4_dst_addr(struct sockaddr_in *src_addr,
108 				 struct sockaddr_in *addr)
109 {
110 	addr->sin_family = AF_INET;
111 	addr->sin_port = src_addr->sin_port;
112 
113 	net_ipv4_addr_copy_raw((uint8_t *)&addr->sin_addr,
114 			       (uint8_t *)&src_addr->sin_addr);
115 }
116 #endif
117 
llmnr_iface_event_handler(struct net_mgmt_event_callback * cb,uint64_t mgmt_event,struct net_if * iface)118 static void llmnr_iface_event_handler(struct net_mgmt_event_callback *cb,
119 				      uint64_t mgmt_event, struct net_if *iface)
120 {
121 	if (mgmt_event == NET_EVENT_IF_UP) {
122 #if defined(CONFIG_NET_IPV4)
123 		int ret = net_ipv4_igmp_join(iface, &local_addr4.sin_addr, NULL);
124 
125 		if (ret < 0) {
126 			NET_DBG("Cannot add IPv4 multicast address to iface %p",
127 				iface);
128 		}
129 #endif /* defined(CONFIG_NET_IPV4) */
130 	}
131 }
132 
get_socket(sa_family_t family)133 static int get_socket(sa_family_t family)
134 {
135 	int ret;
136 
137 	ret = zsock_socket(family, SOCK_DGRAM, IPPROTO_UDP);
138 	if (ret < 0) {
139 		NET_DBG("Cannot get context (%d)", ret);
140 	}
141 
142 	return ret;
143 }
144 
bind_ctx(int sock,struct sockaddr * local_addr,socklen_t addrlen)145 static int bind_ctx(int sock,
146 		    struct sockaddr *local_addr,
147 		    socklen_t addrlen)
148 {
149 	int ret;
150 
151 	if (sock < 0) {
152 		return -EINVAL;
153 	}
154 
155 	ret = zsock_bind(sock, local_addr, addrlen);
156 	if (ret < 0) {
157 		NET_DBG("Cannot bind to %s %s port (%d)", "LLMNR",
158 			local_addr->sa_family == AF_INET ?
159 			"IPv4" : "IPv6", ret);
160 		return ret;
161 	}
162 
163 	return ret;
164 }
165 
setup_dns_hdr(uint8_t * buf,uint16_t answers,uint16_t dns_id)166 static void setup_dns_hdr(uint8_t *buf, uint16_t answers, uint16_t dns_id)
167 {
168 	uint16_t offset;
169 	uint16_t flags;
170 
171 	/* See RFC 1035, ch 4.1.1 and RFC 4795 ch 2.1.1 for header details */
172 
173 	flags = BIT(15);  /* This is response */
174 
175 	UNALIGNED_PUT(htons(dns_id), (uint16_t *)(buf));
176 	offset = DNS_HEADER_ID_LEN;
177 
178 	UNALIGNED_PUT(htons(flags), (uint16_t *)(buf+offset));
179 	offset += DNS_HEADER_FLAGS_LEN;
180 
181 	UNALIGNED_PUT(htons(1), (uint16_t *)(buf + offset));
182 	offset += DNS_QDCOUNT_LEN;
183 
184 	UNALIGNED_PUT(htons(answers), (uint16_t *)(buf + offset));
185 	offset += DNS_ANCOUNT_LEN;
186 
187 	UNALIGNED_PUT(0, (uint16_t *)(buf + offset));
188 	offset += DNS_NSCOUNT_LEN;
189 
190 	UNALIGNED_PUT(0, (uint16_t *)(buf + offset));
191 }
192 
add_question(struct net_buf * query,enum dns_rr_type qtype)193 static void add_question(struct net_buf *query, enum dns_rr_type qtype)
194 {
195 	char *dot = query->data + DNS_MSG_HEADER_SIZE;
196 	char *prev = NULL;
197 	uint16_t offset;
198 
199 	while ((dot = strchr(dot, '.'))) {
200 		if (!prev) {
201 			prev = dot++;
202 			continue;
203 		}
204 
205 		*prev = dot - prev - 1;
206 		prev = dot++;
207 	}
208 
209 	if (prev) {
210 		*prev = strlen(prev) - 1;
211 	}
212 
213 	offset = DNS_MSG_HEADER_SIZE + query->len + 1;
214 	UNALIGNED_PUT(htons(qtype), (uint16_t *)(query->data+offset));
215 
216 	offset += DNS_QTYPE_LEN;
217 	UNALIGNED_PUT(htons(DNS_CLASS_IN), (uint16_t *)(query->data+offset));
218 }
219 
add_answer(struct net_buf * query,uint32_t ttl,uint16_t addr_len,const uint8_t * addr)220 static int add_answer(struct net_buf *query, uint32_t ttl,
221 		       uint16_t addr_len, const uint8_t *addr)
222 {
223 	const uint16_t q_len = query->len + 1 + DNS_QTYPE_LEN + DNS_QCLASS_LEN;
224 	uint16_t offset = DNS_MSG_HEADER_SIZE + q_len;
225 
226 	memcpy(query->data + offset, query->data + DNS_MSG_HEADER_SIZE, q_len);
227 	offset += q_len;
228 
229 	UNALIGNED_PUT(htonl(ttl), query->data + offset);
230 	offset += DNS_TTL_LEN;
231 
232 	UNALIGNED_PUT(htons(addr_len), query->data + offset);
233 	offset += DNS_RDLENGTH_LEN;
234 
235 	memcpy(query->data + offset, addr, addr_len);
236 
237 	return offset + addr_len;
238 }
239 
create_answer(enum dns_rr_type qtype,struct net_buf * query,uint16_t dns_id,uint16_t addr_len,const uint8_t * addr)240 static int create_answer(enum dns_rr_type qtype,
241 			 struct net_buf *query,
242 			 uint16_t dns_id,
243 			 uint16_t addr_len, const uint8_t *addr)
244 {
245 	/* Prepare the response into the query buffer: move the name
246 	 * query buffer has to get enough free space: dns_hdr + query + answer
247 	 */
248 	if ((net_buf_max_len(query) - query->len) < (DNS_MSG_HEADER_SIZE +
249 					  (DNS_QTYPE_LEN + DNS_QCLASS_LEN) * 2 +
250 					  DNS_TTL_LEN + DNS_RDLENGTH_LEN +
251 					  addr_len + query->len)) {
252 		return -ENOBUFS;
253 	}
254 
255 	memmove(query->data + DNS_MSG_HEADER_SIZE, query->data, query->len);
256 
257 	setup_dns_hdr(query->data, 1, dns_id);
258 
259 	add_question(query, qtype);
260 
261 	query->len = add_answer(query, LLMNR_TTL, addr_len, addr);
262 
263 	return 0;
264 }
265 
266 #if defined(CONFIG_NET_IPV4)
get_ipv4_src(struct net_if * iface,struct in_addr * dst)267 static const uint8_t *get_ipv4_src(struct net_if *iface, struct in_addr *dst)
268 {
269 	const struct in_addr *addr;
270 
271 	addr = net_if_ipv4_select_src_addr(iface, dst);
272 	if (!addr || net_ipv4_is_addr_unspecified(addr)) {
273 		return NULL;
274 	}
275 
276 	return (const uint8_t *)addr;
277 }
278 #endif
279 
280 #if defined(CONFIG_NET_IPV6)
get_ipv6_src(struct net_if * iface,struct in6_addr * dst)281 static const uint8_t *get_ipv6_src(struct net_if *iface, struct in6_addr *dst)
282 {
283 	const struct in6_addr *addr;
284 
285 	addr = net_if_ipv6_select_src_addr(iface, dst);
286 	if (!addr || net_ipv6_is_addr_unspecified(addr)) {
287 		return NULL;
288 	}
289 
290 	return (const uint8_t *)addr;
291 }
292 #endif
293 
set_ttl_hop_limit(int sock,int level,int option,int new_limit)294 static int set_ttl_hop_limit(int sock, int level, int option, int new_limit)
295 {
296 	return zsock_setsockopt(sock, level, option, &new_limit, sizeof(new_limit));
297 }
298 
299 #if defined(CONFIG_NET_IPV4)
create_ipv4_answer(int sock,struct sockaddr_in * src_addr,enum dns_rr_type qtype,struct net_buf * query,uint16_t dns_id,struct sockaddr * dst,socklen_t * dst_len)300 static int create_ipv4_answer(int sock,
301 			      struct sockaddr_in *src_addr,
302 			      enum dns_rr_type qtype,
303 			      struct net_buf *query,
304 			      uint16_t dns_id,
305 			      struct sockaddr *dst,
306 			      socklen_t *dst_len)
307 {
308 	const uint8_t *addr;
309 	int addr_len;
310 
311 	create_ipv4_dst_addr(src_addr, net_sin(dst));
312 
313 	*dst_len = sizeof(struct sockaddr_in);
314 
315 	/* Select proper address according to destination */
316 	addr = get_ipv4_src(NULL, &net_sin(dst)->sin_addr);
317 	if (!addr) {
318 		return -ENOENT;
319 	}
320 
321 	addr_len = sizeof(struct in_addr);
322 
323 	if (create_answer(qtype, query, dns_id, addr_len, addr)) {
324 		return -ENOMEM;
325 	}
326 
327 	(void)set_ttl_hop_limit(sock, IPPROTO_IP, IP_MULTICAST_TTL, 255);
328 
329 	return 0;
330 }
331 #endif /* CONFIG_NET_IPV4 */
332 
create_ipv6_answer(int sock,struct sockaddr_in6 * src_addr,enum dns_rr_type qtype,struct net_buf * query,uint16_t dns_id,struct sockaddr * dst,socklen_t * dst_len)333 static int create_ipv6_answer(int sock,
334 			      struct sockaddr_in6 *src_addr,
335 			      enum dns_rr_type qtype,
336 			      struct net_buf *query,
337 			      uint16_t dns_id,
338 			      struct sockaddr *dst,
339 			      socklen_t *dst_len)
340 {
341 #if defined(CONFIG_NET_IPV6)
342 	const uint8_t *addr;
343 	int addr_len;
344 
345 	create_ipv6_dst_addr(src_addr, net_sin6(dst));
346 
347 	*dst_len = sizeof(struct sockaddr_in6);
348 
349 	addr = get_ipv6_src(NULL, &src_addr->sin6_addr);
350 	if (!addr) {
351 		return -ENOENT;
352 	}
353 
354 	addr_len = sizeof(struct in6_addr);
355 
356 	if (create_answer(qtype, query, dns_id, addr_len, addr)) {
357 		return -ENOMEM;
358 	}
359 
360 	(void)set_ttl_hop_limit(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 255);
361 
362 #endif /* CONFIG_NET_IPV6 */
363 	return 0;
364 }
365 
send_response(int sock,struct sockaddr * src_addr,size_t addrlen,struct net_buf * reply,enum dns_rr_type qtype,uint16_t dns_id)366 static int send_response(int sock,
367 			 struct sockaddr *src_addr,
368 			 size_t addrlen,
369 			 struct net_buf *reply,
370 			 enum dns_rr_type qtype,
371 			 uint16_t dns_id)
372 {
373 	socklen_t dst_len;
374 	int ret;
375 	COND_CODE_1(IS_ENABLED(CONFIG_NET_IPV6),
376 		    (struct sockaddr_in6), (struct sockaddr_in)) dst;
377 
378 	if (IS_ENABLED(CONFIG_NET_IPV4) && src_addr->sa_family == AF_INET) {
379 		ret = create_ipv4_answer(sock, (struct sockaddr_in *)src_addr,
380 					 qtype, reply, dns_id,
381 					 (struct sockaddr *)&dst, &dst_len);
382 		if (ret < 0) {
383 			return ret;
384 		}
385 	} else if (IS_ENABLED(CONFIG_NET_IPV6) && src_addr->sa_family == AF_INET6) {
386 		ret = create_ipv6_answer(sock, (struct sockaddr_in6 *)src_addr,
387 					 qtype, reply, dns_id,
388 					 (struct sockaddr *)&dst, &dst_len);
389 		if (ret < 0) {
390 			return ret;
391 		}
392 	} else {
393 		/* TODO: support also service PTRs */
394 		return -EPFNOSUPPORT;
395 	}
396 
397 	ret = zsock_sendto(sock, reply->data, reply->len, 0,
398 			   (struct sockaddr *)&dst, dst_len);
399 	if (ret < 0) {
400 		NET_DBG("Cannot send %s reply to %s (%d)", "LLMNR",
401 			src_addr->sa_family == AF_INET ?
402 			net_sprint_ipv4_addr(&net_sin((struct sockaddr *)&dst)->sin_addr) :
403 			net_sprint_ipv6_addr(&net_sin6((struct sockaddr *)&dst)->sin6_addr),
404 			ret);
405 	} else {
406 		struct net_if *iface = NULL;
407 		struct sockaddr *addr = (struct sockaddr *)&dst;
408 
409 		if (IS_ENABLED(CONFIG_NET_IPV6) && src_addr->sa_family == AF_INET6) {
410 			iface = net_if_ipv6_select_src_iface(&net_sin6(addr)->sin6_addr);
411 		} else if (IS_ENABLED(CONFIG_NET_IPV4) && src_addr->sa_family == AF_INET) {
412 			iface = net_if_ipv4_select_src_iface(&net_sin(addr)->sin_addr);
413 		}
414 
415 		if (iface != NULL) {
416 			net_stats_update_dns_sent(iface);
417 		}
418 	}
419 
420 	return ret;
421 }
422 
dns_read(int sock,struct net_buf * dns_data,size_t len,struct sockaddr * src_addr,size_t addrlen,struct dns_addrinfo * info)423 static int dns_read(int sock,
424 		    struct net_buf *dns_data,
425 		    size_t len,
426 		    struct sockaddr *src_addr,
427 		    size_t addrlen,
428 		    struct dns_addrinfo *info)
429 {
430 	/* Helper struct to track the dns msg received from the server */
431 	const char *hostname = net_hostname_get();
432 	int hostname_len = strlen(hostname);
433 	struct net_buf *result;
434 	struct dns_msg_t dns_msg;
435 	uint16_t dns_id = 0U;
436 	socklen_t optlen;
437 	int data_len;
438 	int queries;
439 	int family;
440 	int ret;
441 
442 	data_len = MIN(len, DNS_RESOLVER_MAX_BUF_SIZE);
443 
444 	/* Store the DNS query name into a temporary net_buf, which will be
445 	 * eventually used to send a response
446 	 */
447 	result = net_buf_alloc(&llmnr_msg_pool, BUF_ALLOC_TIMEOUT);
448 	if (!result) {
449 		ret = -ENOMEM;
450 		goto quit;
451 	}
452 
453 	dns_msg.msg = dns_data->data;
454 	dns_msg.msg_size = data_len;
455 
456 	ret = llmnr_unpack_query_header(&dns_msg, &dns_id);
457 	if (ret < 0) {
458 		ret = -EINVAL;
459 		goto quit;
460 	}
461 
462 	queries = ret;
463 
464 	optlen = sizeof(int);
465 	(void)zsock_getsockopt(sock, SOL_SOCKET, SO_DOMAIN, &family, &optlen);
466 
467 	NET_DBG("Received %d %s from %s (id 0x%04x)", queries,
468 		queries > 1 ? "queries" : "query",
469 		family == AF_INET ?
470 		net_sprint_ipv4_addr(&net_sin(src_addr)->sin_addr) :
471 		net_sprint_ipv6_addr(&net_sin6(src_addr)->sin6_addr),
472 		dns_id);
473 
474 	do {
475 		enum dns_rr_type qtype;
476 		enum dns_class qclass;
477 
478 		(void)memset(result->data, 0, net_buf_max_len(result));
479 		result->len = 0U;
480 
481 		ret = dns_unpack_query(&dns_msg, result, &qtype, &qclass);
482 		if (ret < 0) {
483 			goto quit;
484 		}
485 
486 		NET_DBG("[%d] query %s/%s label %s (%d bytes)", queries,
487 			dns_qtype_to_str(qtype), "IN",
488 			result->data, ret);
489 
490 		/* If the query matches to our hostname, then send reply */
491 		if (!strncasecmp(hostname, result->data + 1, hostname_len) &&
492 		    (result->len - 1) >= hostname_len) {
493 			NET_DBG("%s query to our hostname %s", "LLMNR",
494 				hostname);
495 			ret = send_response(sock, src_addr, addrlen, result, qtype,
496 					    dns_id);
497 			if (ret < 0) {
498 				NET_DBG("Cannot send response (%d)", ret);
499 			}
500 		}
501 	} while (--queries);
502 
503 	ret = 0;
504 
505 quit:
506 	if (result) {
507 		net_buf_unref(result);
508 	}
509 
510 	return ret;
511 }
512 
recv_data(struct net_socket_service_event * pev)513 static int recv_data(struct net_socket_service_event *pev)
514 {
515 	COND_CODE_1(IS_ENABLED(CONFIG_NET_IPV6),
516 		    (struct sockaddr_in6), (struct sockaddr_in)) addr;
517 	struct net_buf *dns_data = NULL;
518 	struct dns_addrinfo info = { 0 };
519 	size_t addrlen = sizeof(addr);
520 	int ret, family = AF_UNSPEC, sock_error, len;
521 	socklen_t optlen;
522 
523 	if ((pev->event.revents & ZSOCK_POLLERR) ||
524 	    (pev->event.revents & ZSOCK_POLLNVAL)) {
525 		(void)zsock_getsockopt(pev->event.fd, SOL_SOCKET,
526 				       SO_DOMAIN, &family, &optlen);
527 		(void)zsock_getsockopt(pev->event.fd, SOL_SOCKET,
528 				       SO_ERROR, &sock_error, &optlen);
529 		NET_ERR("Receiver IPv%d socket error (%d)",
530 			family == AF_INET ? 4 : 6, sock_error);
531 		ret = DNS_EAI_SYSTEM;
532 		goto quit;
533 	}
534 
535 	dns_data = net_buf_alloc(&llmnr_msg_pool, BUF_ALLOC_TIMEOUT);
536 	if (!dns_data) {
537 		ret = -ENOENT;
538 		goto quit;
539 	}
540 
541 	ret = zsock_recvfrom(pev->event.fd, dns_data->data,
542 			     net_buf_max_len(dns_data), 0,
543 			     (struct sockaddr *)&addr, &addrlen);
544 	if (ret < 0) {
545 		ret = -errno;
546 		NET_ERR("recv failed on IPv%d socket (%d)",
547 			family == AF_INET ? 4 : 6, -ret);
548 		goto free_buf;
549 	}
550 
551 	len = ret;
552 
553 	ret = dns_read(pev->event.fd, dns_data, len,
554 		       (struct sockaddr *)&addr, addrlen, &info);
555 	if (ret < 0 && ret != -EINVAL) {
556 		NET_DBG("%s read failed (%d)", "LLMNR", ret);
557 	}
558 
559 free_buf:
560 	net_buf_unref(dns_data);
561 
562 quit:
563 	return ret;
564 }
565 
svc_handler(struct net_socket_service_event * pev)566 static void svc_handler(struct net_socket_service_event *pev)
567 {
568 	int ret;
569 
570 	ret = recv_data(pev);
571 	if (ret < 0) {
572 		NET_ERR("DNS recv error (%d)", ret);
573 	}
574 }
575 
576 #if defined(CONFIG_NET_IPV6)
iface_ipv6_cb(struct net_if * iface,void * user_data)577 static void iface_ipv6_cb(struct net_if *iface, void *user_data)
578 {
579 	struct in6_addr *addr = user_data;
580 	int ret;
581 
582 	ret = net_ipv6_mld_join(iface, addr);
583 	if (ret < 0) {
584 		NET_DBG("Cannot join %s IPv6 multicast group to iface %d (%d)",
585 			net_sprint_ipv6_addr(addr),
586 			net_if_get_by_iface(iface),
587 			ret);
588 	}
589 }
590 
setup_ipv6_addr(struct sockaddr_in6 * local_addr)591 static void setup_ipv6_addr(struct sockaddr_in6 *local_addr)
592 {
593 	create_ipv6_addr(local_addr);
594 
595 	net_if_foreach(iface_ipv6_cb, &local_addr->sin6_addr);
596 }
597 #endif /* CONFIG_NET_IPV6 */
598 
599 #if defined(CONFIG_NET_IPV4)
iface_ipv4_cb(struct net_if * iface,void * user_data)600 static void iface_ipv4_cb(struct net_if *iface, void *user_data)
601 {
602 	struct in_addr *addr = user_data;
603 	int ret;
604 
605 	ret = net_ipv4_igmp_join(iface, addr, NULL);
606 	if (ret < 0) {
607 		NET_DBG("Cannot add %s multicast address to iface %d", "IPv4",
608 			net_if_get_by_iface(iface));
609 	}
610 }
611 
setup_ipv4_addr(struct sockaddr_in * local_addr)612 static void setup_ipv4_addr(struct sockaddr_in *local_addr)
613 {
614 	create_ipv4_addr(local_addr);
615 
616 	net_if_foreach(iface_ipv4_cb, &local_addr->sin_addr);
617 }
618 #endif /* CONFIG_NET_IPV4 */
619 
init_listener(void)620 static int init_listener(void)
621 {
622 	int ret, ok = 0;
623 
624 	ARRAY_FOR_EACH(fds, j) {
625 		fds[j].fd = -1;
626 	}
627 
628 #if defined(CONFIG_NET_IPV6)
629 	{
630 		static struct sockaddr_in6 local_addr;
631 
632 		setup_ipv6_addr(&local_addr);
633 
634 		ipv6 = get_socket(AF_INET6);
635 
636 		ret = bind_ctx(ipv6, (struct sockaddr *)&local_addr,
637 			       sizeof(local_addr));
638 		if (ret < 0) {
639 			zsock_close(ipv6);
640 			goto ipv6_out;
641 		}
642 
643 		ret = -ENOENT;
644 
645 		ARRAY_FOR_EACH(fds, j) {
646 			if (fds[j].fd == ipv6) {
647 				ret = 0;
648 				break;
649 			}
650 
651 			if (fds[j].fd < 0) {
652 				fds[j].fd = ipv6;
653 				fds[j].events = ZSOCK_POLLIN;
654 				ret = 0;
655 				break;
656 			}
657 		}
658 
659 		if (ret < 0) {
660 			NET_DBG("Cannot set %s to socket (%d)", "polling", ret);
661 			zsock_close(ipv6);
662 			goto ipv6_out;
663 		}
664 
665 		ret = net_socket_service_register(&svc_llmnr, fds, ARRAY_SIZE(fds), NULL);
666 		if (ret < 0) {
667 			NET_DBG("Cannot register %s %s socket service (%d)",
668 				"IPv6", "LLMNR", ret);
669 			zsock_close(ipv6);
670 		} else {
671 			ok++;
672 		}
673 	}
674 ipv6_out:
675 #endif /* CONFIG_NET_IPV6 */
676 
677 #if defined(CONFIG_NET_IPV4)
678 	{
679 		setup_ipv4_addr(&local_addr4);
680 
681 		ipv4 = get_socket(AF_INET);
682 
683 		ret = bind_ctx(ipv4, (struct sockaddr *)&local_addr4,
684 			       sizeof(local_addr4));
685 		if (ret < 0) {
686 			zsock_close(ipv4);
687 			goto ipv4_out;
688 		}
689 
690 		ret = -ENOENT;
691 
692 		ARRAY_FOR_EACH(fds, j) {
693 			if (fds[j].fd == ipv4) {
694 				ret = 0;
695 				break;
696 			}
697 
698 			if (fds[j].fd < 0) {
699 				fds[j].fd = ipv4;
700 				fds[j].events = ZSOCK_POLLIN;
701 				ret = 0;
702 				break;
703 			}
704 		}
705 
706 		if (ret < 0) {
707 			NET_DBG("Cannot set %s to socket (%d)", "polling", ret);
708 			zsock_close(ipv4);
709 			goto ipv4_out;
710 		}
711 
712 		ret = net_socket_service_register(&svc_llmnr, fds, ARRAY_SIZE(fds), NULL);
713 		if (ret < 0) {
714 			NET_DBG("Cannot register %s %s socket service (%d)",
715 				"IPv4", "LLMNR", ret);
716 			zsock_close(ipv4);
717 		} else {
718 			ok++;
719 		}
720 	}
721 ipv4_out:
722 #endif /* CONFIG_NET_IPV4 */
723 
724 	if (!ok) {
725 		NET_WARN("Cannot start %s responder", "LLMNR");
726 	}
727 
728 	return !ok;
729 }
730 
llmnr_responder_init(void)731 static int llmnr_responder_init(void)
732 {
733 	net_mgmt_init_event_callback(&mgmt_cb, llmnr_iface_event_handler,
734 				     NET_EVENT_IF_UP);
735 
736 	net_mgmt_add_event_callback(&mgmt_cb);
737 
738 	return init_listener();
739 }
740 
741 SYS_INIT(llmnr_responder_init, APPLICATION, CONFIG_LLMNR_RESPONDER_INIT_PRIO);
742