net: remove need for eth_halt/eth_open
[barebox-mini2440.git] / net / net.c
blob28943a039e11d8d9f58aebbe7fa7b09c2c9d1702
1 /*
2 * Copied from Linux Monitor (LiMon) - Networking.
4 * Copyright 1994 - 2000 Neil Russell.
5 * (See License)
6 * Copyright 2000 Roland Borde
7 * Copyright 2000 Paolo Scaffardi
8 * Copyright 2000-2002 Wolfgang Denk, wd@denx.de
9 */
12 * General Desription:
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:
18 * BOOTP:
20 * Prerequisites: - own ethernet address
21 * We want: - own IP address
22 * - TFTP server IP address
23 * - name of bootfile
24 * Next step: ARP
26 * RARP:
28 * Prerequisites: - own ethernet address
29 * We want: - own IP address
30 * - TFTP server IP address
31 * Next step: ARP
33 * ARP:
35 * Prerequisites: - own ethernet address
36 * - own IP address
37 * - TFTP server IP address
38 * We want: - TFTP server ethernet address
39 * Next step: TFTP
41 * DHCP:
43 * Prerequisites: - own ethernet address
44 * We want: - IP, Netmask, ServerIP, Gateway IP
45 * - bootfilename, lease time
46 * Next step: - TFTP
48 * TFTP:
50 * Prerequisites: - own ethernet address
51 * - own IP 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
57 * Next step: none
59 * NFS:
61 * Prerequisites: - own ethernet address
62 * - own IP 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
66 * Next step: none
71 #include <common.h>
72 #include <clock.h>
73 #include <watchdog.h>
74 #include <command.h>
75 #include <environment.h>
76 #include <param.h>
77 #include <net.h>
78 #include <driver.h>
79 #include <errno.h>
80 #include <linux/ctype.h>
81 #include "tftp.h"
82 #include "rarp.h"
83 #include "nfs.h"
85 #define ARP_TIMEOUT (5 * SECOND) /* Seconds before trying ARP again */
86 #ifndef CONFIG_NET_RETRY_COUNT
87 # define ARP_TIMEOUT_COUNT 5 /* # of timeouts before giving up */
88 #else
89 # define ARP_TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT)
90 #endif
93 /** BOOTP EXTENTIONS **/
95 IPaddr_t NetOurSubnetMask=0; /* Our subnet mask (0=unknown) */
96 IPaddr_t NetOurGatewayIP=0; /* Our gateways IP address */
97 IPaddr_t NetOurDNSIP=0; /* Our DNS IP address */
98 #ifdef CONFIG_BOOTP_DNS2
99 IPaddr_t NetOurDNS2IP=0; /* Our 2nd DNS IP address */
100 #endif
101 char NetOurNISDomain[32]={0,}; /* Our NIS domain */
102 char NetOurHostName[32]={0,}; /* Our hostname */
103 char NetOurRootPath[64]={0,}; /* Our bootpath */
105 /** END OF BOOTP EXTENTIONS **/
107 ulong NetBootFileXferSize; /* The actual transferred size of the bootfile (in bytes) */
108 uchar NetOurEther[6]; /* Our ethernet address */
109 uchar NetServerEther[6] = /* Boot server enet address */
110 { 0, 0, 0, 0, 0, 0 };
111 IPaddr_t NetOurIP; /* Our IP addr (0 = unknown) */
112 IPaddr_t NetServerIP; /* Our IP addr (0 = unknown) */
113 uchar *NetRxPkt; /* Current receive packet */
114 int NetRxPktLen; /* Current rx packet length */
115 unsigned NetIPID; /* IP packet ID */
116 uchar NetBcastAddr[6] = /* Ethernet bcast address */
117 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
118 uchar NetEtherNullAddr[6] =
119 { 0, 0, 0, 0, 0, 0 };
120 int NetState; /* Network loop state */
122 /* XXX in both little & big endian machines 0xFFFF == ntohs(-1) */
123 ushort NetOurVLAN = 0xFFFF; /* default is without VLAN */
124 ushort NetOurNativeVLAN = 0xFFFF; /* ditto */
126 char BootFile[128]; /* Boot File name */
128 uchar PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];
130 uchar *NetRxPackets[PKTBUFSRX]; /* Receive packets */
132 static rxhand_f *packetHandler; /* Current RX packet handler */
133 static thand_f *timeHandler; /* Current timeout handler */
134 static uint64_t timeStart; /* Time base value */
135 static uint64_t timeDelta; /* Current timeout value */
136 uchar *NetTxPacket = 0; /* THE transmit packet */
138 static int net_check_prereq (proto_t protocol);
140 /**********************************************************************/
142 IPaddr_t NetArpWaitPacketIP;
143 IPaddr_t NetArpWaitReplyIP;
144 uchar *NetArpWaitPacketMAC; /* MAC address of waiting packet's destination */
145 uchar *NetArpWaitTxPacket; /* THE transmit packet */
146 int NetArpWaitTxPacketSize;
147 uchar NetArpWaitPacketBuf[PKTSIZE_ALIGN + PKTALIGN];
148 uint64_t NetArpWaitTimerStart;
150 void ArpRequest (void)
152 int i;
153 uchar *pkt;
154 ARP_t *arp;
156 pr_debug("ARP broadcast\n");
158 pkt = NetTxPacket;
160 pkt += NetSetEther (pkt, NetBcastAddr, PROT_ARP);
162 arp = (ARP_t *) pkt;
164 arp->ar_hrd = htons (ARP_ETHER);
165 arp->ar_pro = htons (PROT_IP);
166 arp->ar_hln = 6;
167 arp->ar_pln = 4;
168 arp->ar_op = htons (ARPOP_REQUEST);
170 memcpy (&arp->ar_data[0], NetOurEther, 6); /* source ET addr */
171 NetWriteIP ((uchar *) & arp->ar_data[6], NetOurIP); /* source IP addr */
172 for (i = 10; i < 16; ++i) {
173 arp->ar_data[i] = 0; /* dest ET addr = 0 */
176 if ((NetArpWaitPacketIP & NetOurSubnetMask) !=
177 (NetOurIP & NetOurSubnetMask)) {
178 if (NetOurGatewayIP == 0) {
179 puts ("## Warning: gatewayip needed but not set\n");
180 NetArpWaitReplyIP = NetArpWaitPacketIP;
181 } else {
182 NetArpWaitReplyIP = NetOurGatewayIP;
184 } else {
185 NetArpWaitReplyIP = NetArpWaitPacketIP;
188 NetWriteIP ((uchar *) & arp->ar_data[16], NetArpWaitReplyIP);
189 (void) eth_send (NetTxPacket, (pkt - NetTxPacket) + ARP_HDR_SIZE);
192 /**********************************************************************/
194 * Main network processing loop.
197 int NetLoopInit(proto_t protocol)
199 struct eth_device *eth_current = eth_get_current();
200 IPaddr_t ip;
201 int ret;
202 int i;
204 if (!eth_current) {
205 printf("Current ethernet device not set!\n");
206 return -1;
209 ip = dev_get_param_ip(&eth_current->dev, "ipaddr");
210 NetCopyIP(&NetOurIP, &ip);
212 /* XXX problem with bss workaround */
213 NetArpWaitPacketMAC = NULL;
214 NetArpWaitTxPacket = NULL;
215 NetArpWaitPacketIP = 0;
216 NetArpWaitReplyIP = 0;
219 * Setup packet buffers, aligned correctly.
221 NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
222 NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;
223 for (i = 0; i < PKTBUFSRX; i++) {
224 NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN;
227 NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1);
228 NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN;
229 NetArpWaitTxPacketSize = 0;
231 string_to_ethaddr(dev_get_param(&eth_get_current()->dev, "ethaddr"),
232 NetOurEther);
234 NetState = NETLOOP_CONTINUE;
236 NetOurGatewayIP = dev_get_param_ip(&eth_current->dev, "gateway");
237 NetOurSubnetMask = dev_get_param_ip(&eth_current->dev, "netmask");
238 NetOurVLAN = getenv_VLAN("vlan");
239 NetOurNativeVLAN = getenv_VLAN("nvlan");
240 NetServerIP = dev_get_param_ip(&eth_current->dev, "serverip");
242 ret = net_check_prereq(protocol);
244 return ret;
247 int NetLoop(void)
250 * Start the ball rolling with the given start function. From
251 * here on, this code is a state machine driven by received
252 * packets and timer events.
255 NetBootFileXferSize = 0;
258 * Main packet reception loop. Loop receiving packets until
259 * someone sets `NetState' to a state that terminates.
261 for (;;) {
262 WATCHDOG_RESET();
263 #ifdef CONFIG_SHOW_ACTIVITY
265 extern void show_activity(int arg);
266 show_activity(1);
268 #endif
270 * Check the ethernet for a new packet. The ethernet
271 * receive routine will process it.
273 eth_rx();
276 * Abort if ctrl-c was pressed.
278 if (ctrlc()) {
279 puts ("\nAbort\n");
280 return -1;
283 /* check for arp timeout */
284 if (NetArpWaitPacketIP &&
285 is_timeout(NetArpWaitTimerStart, ARP_TIMEOUT)) {
286 NetArpWaitTimerStart = get_time_ns();
287 ArpRequest();
291 * Check for a timeout, and run the timeout handler
292 * if we have one.
294 if (timeHandler && is_timeout(timeStart, timeDelta)) {
295 thand_f *x;
296 x = timeHandler;
297 timeHandler = (thand_f *)0;
298 (*x)();
302 switch (NetState) {
303 case NETLOOP_SUCCESS:
304 if (NetBootFileXferSize > 0) {
305 char buf[10];
306 printf("Bytes transferred = %ld (%lx hex)\n",
307 NetBootFileXferSize,
308 NetBootFileXferSize);
309 sprintf(buf, "0x%lx", NetBootFileXferSize);
310 setenv("filesize", buf);
312 return NetBootFileXferSize;
314 case NETLOOP_FAIL:
315 return -1;
320 /**********************************************************************/
322 * Miscelaneous bits.
325 void
326 NetSetHandler(rxhand_f * f)
328 packetHandler = f;
332 void
333 NetSetTimeout(uint64_t iv, thand_f * f)
335 if (iv == 0) {
336 timeHandler = (thand_f *)0;
337 } else {
338 timeHandler = f;
339 timeStart = get_time_ns();
340 timeDelta = iv;
345 void
346 NetSendPacket(uchar * pkt, int len)
348 (void) eth_send(pkt, len);
352 NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, int len)
354 uchar *pkt;
356 /* convert to new style broadcast */
357 if (dest == 0)
358 dest = 0xFFFFFFFF;
360 /* if broadcast, make the ether address a broadcast and don't do ARP */
361 if (dest == 0xFFFFFFFF)
362 ether = NetBcastAddr;
364 /* if MAC address was not discovered yet, save the packet and do an ARP request */
365 if (memcmp(ether, NetEtherNullAddr, 6) == 0) {
366 pr_debug("sending ARP for %08lx\n", dest);
368 NetArpWaitPacketIP = dest;
369 NetArpWaitPacketMAC = ether;
371 pkt = NetArpWaitTxPacket;
372 pkt += NetSetEther (pkt, NetArpWaitPacketMAC, PROT_IP);
374 NetSetIP (pkt, dest, dport, sport, len);
375 memcpy(pkt + IP_HDR_SIZE, (uchar *)NetTxPacket + (pkt - (uchar *)NetArpWaitTxPacket) + IP_HDR_SIZE, len);
377 /* size of the waiting packet */
378 NetArpWaitTxPacketSize = (pkt - NetArpWaitTxPacket) + IP_HDR_SIZE + len;
380 /* and do the ARP request */
381 NetArpWaitTimerStart = get_time_ns();
382 ArpRequest();
383 return 1; /* waiting */
386 pr_debug("sending UDP to %08lx/%02x:%02x:%02x:%02x:%02x:%02x\n",
387 dest, ether[0], ether[1], ether[2], ether[3], ether[4], ether[5]);
389 pkt = (uchar *)NetTxPacket;
390 pkt += NetSetEther (pkt, ether, PROT_IP);
391 NetSetIP (pkt, dest, dport, sport, len);
392 (void) eth_send(NetTxPacket, (pkt - NetTxPacket) + IP_HDR_SIZE + len);
394 return 0; /* transmitted */
397 void
398 NetReceive(uchar * inpkt, int len)
400 Ethernet_t *et;
401 IP_t *ip;
402 ARP_t *arp;
403 IPaddr_t tmp;
404 int x;
405 uchar *pkt;
406 ushort cti = 0, vlanid = VLAN_NONE, myvlanid, mynvlanid;
408 pr_debug("packet received\n");
410 NetRxPkt = inpkt;
411 NetRxPktLen = len;
412 et = (Ethernet_t *)inpkt;
414 /* too small packet? */
415 if (len < ETHER_HDR_SIZE)
416 return;
418 myvlanid = ntohs(NetOurVLAN);
419 if (myvlanid == (ushort)-1)
420 myvlanid = VLAN_NONE;
421 mynvlanid = ntohs(NetOurNativeVLAN);
422 if (mynvlanid == (ushort)-1)
423 mynvlanid = VLAN_NONE;
425 x = ntohs(et->et_protlen);
427 pr_debug("packet received\n");
429 if (x < 1514) {
431 * Got a 802 packet. Check the other protocol field.
433 x = ntohs(et->et_prot);
435 ip = (IP_t *)(inpkt + E802_HDR_SIZE);
436 len -= E802_HDR_SIZE;
438 } else if (x != PROT_VLAN) { /* normal packet */
439 ip = (IP_t *)(inpkt + ETHER_HDR_SIZE);
440 len -= ETHER_HDR_SIZE;
442 } else { /* VLAN packet */
443 VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)et;
445 pr_debug("VLAN packet received\n");
447 /* too small packet? */
448 if (len < VLAN_ETHER_HDR_SIZE)
449 return;
451 /* if no VLAN active */
452 if ((ntohs(NetOurVLAN) & VLAN_IDMASK) == VLAN_NONE
454 return;
456 cti = ntohs(vet->vet_tag);
457 vlanid = cti & VLAN_IDMASK;
458 x = ntohs(vet->vet_type);
460 ip = (IP_t *)(inpkt + VLAN_ETHER_HDR_SIZE);
461 len -= VLAN_ETHER_HDR_SIZE;
464 pr_debug("Receive from protocol 0x%x\n", x);
466 if ((myvlanid & VLAN_IDMASK) != VLAN_NONE) {
467 if (vlanid == VLAN_NONE)
468 vlanid = (mynvlanid & VLAN_IDMASK);
469 /* not matched? */
470 if (vlanid != (myvlanid & VLAN_IDMASK))
471 return;
474 switch (x) {
476 case PROT_ARP:
478 * We have to deal with two types of ARP packets:
479 * - REQUEST packets will be answered by sending our
480 * IP address - if we know it.
481 * - REPLY packets are expected only after we asked
482 * for the TFTP server's or the gateway's ethernet
483 * address; so if we receive such a packet, we set
484 * the server ethernet address
486 pr_debug("Got ARP\n");
488 arp = (ARP_t *)ip;
489 if (len < ARP_HDR_SIZE) {
490 printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
491 return;
493 if (ntohs(arp->ar_hrd) != ARP_ETHER) {
494 return;
496 if (ntohs(arp->ar_pro) != PROT_IP) {
497 return;
499 if (arp->ar_hln != 6) {
500 return;
502 if (arp->ar_pln != 4) {
503 return;
506 if (NetOurIP == 0) {
507 return;
510 if (NetReadIP(&arp->ar_data[16]) != NetOurIP) {
511 return;
514 switch (ntohs(arp->ar_op)) {
515 case ARPOP_REQUEST: /* reply with our IP address */
516 pr_debug("Got ARP REQUEST, return our IP\n");
518 pkt = (uchar *)et;
519 pkt += NetSetEther(pkt, et->et_src, PROT_ARP);
520 arp->ar_op = htons(ARPOP_REPLY);
521 memcpy (&arp->ar_data[10], &arp->ar_data[0], 6);
522 NetCopyIP(&arp->ar_data[16], &arp->ar_data[6]);
523 memcpy (&arp->ar_data[ 0], NetOurEther, 6);
524 NetCopyIP(&arp->ar_data[ 6], &NetOurIP);
525 memcpy(NetTxPacket, et, (pkt - (uchar *)et) + ARP_HDR_SIZE);
526 eth_send((uchar *)NetTxPacket, (pkt - (uchar *)et) + ARP_HDR_SIZE);
527 return;
529 case ARPOP_REPLY: /* arp reply */
530 /* are we waiting for a reply */
531 if (!NetArpWaitPacketIP || !NetArpWaitPacketMAC)
532 break;
533 pr_debug("Got ARP REPLY, set server/gtwy eth addr (%02x:%02x:%02x:%02x:%02x:%02x)\n",
534 arp->ar_data[0], arp->ar_data[1],
535 arp->ar_data[2], arp->ar_data[3],
536 arp->ar_data[4], arp->ar_data[5]);
538 tmp = NetReadIP(&arp->ar_data[6]);
540 /* matched waiting packet's address */
541 if (tmp == NetArpWaitReplyIP) {
542 pr_debug("Got it\n");
544 /* save address for later use */
545 memcpy(NetArpWaitPacketMAC, &arp->ar_data[0], 6);
547 /* modify header, and transmit it */
548 memcpy(((Ethernet_t *)NetArpWaitTxPacket)->et_dest, NetArpWaitPacketMAC, 6);
549 (void) eth_send(NetArpWaitTxPacket, NetArpWaitTxPacketSize);
551 /* no arp request pending now */
552 NetArpWaitPacketIP = 0;
553 NetArpWaitTxPacketSize = 0;
554 NetArpWaitPacketMAC = NULL;
557 return;
558 default:
559 pr_debug("Unexpected ARP opcode 0x%x\n", ntohs(arp->ar_op));
560 return;
562 break;
564 case PROT_RARP:
565 pr_debug("Got RARP\n");
567 arp = (ARP_t *)ip;
568 if (len < ARP_HDR_SIZE) {
569 printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
570 return;
573 if ((ntohs(arp->ar_op) != RARPOP_REPLY) ||
574 (ntohs(arp->ar_hrd) != ARP_ETHER) ||
575 (ntohs(arp->ar_pro) != PROT_IP) ||
576 (arp->ar_hln != 6) || (arp->ar_pln != 4)) {
578 puts ("invalid RARP header\n");
579 } else {
580 NetCopyIP(&NetOurIP, &arp->ar_data[16]);
581 if (NetServerIP == 0)
582 NetCopyIP(&NetServerIP, &arp->ar_data[ 6]);
583 memcpy (NetServerEther, &arp->ar_data[ 0], 6);
585 (*packetHandler)(0,0,0,0);
587 break;
589 case PROT_IP:
590 pr_debug("Got IP\n");
592 if (len < IP_HDR_SIZE) {
593 debug ("len bad %d < %d\n", len, IP_HDR_SIZE);
594 return;
596 if (len < ntohs(ip->ip_len)) {
597 printf("len bad %d < %d\n", len, ntohs(ip->ip_len));
598 return;
600 len = ntohs(ip->ip_len);
602 pr_debug("len=%d, v=%02x\n", len, ip->ip_hl_v & 0xff);
604 if ((ip->ip_hl_v & 0xf0) != 0x40) {
605 return;
607 if (ip->ip_off & htons(0x1fff)) { /* Can't deal w/ fragments */
608 return;
610 if (!NetCksumOk((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2)) {
611 puts ("checksum bad\n");
612 return;
614 tmp = NetReadIP(&ip->ip_dst);
615 if (NetOurIP && tmp != NetOurIP && tmp != 0xFFFFFFFF) {
616 return;
619 * watch for ICMP host redirects
621 * There is no real handler code (yet). We just watch
622 * for ICMP host redirect messages. In case anybody
623 * sees these messages: please contact me
624 * (wd@denx.de), or - even better - send me the
625 * necessary fixes :-)
627 * Note: in all cases where I have seen this so far
628 * it was a problem with the router configuration,
629 * for instance when a router was configured in the
630 * BOOTP reply, but the TFTP server was on the same
631 * subnet. So this is probably a warning that your
632 * configuration might be wrong. But I'm not really
633 * sure if there aren't any other situations.
635 if (ip->ip_p == IPPROTO_ICMP) {
636 ICMP_t *icmph = (ICMP_t *)&(ip->udp_src);
638 switch (icmph->type) {
639 case ICMP_REDIRECT:
640 if (icmph->code != ICMP_REDIR_HOST)
641 return;
642 puts (" ICMP Host Redirect to ");
643 print_IPaddr(icmph->un.gateway);
644 putchar(' ');
645 return;
646 #ifdef CONFIG_NET_PING
647 case ICMP_ECHO_REPLY:
649 * IP header OK. Pass the packet to the current handler.
651 /* XXX point to ip packet */
652 (*packetHandler)((uchar *)ip, 0, 0, 0);
653 return;
654 #endif
655 default:
656 return;
658 } else if (ip->ip_p != IPPROTO_UDP) { /* Only UDP packets */
659 return;
662 #ifdef CONFIG_UDP_CHECKSUM
663 if (ip->udp_xsum != 0) {
664 ulong xsum;
665 ushort *sumptr;
666 ushort sumlen;
668 xsum = ip->ip_p;
669 xsum += (ntohs(ip->udp_len));
670 xsum += (ntohl(ip->ip_src) >> 16) & 0x0000ffff;
671 xsum += (ntohl(ip->ip_src) >> 0) & 0x0000ffff;
672 xsum += (ntohl(ip->ip_dst) >> 16) & 0x0000ffff;
673 xsum += (ntohl(ip->ip_dst) >> 0) & 0x0000ffff;
675 sumlen = ntohs(ip->udp_len);
676 sumptr = (ushort *) &(ip->udp_src);
678 while (sumlen > 1) {
679 ushort sumdata;
681 sumdata = *sumptr++;
682 xsum += ntohs(sumdata);
683 sumlen -= 2;
685 if (sumlen > 0) {
686 ushort sumdata;
688 sumdata = *(unsigned char *) sumptr;
689 sumdata = (sumdata << 8) & 0xff00;
690 xsum += sumdata;
692 while ((xsum >> 16) != 0) {
693 xsum = (xsum & 0x0000ffff) + ((xsum >> 16) & 0x0000ffff);
695 if ((xsum != 0x00000000) && (xsum != 0x0000ffff)) {
696 printf(" UDP wrong checksum %08x %08x\n", xsum, ntohs(ip->udp_xsum));
697 return;
700 #endif
702 * IP header OK. Pass the packet to the current handler.
704 (*packetHandler)((uchar *)ip +IP_HDR_SIZE,
705 ntohs(ip->udp_dst),
706 ntohs(ip->udp_src),
707 ntohs(ip->udp_len) - 8);
708 break;
713 /**********************************************************************/
715 static int net_check_prereq (proto_t protocol)
717 struct eth_device *edev = eth_get_current();
719 switch (protocol) {
720 /* Fall through */
721 #ifdef CONFIG_NET_NFS
722 case NFS:
723 #endif
724 case NETCONS:
725 case TFTP:
726 if (NetServerIP == 0) {
727 printf("*** ERROR: `%s.serverip' not set\n", dev_id(&edev->dev));
728 return -1;
731 if (NetOurIP == 0) {
732 printf("*** ERROR: `%s.ipaddr' not set\n", dev_id(&edev->dev));
733 return -1;
735 /* Fall through */
737 case DHCP:
738 case RARP:
739 case BOOTP:
740 if (memcmp (NetOurEther, "\0\0\0\0\0\0", 6) == 0) {
741 printf("*** ERROR: `%s.ethaddr' not set\n", dev_id(&edev->dev));
742 return -1;
744 /* Fall through */
745 default:
746 return 0;
749 return -1; /* not reached */
751 /**********************************************************************/
754 NetCksumOk(uchar * ptr, int len)
756 return !((NetCksum(ptr, len) + 1) & 0xfffe);
760 unsigned
761 NetCksum(uchar * ptr, int len)
763 ulong xsum;
764 ushort *p = (ushort *)ptr;
766 xsum = 0;
767 while (len-- > 0)
768 xsum += *p++;
769 xsum = (xsum & 0xffff) + (xsum >> 16);
770 xsum = (xsum & 0xffff) + (xsum >> 16);
771 return xsum & 0xffff;
775 NetEthHdrSize(void)
777 ushort myvlanid;
779 myvlanid = ntohs(NetOurVLAN);
780 if (myvlanid == (ushort)-1)
781 myvlanid = VLAN_NONE;
783 return ((myvlanid & VLAN_IDMASK) == VLAN_NONE) ? ETHER_HDR_SIZE : VLAN_ETHER_HDR_SIZE;
787 NetSetEther(uchar * xet, uchar * addr, uint prot)
789 Ethernet_t *et = (Ethernet_t *)xet;
790 ushort myvlanid;
792 myvlanid = ntohs(NetOurVLAN);
793 if (myvlanid == (ushort)-1)
794 myvlanid = VLAN_NONE;
796 memcpy (et->et_dest, addr, 6);
797 memcpy (et->et_src, NetOurEther, 6);
798 if ((myvlanid & VLAN_IDMASK) == VLAN_NONE) {
799 et->et_protlen = htons(prot);
800 return ETHER_HDR_SIZE;
801 } else {
802 VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)xet;
804 vet->vet_vlan_type = htons(PROT_VLAN);
805 vet->vet_tag = htons((0 << 5) | (myvlanid & VLAN_IDMASK));
806 vet->vet_type = htons(prot);
807 return VLAN_ETHER_HDR_SIZE;
811 void
812 NetSetIP(uchar * xip, IPaddr_t dest, int dport, int sport, int len)
814 IP_t *ip = (IP_t *)xip;
817 * If the data is an odd number of bytes, zero the
818 * byte after the last byte so that the checksum
819 * will work.
821 if (len & 1)
822 xip[IP_HDR_SIZE + len] = 0;
825 * Construct an IP and UDP header.
826 * (need to set no fragment bit - XXX)
828 ip->ip_hl_v = 0x45; /* IP_HDR_SIZE / 4 (not including UDP) */
829 ip->ip_tos = 0;
830 ip->ip_len = htons(IP_HDR_SIZE + len);
831 ip->ip_id = htons(NetIPID++);
832 ip->ip_off = htons(0x4000); /* No fragmentation */
833 ip->ip_ttl = 255;
834 ip->ip_p = 17; /* UDP */
835 ip->ip_sum = 0;
836 NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */
837 NetCopyIP((void*)&ip->ip_dst, &dest); /* - "" - */
838 ip->udp_src = htons(sport);
839 ip->udp_dst = htons(dport);
840 ip->udp_len = htons(8 + len);
841 ip->udp_xsum = 0;
842 ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
845 char *ip_to_string (IPaddr_t x, char *s)
847 x = ntohl (x);
848 sprintf (s, "%d.%d.%d.%d",
849 (int) ((x >> 24) & 0xff),
850 (int) ((x >> 16) & 0xff),
851 (int) ((x >> 8) & 0xff), (int) ((x >> 0) & 0xff)
853 return s;
856 int string_to_ip(const char *s, IPaddr_t *ip)
858 IPaddr_t addr = 0;
859 char *e;
860 int i;
862 if (!s)
863 return -EINVAL;
865 for (i = 0; i < 4; i++) {
866 ulong val;
868 if (!isdigit(*s))
869 return -EINVAL;
871 val = simple_strtoul(s, &e, 10);
872 addr <<= 8;
873 addr |= (val & 0xFF);
875 if (*e != '.' && i != 3)
876 return -EINVAL;
878 s = e + 1;
881 *ip = htonl(addr);
882 return 0;
885 void VLAN_to_string(ushort x, char *s)
887 x = ntohs(x);
889 if (x == (ushort)-1)
890 x = VLAN_NONE;
892 if (x == VLAN_NONE)
893 strcpy(s, "none");
894 else
895 sprintf(s, "%d", x & VLAN_IDMASK);
898 ushort string_to_VLAN(const char *s)
900 ushort id;
902 if (s == NULL)
903 return htons(VLAN_NONE);
905 if (*s < '0' || *s > '9')
906 id = VLAN_NONE;
907 else
908 id = (ushort)simple_strtoul(s, NULL, 10);
910 return htons(id);
913 void print_IPaddr (IPaddr_t x)
915 char tmp[16];
917 ip_to_string (x, tmp);
919 puts (tmp);
922 ushort getenv_VLAN(char *var)
924 return string_to_VLAN(getenv(var));
927 int string_to_ethaddr(const char *str, char *enetaddr)
929 ulong reg;
930 char *e;
932 if (!str || strlen(str) != 17)
933 return -1;
935 if (str[2] != ':' || str[5] != ':' || str[8] != ':' ||
936 str[11] != ':' || str[14] != ':')
937 return -1;
939 for (reg = 0; reg < 6; ++reg) {
940 enetaddr[reg] = simple_strtoul (str, &e, 16);
941 str = e + 1;
944 return 0;
947 void ethaddr_to_string(const unsigned char *enetaddr, char *str)
949 sprintf (str, "%02X:%02X:%02X:%02X:%02X:%02X",
950 enetaddr[0], enetaddr[1], enetaddr[2], enetaddr[3],
951 enetaddr[4], enetaddr[5]);
954 void net_update_env(void)
956 struct eth_device *edev = eth_get_current();
958 NetOurIP = dev_get_param_ip(&edev->dev, "ipaddr");
959 NetServerIP = dev_get_param_ip(&edev->dev, "serverip");
960 NetOurGatewayIP = dev_get_param_ip(&edev->dev, "gateway");
961 NetOurSubnetMask = dev_get_param_ip(&edev->dev, "netmask");
963 string_to_ethaddr(dev_get_param(&edev->dev, "ethaddr"),
964 NetOurEther);