1 // SPDX-License-Identifier: GPL-2.0
3 * Copied from Linux Monitor (LiMon) - Networking.
5 * Copyright 1994 - 2000 Neil Russell.
7 * Copyright 2000 Roland Borde
8 * Copyright 2000 Paolo Scaffardi
9 * Copyright 2000-2002 Wolfgang Denk, wd@denx.de
16 #include <linux/delay.h>
20 struct in_addr net_arp_wait_packet_ip
;
21 static struct in_addr net_arp_wait_reply_ip
;
22 /* MAC address of waiting packet's destination */
23 uchar
*arp_wait_packet_ethaddr
;
24 int arp_wait_tx_packet_size
;
25 ulong arp_wait_timer_start
;
27 uchar
*arp_tx_packet
; /* THE ARP transmit packet */
28 static uchar arp_tx_packet_buf
[PKTSIZE_ALIGN
+ PKTALIGN
];
32 /* XXX problem with bss workaround */
33 arp_wait_packet_ethaddr
= NULL
;
34 net_arp_wait_packet_ip
.s_addr
= 0;
35 net_arp_wait_reply_ip
.s_addr
= 0;
36 arp_wait_tx_packet_size
= 0;
37 arp_tx_packet
= &arp_tx_packet_buf
[0] + (PKTALIGN
- 1);
38 arp_tx_packet
-= (ulong
)arp_tx_packet
% PKTALIGN
;
41 void arp_raw_request(struct in_addr source_ip
, const uchar
*target_ethaddr
,
42 struct in_addr target_ip
)
48 debug_cond(DEBUG_DEV_PKT
, "ARP broadcast %d\n", arp_wait_try
);
52 eth_hdr_size
= net_set_ether(pkt
, net_bcast_ethaddr
, PROT_ARP
);
55 arp
= (struct arp_hdr
*)pkt
;
57 arp
->ar_hrd
= htons(ARP_ETHER
);
58 arp
->ar_pro
= htons(PROT_IP
);
59 arp
->ar_hln
= ARP_HLEN
;
60 arp
->ar_pln
= ARP_PLEN
;
61 arp
->ar_op
= htons(ARPOP_REQUEST
);
63 memcpy(&arp
->ar_sha
, net_ethaddr
, ARP_HLEN
); /* source ET addr */
64 net_write_ip(&arp
->ar_spa
, source_ip
); /* source IP addr */
65 memcpy(&arp
->ar_tha
, target_ethaddr
, ARP_HLEN
); /* target ET addr */
66 net_write_ip(&arp
->ar_tpa
, target_ip
); /* target IP addr */
68 net_send_packet(arp_tx_packet
, eth_hdr_size
+ ARP_HDR_SIZE
);
71 void arp_request(void)
73 if ((net_arp_wait_packet_ip
.s_addr
& net_netmask
.s_addr
) !=
74 (net_ip
.s_addr
& net_netmask
.s_addr
)) {
75 if (net_gateway
.s_addr
== 0) {
76 puts("## Warning: gatewayip needed but not set\n");
77 net_arp_wait_reply_ip
= net_arp_wait_packet_ip
;
79 net_arp_wait_reply_ip
= net_gateway
;
82 net_arp_wait_reply_ip
= net_arp_wait_packet_ip
;
85 arp_raw_request(net_ip
, net_null_ethaddr
, net_arp_wait_reply_ip
);
88 int arp_timeout_check(void)
92 if (!arp_is_waiting())
97 /* check for arp timeout */
98 if ((t
- arp_wait_timer_start
) > CONFIG_ARP_TIMEOUT
) {
101 if (arp_wait_try
>= CONFIG_NET_RETRY_COUNT
) {
102 puts("\nARP Retry count exceeded; starting again\n");
104 net_set_state(NETLOOP_FAIL
);
106 arp_wait_timer_start
= t
;
113 void arp_receive(struct ethernet_hdr
*et
, struct ip_udp_hdr
*ip
, int len
)
116 struct in_addr reply_ip_addr
;
121 * We have to deal with two types of ARP packets:
122 * - REQUEST packets will be answered by sending our
123 * IP address - if we know it.
124 * - REPLY packates are expected only after we asked
125 * for the TFTP server's or the gateway's ethernet
126 * address; so if we receive such a packet, we set
127 * the server ethernet address
129 debug_cond(DEBUG_NET_PKT
, "Got ARP\n");
131 arp
= (struct arp_hdr
*)ip
;
132 if (len
< ARP_HDR_SIZE
) {
133 printf("bad length %d < %d\n", len
, ARP_HDR_SIZE
);
136 if (ntohs(arp
->ar_hrd
) != ARP_ETHER
)
138 if (ntohs(arp
->ar_pro
) != PROT_IP
)
140 if (arp
->ar_hln
!= ARP_HLEN
)
142 if (arp
->ar_pln
!= ARP_PLEN
)
145 if (net_ip
.s_addr
== 0)
148 if (net_read_ip(&arp
->ar_tpa
).s_addr
!= net_ip
.s_addr
)
151 switch (ntohs(arp
->ar_op
)) {
153 /* reply with our IP address */
154 debug_cond(DEBUG_DEV_PKT
, "Got ARP REQUEST, return our IP\n");
155 eth_hdr_size
= net_update_ether(et
, et
->et_src
, PROT_ARP
);
156 arp
->ar_op
= htons(ARPOP_REPLY
);
157 memcpy(&arp
->ar_tha
, &arp
->ar_sha
, ARP_HLEN
);
158 net_copy_ip(&arp
->ar_tpa
, &arp
->ar_spa
);
159 memcpy(&arp
->ar_sha
, net_ethaddr
, ARP_HLEN
);
160 net_copy_ip(&arp
->ar_spa
, &net_ip
);
162 #ifdef CONFIG_CMD_LINK_LOCAL
164 * Work-around for brain-damaged Cisco equipment with
167 * If the requesting IP is not on our subnet, wait 5ms to
168 * reply to ARP request so that our reply will overwrite
169 * the arp-proxy's instead of the other way around.
171 if ((net_read_ip(&arp
->ar_tpa
).s_addr
& net_netmask
.s_addr
) !=
172 (net_read_ip(&arp
->ar_spa
).s_addr
& net_netmask
.s_addr
))
175 tx_packet
= net_get_async_tx_pkt_buf();
176 memcpy(tx_packet
, et
, eth_hdr_size
+ ARP_HDR_SIZE
);
177 net_send_packet(tx_packet
, eth_hdr_size
+ ARP_HDR_SIZE
);
180 case ARPOP_REPLY
: /* arp reply */
181 /* are we waiting for a reply? */
182 if (!arp_is_waiting())
185 if (IS_ENABLED(CONFIG_KEEP_SERVERADDR
) &&
186 net_server_ip
.s_addr
== net_arp_wait_packet_ip
.s_addr
) {
188 sprintf(buf
, "%pM", &arp
->ar_sha
);
189 env_set("serveraddr", buf
);
192 reply_ip_addr
= net_read_ip(&arp
->ar_spa
);
194 /* matched waiting packet's address */
195 if (reply_ip_addr
.s_addr
== net_arp_wait_reply_ip
.s_addr
) {
196 debug_cond(DEBUG_DEV_PKT
,
197 "Got ARP REPLY, set eth addr (%pM)\n",
200 /* save address for later use */
201 if (arp_wait_packet_ethaddr
!= NULL
)
202 memcpy(arp_wait_packet_ethaddr
,
203 &arp
->ar_sha
, ARP_HLEN
);
205 net_get_arp_handler()((uchar
*)arp
, 0, reply_ip_addr
,
208 /* set the mac address in the waiting packet's header
210 memcpy(((struct ethernet_hdr
*)net_tx_packet
)->et_dest
,
211 &arp
->ar_sha
, ARP_HLEN
);
212 net_send_packet(net_tx_packet
, arp_wait_tx_packet_size
);
214 /* no arp request pending now */
215 net_arp_wait_packet_ip
.s_addr
= 0;
216 arp_wait_tx_packet_size
= 0;
217 arp_wait_packet_ethaddr
= NULL
;
221 debug("Unexpected ARP opcode 0x%x\n",
227 bool arp_is_waiting(void)
229 return !!net_arp_wait_packet_ip
.s_addr
;