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