Blame view

net/arp.c 6.21 KB
f739fcd83   Tom Rini   SPDX: Convert a f...
1
  // SPDX-License-Identifier: GPL-2.0
d280d3f43   Joe Hershberger   net: Move ARP out...
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
  /*
   *	Copied from Linux Monitor (LiMon) - Networking.
   *
   *	Copyright 1994 - 2000 Neil Russell.
   *	(See License)
   *	Copyright 2000 Roland Borde
   *	Copyright 2000 Paolo Scaffardi
   *	Copyright 2000-2002 Wolfgang Denk, wd@denx.de
   */
  
  #include <common.h>
  
  #include "arp.h"
  
  #ifndef	CONFIG_ARP_TIMEOUT
  /* Milliseconds before trying ARP again */
  # define ARP_TIMEOUT		5000UL
  #else
  # define ARP_TIMEOUT		CONFIG_ARP_TIMEOUT
  #endif
  
  
  #ifndef	CONFIG_NET_RETRY_COUNT
  # define ARP_TIMEOUT_COUNT	5	/* # of timeouts before giving up  */
  #else
  # define ARP_TIMEOUT_COUNT	CONFIG_NET_RETRY_COUNT
  #endif
049a95a77   Joe Hershberger   net: cosmetic: Ch...
29
30
  struct in_addr net_arp_wait_packet_ip;
  static struct in_addr net_arp_wait_reply_ip;
d280d3f43   Joe Hershberger   net: Move ARP out...
31
  /* MAC address of waiting packet's destination */
85d25e0e7   Joe Hershberger   net: cosmetic: Cl...
32
33
34
35
  uchar	       *arp_wait_packet_ethaddr;
  int		arp_wait_tx_packet_size;
  ulong		arp_wait_timer_start;
  int		arp_wait_try;
ac3f26cc1   Joe Hershberger   net: Don't overwr...
36
  uchar	       *arp_tx_packet; /* THE ARP transmit packet */
85d25e0e7   Joe Hershberger   net: cosmetic: Cl...
37
  static uchar	arp_tx_packet_buf[PKTSIZE_ALIGN + PKTALIGN];
e94070c44   Joe Hershberger   net: Don't copy e...
38

85d25e0e7   Joe Hershberger   net: cosmetic: Cl...
39
  void arp_init(void)
d280d3f43   Joe Hershberger   net: Move ARP out...
40
41
  {
  	/* XXX problem with bss workaround */
85d25e0e7   Joe Hershberger   net: cosmetic: Cl...
42
  	arp_wait_packet_ethaddr = NULL;
049a95a77   Joe Hershberger   net: cosmetic: Ch...
43
44
  	net_arp_wait_packet_ip.s_addr = 0;
  	net_arp_wait_reply_ip.s_addr = 0;
85d25e0e7   Joe Hershberger   net: cosmetic: Cl...
45
46
47
  	arp_wait_tx_packet_size = 0;
  	arp_tx_packet = &arp_tx_packet_buf[0] + (PKTALIGN - 1);
  	arp_tx_packet -= (ulong)arp_tx_packet % PKTALIGN;
d280d3f43   Joe Hershberger   net: Move ARP out...
48
  }
85d25e0e7   Joe Hershberger   net: cosmetic: Cl...
49
  void arp_raw_request(struct in_addr source_ip, const uchar *target_ethaddr,
049a95a77   Joe Hershberger   net: cosmetic: Ch...
50
  	struct in_addr target_ip)
d280d3f43   Joe Hershberger   net: Move ARP out...
51
52
  {
  	uchar *pkt;
738853bb6   Joe Hershberger   net: cosmetic: Un...
53
  	struct arp_hdr *arp;
00f33268a   Joe Hershberger   net: Refactor pac...
54
  	int eth_hdr_size;
d280d3f43   Joe Hershberger   net: Move ARP out...
55

85d25e0e7   Joe Hershberger   net: cosmetic: Cl...
56
57
  	debug_cond(DEBUG_DEV_PKT, "ARP broadcast %d
  ", arp_wait_try);
d280d3f43   Joe Hershberger   net: Move ARP out...
58

85d25e0e7   Joe Hershberger   net: cosmetic: Cl...
59
  	pkt = arp_tx_packet;
d280d3f43   Joe Hershberger   net: Move ARP out...
60

1203fccee   Joe Hershberger   net: cosmetic: Cl...
61
  	eth_hdr_size = net_set_ether(pkt, net_bcast_ethaddr, PROT_ARP);
00f33268a   Joe Hershberger   net: Refactor pac...
62
  	pkt += eth_hdr_size;
d280d3f43   Joe Hershberger   net: Move ARP out...
63

85d25e0e7   Joe Hershberger   net: cosmetic: Cl...
64
  	arp = (struct arp_hdr *)pkt;
d280d3f43   Joe Hershberger   net: Move ARP out...
65
66
67
  
  	arp->ar_hrd = htons(ARP_ETHER);
  	arp->ar_pro = htons(PROT_IP);
674bb2498   Joe Hershberger   net: cosmetic: Re...
68
69
  	arp->ar_hln = ARP_HLEN;
  	arp->ar_pln = ARP_PLEN;
d280d3f43   Joe Hershberger   net: Move ARP out...
70
  	arp->ar_op = htons(ARPOP_REQUEST);
0adb5b761   Joe Hershberger   net: cosmetic: Na...
71
  	memcpy(&arp->ar_sha, net_ethaddr, ARP_HLEN);	/* source ET addr */
049a95a77   Joe Hershberger   net: cosmetic: Ch...
72
  	net_write_ip(&arp->ar_spa, source_ip);		/* source IP addr */
85d25e0e7   Joe Hershberger   net: cosmetic: Cl...
73
  	memcpy(&arp->ar_tha, target_ethaddr, ARP_HLEN);	/* target ET addr */
049a95a77   Joe Hershberger   net: cosmetic: Ch...
74
  	net_write_ip(&arp->ar_tpa, target_ip);		/* target IP addr */
228041893   Joe Hershberger   net: Separate Arp...
75

85d25e0e7   Joe Hershberger   net: cosmetic: Cl...
76
  	net_send_packet(arp_tx_packet, eth_hdr_size + ARP_HDR_SIZE);
228041893   Joe Hershberger   net: Separate Arp...
77
  }
85d25e0e7   Joe Hershberger   net: cosmetic: Cl...
78
  void arp_request(void)
228041893   Joe Hershberger   net: Separate Arp...
79
  {
049a95a77   Joe Hershberger   net: cosmetic: Ch...
80
81
82
  	if ((net_arp_wait_packet_ip.s_addr & net_netmask.s_addr) !=
  	    (net_ip.s_addr & net_netmask.s_addr)) {
  		if (net_gateway.s_addr == 0) {
d280d3f43   Joe Hershberger   net: Move ARP out...
83
84
  			puts("## Warning: gatewayip needed but not set
  ");
049a95a77   Joe Hershberger   net: cosmetic: Ch...
85
  			net_arp_wait_reply_ip = net_arp_wait_packet_ip;
d280d3f43   Joe Hershberger   net: Move ARP out...
86
  		} else {
049a95a77   Joe Hershberger   net: cosmetic: Ch...
87
  			net_arp_wait_reply_ip = net_gateway;
d280d3f43   Joe Hershberger   net: Move ARP out...
88
89
  		}
  	} else {
049a95a77   Joe Hershberger   net: cosmetic: Ch...
90
  		net_arp_wait_reply_ip = net_arp_wait_packet_ip;
d280d3f43   Joe Hershberger   net: Move ARP out...
91
  	}
0adb5b761   Joe Hershberger   net: cosmetic: Na...
92
  	arp_raw_request(net_ip, net_null_ethaddr, net_arp_wait_reply_ip);
d280d3f43   Joe Hershberger   net: Move ARP out...
93
  }
45b47734a   Stefan Brüns   net/arp: account ...
94
  int arp_timeout_check(void)
d280d3f43   Joe Hershberger   net: Move ARP out...
95
96
  {
  	ulong t;
3f02c98bd   Joe Hershberger   net: Add an acces...
97
  	if (!arp_is_waiting())
45b47734a   Stefan Brüns   net/arp: account ...
98
  		return 0;
d280d3f43   Joe Hershberger   net: Move ARP out...
99
100
101
102
  
  	t = get_timer(0);
  
  	/* check for arp timeout */
85d25e0e7   Joe Hershberger   net: cosmetic: Cl...
103
104
  	if ((t - arp_wait_timer_start) > ARP_TIMEOUT) {
  		arp_wait_try++;
d280d3f43   Joe Hershberger   net: Move ARP out...
105

85d25e0e7   Joe Hershberger   net: cosmetic: Cl...
106
  		if (arp_wait_try >= ARP_TIMEOUT_COUNT) {
d280d3f43   Joe Hershberger   net: Move ARP out...
107
108
109
  			puts("
  ARP Retry count exceeded; starting again
  ");
85d25e0e7   Joe Hershberger   net: cosmetic: Cl...
110
  			arp_wait_try = 0;
943231119   Stefan Brüns   net/arp: Do not r...
111
  			net_set_state(NETLOOP_FAIL);
d280d3f43   Joe Hershberger   net: Move ARP out...
112
  		} else {
85d25e0e7   Joe Hershberger   net: cosmetic: Cl...
113
114
  			arp_wait_timer_start = t;
  			arp_request();
d280d3f43   Joe Hershberger   net: Move ARP out...
115
116
  		}
  	}
45b47734a   Stefan Brüns   net/arp: account ...
117
  	return 1;
d280d3f43   Joe Hershberger   net: Move ARP out...
118
  }
85d25e0e7   Joe Hershberger   net: cosmetic: Cl...
119
  void arp_receive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len)
d280d3f43   Joe Hershberger   net: Move ARP out...
120
  {
738853bb6   Joe Hershberger   net: cosmetic: Un...
121
  	struct arp_hdr *arp;
049a95a77   Joe Hershberger   net: cosmetic: Ch...
122
  	struct in_addr reply_ip_addr;
00f33268a   Joe Hershberger   net: Refactor pac...
123
  	int eth_hdr_size;
ac3f26cc1   Joe Hershberger   net: Don't overwr...
124
  	uchar *tx_packet;
d280d3f43   Joe Hershberger   net: Move ARP out...
125
126
127
128
129
130
131
132
133
134
  
  	/*
  	 * We have to deal with two types of ARP packets:
  	 * - REQUEST packets will be answered by sending  our
  	 *   IP address - if we know it.
  	 * - REPLY packates are expected only after we asked
  	 *   for the TFTP server's or the gateway's ethernet
  	 *   address; so if we receive such a packet, we set
  	 *   the server ethernet address
  	 */
4ef8d53ca   Joe Hershberger   net: Allow filter...
135
136
  	debug_cond(DEBUG_NET_PKT, "Got ARP
  ");
d280d3f43   Joe Hershberger   net: Move ARP out...
137

738853bb6   Joe Hershberger   net: cosmetic: Un...
138
  	arp = (struct arp_hdr *)ip;
d280d3f43   Joe Hershberger   net: Move ARP out...
139
140
141
142
143
144
145
146
147
  	if (len < ARP_HDR_SIZE) {
  		printf("bad length %d < %d
  ", len, ARP_HDR_SIZE);
  		return;
  	}
  	if (ntohs(arp->ar_hrd) != ARP_ETHER)
  		return;
  	if (ntohs(arp->ar_pro) != PROT_IP)
  		return;
674bb2498   Joe Hershberger   net: cosmetic: Re...
148
  	if (arp->ar_hln != ARP_HLEN)
d280d3f43   Joe Hershberger   net: Move ARP out...
149
  		return;
674bb2498   Joe Hershberger   net: cosmetic: Re...
150
  	if (arp->ar_pln != ARP_PLEN)
d280d3f43   Joe Hershberger   net: Move ARP out...
151
  		return;
049a95a77   Joe Hershberger   net: cosmetic: Ch...
152
  	if (net_ip.s_addr == 0)
d280d3f43   Joe Hershberger   net: Move ARP out...
153
  		return;
049a95a77   Joe Hershberger   net: cosmetic: Ch...
154
  	if (net_read_ip(&arp->ar_tpa).s_addr != net_ip.s_addr)
d280d3f43   Joe Hershberger   net: Move ARP out...
155
156
157
158
159
  		return;
  
  	switch (ntohs(arp->ar_op)) {
  	case ARPOP_REQUEST:
  		/* reply with our IP address */
4ef8d53ca   Joe Hershberger   net: Allow filter...
160
161
  		debug_cond(DEBUG_DEV_PKT, "Got ARP REQUEST, return our IP
  ");
e71110158   Joe Hershberger   net: Add net_upda...
162
  		eth_hdr_size = net_update_ether(et, et->et_src, PROT_ARP);
d280d3f43   Joe Hershberger   net: Move ARP out...
163
  		arp->ar_op = htons(ARPOP_REPLY);
674bb2498   Joe Hershberger   net: cosmetic: Re...
164
  		memcpy(&arp->ar_tha, &arp->ar_sha, ARP_HLEN);
049a95a77   Joe Hershberger   net: cosmetic: Ch...
165
  		net_copy_ip(&arp->ar_tpa, &arp->ar_spa);
0adb5b761   Joe Hershberger   net: cosmetic: Na...
166
  		memcpy(&arp->ar_sha, net_ethaddr, ARP_HLEN);
049a95a77   Joe Hershberger   net: cosmetic: Ch...
167
  		net_copy_ip(&arp->ar_spa, &net_ip);
c69757626   Joe Hershberger   net: Work-around ...
168
169
170
171
172
173
174
175
176
177
  
  #ifdef CONFIG_CMD_LINK_LOCAL
  		/*
  		 * Work-around for brain-damaged Cisco equipment with
  		 *   arp-proxy enabled.
  		 *
  		 *   If the requesting IP is not on our subnet, wait 5ms to
  		 *   reply to ARP request so that our reply will overwrite
  		 *   the arp-proxy's instead of the other way around.
  		 */
049a95a77   Joe Hershberger   net: cosmetic: Ch...
178
179
  		if ((net_read_ip(&arp->ar_tpa).s_addr & net_netmask.s_addr) !=
  		    (net_read_ip(&arp->ar_spa).s_addr & net_netmask.s_addr))
c69757626   Joe Hershberger   net: Work-around ...
180
181
  			udelay(5000);
  #endif
ac3f26cc1   Joe Hershberger   net: Don't overwr...
182
183
184
  		tx_packet = net_get_async_tx_pkt_buf();
  		memcpy(tx_packet, et, eth_hdr_size + ARP_HDR_SIZE);
  		net_send_packet(tx_packet, eth_hdr_size + ARP_HDR_SIZE);
d280d3f43   Joe Hershberger   net: Move ARP out...
185
186
187
  		return;
  
  	case ARPOP_REPLY:		/* arp reply */
3f02c98bd   Joe Hershberger   net: Add an acces...
188
189
  		/* are we waiting for a reply? */
  		if (!arp_is_waiting())
d280d3f43   Joe Hershberger   net: Move ARP out...
190
191
192
  			break;
  
  #ifdef CONFIG_KEEP_SERVERADDR
049a95a77   Joe Hershberger   net: cosmetic: Ch...
193
  		if (net_server_ip.s_addr == net_arp_wait_packet_ip.s_addr) {
d280d3f43   Joe Hershberger   net: Move ARP out...
194
  			char buf[20];
a0bc44e68   Mike Frysinger   net: fix typo in ...
195
  			sprintf(buf, "%pM", &arp->ar_sha);
382bee57f   Simon Glass   env: Rename seten...
196
  			env_set("serveraddr", buf);
d280d3f43   Joe Hershberger   net: Move ARP out...
197
198
  		}
  #endif
049a95a77   Joe Hershberger   net: cosmetic: Ch...
199
  		reply_ip_addr = net_read_ip(&arp->ar_spa);
d280d3f43   Joe Hershberger   net: Move ARP out...
200
201
  
  		/* matched waiting packet's address */
049a95a77   Joe Hershberger   net: cosmetic: Ch...
202
  		if (reply_ip_addr.s_addr == net_arp_wait_reply_ip.s_addr) {
4ef8d53ca   Joe Hershberger   net: Allow filter...
203
  			debug_cond(DEBUG_DEV_PKT,
85d25e0e7   Joe Hershberger   net: cosmetic: Cl...
204
205
206
  				   "Got ARP REPLY, set eth addr (%pM)
  ",
  				   arp->ar_data);
d280d3f43   Joe Hershberger   net: Move ARP out...
207
208
  
  			/* save address for later use */
85d25e0e7   Joe Hershberger   net: cosmetic: Cl...
209
210
  			if (arp_wait_packet_ethaddr != NULL)
  				memcpy(arp_wait_packet_ethaddr,
f1d2d2846   Joe Hershberger   net: Remove stati...
211
  				       &arp->ar_sha, ARP_HLEN);
d280d3f43   Joe Hershberger   net: Move ARP out...
212

ece223b52   Joe Hershberger   net: Refactor to ...
213
  			net_get_arp_handler()((uchar *)arp, 0, reply_ip_addr,
85d25e0e7   Joe Hershberger   net: cosmetic: Cl...
214
  					      0, len);
ece223b52   Joe Hershberger   net: Refactor to ...
215

e94070c44   Joe Hershberger   net: Don't copy e...
216
217
  			/* set the mac address in the waiting packet's header
  			   and transmit it */
1203fccee   Joe Hershberger   net: cosmetic: Cl...
218
219
  			memcpy(((struct ethernet_hdr *)net_tx_packet)->et_dest,
  			       &arp->ar_sha, ARP_HLEN);
85d25e0e7   Joe Hershberger   net: cosmetic: Cl...
220
  			net_send_packet(net_tx_packet, arp_wait_tx_packet_size);
d280d3f43   Joe Hershberger   net: Move ARP out...
221
222
  
  			/* no arp request pending now */
049a95a77   Joe Hershberger   net: cosmetic: Ch...
223
  			net_arp_wait_packet_ip.s_addr = 0;
85d25e0e7   Joe Hershberger   net: cosmetic: Cl...
224
225
  			arp_wait_tx_packet_size = 0;
  			arp_wait_packet_ethaddr = NULL;
d280d3f43   Joe Hershberger   net: Move ARP out...
226
227
228
229
230
231
232
233
234
  		}
  		return;
  	default:
  		debug("Unexpected ARP opcode 0x%x
  ",
  		      ntohs(arp->ar_op));
  		return;
  	}
  }
3f02c98bd   Joe Hershberger   net: Add an acces...
235
236
237
238
239
  
  bool arp_is_waiting(void)
  {
  	return !!net_arp_wait_packet_ip.s_addr;
  }