1 /*
2 * Copyright 2025 NXP
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "openthread/platform/mdns_socket.h"
8 #include <openthread/nat64.h>
9 #include <openthread/platform/messagepool.h>
10 #include "openthread/instance.h"
11 #include "openthread_border_router.h"
12 #include "platform-zephyr.h"
13 #include <common/code_utils.hpp>
14 #include <zephyr/net/mld.h>
15 #include <zephyr/net/net_context.h>
16 #include <zephyr/net/socket.h>
17 #include <zephyr/net/net_if.h>
18 #include <zephyr/net/net_ip.h>
19 #include <zephyr/net/net_pkt.h>
20 #include <zephyr/net/openthread.h>
21 #include <zephyr/net/socket_service.h>
22 #include "sockets_internal.h"
23 #include <errno.h>
24
25 #define MULTICAST_PORT 5353
26 #define MAX_SERVICES CONFIG_OPENTHREAD_ZEPHYR_BORDER_ROUTER_MAX_MDNS_SERVICES
27 #define PKT_THRESHOLD_VAL CONFIG_OPENTHREAD_ZEPHYR_BORDER_ROUTER_MDNS_BUFFER_THRESHOLD
28
29 static struct zsock_pollfd sockfd_udp[MAX_SERVICES];
30 static int mdns_sock_v6 = -1;
31 #if defined(CONFIG_NET_IPV4)
32 static int mdns_sock_v4 = -1;
33 #endif /* CONFIG_NET_IPV4 */
34 static struct otInstance *ot_instance_ptr;
35 static uint32_t ail_iface_index;
36 static bool mdns_socket_is_enabled;
37
38 static otError mdns_socket_init_v6(uint32_t ail_iface_idx);
39 #if defined(CONFIG_NET_IPV4)
40 static otError mdns_socket_init_v4(uint32_t ail_iface_idx);
41 #endif /* CONFIG_NET_IPV4 */
42 static otError mdns_socket_deinit(void);
43 static otError set_listening_enable(otInstance *instance, bool enable, uint32_t ail_iface_idx);
44 static void mdns_send_multicast(otMessage *message, uint32_t ail_iface_idx);
45 static void mdns_send_unicast(otMessage *message, const otPlatMdnsAddressInfo *aAddress);
46 static void mdns_receive_handler(struct net_socket_service_event *evt);
47 static void process_mdns_message(struct otbr_msg_ctx *msg_ctx_ptr);
48
49 NET_SOCKET_SERVICE_SYNC_DEFINE_STATIC(mdns_udp_service, mdns_receive_handler, MAX_SERVICES);
50
mdns_plat_socket_init(otInstance * ot_instance,uint32_t ail_iface_idx)51 otError mdns_plat_socket_init(otInstance *ot_instance, uint32_t ail_iface_idx)
52 {
53 ot_instance_ptr = ot_instance;
54 ail_iface_index = ail_iface_idx;
55
56 return OT_ERROR_NONE;
57 }
58
otPlatMdnsSetListeningEnabled(otInstance * aInstance,bool aEnable,uint32_t aInfraIfIndex)59 otError otPlatMdnsSetListeningEnabled(otInstance *aInstance, bool aEnable, uint32_t aInfraIfIndex)
60 {
61 return set_listening_enable(aInstance, aEnable, aInfraIfIndex);
62 }
63
otPlatMdnsSendMulticast(otInstance * aInstance,otMessage * aMessage,uint32_t aInfraIfIndex)64 void otPlatMdnsSendMulticast(otInstance *aInstance, otMessage *aMessage, uint32_t aInfraIfIndex)
65 {
66 OT_UNUSED_VARIABLE(aInstance);
67
68 mdns_send_multicast(aMessage, aInfraIfIndex);
69 }
70
otPlatMdnsSendUnicast(otInstance * aInstance,otMessage * aMessage,const otPlatMdnsAddressInfo * aAddress)71 void otPlatMdnsSendUnicast(otInstance *aInstance, otMessage *aMessage,
72 const otPlatMdnsAddressInfo *aAddress)
73 {
74 OT_UNUSED_VARIABLE(aInstance);
75
76 mdns_send_unicast(aMessage, aAddress);
77 }
78
set_listening_enable(otInstance * instance,bool enable,uint32_t ail_iface_idx)79 static otError set_listening_enable(otInstance *instance, bool enable, uint32_t ail_iface_idx)
80 {
81 OT_UNUSED_VARIABLE(instance);
82 otError error = OT_ERROR_NONE;
83
84 if (enable) {
85 SuccessOrExit(error = mdns_socket_init_v6(ail_iface_idx));
86 #if defined(CONFIG_NET_IPV4)
87 SuccessOrExit(error = mdns_socket_init_v4(ail_iface_idx));
88 #endif /* CONFIG_NET_IPV4 */
89 mdns_socket_is_enabled = true;
90 mdns_plat_monitor_interface(net_if_get_by_index(ail_iface_idx));
91 ExitNow();
92 }
93
94 SuccessOrExit(error = mdns_socket_deinit());
95 mdns_socket_is_enabled = false;
96 exit:
97 return error;
98
99 }
100
mdns_socket_init_v6(uint32_t ail_iface_idx)101 static otError mdns_socket_init_v6(uint32_t ail_iface_idx)
102 {
103 otError error = OT_ERROR_NONE;
104 char name[CONFIG_NET_INTERFACE_NAME_LEN + 1] = {0};
105 struct net_ifreq if_req = {0};
106 struct net_ipv6_mreq mreq_v6 = {0};
107 int mcast_hops = 255;
108 int on = 1;
109 int mcast_join_ret = 0;
110
111 struct net_sockaddr_in6 addr = {.sin6_family = NET_AF_INET6,
112 .sin6_port = net_htons(MULTICAST_PORT),
113 .sin6_addr = {{{0}}},
114 .sin6_scope_id = 0};
115
116 mdns_sock_v6 = zsock_socket(NET_AF_INET6, NET_SOCK_DGRAM, NET_IPPROTO_UDP);
117 VerifyOrExit(mdns_sock_v6 >= 0, error = OT_ERROR_FAILED);
118 VerifyOrExit(net_if_get_name(net_if_get_by_index(ail_iface_idx), name,
119 CONFIG_NET_INTERFACE_NAME_LEN) > 0,
120 error = OT_ERROR_FAILED);
121 memcpy(if_req.ifr_name, name, MIN(sizeof(name) - 1, sizeof(if_req.ifr_name) - 1));
122 VerifyOrExit(zsock_setsockopt(mdns_sock_v6, ZSOCK_SOL_SOCKET, ZSOCK_SO_BINDTODEVICE,
123 &if_req, sizeof(if_req)) == 0,
124 error = OT_ERROR_FAILED);
125 VerifyOrExit(zsock_setsockopt(mdns_sock_v6, ZSOCK_SOL_SOCKET, ZSOCK_SO_REUSEADDR,
126 &on, sizeof(on)) == 0,
127 error = OT_ERROR_FAILED);
128 VerifyOrExit(zsock_setsockopt(mdns_sock_v6, ZSOCK_SOL_SOCKET, ZSOCK_SO_REUSEPORT,
129 &on, sizeof(on)) == 0,
130 error = OT_ERROR_FAILED);
131 VerifyOrExit(zsock_setsockopt(mdns_sock_v6, NET_IPPROTO_IPV6, ZSOCK_IPV6_V6ONLY, &on,
132 sizeof(on)) == 0,
133 error = OT_ERROR_FAILED);
134 mreq_v6.ipv6mr_ifindex = ail_iface_idx;
135 net_ipv6_addr_create(&mreq_v6.ipv6mr_multiaddr, 0xff02, 0, 0, 0, 0, 0, 0, 0x00fb);
136 mcast_join_ret = zsock_setsockopt(mdns_sock_v6, NET_IPPROTO_IPV6, ZSOCK_IPV6_ADD_MEMBERSHIP,
137 &mreq_v6, sizeof(mreq_v6));
138 VerifyOrExit(mcast_join_ret == 0 || (mcast_join_ret == -1 && errno == EALREADY),
139 error = OT_ERROR_FAILED);
140 VerifyOrExit(zsock_setsockopt(mdns_sock_v6, NET_IPPROTO_IPV6, ZSOCK_IPV6_MULTICAST_LOOP,
141 &on, sizeof(on)) == 0,
142 error = OT_ERROR_FAILED);
143 VerifyOrExit(zsock_setsockopt(mdns_sock_v6, NET_IPPROTO_IPV6, ZSOCK_IPV6_MULTICAST_IF,
144 &ail_iface_index, sizeof(ail_iface_index)) == 0,
145 error = OT_ERROR_FAILED);
146 VerifyOrExit(zsock_setsockopt(mdns_sock_v6, NET_IPPROTO_IPV6, ZSOCK_IPV6_MULTICAST_HOPS,
147 &mcast_hops, sizeof(mcast_hops)) == 0,
148 error = OT_ERROR_FAILED);
149 VerifyOrExit(zsock_setsockopt(mdns_sock_v6, NET_IPPROTO_IPV6, ZSOCK_IPV6_UNICAST_HOPS,
150 &mcast_hops, sizeof(mcast_hops)) == 0,
151 error = OT_ERROR_FAILED);
152 VerifyOrExit(zsock_bind(mdns_sock_v6, (struct net_sockaddr *)&addr, sizeof(addr)) == 0,
153 error = OT_ERROR_FAILED);
154
155 sockfd_udp[0].fd = mdns_sock_v6;
156 sockfd_udp[0].events = ZSOCK_POLLIN;
157
158 VerifyOrExit(net_socket_service_register(&mdns_udp_service, sockfd_udp,
159 ARRAY_SIZE(sockfd_udp), NULL) == 0,
160 error = OT_ERROR_FAILED);
161
162 exit:
163 return error;
164 }
165
166 #if defined(CONFIG_NET_IPV4)
mdns_socket_init_v4(uint32_t ail_iface_idx)167 static otError mdns_socket_init_v4(uint32_t ail_iface_idx)
168 {
169 otError error = OT_ERROR_NONE;
170 char name[CONFIG_NET_INTERFACE_NAME_LEN + 1] = {0};
171 struct net_ifreq if_req = {0};
172 struct net_ip_mreqn mreq_v4 = {0};
173 int mcast_hops = 255;
174 int on = 1;
175 int mcast_join_ret = 0;
176
177 struct net_sockaddr_in addr = {.sin_family = NET_AF_INET,
178 .sin_port = net_htons(MULTICAST_PORT),
179 .sin_addr = {{{0}}}};
180
181 mdns_sock_v4 = zsock_socket(NET_AF_INET, NET_SOCK_DGRAM, NET_IPPROTO_UDP);
182 VerifyOrExit(mdns_sock_v4 >= 0, error = OT_ERROR_FAILED);
183 VerifyOrExit(net_if_get_name(net_if_get_by_index(ail_iface_idx), name,
184 CONFIG_NET_INTERFACE_NAME_LEN) > 0,
185 error = OT_ERROR_FAILED);
186 memcpy(if_req.ifr_name, name, MIN(sizeof(name) - 1, sizeof(if_req.ifr_name) - 1));
187 VerifyOrExit(zsock_setsockopt(mdns_sock_v4, ZSOCK_SOL_SOCKET, ZSOCK_SO_BINDTODEVICE,
188 &if_req, sizeof(if_req)) == 0,
189 error = OT_ERROR_FAILED);
190 VerifyOrExit(zsock_setsockopt(mdns_sock_v4, ZSOCK_SOL_SOCKET, ZSOCK_SO_REUSEADDR,
191 &on, sizeof(on)) == 0,
192 error = OT_ERROR_FAILED);
193 VerifyOrExit(zsock_setsockopt(mdns_sock_v4, ZSOCK_SOL_SOCKET, ZSOCK_SO_REUSEPORT,
194 &on, sizeof(on)) == 0,
195 error = OT_ERROR_FAILED);
196 mreq_v4.imr_ifindex = ail_iface_idx;
197 mreq_v4.imr_multiaddr.s_addr = net_htonl(0xE00000FB);
198 mcast_join_ret = zsock_setsockopt(mdns_sock_v4, NET_IPPROTO_IP, ZSOCK_IP_ADD_MEMBERSHIP,
199 &mreq_v4, sizeof(mreq_v4));
200 VerifyOrExit(mcast_join_ret == 0 || (mcast_join_ret == -1 && errno == EALREADY),
201 error = OT_ERROR_FAILED);
202 VerifyOrExit(zsock_setsockopt(mdns_sock_v4, NET_IPPROTO_IP, ZSOCK_IP_MULTICAST_LOOP,
203 &on, sizeof(on)) == 0,
204 error = OT_ERROR_FAILED);
205 VerifyOrExit(zsock_setsockopt(mdns_sock_v4, NET_IPPROTO_IP, ZSOCK_IP_MULTICAST_IF,
206 &mreq_v4, sizeof(mreq_v4)) == 0,
207 error = OT_ERROR_FAILED);
208 VerifyOrExit(zsock_setsockopt(mdns_sock_v4, NET_IPPROTO_IP, ZSOCK_IP_MULTICAST_TTL,
209 &mcast_hops, sizeof(mcast_hops)) == 0,
210 error = OT_ERROR_FAILED);
211 VerifyOrExit(zsock_setsockopt(mdns_sock_v4, NET_IPPROTO_IP, ZSOCK_IP_TTL,
212 &mcast_hops, sizeof(mcast_hops)) == 0,
213 error = OT_ERROR_FAILED);
214 VerifyOrExit(zsock_bind(mdns_sock_v4, (struct net_sockaddr *)&addr, sizeof(addr)) == 0,
215 error = OT_ERROR_FAILED);
216
217 sockfd_udp[1].fd = mdns_sock_v4;
218 sockfd_udp[1].events = ZSOCK_POLLIN;
219
220 VerifyOrExit(net_socket_service_register(&mdns_udp_service, sockfd_udp,
221 ARRAY_SIZE(sockfd_udp), NULL) == 0,
222 error = OT_ERROR_FAILED);
223
224 exit:
225 return error;
226 }
227 #endif /* CONFIG_NET_IPV4 */
228
mdns_socket_deinit(void)229 static otError mdns_socket_deinit(void)
230 {
231 otError error = OT_ERROR_NONE;
232
233 VerifyOrExit(mdns_sock_v6 != -1, error = OT_ERROR_INVALID_STATE);
234 VerifyOrExit(zsock_close(mdns_sock_v6) == 0, error = OT_ERROR_FAILED);
235
236 sockfd_udp[0].fd = -1;
237 mdns_sock_v6 = -1;
238
239 #if defined(CONFIG_NET_IPV4)
240 VerifyOrExit(mdns_sock_v4 != -1, error = OT_ERROR_INVALID_STATE);
241 VerifyOrExit(zsock_close(mdns_sock_v4) == 0, error = OT_ERROR_FAILED);
242
243 sockfd_udp[1].fd = -1;
244 mdns_sock_v4 = -1;
245 #endif /* CONFIG_NET_IPV4 */
246
247 VerifyOrExit(net_socket_service_register(&mdns_udp_service, sockfd_udp,
248 ARRAY_SIZE(sockfd_udp), NULL) == 0,
249 error = OT_ERROR_FAILED);
250 exit:
251 return error;
252 }
253
mdns_send_multicast(otMessage * message,uint32_t ail_iface_idx)254 static void mdns_send_multicast(otMessage *message, uint32_t ail_iface_idx)
255 {
256 uint16_t length = otMessageGetLength(message);
257 struct otbr_msg_ctx *req = NULL;
258 struct net_sockaddr_in6 addr_v6 = {.sin6_family = NET_AF_INET6,
259 .sin6_port = net_htons(MULTICAST_PORT),
260 .sin6_addr = NET_IN6ADDR_ANY_INIT,
261 .sin6_scope_id = 0};
262 #if defined(CONFIG_NET_IPV4)
263 struct net_sockaddr_in addr_v4 = {.sin_family = NET_AF_INET,
264 .sin_port = net_htons(MULTICAST_PORT),
265 .sin_addr = NET_INADDR_ANY_INIT};
266 #endif /* CONFIG_NET_IPV4*/
267
268 VerifyOrExit(length <= OTBR_MESSAGE_SIZE);
269 VerifyOrExit(openthread_border_router_allocate_message((void **)&req) == OT_ERROR_NONE);
270
271 net_ipv6_addr_create(&addr_v6.sin6_addr, 0xff02, 0, 0, 0, 0, 0, 0, 0x00fb);
272 #if defined(CONFIG_NET_IPV4)
273 addr_v4.sin_addr.s_addr = net_htonl(0xE00000FB);
274 #endif /* CONFIG_NET_IPV4 */
275
276 VerifyOrExit(otMessageRead(message, 0, req->buffer, length) == length);
277
278 VerifyOrExit(zsock_sendto(mdns_sock_v6, req->buffer, length, 0,
279 (struct net_sockaddr *)&addr_v6,
280 sizeof(addr_v6)) > 0);
281 #if defined(CONFIG_NET_IPV4)
282 VerifyOrExit(zsock_sendto(mdns_sock_v4, req->buffer, length, 0,
283 (struct net_sockaddr *)&addr_v4,
284 sizeof(addr_v4)) > 0);
285 #endif /* CONFIG_NET_IPV4 */
286 exit:
287 otMessageFree(message);
288 if (req != NULL) {
289 openthread_border_router_deallocate_message((void *)req);
290 }
291 }
292
mdns_send_unicast(otMessage * message,const otPlatMdnsAddressInfo * aAddress)293 static void mdns_send_unicast(otMessage *message, const otPlatMdnsAddressInfo *aAddress)
294 {
295 uint16_t length = otMessageGetLength(message);
296 struct otbr_msg_ctx *req = NULL;
297 otIp4Address ot_ipv4_addr = {0};
298 #if defined(CONFIG_NET_IPV4)
299 bool send_ipv4 = false;
300 struct net_sockaddr_in addr_v4 = {0};
301 #endif /* CONFIG_NET_IPV4*/
302 struct net_sockaddr_in6 addr_v6 = {.sin6_family = NET_AF_INET6,
303 .sin6_port = net_htons(aAddress->mPort),
304 .sin6_addr = NET_IN6ADDR_ANY_INIT,
305 .sin6_scope_id = 0};
306
307 VerifyOrExit(length <= OTBR_MESSAGE_SIZE);
308 VerifyOrExit(openthread_border_router_allocate_message((void **)&req) == OT_ERROR_NONE);
309 #if defined(CONFIG_NET_IPV4)
310 if (otIp4FromIp4MappedIp6Address(&aAddress->mAddress, &ot_ipv4_addr) == OT_ERROR_NONE) {
311 addr_v4.sin_family = NET_AF_INET;
312 addr_v4.sin_port = net_htons(aAddress->mPort);
313 memcpy(&addr_v4.sin_addr.s_addr, &ot_ipv4_addr, sizeof(otIp4Address));
314 send_ipv4 = true;
315 }
316 #endif /* CONFIG_NET_IPV4 */
317 memcpy(&addr_v6.sin6_addr, &aAddress->mAddress, sizeof(otIp6Address));
318
319 VerifyOrExit(otMessageRead(message, 0, req->buffer, length) == length);
320
321 VerifyOrExit(zsock_sendto(mdns_sock_v6, req->buffer, length, 0,
322 (struct net_sockaddr *)&addr_v6,
323 sizeof(addr_v6)) > 0);
324 #if defined(CONFIG_NET_IPV4)
325 if (send_ipv4) {
326 VerifyOrExit(zsock_sendto(mdns_sock_v4, req->buffer, length, 0,
327 (struct net_sockaddr *)&addr_v4,
328 sizeof(addr_v4)) > 0);
329 }
330 #endif /* CONFIG_NET_IPV4 */
331 exit:
332 otMessageFree(message);
333 if (req != NULL) {
334 openthread_border_router_deallocate_message((void *)req);
335 }
336 }
337
mdns_receive_handler(struct net_socket_service_event * evt)338 static void mdns_receive_handler(struct net_socket_service_event *evt)
339 {
340 struct net_sockaddr_in6 addr_v6 = {0};
341 #if defined(CONFIG_NET_IPV4)
342 struct net_sockaddr_in addr_v4 = {0};
343 net_socklen_t optlen = sizeof(int);
344 #endif /* CONFIG_NET_IPV4 */
345 net_socklen_t addrlen;
346 ssize_t len = 0;
347 int family;
348 struct otbr_msg_ctx *req = NULL;
349
350 VerifyOrExit(evt->event.revents & ZSOCK_POLLIN);
351 VerifyOrExit(openthread_border_router_allocate_message((void **)&req) == OT_ERROR_NONE);
352 #if defined(CONFIG_NET_IPV4)
353 (void)zsock_getsockopt(evt->event.fd, ZSOCK_SOL_SOCKET, ZSOCK_SO_DOMAIN, &family, &optlen);
354
355 if (family == NET_AF_INET) {
356 addrlen = sizeof(addr_v4);
357 len = zsock_recvfrom(mdns_sock_v4, req->buffer, sizeof(req->buffer), 0,
358 (struct net_sockaddr *)&addr_v4, &addrlen);
359 VerifyOrExit(len > 0);
360 otIp4ToIp4MappedIp6Address((otIp4Address *)&addr_v4.sin_addr.s_addr,
361 &req->addr_info.mAddress);
362 req->addr_info.mPort = net_ntohs(addr_v4.sin_port);
363 } else {
364 #endif /* CONFIG_NET_IPV4 */
365 addrlen = sizeof(addr_v6);
366 len = zsock_recvfrom(mdns_sock_v6, req->buffer, sizeof(req->buffer), 0,
367 (struct net_sockaddr *)&addr_v6, &addrlen);
368 VerifyOrExit(len > 0);
369 memcpy(&req->addr_info.mAddress, &addr_v6.sin6_addr,
370 sizeof(req->addr_info.mAddress));
371 req->addr_info.mPort = net_ntohs(addr_v6.sin6_port);
372 #if defined(CONFIG_NET_IPV4)
373 }
374 #endif /* CONFIG_NET_IPV4 */
375 req->length = (uint16_t)len;
376 req->addr_info.mInfraIfIndex = ail_iface_index;
377 req->cb = process_mdns_message;
378
379 openthread_border_router_post_message(req);
380
381 exit:
382 return;
383 }
384
process_mdns_message(struct otbr_msg_ctx * msg_ctx_ptr)385 static void process_mdns_message(struct otbr_msg_ctx *msg_ctx_ptr)
386 {
387 otMessageSettings ot_message_settings = {true, OT_MESSAGE_PRIORITY_NORMAL};
388 otMessage *ot_message = NULL;
389 otBufferInfo buffer_info;
390 uint16_t req_buff_num;
391
392 /** In large networks with high traffic, we have observed that mDNS module
393 * might jump to assert when trying to allocate OT message buffers for a new
394 * query/response that has to be sent.
395 * Here, we calculate the approximate number of OT message buffers that will be required
396 * to hold the incoming mDNS packet. If the number of free OT message buffers will drop
397 * below the imposed limit after the conversion has been perfomed, the incoming packet
398 * will be silently dropped.
399 * A possible scenario would be when multipackets (TC bit set) are received from multiple
400 * hosts, as mDNS module stores the incoming messages for a period of time.
401 * This mechanism tries to make sure that there are enough free buffers for mDNS module
402 * to perform it's execution.
403 */
404
405 req_buff_num = (msg_ctx_ptr->length /
406 (CONFIG_OPENTHREAD_MESSAGE_BUFFER_SIZE - sizeof(otMessageBuffer))) + 1;
407 otMessageGetBufferInfo(ot_instance_ptr, &buffer_info);
408
409 VerifyOrExit((buffer_info.mFreeBuffers - req_buff_num) >=
410 ((PKT_THRESHOLD_VAL * CONFIG_OPENTHREAD_NUM_MESSAGE_BUFFERS) / 100));
411
412 ot_message = otIp6NewMessage(ot_instance_ptr, &ot_message_settings);
413 VerifyOrExit(ot_message);
414 VerifyOrExit(otMessageAppend(ot_message, msg_ctx_ptr->buffer,
415 msg_ctx_ptr->length) == OT_ERROR_NONE);
416 otPlatMdnsHandleReceive(ot_instance_ptr, ot_message, /* aIsUnicast */ false,
417 &msg_ctx_ptr->addr_info);
418 ot_message = NULL;
419 exit:
420 if (ot_message != NULL) {
421 otMessageFree(ot_message);
422 }
423 }
424
mdns_plat_monitor_interface(struct net_if * ail_iface)425 void mdns_plat_monitor_interface(struct net_if *ail_iface)
426 {
427 struct net_if_ipv6 *ipv6 = NULL;
428 otIp6Address ip6_addr = {0};
429 struct net_if_addr *unicast = NULL;
430
431 VerifyOrExit(mdns_socket_is_enabled);
432
433 net_if_lock(ail_iface);
434
435 otPlatMdnsHandleHostAddressRemoveAll(ot_instance_ptr, ail_iface_index);
436
437 ipv6 = ail_iface->config.ip.ipv6;
438 ARRAY_FOR_EACH(ipv6->unicast, idx) {
439 unicast = &ipv6->unicast[idx];
440
441 if (!unicast->is_used) {
442 continue;
443 }
444 memcpy(&ip6_addr.mFields.m32, &unicast->address.in6_addr.s6_addr32,
445 sizeof(otIp6Address));
446 otPlatMdnsHandleHostAddressEvent(ot_instance_ptr, &ip6_addr, true,
447 ail_iface_index);
448 }
449
450 #if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_IPV4_MAPPING_TO_IPV6)
451 struct net_if_ipv4 *ipv4 = NULL;
452 otIp4Address ip4_addr = {0};
453
454 ipv4 = ail_iface->config.ip.ipv4;
455 ARRAY_FOR_EACH(ipv4->unicast, idx) {
456 unicast = &ipv4->unicast[idx].ipv4;
457
458 if (!unicast->is_used) {
459 continue;
460 }
461 memcpy(&ip4_addr.mFields.m32, &unicast->address.in_addr.s4_addr32,
462 sizeof(otIp4Address));
463 otIp4ToIp4MappedIp6Address(&ip4_addr, &ip6_addr);
464 otPlatMdnsHandleHostAddressEvent(ot_instance_ptr, &ip6_addr, true,
465 ail_iface_index);
466 }
467 #endif /* CONFIG_NET_IPV4 && CONFIG_NET_IPV4_MAPPING_TO_IPV6 */
468
469 net_if_unlock(ail_iface);
470 exit:
471 return;
472 }
473