1 /* 2 * (C) Copyright 2000-2002 3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4 * 5 * See file CREDITS for list of people who contributed to this 6 * project. 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of 11 * the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21 * MA 02111-1307 USA 22 */ 23 24 #include <common.h> 25 #include <command.h> 26 #include <net.h> 27 #include "nfs.h" 28 #include "bootp.h" 29 #include "rarp.h" 30 #include "tftp.h" 31 32 #define TIMEOUT 5000UL /* Milliseconds before trying BOOTP again */ 33 #ifndef CONFIG_NET_RETRY_COUNT 34 #define TIMEOUT_COUNT 5 /* # of timeouts before giving up */ 35 #else 36 #define TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT) 37 #endif 38 39 int RarpTry; 40 41 /* 42 * Handle a RARP received packet. 43 */ 44 void rarp_receive(struct ip_udp_hdr *ip, unsigned len) 45 { 46 struct arp_hdr *arp; 47 48 debug_cond(DEBUG_NET_PKT, "Got RARP\n"); 49 arp = (struct arp_hdr *)ip; 50 if (len < ARP_HDR_SIZE) { 51 printf("bad length %d < %d\n", len, ARP_HDR_SIZE); 52 return; 53 } 54 55 if ((ntohs(arp->ar_op) != RARPOP_REPLY) || 56 (ntohs(arp->ar_hrd) != ARP_ETHER) || 57 (ntohs(arp->ar_pro) != PROT_IP) || 58 (arp->ar_hln != 6) || (arp->ar_pln != 4)) { 59 60 puts("invalid RARP header\n"); 61 } else { 62 NetCopyIP(&NetOurIP, &arp->ar_data[16]); 63 if (NetServerIP == 0) 64 NetCopyIP(&NetServerIP, &arp->ar_data[6]); 65 memcpy(NetServerEther, &arp->ar_data[0], 6); 66 debug_cond(DEBUG_DEV_PKT, "Got good RARP\n"); 67 net_auto_load(); 68 } 69 } 70 71 72 /* 73 * Timeout on BOOTP request. 74 */ 75 static void RarpTimeout(void) 76 { 77 if (RarpTry >= TIMEOUT_COUNT) { 78 puts("\nRetry count exceeded; starting again\n"); 79 NetStartAgain(); 80 } else { 81 NetSetTimeout(TIMEOUT, RarpTimeout); 82 RarpRequest(); 83 } 84 } 85 86 87 void RarpRequest(void) 88 { 89 uchar *pkt; 90 struct arp_hdr *rarp; 91 int eth_hdr_size; 92 93 printf("RARP broadcast %d\n", ++RarpTry); 94 pkt = NetTxPacket; 95 96 eth_hdr_size = NetSetEther(pkt, NetBcastAddr, PROT_RARP); 97 pkt += eth_hdr_size; 98 99 rarp = (struct arp_hdr *)pkt; 100 101 rarp->ar_hrd = htons(ARP_ETHER); 102 rarp->ar_pro = htons(PROT_IP); 103 rarp->ar_hln = 6; 104 rarp->ar_pln = 4; 105 rarp->ar_op = htons(RARPOP_REQUEST); 106 memcpy(&rarp->ar_data[0], NetOurEther, 6); /* source ET addr */ 107 memcpy(&rarp->ar_data[6], &NetOurIP, 4); /* source IP addr */ 108 /* dest ET addr = source ET addr ??*/ 109 memcpy(&rarp->ar_data[10], NetOurEther, 6); 110 /* dest IP addr set to broadcast */ 111 memset(&rarp->ar_data[16], 0xff, 4); 112 113 NetSendPacket(NetTxPacket, eth_hdr_size + ARP_HDR_SIZE); 114 115 NetSetTimeout(TIMEOUT, RarpTimeout); 116 } 117