arp.c revision 22514
119370Spst/*
219370Spst * arp.c (C) 1995 Darren Reed
319370Spst *
419370Spst * The author provides this program as-is, with no gaurantee for its
598944Sobrien * suitability for any specific purpose.  The author takes no responsibility
619370Spst * for the misuse/abuse of this program and provides it for the sole purpose
798944Sobrien * of testing packet filter policies.  This file maybe distributed freely
898944Sobrien * providing it is not modified and that this notice remains in tact.
998944Sobrien */
1098944Sobrien#if !defined(lint) && defined(LIBC_SCCS)
1119370Spststatic	char	sccsid[] = "@(#)arp.c	1.4 1/11/96 (C)1995 Darren Reed";
1298944Sobrien#endif
1398944Sobrien#include <stdio.h>
1498944Sobrien#include <errno.h>
1598944Sobrien#include <sys/types.h>
1619370Spst#include <sys/socket.h>
1798944Sobrien#include <sys/sockio.h>
1898944Sobrien#include <sys/ioctl.h>
1998944Sobrien#include <netdb.h>
2098944Sobrien#include <netinet/in.h>
2119370Spst#include <net/if.h>
2219370Spst#include <net/if_arp.h>
2398944Sobrien
2419370Spst#if defined(__SVR4) || defined(__svr4__)
2598944Sobrien#define	bcopy(a,b,c)	memmove(b,a,c)
2698944Sobrien#define	bzero(a,c)	memset(a,0,c)
2798944Sobrien#define	bcmp(a,b,c)	memcmp(a,b,c)
2898944Sobrien#endif
2998944Sobrien
3098944Sobrien/*
3198944Sobrien * lookup host and return
3298944Sobrien * its IP address in address
3319370Spst * (4 bytes)
3419370Spst */
3519370Spstint	resolve(host, address)
3619370Spstchar	*host, *address;
3719370Spst{
3819370Spst        struct	hostent	*hp;
3919370Spst        u_long	add;
4019370Spst
4119370Spst	add = inet_addr(host);
4219370Spst	if (add == -1)
4319370Spst	    {
44		if (!(hp = gethostbyname(host)))
45		    {
46			fprintf(stderr, "unknown host: %s\n", host);
47			return -1;
48		    }
49		bcopy((char *)hp->h_addr, (char *)address, 4);
50		return 0;
51	}
52	bcopy((char*)&add, address, 4);
53	return 0;
54}
55
56/*
57 * ARP for the MAC address corresponding
58 * to the IP address.  This taken from
59 * some BSD program, I cant remember which.
60 */
61int	arp(ip, ether)
62char	*ip;
63char	*ether;
64{
65	static	int	sfd = -1;
66	static	char	ethersave[6], ipsave[4];
67	struct	arpreq	ar;
68	struct	sockaddr_in	*sin, san;
69	struct	hostent	*hp;
70	char	*inet_ntoa();
71	int	fd;
72
73	if (!bcmp(ipsave, ip, 4)) {
74		bcopy(ethersave, ether, 6);
75		return 0;
76	}
77	fd = -1;
78	bzero((char *)&ar, sizeof(ar));
79	sin = (struct sockaddr_in *)&ar.arp_pa;
80	sin->sin_family = AF_INET;
81	bcopy(ip, (char *)&sin->sin_addr.s_addr, 4);
82	if ((hp = gethostbyaddr(ip, 4, AF_INET)))
83		if (!(ether_hostton(hp->h_name, ether)))
84			goto savearp;
85
86	if (sfd == -1)
87		if ((sfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
88		    {
89			perror("arp: socket");
90			return -1;
91		    }
92tryagain:
93	if (ioctl(sfd, SIOCGARP, (caddr_t)&ar) == -1)
94	    {
95		if (fd == -1)
96		    {
97			bzero((char *)&san, sizeof(san));
98			san.sin_family = AF_INET;
99			san.sin_port = htons(1);
100			bcopy(ip, &san.sin_addr.s_addr, 4);
101			fd = socket(AF_INET, SOCK_DGRAM, 0);
102			(void) sendto(fd, ip, 4, 0,
103				      (struct sockaddr *)&san, sizeof(san));
104			sleep(1);
105			(void) close(fd);
106			goto tryagain;
107		    }
108		fprintf(stderr, "(%s):", inet_ntoa(sin->sin_addr));
109		if (errno != ENXIO)
110			perror("SIOCGARP");
111		return -1;
112	    }
113
114	bcopy(ar.arp_ha.sa_data, ether, 6);
115savearp:
116	bcopy(ether, ethersave, 6);
117	bcopy(ip, ipsave, 4);
118	return 0;
119}
120