/* Copyright 1985 by the Massachusetts Institute of Technology */
#include <notice.h>

/*
 * ARP protocol definitions
 */

/* An ARP packet */
struct	arppktst {
    unss	arp_hrd;	/* Hardware address space */
    unss	arp_pro;	/* protocol address space */
    unsb	arp_hln;	/* hardware address length */
    unsb	arp_pln;	/* protocol address length */
    unss	arp_op;		/* opcode */
    /* The sizes of the following fields are determined by the
     * protocol/network pair and defined in the ARP descriptor structure. */
/*  unsb	arp_sha[];	/* hardware address of sender */
/*  unsb	arp_spa[];	/* protocol address of sender */
/*  unsb	arp_tha[];	/* hardware address of target */
/*  unsb	arp_tpa[];	/* protocol address of target */
};

#define	arppkt	struct arppktst
#define mkarppkt(x)	((arppkt *) (x))

/* Opcodes */
#ifdef	BIG_ENDIAN
# define	ARP_REQUEST	0x0001
# define	ARP_REPLY	0x0002
#endif	BIG_ENDIAN
#ifdef	LITTLE_ENDIAN
# define	ARP_REQUEST	0x0100
# define	ARP_REPLY	0x0200
#endif	LITTLE_ENDIAN

/* Hardware types */
#ifdef	BIG_ENDIAN
# define	ARP_HRD_ETHERNET	0x0001
# define	ARP_HRD_VII		0x0004
#endif	BIG_ENDIAN
#ifdef	LITTLE_ENDIAN
# define	ARP_HRD_ETHERNET	0x0100
# define	ARP_HRD_VII		0x0400
#endif	LITTLE_ENDIAN


/*
 * Internal ARP data structures
 */

/* Structure which defines ARP for a specific net/protocol pair.
 * Entries which have a $ in the comment are set statically, with a &
 * are set by the hardware protocol init, the rest are set at run time
 * by the ARP code.
 */
#define arp_desc struct _arp_desc_st_
#define arp_ce struct _arp_ce_st_
arp_desc {
    arp_desc *arpd_link;	/*$ Link to next descriptor for this net */
    void (*arpd_myaddp)();	/*$ A per protocol routine which tells
				 *  whether a reply should be sent for
				 *  a given address. */
    void (*arpd_myaddr)();	/*$ A per protocol routine which returns a
				 *  pointer to the protocol address of the
				 *  givin net. */
    char *(*arpd_ppaddr)();	/*$ A per protocol routine for
				 * printing protocol addresses. */
    unsw arpd_protocol;		/*$ Protocol type */
    unss arpd_csize;		/*$ Size of ARP cache */
    unss arpd_hsize;		/*  Size of hash table */
    char *(*arpd_phaddr)();	/*& A per hardware routine for printing
				 *  local net addresses. */
    unss arpd_hrd;		/*& Hardware address space */
    unss arpd_pro;		/*& Protocol address space */
    unsb arpd_hln;		/*& Hardware address length */
    unsb arpd_pln;		/*& Protocol address length */
    arp_ce **arpd_hash;		/*  ARP hash table for this net/protocol */
    arp_ce *arpd_cache;		/*  Free list of ARP cache entries */
	/* Statistics */
    unsl arpd_in_req;		/* Requests recieved and replied to */
    unsl arpd_in_reqi;		/* Requests ignored */
    unsl arpd_in_rep;		/* Replys received */
    unsl arpd_no_rep;		/* Unanswered requests */
    unsl arpd_bd_hrd;		/* Bad hardware type */
    unsl arpd_bd_hln;		/* Bad hardware length */
    unsl arpd_bd_pln;		/* Bad protocol length */
    unsl arpd_bd_op;		/* Bad opcode */
    unsl arpd_req;		/* Requests sent */
    unsl arpd_lookups;		/* Hash table lookups */
    unsl arpd_hmiss;		/* Hash table misses */
    unsl arpd_trans;		/* ARP translations */
    unsl arpd_mwait;		/* Multiple packets waiting for reply */
    unsl arpd_he_used;		/* Hash table entries in use */
    unsl arpd_ce_free;		/* Free cache entries */
    unsl arpd_gc;		/* Garbage collections */
    unsl arpd_gc_free;		/* Entries freed during gc's */
};

/* Structure of an ARP cache entry */
arp_ce {
    arp_ce *arpc_link;		/* Link to next bucket */
    unsl arpc_ltime;		/* Last time this entry was used. */
    arp_desc *arpc_ad;		/* ARP descriptor to which this cache
				 * entry belongs */
    iorb *arpc_iob;		/* Packet waiting for this address to
				 * be resolved.  If more packets
				 * arrive for this destination before
				 * the response arrives, onle the most
				 * recent packet is kept. */
    /* The next two entries' lengths depend on the protocol and hardware */
/*  unsb arpc_pro[];		/* Protocol address */
/*  unsb arpc_hrd[];		/* Hardware address */
};

/* Macros */
#define ARP_SHA(pkt) (((unsb *)((pkt) + 1)))
#define ARP_SPA(pkt) (((unsb *)((pkt) + 1)) + (pkt)->arp_hln)
#define ARP_THA(pkt) (((unsb *)((pkt) + 1)) + (pkt)->arp_hln + (pkt)->arp_pln)
#define ARP_TPA(pkt) (((unsb *)((pkt) + 1)) + (2*(pkt)->arp_hln) + (pkt)->arp_pln)
#define ARP_PKT_SIZE(ad) (sizeof(arppkt) + (2*(ad)->arpd_hln) + (2*(ad)->arpd_pln))
#define ARP_HASH_SIZE(arpd) ((arpd)->arpd_csize/4)
#define ARP_CACHEENT_SIZE(arpd) \
	(sizeof(arp_ce) + (arpd)->arpd_hln + (arpd)->arpd_pln)
#define ARP_CACHEENT_HRD(arpd, arpc) (((unsb *)((arpc) + 1)) + (arpd)->arpd_pln)
#define ARP_CACHEENT_PRO(arpd, arpc) ((unsb *)((arpc) + 1))

/* Priority of ARP "forwarder" */
#define ARPPRI 0250
