arp.c revision 22514
1311966Sngie/*
2311966Sngie * arp.c (C) 1995 Darren Reed
3311966Sngie *
4311966Sngie * The author provides this program as-is, with no gaurantee for its
5311966Sngie * suitability for any specific purpose.  The author takes no responsibility
6311966Sngie * for the misuse/abuse of this program and provides it for the sole purpose
7311966Sngie * of testing packet filter policies.  This file maybe distributed freely
8311966Sngie * providing it is not modified and that this notice remains in tact.
9311966Sngie */
10311966Sngie#if !defined(lint) && defined(LIBC_SCCS)
11311966Sngiestatic	char	sccsid[] = "@(#)arp.c	1.4 1/11/96 (C)1995 Darren Reed";
12311966Sngie#endif
13311966Sngie#include <stdio.h>
14311966Sngie#include <errno.h>
15311966Sngie#include <sys/types.h>
16311966Sngie#include <sys/socket.h>
17311966Sngie#include <sys/sockio.h>
18311966Sngie#include <sys/ioctl.h>
19311966Sngie#include <netdb.h>
20311966Sngie#include <netinet/in.h>
21311966Sngie#include <net/if.h>
22311966Sngie#include <net/if_arp.h>
23311966Sngie
24311966Sngie#if defined(__SVR4) || defined(__svr4__)
25311966Sngie#define	bcopy(a,b,c)	memmove(b,a,c)
26311966Sngie#define	bzero(a,c)	memset(a,0,c)
27311966Sngie#define	bcmp(a,b,c)	memcmp(a,b,c)
28311966Sngie#endif
29311966Sngie
30311966Sngie/*
31 * lookup host and return
32 * its IP address in address
33 * (4 bytes)
34 */
35int	resolve(host, address)
36char	*host, *address;
37{
38        struct	hostent	*hp;
39        u_long	add;
40
41	add = inet_addr(host);
42	if (add == -1)
43	    {
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