| lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 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 | #include <common.h> | 
|  | 12 |  | 
|  | 13 | #include "arp.h" | 
|  | 14 | extern uint32_t g_gmac_init_overtime; | 
|  | 15 | extern ulong  time_over; | 
|  | 16 | #ifndef	CONFIG_ARP_TIMEOUT | 
|  | 17 | /* Milliseconds before trying ARP again */ | 
|  | 18 |  | 
|  | 19 | # define ARP_TIMEOUT	5000UL | 
|  | 20 |  | 
|  | 21 | //uint32_t  ARP_TIMEOUT = g_gmac_init_overtime*5000/3UL; | 
|  | 22 |  | 
|  | 23 | #else | 
|  | 24 | # define ARP_TIMEOUT		CONFIG_ARP_TIMEOUT | 
|  | 25 | #endif | 
|  | 26 |  | 
|  | 27 |  | 
|  | 28 | #ifndef	CONFIG_NET_RETRY_COUNT | 
|  | 29 | # define ARP_TIMEOUT_COUNT	5	/* # of timeouts before giving up  */ | 
|  | 30 | #else | 
|  | 31 | # define ARP_TIMEOUT_COUNT	CONFIG_NET_RETRY_COUNT | 
|  | 32 | #endif | 
|  | 33 |  | 
|  | 34 | IPaddr_t	NetArpWaitPacketIP; | 
|  | 35 | static IPaddr_t	NetArpWaitReplyIP; | 
|  | 36 | /* MAC address of waiting packet's destination */ | 
|  | 37 | uchar	       *NetArpWaitPacketMAC; | 
|  | 38 | int		NetArpWaitTxPacketSize; | 
|  | 39 | ulong		NetArpWaitTimerStart; | 
|  | 40 | int		NetArpWaitTry; | 
|  | 41 |  | 
|  | 42 | static uchar   *NetArpTxPacket;	/* THE ARP transmit packet */ | 
|  | 43 | static uchar	NetArpPacketBuf[PKTSIZE_ALIGN + PKTALIGN]; | 
|  | 44 | int arp_cnt; | 
|  | 45 |  | 
|  | 46 | void ArpInit(void) | 
|  | 47 | { | 
|  | 48 | /* XXX problem with bss workaround */ | 
|  | 49 | NetArpWaitPacketMAC = NULL; | 
|  | 50 | NetArpWaitPacketIP = 0; | 
|  | 51 | NetArpWaitReplyIP = 0; | 
|  | 52 | NetArpWaitTxPacketSize = 0; | 
|  | 53 | NetArpTxPacket = &NetArpPacketBuf[0] + (PKTALIGN - 1); | 
|  | 54 | NetArpTxPacket -= (ulong)NetArpTxPacket % PKTALIGN; | 
|  | 55 | } | 
|  | 56 |  | 
|  | 57 | void arp_raw_request(IPaddr_t sourceIP, const uchar *targetEther, | 
|  | 58 | IPaddr_t targetIP) | 
|  | 59 | { | 
|  | 60 | uchar *pkt; | 
|  | 61 | struct arp_hdr *arp; | 
|  | 62 | int eth_hdr_size; | 
|  | 63 |  | 
|  | 64 | //debug_cond(DEBUG_DEV_PKT, "ARP broadcast %d\n", NetArpWaitTry); | 
|  | 65 | printf("ARP broadcast %d\n", NetArpWaitTry); | 
|  | 66 | ++arp_cnt; | 
|  | 67 |  | 
|  | 68 | pkt = NetArpTxPacket; | 
|  | 69 |  | 
|  | 70 | eth_hdr_size = NetSetEther(pkt, NetBcastAddr, PROT_ARP); | 
|  | 71 | pkt += eth_hdr_size; | 
|  | 72 |  | 
|  | 73 | arp = (struct arp_hdr *) pkt; | 
|  | 74 |  | 
|  | 75 | arp->ar_hrd = htons(ARP_ETHER); | 
|  | 76 | arp->ar_pro = htons(PROT_IP); | 
|  | 77 | arp->ar_hln = ARP_HLEN; | 
|  | 78 | arp->ar_pln = ARP_PLEN; | 
|  | 79 | arp->ar_op = htons(ARPOP_REQUEST); | 
|  | 80 |  | 
|  | 81 | memcpy(&arp->ar_sha, NetOurEther, ARP_HLEN);	/* source ET addr */ | 
|  | 82 | NetWriteIP(&arp->ar_spa, sourceIP);		/* source IP addr */ | 
|  | 83 | memcpy(&arp->ar_tha, targetEther, ARP_HLEN);	/* target ET addr */ | 
|  | 84 | NetWriteIP(&arp->ar_tpa, targetIP);		/* target IP addr */ | 
|  | 85 |  | 
|  | 86 | NetSendPacket(NetArpTxPacket, eth_hdr_size + ARP_HDR_SIZE); | 
|  | 87 | } | 
|  | 88 |  | 
|  | 89 | void ArpRequest(void) | 
|  | 90 | { | 
|  | 91 | if ((NetArpWaitPacketIP & NetOurSubnetMask) != | 
|  | 92 | (NetOurIP & NetOurSubnetMask)) { | 
|  | 93 | if (NetOurGatewayIP == 0) { | 
|  | 94 | puts("## Warning: gatewayip needed but not set\n"); | 
|  | 95 | NetArpWaitReplyIP = NetArpWaitPacketIP; | 
|  | 96 | } else { | 
|  | 97 | NetArpWaitReplyIP = NetOurGatewayIP; | 
|  | 98 | } | 
|  | 99 | } else { | 
|  | 100 | NetArpWaitReplyIP = NetArpWaitPacketIP; | 
|  | 101 | } | 
|  | 102 |  | 
|  | 103 | arp_raw_request(NetOurIP, NetEtherNullAddr, NetArpWaitReplyIP); | 
|  | 104 | } | 
|  | 105 |  | 
|  | 106 | void ArpTimeoutCheck(void) | 
|  | 107 | { | 
|  | 108 | ulong t; | 
|  | 109 |  | 
|  | 110 | if (!NetArpWaitPacketIP) | 
|  | 111 | return; | 
|  | 112 |  | 
|  | 113 | t = get_timer(0); | 
|  | 114 |  | 
|  | 115 | /* check for arp timeout */ | 
|  | 116 | if ((t - NetArpWaitTimerStart) >  time_over) { | 
|  | 117 | //++arp_cnt; | 
|  | 118 | NetArpWaitTry++; | 
|  | 119 |  | 
|  | 120 | if (NetArpWaitTry >= ARP_TIMEOUT_COUNT) { | 
|  | 121 | puts("\nARP Retry count exceeded; starting again\n"); | 
|  | 122 | NetArpWaitTry = 0; | 
|  | 123 | NetStartAgain(); | 
|  | 124 | } else { | 
|  | 125 | NetArpWaitTimerStart = t; | 
|  | 126 | ArpRequest(); | 
|  | 127 |  | 
|  | 128 | } | 
|  | 129 | } | 
|  | 130 | } | 
|  | 131 |  | 
|  | 132 | void ArpReceive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len) | 
|  | 133 | { | 
|  | 134 | struct arp_hdr *arp; | 
|  | 135 | IPaddr_t reply_ip_addr; | 
|  | 136 | uchar *pkt; | 
|  | 137 | int eth_hdr_size; | 
|  | 138 |  | 
|  | 139 | /* | 
|  | 140 | * We have to deal with two types of ARP packets: | 
|  | 141 | * - REQUEST packets will be answered by sending  our | 
|  | 142 | *   IP address - if we know it. | 
|  | 143 | * - REPLY packates are expected only after we asked | 
|  | 144 | *   for the TFTP server's or the gateway's ethernet | 
|  | 145 | *   address; so if we receive such a packet, we set | 
|  | 146 | *   the server ethernet address | 
|  | 147 | */ | 
|  | 148 | debug_cond(DEBUG_NET_PKT, "Got ARP\n"); | 
|  | 149 |  | 
|  | 150 | arp = (struct arp_hdr *)ip; | 
|  | 151 | if (len < ARP_HDR_SIZE) { | 
|  | 152 | printf("bad length %d < %d\n", len, ARP_HDR_SIZE); | 
|  | 153 | return; | 
|  | 154 | } | 
|  | 155 | if (ntohs(arp->ar_hrd) != ARP_ETHER) | 
|  | 156 | return; | 
|  | 157 | if (ntohs(arp->ar_pro) != PROT_IP) | 
|  | 158 | return; | 
|  | 159 | if (arp->ar_hln != ARP_HLEN) | 
|  | 160 | return; | 
|  | 161 | if (arp->ar_pln != ARP_PLEN) | 
|  | 162 | return; | 
|  | 163 |  | 
|  | 164 | if (NetOurIP == 0) | 
|  | 165 | return; | 
|  | 166 |  | 
|  | 167 | if (NetReadIP(&arp->ar_tpa) != NetOurIP) | 
|  | 168 | return; | 
|  | 169 |  | 
|  | 170 | switch (ntohs(arp->ar_op)) { | 
|  | 171 | case ARPOP_REQUEST: | 
|  | 172 | /* reply with our IP address */ | 
|  | 173 | //debug_cond(DEBUG_DEV_PKT, "Got ARP REQUEST, return our IP\n"); | 
|  | 174 | printf("Got ARP REQUEST, return our IP\n"); | 
|  | 175 | pkt = (uchar *)et; | 
|  | 176 | eth_hdr_size = net_update_ether(et, et->et_src, PROT_ARP); | 
|  | 177 | pkt += eth_hdr_size; | 
|  | 178 | arp->ar_op = htons(ARPOP_REPLY); | 
|  | 179 | memcpy(&arp->ar_tha, &arp->ar_sha, ARP_HLEN); | 
|  | 180 | NetCopyIP(&arp->ar_tpa, &arp->ar_spa); | 
|  | 181 | memcpy(&arp->ar_sha, NetOurEther, ARP_HLEN); | 
|  | 182 | NetCopyIP(&arp->ar_spa, &NetOurIP); | 
|  | 183 |  | 
|  | 184 | #ifdef CONFIG_CMD_LINK_LOCAL | 
|  | 185 | /* | 
|  | 186 | * Work-around for brain-damaged Cisco equipment with | 
|  | 187 | *   arp-proxy enabled. | 
|  | 188 | * | 
|  | 189 | *   If the requesting IP is not on our subnet, wait 5ms to | 
|  | 190 | *   reply to ARP request so that our reply will overwrite | 
|  | 191 | *   the arp-proxy's instead of the other way around. | 
|  | 192 | */ | 
|  | 193 | if ((NetReadIP(&arp->ar_tpa) & NetOurSubnetMask) != | 
|  | 194 | (NetReadIP(&arp->ar_spa) & NetOurSubnetMask)) | 
|  | 195 | udelay(5000); | 
|  | 196 | #endif | 
|  | 197 | NetSendPacket((uchar *)et, eth_hdr_size + ARP_HDR_SIZE); | 
|  | 198 | return; | 
|  | 199 |  | 
|  | 200 | case ARPOP_REPLY:		/* arp reply */ | 
|  | 201 | /* are we waiting for a reply */ | 
|  | 202 | if (!NetArpWaitPacketIP) | 
|  | 203 | break; | 
|  | 204 |  | 
|  | 205 | #ifdef CONFIG_KEEP_SERVERADDR | 
|  | 206 | if (NetServerIP == NetArpWaitPacketIP) { | 
|  | 207 | char buf[20]; | 
|  | 208 | sprintf(buf, "%pM", &arp->ar_sha); | 
|  | 209 | setenv("serveraddr", buf); | 
|  | 210 | } | 
|  | 211 | #endif | 
|  | 212 |  | 
|  | 213 | reply_ip_addr = NetReadIP(&arp->ar_spa); | 
|  | 214 |  | 
|  | 215 | /* matched waiting packet's address */ | 
|  | 216 | if (reply_ip_addr == NetArpWaitReplyIP) | 
|  | 217 | { | 
|  | 218 | //debug_cond(DEBUG_DEV_PKT, | 
|  | 219 | //	"Got ARP REPLY, set eth addr (%pM)\n", | 
|  | 220 | //	arp->ar_data); | 
|  | 221 | printf("Got ARP REPLY, set eth addr (%pM)\n",arp->ar_data); | 
|  | 222 | /* save address for later use */ | 
|  | 223 | if (NetArpWaitPacketMAC != NULL) | 
|  | 224 | memcpy(NetArpWaitPacketMAC, | 
|  | 225 | &arp->ar_sha, ARP_HLEN); | 
|  | 226 |  | 
|  | 227 | net_get_arp_handler()((uchar *)arp, 0, reply_ip_addr, 0, len);//??????? | 
|  | 228 |  | 
|  | 229 | /* set the mac address in the waiting packet's header | 
|  | 230 | and transmit it */ | 
|  | 231 | memcpy(((struct ethernet_hdr *)NetTxPacket)->et_dest, | 
|  | 232 | &arp->ar_sha, ARP_HLEN); | 
|  | 233 | NetSendPacket(NetTxPacket, NetArpWaitTxPacketSize); | 
|  | 234 |  | 
|  | 235 | /* no arp request pending now */ | 
|  | 236 | NetArpWaitPacketIP = 0; | 
|  | 237 | NetArpWaitTxPacketSize = 0; | 
|  | 238 | NetArpWaitPacketMAC = NULL; | 
|  | 239 |  | 
|  | 240 | } | 
|  | 241 | return; | 
|  | 242 | default: | 
|  | 243 | //debug("Unexpected ARP opcode 0x%x\n", | 
|  | 244 | //ntohs(arp->ar_op)); | 
|  | 245 | printf("Unexpected ARP opcode 0x%x\n",ntohs(arp->ar_op)); | 
|  | 246 | return; | 
|  | 247 | } | 
|  | 248 | } |