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 * NFS: 60 * 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 67 * 68 * SNTP: 69 * 70 * Prerequisites: - own ethernet address 71 * - own IP address 72 * We want: - network time 73 * Next step: none 74 */ 75 76 77 #include <common.h> 78 #include <watchdog.h> 79 #include <command.h> 80 #include <net.h> 81 #include "bootp.h" 82 #include "tftp.h" 83 #ifdef CONFIG_CMD_RARP 84 #include "rarp.h" 85 #endif 86 #include "nfs.h" 87 #ifdef CONFIG_STATUS_LED 88 #include <status_led.h> 89 #include <miiphy.h> 90 #endif 91 #if defined(CONFIG_CMD_SNTP) 92 #include "sntp.h" 93 #endif 94 #if defined(CONFIG_CDP_VERSION) 95 #include <timestamp.h> 96 #endif 97 #if defined(CONFIG_CMD_DNS) 98 #include "dns.h" 99 #endif 100 101 DECLARE_GLOBAL_DATA_PTR; 102 103 #ifndef CONFIG_ARP_TIMEOUT 104 /* Milliseconds before trying ARP again */ 105 # define ARP_TIMEOUT 5000UL 106 #else 107 # define ARP_TIMEOUT CONFIG_ARP_TIMEOUT 108 #endif 109 110 111 #ifndef CONFIG_NET_RETRY_COUNT 112 # define ARP_TIMEOUT_COUNT 5 /* # of timeouts before giving up */ 113 #else 114 # define ARP_TIMEOUT_COUNT CONFIG_NET_RETRY_COUNT 115 #endif 116 117 /** BOOTP EXTENTIONS **/ 118 119 /* Our subnet mask (0=unknown) */ 120 IPaddr_t NetOurSubnetMask; 121 /* Our gateways IP address */ 122 IPaddr_t NetOurGatewayIP; 123 /* Our DNS IP address */ 124 IPaddr_t NetOurDNSIP; 125 #if defined(CONFIG_BOOTP_DNS2) 126 /* Our 2nd DNS IP address */ 127 IPaddr_t NetOurDNS2IP; 128 #endif 129 /* Our NIS domain */ 130 char NetOurNISDomain[32] = {0,}; 131 /* Our hostname */ 132 char NetOurHostName[32] = {0,}; 133 /* Our bootpath */ 134 char NetOurRootPath[64] = {0,}; 135 /* Our bootfile size in blocks */ 136 ushort NetBootFileSize; 137 138 #ifdef CONFIG_MCAST_TFTP /* Multicast TFTP */ 139 IPaddr_t Mcast_addr; 140 #endif 141 142 /** END OF BOOTP EXTENTIONS **/ 143 144 /* The actual transferred size of the bootfile (in bytes) */ 145 ulong NetBootFileXferSize; 146 /* Our ethernet address */ 147 uchar NetOurEther[6]; 148 /* Boot server enet address */ 149 uchar NetServerEther[6]; 150 /* Our IP addr (0 = unknown) */ 151 IPaddr_t NetOurIP; 152 /* Server IP addr (0 = unknown) */ 153 IPaddr_t NetServerIP; 154 /* Current receive packet */ 155 volatile uchar *NetRxPacket; 156 /* Current rx packet length */ 157 int NetRxPacketLen; 158 /* IP packet ID */ 159 unsigned NetIPID; 160 /* Ethernet bcast address */ 161 uchar NetBcastAddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 162 uchar NetEtherNullAddr[6]; 163 #ifdef CONFIG_API 164 void (*push_packet)(volatile void *, int len) = 0; 165 #endif 166 #if defined(CONFIG_CMD_CDP) 167 /* Ethernet bcast address */ 168 uchar NetCDPAddr[6] = { 0x01, 0x00, 0x0c, 0xcc, 0xcc, 0xcc }; 169 #endif 170 /* Network loop state */ 171 int NetState; 172 /* Tried all network devices */ 173 int NetRestartWrap; 174 /* Network loop restarted */ 175 static int NetRestarted; 176 /* At least one device configured */ 177 static int NetDevExists; 178 179 /* XXX in both little & big endian machines 0xFFFF == ntohs(-1) */ 180 /* default is without VLAN */ 181 ushort NetOurVLAN = 0xFFFF; 182 /* ditto */ 183 ushort NetOurNativeVLAN = 0xFFFF; 184 185 /* Boot File name */ 186 char BootFile[128]; 187 188 #if defined(CONFIG_CMD_PING) 189 /* the ip address to ping */ 190 IPaddr_t NetPingIP; 191 192 static void PingStart(void); 193 #endif 194 195 #if defined(CONFIG_CMD_CDP) 196 static void CDPStart(void); 197 #endif 198 199 #if defined(CONFIG_CMD_SNTP) 200 /* NTP server IP address */ 201 IPaddr_t NetNtpServerIP; 202 /* offset time from UTC */ 203 int NetTimeOffset; 204 #endif 205 206 #ifdef CONFIG_NETCONSOLE 207 void NcStart(void); 208 int nc_input_packet(uchar *pkt, unsigned dest, unsigned src, unsigned len); 209 #endif 210 211 volatile uchar PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN]; 212 213 /* Receive packet */ 214 volatile uchar *NetRxPackets[PKTBUFSRX]; 215 216 /* Current RX packet handler */ 217 static rxhand_f *packetHandler; 218 static rxhand_icmp_f *packet_icmp_handler; /* Current ICMP rx handler */ 219 /* Current timeout handler */ 220 static thand_f *timeHandler; 221 /* Time base value */ 222 static ulong timeStart; 223 /* Current timeout value */ 224 static ulong timeDelta; 225 /* THE transmit packet */ 226 volatile uchar *NetTxPacket; 227 228 static int net_check_prereq(enum proto_t protocol); 229 230 static int NetTryCount; 231 232 /**********************************************************************/ 233 234 IPaddr_t NetArpWaitPacketIP; 235 IPaddr_t NetArpWaitReplyIP; 236 /* MAC address of waiting packet's destination */ 237 uchar *NetArpWaitPacketMAC; 238 /* THE transmit packet */ 239 uchar *NetArpWaitTxPacket; 240 int NetArpWaitTxPacketSize; 241 uchar NetArpWaitPacketBuf[PKTSIZE_ALIGN + PKTALIGN]; 242 ulong NetArpWaitTimerStart; 243 int NetArpWaitTry; 244 245 void ArpRequest(void) 246 { 247 int i; 248 volatile uchar *pkt; 249 ARP_t *arp; 250 251 debug("ARP broadcast %d\n", NetArpWaitTry); 252 253 pkt = NetTxPacket; 254 255 pkt += NetSetEther(pkt, NetBcastAddr, PROT_ARP); 256 257 arp = (ARP_t *) pkt; 258 259 arp->ar_hrd = htons(ARP_ETHER); 260 arp->ar_pro = htons(PROT_IP); 261 arp->ar_hln = 6; 262 arp->ar_pln = 4; 263 arp->ar_op = htons(ARPOP_REQUEST); 264 265 /* source ET addr */ 266 memcpy(&arp->ar_data[0], NetOurEther, 6); 267 /* source IP addr */ 268 NetWriteIP((uchar *) &arp->ar_data[6], NetOurIP); 269 for (i = 10; i < 16; ++i) { 270 /* dest ET addr = 0 */ 271 arp->ar_data[i] = 0; 272 } 273 274 if ((NetArpWaitPacketIP & NetOurSubnetMask) != 275 (NetOurIP & NetOurSubnetMask)) { 276 if (NetOurGatewayIP == 0) { 277 puts("## Warning: gatewayip needed but not set\n"); 278 NetArpWaitReplyIP = NetArpWaitPacketIP; 279 } else { 280 NetArpWaitReplyIP = NetOurGatewayIP; 281 } 282 } else { 283 NetArpWaitReplyIP = NetArpWaitPacketIP; 284 } 285 286 NetWriteIP((uchar *) &arp->ar_data[16], NetArpWaitReplyIP); 287 (void) eth_send(NetTxPacket, (pkt - NetTxPacket) + ARP_HDR_SIZE); 288 } 289 290 void ArpTimeoutCheck(void) 291 { 292 ulong t; 293 294 if (!NetArpWaitPacketIP) 295 return; 296 297 t = get_timer(0); 298 299 /* check for arp timeout */ 300 if ((t - NetArpWaitTimerStart) > ARP_TIMEOUT) { 301 NetArpWaitTry++; 302 303 if (NetArpWaitTry >= ARP_TIMEOUT_COUNT) { 304 puts("\nARP Retry count exceeded; starting again\n"); 305 NetArpWaitTry = 0; 306 NetStartAgain(); 307 } else { 308 NetArpWaitTimerStart = t; 309 ArpRequest(); 310 } 311 } 312 } 313 314 static void NetInitLoop(enum proto_t protocol) 315 { 316 static int env_changed_id; 317 bd_t *bd = gd->bd; 318 int env_id = get_env_id(); 319 320 /* update only when the environment has changed */ 321 if (env_changed_id != env_id) { 322 NetOurIP = getenv_IPaddr("ipaddr"); 323 NetCopyIP(&bd->bi_ip_addr, &NetOurIP); 324 NetOurGatewayIP = getenv_IPaddr("gatewayip"); 325 NetOurSubnetMask = getenv_IPaddr("netmask"); 326 NetServerIP = getenv_IPaddr("serverip"); 327 NetOurNativeVLAN = getenv_VLAN("nvlan"); 328 NetOurVLAN = getenv_VLAN("vlan"); 329 #if defined(CONFIG_CMD_DNS) 330 NetOurDNSIP = getenv_IPaddr("dnsip"); 331 #endif 332 env_changed_id = env_id; 333 } 334 335 return; 336 } 337 338 /**********************************************************************/ 339 /* 340 * Main network processing loop. 341 */ 342 343 int NetLoop(enum proto_t protocol) 344 { 345 bd_t *bd = gd->bd; 346 int ret = -1; 347 348 NetRestarted = 0; 349 NetDevExists = 0; 350 351 /* XXX problem with bss workaround */ 352 NetArpWaitPacketMAC = NULL; 353 NetArpWaitTxPacket = NULL; 354 NetArpWaitPacketIP = 0; 355 NetArpWaitReplyIP = 0; 356 NetArpWaitTxPacket = NULL; 357 NetTxPacket = NULL; 358 NetTryCount = 1; 359 360 if (!NetTxPacket) { 361 int i; 362 /* 363 * Setup packet buffers, aligned correctly. 364 */ 365 NetTxPacket = &PktBuf[0] + (PKTALIGN - 1); 366 NetTxPacket -= (ulong)NetTxPacket % PKTALIGN; 367 for (i = 0; i < PKTBUFSRX; i++) 368 NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN; 369 } 370 371 if (!NetArpWaitTxPacket) { 372 NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1); 373 NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN; 374 NetArpWaitTxPacketSize = 0; 375 } 376 377 eth_halt(); 378 eth_set_current(); 379 if (eth_init(bd) < 0) { 380 eth_halt(); 381 return -1; 382 } 383 384 restart: 385 memcpy(NetOurEther, eth_get_dev()->enetaddr, 6); 386 387 NetState = NETLOOP_CONTINUE; 388 389 /* 390 * Start the ball rolling with the given start function. From 391 * here on, this code is a state machine driven by received 392 * packets and timer events. 393 */ 394 NetInitLoop(protocol); 395 396 switch (net_check_prereq(protocol)) { 397 case 1: 398 /* network not configured */ 399 eth_halt(); 400 return -1; 401 402 case 2: 403 /* network device not configured */ 404 break; 405 406 case 0: 407 NetDevExists = 1; 408 NetBootFileXferSize = 0; 409 switch (protocol) { 410 case TFTPGET: 411 #ifdef CONFIG_CMD_TFTPPUT 412 case TFTPPUT: 413 #endif 414 /* always use ARP to get server ethernet address */ 415 TftpStart(protocol); 416 break; 417 #ifdef CONFIG_CMD_TFTPSRV 418 case TFTPSRV: 419 TftpStartServer(); 420 break; 421 #endif 422 #if defined(CONFIG_CMD_DHCP) 423 case DHCP: 424 BootpTry = 0; 425 NetOurIP = 0; 426 DhcpRequest(); /* Basically same as BOOTP */ 427 break; 428 #endif 429 430 case BOOTP: 431 BootpTry = 0; 432 NetOurIP = 0; 433 BootpRequest(); 434 break; 435 436 #if defined(CONFIG_CMD_RARP) 437 case RARP: 438 RarpTry = 0; 439 NetOurIP = 0; 440 RarpRequest(); 441 break; 442 #endif 443 #if defined(CONFIG_CMD_PING) 444 case PING: 445 PingStart(); 446 break; 447 #endif 448 #if defined(CONFIG_CMD_NFS) 449 case NFS: 450 NfsStart(); 451 break; 452 #endif 453 #if defined(CONFIG_CMD_CDP) 454 case CDP: 455 CDPStart(); 456 break; 457 #endif 458 #ifdef CONFIG_NETCONSOLE 459 case NETCONS: 460 NcStart(); 461 break; 462 #endif 463 #if defined(CONFIG_CMD_SNTP) 464 case SNTP: 465 SntpStart(); 466 break; 467 #endif 468 #if defined(CONFIG_CMD_DNS) 469 case DNS: 470 DnsStart(); 471 break; 472 #endif 473 default: 474 break; 475 } 476 477 break; 478 } 479 480 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) 481 #if defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN) && \ 482 defined(CONFIG_STATUS_LED) && \ 483 defined(STATUS_LED_RED) 484 /* 485 * Echo the inverted link state to the fault LED. 486 */ 487 if (miiphy_link(eth_get_dev()->name, CONFIG_SYS_FAULT_MII_ADDR)) 488 status_led_set(STATUS_LED_RED, STATUS_LED_OFF); 489 else 490 status_led_set(STATUS_LED_RED, STATUS_LED_ON); 491 #endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */ 492 #endif /* CONFIG_MII, ... */ 493 494 /* 495 * Main packet reception loop. Loop receiving packets until 496 * someone sets `NetState' to a state that terminates. 497 */ 498 for (;;) { 499 WATCHDOG_RESET(); 500 #ifdef CONFIG_SHOW_ACTIVITY 501 { 502 extern void show_activity(int arg); 503 show_activity(1); 504 } 505 #endif 506 /* 507 * Check the ethernet for a new packet. The ethernet 508 * receive routine will process it. 509 */ 510 eth_rx(); 511 512 /* 513 * Abort if ctrl-c was pressed. 514 */ 515 if (ctrlc()) { 516 eth_halt(); 517 puts("\nAbort\n"); 518 goto done; 519 } 520 521 ArpTimeoutCheck(); 522 523 /* 524 * Check for a timeout, and run the timeout handler 525 * if we have one. 526 */ 527 if (timeHandler && ((get_timer(0) - timeStart) > timeDelta)) { 528 thand_f *x; 529 530 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) 531 #if defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN) && \ 532 defined(CONFIG_STATUS_LED) && \ 533 defined(STATUS_LED_RED) 534 /* 535 * Echo the inverted link state to the fault LED. 536 */ 537 if (miiphy_link(eth_get_dev()->name, 538 CONFIG_SYS_FAULT_MII_ADDR)) { 539 status_led_set(STATUS_LED_RED, STATUS_LED_OFF); 540 } else { 541 status_led_set(STATUS_LED_RED, STATUS_LED_ON); 542 } 543 #endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */ 544 #endif /* CONFIG_MII, ... */ 545 x = timeHandler; 546 timeHandler = (thand_f *)0; 547 (*x)(); 548 } 549 550 551 switch (NetState) { 552 553 case NETLOOP_RESTART: 554 NetRestarted = 1; 555 goto restart; 556 557 case NETLOOP_SUCCESS: 558 if (NetBootFileXferSize > 0) { 559 char buf[20]; 560 printf("Bytes transferred = %ld (%lx hex)\n", 561 NetBootFileXferSize, 562 NetBootFileXferSize); 563 sprintf(buf, "%lX", NetBootFileXferSize); 564 setenv("filesize", buf); 565 566 sprintf(buf, "%lX", (unsigned long)load_addr); 567 setenv("fileaddr", buf); 568 } 569 eth_halt(); 570 ret = NetBootFileXferSize; 571 goto done; 572 573 case NETLOOP_FAIL: 574 goto done; 575 } 576 } 577 578 done: 579 /* Clear out the handlers */ 580 NetSetHandler(NULL); 581 net_set_icmp_handler(NULL); 582 return ret; 583 } 584 585 /**********************************************************************/ 586 587 static void 588 startAgainTimeout(void) 589 { 590 NetState = NETLOOP_RESTART; 591 } 592 593 static void 594 startAgainHandler(uchar *pkt, unsigned dest, IPaddr_t sip, 595 unsigned src, unsigned len) 596 { 597 /* Totally ignore the packet */ 598 } 599 600 void NetStartAgain(void) 601 { 602 char *nretry; 603 int retry_forever = 0; 604 unsigned long retrycnt = 0; 605 606 nretry = getenv("netretry"); 607 if (nretry) { 608 if (!strcmp(nretry, "yes")) 609 retry_forever = 1; 610 else if (!strcmp(nretry, "no")) 611 retrycnt = 0; 612 else if (!strcmp(nretry, "once")) 613 retrycnt = 1; 614 else 615 retrycnt = simple_strtoul(nretry, NULL, 0); 616 } else 617 retry_forever = 1; 618 619 if ((!retry_forever) && (NetTryCount >= retrycnt)) { 620 eth_halt(); 621 NetState = NETLOOP_FAIL; 622 return; 623 } 624 625 NetTryCount++; 626 627 eth_halt(); 628 #if !defined(CONFIG_NET_DO_NOT_TRY_ANOTHER) 629 eth_try_another(!NetRestarted); 630 #endif 631 eth_init(gd->bd); 632 if (NetRestartWrap) { 633 NetRestartWrap = 0; 634 if (NetDevExists) { 635 NetSetTimeout(10000UL, startAgainTimeout); 636 NetSetHandler(startAgainHandler); 637 } else { 638 NetState = NETLOOP_FAIL; 639 } 640 } else { 641 NetState = NETLOOP_RESTART; 642 } 643 } 644 645 /**********************************************************************/ 646 /* 647 * Miscelaneous bits. 648 */ 649 650 void 651 NetSetHandler(rxhand_f *f) 652 { 653 packetHandler = f; 654 } 655 656 void net_set_icmp_handler(rxhand_icmp_f *f) 657 { 658 packet_icmp_handler = f; 659 } 660 661 void 662 NetSetTimeout(ulong iv, thand_f *f) 663 { 664 if (iv == 0) { 665 timeHandler = (thand_f *)0; 666 } else { 667 timeHandler = f; 668 timeStart = get_timer(0); 669 timeDelta = iv; 670 } 671 } 672 673 674 void 675 NetSendPacket(volatile uchar *pkt, int len) 676 { 677 (void) eth_send(pkt, len); 678 } 679 680 int 681 NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, int len) 682 { 683 uchar *pkt; 684 685 /* convert to new style broadcast */ 686 if (dest == 0) 687 dest = 0xFFFFFFFF; 688 689 /* if broadcast, make the ether address a broadcast and don't do ARP */ 690 if (dest == 0xFFFFFFFF) 691 ether = NetBcastAddr; 692 693 /* 694 * if MAC address was not discovered yet, save the packet and do 695 * an ARP request 696 */ 697 if (memcmp(ether, NetEtherNullAddr, 6) == 0) { 698 699 debug("sending ARP for %08lx\n", dest); 700 701 NetArpWaitPacketIP = dest; 702 NetArpWaitPacketMAC = ether; 703 704 pkt = NetArpWaitTxPacket; 705 pkt += NetSetEther(pkt, NetArpWaitPacketMAC, PROT_IP); 706 707 NetSetIP(pkt, dest, dport, sport, len); 708 memcpy(pkt + IP_HDR_SIZE, (uchar *)NetTxPacket + 709 (pkt - (uchar *)NetArpWaitTxPacket) + IP_HDR_SIZE, len); 710 711 /* size of the waiting packet */ 712 NetArpWaitTxPacketSize = (pkt - NetArpWaitTxPacket) + 713 IP_HDR_SIZE + len; 714 715 /* and do the ARP request */ 716 NetArpWaitTry = 1; 717 NetArpWaitTimerStart = get_timer(0); 718 ArpRequest(); 719 return 1; /* waiting */ 720 } 721 722 debug("sending UDP to %08lx/%pM\n", dest, ether); 723 724 pkt = (uchar *)NetTxPacket; 725 pkt += NetSetEther(pkt, ether, PROT_IP); 726 NetSetIP(pkt, dest, dport, sport, len); 727 (void) eth_send(NetTxPacket, (pkt - NetTxPacket) + IP_HDR_SIZE + len); 728 729 return 0; /* transmitted */ 730 } 731 732 #if defined(CONFIG_CMD_PING) 733 static ushort PingSeqNo; 734 735 int PingSend(void) 736 { 737 static uchar mac[6]; 738 volatile IP_t *ip; 739 volatile ushort *s; 740 uchar *pkt; 741 742 /* XXX always send arp request */ 743 744 memcpy(mac, NetEtherNullAddr, 6); 745 746 debug("sending ARP for %08lx\n", NetPingIP); 747 748 NetArpWaitPacketIP = NetPingIP; 749 NetArpWaitPacketMAC = mac; 750 751 pkt = NetArpWaitTxPacket; 752 pkt += NetSetEther(pkt, mac, PROT_IP); 753 754 ip = (volatile IP_t *)pkt; 755 756 /* 757 * Construct an IP and ICMP header. 758 * (need to set no fragment bit - XXX) 759 */ 760 /* IP_HDR_SIZE / 4 (not including UDP) */ 761 ip->ip_hl_v = 0x45; 762 ip->ip_tos = 0; 763 ip->ip_len = htons(IP_HDR_SIZE_NO_UDP + 8); 764 ip->ip_id = htons(NetIPID++); 765 ip->ip_off = htons(IP_FLAGS_DFRAG); /* Don't fragment */ 766 ip->ip_ttl = 255; 767 ip->ip_p = 0x01; /* ICMP */ 768 ip->ip_sum = 0; 769 /* already in network byte order */ 770 NetCopyIP((void *)&ip->ip_src, &NetOurIP); 771 /* - "" - */ 772 NetCopyIP((void *)&ip->ip_dst, &NetPingIP); 773 ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2); 774 775 s = &ip->udp_src; /* XXX ICMP starts here */ 776 s[0] = htons(0x0800); /* echo-request, code */ 777 s[1] = 0; /* checksum */ 778 s[2] = 0; /* identifier */ 779 s[3] = htons(PingSeqNo++); /* sequence number */ 780 s[1] = ~NetCksum((uchar *)s, 8/2); 781 782 /* size of the waiting packet */ 783 NetArpWaitTxPacketSize = 784 (pkt - NetArpWaitTxPacket) + IP_HDR_SIZE_NO_UDP + 8; 785 786 /* and do the ARP request */ 787 NetArpWaitTry = 1; 788 NetArpWaitTimerStart = get_timer(0); 789 ArpRequest(); 790 return 1; /* waiting */ 791 } 792 793 static void 794 PingTimeout(void) 795 { 796 eth_halt(); 797 NetState = NETLOOP_FAIL; /* we did not get the reply */ 798 } 799 800 static void 801 PingHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, 802 unsigned len) 803 { 804 if (sip != NetPingIP) 805 return; 806 807 NetState = NETLOOP_SUCCESS; 808 } 809 810 static void PingStart(void) 811 { 812 printf("Using %s device\n", eth_get_name()); 813 NetSetTimeout(10000UL, PingTimeout); 814 NetSetHandler(PingHandler); 815 816 PingSend(); 817 } 818 #endif 819 820 #if defined(CONFIG_CMD_CDP) 821 822 #define CDP_DEVICE_ID_TLV 0x0001 823 #define CDP_ADDRESS_TLV 0x0002 824 #define CDP_PORT_ID_TLV 0x0003 825 #define CDP_CAPABILITIES_TLV 0x0004 826 #define CDP_VERSION_TLV 0x0005 827 #define CDP_PLATFORM_TLV 0x0006 828 #define CDP_NATIVE_VLAN_TLV 0x000a 829 #define CDP_APPLIANCE_VLAN_TLV 0x000e 830 #define CDP_TRIGGER_TLV 0x000f 831 #define CDP_POWER_CONSUMPTION_TLV 0x0010 832 #define CDP_SYSNAME_TLV 0x0014 833 #define CDP_SYSOBJECT_TLV 0x0015 834 #define CDP_MANAGEMENT_ADDRESS_TLV 0x0016 835 836 #define CDP_TIMEOUT 250UL /* one packet every 250ms */ 837 838 static int CDPSeq; 839 static int CDPOK; 840 841 ushort CDPNativeVLAN; 842 ushort CDPApplianceVLAN; 843 844 static const uchar CDP_SNAP_hdr[8] = { 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x0C, 0x20, 845 0x00 }; 846 847 static ushort CDP_compute_csum(const uchar *buff, ushort len) 848 { 849 ushort csum; 850 int odd; 851 ulong result = 0; 852 ushort leftover; 853 ushort *p; 854 855 if (len > 0) { 856 odd = 1 & (ulong)buff; 857 if (odd) { 858 result = *buff << 8; 859 len--; 860 buff++; 861 } 862 while (len > 1) { 863 p = (ushort *)buff; 864 result += *p++; 865 buff = (uchar *)p; 866 if (result & 0x80000000) 867 result = (result & 0xFFFF) + (result >> 16); 868 len -= 2; 869 } 870 if (len) { 871 leftover = (signed short)(*(const signed char *)buff); 872 /* CISCO SUCKS big time! (and blows too): 873 * CDP uses the IP checksum algorithm with a twist; 874 * for the last byte it *sign* extends and sums. 875 */ 876 result = (result & 0xffff0000) | 877 ((result + leftover) & 0x0000ffff); 878 } 879 while (result >> 16) 880 result = (result & 0xFFFF) + (result >> 16); 881 882 if (odd) 883 result = ((result >> 8) & 0xff) | 884 ((result & 0xff) << 8); 885 } 886 887 /* add up 16-bit and 17-bit words for 17+c bits */ 888 result = (result & 0xffff) + (result >> 16); 889 /* add up 16-bit and 2-bit for 16+c bit */ 890 result = (result & 0xffff) + (result >> 16); 891 /* add up carry.. */ 892 result = (result & 0xffff) + (result >> 16); 893 894 /* negate */ 895 csum = ~(ushort)result; 896 897 /* run time endian detection */ 898 if (csum != htons(csum)) /* little endian */ 899 csum = htons(csum); 900 901 return csum; 902 } 903 904 int CDPSendTrigger(void) 905 { 906 volatile uchar *pkt; 907 volatile ushort *s; 908 volatile ushort *cp; 909 Ethernet_t *et; 910 int len; 911 ushort chksum; 912 #if defined(CONFIG_CDP_DEVICE_ID) || defined(CONFIG_CDP_PORT_ID) || \ 913 defined(CONFIG_CDP_VERSION) || defined(CONFIG_CDP_PLATFORM) 914 char buf[32]; 915 #endif 916 917 pkt = NetTxPacket; 918 et = (Ethernet_t *)pkt; 919 920 /* NOTE: trigger sent not on any VLAN */ 921 922 /* form ethernet header */ 923 memcpy(et->et_dest, NetCDPAddr, 6); 924 memcpy(et->et_src, NetOurEther, 6); 925 926 pkt += ETHER_HDR_SIZE; 927 928 /* SNAP header */ 929 memcpy((uchar *)pkt, CDP_SNAP_hdr, sizeof(CDP_SNAP_hdr)); 930 pkt += sizeof(CDP_SNAP_hdr); 931 932 /* CDP header */ 933 *pkt++ = 0x02; /* CDP version 2 */ 934 *pkt++ = 180; /* TTL */ 935 s = (volatile ushort *)pkt; 936 cp = s; 937 /* checksum (0 for later calculation) */ 938 *s++ = htons(0); 939 940 /* CDP fields */ 941 #ifdef CONFIG_CDP_DEVICE_ID 942 *s++ = htons(CDP_DEVICE_ID_TLV); 943 *s++ = htons(CONFIG_CDP_DEVICE_ID); 944 sprintf(buf, CONFIG_CDP_DEVICE_ID_PREFIX "%pm", NetOurEther); 945 memcpy((uchar *)s, buf, 16); 946 s += 16 / 2; 947 #endif 948 949 #ifdef CONFIG_CDP_PORT_ID 950 *s++ = htons(CDP_PORT_ID_TLV); 951 memset(buf, 0, sizeof(buf)); 952 sprintf(buf, CONFIG_CDP_PORT_ID, eth_get_dev_index()); 953 len = strlen(buf); 954 if (len & 1) /* make it even */ 955 len++; 956 *s++ = htons(len + 4); 957 memcpy((uchar *)s, buf, len); 958 s += len / 2; 959 #endif 960 961 #ifdef CONFIG_CDP_CAPABILITIES 962 *s++ = htons(CDP_CAPABILITIES_TLV); 963 *s++ = htons(8); 964 *(ulong *)s = htonl(CONFIG_CDP_CAPABILITIES); 965 s += 2; 966 #endif 967 968 #ifdef CONFIG_CDP_VERSION 969 *s++ = htons(CDP_VERSION_TLV); 970 memset(buf, 0, sizeof(buf)); 971 strcpy(buf, CONFIG_CDP_VERSION); 972 len = strlen(buf); 973 if (len & 1) /* make it even */ 974 len++; 975 *s++ = htons(len + 4); 976 memcpy((uchar *)s, buf, len); 977 s += len / 2; 978 #endif 979 980 #ifdef CONFIG_CDP_PLATFORM 981 *s++ = htons(CDP_PLATFORM_TLV); 982 memset(buf, 0, sizeof(buf)); 983 strcpy(buf, CONFIG_CDP_PLATFORM); 984 len = strlen(buf); 985 if (len & 1) /* make it even */ 986 len++; 987 *s++ = htons(len + 4); 988 memcpy((uchar *)s, buf, len); 989 s += len / 2; 990 #endif 991 992 #ifdef CONFIG_CDP_TRIGGER 993 *s++ = htons(CDP_TRIGGER_TLV); 994 *s++ = htons(8); 995 *(ulong *)s = htonl(CONFIG_CDP_TRIGGER); 996 s += 2; 997 #endif 998 999 #ifdef CONFIG_CDP_POWER_CONSUMPTION 1000 *s++ = htons(CDP_POWER_CONSUMPTION_TLV); 1001 *s++ = htons(6); 1002 *s++ = htons(CONFIG_CDP_POWER_CONSUMPTION); 1003 #endif 1004 1005 /* length of ethernet packet */ 1006 len = (uchar *)s - ((uchar *)NetTxPacket + ETHER_HDR_SIZE); 1007 et->et_protlen = htons(len); 1008 1009 len = ETHER_HDR_SIZE + sizeof(CDP_SNAP_hdr); 1010 chksum = CDP_compute_csum((uchar *)NetTxPacket + len, 1011 (uchar *)s - (NetTxPacket + len)); 1012 if (chksum == 0) 1013 chksum = 0xFFFF; 1014 *cp = htons(chksum); 1015 1016 (void) eth_send(NetTxPacket, (uchar *)s - NetTxPacket); 1017 return 0; 1018 } 1019 1020 static void 1021 CDPTimeout(void) 1022 { 1023 CDPSeq++; 1024 1025 if (CDPSeq < 3) { 1026 NetSetTimeout(CDP_TIMEOUT, CDPTimeout); 1027 CDPSendTrigger(); 1028 return; 1029 } 1030 1031 /* if not OK try again */ 1032 if (!CDPOK) 1033 NetStartAgain(); 1034 else 1035 NetState = NETLOOP_SUCCESS; 1036 } 1037 1038 static void 1039 CDPDummyHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, 1040 unsigned len) 1041 { 1042 /* nothing */ 1043 } 1044 1045 static void 1046 CDPHandler(const uchar *pkt, unsigned len) 1047 { 1048 const uchar *t; 1049 const ushort *ss; 1050 ushort type, tlen; 1051 uchar applid; 1052 ushort vlan, nvlan; 1053 1054 /* minimum size? */ 1055 if (len < sizeof(CDP_SNAP_hdr) + 4) 1056 goto pkt_short; 1057 1058 /* check for valid CDP SNAP header */ 1059 if (memcmp(pkt, CDP_SNAP_hdr, sizeof(CDP_SNAP_hdr)) != 0) 1060 return; 1061 1062 pkt += sizeof(CDP_SNAP_hdr); 1063 len -= sizeof(CDP_SNAP_hdr); 1064 1065 /* Version of CDP protocol must be >= 2 and TTL != 0 */ 1066 if (pkt[0] < 0x02 || pkt[1] == 0) 1067 return; 1068 1069 /* 1070 * if version is greater than 0x02 maybe we'll have a problem; 1071 * output a warning 1072 */ 1073 if (pkt[0] != 0x02) 1074 printf("** WARNING: CDP packet received with a protocol version %d > 2\n", 1075 pkt[0] & 0xff); 1076 1077 if (CDP_compute_csum(pkt, len) != 0) 1078 return; 1079 1080 pkt += 4; 1081 len -= 4; 1082 1083 vlan = htons(-1); 1084 nvlan = htons(-1); 1085 while (len > 0) { 1086 if (len < 4) 1087 goto pkt_short; 1088 1089 ss = (const ushort *)pkt; 1090 type = ntohs(ss[0]); 1091 tlen = ntohs(ss[1]); 1092 if (tlen > len) 1093 goto pkt_short; 1094 1095 pkt += tlen; 1096 len -= tlen; 1097 1098 ss += 2; /* point ss to the data of the TLV */ 1099 tlen -= 4; 1100 1101 switch (type) { 1102 case CDP_DEVICE_ID_TLV: 1103 break; 1104 case CDP_ADDRESS_TLV: 1105 break; 1106 case CDP_PORT_ID_TLV: 1107 break; 1108 case CDP_CAPABILITIES_TLV: 1109 break; 1110 case CDP_VERSION_TLV: 1111 break; 1112 case CDP_PLATFORM_TLV: 1113 break; 1114 case CDP_NATIVE_VLAN_TLV: 1115 nvlan = *ss; 1116 break; 1117 case CDP_APPLIANCE_VLAN_TLV: 1118 t = (const uchar *)ss; 1119 while (tlen > 0) { 1120 if (tlen < 3) 1121 goto pkt_short; 1122 1123 applid = t[0]; 1124 ss = (const ushort *)(t + 1); 1125 1126 #ifdef CONFIG_CDP_APPLIANCE_VLAN_TYPE 1127 if (applid == CONFIG_CDP_APPLIANCE_VLAN_TYPE) 1128 vlan = *ss; 1129 #else 1130 /* XXX will this work; dunno */ 1131 vlan = ntohs(*ss); 1132 #endif 1133 t += 3; tlen -= 3; 1134 } 1135 break; 1136 case CDP_TRIGGER_TLV: 1137 break; 1138 case CDP_POWER_CONSUMPTION_TLV: 1139 break; 1140 case CDP_SYSNAME_TLV: 1141 break; 1142 case CDP_SYSOBJECT_TLV: 1143 break; 1144 case CDP_MANAGEMENT_ADDRESS_TLV: 1145 break; 1146 } 1147 } 1148 1149 CDPApplianceVLAN = vlan; 1150 CDPNativeVLAN = nvlan; 1151 1152 CDPOK = 1; 1153 return; 1154 1155 pkt_short: 1156 printf("** CDP packet is too short\n"); 1157 return; 1158 } 1159 1160 static void CDPStart(void) 1161 { 1162 printf("Using %s device\n", eth_get_name()); 1163 CDPSeq = 0; 1164 CDPOK = 0; 1165 1166 CDPNativeVLAN = htons(-1); 1167 CDPApplianceVLAN = htons(-1); 1168 1169 NetSetTimeout(CDP_TIMEOUT, CDPTimeout); 1170 NetSetHandler(CDPDummyHandler); 1171 1172 CDPSendTrigger(); 1173 } 1174 #endif 1175 1176 #ifdef CONFIG_IP_DEFRAG 1177 /* 1178 * This function collects fragments in a single packet, according 1179 * to the algorithm in RFC815. It returns NULL or the pointer to 1180 * a complete packet, in static storage 1181 */ 1182 #ifndef CONFIG_NET_MAXDEFRAG 1183 #define CONFIG_NET_MAXDEFRAG 16384 1184 #endif 1185 /* 1186 * MAXDEFRAG, above, is chosen in the config file and is real data 1187 * so we need to add the NFS overhead, which is more than TFTP. 1188 * To use sizeof in the internal unnamed structures, we need a real 1189 * instance (can't do "sizeof(struct rpc_t.u.reply))", unfortunately). 1190 * The compiler doesn't complain nor allocates the actual structure 1191 */ 1192 static struct rpc_t rpc_specimen; 1193 #define IP_PKTSIZE (CONFIG_NET_MAXDEFRAG + sizeof(rpc_specimen.u.reply)) 1194 1195 #define IP_MAXUDP (IP_PKTSIZE - IP_HDR_SIZE_NO_UDP) 1196 1197 /* 1198 * this is the packet being assembled, either data or frag control. 1199 * Fragments go by 8 bytes, so this union must be 8 bytes long 1200 */ 1201 struct hole { 1202 /* first_byte is address of this structure */ 1203 u16 last_byte; /* last byte in this hole + 1 (begin of next hole) */ 1204 u16 next_hole; /* index of next (in 8-b blocks), 0 == none */ 1205 u16 prev_hole; /* index of prev, 0 == none */ 1206 u16 unused; 1207 }; 1208 1209 static IP_t *__NetDefragment(IP_t *ip, int *lenp) 1210 { 1211 static uchar pkt_buff[IP_PKTSIZE] __attribute__((aligned(PKTALIGN))); 1212 static u16 first_hole, total_len; 1213 struct hole *payload, *thisfrag, *h, *newh; 1214 IP_t *localip = (IP_t *)pkt_buff; 1215 uchar *indata = (uchar *)ip; 1216 int offset8, start, len, done = 0; 1217 u16 ip_off = ntohs(ip->ip_off); 1218 1219 /* payload starts after IP header, this fragment is in there */ 1220 payload = (struct hole *)(pkt_buff + IP_HDR_SIZE_NO_UDP); 1221 offset8 = (ip_off & IP_OFFS); 1222 thisfrag = payload + offset8; 1223 start = offset8 * 8; 1224 len = ntohs(ip->ip_len) - IP_HDR_SIZE_NO_UDP; 1225 1226 if (start + len > IP_MAXUDP) /* fragment extends too far */ 1227 return NULL; 1228 1229 if (!total_len || localip->ip_id != ip->ip_id) { 1230 /* new (or different) packet, reset structs */ 1231 total_len = 0xffff; 1232 payload[0].last_byte = ~0; 1233 payload[0].next_hole = 0; 1234 payload[0].prev_hole = 0; 1235 first_hole = 0; 1236 /* any IP header will work, copy the first we received */ 1237 memcpy(localip, ip, IP_HDR_SIZE_NO_UDP); 1238 } 1239 1240 /* 1241 * What follows is the reassembly algorithm. We use the payload 1242 * array as a linked list of hole descriptors, as each hole starts 1243 * at a multiple of 8 bytes. However, last byte can be whatever value, 1244 * so it is represented as byte count, not as 8-byte blocks. 1245 */ 1246 1247 h = payload + first_hole; 1248 while (h->last_byte < start) { 1249 if (!h->next_hole) { 1250 /* no hole that far away */ 1251 return NULL; 1252 } 1253 h = payload + h->next_hole; 1254 } 1255 1256 /* last fragment may be 1..7 bytes, the "+7" forces acceptance */ 1257 if (offset8 + ((len + 7) / 8) <= h - payload) { 1258 /* no overlap with holes (dup fragment?) */ 1259 return NULL; 1260 } 1261 1262 if (!(ip_off & IP_FLAGS_MFRAG)) { 1263 /* no more fragmentss: truncate this (last) hole */ 1264 total_len = start + len; 1265 h->last_byte = start + len; 1266 } 1267 1268 /* 1269 * There is some overlap: fix the hole list. This code doesn't 1270 * deal with a fragment that overlaps with two different holes 1271 * (thus being a superset of a previously-received fragment). 1272 */ 1273 1274 if ((h >= thisfrag) && (h->last_byte <= start + len)) { 1275 /* complete overlap with hole: remove hole */ 1276 if (!h->prev_hole && !h->next_hole) { 1277 /* last remaining hole */ 1278 done = 1; 1279 } else if (!h->prev_hole) { 1280 /* first hole */ 1281 first_hole = h->next_hole; 1282 payload[h->next_hole].prev_hole = 0; 1283 } else if (!h->next_hole) { 1284 /* last hole */ 1285 payload[h->prev_hole].next_hole = 0; 1286 } else { 1287 /* in the middle of the list */ 1288 payload[h->next_hole].prev_hole = h->prev_hole; 1289 payload[h->prev_hole].next_hole = h->next_hole; 1290 } 1291 1292 } else if (h->last_byte <= start + len) { 1293 /* overlaps with final part of the hole: shorten this hole */ 1294 h->last_byte = start; 1295 1296 } else if (h >= thisfrag) { 1297 /* overlaps with initial part of the hole: move this hole */ 1298 newh = thisfrag + (len / 8); 1299 *newh = *h; 1300 h = newh; 1301 if (h->next_hole) 1302 payload[h->next_hole].prev_hole = (h - payload); 1303 if (h->prev_hole) 1304 payload[h->prev_hole].next_hole = (h - payload); 1305 else 1306 first_hole = (h - payload); 1307 1308 } else { 1309 /* fragment sits in the middle: split the hole */ 1310 newh = thisfrag + (len / 8); 1311 *newh = *h; 1312 h->last_byte = start; 1313 h->next_hole = (newh - payload); 1314 newh->prev_hole = (h - payload); 1315 if (newh->next_hole) 1316 payload[newh->next_hole].prev_hole = (newh - payload); 1317 } 1318 1319 /* finally copy this fragment and possibly return whole packet */ 1320 memcpy((uchar *)thisfrag, indata + IP_HDR_SIZE_NO_UDP, len); 1321 if (!done) 1322 return NULL; 1323 1324 localip->ip_len = htons(total_len); 1325 *lenp = total_len + IP_HDR_SIZE_NO_UDP; 1326 return localip; 1327 } 1328 1329 static inline IP_t *NetDefragment(IP_t *ip, int *lenp) 1330 { 1331 u16 ip_off = ntohs(ip->ip_off); 1332 if (!(ip_off & (IP_OFFS | IP_FLAGS_MFRAG))) 1333 return ip; /* not a fragment */ 1334 return __NetDefragment(ip, lenp); 1335 } 1336 1337 #else /* !CONFIG_IP_DEFRAG */ 1338 1339 static inline IP_t *NetDefragment(IP_t *ip, int *lenp) 1340 { 1341 u16 ip_off = ntohs(ip->ip_off); 1342 if (!(ip_off & (IP_OFFS | IP_FLAGS_MFRAG))) 1343 return ip; /* not a fragment */ 1344 return NULL; 1345 } 1346 #endif 1347 1348 /** 1349 * Receive an ICMP packet. We deal with REDIRECT and PING here, and silently 1350 * drop others. 1351 * 1352 * @parma ip IP packet containing the ICMP 1353 */ 1354 static void receive_icmp(IP_t *ip, int len, IPaddr_t src_ip, Ethernet_t *et) 1355 { 1356 ICMP_t *icmph = (ICMP_t *)&ip->udp_src; 1357 1358 switch (icmph->type) { 1359 case ICMP_REDIRECT: 1360 if (icmph->code != ICMP_REDIR_HOST) 1361 return; 1362 printf(" ICMP Host Redirect to %pI4 ", 1363 &icmph->un.gateway); 1364 break; 1365 #if defined(CONFIG_CMD_PING) 1366 case ICMP_ECHO_REPLY: 1367 /* 1368 * IP header OK. Pass the packet to the 1369 * current handler. 1370 */ 1371 /* 1372 * XXX point to ip packet - should this use 1373 * packet_icmp_handler? 1374 */ 1375 (*packetHandler)((uchar *)ip, 0, src_ip, 0, 0); 1376 break; 1377 case ICMP_ECHO_REQUEST: 1378 debug("Got ICMP ECHO REQUEST, return %d bytes\n", 1379 ETHER_HDR_SIZE + len); 1380 1381 memcpy(&et->et_dest[0], &et->et_src[0], 6); 1382 memcpy(&et->et_src[0], NetOurEther, 6); 1383 1384 ip->ip_sum = 0; 1385 ip->ip_off = 0; 1386 NetCopyIP((void *)&ip->ip_dst, &ip->ip_src); 1387 NetCopyIP((void *)&ip->ip_src, &NetOurIP); 1388 ip->ip_sum = ~NetCksum((uchar *)ip, 1389 IP_HDR_SIZE_NO_UDP >> 1); 1390 1391 icmph->type = ICMP_ECHO_REPLY; 1392 icmph->checksum = 0; 1393 icmph->checksum = ~NetCksum((uchar *)icmph, 1394 (len - IP_HDR_SIZE_NO_UDP) >> 1); 1395 (void) eth_send((uchar *)et, 1396 ETHER_HDR_SIZE + len); 1397 break; 1398 #endif 1399 default: 1400 if (packet_icmp_handler) 1401 packet_icmp_handler(icmph->type, icmph->code, 1402 ntohs(ip->udp_dst), src_ip, ntohs(ip->udp_src), 1403 icmph->un.data, ntohs(ip->udp_len)); 1404 break; 1405 } 1406 } 1407 1408 void 1409 NetReceive(volatile uchar *inpkt, int len) 1410 { 1411 Ethernet_t *et; 1412 IP_t *ip; 1413 ARP_t *arp; 1414 IPaddr_t tmp; 1415 IPaddr_t src_ip; 1416 int x; 1417 uchar *pkt; 1418 #if defined(CONFIG_CMD_CDP) 1419 int iscdp; 1420 #endif 1421 ushort cti = 0, vlanid = VLAN_NONE, myvlanid, mynvlanid; 1422 1423 debug("packet received\n"); 1424 1425 NetRxPacket = inpkt; 1426 NetRxPacketLen = len; 1427 et = (Ethernet_t *)inpkt; 1428 1429 /* too small packet? */ 1430 if (len < ETHER_HDR_SIZE) 1431 return; 1432 1433 #ifdef CONFIG_API 1434 if (push_packet) { 1435 (*push_packet)(inpkt, len); 1436 return; 1437 } 1438 #endif 1439 1440 #if defined(CONFIG_CMD_CDP) 1441 /* keep track if packet is CDP */ 1442 iscdp = memcmp(et->et_dest, NetCDPAddr, 6) == 0; 1443 #endif 1444 1445 myvlanid = ntohs(NetOurVLAN); 1446 if (myvlanid == (ushort)-1) 1447 myvlanid = VLAN_NONE; 1448 mynvlanid = ntohs(NetOurNativeVLAN); 1449 if (mynvlanid == (ushort)-1) 1450 mynvlanid = VLAN_NONE; 1451 1452 x = ntohs(et->et_protlen); 1453 1454 debug("packet received\n"); 1455 1456 if (x < 1514) { 1457 /* 1458 * Got a 802 packet. Check the other protocol field. 1459 */ 1460 x = ntohs(et->et_prot); 1461 1462 ip = (IP_t *)(inpkt + E802_HDR_SIZE); 1463 len -= E802_HDR_SIZE; 1464 1465 } else if (x != PROT_VLAN) { /* normal packet */ 1466 ip = (IP_t *)(inpkt + ETHER_HDR_SIZE); 1467 len -= ETHER_HDR_SIZE; 1468 1469 } else { /* VLAN packet */ 1470 VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)et; 1471 1472 debug("VLAN packet received\n"); 1473 1474 /* too small packet? */ 1475 if (len < VLAN_ETHER_HDR_SIZE) 1476 return; 1477 1478 /* if no VLAN active */ 1479 if ((ntohs(NetOurVLAN) & VLAN_IDMASK) == VLAN_NONE 1480 #if defined(CONFIG_CMD_CDP) 1481 && iscdp == 0 1482 #endif 1483 ) 1484 return; 1485 1486 cti = ntohs(vet->vet_tag); 1487 vlanid = cti & VLAN_IDMASK; 1488 x = ntohs(vet->vet_type); 1489 1490 ip = (IP_t *)(inpkt + VLAN_ETHER_HDR_SIZE); 1491 len -= VLAN_ETHER_HDR_SIZE; 1492 } 1493 1494 debug("Receive from protocol 0x%x\n", x); 1495 1496 #if defined(CONFIG_CMD_CDP) 1497 if (iscdp) { 1498 CDPHandler((uchar *)ip, len); 1499 return; 1500 } 1501 #endif 1502 1503 if ((myvlanid & VLAN_IDMASK) != VLAN_NONE) { 1504 if (vlanid == VLAN_NONE) 1505 vlanid = (mynvlanid & VLAN_IDMASK); 1506 /* not matched? */ 1507 if (vlanid != (myvlanid & VLAN_IDMASK)) 1508 return; 1509 } 1510 1511 switch (x) { 1512 1513 case PROT_ARP: 1514 /* 1515 * We have to deal with two types of ARP packets: 1516 * - REQUEST packets will be answered by sending our 1517 * IP address - if we know it. 1518 * - REPLY packates are expected only after we asked 1519 * for the TFTP server's or the gateway's ethernet 1520 * address; so if we receive such a packet, we set 1521 * the server ethernet address 1522 */ 1523 debug("Got ARP\n"); 1524 1525 arp = (ARP_t *)ip; 1526 if (len < ARP_HDR_SIZE) { 1527 printf("bad length %d < %d\n", len, ARP_HDR_SIZE); 1528 return; 1529 } 1530 if (ntohs(arp->ar_hrd) != ARP_ETHER) 1531 return; 1532 if (ntohs(arp->ar_pro) != PROT_IP) 1533 return; 1534 if (arp->ar_hln != 6) 1535 return; 1536 if (arp->ar_pln != 4) 1537 return; 1538 1539 if (NetOurIP == 0) 1540 return; 1541 1542 if (NetReadIP(&arp->ar_data[16]) != NetOurIP) 1543 return; 1544 1545 switch (ntohs(arp->ar_op)) { 1546 case ARPOP_REQUEST: 1547 /* reply with our IP address */ 1548 debug("Got ARP REQUEST, return our IP\n"); 1549 pkt = (uchar *)et; 1550 pkt += NetSetEther(pkt, et->et_src, PROT_ARP); 1551 arp->ar_op = htons(ARPOP_REPLY); 1552 memcpy(&arp->ar_data[10], &arp->ar_data[0], 6); 1553 NetCopyIP(&arp->ar_data[16], &arp->ar_data[6]); 1554 memcpy(&arp->ar_data[0], NetOurEther, 6); 1555 NetCopyIP(&arp->ar_data[6], &NetOurIP); 1556 (void) eth_send((uchar *)et, 1557 (pkt - (uchar *)et) + ARP_HDR_SIZE); 1558 return; 1559 1560 case ARPOP_REPLY: /* arp reply */ 1561 /* are we waiting for a reply */ 1562 if (!NetArpWaitPacketIP || !NetArpWaitPacketMAC) 1563 break; 1564 1565 #ifdef CONFIG_KEEP_SERVERADDR 1566 if (NetServerIP == NetArpWaitPacketIP) { 1567 char buf[20]; 1568 sprintf(buf, "%pM", arp->ar_data); 1569 setenv("serveraddr", buf); 1570 } 1571 #endif 1572 1573 debug("Got ARP REPLY, set server/gtwy eth addr (%pM)\n", 1574 arp->ar_data); 1575 1576 tmp = NetReadIP(&arp->ar_data[6]); 1577 1578 /* matched waiting packet's address */ 1579 if (tmp == NetArpWaitReplyIP) { 1580 debug("Got it\n"); 1581 /* save address for later use */ 1582 memcpy(NetArpWaitPacketMAC, 1583 &arp->ar_data[0], 6); 1584 1585 #ifdef CONFIG_NETCONSOLE 1586 (*packetHandler)(0, 0, 0, 0, 0); 1587 #endif 1588 /* modify header, and transmit it */ 1589 memcpy(((Ethernet_t *)NetArpWaitTxPacket)->et_dest, NetArpWaitPacketMAC, 6); 1590 (void) eth_send(NetArpWaitTxPacket, 1591 NetArpWaitTxPacketSize); 1592 1593 /* no arp request pending now */ 1594 NetArpWaitPacketIP = 0; 1595 NetArpWaitTxPacketSize = 0; 1596 NetArpWaitPacketMAC = NULL; 1597 1598 } 1599 return; 1600 default: 1601 debug("Unexpected ARP opcode 0x%x\n", 1602 ntohs(arp->ar_op)); 1603 return; 1604 } 1605 break; 1606 1607 #ifdef CONFIG_CMD_RARP 1608 case PROT_RARP: 1609 debug("Got RARP\n"); 1610 arp = (ARP_t *)ip; 1611 if (len < ARP_HDR_SIZE) { 1612 printf("bad length %d < %d\n", len, ARP_HDR_SIZE); 1613 return; 1614 } 1615 1616 if ((ntohs(arp->ar_op) != RARPOP_REPLY) || 1617 (ntohs(arp->ar_hrd) != ARP_ETHER) || 1618 (ntohs(arp->ar_pro) != PROT_IP) || 1619 (arp->ar_hln != 6) || (arp->ar_pln != 4)) { 1620 1621 puts("invalid RARP header\n"); 1622 } else { 1623 NetCopyIP(&NetOurIP, &arp->ar_data[16]); 1624 if (NetServerIP == 0) 1625 NetCopyIP(&NetServerIP, &arp->ar_data[6]); 1626 memcpy(NetServerEther, &arp->ar_data[0], 6); 1627 1628 (*packetHandler)(0, 0, 0, 0, 0); 1629 } 1630 break; 1631 #endif 1632 case PROT_IP: 1633 debug("Got IP\n"); 1634 /* Before we start poking the header, make sure it is there */ 1635 if (len < IP_HDR_SIZE) { 1636 debug("len bad %d < %lu\n", len, (ulong)IP_HDR_SIZE); 1637 return; 1638 } 1639 /* Check the packet length */ 1640 if (len < ntohs(ip->ip_len)) { 1641 printf("len bad %d < %d\n", len, ntohs(ip->ip_len)); 1642 return; 1643 } 1644 len = ntohs(ip->ip_len); 1645 debug("len=%d, v=%02x\n", len, ip->ip_hl_v & 0xff); 1646 1647 /* Can't deal with anything except IPv4 */ 1648 if ((ip->ip_hl_v & 0xf0) != 0x40) 1649 return; 1650 /* Can't deal with IP options (headers != 20 bytes) */ 1651 if ((ip->ip_hl_v & 0x0f) > 0x05) 1652 return; 1653 /* Check the Checksum of the header */ 1654 if (!NetCksumOk((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2)) { 1655 puts("checksum bad\n"); 1656 return; 1657 } 1658 /* If it is not for us, ignore it */ 1659 tmp = NetReadIP(&ip->ip_dst); 1660 if (NetOurIP && tmp != NetOurIP && tmp != 0xFFFFFFFF) { 1661 #ifdef CONFIG_MCAST_TFTP 1662 if (Mcast_addr != tmp) 1663 #endif 1664 return; 1665 } 1666 /* Read source IP address for later use */ 1667 src_ip = NetReadIP(&ip->ip_src); 1668 /* 1669 * The function returns the unchanged packet if it's not 1670 * a fragment, and either the complete packet or NULL if 1671 * it is a fragment (if !CONFIG_IP_DEFRAG, it returns NULL) 1672 */ 1673 ip = NetDefragment(ip, &len); 1674 if (!ip) 1675 return; 1676 /* 1677 * watch for ICMP host redirects 1678 * 1679 * There is no real handler code (yet). We just watch 1680 * for ICMP host redirect messages. In case anybody 1681 * sees these messages: please contact me 1682 * (wd@denx.de), or - even better - send me the 1683 * necessary fixes :-) 1684 * 1685 * Note: in all cases where I have seen this so far 1686 * it was a problem with the router configuration, 1687 * for instance when a router was configured in the 1688 * BOOTP reply, but the TFTP server was on the same 1689 * subnet. So this is probably a warning that your 1690 * configuration might be wrong. But I'm not really 1691 * sure if there aren't any other situations. 1692 * 1693 * Simon Glass <sjg@chromium.org>: We get an ICMP when 1694 * we send a tftp packet to a dead connection, or when 1695 * there is no server at the other end. 1696 */ 1697 if (ip->ip_p == IPPROTO_ICMP) { 1698 receive_icmp(ip, len, src_ip, et); 1699 return; 1700 } else if (ip->ip_p != IPPROTO_UDP) { /* Only UDP packets */ 1701 return; 1702 } 1703 1704 #ifdef CONFIG_UDP_CHECKSUM 1705 if (ip->udp_xsum != 0) { 1706 ulong xsum; 1707 ushort *sumptr; 1708 ushort sumlen; 1709 1710 xsum = ip->ip_p; 1711 xsum += (ntohs(ip->udp_len)); 1712 xsum += (ntohl(ip->ip_src) >> 16) & 0x0000ffff; 1713 xsum += (ntohl(ip->ip_src) >> 0) & 0x0000ffff; 1714 xsum += (ntohl(ip->ip_dst) >> 16) & 0x0000ffff; 1715 xsum += (ntohl(ip->ip_dst) >> 0) & 0x0000ffff; 1716 1717 sumlen = ntohs(ip->udp_len); 1718 sumptr = (ushort *) &(ip->udp_src); 1719 1720 while (sumlen > 1) { 1721 ushort sumdata; 1722 1723 sumdata = *sumptr++; 1724 xsum += ntohs(sumdata); 1725 sumlen -= 2; 1726 } 1727 if (sumlen > 0) { 1728 ushort sumdata; 1729 1730 sumdata = *(unsigned char *) sumptr; 1731 sumdata = (sumdata << 8) & 0xff00; 1732 xsum += sumdata; 1733 } 1734 while ((xsum >> 16) != 0) { 1735 xsum = (xsum & 0x0000ffff) + 1736 ((xsum >> 16) & 0x0000ffff); 1737 } 1738 if ((xsum != 0x00000000) && (xsum != 0x0000ffff)) { 1739 printf(" UDP wrong checksum %08lx %08x\n", 1740 xsum, ntohs(ip->udp_xsum)); 1741 return; 1742 } 1743 } 1744 #endif 1745 1746 1747 #ifdef CONFIG_NETCONSOLE 1748 nc_input_packet((uchar *)ip + IP_HDR_SIZE, 1749 ntohs(ip->udp_dst), 1750 ntohs(ip->udp_src), 1751 ntohs(ip->udp_len) - 8); 1752 #endif 1753 /* 1754 * IP header OK. Pass the packet to the current handler. 1755 */ 1756 (*packetHandler)((uchar *)ip + IP_HDR_SIZE, 1757 ntohs(ip->udp_dst), 1758 src_ip, 1759 ntohs(ip->udp_src), 1760 ntohs(ip->udp_len) - 8); 1761 break; 1762 } 1763 } 1764 1765 1766 /**********************************************************************/ 1767 1768 static int net_check_prereq(enum proto_t protocol) 1769 { 1770 switch (protocol) { 1771 /* Fall through */ 1772 #if defined(CONFIG_CMD_PING) 1773 case PING: 1774 if (NetPingIP == 0) { 1775 puts("*** ERROR: ping address not given\n"); 1776 return 1; 1777 } 1778 goto common; 1779 #endif 1780 #if defined(CONFIG_CMD_SNTP) 1781 case SNTP: 1782 if (NetNtpServerIP == 0) { 1783 puts("*** ERROR: NTP server address not given\n"); 1784 return 1; 1785 } 1786 goto common; 1787 #endif 1788 #if defined(CONFIG_CMD_DNS) 1789 case DNS: 1790 if (NetOurDNSIP == 0) { 1791 puts("*** ERROR: DNS server address not given\n"); 1792 return 1; 1793 } 1794 goto common; 1795 #endif 1796 #if defined(CONFIG_CMD_NFS) 1797 case NFS: 1798 #endif 1799 case TFTPGET: 1800 case TFTPPUT: 1801 if (NetServerIP == 0) { 1802 puts("*** ERROR: `serverip' not set\n"); 1803 return 1; 1804 } 1805 #if defined(CONFIG_CMD_PING) || defined(CONFIG_CMD_SNTP) || \ 1806 defined(CONFIG_CMD_DNS) 1807 common: 1808 #endif 1809 /* Fall through */ 1810 1811 case NETCONS: 1812 case TFTPSRV: 1813 if (NetOurIP == 0) { 1814 puts("*** ERROR: `ipaddr' not set\n"); 1815 return 1; 1816 } 1817 /* Fall through */ 1818 1819 #ifdef CONFIG_CMD_RARP 1820 case RARP: 1821 #endif 1822 case BOOTP: 1823 case CDP: 1824 case DHCP: 1825 if (memcmp(NetOurEther, "\0\0\0\0\0\0", 6) == 0) { 1826 extern int eth_get_dev_index(void); 1827 int num = eth_get_dev_index(); 1828 1829 switch (num) { 1830 case -1: 1831 puts("*** ERROR: No ethernet found.\n"); 1832 return 1; 1833 case 0: 1834 puts("*** ERROR: `ethaddr' not set\n"); 1835 break; 1836 default: 1837 printf("*** ERROR: `eth%daddr' not set\n", 1838 num); 1839 break; 1840 } 1841 1842 NetStartAgain(); 1843 return 2; 1844 } 1845 /* Fall through */ 1846 default: 1847 return 0; 1848 } 1849 return 0; /* OK */ 1850 } 1851 /**********************************************************************/ 1852 1853 int 1854 NetCksumOk(uchar *ptr, int len) 1855 { 1856 return !((NetCksum(ptr, len) + 1) & 0xfffe); 1857 } 1858 1859 1860 unsigned 1861 NetCksum(uchar *ptr, int len) 1862 { 1863 ulong xsum; 1864 ushort *p = (ushort *)ptr; 1865 1866 xsum = 0; 1867 while (len-- > 0) 1868 xsum += *p++; 1869 xsum = (xsum & 0xffff) + (xsum >> 16); 1870 xsum = (xsum & 0xffff) + (xsum >> 16); 1871 return xsum & 0xffff; 1872 } 1873 1874 int 1875 NetEthHdrSize(void) 1876 { 1877 ushort myvlanid; 1878 1879 myvlanid = ntohs(NetOurVLAN); 1880 if (myvlanid == (ushort)-1) 1881 myvlanid = VLAN_NONE; 1882 1883 return ((myvlanid & VLAN_IDMASK) == VLAN_NONE) ? ETHER_HDR_SIZE : 1884 VLAN_ETHER_HDR_SIZE; 1885 } 1886 1887 int 1888 NetSetEther(volatile uchar *xet, uchar * addr, uint prot) 1889 { 1890 Ethernet_t *et = (Ethernet_t *)xet; 1891 ushort myvlanid; 1892 1893 myvlanid = ntohs(NetOurVLAN); 1894 if (myvlanid == (ushort)-1) 1895 myvlanid = VLAN_NONE; 1896 1897 memcpy(et->et_dest, addr, 6); 1898 memcpy(et->et_src, NetOurEther, 6); 1899 if ((myvlanid & VLAN_IDMASK) == VLAN_NONE) { 1900 et->et_protlen = htons(prot); 1901 return ETHER_HDR_SIZE; 1902 } else { 1903 VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)xet; 1904 1905 vet->vet_vlan_type = htons(PROT_VLAN); 1906 vet->vet_tag = htons((0 << 5) | (myvlanid & VLAN_IDMASK)); 1907 vet->vet_type = htons(prot); 1908 return VLAN_ETHER_HDR_SIZE; 1909 } 1910 } 1911 1912 void 1913 NetSetIP(volatile uchar *xip, IPaddr_t dest, int dport, int sport, int len) 1914 { 1915 IP_t *ip = (IP_t *)xip; 1916 1917 /* 1918 * If the data is an odd number of bytes, zero the 1919 * byte after the last byte so that the checksum 1920 * will work. 1921 */ 1922 if (len & 1) 1923 xip[IP_HDR_SIZE + len] = 0; 1924 1925 /* 1926 * Construct an IP and UDP header. 1927 * (need to set no fragment bit - XXX) 1928 */ 1929 /* IP_HDR_SIZE / 4 (not including UDP) */ 1930 ip->ip_hl_v = 0x45; 1931 ip->ip_tos = 0; 1932 ip->ip_len = htons(IP_HDR_SIZE + len); 1933 ip->ip_id = htons(NetIPID++); 1934 ip->ip_off = htons(IP_FLAGS_DFRAG); /* Don't fragment */ 1935 ip->ip_ttl = 255; 1936 ip->ip_p = 17; /* UDP */ 1937 ip->ip_sum = 0; 1938 /* already in network byte order */ 1939 NetCopyIP((void *)&ip->ip_src, &NetOurIP); 1940 /* - "" - */ 1941 NetCopyIP((void *)&ip->ip_dst, &dest); 1942 ip->udp_src = htons(sport); 1943 ip->udp_dst = htons(dport); 1944 ip->udp_len = htons(8 + len); 1945 ip->udp_xsum = 0; 1946 ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2); 1947 } 1948 1949 void copy_filename(char *dst, const char *src, int size) 1950 { 1951 if (*src && (*src == '"')) { 1952 ++src; 1953 --size; 1954 } 1955 1956 while ((--size > 0) && *src && (*src != '"')) 1957 *dst++ = *src++; 1958 *dst = '\0'; 1959 } 1960 1961 #if defined(CONFIG_CMD_NFS) || \ 1962 defined(CONFIG_CMD_SNTP) || \ 1963 defined(CONFIG_CMD_DNS) 1964 /* 1965 * make port a little random (1024-17407) 1966 * This keeps the math somewhat trivial to compute, and seems to work with 1967 * all supported protocols/clients/servers 1968 */ 1969 unsigned int random_port(void) 1970 { 1971 return 1024 + (get_timer(0) % 0x4000); 1972 } 1973 #endif 1974 1975 void ip_to_string(IPaddr_t x, char *s) 1976 { 1977 x = ntohl(x); 1978 sprintf(s, "%d.%d.%d.%d", 1979 (int) ((x >> 24) & 0xff), 1980 (int) ((x >> 16) & 0xff), 1981 (int) ((x >> 8) & 0xff), (int) ((x >> 0) & 0xff) 1982 ); 1983 } 1984 1985 void VLAN_to_string(ushort x, char *s) 1986 { 1987 x = ntohs(x); 1988 1989 if (x == (ushort)-1) 1990 x = VLAN_NONE; 1991 1992 if (x == VLAN_NONE) 1993 strcpy(s, "none"); 1994 else 1995 sprintf(s, "%d", x & VLAN_IDMASK); 1996 } 1997 1998 ushort string_to_VLAN(const char *s) 1999 { 2000 ushort id; 2001 2002 if (s == NULL) 2003 return htons(VLAN_NONE); 2004 2005 if (*s < '0' || *s > '9') 2006 id = VLAN_NONE; 2007 else 2008 id = (ushort)simple_strtoul(s, NULL, 10); 2009 2010 return htons(id); 2011 } 2012 2013 ushort getenv_VLAN(char *var) 2014 { 2015 return string_to_VLAN(getenv(var)); 2016 } 2017