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