]> Git Repo - J-u-boot.git/blame - net/net.c
Merge tag 'fsl-qoriq-2022-10-18' of https://source.denx.de/u-boot/custodians/u-boot...
[J-u-boot.git] / net / net.c
CommitLineData
f739fcd8 1// SPDX-License-Identifier: GPL-2.0
2d966958
WD
2/*
3 * Copied from Linux Monitor (LiMon) - Networking.
4 *
5 * Copyright 1994 - 2000 Neil Russell.
6 * (See License)
7 * Copyright 2000 Roland Borde
8 * Copyright 2000 Paolo Scaffardi
9 * Copyright 2000-2002 Wolfgang Denk, [email protected]
10 */
11
12/*
13 * General Desription:
14 *
15 * The user interface supports commands for BOOTP, RARP, and TFTP.
16 * Also, we support ARP internally. Depending on available data,
17 * these interact as follows:
18 *
19 * BOOTP:
20 *
21 * Prerequisites: - own ethernet address
22 * We want: - own IP address
23 * - TFTP server IP address
24 * - name of bootfile
25 * Next step: ARP
26 *
d22c338e
JH
27 * LINK_LOCAL:
28 *
29 * Prerequisites: - own ethernet address
30 * We want: - own IP address
31 * Next step: ARP
32 *
2d966958
WD
33 * RARP:
34 *
35 * Prerequisites: - own ethernet address
36 * We want: - own IP address
37 * - TFTP server IP address
38 * Next step: ARP
39 *
40 * ARP:
41 *
42 * Prerequisites: - own ethernet address
43 * - own IP address
44 * - TFTP server IP address
45 * We want: - TFTP server ethernet address
46 * Next step: TFTP
47 *
48 * DHCP:
49 *
b2f50807
WD
50 * Prerequisites: - own ethernet address
51 * We want: - IP, Netmask, ServerIP, Gateway IP
52 * - bootfilename, lease time
53 * Next step: - TFTP
2d966958
WD
54 *
55 * TFTP:
56 *
57 * Prerequisites: - own ethernet address
58 * - own IP address
59 * - TFTP server IP address
60 * - TFTP server ethernet address
61 * - name of bootfile (if unknown, we use a default name
62 * derived from our own IP address)
63 * We want: - load the boot file
64 * Next step: none
cbd8a35c
WD
65 *
66 * NFS:
67 *
68 * Prerequisites: - own ethernet address
69 * - own IP address
70 * - name of bootfile (if unknown, we use a default name
71 * derived from our own IP address)
72 * We want: - load the boot file
73 * Next step: none
ea287deb 74 *
d8970dae
LF
75 *
76 * WOL:
77 *
78 * Prerequisites: - own ethernet address
79 * We want: - magic packet or timeout
80 * Next step: none
2d966958
WD
81 */
82
83
84#include <common.h>
52f24238 85#include <bootstage.h>
2d966958 86#include <command.h>
24b852a7 87#include <console.h>
c7694dd4 88#include <env.h>
f3998fdc 89#include <env_internal.h>
60304592 90#include <errno.h>
8e8ccfe1 91#include <image.h>
f7ae49fc 92#include <log.h>
2d966958 93#include <net.h>
f73a7df9 94#include <net/fastboot.h>
34696958 95#include <net/tftp.h>
09bd3d0b 96#include <net/ncsi.h>
3eaac630
RF
97#if defined(CONFIG_CMD_PCAP)
98#include <net/pcap.h>
99#endif
b43ea1bf 100#include <net/udp.h>
2d8d190c 101#if defined(CONFIG_LED_STATUS)
fc3e2165 102#include <miiphy.h>
4545f4e6 103#include <status_led.h>
fc3e2165 104#endif
4545f4e6
JH
105#include <watchdog.h>
106#include <linux/compiler.h>
107#include "arp.h"
108#include "bootp.h"
f575ae1f 109#include "cdp.h"
1a32bf41
RG
110#if defined(CONFIG_CMD_DNS)
111#include "dns.h"
112#endif
d22c338e 113#include "link_local.h"
4545f4e6 114#include "nfs.h"
a36b12f9 115#include "ping.h"
4545f4e6 116#include "rarp.h"
d8970dae
LF
117#if defined(CONFIG_CMD_WOL)
118#include "wol.h"
119#endif
2d966958 120
2d966958
WD
121/** BOOTP EXTENTIONS **/
122
3e38e429 123/* Our subnet mask (0=unknown) */
049a95a7 124struct in_addr net_netmask;
3e38e429 125/* Our gateways IP address */
049a95a7 126struct in_addr net_gateway;
3e38e429 127/* Our DNS IP address */
049a95a7 128struct in_addr net_dns_server;
1fe80d79 129#if defined(CONFIG_BOOTP_DNS2)
3e38e429 130/* Our 2nd DNS IP address */
049a95a7 131struct in_addr net_dns_server2;
3e38e429 132#endif
2d966958
WD
133
134/** END OF BOOTP EXTENTIONS **/
135
3e38e429 136/* Our ethernet address */
0adb5b76 137u8 net_ethaddr[6];
3e38e429 138/* Boot server enet address */
0adb5b76 139u8 net_server_ethaddr[6];
3e38e429 140/* Our IP addr (0 = unknown) */
049a95a7 141struct in_addr net_ip;
3e38e429 142/* Server IP addr (0 = unknown) */
049a95a7 143struct in_addr net_server_ip;
3e38e429 144/* Current receive packet */
1203fcce 145uchar *net_rx_packet;
3e38e429 146/* Current rx packet length */
1203fcce 147int net_rx_packet_len;
3e38e429 148/* IP packet ID */
bc0571fc 149static unsigned net_ip_id;
3e38e429 150/* Ethernet bcast address */
0adb5b76
JH
151const u8 net_bcast_ethaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
152const u8 net_null_ethaddr[6];
0efe1bcf 153#if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER)
bc0571fc 154void (*push_packet)(void *, int len) = 0;
f85b6071 155#endif
3e38e429 156/* Network loop state */
22f6e99d 157enum net_loop_state net_state;
3e38e429 158/* Tried all network devices */
bc0571fc 159int net_restart_wrap;
3e38e429 160/* Network loop restarted */
bc0571fc 161static int net_restarted;
3e38e429 162/* At least one device configured */
bc0571fc 163static int net_dev_exists;
2d966958 164
6e592385 165/* XXX in both little & big endian machines 0xFFFF == ntohs(-1) */
3e38e429 166/* default is without VLAN */
4fd5055f 167ushort net_our_vlan = 0xFFFF;
3e38e429 168/* ditto */
4fd5055f 169ushort net_native_vlan = 0xFFFF;
a3d991bd 170
3e38e429 171/* Boot File name */
11a69ff8 172char net_boot_file_name[1024];
449312c1
AG
173/* Indicates whether the file name was specified on the command line */
174bool net_boot_file_name_explicit;
1411157d
JH
175/* The actual transferred size of the bootfile (in bytes) */
176u32 net_boot_file_size;
177/* Boot file size in blocks as reported by the DHCP server */
178u32 net_boot_file_expected_size_in_blocks;
2d966958 179
1203fcce 180static uchar net_pkt_buf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];
2a504df0
JH
181/* Receive packets */
182uchar *net_rx_packets[PKTBUFSRX];
ece223b5
JH
183/* Current UDP RX packet handler */
184static rxhand_f *udp_packet_handler;
185/* Current ARP RX packet handler */
186static rxhand_f *arp_packet_handler;
39bccd21 187#ifdef CONFIG_CMD_TFTPPUT
ece223b5
JH
188/* Current ICMP rx handler */
189static rxhand_icmp_f *packet_icmp_handler;
39bccd21 190#endif
3e38e429 191/* Current timeout handler */
bc0571fc 192static thand_f *time_handler;
3e38e429 193/* Time base value */
bc0571fc 194static ulong time_start;
3e38e429 195/* Current timeout value */
bc0571fc 196static ulong time_delta;
3e38e429 197/* THE transmit packet */
1203fcce 198uchar *net_tx_packet;
2d966958 199
e4bf0c5c 200static int net_check_prereq(enum proto_t protocol);
2d966958 201
bc0571fc 202static int net_try_count;
67b96e87 203
b63056d6
JL
204int __maybe_unused net_busy_flag;
205
73a8b27c
WD
206/**********************************************************************/
207
fd305633
JH
208static int on_ipaddr(const char *name, const char *value, enum env_op op,
209 int flags)
210{
211 if (flags & H_PROGRAMMATIC)
212 return 0;
213
214 net_ip = string_to_ip(value);
215
216 return 0;
217}
218U_BOOT_ENV_CALLBACK(ipaddr, on_ipaddr);
219
220static int on_gatewayip(const char *name, const char *value, enum env_op op,
221 int flags)
222{
223 if (flags & H_PROGRAMMATIC)
224 return 0;
225
226 net_gateway = string_to_ip(value);
227
228 return 0;
229}
230U_BOOT_ENV_CALLBACK(gatewayip, on_gatewayip);
231
232static int on_netmask(const char *name, const char *value, enum env_op op,
233 int flags)
234{
235 if (flags & H_PROGRAMMATIC)
236 return 0;
237
238 net_netmask = string_to_ip(value);
239
240 return 0;
241}
242U_BOOT_ENV_CALLBACK(netmask, on_netmask);
243
244static int on_serverip(const char *name, const char *value, enum env_op op,
245 int flags)
246{
247 if (flags & H_PROGRAMMATIC)
248 return 0;
249
250 net_server_ip = string_to_ip(value);
251
252 return 0;
253}
254U_BOOT_ENV_CALLBACK(serverip, on_serverip);
255
256static int on_nvlan(const char *name, const char *value, enum env_op op,
257 int flags)
258{
259 if (flags & H_PROGRAMMATIC)
260 return 0;
261
262 net_native_vlan = string_to_vlan(value);
263
264 return 0;
265}
266U_BOOT_ENV_CALLBACK(nvlan, on_nvlan);
267
268static int on_vlan(const char *name, const char *value, enum env_op op,
269 int flags)
270{
271 if (flags & H_PROGRAMMATIC)
272 return 0;
273
274 net_our_vlan = string_to_vlan(value);
275
276 return 0;
277}
278U_BOOT_ENV_CALLBACK(vlan, on_vlan);
279
280#if defined(CONFIG_CMD_DNS)
281static int on_dnsip(const char *name, const char *value, enum env_op op,
282 int flags)
283{
284 if (flags & H_PROGRAMMATIC)
285 return 0;
286
287 net_dns_server = string_to_ip(value);
288
289 return 0;
290}
291U_BOOT_ENV_CALLBACK(dnsip, on_dnsip);
292#endif
293
e4a3d57d
SG
294/*
295 * Check if autoload is enabled. If so, use either NFS or TFTP to download
296 * the boot file.
297 */
298void net_auto_load(void)
299{
a6ab4b54 300#if defined(CONFIG_CMD_NFS) && !defined(CONFIG_SPL_BUILD)
00caae6d 301 const char *s = env_get("autoload");
e4a3d57d 302
ec8a252c 303 if (s != NULL && strcmp(s, "NFS") == 0) {
3855cad6
JH
304 if (net_check_prereq(NFS)) {
305/* We aren't expecting to get a serverip, so just accept the assigned IP */
43407539
SG
306 if (IS_ENABLED(CONFIG_BOOTP_SERVERIP)) {
307 net_set_state(NETLOOP_SUCCESS);
308 } else {
309 printf("Cannot autoload with NFS\n");
310 net_set_state(NETLOOP_FAIL);
311 }
3855cad6
JH
312 return;
313 }
ec8a252c
JH
314 /*
315 * Use NFS to load the bootfile.
316 */
68c76a3a 317 nfs_start();
ec8a252c
JH
318 return;
319 }
e4a3d57d 320#endif
bfebc8c9 321 if (env_get_yesno("autoload") == 0) {
ec8a252c
JH
322 /*
323 * Just use BOOTP/RARP to configure system;
324 * Do not use TFTP to load the bootfile.
325 */
326 net_set_state(NETLOOP_SUCCESS);
327 return;
e4a3d57d 328 }
3855cad6
JH
329 if (net_check_prereq(TFTPGET)) {
330/* We aren't expecting to get a serverip, so just accept the assigned IP */
43407539
SG
331 if (IS_ENABLED(CONFIG_BOOTP_SERVERIP)) {
332 net_set_state(NETLOOP_SUCCESS);
333 } else {
334 printf("Cannot autoload with TFTPGET\n");
335 net_set_state(NETLOOP_FAIL);
336 }
3855cad6
JH
337 return;
338 }
8885c5fe 339 tftp_start(TFTPGET);
e4a3d57d
SG
340}
341
c3f0278e 342static int net_init_loop(void)
2f70c49e 343{
7315cfd9 344 if (eth_get_dev())
0adb5b76 345 memcpy(net_ethaddr, eth_get_ethaddr(), 6);
c3f0278e
SA
346 else
347 /*
348 * Not ideal, but there's no way to get the actual error, and I
349 * don't feel like fixing all the users of eth_get_dev to deal
350 * with errors.
351 */
352 return -ENONET;
3c172c4f 353
c3f0278e 354 return 0;
2f70c49e
HS
355}
356
ece223b5
JH
357static void net_clear_handlers(void)
358{
359 net_set_udp_handler(NULL);
360 net_set_arp_handler(NULL);
bc0571fc 361 net_set_timeout_handler(0, NULL);
ece223b5
JH
362}
363
364static void net_cleanup_loop(void)
365{
366 net_clear_handlers();
367}
368
c3f0278e 369int net_init(void)
46c495d5
JH
370{
371 static int first_call = 1;
372
373 if (first_call) {
374 /*
375 * Setup packet buffers, aligned correctly.
376 */
377 int i;
378
1203fcce
JH
379 net_tx_packet = &net_pkt_buf[0] + (PKTALIGN - 1);
380 net_tx_packet -= (ulong)net_tx_packet % PKTALIGN;
2a504df0 381 for (i = 0; i < PKTBUFSRX; i++) {
1203fcce
JH
382 net_rx_packets[i] = net_tx_packet +
383 (i + 1) * PKTSIZE_ALIGN;
2a504df0 384 }
85d25e0e 385 arp_init();
46c495d5
JH
386 net_clear_handlers();
387
388 /* Only need to setup buffer pointers once. */
389 first_call = 0;
390 }
391
c3f0278e 392 return net_init_loop();
46c495d5
JH
393}
394
2d966958
WD
395/**********************************************************************/
396/*
397 * Main network processing loop.
398 */
399
bc0571fc 400int net_loop(enum proto_t protocol)
2d966958 401{
60304592 402 int ret = -EINVAL;
60177b26 403 enum net_loop_state prev_net_state = net_state;
2d966958 404
def7a5c0
MS
405#if defined(CONFIG_CMD_PING)
406 if (protocol != PING)
407 net_ping_ip.s_addr = 0;
408#endif
bc0571fc
JH
409 net_restarted = 0;
410 net_dev_exists = 0;
411 net_try_count = 1;
412 debug_cond(DEBUG_INT_STATE, "--- net_loop Entry\n");
73a8b27c 413
09bd3d0b
SMJ
414#ifdef CONFIG_PHY_NCSI
415 if (phy_interface_is_ncsi() && protocol != NCSI && !ncsi_active()) {
416 printf("%s: configuring NCSI first\n", __func__);
417 if (net_loop(NCSI) < 0)
418 return ret;
419 eth_init_state_only();
420 goto restart;
421 }
422#endif
423
573f14fe 424 bootstage_mark_name(BOOTSTAGE_ID_ETH_START, "eth_start");
46c495d5 425 net_init();
d9506cd4 426 if (eth_is_on_demand_init()) {
b1bf6f2c 427 eth_halt();
f8be7d65 428 eth_set_current();
60304592
JH
429 ret = eth_init();
430 if (ret < 0) {
f8be7d65 431 eth_halt();
60304592 432 return ret;
f8be7d65 433 }
bc0571fc 434 } else {
d2eaec60 435 eth_init_state_only();
bc0571fc 436 }
4b290d4a 437
2d966958 438restart:
b63056d6
JL
439#ifdef CONFIG_USB_KEYBOARD
440 net_busy_flag = 0;
441#endif
22f6e99d 442 net_set_state(NETLOOP_CONTINUE);
2d966958
WD
443
444 /*
445 * Start the ball rolling with the given start function. From
446 * here on, this code is a state machine driven by received
447 * packets and timer events.
448 */
bc0571fc
JH
449 debug_cond(DEBUG_INT_STATE, "--- net_loop Init\n");
450 net_init_loop();
2d966958 451
4f63acd0 452 switch (net_check_prereq(protocol)) {
2d966958
WD
453 case 1:
454 /* network not configured */
b1bf6f2c 455 eth_halt();
60177b26 456 net_set_state(prev_net_state);
60304592 457 return -ENODEV;
2d966958 458
2d966958
WD
459 case 2:
460 /* network device not configured */
461 break;
2d966958
WD
462
463 case 0:
bc0571fc 464 net_dev_exists = 1;
1411157d 465 net_boot_file_size = 0;
2d966958 466 switch (protocol) {
808f13d8 467#ifdef CONFIG_CMD_TFTPBOOT
e4bf0c5c 468 case TFTPGET:
1fb7cd49
SG
469#ifdef CONFIG_CMD_TFTPPUT
470 case TFTPPUT:
471#endif
2d966958 472 /* always use ARP to get server ethernet address */
8885c5fe 473 tftp_start(protocol);
2d966958 474 break;
808f13d8 475#endif
7a83af07
LC
476#ifdef CONFIG_CMD_TFTPSRV
477 case TFTPSRV:
8885c5fe 478 tftp_start_server();
7a83af07
LC
479 break;
480#endif
f73a7df9
AK
481#ifdef CONFIG_UDP_FUNCTION_FASTBOOT
482 case FASTBOOT:
483 fastboot_start_server();
484 break;
485#endif
643d1ab2 486#if defined(CONFIG_CMD_DHCP)
2d966958 487 case DHCP:
7044c6bb 488 bootp_reset();
049a95a7 489 net_ip.s_addr = 0;
7044c6bb 490 dhcp_request(); /* Basically same as BOOTP */
2d966958 491 break;
610f2e9c 492#endif
808f13d8 493#if defined(CONFIG_CMD_BOOTP)
2d966958 494 case BOOTP:
7044c6bb 495 bootp_reset();
049a95a7 496 net_ip.s_addr = 0;
7044c6bb 497 bootp_request();
2d966958 498 break;
808f13d8 499#endif
bf6cb247 500#if defined(CONFIG_CMD_RARP)
2d966958 501 case RARP:
698d78e5 502 rarp_try = 0;
049a95a7 503 net_ip.s_addr = 0;
698d78e5 504 rarp_request();
2d966958 505 break;
bf6cb247 506#endif
643d1ab2 507#if defined(CONFIG_CMD_PING)
73a8b27c 508 case PING:
a36b12f9 509 ping_start();
73a8b27c 510 break;
cbd8a35c 511#endif
a6ab4b54 512#if defined(CONFIG_CMD_NFS) && !defined(CONFIG_SPL_BUILD)
cbd8a35c 513 case NFS:
68c76a3a 514 nfs_start();
cbd8a35c 515 break;
a3d991bd 516#endif
643d1ab2 517#if defined(CONFIG_CMD_CDP)
a3d991bd 518 case CDP:
6aede5b7 519 cdp_start();
a3d991bd 520 break;
68ceb29e 521#endif
66c89ee3 522#if defined(CONFIG_NETCONSOLE) && !defined(CONFIG_SPL_BUILD)
68ceb29e 523 case NETCONS:
6a38a5f3 524 nc_start();
68ceb29e 525 break;
ea287deb 526#endif
1a32bf41
RG
527#if defined(CONFIG_CMD_DNS)
528 case DNS:
786eac5f 529 dns_start();
1a32bf41 530 break;
d22c338e
JH
531#endif
532#if defined(CONFIG_CMD_LINK_LOCAL)
533 case LINKLOCAL:
534 link_local_start();
535 break;
d8970dae
LF
536#endif
537#if defined(CONFIG_CMD_WOL)
538 case WOL:
539 wol_start();
540 break;
09bd3d0b
SMJ
541#endif
542#if defined(CONFIG_PHY_NCSI)
543 case NCSI:
544 ncsi_probe_packages();
545 break;
73a8b27c 546#endif
2d966958
WD
547 default:
548 break;
549 }
550
b43ea1bf
PR
551 if (IS_ENABLED(CONFIG_PROT_UDP) && protocol == UDP)
552 udp_start();
553
2d966958
WD
554 break;
555 }
556
643d1ab2 557#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
3e38e429 558#if defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN) && \
2d8d190c
UM
559 defined(CONFIG_LED_STATUS) && \
560 defined(CONFIG_LED_STATUS_RED)
fc3e2165 561 /*
42d1f039 562 * Echo the inverted link state to the fault LED.
fc3e2165 563 */
d3c65b01 564 if (miiphy_link(eth_get_dev()->name, CONFIG_SYS_FAULT_MII_ADDR))
2d8d190c 565 status_led_set(CONFIG_LED_STATUS_RED, CONFIG_LED_STATUS_OFF);
d3c65b01 566 else
2d8d190c 567 status_led_set(CONFIG_LED_STATUS_RED, CONFIG_LED_STATUS_ON);
6d0f6bcf 568#endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */
fc3e2165 569#endif /* CONFIG_MII, ... */
b63056d6
JL
570#ifdef CONFIG_USB_KEYBOARD
571 net_busy_flag = 1;
572#endif
2d966958
WD
573
574 /*
575 * Main packet reception loop. Loop receiving packets until
22f6e99d 576 * someone sets `net_state' to a state that terminates.
2d966958
WD
577 */
578 for (;;) {
29caf930 579 schedule();
c5a75339
JH
580 if (arp_timeout_check() > 0)
581 time_start = get_timer(0);
582
2d966958
WD
583 /*
584 * Check the ethernet for a new packet. The ethernet
585 * receive routine will process it.
60304592
JH
586 * Most drivers return the most recent packet size, but not
587 * errors that may have happened.
2d966958 588 */
40cb90ee 589 eth_rx();
2d966958
WD
590
591 /*
592 * Abort if ctrl-c was pressed.
593 */
594 if (ctrlc()) {
e94070c4 595 /* cancel any ARP that may not have completed */
049a95a7 596 net_arp_wait_packet_ip.s_addr = 0;
e94070c4 597
ece223b5 598 net_cleanup_loop();
8bde7f77 599 eth_halt();
f8be7d65
JH
600 /* Invalidate the last protocol */
601 eth_set_last_protocol(BOOTP);
602
4f63acd0 603 puts("\nAbort\n");
4ef8d53c
JH
604 /* include a debug print as well incase the debug
605 messages are directed to stderr */
bc0571fc 606 debug_cond(DEBUG_INT_STATE, "--- net_loop Abort!\n");
19a4fbaa 607 ret = -EINTR;
4793ee65 608 goto done;
2d966958
WD
609 }
610
2d966958
WD
611 /*
612 * Check for a timeout, and run the timeout handler
613 * if we have one.
614 */
bc0571fc
JH
615 if (time_handler &&
616 ((get_timer(0) - time_start) > time_delta)) {
2d966958
WD
617 thand_f *x;
618
643d1ab2 619#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
4f63acd0 620#if defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN) && \
2d8d190c
UM
621 defined(CONFIG_LED_STATUS) && \
622 defined(CONFIG_LED_STATUS_RED)
fc3e2165 623 /*
42d1f039 624 * Echo the inverted link state to the fault LED.
fc3e2165 625 */
4f63acd0 626 if (miiphy_link(eth_get_dev()->name,
bc0571fc 627 CONFIG_SYS_FAULT_MII_ADDR))
2d8d190c
UM
628 status_led_set(CONFIG_LED_STATUS_RED,
629 CONFIG_LED_STATUS_OFF);
bc0571fc 630 else
2d8d190c
UM
631 status_led_set(CONFIG_LED_STATUS_RED,
632 CONFIG_LED_STATUS_ON);
4f63acd0 633#endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */
fc3e2165 634#endif /* CONFIG_MII, ... */
bc0571fc
JH
635 debug_cond(DEBUG_INT_STATE, "--- net_loop timeout\n");
636 x = time_handler;
637 time_handler = (thand_f *)0;
2d966958
WD
638 (*x)();
639 }
640
5c421331 641 if (net_state == NETLOOP_FAIL)
bc0571fc 642 ret = net_start_again();
2d966958 643
22f6e99d 644 switch (net_state) {
2d966958 645 case NETLOOP_RESTART:
bc0571fc 646 net_restarted = 1;
2d966958
WD
647 goto restart;
648
649 case NETLOOP_SUCCESS:
ece223b5 650 net_cleanup_loop();
1411157d
JH
651 if (net_boot_file_size > 0) {
652 printf("Bytes transferred = %d (%x hex)\n",
653 net_boot_file_size, net_boot_file_size);
018f5303 654 env_set_hex("filesize", net_boot_file_size);
bb872dd9 655 env_set_hex("fileaddr", image_load_addr);
2d966958 656 }
09bd3d0b 657 if (protocol != NETCONS && protocol != NCSI)
f8be7d65
JH
658 eth_halt();
659 else
660 eth_halt_state_only();
661
662 eth_set_last_protocol(protocol);
663
1411157d 664 ret = net_boot_file_size;
bc0571fc 665 debug_cond(DEBUG_INT_STATE, "--- net_loop Success!\n");
4793ee65 666 goto done;
2d966958
WD
667
668 case NETLOOP_FAIL:
ece223b5 669 net_cleanup_loop();
f8be7d65
JH
670 /* Invalidate the last protocol */
671 eth_set_last_protocol(BOOTP);
bc0571fc 672 debug_cond(DEBUG_INT_STATE, "--- net_loop Fail!\n");
a735e6e9 673 ret = -ENONET;
4793ee65 674 goto done;
22f6e99d
JH
675
676 case NETLOOP_CONTINUE:
677 continue;
2d966958
WD
678 }
679 }
4793ee65
SG
680
681done:
b63056d6
JL
682#ifdef CONFIG_USB_KEYBOARD
683 net_busy_flag = 0;
684#endif
39bccd21 685#ifdef CONFIG_CMD_TFTPPUT
4793ee65 686 /* Clear out the handlers */
ece223b5 687 net_set_udp_handler(NULL);
4793ee65 688 net_set_icmp_handler(NULL);
39bccd21 689#endif
60177b26 690 net_set_state(prev_net_state);
3eaac630
RF
691
692#if defined(CONFIG_CMD_PCAP)
693 if (pcap_active())
694 pcap_print_status();
695#endif
4793ee65 696 return ret;
2d966958
WD
697}
698
699/**********************************************************************/
700
bc0571fc 701static void start_again_timeout_handler(void)
2d966958 702{
22f6e99d 703 net_set_state(NETLOOP_RESTART);
2d966958
WD
704}
705
bc0571fc 706int net_start_again(void)
2d966958 707{
6e592385 708 char *nretry;
67b96e87
RB
709 int retry_forever = 0;
710 unsigned long retrycnt = 0;
60304592 711 int ret;
67b96e87 712
00caae6d 713 nretry = env_get("netretry");
67b96e87
RB
714 if (nretry) {
715 if (!strcmp(nretry, "yes"))
716 retry_forever = 1;
717 else if (!strcmp(nretry, "no"))
718 retrycnt = 0;
719 else if (!strcmp(nretry, "once"))
720 retrycnt = 1;
721 else
722 retrycnt = simple_strtoul(nretry, NULL, 0);
5c421331
JH
723 } else {
724 retrycnt = 0;
725 retry_forever = 0;
726 }
67b96e87 727
17d413b2 728 if ((!retry_forever) && (net_try_count > retrycnt)) {
67b96e87 729 eth_halt();
22f6e99d 730 net_set_state(NETLOOP_FAIL);
60304592
JH
731 /*
732 * We don't provide a way for the protocol to return an error,
733 * but this is almost always the reason.
734 */
735 return -ETIMEDOUT;
a3d991bd 736 }
67b96e87 737
bc0571fc 738 net_try_count++;
67b96e87 739
4f63acd0 740 eth_halt();
8b0c5c12 741#if !defined(CONFIG_NET_DO_NOT_TRY_ANOTHER)
bc0571fc 742 eth_try_another(!net_restarted);
8b0c5c12 743#endif
60304592 744 ret = eth_init();
bc0571fc
JH
745 if (net_restart_wrap) {
746 net_restart_wrap = 0;
747 if (net_dev_exists) {
748 net_set_timeout_handler(10000UL,
749 start_again_timeout_handler);
ece223b5 750 net_set_udp_handler(NULL);
6e592385 751 } else {
22f6e99d 752 net_set_state(NETLOOP_FAIL);
2d966958 753 }
6e592385 754 } else {
22f6e99d 755 net_set_state(NETLOOP_RESTART);
2d966958 756 }
60304592 757 return ret;
2d966958
WD
758}
759
760/**********************************************************************/
761/*
762 * Miscelaneous bits.
763 */
764
ece223b5 765static void dummy_handler(uchar *pkt, unsigned dport,
049a95a7 766 struct in_addr sip, unsigned sport,
ece223b5 767 unsigned len)
d280d3f4 768{
d280d3f4
JH
769}
770
ece223b5
JH
771rxhand_f *net_get_udp_handler(void)
772{
773 return udp_packet_handler;
774}
d280d3f4 775
ece223b5
JH
776void net_set_udp_handler(rxhand_f *f)
777{
bc0571fc 778 debug_cond(DEBUG_INT_STATE, "--- net_loop UDP handler set (%p)\n", f);
ece223b5
JH
779 if (f == NULL)
780 udp_packet_handler = dummy_handler;
781 else
782 udp_packet_handler = f;
783}
784
785rxhand_f *net_get_arp_handler(void)
2d966958 786{
ece223b5
JH
787 return arp_packet_handler;
788}
789
790void net_set_arp_handler(rxhand_f *f)
791{
bc0571fc 792 debug_cond(DEBUG_INT_STATE, "--- net_loop ARP handler set (%p)\n", f);
ece223b5
JH
793 if (f == NULL)
794 arp_packet_handler = dummy_handler;
795 else
796 arp_packet_handler = f;
2d966958
WD
797}
798
39bccd21 799#ifdef CONFIG_CMD_TFTPPUT
4793ee65
SG
800void net_set_icmp_handler(rxhand_icmp_f *f)
801{
802 packet_icmp_handler = f;
803}
39bccd21 804#endif
2d966958 805
bc0571fc 806void net_set_timeout_handler(ulong iv, thand_f *f)
2d966958
WD
807{
808 if (iv == 0) {
4ef8d53c 809 debug_cond(DEBUG_INT_STATE,
bc0571fc
JH
810 "--- net_loop timeout handler cancelled\n");
811 time_handler = (thand_f *)0;
2d966958 812 } else {
4ef8d53c 813 debug_cond(DEBUG_INT_STATE,
bc0571fc
JH
814 "--- net_loop timeout handler set (%p)\n", f);
815 time_handler = f;
816 time_start = get_timer(0);
817 time_delta = iv * CONFIG_SYS_HZ / 1000;
2d966958
WD
818 }
819}
820
ac3f26cc
JH
821uchar *net_get_async_tx_pkt_buf(void)
822{
823 if (arp_is_waiting())
824 return arp_tx_packet; /* If we are waiting, we already sent */
825 else
826 return net_tx_packet;
827}
828
1203fcce 829int net_send_udp_packet(uchar *ether, struct in_addr dest, int dport, int sport,
206d07fd 830 int payload_len)
5d457ecb
DH
831{
832 return net_send_ip_packet(ether, dest, dport, sport, payload_len,
833 IPPROTO_UDP, 0, 0, 0);
834}
835
836int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport,
837 int payload_len, int proto, u8 action, u32 tcp_seq_num,
838 u32 tcp_ack_num)
73a8b27c 839{
a3d991bd 840 uchar *pkt;
9214637a
JH
841 int eth_hdr_size;
842 int pkt_hdr_size;
a3d991bd 843
bc0571fc 844 /* make sure the net_tx_packet is initialized (net_init() was called) */
1203fcce
JH
845 assert(net_tx_packet != NULL);
846 if (net_tx_packet == NULL)
46c495d5
JH
847 return -1;
848
73a8b27c 849 /* convert to new style broadcast */
049a95a7
JH
850 if (dest.s_addr == 0)
851 dest.s_addr = 0xFFFFFFFF;
73a8b27c
WD
852
853 /* if broadcast, make the ether address a broadcast and don't do ARP */
049a95a7 854 if (dest.s_addr == 0xFFFFFFFF)
0adb5b76 855 ether = (uchar *)net_bcast_ethaddr;
73a8b27c 856
1203fcce 857 pkt = (uchar *)net_tx_packet;
9214637a 858
1203fcce 859 eth_hdr_size = net_set_ether(pkt, ether, PROT_IP);
5d457ecb
DH
860
861 switch (proto) {
862 case IPPROTO_UDP:
863 net_set_udp_header(pkt + eth_hdr_size, dest, dport, sport,
864 payload_len);
865 pkt_hdr_size = eth_hdr_size + IP_UDP_HDR_SIZE;
866 break;
867 default:
868 return -EINVAL;
869 }
73a8b27c 870
e94070c4 871 /* if MAC address was not discovered yet, do an ARP request */
0adb5b76 872 if (memcmp(ether, net_null_ethaddr, 6) == 0) {
4ef8d53c 873 debug_cond(DEBUG_DEV_PKT, "sending ARP for %pI4\n", &dest);
0ebf04c6 874
9214637a 875 /* save the ip and eth addr for the packet to send after arp */
049a95a7 876 net_arp_wait_packet_ip = dest;
85d25e0e 877 arp_wait_packet_ethaddr = ether;
a3d991bd 878
73a8b27c 879 /* size of the waiting packet */
85d25e0e 880 arp_wait_tx_packet_size = pkt_hdr_size + payload_len;
73a8b27c
WD
881
882 /* and do the ARP request */
85d25e0e
JH
883 arp_wait_try = 1;
884 arp_wait_timer_start = get_timer(0);
885 arp_request();
73a8b27c 886 return 1; /* waiting */
9214637a 887 } else {
4ef8d53c 888 debug_cond(DEBUG_DEV_PKT, "sending UDP to %pI4/%pM\n",
bc0571fc 889 &dest, ether);
1203fcce 890 net_send_packet(net_tx_packet, pkt_hdr_size + payload_len);
9214637a 891 return 0; /* transmitted */
73a8b27c 892 }
73a8b27c
WD
893}
894
5cfaa4e5
AR
895#ifdef CONFIG_IP_DEFRAG
896/*
897 * This function collects fragments in a single packet, according
898 * to the algorithm in RFC815. It returns NULL or the pointer to
899 * a complete packet, in static storage
900 */
aa7a6487 901#define IP_PKTSIZE (CONFIG_NET_MAXDEFRAG)
5cfaa4e5 902
c5c59df0 903#define IP_MAXUDP (IP_PKTSIZE - IP_HDR_SIZE)
5cfaa4e5
AR
904
905/*
906 * this is the packet being assembled, either data or frag control.
907 * Fragments go by 8 bytes, so this union must be 8 bytes long
908 */
909struct hole {
910 /* first_byte is address of this structure */
911 u16 last_byte; /* last byte in this hole + 1 (begin of next hole) */
912 u16 next_hole; /* index of next (in 8-b blocks), 0 == none */
913 u16 prev_hole; /* index of prev, 0 == none */
914 u16 unused;
915};
916
bc0571fc 917static struct ip_udp_hdr *__net_defragment(struct ip_udp_hdr *ip, int *lenp)
5cfaa4e5 918{
48522bb5 919 static uchar pkt_buff[IP_PKTSIZE] __aligned(PKTALIGN);
5cfaa4e5
AR
920 static u16 first_hole, total_len;
921 struct hole *payload, *thisfrag, *h, *newh;
594c26f8 922 struct ip_udp_hdr *localip = (struct ip_udp_hdr *)pkt_buff;
5cfaa4e5
AR
923 uchar *indata = (uchar *)ip;
924 int offset8, start, len, done = 0;
925 u16 ip_off = ntohs(ip->ip_off);
926
b85d130e
FE
927 if (ip->ip_len < IP_MIN_FRAG_DATAGRAM_SIZE)
928 return NULL;
929
5cfaa4e5 930 /* payload starts after IP header, this fragment is in there */
c5c59df0 931 payload = (struct hole *)(pkt_buff + IP_HDR_SIZE);
5cfaa4e5
AR
932 offset8 = (ip_off & IP_OFFS);
933 thisfrag = payload + offset8;
934 start = offset8 * 8;
c5c59df0 935 len = ntohs(ip->ip_len) - IP_HDR_SIZE;
5cfaa4e5
AR
936
937 if (start + len > IP_MAXUDP) /* fragment extends too far */
938 return NULL;
939
940 if (!total_len || localip->ip_id != ip->ip_id) {
941 /* new (or different) packet, reset structs */
942 total_len = 0xffff;
943 payload[0].last_byte = ~0;
944 payload[0].next_hole = 0;
945 payload[0].prev_hole = 0;
946 first_hole = 0;
947 /* any IP header will work, copy the first we received */
c5c59df0 948 memcpy(localip, ip, IP_HDR_SIZE);
5cfaa4e5
AR
949 }
950
951 /*
952 * What follows is the reassembly algorithm. We use the payload
953 * array as a linked list of hole descriptors, as each hole starts
954 * at a multiple of 8 bytes. However, last byte can be whatever value,
955 * so it is represented as byte count, not as 8-byte blocks.
956 */
957
958 h = payload + first_hole;
959 while (h->last_byte < start) {
960 if (!h->next_hole) {
961 /* no hole that far away */
962 return NULL;
963 }
964 h = payload + h->next_hole;
965 }
966
e397e59e
FS
967 /* last fragment may be 1..7 bytes, the "+7" forces acceptance */
968 if (offset8 + ((len + 7) / 8) <= h - payload) {
5cfaa4e5
AR
969 /* no overlap with holes (dup fragment?) */
970 return NULL;
971 }
972
973 if (!(ip_off & IP_FLAGS_MFRAG)) {
974 /* no more fragmentss: truncate this (last) hole */
975 total_len = start + len;
976 h->last_byte = start + len;
977 }
978
979 /*
980 * There is some overlap: fix the hole list. This code doesn't
981 * deal with a fragment that overlaps with two different holes
982 * (thus being a superset of a previously-received fragment).
983 */
984
4f63acd0 985 if ((h >= thisfrag) && (h->last_byte <= start + len)) {
5cfaa4e5
AR
986 /* complete overlap with hole: remove hole */
987 if (!h->prev_hole && !h->next_hole) {
988 /* last remaining hole */
989 done = 1;
990 } else if (!h->prev_hole) {
991 /* first hole */
992 first_hole = h->next_hole;
993 payload[h->next_hole].prev_hole = 0;
994 } else if (!h->next_hole) {
995 /* last hole */
996 payload[h->prev_hole].next_hole = 0;
997 } else {
998 /* in the middle of the list */
999 payload[h->next_hole].prev_hole = h->prev_hole;
1000 payload[h->prev_hole].next_hole = h->next_hole;
1001 }
1002
1003 } else if (h->last_byte <= start + len) {
1004 /* overlaps with final part of the hole: shorten this hole */
1005 h->last_byte = start;
1006
1007 } else if (h >= thisfrag) {
1008 /* overlaps with initial part of the hole: move this hole */
1009 newh = thisfrag + (len / 8);
1010 *newh = *h;
1011 h = newh;
1012 if (h->next_hole)
1013 payload[h->next_hole].prev_hole = (h - payload);
1014 if (h->prev_hole)
1015 payload[h->prev_hole].next_hole = (h - payload);
1016 else
1017 first_hole = (h - payload);
1018
1019 } else {
1020 /* fragment sits in the middle: split the hole */
1021 newh = thisfrag + (len / 8);
1022 *newh = *h;
1023 h->last_byte = start;
1024 h->next_hole = (newh - payload);
1025 newh->prev_hole = (h - payload);
1026 if (newh->next_hole)
1027 payload[newh->next_hole].prev_hole = (newh - payload);
1028 }
1029
1030 /* finally copy this fragment and possibly return whole packet */
c5c59df0 1031 memcpy((uchar *)thisfrag, indata + IP_HDR_SIZE, len);
5cfaa4e5
AR
1032 if (!done)
1033 return NULL;
1034
1035 localip->ip_len = htons(total_len);
c5c59df0 1036 *lenp = total_len + IP_HDR_SIZE;
5cfaa4e5
AR
1037 return localip;
1038}
1039
bc0571fc
JH
1040static inline struct ip_udp_hdr *net_defragment(struct ip_udp_hdr *ip,
1041 int *lenp)
5cfaa4e5
AR
1042{
1043 u16 ip_off = ntohs(ip->ip_off);
1044 if (!(ip_off & (IP_OFFS | IP_FLAGS_MFRAG)))
1045 return ip; /* not a fragment */
bc0571fc 1046 return __net_defragment(ip, lenp);
5cfaa4e5
AR
1047}
1048
1049#else /* !CONFIG_IP_DEFRAG */
1050
bc0571fc
JH
1051static inline struct ip_udp_hdr *net_defragment(struct ip_udp_hdr *ip,
1052 int *lenp)
5cfaa4e5
AR
1053{
1054 u16 ip_off = ntohs(ip->ip_off);
1055 if (!(ip_off & (IP_OFFS | IP_FLAGS_MFRAG)))
1056 return ip; /* not a fragment */
1057 return NULL;
1058}
1059#endif
a3d991bd 1060
8f79bb17
SG
1061/**
1062 * Receive an ICMP packet. We deal with REDIRECT and PING here, and silently
1063 * drop others.
1064 *
1065 * @parma ip IP packet containing the ICMP
1066 */
594c26f8 1067static void receive_icmp(struct ip_udp_hdr *ip, int len,
049a95a7 1068 struct in_addr src_ip, struct ethernet_hdr *et)
8f79bb17 1069{
e0a63079 1070 struct icmp_hdr *icmph = (struct icmp_hdr *)&ip->udp_src;
8f79bb17
SG
1071
1072 switch (icmph->type) {
1073 case ICMP_REDIRECT:
1074 if (icmph->code != ICMP_REDIR_HOST)
1075 return;
1076 printf(" ICMP Host Redirect to %pI4 ",
bc0571fc 1077 &icmph->un.gateway);
8f79bb17 1078 break;
a36b12f9 1079 default:
8f79bb17 1080#if defined(CONFIG_CMD_PING)
a36b12f9 1081 ping_receive(et, ip, len);
8f79bb17 1082#endif
39bccd21 1083#ifdef CONFIG_CMD_TFTPPUT
4793ee65
SG
1084 if (packet_icmp_handler)
1085 packet_icmp_handler(icmph->type, icmph->code,
bc0571fc
JH
1086 ntohs(ip->udp_dst), src_ip,
1087 ntohs(ip->udp_src), icmph->un.data,
1088 ntohs(ip->udp_len));
39bccd21 1089#endif
8f79bb17
SG
1090 break;
1091 }
1092}
1093
2a504df0 1094void net_process_received_packet(uchar *in_packet, int len)
2d966958 1095{
cb487f56 1096 struct ethernet_hdr *et;
594c26f8 1097 struct ip_udp_hdr *ip;
049a95a7
JH
1098 struct in_addr dst_ip;
1099 struct in_addr src_ip;
8d353eb8 1100 int eth_proto;
643d1ab2 1101#if defined(CONFIG_CMD_CDP)
a3d991bd
WD
1102 int iscdp;
1103#endif
1104 ushort cti = 0, vlanid = VLAN_NONE, myvlanid, mynvlanid;
1105
4ef8d53c 1106 debug_cond(DEBUG_NET_PKT, "packet received\n");
2d966958 1107
3eaac630
RF
1108#if defined(CONFIG_CMD_PCAP)
1109 pcap_post(in_packet, len, false);
1110#endif
1203fcce
JH
1111 net_rx_packet = in_packet;
1112 net_rx_packet_len = len;
2a504df0 1113 et = (struct ethernet_hdr *)in_packet;
a3d991bd
WD
1114
1115 /* too small packet? */
1116 if (len < ETHER_HDR_SIZE)
1117 return;
1118
0efe1bcf 1119#if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER)
f85b6071 1120 if (push_packet) {
2a504df0 1121 (*push_packet)(in_packet, len);
f85b6071
RJ
1122 return;
1123 }
1124#endif
1125
643d1ab2 1126#if defined(CONFIG_CMD_CDP)
a3d991bd 1127 /* keep track if packet is CDP */
17351883 1128 iscdp = is_cdp_packet(et->et_dest);
a3d991bd
WD
1129#endif
1130
4fd5055f 1131 myvlanid = ntohs(net_our_vlan);
a3d991bd
WD
1132 if (myvlanid == (ushort)-1)
1133 myvlanid = VLAN_NONE;
4fd5055f 1134 mynvlanid = ntohs(net_native_vlan);
a3d991bd
WD
1135 if (mynvlanid == (ushort)-1)
1136 mynvlanid = VLAN_NONE;
2d966958 1137
8d353eb8 1138 eth_proto = ntohs(et->et_protlen);
2d966958 1139
8d353eb8 1140 if (eth_proto < 1514) {
cb487f56 1141 struct e802_hdr *et802 = (struct e802_hdr *)et;
2d966958 1142 /*
da5ebe2c
JH
1143 * Got a 802.2 packet. Check the other protocol field.
1144 * XXX VLAN over 802.2+SNAP not implemented!
2d966958 1145 */
8d353eb8 1146 eth_proto = ntohs(et802->et_prot);
a3d991bd 1147
2a504df0 1148 ip = (struct ip_udp_hdr *)(in_packet + E802_HDR_SIZE);
2d966958 1149 len -= E802_HDR_SIZE;
a3d991bd 1150
8d353eb8 1151 } else if (eth_proto != PROT_VLAN) { /* normal packet */
2a504df0 1152 ip = (struct ip_udp_hdr *)(in_packet + ETHER_HDR_SIZE);
2d966958 1153 len -= ETHER_HDR_SIZE;
a3d991bd
WD
1154
1155 } else { /* VLAN packet */
c68cca35
JH
1156 struct vlan_ethernet_hdr *vet =
1157 (struct vlan_ethernet_hdr *)et;
a3d991bd 1158
4ef8d53c 1159 debug_cond(DEBUG_NET_PKT, "VLAN packet received\n");
0ebf04c6 1160
a3d991bd
WD
1161 /* too small packet? */
1162 if (len < VLAN_ETHER_HDR_SIZE)
1163 return;
1164
1165 /* if no VLAN active */
4fd5055f 1166 if ((ntohs(net_our_vlan) & VLAN_IDMASK) == VLAN_NONE
643d1ab2 1167#if defined(CONFIG_CMD_CDP)
a3d991bd
WD
1168 && iscdp == 0
1169#endif
1170 )
1171 return;
1172
1173 cti = ntohs(vet->vet_tag);
1174 vlanid = cti & VLAN_IDMASK;
8d353eb8 1175 eth_proto = ntohs(vet->vet_type);
a3d991bd 1176
2a504df0 1177 ip = (struct ip_udp_hdr *)(in_packet + VLAN_ETHER_HDR_SIZE);
a3d991bd 1178 len -= VLAN_ETHER_HDR_SIZE;
2d966958
WD
1179 }
1180
4ef8d53c 1181 debug_cond(DEBUG_NET_PKT, "Receive from protocol 0x%x\n", eth_proto);
2d966958 1182
643d1ab2 1183#if defined(CONFIG_CMD_CDP)
a3d991bd 1184 if (iscdp) {
0b4c5ff4 1185 cdp_receive((uchar *)ip, len);
a3d991bd
WD
1186 return;
1187 }
1188#endif
1189
1190 if ((myvlanid & VLAN_IDMASK) != VLAN_NONE) {
1191 if (vlanid == VLAN_NONE)
1192 vlanid = (mynvlanid & VLAN_IDMASK);
1193 /* not matched? */
1194 if (vlanid != (myvlanid & VLAN_IDMASK))
1195 return;
1196 }
1197
8d353eb8 1198 switch (eth_proto) {
2d966958 1199 case PROT_ARP:
85d25e0e 1200 arp_receive(et, ip, len);
289f932c 1201 break;
2d966958 1202
bf6cb247 1203#ifdef CONFIG_CMD_RARP
2d966958 1204 case PROT_RARP:
8b9c5322 1205 rarp_receive(ip, len);
2d966958 1206 break;
bf6cb247 1207#endif
2d966958 1208 case PROT_IP:
4ef8d53c 1209 debug_cond(DEBUG_NET_PKT, "Got IP\n");
5cfaa4e5 1210 /* Before we start poking the header, make sure it is there */
594c26f8
JH
1211 if (len < IP_UDP_HDR_SIZE) {
1212 debug("len bad %d < %lu\n", len,
bc0571fc 1213 (ulong)IP_UDP_HDR_SIZE);
2d966958
WD
1214 return;
1215 }
5cfaa4e5 1216 /* Check the packet length */
2d966958 1217 if (len < ntohs(ip->ip_len)) {
4ef8d53c 1218 debug("len bad %d < %d\n", len, ntohs(ip->ip_len));
2d966958
WD
1219 return;
1220 }
1221 len = ntohs(ip->ip_len);
4ef8d53c 1222 debug_cond(DEBUG_NET_PKT, "len=%d, v=%02x\n",
bc0571fc 1223 len, ip->ip_hl_v & 0xff);
0ebf04c6 1224
5cfaa4e5 1225 /* Can't deal with anything except IPv4 */
d3c65b01 1226 if ((ip->ip_hl_v & 0xf0) != 0x40)
2d966958 1227 return;
5cfaa4e5 1228 /* Can't deal with IP options (headers != 20 bytes) */
d3c65b01 1229 if ((ip->ip_hl_v & 0x0f) > 0x05)
6b52cfe1 1230 return;
5cfaa4e5 1231 /* Check the Checksum of the header */
0da0fcd5 1232 if (!ip_checksum_ok((uchar *)ip, IP_HDR_SIZE)) {
4ef8d53c 1233 debug("checksum bad\n");
2d966958
WD
1234 return;
1235 }
5cfaa4e5 1236 /* If it is not for us, ignore it */
049a95a7
JH
1237 dst_ip = net_read_ip(&ip->ip_dst);
1238 if (net_ip.s_addr && dst_ip.s_addr != net_ip.s_addr &&
1239 dst_ip.s_addr != 0xFFFFFFFF) {
c819abee 1240 return;
2d966958 1241 }
03eb129f 1242 /* Read source IP address for later use */
049a95a7 1243 src_ip = net_read_ip(&ip->ip_src);
5cfaa4e5
AR
1244 /*
1245 * The function returns the unchanged packet if it's not
1246 * a fragment, and either the complete packet or NULL if
1247 * it is a fragment (if !CONFIG_IP_DEFRAG, it returns NULL)
1248 */
bc0571fc 1249 ip = net_defragment(ip, &len);
ccb9ebef 1250 if (!ip)
5cfaa4e5 1251 return;
2d966958
WD
1252 /*
1253 * watch for ICMP host redirects
1254 *
8bde7f77
WD
1255 * There is no real handler code (yet). We just watch
1256 * for ICMP host redirect messages. In case anybody
1257 * sees these messages: please contact me
1258 * ([email protected]), or - even better - send me the
1259 * necessary fixes :-)
2d966958 1260 *
8bde7f77
WD
1261 * Note: in all cases where I have seen this so far
1262 * it was a problem with the router configuration,
1263 * for instance when a router was configured in the
1264 * BOOTP reply, but the TFTP server was on the same
1265 * subnet. So this is probably a warning that your
1266 * configuration might be wrong. But I'm not really
1267 * sure if there aren't any other situations.
4793ee65
SG
1268 *
1269 * Simon Glass <[email protected]>: We get an ICMP when
1270 * we send a tftp packet to a dead connection, or when
1271 * there is no server at the other end.
2d966958
WD
1272 */
1273 if (ip->ip_p == IPPROTO_ICMP) {
8f79bb17
SG
1274 receive_icmp(ip, len, src_ip, et);
1275 return;
2d966958
WD
1276 } else if (ip->ip_p != IPPROTO_UDP) { /* Only UDP packets */
1277 return;
1278 }
1279
fe728806 1280 if (ntohs(ip->udp_len) < UDP_HDR_SIZE || ntohs(ip->udp_len) > ntohs(ip->ip_len))
1281 return;
1282
4ef8d53c 1283 debug_cond(DEBUG_DEV_PKT,
bc0571fc
JH
1284 "received UDP (to=%pI4, from=%pI4, len=%d)\n",
1285 &dst_ip, &src_ip, len);
4ef8d53c 1286
4b37fd14 1287 if (IS_ENABLED(CONFIG_UDP_CHECKSUM) && ip->udp_xsum != 0) {
b2f50807 1288 ulong xsum;
8524423d 1289 u8 *sumptr;
8534bf9a
SR
1290 ushort sumlen;
1291
1292 xsum = ip->ip_p;
1293 xsum += (ntohs(ip->udp_len));
049a95a7
JH
1294 xsum += (ntohl(ip->ip_src.s_addr) >> 16) & 0x0000ffff;
1295 xsum += (ntohl(ip->ip_src.s_addr) >> 0) & 0x0000ffff;
1296 xsum += (ntohl(ip->ip_dst.s_addr) >> 16) & 0x0000ffff;
1297 xsum += (ntohl(ip->ip_dst.s_addr) >> 0) & 0x0000ffff;
8534bf9a
SR
1298
1299 sumlen = ntohs(ip->udp_len);
8524423d 1300 sumptr = (u8 *)&ip->udp_src;
8534bf9a
SR
1301
1302 while (sumlen > 1) {
8524423d
HS
1303 /* inlined ntohs() to avoid alignment errors */
1304 xsum += (sumptr[0] << 8) + sumptr[1];
1305 sumptr += 2;
8534bf9a
SR
1306 sumlen -= 2;
1307 }
8524423d
HS
1308 if (sumlen > 0)
1309 xsum += (sumptr[0] << 8) + sumptr[0];
8534bf9a 1310 while ((xsum >> 16) != 0) {
3e38e429
LC
1311 xsum = (xsum & 0x0000ffff) +
1312 ((xsum >> 16) & 0x0000ffff);
8534bf9a
SR
1313 }
1314 if ((xsum != 0x00000000) && (xsum != 0x0000ffff)) {
9b55a253 1315 printf(" UDP wrong checksum %08lx %08x\n",
bc0571fc 1316 xsum, ntohs(ip->udp_xsum));
8534bf9a
SR
1317 return;
1318 }
1319 }
8534bf9a 1320
66c89ee3 1321#if defined(CONFIG_NETCONSOLE) && !defined(CONFIG_SPL_BUILD)
594c26f8 1322 nc_input_packet((uchar *)ip + IP_UDP_HDR_SIZE,
bc0571fc
JH
1323 src_ip,
1324 ntohs(ip->udp_dst),
1325 ntohs(ip->udp_src),
1326 ntohs(ip->udp_len) - UDP_HDR_SIZE);
68ceb29e 1327#endif
2d966958 1328 /*
bc0571fc 1329 * IP header OK. Pass the packet to the current handler.
2d966958 1330 */
ece223b5 1331 (*udp_packet_handler)((uchar *)ip + IP_UDP_HDR_SIZE,
bc0571fc
JH
1332 ntohs(ip->udp_dst),
1333 src_ip,
1334 ntohs(ip->udp_src),
1335 ntohs(ip->udp_len) - UDP_HDR_SIZE);
2d966958 1336 break;
d8970dae
LF
1337#ifdef CONFIG_CMD_WOL
1338 case PROT_WOL:
1339 wol_receive(ip, len);
1340 break;
09bd3d0b
SMJ
1341#endif
1342#ifdef CONFIG_PHY_NCSI
1343 case PROT_NCSI:
1344 ncsi_receive(et, ip, len);
1345 break;
d8970dae 1346#endif
2d966958
WD
1347 }
1348}
1349
2d966958
WD
1350/**********************************************************************/
1351
e4bf0c5c 1352static int net_check_prereq(enum proto_t protocol)
2d966958
WD
1353{
1354 switch (protocol) {
6e592385 1355 /* Fall through */
643d1ab2 1356#if defined(CONFIG_CMD_PING)
73a8b27c 1357 case PING:
049a95a7 1358 if (net_ping_ip.s_addr == 0) {
4f63acd0 1359 puts("*** ERROR: ping address not given\n");
92895de9 1360 return 1;
6e592385
WD
1361 }
1362 goto common;
cbd8a35c 1363#endif
1a32bf41
RG
1364#if defined(CONFIG_CMD_DNS)
1365 case DNS:
049a95a7 1366 if (net_dns_server.s_addr == 0) {
1a32bf41
RG
1367 puts("*** ERROR: DNS server address not given\n");
1368 return 1;
1369 }
1370 goto common;
1371#endif
b43ea1bf
PR
1372#if defined(CONFIG_PROT_UDP)
1373 case UDP:
1374 if (udp_prereq())
1375 return 1;
1376 goto common;
1377#endif
1378
643d1ab2 1379#if defined(CONFIG_CMD_NFS)
cbd8a35c 1380 case NFS:
73a8b27c 1381#endif
bc0571fc 1382 /* Fall through */
e4bf0c5c 1383 case TFTPGET:
1fb7cd49 1384 case TFTPPUT:
3a66fcb7 1385 if (net_server_ip.s_addr == 0 && !is_serverip_in_cmd()) {
4f63acd0 1386 puts("*** ERROR: `serverip' not set\n");
92895de9 1387 return 1;
6e592385 1388 }
912ece4c 1389#if defined(CONFIG_CMD_PING) || \
b43ea1bf 1390 defined(CONFIG_CMD_DNS) || defined(CONFIG_PROT_UDP)
4f63acd0 1391common:
73a8b27c 1392#endif
8b6bbe10 1393 /* Fall through */
73a8b27c 1394
8b6bbe10 1395 case NETCONS:
f73a7df9 1396 case FASTBOOT:
7a83af07 1397 case TFTPSRV:
049a95a7 1398 if (net_ip.s_addr == 0) {
4f63acd0 1399 puts("*** ERROR: `ipaddr' not set\n");
92895de9 1400 return 1;
6e592385
WD
1401 }
1402 /* Fall through */
2d966958 1403
bf6cb247 1404#ifdef CONFIG_CMD_RARP
2d966958 1405 case RARP:
09bd3d0b
SMJ
1406#endif
1407#ifdef CONFIG_PHY_NCSI
1408 case NCSI:
bf6cb247 1409#endif
2d966958 1410 case BOOTP:
a3d991bd 1411 case CDP:
bf6cb247 1412 case DHCP:
d22c338e 1413 case LINKLOCAL:
0adb5b76 1414 if (memcmp(net_ethaddr, "\0\0\0\0\0\0", 6) == 0) {
4f63acd0 1415 int num = eth_get_dev_index();
2d966958 1416
6e592385
WD
1417 switch (num) {
1418 case -1:
4f63acd0 1419 puts("*** ERROR: No ethernet found.\n");
92895de9 1420 return 1;
6e592385 1421 case 0:
4f63acd0 1422 puts("*** ERROR: `ethaddr' not set\n");
2d966958 1423 break;
6e592385 1424 default:
4f63acd0 1425 printf("*** ERROR: `eth%daddr' not set\n",
bc0571fc 1426 num);
2d966958 1427 break;
6e592385 1428 }
2d966958 1429
bc0571fc 1430 net_start_again();
92895de9 1431 return 2;
6e592385
WD
1432 }
1433 /* Fall through */
1434 default:
92895de9 1435 return 0;
2d966958 1436 }
92895de9 1437 return 0; /* OK */
2d966958
WD
1438}
1439/**********************************************************************/
1440
a3d991bd 1441int
1203fcce 1442net_eth_hdr_size(void)
a3d991bd
WD
1443{
1444 ushort myvlanid;
2d966958 1445
4fd5055f 1446 myvlanid = ntohs(net_our_vlan);
a3d991bd
WD
1447 if (myvlanid == (ushort)-1)
1448 myvlanid = VLAN_NONE;
1449
3e38e429
LC
1450 return ((myvlanid & VLAN_IDMASK) == VLAN_NONE) ? ETHER_HDR_SIZE :
1451 VLAN_ETHER_HDR_SIZE;
a3d991bd
WD
1452}
1453
1203fcce 1454int net_set_ether(uchar *xet, const uchar *dest_ethaddr, uint prot)
2d966958 1455{
cb487f56 1456 struct ethernet_hdr *et = (struct ethernet_hdr *)xet;
a3d991bd
WD
1457 ushort myvlanid;
1458
4fd5055f 1459 myvlanid = ntohs(net_our_vlan);
a3d991bd
WD
1460 if (myvlanid == (ushort)-1)
1461 myvlanid = VLAN_NONE;
2d966958 1462
0adb5b76
JH
1463 memcpy(et->et_dest, dest_ethaddr, 6);
1464 memcpy(et->et_src, net_ethaddr, 6);
a3d991bd 1465 if ((myvlanid & VLAN_IDMASK) == VLAN_NONE) {
c819abee 1466 et->et_protlen = htons(prot);
a3d991bd
WD
1467 return ETHER_HDR_SIZE;
1468 } else {
c68cca35
JH
1469 struct vlan_ethernet_hdr *vet =
1470 (struct vlan_ethernet_hdr *)xet;
2d966958 1471
a3d991bd
WD
1472 vet->vet_vlan_type = htons(PROT_VLAN);
1473 vet->vet_tag = htons((0 << 5) | (myvlanid & VLAN_IDMASK));
1474 vet->vet_type = htons(prot);
1475 return VLAN_ETHER_HDR_SIZE;
1476 }
1477}
2d966958 1478
e7111015
JH
1479int net_update_ether(struct ethernet_hdr *et, uchar *addr, uint prot)
1480{
1481 ushort protlen;
1482
1483 memcpy(et->et_dest, addr, 6);
0adb5b76 1484 memcpy(et->et_src, net_ethaddr, 6);
e7111015
JH
1485 protlen = ntohs(et->et_protlen);
1486 if (protlen == PROT_VLAN) {
1487 struct vlan_ethernet_hdr *vet =
1488 (struct vlan_ethernet_hdr *)et;
1489 vet->vet_type = htons(prot);
1490 return VLAN_ETHER_HDR_SIZE;
1491 } else if (protlen > 1514) {
1492 et->et_protlen = htons(prot);
1493 return ETHER_HDR_SIZE;
1494 } else {
1495 /* 802.2 + SNAP */
1496 struct e802_hdr *et802 = (struct e802_hdr *)et;
1497 et802->et_prot = htons(prot);
1498 return E802_HDR_SIZE;
1499 }
1500}
1501
5d457ecb
DH
1502void net_set_ip_header(uchar *pkt, struct in_addr dest, struct in_addr source,
1503 u16 pkt_len, u8 proto)
2d966958 1504{
4b11c916 1505 struct ip_udp_hdr *ip = (struct ip_udp_hdr *)pkt;
2d966958
WD
1506
1507 /*
4b11c916 1508 * Construct an IP header.
2d966958 1509 */
3e38e429
LC
1510 /* IP_HDR_SIZE / 4 (not including UDP) */
1511 ip->ip_hl_v = 0x45;
2d966958 1512 ip->ip_tos = 0;
5d457ecb
DH
1513 ip->ip_len = htons(pkt_len);
1514 ip->ip_p = proto;
bc0571fc 1515 ip->ip_id = htons(net_ip_id++);
e0c07b86 1516 ip->ip_off = htons(IP_FLAGS_DFRAG); /* Don't fragment */
2d966958 1517 ip->ip_ttl = 255;
2d966958 1518 ip->ip_sum = 0;
3e38e429 1519 /* already in network byte order */
049a95a7 1520 net_copy_ip((void *)&ip->ip_src, &source);
4b11c916 1521 /* already in network byte order */
049a95a7 1522 net_copy_ip((void *)&ip->ip_dst, &dest);
5d457ecb
DH
1523
1524 ip->ip_sum = compute_ip_checksum(ip, IP_HDR_SIZE);
4b11c916
JH
1525}
1526
049a95a7 1527void net_set_udp_header(uchar *pkt, struct in_addr dest, int dport, int sport,
4b11c916
JH
1528 int len)
1529{
1530 struct ip_udp_hdr *ip = (struct ip_udp_hdr *)pkt;
1531
1532 /*
1533 * If the data is an odd number of bytes, zero the
1534 * byte after the last byte so that the checksum
1535 * will work.
1536 */
1537 if (len & 1)
1538 pkt[IP_UDP_HDR_SIZE + len] = 0;
1539
5d457ecb
DH
1540 net_set_ip_header(pkt, dest, net_ip, IP_UDP_HDR_SIZE + len,
1541 IPPROTO_UDP);
4b11c916 1542
2d966958
WD
1543 ip->udp_src = htons(sport);
1544 ip->udp_dst = htons(dport);
594c26f8 1545 ip->udp_len = htons(UDP_HDR_SIZE + len);
2d966958 1546 ip->udp_xsum = 0;
2d966958
WD
1547}
1548
4f63acd0 1549void copy_filename(char *dst, const char *src, int size)
2d966958 1550{
16cf145f 1551 if (src && *src && (*src == '"')) {
2d966958
WD
1552 ++src;
1553 --size;
1554 }
1555
16cf145f 1556 while ((--size > 0) && src && *src && (*src != '"'))
2d966958 1557 *dst++ = *src++;
2d966958
WD
1558 *dst = '\0';
1559}
1560
3a66fcb7
JH
1561int is_serverip_in_cmd(void)
1562{
1563 return !!strchr(net_boot_file_name, ':');
1564}
1565
6ab12830
JH
1566int net_parse_bootfile(struct in_addr *ipaddr, char *filename, int max_len)
1567{
1568 char *colon;
85f8e03b
LF
1569 struct in_addr ip;
1570 ip.s_addr = 0;
6ab12830
JH
1571
1572 if (net_boot_file_name[0] == '\0')
1573 return 0;
1574
1575 colon = strchr(net_boot_file_name, ':');
1576 if (colon) {
85f8e03b
LF
1577 ip = string_to_ip(net_boot_file_name);
1578 if (ipaddr && ip.s_addr)
1579 *ipaddr = ip;
1580 }
1581 if (ip.s_addr) {
6ab12830
JH
1582 strncpy(filename, colon + 1, max_len);
1583 } else {
1584 strncpy(filename, net_boot_file_name, max_len);
1585 }
1586 filename[max_len - 1] = '\0';
1587
1588 return 1;
1589}
1590
049a95a7 1591void ip_to_string(struct in_addr x, char *s)
2d966958 1592{
049a95a7 1593 x.s_addr = ntohl(x.s_addr);
4f63acd0 1594 sprintf(s, "%d.%d.%d.%d",
049a95a7
JH
1595 (int) ((x.s_addr >> 24) & 0xff),
1596 (int) ((x.s_addr >> 16) & 0xff),
1597 (int) ((x.s_addr >> 8) & 0xff),
1598 (int) ((x.s_addr >> 0) & 0xff)
6e592385 1599 );
2d966958
WD
1600}
1601
4fd5055f 1602void vlan_to_string(ushort x, char *s)
a3d991bd
WD
1603{
1604 x = ntohs(x);
1605
1606 if (x == (ushort)-1)
1607 x = VLAN_NONE;
1608
1609 if (x == VLAN_NONE)
1610 strcpy(s, "none");
1611 else
1612 sprintf(s, "%d", x & VLAN_IDMASK);
1613}
1614
4fd5055f 1615ushort string_to_vlan(const char *s)
a3d991bd
WD
1616{
1617 ushort id;
1618
1619 if (s == NULL)
b9711de1 1620 return htons(VLAN_NONE);
a3d991bd
WD
1621
1622 if (*s < '0' || *s > '9')
1623 id = VLAN_NONE;
1624 else
0b1284eb 1625 id = (ushort)dectoul(s, NULL);
a3d991bd 1626
b9711de1 1627 return htons(id);
a3d991bd
WD
1628}
1629
723806cc 1630ushort env_get_vlan(char *var)
a3d991bd 1631{
00caae6d 1632 return string_to_vlan(env_get(var));
a3d991bd 1633}
This page took 0.81544 seconds and 4 git commands to generate.