2 * Copied from Linux Monitor (LiMon) - Networking.
4 * Copyright 1994 - 2000 Neil Russell.
6 * Copyright 2000 Roland Borde
7 * Copyright 2000 Paolo Scaffardi
8 * Copyright 2000-2002 Wolfgang Denk, wd@denx.de
14 * The user interface supports commands for BOOTP, RARP, and TFTP.
15 * Also, we support ARP internally. Depending on available data,
16 * these interact as follows:
20 * Prerequisites: - own ethernet address
21 * We want: - own IP address
22 * - TFTP server IP address
28 * Prerequisites: - own ethernet address
29 * We want: - own IP address
30 * - TFTP server IP address
35 * Prerequisites: - own ethernet address
37 * - TFTP server IP address
38 * We want: - TFTP server ethernet address
43 * Prerequisites: - own ethernet address
44 * We want: - IP, Netmask, ServerIP, Gateway IP
45 * - bootfilename, lease time
50 * Prerequisites: - own ethernet address
52 * - TFTP server IP address
53 * - TFTP server ethernet address
54 * - name of bootfile (if unknown, we use a default name
55 * derived from our own IP address)
56 * We want: - load the boot file
61 * Prerequisites: - own ethernet address
63 * - name of bootfile (if unknown, we use a default name
64 * derived from our own IP address)
65 * We want: - load the boot file
78 #ifdef CONFIG_STATUS_LED
79 #include <status_led.h>
83 #if (CONFIG_COMMANDS & CFG_CMD_NET)
85 #define ARP_TIMEOUT 5 /* Seconds before trying ARP again */
86 #ifndef CONFIG_NET_RETRY_COUNT
87 # define ARP_TIMEOUT_COUNT 5 /* # of timeouts before giving up */
89 # define ARP_TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT)
96 /** BOOTP EXTENTIONS **/
98 IPaddr_t NetOurSubnetMask
=0; /* Our subnet mask (0=unknown) */
99 IPaddr_t NetOurGatewayIP
=0; /* Our gateways IP address */
100 IPaddr_t NetOurDNSIP
=0; /* Our DNS IP address */
101 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS2)
102 IPaddr_t NetOurDNS2IP
=0; /* Our 2nd DNS IP address */
104 char NetOurNISDomain
[32]={0,}; /* Our NIS domain */
105 char NetOurHostName
[32]={0,}; /* Our hostname */
106 char NetOurRootPath
[64]={0,}; /* Our bootpath */
107 ushort NetBootFileSize
=0; /* Our bootfile size in blocks */
109 /** END OF BOOTP EXTENTIONS **/
111 ulong NetBootFileXferSize
; /* The actual transferred size of the bootfile (in bytes) */
112 uchar NetOurEther
[6]; /* Our ethernet address */
113 uchar NetServerEther
[6] = /* Boot server enet address */
114 { 0, 0, 0, 0, 0, 0 };
115 IPaddr_t NetOurIP
; /* Our IP addr (0 = unknown) */
116 IPaddr_t NetServerIP
; /* Our IP addr (0 = unknown) */
117 volatile uchar
*NetRxPkt
; /* Current receive packet */
118 int NetRxPktLen
; /* Current rx packet length */
119 unsigned NetIPID
; /* IP packet ID */
120 uchar NetBcastAddr
[6] = /* Ethernet bcast address */
121 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
122 uchar NetEtherNullAddr
[6] =
123 { 0, 0, 0, 0, 0, 0 };
124 int NetState
; /* Network loop state */
125 #ifdef CONFIG_NET_MULTI
126 int NetRestartWrap
= 0; /* Tried all network devices */
127 static int NetRestarted
= 0; /* Network loop restarted */
128 static int NetDevExists
= 0; /* At least one device configured */
131 char BootFile
[128]; /* Boot File name */
133 #if (CONFIG_COMMANDS & CFG_CMD_PING)
134 IPaddr_t NetPingIP
; /* the ip address to ping */
136 static void PingStart(void);
139 volatile uchar PktBuf
[(PKTBUFSRX
+1) * PKTSIZE_ALIGN
+ PKTALIGN
];
141 volatile uchar
*NetRxPackets
[PKTBUFSRX
]; /* Receive packets */
143 static rxhand_f
*packetHandler
; /* Current RX packet handler */
144 static thand_f
*timeHandler
; /* Current timeout handler */
145 static ulong timeStart
; /* Time base value */
146 static ulong timeDelta
; /* Current timeout value */
147 volatile uchar
*NetTxPacket
= 0; /* THE transmit packet */
149 static int net_check_prereq (proto_t protocol
);
151 /**********************************************************************/
153 IPaddr_t NetArpWaitPacketIP
;
154 IPaddr_t NetArpWaitReplyIP
;
155 uchar
*NetArpWaitPacketMAC
; /* MAC address of waiting packet's destination */
156 uchar
*NetArpWaitTxPacket
; /* THE transmit packet */
157 int NetArpWaitTxPacketSize
;
158 uchar NetArpWaitPacketBuf
[PKTSIZE_ALIGN
+ PKTALIGN
];
159 ulong NetArpWaitTimerStart
;
162 void ArpRequest(void)
169 printf("ARP broadcast %d\n", NetArpWaitTry
);
173 NetSetEther(pkt
, NetBcastAddr
, PROT_ARP
);
174 pkt
+= ETHER_HDR_SIZE
;
178 arp
->ar_hrd
= htons(ARP_ETHER
);
179 arp
->ar_pro
= htons(PROT_IP
);
182 arp
->ar_op
= htons(ARPOP_REQUEST
);
184 memcpy (&arp
->ar_data
[0], NetOurEther
, 6); /* source ET addr */
185 NetWriteIP((uchar
*)&arp
->ar_data
[6], NetOurIP
); /* source IP addr */
186 for (i
=10; i
<16; ++i
) {
187 arp
->ar_data
[i
] = 0; /* dest ET addr = 0 */
190 if((NetArpWaitPacketIP
& NetOurSubnetMask
) != (NetOurIP
& NetOurSubnetMask
)) {
191 if (NetOurGatewayIP
== 0) {
192 puts ("## Warning: gatewayip needed but not set\n");
194 NetArpWaitReplyIP
= NetOurGatewayIP
;
196 NetArpWaitReplyIP
= NetArpWaitPacketIP
;
198 NetWriteIP((uchar
*)&arp
->ar_data
[16], NetArpWaitReplyIP
);
199 (void) eth_send(NetTxPacket
, ETHER_HDR_SIZE
+ ARP_HDR_SIZE
);
202 void ArpTimeoutCheck(void)
206 if (!NetArpWaitPacketIP
)
211 /* check for arp timeout */
212 if ((t
- NetArpWaitTimerStart
) > ARP_TIMEOUT
* CFG_HZ
) {
215 if (NetArpWaitTry
>= ARP_TIMEOUT_COUNT
) {
216 puts ("\nARP Retry count exceeded; starting again\n");
220 NetArpWaitTimerStart
= t
;
226 /**********************************************************************/
228 * Main network processing loop.
232 NetLoop(proto_t protocol
)
234 DECLARE_GLOBAL_DATA_PTR
;
238 #ifdef CONFIG_NET_MULTI
243 /* XXX problem with bss workaround */
244 NetArpWaitPacketMAC
= NULL
;
245 NetArpWaitTxPacket
= NULL
;
246 NetArpWaitPacketIP
= 0;
247 NetArpWaitReplyIP
= 0;
248 NetArpWaitTxPacket
= NULL
;
255 * Setup packet buffers, aligned correctly.
257 NetTxPacket
= &PktBuf
[0] + (PKTALIGN
- 1);
258 NetTxPacket
-= (ulong
)NetTxPacket
% PKTALIGN
;
259 for (i
= 0; i
< PKTBUFSRX
; i
++) {
260 NetRxPackets
[i
] = NetTxPacket
+ (i
+1)*PKTSIZE_ALIGN
;
265 if (!NetArpWaitTxPacket
) {
266 NetArpWaitTxPacket
= &NetArpWaitPacketBuf
[0] + (PKTALIGN
- 1);
267 NetArpWaitTxPacket
-= (ulong
)NetArpWaitTxPacket
% PKTALIGN
;
268 NetArpWaitTxPacketSize
= 0;
276 #ifdef CONFIG_NET_MULTI
277 memcpy (NetOurEther
, eth_get_dev()->enetaddr
, 6);
279 memcpy (NetOurEther
, bd
->bi_enetaddr
, 6);
282 NetState
= NETLOOP_CONTINUE
;
285 * Start the ball rolling with the given start function. From
286 * here on, this code is a state machine driven by received
287 * packets and timer events.
291 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
294 #if (CONFIG_COMMANDS & CFG_CMD_PING)
298 NetCopyIP(&NetOurIP
, &bd
->bi_ip_addr
);
299 NetOurGatewayIP
= getenv_IPaddr ("gatewayip");
300 NetOurSubnetMask
= getenv_IPaddr ("netmask");
303 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
307 NetServerIP
= getenv_IPaddr ("serverip");
309 #if (CONFIG_COMMANDS & CFG_CMD_PING)
322 * initialize our IP addr to 0 in order to accept ANY
323 * IP addr assigned to us by the BOOTP / RARP server
326 NetServerIP
= getenv_IPaddr ("serverip");
332 switch (net_check_prereq (protocol
)) {
334 /* network not configured */
337 #ifdef CONFIG_NET_MULTI
339 /* network device not configured */
341 #endif /* CONFIG_NET_MULTI */
344 #ifdef CONFIG_NET_MULTI
349 /* always use ARP to get server ethernet address */
353 #if (CONFIG_COMMANDS & CFG_CMD_DHCP)
355 /* Start with a clean slate... */
357 NetServerIP
= getenv_IPaddr ("serverip");
358 DhcpRequest(); /* Basically same as BOOTP */
360 #endif /* CFG_CMD_DHCP */
371 #if (CONFIG_COMMANDS & CFG_CMD_PING)
376 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
385 NetBootFileXferSize
= 0;
389 #if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
390 #if defined(CFG_FAULT_ECHO_LINK_DOWN) && defined(CONFIG_STATUS_LED) && defined(STATUS_LED_RED)
392 * Echo the inverted link state to the fault LED.
394 if(miiphy_link(CFG_FAULT_MII_ADDR
)) {
395 status_led_set (STATUS_LED_RED
, STATUS_LED_OFF
);
397 status_led_set (STATUS_LED_RED
, STATUS_LED_ON
);
399 #endif /* CFG_FAULT_ECHO_LINK_DOWN, ... */
400 #endif /* CONFIG_MII, ... */
403 * Main packet reception loop. Loop receiving packets until
404 * someone sets `NetQuit'.
408 #ifdef CONFIG_SHOW_ACTIVITY
410 extern void show_activity(int arg
);
415 * Check the ethernet for a new packet. The ethernet
416 * receive routine will process it.
421 * Abort if ctrl-c was pressed.
432 * Check for a timeout, and run the timeout handler
435 if (timeHandler
&& ((get_timer(0) - timeStart
) > timeDelta
)) {
438 #if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
439 #if defined(CFG_FAULT_ECHO_LINK_DOWN) && defined(CONFIG_STATUS_LED) && defined(STATUS_LED_RED)
441 * Echo the inverted link state to the fault LED.
443 if(miiphy_link(CFG_FAULT_MII_ADDR
)) {
444 status_led_set (STATUS_LED_RED
, STATUS_LED_OFF
);
446 status_led_set (STATUS_LED_RED
, STATUS_LED_ON
);
448 #endif /* CFG_FAULT_ECHO_LINK_DOWN, ... */
449 #endif /* CONFIG_MII, ... */
451 timeHandler
= (thand_f
*)0;
458 case NETLOOP_RESTART
:
459 #ifdef CONFIG_NET_MULTI
464 case NETLOOP_SUCCESS
:
465 if (NetBootFileXferSize
> 0) {
467 printf("Bytes transferred = %ld (%lx hex)\n",
469 NetBootFileXferSize
);
470 sprintf(buf
, "%lx", NetBootFileXferSize
);
471 setenv("filesize", buf
);
474 return NetBootFileXferSize
;
482 /**********************************************************************/
485 startAgainTimeout(void)
487 NetState
= NETLOOP_RESTART
;
491 startAgainHandler(uchar
* pkt
, unsigned dest
, unsigned src
, unsigned len
)
493 /* Totally ignore the packet */
499 #ifndef CONFIG_NET_MULTI
500 NetSetTimeout(10 * CFG_HZ
, startAgainTimeout
);
501 NetSetHandler(startAgainHandler
);
503 DECLARE_GLOBAL_DATA_PTR
;
506 eth_try_another(!NetRestarted
);
513 NetSetTimeout(10 * CFG_HZ
, startAgainTimeout
);
514 NetSetHandler(startAgainHandler
);
518 NetState
= NETLOOP_FAIL
;
523 NetState
= NETLOOP_RESTART
;
528 /**********************************************************************/
534 NetSetHandler(rxhand_f
* f
)
541 NetSetTimeout(int iv
, thand_f
* f
)
544 timeHandler
= (thand_f
*)0;
547 timeStart
= get_timer(0);
554 NetSendPacket(volatile uchar
* pkt
, int len
)
556 (void) eth_send(pkt
, len
);
560 NetSendUDPPacket(uchar
*ether
, IPaddr_t dest
, int dport
, int sport
, int len
)
562 /* convert to new style broadcast */
566 /* if broadcast, make the ether address a broadcast and don't do ARP */
567 if (dest
== 0xFFFFFFFF)
568 ether
= NetBcastAddr
;
570 /* if MAC address was not discovered yet, save the packet and do an ARP request */
571 if (memcmp(ether
, NetEtherNullAddr
, 6) == 0) {
574 printf("sending ARP for %08lx\n", dest
);
577 NetArpWaitPacketIP
= dest
;
578 NetArpWaitPacketMAC
= ether
;
579 NetSetEther (NetArpWaitTxPacket
, NetArpWaitPacketMAC
, PROT_IP
);
580 NetSetIP (NetArpWaitTxPacket
+ ETHER_HDR_SIZE
, dest
, dport
, sport
, len
);
581 memcpy(NetArpWaitTxPacket
+ ETHER_HDR_SIZE
+ IP_HDR_SIZE
,
582 (uchar
*)NetTxPacket
+ ETHER_HDR_SIZE
+ IP_HDR_SIZE
, len
);
584 /* size of the waiting packet */
585 NetArpWaitTxPacketSize
= ETHER_HDR_SIZE
+ IP_HDR_SIZE
+ len
;
587 /* and do the ARP request */
589 NetArpWaitTimerStart
= get_timer(0);
591 return 1; /* waiting */
595 printf("sending UDP to %08lx/%02x:%02x:%02x:%02x:%02x:%02x\n",
596 dest
, ether
[0], ether
[1], ether
[2], ether
[3], ether
[4], ether
[5]);
599 NetSetEther (NetTxPacket
, ether
, PROT_IP
);
600 NetSetIP (NetTxPacket
+ ETHER_HDR_SIZE
, dest
, dport
, sport
, len
);
601 (void) eth_send(NetTxPacket
, ETHER_HDR_SIZE
+ IP_HDR_SIZE
+ len
);
603 return 0; /* transmited */
606 #if (CONFIG_COMMANDS & CFG_CMD_PING)
607 static ushort PingSeqNo
;
615 /* XXX always send arp request */
617 memcpy(mac
, NetEtherNullAddr
, 6);
620 printf("sending ARP for %08lx\n", NetPingIP
);
623 NetArpWaitPacketIP
= NetPingIP
;
624 NetArpWaitPacketMAC
= mac
;
626 NetSetEther(NetArpWaitTxPacket
, mac
, PROT_IP
);
628 ip
= (volatile IP_t
*)(NetArpWaitTxPacket
+ ETHER_HDR_SIZE
);
631 * Construct an IP and ICMP header. (need to set no fragment bit - XXX)
633 ip
->ip_hl_v
= 0x45; /* IP_HDR_SIZE / 4 (not including UDP) */
635 ip
->ip_len
= htons(IP_HDR_SIZE_NO_UDP
+ 8);
636 ip
->ip_id
= htons(NetIPID
++);
637 ip
->ip_off
= htons(0x4000); /* No fragmentation */
639 ip
->ip_p
= 0x01; /* ICMP */
641 NetCopyIP((void*)&ip
->ip_src
, &NetOurIP
); /* already in network byte order */
642 NetCopyIP((void*)&ip
->ip_dst
, &NetPingIP
); /* - "" - */
643 ip
->ip_sum
= ~NetCksum((uchar
*)ip
, IP_HDR_SIZE_NO_UDP
/ 2);
645 s
= &ip
->udp_src
; /* XXX ICMP starts here */
646 s
[0] = htons(0x0800); /* echo-request, code */
647 s
[1] = 0; /* checksum */
648 s
[2] = 0; /* identifier */
649 s
[3] = htons(PingSeqNo
++); /* sequence number */
650 s
[1] = ~NetCksum((uchar
*)s
, 8/2);
652 /* size of the waiting packet */
653 NetArpWaitTxPacketSize
= ETHER_HDR_SIZE
+ IP_HDR_SIZE_NO_UDP
+ 8;
655 /* and do the ARP request */
657 NetArpWaitTimerStart
= get_timer(0);
659 return 1; /* waiting */
666 NetState
= NETLOOP_FAIL
; /* we did not get the reply */
670 PingHandler (uchar
* pkt
, unsigned dest
, unsigned src
, unsigned len
)
673 volatile IP_t
*ip
= (volatile IP_t
*)pkt
;
675 tmp
= NetReadIP((void *)&ip
->ip_src
);
676 if (tmp
!= NetPingIP
)
679 NetState
= NETLOOP_SUCCESS
;
682 static void PingStart(void)
684 NetSetTimeout (10 * CFG_HZ
, PingTimeout
);
685 NetSetHandler (PingHandler
);
693 NetReceive(volatile uchar
* pkt
, int len
)
703 et
= (Ethernet_t
*)pkt
;
705 x
= ntohs(et
->et_protlen
);
709 * Got a 802 packet. Check the other protocol field.
711 x
= ntohs(et
->et_prot
);
712 ip
= (IP_t
*)(pkt
+ E802_HDR_SIZE
);
713 len
-= E802_HDR_SIZE
;
715 ip
= (IP_t
*)(pkt
+ ETHER_HDR_SIZE
);
716 len
-= ETHER_HDR_SIZE
;
720 printf("Receive from protocol 0x%x\n", x
);
727 * We have to deal with two types of ARP packets:
728 * - REQUEST packets will be answered by sending our
729 * IP address - if we know it.
730 * - REPLY packates are expected only after we asked
731 * for the TFTP server's or the gateway's ethernet
732 * address; so if we receive such a packet, we set
733 * the server ethernet address
739 if (len
< ARP_HDR_SIZE
) {
740 printf("bad length %d < %d\n", len
, ARP_HDR_SIZE
);
743 if (ntohs(arp
->ar_hrd
) != ARP_ETHER
) {
746 if (ntohs(arp
->ar_pro
) != PROT_IP
) {
749 if (arp
->ar_hln
!= 6) {
752 if (arp
->ar_pln
!= 4) {
760 if (NetReadIP(&arp
->ar_data
[16]) != NetOurIP
) {
764 switch (ntohs(arp
->ar_op
)) {
765 case ARPOP_REQUEST
: /* reply with our IP address */
767 printf("Got ARP REQUEST, return our IP\n");
769 NetSetEther((uchar
*)et
, et
->et_src
, PROT_ARP
);
770 arp
->ar_op
= htons(ARPOP_REPLY
);
771 memcpy (&arp
->ar_data
[10], &arp
->ar_data
[0], 6);
772 NetCopyIP(&arp
->ar_data
[16], &arp
->ar_data
[6]);
773 memcpy (&arp
->ar_data
[ 0], NetOurEther
, 6);
774 NetCopyIP(&arp
->ar_data
[ 6], &NetOurIP
);
775 (void) eth_send((uchar
*)et
, ((uchar
*)arp
-pkt
) + ARP_HDR_SIZE
);
778 case ARPOP_REPLY
: /* arp reply */
779 /* are we waiting for a reply */
780 if (!NetArpWaitPacketIP
|| !NetArpWaitPacketMAC
)
783 printf("Got ARP REPLY, set server/gtwy eth addr (%02x:%02x:%02x:%02x:%02x:%02x)\n",
784 arp
->ar_data
[0], arp
->ar_data
[1],
785 arp
->ar_data
[2], arp
->ar_data
[3],
786 arp
->ar_data
[4], arp
->ar_data
[5]);
789 tmp
= NetReadIP(&arp
->ar_data
[6]);
791 /* matched waiting packet's address */
792 if (tmp
== NetArpWaitReplyIP
) {
796 /* save address for later use */
797 memcpy(NetArpWaitPacketMAC
, &arp
->ar_data
[0], 6);
799 /* modify header, and transmit it */
800 memcpy(((Ethernet_t
*)NetArpWaitTxPacket
)->et_dest
, NetArpWaitPacketMAC
, 6);
801 (void) eth_send(NetArpWaitTxPacket
, NetArpWaitTxPacketSize
);
803 /* no arp request pending now */
804 NetArpWaitPacketIP
= 0;
805 NetArpWaitTxPacketSize
= 0;
806 NetArpWaitPacketMAC
= NULL
;
812 printf("Unexpected ARP opcode 0x%x\n", ntohs(arp
->ar_op
));
819 printf("Got RARP\n");
822 if (len
< ARP_HDR_SIZE
) {
823 printf("bad length %d < %d\n", len
, ARP_HDR_SIZE
);
827 if ((ntohs(arp
->ar_op
) != RARPOP_REPLY
) ||
828 (ntohs(arp
->ar_hrd
) != ARP_ETHER
) ||
829 (ntohs(arp
->ar_pro
) != PROT_IP
) ||
830 (arp
->ar_hln
!= 6) || (arp
->ar_pln
!= 4)) {
832 printf("invalid RARP header\n");
834 NetCopyIP(&NetOurIP
, &arp
->ar_data
[16]);
835 if (NetServerIP
== 0)
836 NetCopyIP(&NetServerIP
, &arp
->ar_data
[ 6]);
837 memcpy (NetServerEther
, &arp
->ar_data
[ 0], 6);
839 (*packetHandler
)(0,0,0,0);
847 if (len
< IP_HDR_SIZE
) {
848 debug ("len bad %d < %d\n", len
, IP_HDR_SIZE
);
851 if (len
< ntohs(ip
->ip_len
)) {
852 printf("len bad %d < %d\n", len
, ntohs(ip
->ip_len
));
855 len
= ntohs(ip
->ip_len
);
857 printf("len=%d, v=%02x\n", len
, ip
->ip_hl_v
& 0xff);
859 if ((ip
->ip_hl_v
& 0xf0) != 0x40) {
862 if (ip
->ip_off
& htons(0x1fff)) { /* Can't deal w/ fragments */
865 if (!NetCksumOk((uchar
*)ip
, IP_HDR_SIZE_NO_UDP
/ 2)) {
866 printf("checksum bad\n");
869 tmp
= NetReadIP(&ip
->ip_dst
);
870 if (NetOurIP
&& tmp
!= NetOurIP
&& tmp
!= 0xFFFFFFFF) {
874 * watch for ICMP host redirects
876 * There is no real handler code (yet). We just watch
877 * for ICMP host redirect messages. In case anybody
878 * sees these messages: please contact me
879 * (wd@denx.de), or - even better - send me the
880 * necessary fixes :-)
882 * Note: in all cases where I have seen this so far
883 * it was a problem with the router configuration,
884 * for instance when a router was configured in the
885 * BOOTP reply, but the TFTP server was on the same
886 * subnet. So this is probably a warning that your
887 * configuration might be wrong. But I'm not really
888 * sure if there aren't any other situations.
890 if (ip
->ip_p
== IPPROTO_ICMP
) {
891 ICMP_t
*icmph
= (ICMP_t
*)&(ip
->udp_src
);
893 switch (icmph
->type
) {
895 if (icmph
->code
!= ICMP_REDIR_HOST
)
897 puts (" ICMP Host Redirect to ");
898 print_IPaddr(icmph
->un
.gateway
);
901 #if (CONFIG_COMMANDS & CFG_CMD_PING)
902 case ICMP_ECHO_REPLY
:
904 * IP header OK. Pass the packet to the current handler.
906 /* XXX point to ip packet */
907 (*packetHandler
)((uchar
*)ip
, 0, 0, 0);
913 } else if (ip
->ip_p
!= IPPROTO_UDP
) { /* Only UDP packets */
918 * IP header OK. Pass the packet to the current handler.
920 (*packetHandler
)((uchar
*)ip
+IP_HDR_SIZE
,
923 ntohs(ip
->udp_len
) - 8);
930 /**********************************************************************/
932 static int net_check_prereq (proto_t protocol
)
936 #if (CONFIG_COMMANDS & CFG_CMD_PING)
938 if (NetPingIP
== 0) {
939 puts ("*** ERROR: ping address not given\n");
944 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
948 if (NetServerIP
== 0) {
949 puts ("*** ERROR: `serverip' not set\n");
953 #if (CONFIG_COMMANDS & CFG_CMD_PING)
958 puts ("*** ERROR: `ipaddr' not set\n");
966 if (memcmp(NetOurEther
, "\0\0\0\0\0\0", 6) == 0) {
967 #ifdef CONFIG_NET_MULTI
968 extern int eth_get_dev_index (void);
969 int num
= eth_get_dev_index();
973 puts ("*** ERROR: No ethernet found.\n");
976 puts ("*** ERROR: `ethaddr' not set\n");
979 printf ("*** ERROR: `eth%daddr' not set\n",
987 puts ("*** ERROR: `ethaddr' not set\n");
997 /**********************************************************************/
1000 NetCksumOk(uchar
* ptr
, int len
)
1002 return !((NetCksum(ptr
, len
) + 1) & 0xfffe);
1007 NetCksum(uchar
* ptr
, int len
)
1013 xsum
+= *((ushort
*)ptr
)++;
1014 xsum
= (xsum
& 0xffff) + (xsum
>> 16);
1015 xsum
= (xsum
& 0xffff) + (xsum
>> 16);
1016 return (xsum
& 0xffff);
1021 NetSetEther(volatile uchar
* xet
, uchar
* addr
, uint prot
)
1023 Ethernet_t
*et
= (Ethernet_t
*)xet
;
1025 memcpy (et
->et_dest
, addr
, 6);
1026 memcpy (et
->et_src
, NetOurEther
, 6);
1027 et
->et_protlen
= htons(prot
);
1032 NetSetIP(volatile uchar
* xip
, IPaddr_t dest
, int dport
, int sport
, int len
)
1034 volatile IP_t
*ip
= (IP_t
*)xip
;
1037 * If the data is an odd number of bytes, zero the
1038 * byte after the last byte so that the checksum
1042 xip
[IP_HDR_SIZE
+ len
] = 0;
1045 * Construct an IP and UDP header.
1046 (need to set no fragment bit - XXX)
1048 ip
->ip_hl_v
= 0x45; /* IP_HDR_SIZE / 4 (not including UDP) */
1050 ip
->ip_len
= htons(IP_HDR_SIZE
+ len
);
1051 ip
->ip_id
= htons(NetIPID
++);
1052 ip
->ip_off
= htons(0x4000); /* No fragmentation */
1054 ip
->ip_p
= 17; /* UDP */
1056 NetCopyIP((void*)&ip
->ip_src
, &NetOurIP
); /* already in network byte order */
1057 NetCopyIP((void*)&ip
->ip_dst
, &dest
); /* - "" - */
1058 ip
->udp_src
= htons(sport
);
1059 ip
->udp_dst
= htons(dport
);
1060 ip
->udp_len
= htons(8 + len
);
1062 ip
->ip_sum
= ~NetCksum((uchar
*)ip
, IP_HDR_SIZE_NO_UDP
/ 2);
1065 void copy_filename (uchar
*dst
, uchar
*src
, int size
)
1067 if (*src
&& (*src
== '"')) {
1072 while ((--size
> 0) && *src
&& (*src
!= '"')) {
1078 #endif /* CFG_CMD_NET */
1080 void ip_to_string (IPaddr_t x
, char *s
)
1083 sprintf (s
,"%d.%d.%d.%d",
1084 (int)((x
>> 24) & 0xff),
1085 (int)((x
>> 16) & 0xff),
1086 (int)((x
>> 8) & 0xff),
1087 (int)((x
>> 0) & 0xff)
1091 IPaddr_t
string_to_ip(char *s
)
1100 for (addr
=0, i
=0; i
<4; ++i
) {
1101 ulong val
= s
? simple_strtoul(s
, &e
, 10) : 0;
1103 addr
|= (val
& 0xFF);
1109 return (htonl(addr
));
1112 void print_IPaddr (IPaddr_t x
)
1116 ip_to_string(x
, tmp
);
1121 IPaddr_t
getenv_IPaddr (char *var
)
1123 return (string_to_ip(getenv(var
)));