#ifndef lint
static char *RCSid = "$Header: /usr/src/ecn/getethers/RCS/arp.c,v 1.3 92/05/08 14:15:55 davy Exp $";
#endif

/*
 * arp.c - routines for digging up arp table entries.
 *
 * David A. Curry
 * Purdue University
 * Engineering Computer Network
 * davy@ecn.purdue.edu
 * November, 1991
 *
 * $Log:	arp.c,v $
 * Revision 1.3  92/05/08  14:15:55  davy
 * Made portable to 4.3BSD, from Peter Shipley (shipley@tfs.com).
 * 
 * Revision 1.2  92/05/08  13:06:31  davy
 * Added vendor name printing from Peter Shipley (shipley@tfs.com).
 * 
 * Revision 1.1  91/11/27  10:56:13  davy
 * Initial revision
 * 
 */
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <net/if.h>
#if defined(sun) || defined(__convex__)
#include <net/if_arp.h>
#endif
#include <netinet/if_ether.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include "defs.h"

extern int errno;

/*
 * get_arp - get the arp table entry for the internet address in addr, and
 *	     return the ethernet address as a character string.
 */
char *
get_arp(addr, vname)
struct in_addr addr;
char **vname;
{
	int s;
	struct arpreq ar;
	struct sockaddr_in *sin;
	char *ether_ntoa(), *vendor_name();

	/*
	 * Clear the structure.
	 */
	bzero((char *) &ar, sizeof(struct arpreq));

	/*
	 * We want internet family only.
	 */
	ar.arp_pa.sa_family = AF_INET;
	sin = (struct sockaddr_in *) &ar.arp_pa;

	/*
	 * Copy in the internet address.
	 */
	sin->sin_family = AF_INET;
	bcopy((char *) &addr, (char *) &sin->sin_addr, sizeof(struct in_addr));

	/*
	 * Get a socket.
	 */
	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
		error("socket");
		return(strdup("(unknown)"));
	}

	/*
	 * Get the arp table entry.
	 */
	if (ioctl(s, SIOCGARP, (char *) &ar) < 0) {
		/*
		 * Nothing in the table.
		 */
		if (errno == ENXIO) {
			close(s);
			return(strdup("(no entry)"));
		}

		error("ioctl: SIOCGARP");
		close(s);

		return("(unknown)");
	}

	close(s);

	/*
	 * Is the entry complete?
	 */
	if (ar.arp_flags & ATF_COM) {
		*vname = vendor_name((struct ether_addr *) ar.arp_ha.sa_data);
		return(strdup(ether_ntoa((struct ether_addr *) ar.arp_ha.sa_data)));
	}

	return(strdup("(incomplete)"));
}
