/*
 *	ARP/RARP structures and definitions.
 *
 *	12/11/94, Kay Roemer.
 */

#ifndef _ARP_H
#define _ARP_H

#include "kerbind.h"
#include "socket.h"
#include "if.h"
#include "ifeth.h"
#include "buf.h"
#include "timer.h"

/*
 * ARP request/reply packet
 */
struct arp_dgram {
	unsigned short	hwtype;
	unsigned short	prtype;
	unsigned short	hwlen;
	unsigned short	prlen;
	unsigned short	op;
	unsigned char	data[0];
};

#define ARP_SHW(a)	((a)->data)
#define ARP_SPR(a)	((a)->data + (a)->hwlen)
#define ARP_DHW(a)	((a)->data + (a)->hwlen + (a)->prlen)
#define ARP_DPR(a)	((a)->data + 2*(a)->hwlen + (a)->prlen)
#define ARP_LEN(a)	(sizeof(struct arp_dgram) + 2*((a)->hwlen + (a)->prlen))

/* possible hardware types for arp_dgram.hwtype */
#define ARHWTYPE_ETH	1

/* possible protocol types for arp_dgram.prtype */
#define ARPRTYPE_IP	ETHPROTO_IP

/* possible op-codes for arp_dgram.op */
#define AROP_ARPREQ	1
#define AROP_ARPREP	2
#define AROP_RARPREQ	3
#define AROP_RARPREP	4

/*
 * ARP cache node
 */
struct arp_entry {
	unsigned short	links;		/* reference count */
	unsigned short	flags;		/* ATF_* flags */
	
	unsigned short	hwtype;		/* hardware type */
	unsigned short	prtype;		/* protocol type */
	struct hwaddr	praddr;		/* protocol address */
	struct hwaddr	hwaddr;		/* hardware address */

	struct netif	*nif;		/* iface this entry was obtained from*/
	struct ifq	outq;		/* queue of packets for this addr */

	struct event	tmout;		/* retransmit/timeout event */
	unsigned short	retries;	/* number of retries so far */

	struct arp_entry *prnext;	/* link to next entry in pr chain */
	struct arp_entry *hwnext;	/* link to next entry in hw chain */
};

#define ARP_RETRIES	4			/* 4 retries before giving up*/
#define ARP_RETRANS	(1000L/EVTGRAN)		/* retry after 1 sec */
#define ARP_EXPIRE	(1200000L/EVTGRAN)	/* remove entry after 20 min */
#define ARP_HASHSIZE	47			/* hash table size */
#define ARP_RESERVE	100

/*
 * structure passed on ARP ioctl's
 */
struct arp_req {
	struct sockaddr	praddr;		/* protocol address */
	struct sockaddr	hwaddr;		/* hardware address */
	unsigned short	flags;		/* ATF_* flags */
};

/* flags for arp_req.flags and arp_entry.flags */
#define ATF_PRCOM	0x01	/* pr entry resolved */
#define ATF_HWCOM	0x02	/* hw entry resolved */
#define ATF_PERM	0x04	/* static entry */
#define ATF_PUBL	0x08	/* proxy entry */
#define ATF_USETRAILERS	0x10	/* other side wants trailers */
#define ATF_NORARP	0x20	/* don't use this entry for RARP */
#define ATF_COM		(ATF_PRCOM|ATF_HWCOM)
#define ATF_USRMASK	(ATF_PUBL|ATF_PERM|ATF_NORARP)

/* is this entry resolved? */
#define ATF_ISCOM(are)	(((are)->flags & ATF_COM) == ATF_COM)

extern long			arp_init (void);
extern void			arp_free (struct arp_entry *);
extern void			arp_input (struct netif *, BUF *);
extern void			rarp_input (struct netif *, BUF *);
extern void			arp_flush (struct netif *);
extern long			arp_ioctl (short, void *);
static void			arp_deref (struct arp_entry *);
extern struct arp_entry *	arp_lookup (short flags, struct netif *,
					short type, short len, char *);

extern struct arp_entry *	rarp_lookup (short flags, struct netif *,
					short type, short len, char *);

/* flags for arp_lookup() */
#define ARLK_NOCREAT	0x01	/* don't create+resolve entry if not found */
#define ARLK_NORESOLV	0x02	/* don't resolve entry if not found */

static inline void
arp_deref (are)
	struct arp_entry *are;
{
	if (--are->links <= 0)
		arp_free (are);
}

#endif
