// SPDX-License-Identifier: GPL-2.0
/*
 *	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

struct in_addr net_arp_wait_packet_ip;
static struct in_addr net_arp_wait_reply_ip;
/* MAC address of waiting packet's destination */
uchar	       *arp_wait_packet_ethaddr;
int		arp_wait_tx_packet_size;
ulong		arp_wait_timer_start;
int		arp_wait_try;
uchar	       *arp_tx_packet; /* THE ARP transmit packet */
static uchar	arp_tx_packet_buf[PKTSIZE_ALIGN + PKTALIGN];

void arp_init(void)
{
	/* XXX problem with bss workaround */
	arp_wait_packet_ethaddr = NULL;
	net_arp_wait_packet_ip.s_addr = 0;
	net_arp_wait_reply_ip.s_addr = 0;
	arp_wait_tx_packet_size = 0;
	arp_tx_packet = &arp_tx_packet_buf[0] + (PKTALIGN - 1);
	arp_tx_packet -= (ulong)arp_tx_packet % PKTALIGN;
}

void arp_raw_request(struct in_addr source_ip, const uchar *target_ethaddr,
	struct in_addr target_ip)
{
	uchar *pkt;
	struct arp_hdr *arp;
	int eth_hdr_size;

	debug_cond(DEBUG_DEV_PKT, "ARP broadcast %d\n", arp_wait_try);

	pkt = arp_tx_packet;

	eth_hdr_size = net_set_ether(pkt, net_bcast_ethaddr, PROT_ARP);
	pkt += eth_hdr_size;

	arp = (struct arp_hdr *)pkt;

	arp->ar_hrd = htons(ARP_ETHER);
	arp->ar_pro = htons(PROT_IP);
	arp->ar_hln = ARP_HLEN;
	arp->ar_pln = ARP_PLEN;
	arp->ar_op = htons(ARPOP_REQUEST);

	memcpy(&arp->ar_sha, net_ethaddr, ARP_HLEN);	/* source ET addr */
	net_write_ip(&arp->ar_spa, source_ip);		/* source IP addr */
	memcpy(&arp->ar_tha, target_ethaddr, ARP_HLEN);	/* target ET addr */
	net_write_ip(&arp->ar_tpa, target_ip);		/* target IP addr */

	net_send_packet(arp_tx_packet, eth_hdr_size + ARP_HDR_SIZE);
}

void arp_request(void)
{
	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) {
			puts("## Warning: gatewayip needed but not set\n");
			net_arp_wait_reply_ip = net_arp_wait_packet_ip;
		} else {
			net_arp_wait_reply_ip = net_gateway;
		}
	} else {
		net_arp_wait_reply_ip = net_arp_wait_packet_ip;
	}

	arp_raw_request(net_ip, net_null_ethaddr, net_arp_wait_reply_ip);
}

int arp_timeout_check(void)
{
	ulong t;

	if (!arp_is_waiting())
		return 0;

	t = get_timer(0);

	/* check for arp timeout */
	if ((t - arp_wait_timer_start) > ARP_TIMEOUT) {
		arp_wait_try++;

		if (arp_wait_try >= ARP_TIMEOUT_COUNT) {
			puts("\nARP Retry count exceeded; starting again\n");
			arp_wait_try = 0;
			net_set_state(NETLOOP_FAIL);
		} else {
			arp_wait_timer_start = t;
			arp_request();
		}
	}
	return 1;
}

void arp_receive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len)
{
	struct arp_hdr *arp;
	struct in_addr reply_ip_addr;
	int eth_hdr_size;
	uchar *tx_packet;

	/*
	 * 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
	 */
	debug_cond(DEBUG_NET_PKT, "Got ARP\n");

	arp = (struct arp_hdr *)ip;
	if (len < ARP_HDR_SIZE) {
		printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
		return;
	}
	if (ntohs(arp->ar_hrd) != ARP_ETHER)
		return;
	if (ntohs(arp->ar_pro) != PROT_IP)
		return;
	if (arp->ar_hln != ARP_HLEN)
		return;
	if (arp->ar_pln != ARP_PLEN)
		return;

	if (net_ip.s_addr == 0)
		return;

	if (net_read_ip(&arp->ar_tpa).s_addr != net_ip.s_addr)
		return;

	switch (ntohs(arp->ar_op)) {
	case ARPOP_REQUEST:
		/* reply with our IP address */
		debug_cond(DEBUG_DEV_PKT, "Got ARP REQUEST, return our IP\n");
		eth_hdr_size = net_update_ether(et, et->et_src, PROT_ARP);
		arp->ar_op = htons(ARPOP_REPLY);
		memcpy(&arp->ar_tha, &arp->ar_sha, ARP_HLEN);
		net_copy_ip(&arp->ar_tpa, &arp->ar_spa);
		memcpy(&arp->ar_sha, net_ethaddr, ARP_HLEN);
		net_copy_ip(&arp->ar_spa, &net_ip);

#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.
		 */
		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))
			udelay(5000);
#endif
		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);
		return;

	case ARPOP_REPLY:		/* arp reply */
		/* are we waiting for a reply? */
		if (!arp_is_waiting())
			break;

#ifdef CONFIG_KEEP_SERVERADDR
		if (net_server_ip.s_addr == net_arp_wait_packet_ip.s_addr) {
			char buf[20];
			sprintf(buf, "%pM", &arp->ar_sha);
			env_set("serveraddr", buf);
		}
#endif

		reply_ip_addr = net_read_ip(&arp->ar_spa);

		/* matched waiting packet's address */
		if (reply_ip_addr.s_addr == net_arp_wait_reply_ip.s_addr) {
			debug_cond(DEBUG_DEV_PKT,
				   "Got ARP REPLY, set eth addr (%pM)\n",
				   arp->ar_data);

			/* save address for later use */
			if (arp_wait_packet_ethaddr != NULL)
				memcpy(arp_wait_packet_ethaddr,
				       &arp->ar_sha, ARP_HLEN);

			net_get_arp_handler()((uchar *)arp, 0, reply_ip_addr,
					      0, len);

			/* set the mac address in the waiting packet's header
			   and transmit it */
			memcpy(((struct ethernet_hdr *)net_tx_packet)->et_dest,
			       &arp->ar_sha, ARP_HLEN);
			net_send_packet(net_tx_packet, arp_wait_tx_packet_size);

			/* no arp request pending now */
			net_arp_wait_packet_ip.s_addr = 0;
			arp_wait_tx_packet_size = 0;
			arp_wait_packet_ethaddr = NULL;
		}
		return;
	default:
		debug("Unexpected ARP opcode 0x%x\n",
		      ntohs(arp->ar_op));
		return;
	}
}

bool arp_is_waiting(void)
{
	return !!net_arp_wait_packet_ip.s_addr;
}
