1 /* 2 * Copied from Linux Monitor (LiMon) - Networking. 3 * 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 */ 10 11 /* 12 * General Desription: 13 * 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: 17 * 18 * BOOTP: 19 * 20 * Prerequisites: - own ethernet address 21 * We want: - own IP address 22 * - TFTP server IP address 23 * - name of bootfile 24 * Next step: ARP 25 * 26 * RARP: 27 * 28 * Prerequisites: - own ethernet address 29 * We want: - own IP address 30 * - TFTP server IP address 31 * Next step: ARP 32 * 33 * ARP: 34 * 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 40 * 41 * DHCP: 42 * 43 * Prerequisites: - own ethernet address 44 * We want: - IP, Netmask, ServerIP, Gateway IP 45 * - bootfilename, lease time 46 * Next step: - TFTP 47 * 48 * TFTP: 49 * 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 58 */ 59 60 61 #include <common.h> 62 #include <watchdog.h> 63 #include <command.h> 64 #include <net.h> 65 #include "bootp.h" 66 #include "tftp.h" 67 #include "rarp.h" 68 69 #if (CONFIG_COMMANDS & CFG_CMD_NET) 70 71 #define ARP_TIMEOUT 5 /* Seconds before trying ARP again */ 72 #ifndef CONFIG_NET_RETRY_COUNT 73 # define ARP_TIMEOUT_COUNT 5 /* # of timeouts before giving up */ 74 #else 75 # define ARP_TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT) 76 #endif 77 78 #if 0 79 #define ET_DEBUG 80 #endif 81 82 /** BOOTP EXTENTIONS **/ 83 84 IPaddr_t NetOurSubnetMask=0; /* Our subnet mask (0=unknown) */ 85 IPaddr_t NetOurGatewayIP=0; /* Our gateways IP address */ 86 IPaddr_t NetOurDNSIP=0; /* Our DNS IP address */ 87 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS2) 88 IPaddr_t NetOurDNS2IP=0; /* Our 2nd DNS IP address */ 89 #endif 90 char NetOurNISDomain[32]={0,}; /* Our NIS domain */ 91 char NetOurHostName[32]={0,}; /* Our hostname */ 92 char NetOurRootPath[64]={0,}; /* Our bootpath */ 93 ushort NetBootFileSize=0; /* Our bootfile size in blocks */ 94 95 /** END OF BOOTP EXTENTIONS **/ 96 97 ulong NetBootFileXferSize; /* The actual transferred size of the bootfile (in bytes) */ 98 uchar NetOurEther[6]; /* Our ethernet address */ 99 uchar NetServerEther[6] = /* Boot server enet address */ 100 { 0, 0, 0, 0, 0, 0 }; 101 IPaddr_t NetOurIP; /* Our IP addr (0 = unknown) */ 102 IPaddr_t NetServerIP; /* Our IP addr (0 = unknown) */ 103 volatile uchar *NetRxPkt; /* Current receive packet */ 104 int NetRxPktLen; /* Current rx packet length */ 105 unsigned NetIPID; /* IP packet ID */ 106 uchar NetBcastAddr[6] = /* Ethernet bcast address */ 107 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 108 uchar NetEtherNullAddr[6] = 109 { 0, 0, 0, 0, 0, 0 }; 110 int NetState; /* Network loop state */ 111 #ifdef CONFIG_NET_MULTI 112 int NetRestartWrap = 0; /* Tried all network devices */ 113 static int NetRestarted = 0; /* Network loop restarted */ 114 static int NetDevExists = 0; /* At least one device configured */ 115 #endif 116 117 char BootFile[128]; /* Boot File name */ 118 119 #if (CONFIG_COMMANDS & CFG_CMD_PING) 120 IPaddr_t NetPingIP; /* the ip address to ping */ 121 122 static void PingStart(void); 123 #endif 124 125 volatile uchar PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN]; 126 127 volatile uchar *NetRxPackets[PKTBUFSRX]; /* Receive packets */ 128 129 static rxhand_f *packetHandler; /* Current RX packet handler */ 130 static thand_f *timeHandler; /* Current timeout handler */ 131 static ulong timeStart; /* Time base value */ 132 static ulong timeDelta; /* Current timeout value */ 133 volatile uchar *NetTxPacket = 0; /* THE transmit packet */ 134 135 static int net_check_prereq (proto_t protocol); 136 137 /**********************************************************************/ 138 139 IPaddr_t NetArpWaitPacketIP; 140 IPaddr_t NetArpWaitReplyIP; 141 uchar *NetArpWaitPacketMAC; /* MAC address of waiting packet's destination */ 142 uchar *NetArpWaitTxPacket; /* THE transmit packet */ 143 int NetArpWaitTxPacketSize; 144 uchar NetArpWaitPacketBuf[PKTSIZE_ALIGN + PKTALIGN]; 145 ulong NetArpWaitTimerStart; 146 int NetArpWaitTry; 147 148 void ArpRequest(void) 149 { 150 int i; 151 volatile uchar *pkt; 152 ARP_t * arp; 153 154 #ifdef ET_DEBUG 155 printf("ARP broadcast %d\n", NetArpWaitTry); 156 #endif 157 pkt = NetTxPacket; 158 159 NetSetEther(pkt, NetBcastAddr, PROT_ARP); 160 pkt += ETHER_HDR_SIZE; 161 162 arp = (ARP_t *)pkt; 163 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); 169 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 */ 174 } 175 176 if((NetArpWaitPacketIP & NetOurSubnetMask) != (NetOurIP & NetOurSubnetMask)) { 177 if (NetOurGatewayIP == 0) { 178 puts ("## Warning: gatewayip needed but not set\n"); 179 } 180 NetArpWaitReplyIP = NetOurGatewayIP; 181 } else 182 NetArpWaitReplyIP = NetArpWaitPacketIP; 183 184 NetWriteIP((uchar*)&arp->ar_data[16], NetArpWaitReplyIP); 185 (void) eth_send(NetTxPacket, ETHER_HDR_SIZE + ARP_HDR_SIZE); 186 } 187 188 void ArpTimeoutCheck(void) 189 { 190 ulong t; 191 192 if (!NetArpWaitPacketIP) 193 return; 194 195 t = get_timer(0); 196 197 /* check for arp timeout */ 198 if ((t - NetArpWaitTimerStart) > ARP_TIMEOUT * CFG_HZ) { 199 NetArpWaitTry++; 200 201 if (NetArpWaitTry >= ARP_TIMEOUT_COUNT) { 202 puts ("\nARP Retry count exceeded; starting again\n"); 203 NetArpWaitTry = 0; 204 NetStartAgain(); 205 } else { 206 NetArpWaitTimerStart = t; 207 ArpRequest(); 208 } 209 } 210 } 211 212 /**********************************************************************/ 213 /* 214 * Main network processing loop. 215 */ 216 217 int 218 NetLoop(proto_t protocol) 219 { 220 DECLARE_GLOBAL_DATA_PTR; 221 222 bd_t *bd = gd->bd; 223 224 #ifdef CONFIG_NET_MULTI 225 NetRestarted = 0; 226 NetDevExists = 0; 227 #endif 228 229 /* XXX problem with bss workaround */ 230 NetArpWaitPacketMAC = NULL; 231 NetArpWaitTxPacket = NULL; 232 NetArpWaitPacketIP = 0; 233 NetArpWaitReplyIP = 0; 234 NetArpWaitTxPacket = NULL; 235 NetTxPacket = NULL; 236 237 if (!NetTxPacket) { 238 int i; 239 240 /* 241 * Setup packet buffers, aligned correctly. 242 */ 243 NetTxPacket = &PktBuf[0] + (PKTALIGN - 1); 244 NetTxPacket -= (ulong)NetTxPacket % PKTALIGN; 245 for (i = 0; i < PKTBUFSRX; i++) { 246 NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN; 247 } 248 249 } 250 251 if (!NetArpWaitTxPacket) { 252 NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1); 253 NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN; 254 NetArpWaitTxPacketSize = 0; 255 } 256 257 eth_halt(); 258 if(eth_init(bd) < 0) 259 return(-1); 260 261 restart: 262 #ifdef CONFIG_NET_MULTI 263 memcpy (NetOurEther, eth_get_dev()->enetaddr, 6); 264 #else 265 memcpy (NetOurEther, bd->bi_enetaddr, 6); 266 #endif 267 268 NetState = NETLOOP_CONTINUE; 269 270 /* 271 * Start the ball rolling with the given start function. From 272 * here on, this code is a state machine driven by received 273 * packets and timer events. 274 */ 275 276 switch (protocol) { 277 #if (CONFIG_COMMANDS & CFG_CMD_PING) 278 case PING: 279 #endif 280 case TFTP: 281 NetCopyIP(&NetOurIP, &bd->bi_ip_addr); 282 NetOurGatewayIP = getenv_IPaddr ("gatewayip"); 283 NetOurSubnetMask= getenv_IPaddr ("netmask"); 284 285 switch (protocol) { 286 case TFTP: 287 NetServerIP = getenv_IPaddr ("serverip"); 288 break; 289 #if (CONFIG_COMMANDS & CFG_CMD_PING) 290 case PING: 291 /* nothing */ 292 break; 293 #endif 294 default: 295 break; 296 } 297 298 break; 299 case BOOTP: 300 case RARP: 301 /* 302 * initialize our IP addr to 0 in order to accept ANY 303 * IP addr assigned to us by the BOOTP / RARP server 304 */ 305 NetOurIP = 0; 306 NetServerIP = 0; 307 break; 308 default: 309 break; 310 } 311 312 switch (net_check_prereq (protocol)) { 313 case 1: 314 /* network not configured */ 315 return (-1); 316 317 #ifdef CONFIG_NET_MULTI 318 case 2: 319 /* network device not configured */ 320 break; 321 #endif /* CONFIG_NET_MULTI */ 322 323 case 0: 324 #ifdef CONFIG_NET_MULTI 325 NetDevExists = 1; 326 #endif 327 switch (protocol) { 328 case TFTP: 329 /* always use ARP to get server ethernet address */ 330 TftpStart(); 331 break; 332 333 #if (CONFIG_COMMANDS & CFG_CMD_DHCP) 334 case DHCP: 335 /* Start with a clean slate... */ 336 NetOurIP = 0; 337 NetServerIP = 0; 338 DhcpRequest(); /* Basically same as BOOTP */ 339 break; 340 #endif /* CFG_CMD_DHCP */ 341 342 case BOOTP: 343 BootpTry = 0; 344 BootpRequest (); 345 break; 346 347 case RARP: 348 RarpTry = 0; 349 RarpRequest (); 350 break; 351 #if (CONFIG_COMMANDS & CFG_CMD_PING) 352 case PING: 353 PingStart(); 354 break; 355 #endif 356 default: 357 break; 358 } 359 360 NetBootFileXferSize = 0; 361 break; 362 } 363 364 365 /* 366 * Main packet reception loop. Loop receiving packets until 367 * someone sets `NetQuit'. 368 */ 369 for (;;) { 370 WATCHDOG_RESET(); 371 #ifdef CONFIG_SHOW_ACTIVITY 372 { 373 extern void show_activity(int arg); 374 show_activity(1); 375 } 376 #endif 377 /* 378 * Check the ethernet for a new packet. The ethernet 379 * receive routine will process it. 380 */ 381 eth_rx(); 382 383 /* 384 * Abort if ctrl-c was pressed. 385 */ 386 if (ctrlc()) { 387 eth_halt(); 388 printf("\nAbort\n"); 389 return (-1); 390 } 391 392 ArpTimeoutCheck(); 393 394 /* 395 * Check for a timeout, and run the timeout handler 396 * if we have one. 397 */ 398 if (timeHandler && ((get_timer(0) - timeStart) > timeDelta)) { 399 thand_f *x; 400 401 x = timeHandler; 402 timeHandler = (thand_f *)0; 403 (*x)(); 404 } 405 406 407 switch (NetState) { 408 409 case NETLOOP_RESTART: 410 #ifdef CONFIG_NET_MULTI 411 NetRestarted = 1; 412 #endif 413 goto restart; 414 415 case NETLOOP_SUCCESS: 416 if (NetBootFileXferSize > 0) { 417 char buf[10]; 418 printf("Bytes transferred = %ld (%lx hex)\n", 419 NetBootFileXferSize, 420 NetBootFileXferSize); 421 sprintf(buf, "%lx", NetBootFileXferSize); 422 setenv("filesize", buf); 423 } 424 eth_halt(); 425 return NetBootFileXferSize; 426 427 case NETLOOP_FAIL: 428 return (-1); 429 } 430 } 431 } 432 433 /**********************************************************************/ 434 435 static void 436 startAgainTimeout(void) 437 { 438 NetState = NETLOOP_RESTART; 439 } 440 441 static void 442 startAgainHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len) 443 { 444 /* Totally ignore the packet */ 445 } 446 447 void 448 NetStartAgain(void) 449 { 450 #ifndef CONFIG_NET_MULTI 451 NetSetTimeout(10 * CFG_HZ, startAgainTimeout); 452 NetSetHandler(startAgainHandler); 453 #else 454 DECLARE_GLOBAL_DATA_PTR; 455 456 eth_halt(); 457 eth_try_another(!NetRestarted); 458 eth_init(gd->bd); 459 if (NetRestartWrap) 460 { 461 NetRestartWrap = 0; 462 if (NetDevExists) 463 { 464 NetSetTimeout(10 * CFG_HZ, startAgainTimeout); 465 NetSetHandler(startAgainHandler); 466 } 467 else 468 { 469 NetState = NETLOOP_FAIL; 470 } 471 } 472 else 473 { 474 NetState = NETLOOP_RESTART; 475 } 476 #endif 477 } 478 479 /**********************************************************************/ 480 /* 481 * Miscelaneous bits. 482 */ 483 484 void 485 NetSetHandler(rxhand_f * f) 486 { 487 packetHandler = f; 488 } 489 490 491 void 492 NetSetTimeout(int iv, thand_f * f) 493 { 494 if (iv == 0) { 495 timeHandler = (thand_f *)0; 496 } else { 497 timeHandler = f; 498 timeStart = get_timer(0); 499 timeDelta = iv; 500 } 501 } 502 503 504 void 505 NetSendPacket(volatile uchar * pkt, int len) 506 { 507 (void) eth_send(pkt, len); 508 } 509 510 int 511 NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, int len) 512 { 513 /* convert to new style broadcast */ 514 if (dest == 0) 515 dest = 0xFFFFFFFF; 516 517 /* if broadcast, make the ether address a broadcast and don't do ARP */ 518 if (dest == 0xFFFFFFFF) 519 ether = NetBcastAddr; 520 521 /* if MAC address was not discovered yet, save the packet and do an ARP request */ 522 if (memcmp(ether, NetEtherNullAddr, 6) == 0) { 523 524 #ifdef ET_DEBUG 525 printf("sending ARP for %08lx\n", dest); 526 #endif 527 528 NetArpWaitPacketIP = dest; 529 NetArpWaitPacketMAC = ether; 530 NetSetEther (NetArpWaitTxPacket, NetArpWaitPacketMAC, PROT_IP); 531 NetSetIP (NetArpWaitTxPacket + ETHER_HDR_SIZE, dest, dport, sport, len); 532 memcpy(NetArpWaitTxPacket + ETHER_HDR_SIZE + IP_HDR_SIZE, 533 (uchar *)NetTxPacket + ETHER_HDR_SIZE + IP_HDR_SIZE, len); 534 535 /* size of the waiting packet */ 536 NetArpWaitTxPacketSize = ETHER_HDR_SIZE + IP_HDR_SIZE + len; 537 538 /* and do the ARP request */ 539 NetArpWaitTry = 1; 540 NetArpWaitTimerStart = get_timer(0); 541 ArpRequest(); 542 return 1; /* waiting */ 543 } 544 545 #ifdef ET_DEBUG 546 printf("sending UDP to %08lx/%02x:%02x:%02x:%02x:%02x:%02x\n", 547 dest, ether[0], ether[1], ether[2], ether[3], ether[4], ether[5]); 548 #endif 549 550 NetSetEther (NetTxPacket, ether, PROT_IP); 551 NetSetIP (NetTxPacket + ETHER_HDR_SIZE, dest, dport, sport, len); 552 (void) eth_send(NetTxPacket, ETHER_HDR_SIZE + IP_HDR_SIZE + len); 553 554 return 0; /* transmited */ 555 } 556 557 #if (CONFIG_COMMANDS & CFG_CMD_PING) 558 static ushort PingSeqNo; 559 560 int PingSend(void) 561 { 562 static uchar mac[6]; 563 volatile IP_t *ip; 564 volatile ushort *s; 565 566 /* XXX always send arp request */ 567 568 memcpy(mac, NetEtherNullAddr, 6); 569 570 #ifdef ET_DEBUG 571 printf("sending ARP for %08lx\n", NetPingIP); 572 #endif 573 574 NetArpWaitPacketIP = NetPingIP; 575 NetArpWaitPacketMAC = mac; 576 577 NetSetEther(NetArpWaitTxPacket, mac, PROT_IP); 578 579 ip = (volatile IP_t *)(NetArpWaitTxPacket + ETHER_HDR_SIZE); 580 581 /* 582 * Construct an IP and ICMP header. (need to set no fragment bit - XXX) 583 */ 584 ip->ip_hl_v = 0x45; /* IP_HDR_SIZE / 4 (not including UDP) */ 585 ip->ip_tos = 0; 586 ip->ip_len = htons(IP_HDR_SIZE_NO_UDP + 8); 587 ip->ip_id = htons(NetIPID++); 588 ip->ip_off = htons(0x4000); /* No fragmentation */ 589 ip->ip_ttl = 255; 590 ip->ip_p = 0x01; /* ICMP */ 591 ip->ip_sum = 0; 592 NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */ 593 NetCopyIP((void*)&ip->ip_dst, &NetPingIP); /* - "" - */ 594 ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2); 595 596 s = &ip->udp_src; /* XXX ICMP starts here */ 597 s[0] = htons(0x0800); /* echo-request, code */ 598 s[1] = 0; /* checksum */ 599 s[2] = 0; /* identifier */ 600 s[3] = htons(PingSeqNo++); /* sequence number */ 601 s[1] = ~NetCksum((uchar *)s, 8/2); 602 603 /* size of the waiting packet */ 604 NetArpWaitTxPacketSize = ETHER_HDR_SIZE + IP_HDR_SIZE_NO_UDP + 8; 605 606 /* and do the ARP request */ 607 NetArpWaitTry = 1; 608 NetArpWaitTimerStart = get_timer(0); 609 ArpRequest(); 610 return 1; /* waiting */ 611 } 612 613 static void 614 PingTimeout (void) 615 { 616 eth_halt(); 617 NetState = NETLOOP_FAIL; /* we did not get the reply */ 618 } 619 620 static void 621 PingHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len) 622 { 623 IPaddr_t tmp; 624 volatile IP_t *ip = (volatile IP_t *)pkt; 625 626 tmp = NetReadIP((void *)&ip->ip_src); 627 if (tmp != NetPingIP) 628 return; 629 630 NetState = NETLOOP_SUCCESS; 631 } 632 633 static void PingStart(void) 634 { 635 NetSetTimeout (10 * CFG_HZ, PingTimeout); 636 NetSetHandler (PingHandler); 637 638 PingSend(); 639 } 640 641 #endif 642 643 void 644 NetReceive(volatile uchar * pkt, int len) 645 { 646 Ethernet_t *et; 647 IP_t *ip; 648 ARP_t *arp; 649 IPaddr_t tmp; 650 int x; 651 652 NetRxPkt = pkt; 653 NetRxPktLen = len; 654 et = (Ethernet_t *)pkt; 655 656 x = ntohs(et->et_protlen); 657 658 if (x < 1514) { 659 /* 660 * Got a 802 packet. Check the other protocol field. 661 */ 662 x = ntohs(et->et_prot); 663 ip = (IP_t *)(pkt + E802_HDR_SIZE); 664 len -= E802_HDR_SIZE; 665 } else { 666 ip = (IP_t *)(pkt + ETHER_HDR_SIZE); 667 len -= ETHER_HDR_SIZE; 668 } 669 670 #ifdef ET_DEBUG 671 printf("Receive from protocol 0x%x\n", x); 672 #endif 673 674 switch (x) { 675 676 case PROT_ARP: 677 /* 678 * We have to deal with two types of ARP packets: 679 * - REQUEST packets will be answered by sending our 680 * IP address - if we know it. 681 * - REPLY packates are expected only after we asked 682 * for the TFTP server's or the gateway's ethernet 683 * address; so if we receive such a packet, we set 684 * the server ethernet address 685 */ 686 #ifdef ET_DEBUG 687 printf("Got ARP\n"); 688 #endif 689 arp = (ARP_t *)ip; 690 if (len < ARP_HDR_SIZE) { 691 printf("bad length %d < %d\n", len, ARP_HDR_SIZE); 692 return; 693 } 694 if (ntohs(arp->ar_hrd) != ARP_ETHER) { 695 return; 696 } 697 if (ntohs(arp->ar_pro) != PROT_IP) { 698 return; 699 } 700 if (arp->ar_hln != 6) { 701 return; 702 } 703 if (arp->ar_pln != 4) { 704 return; 705 } 706 707 if (NetOurIP == 0) { 708 return; 709 } 710 711 if (NetReadIP(&arp->ar_data[16]) != NetOurIP) { 712 return; 713 } 714 715 switch (ntohs(arp->ar_op)) { 716 case ARPOP_REQUEST: /* reply with our IP address */ 717 #ifdef ET_DEBUG 718 printf("Got ARP REQUEST, return our IP\n"); 719 #endif 720 NetSetEther((uchar *)et, et->et_src, PROT_ARP); 721 arp->ar_op = htons(ARPOP_REPLY); 722 memcpy (&arp->ar_data[10], &arp->ar_data[0], 6); 723 NetCopyIP(&arp->ar_data[16], &arp->ar_data[6]); 724 memcpy (&arp->ar_data[ 0], NetOurEther, 6); 725 NetCopyIP(&arp->ar_data[ 6], &NetOurIP); 726 (void) eth_send((uchar *)et, ((uchar *)arp-pkt) + ARP_HDR_SIZE); 727 return; 728 729 case ARPOP_REPLY: /* arp reply */ 730 /* are we waiting for a reply */ 731 if (!NetArpWaitPacketIP || !NetArpWaitPacketMAC) 732 break; 733 #ifdef ET_DEBUG 734 printf("Got ARP REPLY, set server/gtwy eth addr (%02x:%02x:%02x:%02x:%02x:%02x)\n", 735 arp->ar_data[0], arp->ar_data[1], 736 arp->ar_data[2], arp->ar_data[3], 737 arp->ar_data[4], arp->ar_data[5]); 738 #endif 739 740 tmp = NetReadIP(&arp->ar_data[6]); 741 742 /* matched waiting packet's address */ 743 if (tmp == NetArpWaitReplyIP) { 744 #ifdef ET_DEBUG 745 printf("Got it\n"); 746 #endif 747 /* save address for later use */ 748 memcpy(NetArpWaitPacketMAC, &arp->ar_data[0], 6); 749 750 /* modify header, and transmit it */ 751 memcpy(((Ethernet_t *)NetArpWaitTxPacket)->et_dest, NetArpWaitPacketMAC, 6); 752 (void) eth_send(NetArpWaitTxPacket, NetArpWaitTxPacketSize); 753 754 /* no arp request pending now */ 755 NetArpWaitPacketIP = 0; 756 NetArpWaitTxPacketSize = 0; 757 NetArpWaitPacketMAC = NULL; 758 759 } 760 return; 761 default: 762 #ifdef ET_DEBUG 763 printf("Unexpected ARP opcode 0x%x\n", ntohs(arp->ar_op)); 764 #endif 765 return; 766 } 767 768 case PROT_RARP: 769 #ifdef ET_DEBUG 770 printf("Got RARP\n"); 771 #endif 772 arp = (ARP_t *)ip; 773 if (len < ARP_HDR_SIZE) { 774 printf("bad length %d < %d\n", len, ARP_HDR_SIZE); 775 return; 776 } 777 778 if ((ntohs(arp->ar_op) != RARPOP_REPLY) || 779 (ntohs(arp->ar_hrd) != ARP_ETHER) || 780 (ntohs(arp->ar_pro) != PROT_IP) || 781 (arp->ar_hln != 6) || (arp->ar_pln != 4)) { 782 783 printf("invalid RARP header\n"); 784 } else { 785 NetCopyIP(&NetOurIP, &arp->ar_data[16]); 786 NetCopyIP(&NetServerIP, &arp->ar_data[ 6]); 787 memcpy (NetServerEther, &arp->ar_data[ 0], 6); 788 789 (*packetHandler)(0,0,0,0); 790 } 791 break; 792 793 case PROT_IP: 794 #ifdef ET_DEBUG 795 printf("Got IP\n"); 796 #endif 797 if (len < IP_HDR_SIZE) { 798 debug ("len bad %d < %d\n", len, IP_HDR_SIZE); 799 return; 800 } 801 if (len < ntohs(ip->ip_len)) { 802 printf("len bad %d < %d\n", len, ntohs(ip->ip_len)); 803 return; 804 } 805 len = ntohs(ip->ip_len); 806 #ifdef ET_DEBUG 807 printf("len=%d, v=%02x\n", len, ip->ip_hl_v & 0xff); 808 #endif 809 if ((ip->ip_hl_v & 0xf0) != 0x40) { 810 return; 811 } 812 if (ip->ip_off & htons(0x1fff)) { /* Can't deal w/ fragments */ 813 return; 814 } 815 if (!NetCksumOk((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2)) { 816 printf("checksum bad\n"); 817 return; 818 } 819 tmp = NetReadIP(&ip->ip_dst); 820 if (NetOurIP && tmp != NetOurIP && tmp != 0xFFFFFFFF) { 821 return; 822 } 823 /* 824 * watch for ICMP host redirects 825 * 826 * There is no real handler code (yet). We just watch 827 * for ICMP host redirect messages. In case anybody 828 * sees these messages: please contact me 829 * (wd@denx.de), or - even better - send me the 830 * necessary fixes :-) 831 * 832 * Note: in all cases where I have seen this so far 833 * it was a problem with the router configuration, 834 * for instance when a router was configured in the 835 * BOOTP reply, but the TFTP server was on the same 836 * subnet. So this is probably a warning that your 837 * configuration might be wrong. But I'm not really 838 * sure if there aren't any other situations. 839 */ 840 if (ip->ip_p == IPPROTO_ICMP) { 841 ICMP_t *icmph = (ICMP_t *)&(ip->udp_src); 842 843 switch (icmph->type) { 844 case ICMP_REDIRECT: 845 if (icmph->code != ICMP_REDIR_HOST) 846 return; 847 puts (" ICMP Host Redirect to "); 848 print_IPaddr(icmph->un.gateway); 849 putc(' '); 850 break; 851 #if (CONFIG_COMMANDS & CFG_CMD_PING) 852 case ICMP_ECHO_REPLY: 853 /* 854 * IP header OK. Pass the packet to the current handler. 855 */ 856 /* XXX point to ip packet */ 857 (*packetHandler)((uchar *)ip, 0, 0, 0); 858 break; 859 #endif 860 default: 861 return; 862 } 863 } else if (ip->ip_p != IPPROTO_UDP) { /* Only UDP packets */ 864 return; 865 } 866 867 /* 868 * IP header OK. Pass the packet to the current handler. 869 */ 870 (*packetHandler)((uchar *)ip +IP_HDR_SIZE, 871 ntohs(ip->udp_dst), 872 ntohs(ip->udp_src), 873 ntohs(ip->udp_len) - 8); 874 875 break; 876 } 877 } 878 879 880 /**********************************************************************/ 881 882 static int net_check_prereq (proto_t protocol) 883 { 884 switch (protocol) { 885 /* Fall through */ 886 #if (CONFIG_COMMANDS & CFG_CMD_PING) 887 case PING: 888 if (NetPingIP == 0) { 889 puts ("*** ERROR: ping address not given\n"); 890 return (1); 891 } 892 goto common; 893 #endif 894 case TFTP: 895 if (NetServerIP == 0) { 896 puts ("*** ERROR: `serverip' not set\n"); 897 return (1); 898 } 899 900 #if (CONFIG_COMMANDS & CFG_CMD_PING) 901 common: 902 #endif 903 904 if (NetOurIP == 0) { 905 puts ("*** ERROR: `ipaddr' not set\n"); 906 return (1); 907 } 908 /* Fall through */ 909 910 case DHCP: 911 case RARP: 912 case BOOTP: 913 if (memcmp(NetOurEther, "\0\0\0\0\0\0", 6) == 0) { 914 #ifdef CONFIG_NET_MULTI 915 extern int eth_get_dev_index (void); 916 int num = eth_get_dev_index(); 917 918 switch (num) { 919 case -1: 920 puts ("*** ERROR: No ethernet found.\n"); 921 return (1); 922 case 0: 923 puts ("*** ERROR: `ethaddr' not set\n"); 924 break; 925 default: 926 printf ("*** ERROR: `eth%daddr' not set\n", 927 num); 928 break; 929 } 930 931 NetStartAgain (); 932 return (2); 933 #else 934 puts ("*** ERROR: `ethaddr' not set\n"); 935 return (1); 936 #endif 937 } 938 /* Fall through */ 939 default: 940 return(0); 941 } 942 return (0); /* OK */ 943 } 944 /**********************************************************************/ 945 946 int 947 NetCksumOk(uchar * ptr, int len) 948 { 949 return !((NetCksum(ptr, len) + 1) & 0xfffe); 950 } 951 952 953 unsigned 954 NetCksum(uchar * ptr, int len) 955 { 956 ulong xsum; 957 958 xsum = 0; 959 while (len-- > 0) 960 xsum += *((ushort *)ptr)++; 961 xsum = (xsum & 0xffff) + (xsum >> 16); 962 xsum = (xsum & 0xffff) + (xsum >> 16); 963 return (xsum & 0xffff); 964 } 965 966 967 void 968 NetSetEther(volatile uchar * xet, uchar * addr, uint prot) 969 { 970 Ethernet_t *et = (Ethernet_t *)xet; 971 972 memcpy (et->et_dest, addr, 6); 973 memcpy (et->et_src, NetOurEther, 6); 974 et->et_protlen = htons(prot); 975 } 976 977 978 void 979 NetSetIP(volatile uchar * xip, IPaddr_t dest, int dport, int sport, int len) 980 { 981 volatile IP_t *ip = (IP_t *)xip; 982 983 /* 984 * If the data is an odd number of bytes, zero the 985 * byte after the last byte so that the checksum 986 * will work. 987 */ 988 if (len & 1) 989 xip[IP_HDR_SIZE + len] = 0; 990 991 /* 992 * Construct an IP and UDP header. 993 (need to set no fragment bit - XXX) 994 */ 995 ip->ip_hl_v = 0x45; /* IP_HDR_SIZE / 4 (not including UDP) */ 996 ip->ip_tos = 0; 997 ip->ip_len = htons(IP_HDR_SIZE + len); 998 ip->ip_id = htons(NetIPID++); 999 ip->ip_off = htons(0x4000); /* No fragmentation */ 1000 ip->ip_ttl = 255; 1001 ip->ip_p = 17; /* UDP */ 1002 ip->ip_sum = 0; 1003 NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */ 1004 NetCopyIP((void*)&ip->ip_dst, &dest); /* - "" - */ 1005 ip->udp_src = htons(sport); 1006 ip->udp_dst = htons(dport); 1007 ip->udp_len = htons(8 + len); 1008 ip->udp_xsum = 0; 1009 ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2); 1010 } 1011 1012 void copy_filename (uchar *dst, uchar *src, int size) 1013 { 1014 if (*src && (*src == '"')) { 1015 ++src; 1016 --size; 1017 } 1018 1019 while ((--size > 0) && *src && (*src != '"')) { 1020 *dst++ = *src++; 1021 } 1022 *dst = '\0'; 1023 } 1024 1025 #endif /* CFG_CMD_NET */ 1026 1027 void ip_to_string (IPaddr_t x, char *s) 1028 { 1029 x = ntohl(x); 1030 sprintf (s,"%d.%d.%d.%d", 1031 (int)((x >> 24) & 0xff), 1032 (int)((x >> 16) & 0xff), 1033 (int)((x >> 8) & 0xff), 1034 (int)((x >> 0) & 0xff) 1035 ); 1036 } 1037 1038 IPaddr_t string_to_ip(char *s) 1039 { 1040 IPaddr_t addr; 1041 char *e; 1042 int i; 1043 1044 if (s == NULL) 1045 return(0); 1046 1047 for (addr=0, i=0; i<4; ++i) { 1048 ulong val = s ? simple_strtoul(s, &e, 10) : 0; 1049 addr <<= 8; 1050 addr |= (val & 0xFF); 1051 if (s) { 1052 s = (*e) ? e+1 : e; 1053 } 1054 } 1055 1056 return (htonl(addr)); 1057 } 1058 1059 void print_IPaddr (IPaddr_t x) 1060 { 1061 char tmp[16]; 1062 1063 ip_to_string(x, tmp); 1064 1065 puts(tmp); 1066 } 1067 1068 IPaddr_t getenv_IPaddr (char *var) 1069 { 1070 return (string_to_ip(getenv(var))); 1071 } 1072