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