1 /* main.c - Application main entry point */
2 
3 /*
4  * Copyright (c) 2015 Intel Corporation
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include <zephyr/logging/log.h>
10 LOG_MODULE_REGISTER(net_test, CONFIG_NET_IPV6_LOG_LEVEL);
11 
12 #include <zephyr/types.h>
13 #include <stdbool.h>
14 #include <stddef.h>
15 #include <string.h>
16 #include <errno.h>
17 #include <zephyr/linker/sections.h>
18 
19 #include <zephyr/ztest.h>
20 
21 #include <zephyr/net/mld.h>
22 #include <zephyr/net/net_if.h>
23 #include <zephyr/net/net_pkt.h>
24 #include <zephyr/net/net_ip.h>
25 #include <zephyr/net/net_core.h>
26 #include <zephyr/net/ethernet.h>
27 #include <zephyr/net/dummy.h>
28 #include <zephyr/net/net_mgmt.h>
29 #include <zephyr/net/net_event.h>
30 #include <zephyr/net/socket.h>
31 
32 #include <zephyr/random/random.h>
33 
34 #include "icmpv6.h"
35 #include "ipv6.h"
36 #include "route.h"
37 
38 #define THREAD_SLEEP 50 /* ms */
39 #define MLD_REPORT_ADDR_COUNT 8
40 
41 #define NET_LOG_ENABLED 1
42 #include "net_private.h"
43 
44 #if defined(CONFIG_NET_IPV6_LOG_LEVEL_DBG)
45 #define DBG(fmt, ...) printk(fmt, ##__VA_ARGS__)
46 #else
47 #define DBG(fmt, ...)
48 #endif
49 
50 struct mld_report_mcast_record {
51 	uint8_t record_type;
52 	uint8_t aux_data_len;
53 	uint16_t num_of_sources;
54 	struct in6_addr mcast_addr;
55 } __packed;
56 
57 struct mld_report_info {
58 	uint16_t records_count;
59 	struct mld_report_mcast_record records[MLD_REPORT_ADDR_COUNT];
60 };
61 
62 typedef void (*mld_report_callback)(struct net_pkt *pkt, void *user_data);
63 
64 struct mld_report_handler {
65 	mld_report_callback fn;
66 	void *user_data;
67 };
68 
69 static struct in6_addr my_addr = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
70 				       0, 0, 0, 0, 0, 0, 0, 0x1 } } };
71 static struct in6_addr peer_addr = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
72 					 0, 0, 0, 0, 0, 0, 0, 0x2 } } };
73 static struct in6_addr mcast_addr = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
74 					  0, 0, 0, 0, 0, 0, 0, 0x1 } } };
75 
76 static struct in6_addr *exp_mcast_group;
77 static struct net_if *net_iface;
78 static bool is_group_joined;
79 static bool is_group_left;
80 static bool is_join_msg_ok;
81 static bool is_leave_msg_ok;
82 static bool is_query_received;
83 static bool is_report_sent;
84 static bool ignore_already;
85 
86 static struct mld_report_handler *report_handler;
87 
88 K_SEM_DEFINE(wait_data, 0, UINT_MAX);
89 K_SEM_DEFINE(wait_joined, 0, UINT_MAX);
90 K_SEM_DEFINE(wait_left, 0, UINT_MAX);
91 
92 #define WAIT_TIME 500
93 #define WAIT_TIME_LONG MSEC_PER_SEC
94 #define MY_PORT 1969
95 #define PEER_PORT 13856
96 
97 struct net_test_mld {
98 	uint8_t mac_addr[sizeof(struct net_eth_addr)];
99 	struct net_linkaddr ll_addr;
100 };
101 
net_test_dev_init(const struct device * dev)102 int net_test_dev_init(const struct device *dev)
103 {
104 	return 0;
105 }
106 
net_test_get_mac(const struct device * dev)107 static uint8_t *net_test_get_mac(const struct device *dev)
108 {
109 	struct net_test_mld *context = dev->data;
110 
111 	if (context->mac_addr[2] == 0x00) {
112 		/* 00-00-5E-00-53-xx Documentation RFC 7042 */
113 		context->mac_addr[0] = 0x00;
114 		context->mac_addr[1] = 0x00;
115 		context->mac_addr[2] = 0x5E;
116 		context->mac_addr[3] = 0x00;
117 		context->mac_addr[4] = 0x53;
118 		context->mac_addr[5] = sys_rand8_get();
119 	}
120 
121 	return context->mac_addr;
122 }
123 
net_test_iface_init(struct net_if * iface)124 static void net_test_iface_init(struct net_if *iface)
125 {
126 	uint8_t *mac = net_test_get_mac(net_if_get_device(iface));
127 
128 	net_if_set_link_addr(iface, mac, sizeof(struct net_eth_addr),
129 			     NET_LINK_ETHERNET);
130 }
131 
get_icmp_hdr(struct net_pkt * pkt)132 static struct net_icmp_hdr *get_icmp_hdr(struct net_pkt *pkt)
133 {
134 	net_pkt_cursor_init(pkt);
135 
136 	net_pkt_skip(pkt, net_pkt_ip_hdr_len(pkt) +
137 		     net_pkt_ipv6_ext_len(pkt));
138 
139 	return (struct net_icmp_hdr *)net_pkt_cursor_get_pos(pkt);
140 }
141 
tester_send(const struct device * dev,struct net_pkt * pkt)142 static int tester_send(const struct device *dev, struct net_pkt *pkt)
143 {
144 	struct net_icmp_hdr *icmp;
145 
146 	if (!pkt->buffer) {
147 		TC_ERROR("No data to send!\n");
148 		return -ENODATA;
149 	}
150 
151 	icmp = get_icmp_hdr(pkt);
152 
153 	if (icmp->type == NET_ICMPV6_MLDv2) {
154 		/* FIXME, add more checks here */
155 
156 		NET_DBG("Received something....");
157 		is_join_msg_ok = true;
158 		is_leave_msg_ok = true;
159 		is_report_sent = true;
160 
161 		if (report_handler) {
162 			report_handler->fn(pkt, report_handler->user_data);
163 		}
164 
165 		k_sem_give(&wait_data);
166 	}
167 
168 	return 0;
169 }
170 
tester_null_send(const struct device * dev,struct net_pkt * pkt)171 static int tester_null_send(const struct device *dev, struct net_pkt *pkt)
172 {
173 	ARG_UNUSED(dev);
174 	ARG_UNUSED(pkt);
175 
176 	return 0;
177 }
178 
179 struct net_test_mld net_test_data;
180 struct net_test_mld net_test_null_data;
181 
182 static struct dummy_api net_test_if_api = {
183 	.iface_api.init = net_test_iface_init,
184 	.send = tester_send,
185 };
186 
init_null_iface(struct net_if * iface)187 static void init_null_iface(struct net_if *iface)
188 {
189 	struct net_test_mld *context = iface->if_dev->dev->data;
190 
191 	memset(&context->mac_addr, 0, sizeof(context->mac_addr));
192 
193 	net_if_set_link_addr(iface, context->mac_addr, sizeof(struct net_eth_addr),
194 			     NET_LINK_ETHERNET);
195 }
196 
197 static struct dummy_api net_test_null_if_api = {
198 	.iface_api.init = init_null_iface,
199 	.send = tester_null_send,
200 };
201 
202 #define _ETH_L2_LAYER DUMMY_L2
203 #define _ETH_L2_CTX_TYPE NET_L2_GET_CTX_TYPE(DUMMY_L2)
204 
205 NET_DEVICE_INIT(net_test_mld, "net_test_mld",
206 		net_test_dev_init, NULL, &net_test_data, NULL,
207 		CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
208 		&net_test_if_api, _ETH_L2_LAYER, _ETH_L2_CTX_TYPE,
209 		127);
210 
211 /* Interface without a device or API, only for usage of `struct net_if` */
212 NET_DEVICE_INIT(net_test_null_iface, "net_test_null_iface", net_test_dev_init, NULL,
213 		&net_test_null_data, NULL, 99, &net_test_null_if_api, _ETH_L2_LAYER,
214 		_ETH_L2_CTX_TYPE, 127);
215 
test_iface_down_up(void)216 static void test_iface_down_up(void)
217 {
218 	zassert_ok(net_if_down(net_iface), "Failed to bring iface down");
219 	k_msleep(10);
220 	zassert_ok(net_if_up(net_iface), "Failed to bring iface up");
221 }
222 
test_iface_down_up_delayed_carrier(void)223 static void test_iface_down_up_delayed_carrier(void)
224 {
225 	zassert_ok(net_if_down(net_iface), "Failed to bring iface down");
226 	k_msleep(10);
227 	net_if_carrier_off(net_iface);
228 	zassert_ok(net_if_up(net_iface), "Failed to bring iface up");
229 	k_msleep(10);
230 	net_if_carrier_on(net_iface);
231 }
232 
test_iface_carrier_off_on(void)233 static void test_iface_carrier_off_on(void)
234 {
235 	net_if_carrier_off(net_iface);
236 	k_msleep(10);
237 	net_if_carrier_on(net_iface);
238 }
239 
group_joined(struct net_mgmt_event_callback * cb,uint32_t nm_event,struct net_if * iface)240 static void group_joined(struct net_mgmt_event_callback *cb,
241 			 uint32_t nm_event, struct net_if *iface)
242 {
243 	if (nm_event != NET_EVENT_IPV6_MCAST_JOIN) {
244 		/* Spurious callback. */
245 		return;
246 	}
247 
248 	if (exp_mcast_group == NULL ||
249 	    net_ipv6_addr_cmp(exp_mcast_group, cb->info)) {
250 		is_group_joined = true;
251 
252 		k_sem_give(&wait_joined);
253 	}
254 }
255 
group_left(struct net_mgmt_event_callback * cb,uint32_t nm_event,struct net_if * iface)256 static void group_left(struct net_mgmt_event_callback *cb,
257 			 uint32_t nm_event, struct net_if *iface)
258 {
259 	if (nm_event != NET_EVENT_IPV6_MCAST_LEAVE) {
260 		/* Spurious callback. */
261 		return;
262 	}
263 
264 	if (exp_mcast_group == NULL ||
265 	    net_ipv6_addr_cmp(exp_mcast_group, cb->info)) {
266 		is_group_left = true;
267 
268 		k_sem_give(&wait_left);
269 	}
270 }
271 
272 static struct mgmt_events {
273 	uint32_t event;
274 	net_mgmt_event_handler_t handler;
275 	struct net_mgmt_event_callback cb;
276 } mgmt_events[] = {
277 	{ .event = NET_EVENT_IPV6_MCAST_JOIN, .handler = group_joined },
278 	{ .event = NET_EVENT_IPV6_MCAST_LEAVE, .handler = group_left },
279 	{ 0 }
280 };
281 
setup_mgmt_events(void)282 static void setup_mgmt_events(void)
283 {
284 	int i;
285 
286 	for (i = 0; mgmt_events[i].event; i++) {
287 		net_mgmt_init_event_callback(&mgmt_events[i].cb,
288 					     mgmt_events[i].handler,
289 					     mgmt_events[i].event);
290 
291 		net_mgmt_add_event_callback(&mgmt_events[i].cb);
292 	}
293 }
294 
test_mld_setup(void)295 static void *test_mld_setup(void)
296 {
297 	struct net_if_addr *ifaddr;
298 
299 	setup_mgmt_events();
300 
301 	net_iface = net_if_get_first_by_type(&NET_L2_GET_NAME(DUMMY));
302 
303 	zassert_not_null(net_iface, "Interface is NULL");
304 
305 	ifaddr = net_if_ipv6_addr_add(net_iface, &my_addr,
306 				      NET_ADDR_MANUAL, 0);
307 
308 	zassert_not_null(ifaddr, "Cannot add IPv6 address");
309 
310 	return NULL;
311 }
312 
test_mld_before(void * fixture)313 static void test_mld_before(void *fixture)
314 {
315 	ARG_UNUSED(fixture);
316 
317 	report_handler = NULL;
318 	exp_mcast_group = NULL;
319 }
320 
test_join_group(void)321 static void test_join_group(void)
322 {
323 	int ret;
324 
325 	/* Using adhoc multicast group outside standard range */
326 	net_ipv6_addr_create(&mcast_addr, 0xff10, 0, 0, 0, 0, 0, 0, 0x0001);
327 
328 	ret = net_ipv6_mld_join(net_iface, &mcast_addr);
329 
330 	if (ignore_already) {
331 		zassert_true(ret == 0 || ret == -EALREADY,
332 			     "Cannot join IPv6 multicast group");
333 	} else {
334 		zassert_equal(ret, 0, "Cannot join IPv6 multicast group");
335 	}
336 
337 	/* Let the network stack to proceed */
338 	k_msleep(THREAD_SLEEP);
339 }
340 
test_leave_group(void)341 static void test_leave_group(void)
342 {
343 	int ret;
344 
345 	net_ipv6_addr_create(&mcast_addr, 0xff10, 0, 0, 0, 0, 0, 0, 0x0001);
346 
347 	ret = net_ipv6_mld_leave(net_iface, &mcast_addr);
348 
349 	zassert_equal(ret, 0, "Cannot leave IPv6 multicast group");
350 
351 	k_msleep(THREAD_SLEEP);
352 }
353 
test_catch_join_group(void)354 static void test_catch_join_group(void)
355 {
356 	is_group_joined = false;
357 
358 	ignore_already = false;
359 
360 	test_join_group();
361 
362 	if (k_sem_take(&wait_joined, K_MSEC(WAIT_TIME))) {
363 		zassert_true(0, "Timeout while waiting join event");
364 	}
365 
366 	if (!is_group_joined) {
367 		zassert_true(0, "Did not catch join event");
368 	}
369 
370 	is_group_joined = false;
371 }
372 
test_catch_leave_group(void)373 static void test_catch_leave_group(void)
374 {
375 	is_group_joined = false;
376 
377 	test_leave_group();
378 
379 	if (k_sem_take(&wait_left, K_MSEC(WAIT_TIME))) {
380 		zassert_true(0, "Timeout while waiting leave event");
381 	}
382 
383 	if (!is_group_left) {
384 		zassert_true(0, "Did not catch leave event");
385 	}
386 
387 	is_group_left = false;
388 }
389 
test_verify_join_group(void)390 static void test_verify_join_group(void)
391 {
392 	is_join_msg_ok = false;
393 
394 	ignore_already = false;
395 
396 	test_join_group();
397 
398 	if (k_sem_take(&wait_joined, K_MSEC(WAIT_TIME))) {
399 		zassert_true(0, "Timeout while waiting join event");
400 	}
401 
402 	if (!is_join_msg_ok) {
403 		zassert_true(0, "Join msg invalid");
404 	}
405 
406 	is_join_msg_ok = false;
407 }
408 
test_verify_leave_group(void)409 static void test_verify_leave_group(void)
410 {
411 	is_leave_msg_ok = false;
412 
413 	test_leave_group();
414 
415 	if (k_sem_take(&wait_left, K_MSEC(WAIT_TIME))) {
416 		zassert_true(0, "Timeout while waiting leave event");
417 	}
418 
419 	if (!is_leave_msg_ok) {
420 		zassert_true(0, "Leave msg invalid");
421 	}
422 
423 	is_leave_msg_ok = false;
424 }
425 
send_query(struct net_if * iface)426 static void send_query(struct net_if *iface)
427 {
428 	struct net_pkt *pkt;
429 	struct in6_addr dst;
430 	int ret;
431 
432 	/* Sent to all MLDv2-capable routers */
433 	net_ipv6_addr_create(&dst, 0xff02, 0, 0, 0, 0, 0, 0, 0x0016);
434 
435 	/* router alert opt + icmpv6 reserved space + mldv2 mcast record */
436 	pkt = net_pkt_alloc_with_buffer(iface, 144, AF_INET6,
437 					IPPROTO_ICMPV6, K_FOREVER);
438 	zassert_not_null(pkt, "Cannot allocate pkt");
439 
440 	net_pkt_set_ipv6_hop_limit(pkt, 1); /* RFC 3810 ch 7.4 */
441 	ret = net_ipv6_create(pkt, &peer_addr, &dst);
442 	zassert_false(ret, "Cannot create ipv6 pkt");
443 
444 	/* Add hop-by-hop option and router alert option, RFC 3810 ch 5. */
445 	ret = net_pkt_write_u8(pkt, IPPROTO_ICMPV6);
446 	zassert_false(ret, "Failed to write");
447 	ret = net_pkt_write_u8(pkt, 0); /* length (0 means 8 bytes) */
448 	zassert_false(ret, "Failed to write");
449 
450 #define ROUTER_ALERT_LEN 8
451 
452 	/* IPv6 router alert option is described in RFC 2711. */
453 	ret = net_pkt_write_be16(pkt, 0x0502); /* RFC 2711 ch 2.1 */
454 	zassert_false(ret, "Failed to write");
455 	ret = net_pkt_write_be16(pkt, 0); /* pkt contains MLD msg */
456 	zassert_false(ret, "Failed to write");
457 
458 	ret = net_pkt_write_u8(pkt, 1); /* padn */
459 	zassert_false(ret, "Failed to write");
460 	ret = net_pkt_write_u8(pkt, 0); /* padn len */
461 	zassert_false(ret, "Failed to write");
462 
463 	net_pkt_set_ipv6_ext_len(pkt, ROUTER_ALERT_LEN);
464 
465 	/* ICMPv6 header */
466 	ret = net_icmpv6_create(pkt, NET_ICMPV6_MLD_QUERY, 0);
467 	zassert_false(ret, "Cannot create icmpv6 pkt");
468 
469 	ret = net_pkt_write_be16(pkt, 3); /* maximum response code */
470 	zassert_false(ret, "Failed to write");
471 	ret = net_pkt_write_be16(pkt, 0); /* reserved field */
472 	zassert_false(ret, "Failed to write");
473 
474 	net_pkt_set_ipv6_next_hdr(pkt, NET_IPV6_NEXTHDR_HBHO);
475 
476 	ret = net_pkt_write_be16(pkt, 0); /* Resv, S, QRV and QQIC */
477 	zassert_false(ret, "Failed to write");
478 	ret = net_pkt_write_be16(pkt, 0); /* number of addresses */
479 	zassert_false(ret, "Failed to write");
480 
481 	ret = net_pkt_write(pkt, net_ipv6_unspecified_address(),
482 			    sizeof(struct in6_addr));
483 	zassert_false(ret, "Failed to write");
484 
485 	net_pkt_cursor_init(pkt);
486 	ret = net_ipv6_finalize(pkt, IPPROTO_ICMPV6);
487 	zassert_false(ret, "Failed to finalize ipv6 packet");
488 
489 	net_pkt_cursor_init(pkt);
490 
491 	ret = net_recv_data(iface, pkt);
492 	zassert_false(ret, "Failed to receive data");
493 }
494 
495 /* interface needs to join the MLDv2-capable routers multicast group before it
496  * can receive MLD queries
497  */
join_mldv2_capable_routers_group(void)498 static void join_mldv2_capable_routers_group(void)
499 {
500 	struct net_if *iface;
501 	int ret;
502 
503 	iface = net_if_get_first_by_type(&NET_L2_GET_NAME(DUMMY));
504 
505 	net_ipv6_addr_create(&mcast_addr, 0xff02, 0, 0, 0, 0, 0, 0, 0x0016);
506 	ret = net_ipv6_mld_join(iface, &mcast_addr);
507 
508 	zassert_true(ret == 0 || ret == -EALREADY,
509 		     "Cannot join MLDv2-capable routers multicast group");
510 
511 	k_msleep(THREAD_SLEEP);
512 
513 }
514 
leave_mldv2_capable_routers_group(void)515 static void leave_mldv2_capable_routers_group(void)
516 {
517 	struct net_if *iface;
518 	int ret;
519 
520 	iface = net_if_get_first_by_type(&NET_L2_GET_NAME(DUMMY));
521 
522 	net_ipv6_addr_create(&mcast_addr, 0xff02, 0, 0, 0, 0, 0, 0, 0x0016);
523 	ret = net_ipv6_mld_leave(iface, &mcast_addr);
524 
525 	zassert_equal(ret, 0,
526 		      "Cannot leave MLDv2-capable routers multicast group");
527 
528 	k_msleep(THREAD_SLEEP);
529 }
530 
531 /* We are not really interested to parse the query at this point */
handle_mld_query(struct net_icmp_ctx * ctx,struct net_pkt * pkt,struct net_icmp_ip_hdr * hdr,struct net_icmp_hdr * icmp_hdr,void * user_data)532 static int handle_mld_query(struct net_icmp_ctx *ctx,
533 			    struct net_pkt *pkt,
534 			    struct net_icmp_ip_hdr *hdr,
535 			    struct net_icmp_hdr *icmp_hdr,
536 			    void *user_data)
537 {
538 	ARG_UNUSED(ctx);
539 	ARG_UNUSED(pkt);
540 	ARG_UNUSED(hdr);
541 	ARG_UNUSED(icmp_hdr);
542 	ARG_UNUSED(user_data);
543 
544 	is_query_received = true;
545 
546 	NET_DBG("Handling MLD query");
547 
548 	return NET_DROP;
549 }
550 
test_catch_query(void)551 static void test_catch_query(void)
552 {
553 	struct net_icmp_ctx ctx;
554 	int ret;
555 
556 	join_mldv2_capable_routers_group();
557 
558 	is_query_received = false;
559 
560 	ret = net_icmp_init_ctx(&ctx, NET_ICMPV6_MLD_QUERY,
561 				0, handle_mld_query);
562 	zassert_equal(ret, 0, "Cannot register %s handler (%d)",
563 		      STRINGIFY(NET_ICMPV6_MLD_QUERY), ret);
564 
565 	send_query(net_if_get_first_by_type(&NET_L2_GET_NAME(DUMMY)));
566 
567 	k_msleep(THREAD_SLEEP);
568 
569 	if (k_sem_take(&wait_data, K_MSEC(WAIT_TIME))) {
570 		zassert_true(0, "Timeout while waiting query event");
571 	}
572 
573 	if (!is_query_received) {
574 		zassert_true(0, "Query msg invalid");
575 	}
576 
577 	is_query_received = false;
578 
579 	leave_mldv2_capable_routers_group();
580 
581 	net_icmp_cleanup_ctx(&ctx);
582 }
583 
test_verify_send_report(void)584 static void test_verify_send_report(void)
585 {
586 	join_mldv2_capable_routers_group();
587 
588 	is_query_received = false;
589 	is_report_sent = false;
590 
591 	ignore_already = true;
592 
593 	k_sem_reset(&wait_data);
594 
595 	test_join_group();
596 
597 	k_yield();
598 
599 	/* Did we send a report? */
600 	if (k_sem_take(&wait_data, K_MSEC(WAIT_TIME))) {
601 		zassert_true(0, "Timeout while waiting for report");
602 	}
603 
604 	k_sem_reset(&wait_data);
605 
606 	is_report_sent = false;
607 	send_query(net_if_get_first_by_type(&NET_L2_GET_NAME(DUMMY)));
608 
609 	k_yield();
610 
611 	/* Did we send a report? */
612 	if (k_sem_take(&wait_data, K_MSEC(WAIT_TIME))) {
613 		zassert_true(0, "Timeout while waiting for report");
614 	}
615 
616 	zassert_true(is_report_sent, "Report not sent");
617 
618 	leave_mldv2_capable_routers_group();
619 }
620 
621 /* This value should be longer that the one in net_if.c when DAD timeouts */
622 #define DAD_TIMEOUT (MSEC_PER_SEC / 5U)
623 
ZTEST(net_mld_test_suite,test_allnodes)624 ZTEST(net_mld_test_suite, test_allnodes)
625 {
626 	struct net_if *iface = NULL;
627 	struct net_if_mcast_addr *ifmaddr;
628 	struct in6_addr addr;
629 
630 	net_ipv6_addr_create_ll_allnodes_mcast(&addr);
631 
632 	/* Let the DAD succeed so that the multicast address will be there */
633 	k_sleep(K_MSEC(DAD_TIMEOUT));
634 
635 	ifmaddr = net_if_ipv6_maddr_lookup(&addr, &iface);
636 
637 	zassert_not_null(ifmaddr, "Interface does not contain "
638 			"allnodes multicast address");
639 }
640 
expect_exclude_mcast_report(struct net_pkt * pkt,void * user_data)641 static void expect_exclude_mcast_report(struct net_pkt *pkt, void *user_data)
642 {
643 	struct mld_report_mcast_record record;
644 	uint16_t records_count;
645 	uint16_t res_bytes;
646 	bool *report_sent = user_data;
647 
648 	zassert_not_null(exp_mcast_group, "Expected mcast group not sent");
649 
650 	net_pkt_set_overwrite(pkt, true);
651 	net_pkt_skip(pkt, sizeof(struct net_icmp_hdr));
652 
653 	zassert_ok(net_pkt_read_be16(pkt, &res_bytes), "Failed to read reserved bytes");
654 	zassert_equal(0, res_bytes, "Reserved bytes must be zeroed");
655 
656 	zassert_ok(net_pkt_read_be16(pkt, &records_count), "Failed to read addr count");
657 	zexpect_equal(records_count, 1, "Incorrect record count ");
658 
659 	net_pkt_read(pkt, &record, sizeof(struct mld_report_mcast_record));
660 
661 	if (record.record_type == NET_IPV6_MLDv2_CHANGE_TO_EXCLUDE_MODE &&
662 	    net_ipv6_addr_cmp_raw((const uint8_t *)exp_mcast_group,
663 				  (const uint8_t *)&record.mcast_addr)) {
664 		*report_sent = true;
665 	}
666 }
667 
verify_allnodes_on_iface_event(void (* action)(void))668 static void verify_allnodes_on_iface_event(void (*action)(void))
669 {
670 	struct net_if *iface = NULL;
671 	struct net_if_mcast_addr *ifmaddr;
672 	struct in6_addr addr;
673 	bool exclude_report_sent = false;
674 	struct mld_report_handler handler = {
675 		.fn = expect_exclude_mcast_report,
676 		.user_data = &exclude_report_sent
677 	};
678 
679 	net_ipv6_addr_create_ll_allnodes_mcast(&addr);
680 	k_sem_reset(&wait_joined);
681 
682 	is_group_joined = false;
683 	exp_mcast_group = &addr;
684 	report_handler = &handler;
685 
686 	action();
687 
688 	zassert_ok(k_sem_take(&wait_joined, K_MSEC(WAIT_TIME)),
689 		   "Timeout while waiting for an event");
690 
691 	ifmaddr = net_if_ipv6_maddr_lookup(&addr, &iface);
692 	zassert_not_null(ifmaddr, "Interface does not contain "
693 			"allnodes multicast address");
694 
695 	zassert_true(is_group_joined, "Did not join mcast group");
696 	zassert_true(exclude_report_sent, "Did not send report");
697 }
698 
699 /* Verify that mcast all nodes is present after interface admin state toggle */
ZTEST(net_mld_test_suite,test_allnodes_after_iface_up)700 ZTEST(net_mld_test_suite, test_allnodes_after_iface_up)
701 {
702 	verify_allnodes_on_iface_event(test_iface_down_up);
703 }
704 
705 /* Verify that mcast all nodes is present after delayed carrier on */
ZTEST(net_mld_test_suite,test_allnodes_after_iface_up_carrier_delayed)706 ZTEST(net_mld_test_suite, test_allnodes_after_iface_up_carrier_delayed)
707 {
708 	verify_allnodes_on_iface_event(test_iface_down_up_delayed_carrier);
709 }
710 
711 /* Verify that mcast all nodes is present after carrier toggle */
ZTEST(net_mld_test_suite,test_allnodes_after_carrier_toggle)712 ZTEST(net_mld_test_suite, test_allnodes_after_carrier_toggle)
713 {
714 	verify_allnodes_on_iface_event(test_iface_carrier_off_on);
715 }
716 
ZTEST(net_mld_test_suite,test_solicit_node)717 ZTEST(net_mld_test_suite, test_solicit_node)
718 {
719 	struct net_if *iface = NULL;
720 	struct net_if_mcast_addr *ifmaddr;
721 	struct in6_addr addr;
722 
723 	net_ipv6_addr_create_solicited_node(&my_addr, &addr);
724 
725 	ifmaddr = net_if_ipv6_maddr_lookup(&addr, &iface);
726 
727 	zassert_not_null(ifmaddr, "Interface does not contain "
728 			"solicit node multicast address");
729 }
730 
verify_solicit_node_on_iface_event(void (* action)(void))731 static void verify_solicit_node_on_iface_event(void (*action)(void))
732 {
733 	struct net_if *iface = NULL;
734 	struct net_if_mcast_addr *ifmaddr;
735 	struct in6_addr addr;
736 	bool exclude_report_sent = false;
737 	struct mld_report_handler handler = {
738 		.fn = expect_exclude_mcast_report,
739 		.user_data = &exclude_report_sent
740 	};
741 
742 	net_ipv6_addr_create_solicited_node(&my_addr, &addr);
743 	k_sem_reset(&wait_joined);
744 
745 	is_group_joined = false;
746 	exp_mcast_group = &addr;
747 	report_handler = &handler;
748 
749 	action();
750 
751 	zassert_ok(k_sem_take(&wait_joined, K_MSEC(WAIT_TIME)),
752 		   "Timeout while waiting for an event");
753 
754 	ifmaddr = net_if_ipv6_maddr_lookup(&addr, &iface);
755 	zassert_not_null(ifmaddr, "Interface does not contain "
756 			"solicit node multicast address");
757 
758 	zassert_true(is_group_joined, "Did not join mcast group");
759 	zassert_true(exclude_report_sent, "Did not send report");
760 }
761 
762 /* Verify that mcast solicited node is present after interface admin state toggle */
ZTEST(net_mld_test_suite,test_solicit_node_after_iface_up)763 ZTEST(net_mld_test_suite, test_solicit_node_after_iface_up)
764 {
765 	verify_solicit_node_on_iface_event(test_iface_down_up);
766 }
767 
768 /* Verify that mcast solicited node is present after delayed carrier on */
ZTEST(net_mld_test_suite,test_solicit_node_after_iface_up_carrier_delayed)769 ZTEST(net_mld_test_suite, test_solicit_node_after_iface_up_carrier_delayed)
770 {
771 	verify_solicit_node_on_iface_event(test_iface_down_up_delayed_carrier);
772 }
773 
774 /* Verify that mcast solicited node is present after delayed carrier toggle */
ZTEST(net_mld_test_suite,test_solicit_node_after_carrier_toggle)775 ZTEST(net_mld_test_suite, test_solicit_node_after_carrier_toggle)
776 {
777 	verify_solicit_node_on_iface_event(test_iface_carrier_off_on);
778 }
779 
ZTEST(net_mld_test_suite,test_join_leave)780 ZTEST(net_mld_test_suite, test_join_leave)
781 {
782 	test_join_group();
783 	test_leave_group();
784 }
785 
ZTEST(net_mld_test_suite,test_catch_join_leave)786 ZTEST(net_mld_test_suite, test_catch_join_leave)
787 {
788 	test_catch_join_group();
789 	test_catch_leave_group();
790 }
791 
ZTEST(net_mld_test_suite,test_verify_join_leave)792 ZTEST(net_mld_test_suite, test_verify_join_leave)
793 {
794 	test_verify_join_group();
795 	test_verify_leave_group();
796 	test_catch_query();
797 	test_verify_send_report();
798 }
799 
ZTEST(net_mld_test_suite,test_no_mld_flag)800 ZTEST(net_mld_test_suite, test_no_mld_flag)
801 {
802 	int ret;
803 
804 	is_join_msg_ok = false;
805 	is_leave_msg_ok = false;
806 
807 	net_if_flag_set(net_iface, NET_IF_IPV6_NO_MLD);
808 
809 	/* Using adhoc multicast group outside standard range */
810 	net_ipv6_addr_create(&mcast_addr, 0xff10, 0, 0, 0, 0, 0, 0, 0x0001);
811 
812 	ret = net_ipv6_mld_join(net_iface, &mcast_addr);
813 	zassert_equal(ret, 0, "Cannot add multicast address");
814 
815 	/* Let the network stack to proceed */
816 	k_msleep(THREAD_SLEEP);
817 
818 	zassert_false(is_join_msg_ok, "Received join message when not expected");
819 
820 	ret = net_ipv6_mld_leave(net_iface, &mcast_addr);
821 	zassert_equal(ret, 0, "Cannot remove multicast address");
822 
823 	/* Let the network stack to proceed */
824 	k_msleep(THREAD_SLEEP);
825 
826 	zassert_false(is_leave_msg_ok, "Received leave message when not expected");
827 
828 	net_if_flag_clear(net_iface, NET_IF_IPV6_NO_MLD);
829 }
830 
handle_mld_report(struct net_pkt * pkt,void * user_data)831 static void handle_mld_report(struct net_pkt *pkt, void *user_data)
832 {
833 	struct mld_report_info *info = (struct mld_report_info *)user_data;
834 	uint16_t res_bytes;
835 
836 	net_pkt_set_overwrite(pkt, true);
837 	net_pkt_skip(pkt, sizeof(struct net_icmp_hdr));
838 
839 	zassert_ok(net_pkt_read_be16(pkt, &res_bytes), "Failed to read reserved bytes");
840 	zassert_equal(0, res_bytes, "Reserved bytes must be zeroed");
841 
842 	zassert_ok(net_pkt_read_be16(pkt, &info->records_count), "Failed to read addr count");
843 	zexpect_between_inclusive(info->records_count, 0, MLD_REPORT_ADDR_COUNT,
844 				  "Cannot decode all addresses");
845 
846 	for (size_t i = 0; i < info->records_count; ++i) {
847 		net_pkt_read(pkt, &info->records[i], sizeof(struct mld_report_mcast_record));
848 	}
849 }
850 
get_mcast_addr_count(struct net_if * iface)851 static size_t get_mcast_addr_count(struct net_if *iface)
852 {
853 	size_t ret = 0;
854 
855 	ARRAY_FOR_EACH_PTR(iface->config.ip.ipv6->mcast, mcast_addr) {
856 		if (mcast_addr->is_used) {
857 			ret++;
858 		}
859 	}
860 
861 	return ret;
862 }
863 
add_mcast_route_and_verify(struct net_if * iface,struct in6_addr * addr,struct mld_report_info * info)864 static void add_mcast_route_and_verify(struct net_if *iface, struct in6_addr *addr,
865 				       struct mld_report_info *info)
866 {
867 	k_sem_reset(&wait_data);
868 
869 	zassert_not_null(net_route_mcast_add(iface, addr, 128), "Failed to add multicast route");
870 
871 	k_msleep(THREAD_SLEEP);
872 
873 	zassert_ok(k_sem_take(&wait_data, K_MSEC(WAIT_TIME)), "Timeout while waiting for a report");
874 
875 	zassert_equal(info->records_count, 1, "Invalid number of reported addresses");
876 	zassert_equal(info->records[0].record_type, NET_IPV6_MLDv2_CHANGE_TO_EXCLUDE_MODE,
877 		      "Invalid MLDv2 record type");
878 	zassert_mem_equal(&info->records[0].mcast_addr, addr,
879 			  sizeof(struct in6_addr), "Invalid reported address");
880 }
881 
del_mcast_route_and_verify(struct net_if * iface,struct in6_addr * addr,struct mld_report_info * info)882 static void del_mcast_route_and_verify(struct net_if *iface, struct in6_addr *addr,
883 				       struct mld_report_info *info)
884 {
885 	struct net_route_entry_mcast *entry;
886 
887 	k_sem_reset(&wait_data);
888 
889 	entry = net_route_mcast_lookup(addr);
890 
891 	zassert_not_null(entry, "Could not find the multicast route entry");
892 	zassert_true(net_route_mcast_del(entry), "Failed to delete a route");
893 
894 	k_msleep(THREAD_SLEEP);
895 
896 	zassert_ok(k_sem_take(&wait_data, K_MSEC(WAIT_TIME)), "Timeout while waiting for a report");
897 
898 	zassert_equal(info->records_count, 1, "Invalid number of reported addresses");
899 	zassert_equal(info->records[0].record_type, NET_IPV6_MLDv2_CHANGE_TO_INCLUDE_MODE,
900 		      "Invalid MLDv2 record type");
901 	zassert_mem_equal(&info->records[0].mcast_addr, addr,
902 			  sizeof(struct in6_addr), "Invalid reported address");
903 }
904 
verify_mcast_routes_in_mld(struct mld_report_info * info)905 static void verify_mcast_routes_in_mld(struct mld_report_info *info)
906 {
907 	struct net_if *dummy_iface = net_if_get_by_index(net_if_get_by_name("dummy0"));
908 	struct net_if *null_iface = net_if_get_by_index(net_if_get_by_name("dummy1"));
909 	struct in6_addr site_local_mcast_addr_abcd;
910 	struct in6_addr site_local_mcast_addr_beef;
911 	struct in6_addr site_local_mcast_addr_cafe;
912 
913 	zassert_not_null(dummy_iface, "Invalid dummy iface");
914 	zassert_not_null(null_iface, "Invalid null iface");
915 
916 	net_if_flag_set(null_iface, NET_IF_FORWARD_MULTICASTS);
917 
918 	net_ipv6_addr_create(&site_local_mcast_addr_abcd, 0xff05, 0, 0, 0, 0, 0, 0, 0xabcd);
919 	net_ipv6_addr_create(&site_local_mcast_addr_beef, 0xff05, 0, 0, 0, 0, 0, 0, 0xbeef);
920 	net_ipv6_addr_create(&site_local_mcast_addr_cafe, 0xff05, 0, 0, 0, 0, 0, 0, 0xcafe);
921 
922 	/* Next steps: verify that adding a multicast routes to a complete IPv6 address emits
923 	 * MLDv2 reports with a single entries.
924 	 */
925 	add_mcast_route_and_verify(null_iface, &site_local_mcast_addr_abcd, info);
926 	add_mcast_route_and_verify(null_iface, &site_local_mcast_addr_beef, info);
927 
928 	/* Next steps: verify that report is not sent to an iface if it has already joined
929 	 * the group.
930 	 */
931 	zassert_ok(net_ipv6_mld_join(dummy_iface, &site_local_mcast_addr_cafe),
932 		   "Failed to join a group");
933 
934 	k_msleep(THREAD_SLEEP);
935 
936 	k_sem_reset(&wait_data);
937 
938 	zassert_not_null(net_route_mcast_add(null_iface, &site_local_mcast_addr_cafe, 128),
939 			 "Failed to add multicast route");
940 
941 	k_msleep(THREAD_SLEEP);
942 
943 	zassert_equal(-EAGAIN, k_sem_take(&wait_data, K_MSEC(WAIT_TIME)), "Expected a timeout");
944 
945 	k_sem_reset(&wait_data);
946 
947 	/* Verify that multicast routes can be found in MLDv2 report and that there are
948 	 * no duplicates.
949 	 */
950 	send_query(dummy_iface);
951 
952 	k_msleep(THREAD_SLEEP);
953 
954 	zassert_ok(k_sem_take(&wait_data, K_MSEC(WAIT_TIME)), "Expected a report");
955 
956 	/* Expect 2 additional addresses as 3rd is a duplicate of iface's multicast address */
957 	zassert_equal(info->records_count, get_mcast_addr_count(dummy_iface) + 2,
958 		      "Different number of reported addresses");
959 
960 	/* Next steps: Remove routes and expect MLDv2 reports as these addresses are not
961 	 * used by the interface.
962 	 */
963 	del_mcast_route_and_verify(dummy_iface, &site_local_mcast_addr_abcd, info);
964 	del_mcast_route_and_verify(dummy_iface, &site_local_mcast_addr_beef, info);
965 
966 	/* Next steps: Remove the last route and verify that report is NOT sent as this address
967 	 * is joined by the interface itself.
968 	 */
969 	k_sem_reset(&wait_data);
970 
971 	zassert_true(net_route_mcast_del(net_route_mcast_lookup(&site_local_mcast_addr_cafe)),
972 		     "Failed to cleanup route to ff05::cafe");
973 
974 	k_msleep(THREAD_SLEEP);
975 
976 	zassert_equal(-EAGAIN, k_sem_take(&wait_data, K_MSEC(WAIT_TIME)), "Expected a timeout");
977 
978 	/* Finalize cleanup */
979 	net_ipv6_mld_leave(dummy_iface, &site_local_mcast_addr_cafe);
980 }
981 
ZTEST(net_mld_test_suite,test_mcast_routes_in_mld)982 ZTEST(net_mld_test_suite, test_mcast_routes_in_mld)
983 {
984 	struct mld_report_info info;
985 	struct mld_report_handler handler = { .fn = handle_mld_report, .user_data = &info};
986 	struct net_if *iface = net_if_get_first_by_type(&NET_L2_GET_NAME(DUMMY));
987 	char str[INET6_ADDRSTRLEN], *addr_str;
988 
989 	memset(&info, 0, sizeof(info));
990 
991 	join_mldv2_capable_routers_group();
992 
993 	/* Enable report handler */
994 	report_handler = &handler;
995 
996 	k_msleep(THREAD_SLEEP);
997 
998 	k_sem_reset(&wait_data);
999 
1000 	send_query(iface);
1001 
1002 	k_msleep(THREAD_SLEEP);
1003 
1004 	zassert_ok(k_sem_take(&wait_data, K_MSEC(WAIT_TIME)), "Timeout while waiting for a report");
1005 
1006 	for (int i = 0; i < info.records_count; ++i) {
1007 		addr_str = zsock_inet_ntop(AF_INET6, &info.records[i].mcast_addr, str, sizeof(str));
1008 	}
1009 
1010 	/* 1. Expect that report contains all iface's multicast addressses and no route */
1011 	zassert_equal(info.records_count, get_mcast_addr_count(iface),
1012 		      "Different number of reported addresses");
1013 
1014 	/* 2. If CONFIG_NET_MCAST_ROUTE_MLD_REPORTS is enabled check that funtionality works */
1015 	if (IS_ENABLED(CONFIG_NET_MCAST_ROUTE_MLD_REPORTS)) {
1016 		verify_mcast_routes_in_mld(&info);
1017 	}
1018 
1019 	leave_mldv2_capable_routers_group();
1020 }
1021 
socket_group_with_index(const struct in6_addr * local_addr,bool do_join)1022 static void socket_group_with_index(const struct in6_addr *local_addr, bool do_join)
1023 {
1024 	struct ipv6_mreq mreq = { 0 };
1025 	int option;
1026 	int ret, fd;
1027 
1028 	if (do_join) {
1029 		option = IPV6_ADD_MEMBERSHIP;
1030 	} else {
1031 		option = IPV6_DROP_MEMBERSHIP;
1032 	}
1033 
1034 	fd = zsock_socket(AF_INET6, SOCK_DGRAM, 0);
1035 	zassert_true(fd >= 0, "Cannot get socket (%d)", -errno);
1036 
1037 	ret = zsock_setsockopt(fd, IPPROTO_IPV6, option,
1038 			       NULL, sizeof(mreq));
1039 	zassert_true(ret == -1 && errno == EINVAL,
1040 		     "Incorrect return value (%d)", -errno);
1041 
1042 	ret = zsock_setsockopt(fd, IPPROTO_IPV6, option,
1043 			       (void *)&mreq, 1);
1044 	zassert_true(ret == -1 && errno == EINVAL,
1045 		     "Incorrect return value (%d)", -errno);
1046 
1047 	/* First try with empty mreq */
1048 	ret = zsock_setsockopt(fd, IPPROTO_IPV6, option,
1049 			       (void *)&mreq, sizeof(mreq));
1050 	zassert_true(ret == -1 && errno == EINVAL,
1051 		     "Incorrect return value (%d)", -errno);
1052 
1053 	mreq.ipv6mr_ifindex = net_if_ipv6_addr_lookup_by_index(local_addr);
1054 	memcpy(&mreq.ipv6mr_multiaddr, &mcast_addr,
1055 	       sizeof(mreq.ipv6mr_multiaddr));
1056 
1057 	ret = zsock_setsockopt(fd, IPPROTO_IPV6, option,
1058 			       (void *)&mreq, sizeof(mreq));
1059 
1060 	if (do_join) {
1061 		if (ignore_already) {
1062 			zassert_true(ret == 0 || ret == -EALREADY,
1063 				     "Cannot join IPv6 multicast group (%d)",
1064 				     -errno);
1065 		} else {
1066 			zassert_equal(ret, 0,
1067 				      "Cannot join IPv6 multicast group (%d)",
1068 				      -errno);
1069 		}
1070 	} else {
1071 		zassert_equal(ret, 0, "Cannot leave IPv6 multicast group (%d)",
1072 			      -errno);
1073 
1074 		if (IS_ENABLED(CONFIG_NET_TC_THREAD_PREEMPTIVE)) {
1075 			/* Let the network stack to proceed */
1076 			k_msleep(THREAD_SLEEP);
1077 		} else {
1078 			k_yield();
1079 		}
1080 	}
1081 
1082 	zsock_close(fd);
1083 
1084 	/* Let the network stack to proceed */
1085 	k_msleep(THREAD_SLEEP);
1086 }
1087 
socket_join_group_with_index(const struct in6_addr * addr)1088 static void socket_join_group_with_index(const struct in6_addr *addr)
1089 {
1090 	socket_group_with_index(addr, true);
1091 }
1092 
socket_leave_group_with_index(const struct in6_addr * addr)1093 static void socket_leave_group_with_index(const struct in6_addr *addr)
1094 {
1095 	socket_group_with_index(addr, false);
1096 }
1097 
ZTEST_USER(net_mld_test_suite,test_socket_catch_join_with_index)1098 ZTEST_USER(net_mld_test_suite, test_socket_catch_join_with_index)
1099 {
1100 	socket_join_group_with_index(net_ipv6_unspecified_address());
1101 	socket_leave_group_with_index(net_ipv6_unspecified_address());
1102 	socket_join_group_with_index(&my_addr);
1103 	socket_leave_group_with_index(&my_addr);
1104 }
1105 
1106 ZTEST_SUITE(net_mld_test_suite, NULL, test_mld_setup, test_mld_before, NULL, NULL);
1107