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