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