arp.c revision 26119
1/*
2 * arp.c (C) 1995 Darren Reed
3 *
4 * The author provides this program as-is, with no gaurantee for its
5 * suitability for any specific purpose.  The author takes no responsibility
6 * for the misuse/abuse of this program and provides it for the sole purpose
7 * of testing packet filter policies.  This file maybe distributed freely
8 * providing it is not modified and that this notice remains in tact.
9 */
10#if !defined(lint) && defined(LIBC_SCCS)
11static	char	sccsid[] = "@(#)arp.c	1.4 1/11/96 (C)1995 Darren Reed";
12#endif
13#include <stdio.h>
14#include <errno.h>
15#include <sys/types.h>
16#include <sys/socket.h>
17#include <sys/sockio.h>
18#include <sys/ioctl.h>
19#include <netdb.h>
20#include <netinet/in.h>
21#include <net/if.h>
22#include <net/if_arp.h>
23#include <netinet/in.h>
24#include <netinet/ip_var.h>
25#include <netinet/tcp.h>
26#include "ipsend.h"
27
28
29/*
30 * lookup host and return
31 * its IP address in address
32 * (4 bytes)
33 */
34int	resolve(host, address)
35char	*host, *address;
36{
37        struct	hostent	*hp;
38        u_long	add;
39
40	add = inet_addr(host);
41	if (add == -1)
42	    {
43		if (!(hp = gethostbyname(host)))
44		    {
45			fprintf(stderr, "unknown host: %s\n", host);
46			return -1;
47		    }
48		bcopy((char *)hp->h_addr, (char *)address, 4);
49		return 0;
50	}
51	bcopy((char*)&add, address, 4);
52	return 0;
53}
54
55/*
56 * ARP for the MAC address corresponding
57 * to the IP address.  This taken from
58 * some BSD program, I cant remember which.
59 */
60int	arp(ip, ether)
61char	*ip;
62char	*ether;
63{
64	static	int	sfd = -1;
65	static	char	ethersave[6], ipsave[4];
66	struct	arpreq	ar;
67	struct	sockaddr_in	*sin, san;
68	struct	hostent	*hp;
69	int	fd;
70
71	if (!bcmp(ipsave, ip, 4)) {
72		bcopy(ethersave, ether, 6);
73		return 0;
74	}
75	fd = -1;
76	bzero((char *)&ar, sizeof(ar));
77	sin = (struct sockaddr_in *)&ar.arp_pa;
78	sin->sin_family = AF_INET;
79	bcopy(ip, (char *)&sin->sin_addr.s_addr, 4);
80	if ((hp = gethostbyaddr(ip, 4, AF_INET)))
81		if (!(ether_hostton(hp->h_name, ether)))
82			goto savearp;
83
84	if (sfd == -1)
85		if ((sfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
86		    {
87			perror("arp: socket");
88			return -1;
89		    }
90tryagain:
91	if (ioctl(sfd, SIOCGARP, (caddr_t)&ar) == -1)
92	    {
93		if (fd == -1)
94		    {
95			bzero((char *)&san, sizeof(san));
96			san.sin_family = AF_INET;
97			san.sin_port = htons(1);
98			bcopy(ip, &san.sin_addr.s_addr, 4);
99			fd = socket(AF_INET, SOCK_DGRAM, 0);
100			(void) sendto(fd, ip, 4, 0,
101				      (struct sockaddr *)&san, sizeof(san));
102			sleep(1);
103			(void) close(fd);
104			goto tryagain;
105		    }
106		fprintf(stderr, "(%s):", inet_ntoa(sin->sin_addr));
107		if (errno != ENXIO)
108			perror("SIOCGARP");
109		return -1;
110	    }
111
112	bcopy(ar.arp_ha.sa_data, ether, 6);
113savearp:
114	bcopy(ether, ethersave, 6);
115	bcopy(ip, ipsave, 4);
116	return 0;
117}
118