arp.c revision 80486
1/*
2 * arp.c (C) 1995-1998 Darren Reed
3 *
4 * See the IPFILTER.LICENCE file for details on licencing.
5 */
6#include <stdio.h>
7#include <errno.h>
8#include <sys/types.h>
9#include <sys/socket.h>
10#if !defined(ultrix) && !defined(hpux)
11#include <sys/sockio.h>
12#endif
13#include <sys/ioctl.h>
14#include <netdb.h>
15#include <netinet/in.h>
16#include <net/if.h>
17#include <netinet/if_ether.h>
18#ifndef	ultrix
19#include <net/if_arp.h>
20#endif
21#include <netinet/in.h>
22#include <netinet/ip_var.h>
23#include <netinet/tcp.h>
24#include "ipsend.h"
25#include "iplang/iplang.h"
26
27#if !defined(lint)
28static const char sccsid[] = "@(#)arp.c	1.4 1/11/96 (C)1995 Darren Reed";
29static const char rcsid[] = "@(#)$Id: arp.c,v 2.1.4.2 2001/07/15 22:00:13 darrenr Exp $";
30#endif
31
32
33/*
34 * lookup host and return
35 * its IP address in address
36 * (4 bytes)
37 */
38int	resolve(host, address)
39char	*host, *address;
40{
41        struct	hostent	*hp;
42        u_long	add;
43
44	add = inet_addr(host);
45	if (add == -1)
46	    {
47		if (!(hp = gethostbyname(host)))
48		    {
49			fprintf(stderr, "unknown host: %s\n", host);
50			return -1;
51		    }
52		bcopy((char *)hp->h_addr, (char *)address, 4);
53		return 0;
54	}
55	bcopy((char*)&add, address, 4);
56	return 0;
57}
58
59/*
60 * ARP for the MAC address corresponding
61 * to the IP address.  This taken from
62 * some BSD program, I cant remember which.
63 */
64int	arp(ip, ether)
65char	*ip;
66char	*ether;
67{
68	static	int	sfd = -1;
69	static	char	ethersave[6], ipsave[4];
70	struct	arpreq	ar;
71	struct	sockaddr_in	*sin, san;
72	struct	hostent	*hp;
73	int	fd;
74
75#ifdef	IPSEND
76	if (arp_getipv4(ip, ether) == 0)
77		return 0;
78#endif
79	if (!bcmp(ipsave, ip, 4)) {
80		bcopy(ethersave, ether, 6);
81		return 0;
82	}
83	fd = -1;
84	bzero((char *)&ar, sizeof(ar));
85	sin = (struct sockaddr_in *)&ar.arp_pa;
86	sin->sin_family = AF_INET;
87	bcopy(ip, (char *)&sin->sin_addr.s_addr, 4);
88#ifndef	hpux
89	if ((hp = gethostbyaddr(ip, 4, AF_INET)))
90		if (!(ether_hostton(hp->h_name, ether)))
91			goto savearp;
92#endif
93
94	if (sfd == -1)
95		if ((sfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
96		    {
97			perror("arp: socket");
98			return -1;
99		    }
100tryagain:
101	if (ioctl(sfd, SIOCGARP, (caddr_t)&ar) == -1)
102	    {
103		if (fd == -1)
104		    {
105			bzero((char *)&san, sizeof(san));
106			san.sin_family = AF_INET;
107			san.sin_port = htons(1);
108			bcopy(ip, &san.sin_addr.s_addr, 4);
109			fd = socket(AF_INET, SOCK_DGRAM, 0);
110			(void) sendto(fd, ip, 4, 0,
111				      (struct sockaddr *)&san, sizeof(san));
112			sleep(1);
113			(void) close(fd);
114			goto tryagain;
115		    }
116		fprintf(stderr, "(%s):", inet_ntoa(sin->sin_addr));
117		if (errno != ENXIO)
118			perror("SIOCGARP");
119		return -1;
120	    }
121
122	bcopy(ar.arp_ha.sa_data, ether, 6);
123savearp:
124	bcopy(ether, ethersave, 6);
125	bcopy(ip, ipsave, 4);
126	return 0;
127}
128