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 int arp_timeout_check(void) 100 { 101 ulong t; 102 103 if (!net_arp_wait_packet_ip.s_addr) 104 return 0; 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_set_state(NETLOOP_FAIL); 116 } else { 117 arp_wait_timer_start = t; 118 arp_request(); 119 } 120 } 121 return 1; 122 } 123 124 void arp_receive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len) 125 { 126 struct arp_hdr *arp; 127 struct in_addr reply_ip_addr; 128 uchar *pkt; 129 int eth_hdr_size; 130 131 /* 132 * We have to deal with two types of ARP packets: 133 * - REQUEST packets will be answered by sending our 134 * IP address - if we know it. 135 * - REPLY packates are expected only after we asked 136 * for the TFTP server's or the gateway's ethernet 137 * address; so if we receive such a packet, we set 138 * the server ethernet address 139 */ 140 debug_cond(DEBUG_NET_PKT, "Got ARP\n"); 141 142 arp = (struct arp_hdr *)ip; 143 if (len < ARP_HDR_SIZE) { 144 printf("bad length %d < %d\n", len, ARP_HDR_SIZE); 145 return; 146 } 147 if (ntohs(arp->ar_hrd) != ARP_ETHER) 148 return; 149 if (ntohs(arp->ar_pro) != PROT_IP) 150 return; 151 if (arp->ar_hln != ARP_HLEN) 152 return; 153 if (arp->ar_pln != ARP_PLEN) 154 return; 155 156 if (net_ip.s_addr == 0) 157 return; 158 159 if (net_read_ip(&arp->ar_tpa).s_addr != net_ip.s_addr) 160 return; 161 162 switch (ntohs(arp->ar_op)) { 163 case ARPOP_REQUEST: 164 /* reply with our IP address */ 165 debug_cond(DEBUG_DEV_PKT, "Got ARP REQUEST, return our IP\n"); 166 pkt = (uchar *)et; 167 eth_hdr_size = net_update_ether(et, et->et_src, PROT_ARP); 168 pkt += eth_hdr_size; 169 arp->ar_op = htons(ARPOP_REPLY); 170 memcpy(&arp->ar_tha, &arp->ar_sha, ARP_HLEN); 171 net_copy_ip(&arp->ar_tpa, &arp->ar_spa); 172 memcpy(&arp->ar_sha, net_ethaddr, ARP_HLEN); 173 net_copy_ip(&arp->ar_spa, &net_ip); 174 175 #ifdef CONFIG_CMD_LINK_LOCAL 176 /* 177 * Work-around for brain-damaged Cisco equipment with 178 * arp-proxy enabled. 179 * 180 * If the requesting IP is not on our subnet, wait 5ms to 181 * reply to ARP request so that our reply will overwrite 182 * the arp-proxy's instead of the other way around. 183 */ 184 if ((net_read_ip(&arp->ar_tpa).s_addr & net_netmask.s_addr) != 185 (net_read_ip(&arp->ar_spa).s_addr & net_netmask.s_addr)) 186 udelay(5000); 187 #endif 188 net_send_packet((uchar *)et, eth_hdr_size + ARP_HDR_SIZE); 189 return; 190 191 case ARPOP_REPLY: /* arp reply */ 192 /* are we waiting for a reply */ 193 if (!net_arp_wait_packet_ip.s_addr) 194 break; 195 196 #ifdef CONFIG_KEEP_SERVERADDR 197 if (net_server_ip.s_addr == net_arp_wait_packet_ip.s_addr) { 198 char buf[20]; 199 sprintf(buf, "%pM", &arp->ar_sha); 200 setenv("serveraddr", buf); 201 } 202 #endif 203 204 reply_ip_addr = net_read_ip(&arp->ar_spa); 205 206 /* matched waiting packet's address */ 207 if (reply_ip_addr.s_addr == net_arp_wait_reply_ip.s_addr) { 208 debug_cond(DEBUG_DEV_PKT, 209 "Got ARP REPLY, set eth addr (%pM)\n", 210 arp->ar_data); 211 212 /* save address for later use */ 213 if (arp_wait_packet_ethaddr != NULL) 214 memcpy(arp_wait_packet_ethaddr, 215 &arp->ar_sha, ARP_HLEN); 216 217 net_get_arp_handler()((uchar *)arp, 0, reply_ip_addr, 218 0, len); 219 220 /* set the mac address in the waiting packet's header 221 and transmit it */ 222 memcpy(((struct ethernet_hdr *)net_tx_packet)->et_dest, 223 &arp->ar_sha, ARP_HLEN); 224 net_send_packet(net_tx_packet, arp_wait_tx_packet_size); 225 226 /* no arp request pending now */ 227 net_arp_wait_packet_ip.s_addr = 0; 228 arp_wait_tx_packet_size = 0; 229 arp_wait_packet_ethaddr = NULL; 230 } 231 return; 232 default: 233 debug("Unexpected ARP opcode 0x%x\n", 234 ntohs(arp->ar_op)); 235 return; 236 } 237 } 238