1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copied from Linux Monitor (LiMon) - Networking. 4 * 5 * Copyright 1994 - 2000 Neil Russell. 6 * (See License) 7 * Copyright 2000 Roland Borde 8 * Copyright 2000 Paolo Scaffardi 9 * Copyright 2000-2002 Wolfgang Denk, wd@denx.de 10 */ 11 12 #include <common.h> 13 14 #include "arp.h" 15 16 #ifndef CONFIG_ARP_TIMEOUT 17 /* Milliseconds before trying ARP again */ 18 # define ARP_TIMEOUT 5000UL 19 #else 20 # define ARP_TIMEOUT CONFIG_ARP_TIMEOUT 21 #endif 22 23 24 #ifndef CONFIG_NET_RETRY_COUNT 25 # define ARP_TIMEOUT_COUNT 5 /* # of timeouts before giving up */ 26 #else 27 # define ARP_TIMEOUT_COUNT CONFIG_NET_RETRY_COUNT 28 #endif 29 30 struct in_addr net_arp_wait_packet_ip; 31 static struct in_addr net_arp_wait_reply_ip; 32 /* MAC address of waiting packet's destination */ 33 uchar *arp_wait_packet_ethaddr; 34 int arp_wait_tx_packet_size; 35 ulong arp_wait_timer_start; 36 int arp_wait_try; 37 uchar *arp_tx_packet; /* THE ARP transmit packet */ 38 static uchar arp_tx_packet_buf[PKTSIZE_ALIGN + PKTALIGN]; 39 40 void arp_init(void) 41 { 42 /* XXX problem with bss workaround */ 43 arp_wait_packet_ethaddr = NULL; 44 net_arp_wait_packet_ip.s_addr = 0; 45 net_arp_wait_reply_ip.s_addr = 0; 46 arp_wait_tx_packet_size = 0; 47 arp_tx_packet = &arp_tx_packet_buf[0] + (PKTALIGN - 1); 48 arp_tx_packet -= (ulong)arp_tx_packet % PKTALIGN; 49 } 50 51 void arp_raw_request(struct in_addr source_ip, const uchar *target_ethaddr, 52 struct in_addr target_ip) 53 { 54 uchar *pkt; 55 struct arp_hdr *arp; 56 int eth_hdr_size; 57 58 debug_cond(DEBUG_DEV_PKT, "ARP broadcast %d\n", arp_wait_try); 59 60 pkt = arp_tx_packet; 61 62 eth_hdr_size = net_set_ether(pkt, net_bcast_ethaddr, PROT_ARP); 63 pkt += eth_hdr_size; 64 65 arp = (struct arp_hdr *)pkt; 66 67 arp->ar_hrd = htons(ARP_ETHER); 68 arp->ar_pro = htons(PROT_IP); 69 arp->ar_hln = ARP_HLEN; 70 arp->ar_pln = ARP_PLEN; 71 arp->ar_op = htons(ARPOP_REQUEST); 72 73 memcpy(&arp->ar_sha, net_ethaddr, ARP_HLEN); /* source ET addr */ 74 net_write_ip(&arp->ar_spa, source_ip); /* source IP addr */ 75 memcpy(&arp->ar_tha, target_ethaddr, ARP_HLEN); /* target ET addr */ 76 net_write_ip(&arp->ar_tpa, target_ip); /* target IP addr */ 77 78 net_send_packet(arp_tx_packet, eth_hdr_size + ARP_HDR_SIZE); 79 } 80 81 void arp_request(void) 82 { 83 if ((net_arp_wait_packet_ip.s_addr & net_netmask.s_addr) != 84 (net_ip.s_addr & net_netmask.s_addr)) { 85 if (net_gateway.s_addr == 0) { 86 puts("## Warning: gatewayip needed but not set\n"); 87 net_arp_wait_reply_ip = net_arp_wait_packet_ip; 88 } else { 89 net_arp_wait_reply_ip = net_gateway; 90 } 91 } else { 92 net_arp_wait_reply_ip = net_arp_wait_packet_ip; 93 } 94 95 arp_raw_request(net_ip, net_null_ethaddr, net_arp_wait_reply_ip); 96 } 97 98 int arp_timeout_check(void) 99 { 100 ulong t; 101 102 if (!arp_is_waiting()) 103 return 0; 104 105 t = get_timer(0); 106 107 /* check for arp timeout */ 108 if ((t - arp_wait_timer_start) > ARP_TIMEOUT) { 109 arp_wait_try++; 110 111 if (arp_wait_try >= ARP_TIMEOUT_COUNT) { 112 puts("\nARP Retry count exceeded; starting again\n"); 113 arp_wait_try = 0; 114 net_set_state(NETLOOP_FAIL); 115 } else { 116 arp_wait_timer_start = t; 117 arp_request(); 118 } 119 } 120 return 1; 121 } 122 123 void arp_receive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len) 124 { 125 struct arp_hdr *arp; 126 struct in_addr reply_ip_addr; 127 int eth_hdr_size; 128 uchar *tx_packet; 129 130 /* 131 * We have to deal with two types of ARP packets: 132 * - REQUEST packets will be answered by sending our 133 * IP address - if we know it. 134 * - REPLY packates are expected only after we asked 135 * for the TFTP server's or the gateway's ethernet 136 * address; so if we receive such a packet, we set 137 * the server ethernet address 138 */ 139 debug_cond(DEBUG_NET_PKT, "Got ARP\n"); 140 141 arp = (struct arp_hdr *)ip; 142 if (len < ARP_HDR_SIZE) { 143 printf("bad length %d < %d\n", len, ARP_HDR_SIZE); 144 return; 145 } 146 if (ntohs(arp->ar_hrd) != ARP_ETHER) 147 return; 148 if (ntohs(arp->ar_pro) != PROT_IP) 149 return; 150 if (arp->ar_hln != ARP_HLEN) 151 return; 152 if (arp->ar_pln != ARP_PLEN) 153 return; 154 155 if (net_ip.s_addr == 0) 156 return; 157 158 if (net_read_ip(&arp->ar_tpa).s_addr != net_ip.s_addr) 159 return; 160 161 switch (ntohs(arp->ar_op)) { 162 case ARPOP_REQUEST: 163 /* reply with our IP address */ 164 debug_cond(DEBUG_DEV_PKT, "Got ARP REQUEST, return our IP\n"); 165 eth_hdr_size = net_update_ether(et, et->et_src, PROT_ARP); 166 arp->ar_op = htons(ARPOP_REPLY); 167 memcpy(&arp->ar_tha, &arp->ar_sha, ARP_HLEN); 168 net_copy_ip(&arp->ar_tpa, &arp->ar_spa); 169 memcpy(&arp->ar_sha, net_ethaddr, ARP_HLEN); 170 net_copy_ip(&arp->ar_spa, &net_ip); 171 172 #ifdef CONFIG_CMD_LINK_LOCAL 173 /* 174 * Work-around for brain-damaged Cisco equipment with 175 * arp-proxy enabled. 176 * 177 * If the requesting IP is not on our subnet, wait 5ms to 178 * reply to ARP request so that our reply will overwrite 179 * the arp-proxy's instead of the other way around. 180 */ 181 if ((net_read_ip(&arp->ar_tpa).s_addr & net_netmask.s_addr) != 182 (net_read_ip(&arp->ar_spa).s_addr & net_netmask.s_addr)) 183 udelay(5000); 184 #endif 185 tx_packet = net_get_async_tx_pkt_buf(); 186 memcpy(tx_packet, et, eth_hdr_size + ARP_HDR_SIZE); 187 net_send_packet(tx_packet, eth_hdr_size + ARP_HDR_SIZE); 188 return; 189 190 case ARPOP_REPLY: /* arp reply */ 191 /* are we waiting for a reply? */ 192 if (!arp_is_waiting()) 193 break; 194 195 #ifdef CONFIG_KEEP_SERVERADDR 196 if (net_server_ip.s_addr == net_arp_wait_packet_ip.s_addr) { 197 char buf[20]; 198 sprintf(buf, "%pM", &arp->ar_sha); 199 env_set("serveraddr", buf); 200 } 201 #endif 202 203 reply_ip_addr = net_read_ip(&arp->ar_spa); 204 205 /* matched waiting packet's address */ 206 if (reply_ip_addr.s_addr == net_arp_wait_reply_ip.s_addr) { 207 debug_cond(DEBUG_DEV_PKT, 208 "Got ARP REPLY, set eth addr (%pM)\n", 209 arp->ar_data); 210 211 /* save address for later use */ 212 if (arp_wait_packet_ethaddr != NULL) 213 memcpy(arp_wait_packet_ethaddr, 214 &arp->ar_sha, ARP_HLEN); 215 216 net_get_arp_handler()((uchar *)arp, 0, reply_ip_addr, 217 0, len); 218 219 /* set the mac address in the waiting packet's header 220 and transmit it */ 221 memcpy(((struct ethernet_hdr *)net_tx_packet)->et_dest, 222 &arp->ar_sha, ARP_HLEN); 223 net_send_packet(net_tx_packet, arp_wait_tx_packet_size); 224 225 /* no arp request pending now */ 226 net_arp_wait_packet_ip.s_addr = 0; 227 arp_wait_tx_packet_size = 0; 228 arp_wait_packet_ethaddr = NULL; 229 } 230 return; 231 default: 232 debug("Unexpected ARP opcode 0x%x\n", 233 ntohs(arp->ar_op)); 234 return; 235 } 236 } 237 238 bool arp_is_waiting(void) 239 { 240 return !!net_arp_wait_packet_ip.s_addr; 241 } 242