// 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 <env.h>
#include <log.h>
#include <net.h>
#include <vsprintf.h>
#include <linux/delay.h>

#include "arp.h"

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) > CONFIG_ARP_TIMEOUT) {
		arp_wait_try++;

		if (arp_wait_try >= CONFIG_NET_RETRY_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;

		if (IS_ENABLED(CONFIG_KEEP_SERVERADDR) &&
		    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);
		}

		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;
}
