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 * SPDX-License-Identifier: GPL-2.0 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 38 static uchar *arp_tx_packet; /* THE ARP transmit packet */ 39 static uchar arp_tx_packet_buf[PKTSIZE_ALIGN + PKTALIGN]; 40 41 void arp_init(void) 42 { 43 /* XXX problem with bss workaround */ 44 arp_wait_packet_ethaddr = NULL; 45 net_arp_wait_packet_ip.s_addr = 0; 46 net_arp_wait_reply_ip.s_addr = 0; 47 arp_wait_tx_packet_size = 0; 48 arp_tx_packet = &arp_tx_packet_buf[0] + (PKTALIGN - 1); 49 arp_tx_packet -= (ulong)arp_tx_packet % PKTALIGN; 50 } 51 52 void arp_raw_request(struct in_addr source_ip, const uchar *target_ethaddr, 53 struct in_addr target_ip) 54 { 55 uchar *pkt; 56 struct arp_hdr *arp; 57 int eth_hdr_size; 58 59 debug_cond(DEBUG_DEV_PKT, "ARP broadcast %d\n", arp_wait_try); 60 61 pkt = arp_tx_packet; 62 63 eth_hdr_size = net_set_ether(pkt, net_bcast_ethaddr, PROT_ARP); 64 pkt += eth_hdr_size; 65 66 arp = (struct arp_hdr *)pkt; 67 68 arp->ar_hrd = htons(ARP_ETHER); 69 arp->ar_pro = htons(PROT_IP); 70 arp->ar_hln = ARP_HLEN; 71 arp->ar_pln = ARP_PLEN; 72 arp->ar_op = htons(ARPOP_REQUEST); 73 74 memcpy(&arp->ar_sha, net_ethaddr, ARP_HLEN); /* source ET addr */ 75 net_write_ip(&arp->ar_spa, source_ip); /* source IP addr */ 76 memcpy(&arp->ar_tha, target_ethaddr, ARP_HLEN); /* target ET addr */ 77 net_write_ip(&arp->ar_tpa, target_ip); /* target IP addr */ 78 79 net_send_packet(arp_tx_packet, eth_hdr_size + ARP_HDR_SIZE); 80 } 81 82 void arp_request(void) 83 { 84 if ((net_arp_wait_packet_ip.s_addr & net_netmask.s_addr) != 85 (net_ip.s_addr & net_netmask.s_addr)) { 86 if (net_gateway.s_addr == 0) { 87 puts("## Warning: gatewayip needed but not set\n"); 88 net_arp_wait_reply_ip = net_arp_wait_packet_ip; 89 } else { 90 net_arp_wait_reply_ip = net_gateway; 91 } 92 } else { 93 net_arp_wait_reply_ip = net_arp_wait_packet_ip; 94 } 95 96 arp_raw_request(net_ip, net_null_ethaddr, net_arp_wait_reply_ip); 97 } 98 99 void arp_timeout_check(void) 100 { 101 ulong t; 102 103 if (!net_arp_wait_packet_ip.s_addr) 104 return; 105 106 t = get_timer(0); 107 108 /* check for arp timeout */ 109 if ((t - arp_wait_timer_start) > ARP_TIMEOUT) { 110 arp_wait_try++; 111 112 if (arp_wait_try >= ARP_TIMEOUT_COUNT) { 113 puts("\nARP Retry count exceeded; starting again\n"); 114 arp_wait_try = 0; 115 net_start_again(); 116 } else { 117 arp_wait_timer_start = t; 118 arp_request(); 119 } 120 } 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 uchar *pkt; 128 int eth_hdr_size; 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 pkt = (uchar *)et; 166 eth_hdr_size = net_update_ether(et, et->et_src, PROT_ARP); 167 pkt += eth_hdr_size; 168 arp->ar_op = htons(ARPOP_REPLY); 169 memcpy(&arp->ar_tha, &arp->ar_sha, ARP_HLEN); 170 net_copy_ip(&arp->ar_tpa, &arp->ar_spa); 171 memcpy(&arp->ar_sha, net_ethaddr, ARP_HLEN); 172 net_copy_ip(&arp->ar_spa, &net_ip); 173 174 #ifdef CONFIG_CMD_LINK_LOCAL 175 /* 176 * Work-around for brain-damaged Cisco equipment with 177 * arp-proxy enabled. 178 * 179 * If the requesting IP is not on our subnet, wait 5ms to 180 * reply to ARP request so that our reply will overwrite 181 * the arp-proxy's instead of the other way around. 182 */ 183 if ((net_read_ip(&arp->ar_tpa).s_addr & net_netmask.s_addr) != 184 (net_read_ip(&arp->ar_spa).s_addr & net_netmask.s_addr)) 185 udelay(5000); 186 #endif 187 net_send_packet((uchar *)et, eth_hdr_size + ARP_HDR_SIZE); 188 return; 189 190 case ARPOP_REPLY: /* arp reply */ 191 /* are we waiting for a reply */ 192 if (!net_arp_wait_packet_ip.s_addr) 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 setenv("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