1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2015 National Instruments
4 *
5 * (C) Copyright 2015
6 * Joe Hershberger <joe.hershberger@ni.com>
7 */
8
9#include <common.h>
10#include <dm.h>
11#include <env.h>
12#include <fdtdec.h>
13#include <log.h>
14#include <malloc.h>
15#include <net.h>
16#include <net6.h>
17#include <asm/eth.h>
18#include <dm/test.h>
19#include <dm/device-internal.h>
20#include <dm/uclass-internal.h>
21#include <test/test.h>
22#include <test/ut.h>
23#include <ndisc.h>
24
25#define DM_TEST_ETH_NUM		4
26
27#if IS_ENABLED(CONFIG_IPV6)
28static int dm_test_string_to_ip6(struct unit_test_state *uts)
29{
30	char *str;
31	struct test_ip6_pair {
32		char 		*string_addr;
33		struct in6_addr ip6_addr;
34	};
35
36	struct in6_addr ip6 = {0};
37
38	/* Correct statements */
39	struct test_ip6_pair test_suite[] = {
40		{"2001:db8::0:1234:1", {.s6_addr32[0] = 0xb80d0120,
41					.s6_addr32[1] = 0x00000000,
42					.s6_addr32[2] = 0x00000000,
43					.s6_addr32[3] = 0x01003412}},
44		{"2001:0db8:0000:0000:0000:0000:1234:0001",
45				       {.s6_addr32[0] = 0xb80d0120,
46					.s6_addr32[1] = 0x00000000,
47					.s6_addr32[2] = 0x00000000,
48					.s6_addr32[3] = 0x01003412}},
49		{"::1", 	       {.s6_addr32[0] = 0x00000000,
50					.s6_addr32[1] = 0x00000000,
51					.s6_addr32[2] = 0x00000000,
52					.s6_addr32[3] = 0x01000000}},
53		{"::ffff:192.168.1.1", {.s6_addr32[0] = 0x00000000,
54					.s6_addr32[1] = 0x00000000,
55					.s6_addr32[2] = 0xffff0000,
56					.s6_addr32[3] = 0x0101a8c0}},
57	};
58
59	for (int i = 0; i < ARRAY_SIZE(test_suite); ++i) {
60		ut_assertok(string_to_ip6(test_suite[i].string_addr,
61			    strlen(test_suite[i].string_addr), &ip6));
62		ut_asserteq_mem(&ip6, &test_suite[i].ip6_addr,
63				sizeof(struct in6_addr));
64	}
65
66	/* Incorrect statements */
67	str = "hello:world";
68	ut_assertok(!string_to_ip6(str, strlen(str), &ip6));
69	str = "2001:db8::0::0";
70	ut_assertok(!string_to_ip6(str, strlen(str), &ip6));
71	str = "2001:db8:192.168.1.1::1";
72	ut_assertok(!string_to_ip6(str, strlen(str), &ip6));
73	str = "192.168.1.1";
74	ut_assertok(!string_to_ip6(str, strlen(str), &ip6));
75
76	return 0;
77}
78DM_TEST(dm_test_string_to_ip6, 0);
79
80static int dm_test_csum_ipv6_magic(struct unit_test_state *uts)
81{
82	unsigned short csum = 0xbeef;
83	/* Predefined correct parameters */
84	unsigned short correct_csum = 0xd8ac;
85	struct in6_addr saddr = {.s6_addr32[0] = 0x000080fe,
86				 .s6_addr32[1] = 0x00000000,
87				 .s6_addr32[2] = 0xffe9f242,
88				 .s6_addr32[3] = 0xe8f66dfe};
89	struct in6_addr daddr = {.s6_addr32[0] = 0x000080fe,
90				 .s6_addr32[1] = 0x00000000,
91				 .s6_addr32[2] = 0xffd5b372,
92				 .s6_addr32[3] = 0x3ef692fe};
93	u16 len = 1460;
94	unsigned short proto = 17;
95	unsigned int head_csum = 0x91f0;
96
97	csum = csum_ipv6_magic(&saddr, &daddr, len, proto, head_csum);
98	ut_asserteq(csum, correct_csum);
99
100	/* Broke a parameter */
101	proto--;
102	csum = csum_ipv6_magic(&saddr, &daddr, len, proto, head_csum);
103	ut_assert(csum != correct_csum);
104
105	return 0;
106}
107DM_TEST(dm_test_csum_ipv6_magic, 0);
108
109static int dm_test_ip6_addr_in_subnet(struct unit_test_state *uts)
110{
111	struct in6_addr our = {.s6_addr32[0] = 0x000080fe,
112				 .s6_addr32[1] = 0x00000000,
113				 .s6_addr32[2] = 0xffe9f242,
114				 .s6_addr32[3] = 0xe8f66dfe};
115	struct in6_addr neigh1 = {.s6_addr32[0] = 0x000080fe,
116				 .s6_addr32[1] = 0x00000000,
117				 .s6_addr32[2] = 0xffd5b372,
118				 .s6_addr32[3] = 0x3ef692fe};
119	struct in6_addr neigh2 = {.s6_addr32[0] = 0x60480120,
120				 .s6_addr32[1] = 0x00006048,
121				 .s6_addr32[2] = 0x00000000,
122				 .s6_addr32[3] = 0x00008888};
123
124	/* in */
125	ut_assert(ip6_addr_in_subnet(&our, &neigh1, 64));
126	/* outside */
127	ut_assert(!ip6_addr_in_subnet(&our, &neigh2, 64));
128	ut_assert(!ip6_addr_in_subnet(&our, &neigh1, 128));
129
130	return 0;
131}
132DM_TEST(dm_test_ip6_addr_in_subnet, 0);
133
134static int dm_test_ip6_make_snma(struct unit_test_state *uts)
135{
136	struct in6_addr mult = {0};
137	struct in6_addr correct_addr = {
138				 .s6_addr32[0] = 0x000002ff,
139				 .s6_addr32[1] = 0x00000000,
140				 .s6_addr32[2] = 0x01000000,
141				 .s6_addr32[3] = 0xe8f66dff};
142	struct in6_addr addr = { .s6_addr32[0] = 0x000080fe,
143				 .s6_addr32[1] = 0x00000000,
144				 .s6_addr32[2] = 0xffe9f242,
145				 .s6_addr32[3] = 0xe8f66dfe};
146
147	ip6_make_snma(&mult, &addr);
148	ut_asserteq_mem(&mult, &correct_addr, sizeof(struct in6_addr));
149
150	return 0;
151}
152DM_TEST(dm_test_ip6_make_snma, 0);
153
154static int dm_test_ip6_make_lladdr(struct unit_test_state *uts)
155{
156	struct in6_addr generated_lladdr = {0};
157	struct in6_addr correct_lladdr = {
158				 .s6_addr32[0] = 0x000080fe,
159				 .s6_addr32[1] = 0x00000000,
160				 .s6_addr32[2] = 0xffabf33a,
161				 .s6_addr32[3] = 0xfbb352fe};
162	const unsigned char mac[6] = {0x38, 0xf3, 0xab, 0x52, 0xb3, 0xfb};
163
164	ip6_make_lladdr(&generated_lladdr, mac);
165	ut_asserteq_mem(&generated_lladdr, &correct_lladdr,
166			sizeof(struct in6_addr));
167
168	return 0;
169}
170DM_TEST(dm_test_ip6_make_lladdr, UT_TESTF_SCAN_FDT);
171#endif
172
173static int dm_test_eth(struct unit_test_state *uts)
174{
175	net_ping_ip = string_to_ip("1.1.2.2");
176
177	env_set("ethact", "eth@10002000");
178	ut_assertok(net_loop(PING));
179	ut_asserteq_str("eth@10002000", env_get("ethact"));
180
181	env_set("ethact", "eth@10003000");
182	ut_assertok(net_loop(PING));
183	ut_asserteq_str("eth@10003000", env_get("ethact"));
184
185	env_set("ethact", "eth@10004000");
186	ut_assertok(net_loop(PING));
187	ut_asserteq_str("eth@10004000", env_get("ethact"));
188
189	return 0;
190}
191DM_TEST(dm_test_eth, UT_TESTF_SCAN_FDT);
192
193static int dm_test_eth_alias(struct unit_test_state *uts)
194{
195	net_ping_ip = string_to_ip("1.1.2.2");
196	env_set("ethact", "eth0");
197	ut_assertok(net_loop(PING));
198	ut_asserteq_str("eth@10002000", env_get("ethact"));
199
200	env_set("ethact", "eth6");
201	ut_assertok(net_loop(PING));
202	ut_asserteq_str("eth@10004000", env_get("ethact"));
203
204	/* Expected to fail since eth1 is not defined in the device tree */
205	env_set("ethact", "eth1");
206	ut_assertok(net_loop(PING));
207	ut_asserteq_str("eth@10002000", env_get("ethact"));
208
209	env_set("ethact", "eth5");
210	ut_assertok(net_loop(PING));
211	ut_asserteq_str("eth@10003000", env_get("ethact"));
212
213	return 0;
214}
215DM_TEST(dm_test_eth_alias, UT_TESTF_SCAN_FDT);
216
217static int dm_test_eth_prime(struct unit_test_state *uts)
218{
219	net_ping_ip = string_to_ip("1.1.2.2");
220
221	/* Expected to be "eth@10003000" because of ethprime variable */
222	env_set("ethact", NULL);
223	env_set("ethprime", "eth5");
224	ut_assertok(net_loop(PING));
225	ut_asserteq_str("eth@10003000", env_get("ethact"));
226
227	/* Expected to be "eth@10002000" because it is first */
228	env_set("ethact", NULL);
229	env_set("ethprime", NULL);
230	ut_assertok(net_loop(PING));
231	ut_asserteq_str("eth@10002000", env_get("ethact"));
232
233	return 0;
234}
235DM_TEST(dm_test_eth_prime, UT_TESTF_SCAN_FDT);
236
237/**
238 * This test case is trying to test the following scenario:
239 *	- All ethernet devices are not probed
240 *	- "ethaddr" for all ethernet devices are not set
241 *	- "ethact" is set to a valid ethernet device name
242 *
243 * With Sandbox default test configuration, all ethernet devices are
244 * probed after power-up, so we have to manually create such scenario:
245 *	- Remove all ethernet devices
246 *	- Remove all "ethaddr" environment variables
247 *	- Set "ethact" to the first ethernet device
248 *
249 * Do a ping test to see if anything goes wrong.
250 */
251static int dm_test_eth_act(struct unit_test_state *uts)
252{
253	struct udevice *dev[DM_TEST_ETH_NUM];
254	const char *ethname[DM_TEST_ETH_NUM] = {"eth@10002000", "eth@10003000",
255						"sbe5", "eth@10004000"};
256	const char *addrname[DM_TEST_ETH_NUM] = {"ethaddr", "eth5addr",
257						 "eth3addr", "eth6addr"};
258	char ethaddr[DM_TEST_ETH_NUM][18];
259	int i;
260
261	memset(ethaddr, '\0', sizeof(ethaddr));
262	net_ping_ip = string_to_ip("1.1.2.2");
263
264	/* Prepare the test scenario */
265	for (i = 0; i < DM_TEST_ETH_NUM; i++) {
266		char *addr;
267
268		ut_assertok(uclass_find_device_by_name(UCLASS_ETH,
269						       ethname[i], &dev[i]));
270		ut_assertok(device_remove(dev[i], DM_REMOVE_NORMAL));
271
272		/* Invalidate MAC address */
273		addr = env_get(addrname[i]);
274		ut_assertnonnull(addr);
275		strncpy(ethaddr[i], addr, 17);
276		/* Must disable access protection for ethaddr before clearing */
277		env_set(".flags", addrname[i]);
278		env_set(addrname[i], NULL);
279	}
280
281	/* Set ethact to "eth@10002000" */
282	env_set("ethact", ethname[0]);
283
284	/* Segment fault might happen if something is wrong */
285	ut_asserteq(-ENODEV, net_loop(PING));
286
287	for (i = 0; i < DM_TEST_ETH_NUM; i++) {
288		/* Restore the env */
289		env_set(".flags", addrname[i]);
290		env_set(addrname[i], ethaddr[i]);
291
292		/* Probe the device again */
293		ut_assertok(device_probe(dev[i]));
294	}
295	env_set(".flags", NULL);
296	env_set("ethact", NULL);
297
298	return 0;
299}
300DM_TEST(dm_test_eth_act, UT_TESTF_SCAN_FDT);
301
302/* Ensure that all addresses are loaded properly */
303static int dm_test_ethaddr(struct unit_test_state *uts)
304{
305	static const char *const addr[] = {
306		"02:00:11:22:33:44",
307		"02:00:11:22:33:48", /* dsa slave */
308		"02:00:11:22:33:45",
309		"02:00:11:22:33:48", /* dsa master */
310		"02:00:11:22:33:46",
311		"02:00:11:22:33:47",
312		"02:00:11:22:33:48", /* dsa slave */
313		"02:00:11:22:33:49",
314	};
315	int i;
316
317	for (i = 0; i < ARRAY_SIZE(addr); i++) {
318		char addrname[10];
319		char *env_addr;
320
321		if (i)
322			snprintf(addrname, sizeof(addrname), "eth%daddr", i + 1);
323		else
324			strcpy(addrname, "ethaddr");
325
326		env_addr = env_get(addrname);
327		ut_assertnonnull(env_addr);
328		ut_asserteq_str(addr[i], env_addr);
329	}
330
331	return 0;
332}
333DM_TEST(dm_test_ethaddr, UT_TESTF_SCAN_FDT);
334
335/* The asserts include a return on fail; cleanup in the caller */
336static int _dm_test_eth_rotate1(struct unit_test_state *uts)
337{
338	/* Make sure that the default is to rotate to the next interface */
339	env_set("ethact", "eth@10004000");
340	ut_assertok(net_loop(PING));
341	ut_asserteq_str("eth@10002000", env_get("ethact"));
342
343	/* If ethrotate is no, then we should fail on a bad MAC */
344	env_set("ethact", "eth@10004000");
345	env_set("ethrotate", "no");
346	ut_asserteq(-EINVAL, net_loop(PING));
347	ut_asserteq_str("eth@10004000", env_get("ethact"));
348
349	return 0;
350}
351
352static int _dm_test_eth_rotate2(struct unit_test_state *uts)
353{
354	/* Make sure we can skip invalid devices */
355	env_set("ethact", "eth@10004000");
356	ut_assertok(net_loop(PING));
357	ut_asserteq_str("eth@10004000", env_get("ethact"));
358
359	/* Make sure we can handle device name which is not eth# */
360	env_set("ethact", "sbe5");
361	ut_assertok(net_loop(PING));
362	ut_asserteq_str("sbe5", env_get("ethact"));
363
364	return 0;
365}
366
367static int dm_test_eth_rotate(struct unit_test_state *uts)
368{
369	char ethaddr[18];
370	int retval;
371
372	/* Set target IP to mock ping */
373	net_ping_ip = string_to_ip("1.1.2.2");
374
375	/* Invalidate eth1's MAC address */
376	memset(ethaddr, '\0', sizeof(ethaddr));
377	strncpy(ethaddr, env_get("eth6addr"), 17);
378	/* Must disable access protection for eth6addr before clearing */
379	env_set(".flags", "eth6addr");
380	env_set("eth6addr", NULL);
381
382	retval = _dm_test_eth_rotate1(uts);
383
384	/* Restore the env */
385	env_set("eth6addr", ethaddr);
386	env_set("ethrotate", NULL);
387
388	if (!retval) {
389		/* Invalidate eth0's MAC address */
390		strncpy(ethaddr, env_get("ethaddr"), 17);
391		/* Must disable access protection for ethaddr before clearing */
392		env_set(".flags", "ethaddr");
393		env_set("ethaddr", NULL);
394
395		retval = _dm_test_eth_rotate2(uts);
396
397		/* Restore the env */
398		env_set("ethaddr", ethaddr);
399	}
400	/* Restore the env */
401	env_set(".flags", NULL);
402
403	return retval;
404}
405DM_TEST(dm_test_eth_rotate, UT_TESTF_SCAN_FDT);
406
407/* The asserts include a return on fail; cleanup in the caller */
408static int _dm_test_net_retry(struct unit_test_state *uts)
409{
410	/*
411	 * eth1 is disabled and netretry is yes, so the ping should succeed and
412	 * the active device should be eth0
413	 */
414	sandbox_eth_disable_response(1, true);
415	env_set("ethact", "lan1");
416	env_set("netretry", "yes");
417	sandbox_eth_skip_timeout();
418	ut_assertok(net_loop(PING));
419	ut_asserteq_str("eth@10002000", env_get("ethact"));
420
421	/*
422	 * eth1 is disabled and netretry is no, so the ping should fail and the
423	 * active device should be eth1
424	 */
425	env_set("ethact", "lan1");
426	env_set("netretry", "no");
427	sandbox_eth_skip_timeout();
428	ut_asserteq(-ENONET, net_loop(PING));
429	ut_asserteq_str("lan1", env_get("ethact"));
430
431	return 0;
432}
433
434static int dm_test_net_retry(struct unit_test_state *uts)
435{
436	int retval;
437
438	net_ping_ip = string_to_ip("1.1.2.2");
439
440	retval = _dm_test_net_retry(uts);
441
442	/* Restore the env */
443	env_set("netretry", NULL);
444	sandbox_eth_disable_response(1, false);
445
446	return retval;
447}
448DM_TEST(dm_test_net_retry, UT_TESTF_SCAN_FDT);
449
450static int sb_check_arp_reply(struct udevice *dev, void *packet,
451			      unsigned int len)
452{
453	struct eth_sandbox_priv *priv = dev_get_priv(dev);
454	struct ethernet_hdr *eth = packet;
455	struct arp_hdr *arp;
456	/* Used by all of the ut_assert macros */
457	struct unit_test_state *uts = priv->priv;
458
459	if (ntohs(eth->et_protlen) != PROT_ARP)
460		return 0;
461
462	arp = packet + ETHER_HDR_SIZE;
463
464	if (ntohs(arp->ar_op) != ARPOP_REPLY)
465		return 0;
466
467	/* This test would be worthless if we are not waiting */
468	ut_assert(arp_is_waiting());
469
470	/* Validate response */
471	ut_asserteq_mem(eth->et_src, net_ethaddr, ARP_HLEN);
472	ut_asserteq_mem(eth->et_dest, priv->fake_host_hwaddr, ARP_HLEN);
473	ut_assert(eth->et_protlen == htons(PROT_ARP));
474
475	ut_assert(arp->ar_hrd == htons(ARP_ETHER));
476	ut_assert(arp->ar_pro == htons(PROT_IP));
477	ut_assert(arp->ar_hln == ARP_HLEN);
478	ut_assert(arp->ar_pln == ARP_PLEN);
479	ut_asserteq_mem(&arp->ar_sha, net_ethaddr, ARP_HLEN);
480	ut_assert(net_read_ip(&arp->ar_spa).s_addr == net_ip.s_addr);
481	ut_asserteq_mem(&arp->ar_tha, priv->fake_host_hwaddr, ARP_HLEN);
482	ut_assert(net_read_ip(&arp->ar_tpa).s_addr ==
483		  string_to_ip("1.1.2.4").s_addr);
484
485	return 0;
486}
487
488static int sb_with_async_arp_handler(struct udevice *dev, void *packet,
489				     unsigned int len)
490{
491	struct eth_sandbox_priv *priv = dev_get_priv(dev);
492	struct ethernet_hdr *eth = packet;
493	struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
494	int ret;
495
496	/*
497	 * If we are about to generate a reply to ARP, first inject a request
498	 * from another host
499	 */
500	if (ntohs(eth->et_protlen) == PROT_ARP &&
501	    ntohs(arp->ar_op) == ARPOP_REQUEST) {
502		/* Make sure sandbox_eth_recv_arp_req() knows who is asking */
503		priv->fake_host_ipaddr = string_to_ip("1.1.2.4");
504
505		ret = sandbox_eth_recv_arp_req(dev);
506		if (ret)
507			return ret;
508	}
509
510	sandbox_eth_arp_req_to_reply(dev, packet, len);
511	sandbox_eth_ping_req_to_reply(dev, packet, len);
512
513	return sb_check_arp_reply(dev, packet, len);
514}
515
516static int dm_test_eth_async_arp_reply(struct unit_test_state *uts)
517{
518	net_ping_ip = string_to_ip("1.1.2.2");
519
520	sandbox_eth_set_tx_handler(0, sb_with_async_arp_handler);
521	/* Used by all of the ut_assert macros in the tx_handler */
522	sandbox_eth_set_priv(0, uts);
523
524	env_set("ethact", "eth@10002000");
525	ut_assertok(net_loop(PING));
526	ut_asserteq_str("eth@10002000", env_get("ethact"));
527
528	sandbox_eth_set_tx_handler(0, NULL);
529
530	return 0;
531}
532
533DM_TEST(dm_test_eth_async_arp_reply, UT_TESTF_SCAN_FDT);
534
535static int sb_check_ping_reply(struct udevice *dev, void *packet,
536			       unsigned int len)
537{
538	struct eth_sandbox_priv *priv = dev_get_priv(dev);
539	struct ethernet_hdr *eth = packet;
540	struct ip_udp_hdr *ip;
541	struct icmp_hdr *icmp;
542	/* Used by all of the ut_assert macros */
543	struct unit_test_state *uts = priv->priv;
544
545	if (ntohs(eth->et_protlen) != PROT_IP)
546		return 0;
547
548	ip = packet + ETHER_HDR_SIZE;
549
550	if (ip->ip_p != IPPROTO_ICMP)
551		return 0;
552
553	icmp = (struct icmp_hdr *)&ip->udp_src;
554
555	if (icmp->type != ICMP_ECHO_REPLY)
556		return 0;
557
558	/* This test would be worthless if we are not waiting */
559	ut_assert(arp_is_waiting());
560
561	/* Validate response */
562	ut_asserteq_mem(eth->et_src, net_ethaddr, ARP_HLEN);
563	ut_asserteq_mem(eth->et_dest, priv->fake_host_hwaddr, ARP_HLEN);
564	ut_assert(eth->et_protlen == htons(PROT_IP));
565
566	ut_assert(net_read_ip(&ip->ip_src).s_addr == net_ip.s_addr);
567	ut_assert(net_read_ip(&ip->ip_dst).s_addr ==
568		  string_to_ip("1.1.2.4").s_addr);
569
570	return 0;
571}
572
573static int sb_with_async_ping_handler(struct udevice *dev, void *packet,
574				      unsigned int len)
575{
576	struct eth_sandbox_priv *priv = dev_get_priv(dev);
577	struct ethernet_hdr *eth = packet;
578	struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
579	int ret;
580
581	/*
582	 * If we are about to generate a reply to ARP, first inject a request
583	 * from another host
584	 */
585	if (ntohs(eth->et_protlen) == PROT_ARP &&
586	    ntohs(arp->ar_op) == ARPOP_REQUEST) {
587		/* Make sure sandbox_eth_recv_arp_req() knows who is asking */
588		priv->fake_host_ipaddr = string_to_ip("1.1.2.4");
589
590		ret = sandbox_eth_recv_ping_req(dev);
591		if (ret)
592			return ret;
593	}
594
595	sandbox_eth_arp_req_to_reply(dev, packet, len);
596	sandbox_eth_ping_req_to_reply(dev, packet, len);
597
598	return sb_check_ping_reply(dev, packet, len);
599}
600
601static int dm_test_eth_async_ping_reply(struct unit_test_state *uts)
602{
603	net_ping_ip = string_to_ip("1.1.2.2");
604
605	sandbox_eth_set_tx_handler(0, sb_with_async_ping_handler);
606	/* Used by all of the ut_assert macros in the tx_handler */
607	sandbox_eth_set_priv(0, uts);
608
609	env_set("ethact", "eth@10002000");
610	ut_assertok(net_loop(PING));
611	ut_asserteq_str("eth@10002000", env_get("ethact"));
612
613	sandbox_eth_set_tx_handler(0, NULL);
614
615	return 0;
616}
617
618DM_TEST(dm_test_eth_async_ping_reply, UT_TESTF_SCAN_FDT);
619
620#if IS_ENABLED(CONFIG_IPV6_ROUTER_DISCOVERY)
621
622static u8 ip6_ra_buf[] = {0x60, 0xf, 0xc5, 0x4a, 0x0, 0x38, 0x3a, 0xff, 0xfe,
623			  0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x85, 0xe6,
624			  0x29, 0x77, 0xcb, 0xc8, 0x53, 0xff, 0x2, 0x0, 0x0,
625			  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
626			  0x1, 0x86, 0x0, 0xdc, 0x90, 0x40, 0x80, 0x15, 0x18,
627			  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x4,
628			  0x40, 0xc0, 0x0, 0x0, 0x37, 0xdc, 0x0, 0x0, 0x37,
629			  0x78, 0x0, 0x0, 0x0, 0x0, 0x20, 0x1, 0xca, 0xfe, 0xca,
630			  0xfe, 0xca, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
631			  0x0, 0x1, 0x1, 0x0, 0x15, 0x5d, 0xe2, 0x8a, 0x2};
632
633static int dm_test_validate_ra(struct unit_test_state *uts)
634{
635	struct ip6_hdr *ip6 = (struct ip6_hdr *)ip6_ra_buf;
636	struct icmp6hdr *icmp = (struct icmp6hdr *)(ip6 + 1);
637	__be16 temp = 0;
638
639	ut_assert(validate_ra(ip6) == true);
640
641	temp = ip6->payload_len;
642	ip6->payload_len = 15;
643	ut_assert(validate_ra(ip6) == false);
644	ip6->payload_len = temp;
645
646	temp = ip6->saddr.s6_addr16[0];
647	ip6->saddr.s6_addr16[0] = 0x2001;
648	ut_assert(validate_ra(ip6) == false);
649	ip6->saddr.s6_addr16[0] = temp;
650
651	temp = ip6->hop_limit;
652	ip6->hop_limit = 15;
653	ut_assert(validate_ra(ip6) == false);
654	ip6->hop_limit = temp;
655
656	temp = icmp->icmp6_code;
657	icmp->icmp6_code = 15;
658	ut_assert(validate_ra(ip6) == false);
659	icmp->icmp6_code = temp;
660
661	return 0;
662}
663
664DM_TEST(dm_test_validate_ra, 0);
665
666static int dm_test_process_ra(struct unit_test_state *uts)
667{
668	int len = sizeof(ip6_ra_buf);
669	struct ip6_hdr *ip6 = (struct ip6_hdr *)ip6_ra_buf;
670	struct icmp6hdr *icmp = (struct icmp6hdr *)(ip6 + 1);
671	struct ra_msg *msg = (struct ra_msg *)icmp;
672	unsigned char *option = msg->opt;
673	struct icmp6_ra_prefix_info *prefix =
674					(struct icmp6_ra_prefix_info *)option;
675	__be16 temp = 0;
676	unsigned char option_len = option[1];
677
678	ut_assert(process_ra(ip6, len) == 0);
679
680	temp = icmp->icmp6_rt_lifetime;
681	icmp->icmp6_rt_lifetime = 0;
682	ut_assert(process_ra(ip6, len) != 0);
683	icmp->icmp6_rt_lifetime = temp;
684
685	ut_assert(process_ra(ip6, 0) != 0);
686
687	option[1] = 0;
688	ut_assert(process_ra(ip6, len) != 0);
689	option[1] = option_len;
690
691	prefix->on_link = false;
692	ut_assert(process_ra(ip6, len) != 0);
693	prefix->on_link = true;
694
695	temp = prefix->prefix.s6_addr16[0];
696	prefix->prefix.s6_addr16[0] = 0x80fe;
697	ut_assert(process_ra(ip6, len) != 0);
698	prefix->prefix.s6_addr16[0] = temp;
699
700	return 0;
701}
702
703DM_TEST(dm_test_process_ra, 0);
704
705#endif
706