Xinu7/src/serve11/sys/arp_in.c

/* arp_in.c - arp_in */

#include <conf.h>
#include <kernel.h>
#include <proc.h>
#include <network.h>

/*------------------------------------------------------------------------
 *  arp_in  -  handle ARP packet coming in from Ethernet network
 *------------------------------------------------------------------------
 */
arp_in(packet, device)
struct	epacket	*packet;
int	device;
{
	char	ps;
	int	pid;
	short	arop;
	struct	arppak	*apacptr;
	struct	arpent	*atabptr;
	struct	etblk	*etptr;	
	
	etptr = (struct etblk *) devtab[device].dvioblk;
	apacptr = (struct arppak *) packet->ep_data;
	atabptr = &Arp.arptab[arpfind(apacptr->ar_spa)];
	if (atabptr->arp_state != AR_RSLVD) {
		blkcopy(atabptr->arp_Ead, apacptr->ar_sha, EPADLEN);
		atabptr->arp_dev = device;
		atabptr->arp_state = AR_RSLVD;
	}
	arop = net2hs(apacptr->ar_op);
	switch (arop) {

	    case AR_REQ:	/* request - answer if for me */
		if (! blkequ(Net.myaddr, apacptr->ar_tpa, IPLEN)) {
			freebuf(packet);
			return(OK);
		}
		apacptr->ar_op = hs2net(AR_RPLY);
		blkcopy(apacptr->ar_tpa, apacptr->ar_spa, IPLEN);
		blkcopy(apacptr->ar_tha, packet->ep_hdr.e_src, EPADLEN);
		blkcopy(packet->ep_hdr.e_dest, apacptr->ar_tha, EPADLEN);
		blkcopy(apacptr->ar_sha, etptr->etpaddr, EPADLEN);
		blkcopy(apacptr->ar_spa, Net.myaddr, IPLEN);
		write(device, packet, EMINPAK);
		return(OK);

	    case AR_RPLY:	/* reply - awaken requestor if any */
		disable(ps);
		pid = Arp.arppid;
		if (!isbadpid(pid)
		    && blkequ(Arp.arpwant, apacptr->ar_spa, IPLEN)) {
			Arp.arppid = BADPID;
			send(pid, OK);
		}
		freebuf(packet);
		restore(ps);
		return(OK);

	    default:
		Net.ndrop++;
		freebuf(packet);
		return(SYSERR);
	}
}