xref: /freebsd/sbin/ipf/ipsend/arp.c (revision efeb8bffe34422937c7f8df836afb5b817366d16)
141edb306SCy Schubert /*	$FreeBSD$	*/
241edb306SCy Schubert 
341edb306SCy Schubert /*
441edb306SCy Schubert  * arp.c (C) 1995-1998 Darren Reed
541edb306SCy Schubert  *
641edb306SCy Schubert  * See the IPFILTER.LICENCE file for details on licencing.
741edb306SCy Schubert  */
841edb306SCy Schubert #if !defined(lint)
941edb306SCy Schubert static const char sccsid[] = "@(#)arp.c	1.4 1/11/96 (C)1995 Darren Reed";
1041edb306SCy Schubert static const char rcsid[] = "@(#)$Id$";
1141edb306SCy Schubert #endif
1241edb306SCy Schubert #include <sys/types.h>
1341edb306SCy Schubert #include <sys/socket.h>
1441edb306SCy Schubert # include <sys/sockio.h>
1541edb306SCy Schubert #include <sys/ioctl.h>
1641edb306SCy Schubert #include <netinet/in_systm.h>
1741edb306SCy Schubert #include <netinet/in.h>
1841edb306SCy Schubert #include <net/if.h>
1941edb306SCy Schubert #include <netinet/if_ether.h>
2041edb306SCy Schubert # include <net/if_arp.h>
2141edb306SCy Schubert #include <netinet/in.h>
2241edb306SCy Schubert #include <netinet/ip.h>
2341edb306SCy Schubert #include <netinet/ip_var.h>
2441edb306SCy Schubert #include <netinet/tcp.h>
2541edb306SCy Schubert #include <stdio.h>
2641edb306SCy Schubert #include <errno.h>
2741edb306SCy Schubert #include <netdb.h>
2841edb306SCy Schubert #include "ipsend.h"
2941edb306SCy Schubert #include "iplang/iplang.h"
3041edb306SCy Schubert 
3141edb306SCy Schubert 
3241edb306SCy Schubert /*
3341edb306SCy Schubert  * lookup host and return
3441edb306SCy Schubert  * its IP address in address
3541edb306SCy Schubert  * (4 bytes)
3641edb306SCy Schubert  */
37*efeb8bffSCy Schubert int	resolve(char *host, char *address)
3841edb306SCy Schubert {
3941edb306SCy Schubert         struct	hostent	*hp;
4041edb306SCy Schubert         u_long	add;
4141edb306SCy Schubert 
4241edb306SCy Schubert 	add = inet_addr(host);
4341edb306SCy Schubert 	if (add == -1)
4441edb306SCy Schubert 	    {
4541edb306SCy Schubert 		if (!(hp = gethostbyname(host)))
4641edb306SCy Schubert 		    {
4741edb306SCy Schubert 			fprintf(stderr, "unknown host: %s\n", host);
4841edb306SCy Schubert 			return -1;
4941edb306SCy Schubert 		    }
5041edb306SCy Schubert 		bcopy((char *)hp->h_addr, (char *)address, 4);
5141edb306SCy Schubert 		return 0;
5241edb306SCy Schubert 	}
5341edb306SCy Schubert 	bcopy((char*)&add, address, 4);
5441edb306SCy Schubert 	return 0;
5541edb306SCy Schubert }
5641edb306SCy Schubert 
5741edb306SCy Schubert /*
5841edb306SCy Schubert  * ARP for the MAC address corresponding
5941edb306SCy Schubert  * to the IP address.  This taken from
6041edb306SCy Schubert  * some BSD program, I cant remember which.
6141edb306SCy Schubert  */
6241edb306SCy Schubert int	arp(ip, ether)
6341edb306SCy Schubert 	char	*ip;
6441edb306SCy Schubert 	char	*ether;
6541edb306SCy Schubert {
6641edb306SCy Schubert 	static	int	sfd = -1;
6741edb306SCy Schubert 	static	char	ethersave[6], ipsave[4];
6841edb306SCy Schubert 	struct	arpreq	ar;
6941edb306SCy Schubert 	struct	sockaddr_in	*sin, san;
7041edb306SCy Schubert 	struct	hostent	*hp;
7141edb306SCy Schubert 	int	fd;
7241edb306SCy Schubert 
7341edb306SCy Schubert #ifdef	IPSEND
7441edb306SCy Schubert 	if (arp_getipv4(ip, ether) == 0)
7541edb306SCy Schubert 		return 0;
7641edb306SCy Schubert #endif
7741edb306SCy Schubert 	if (!bcmp(ipsave, ip, 4)) {
7841edb306SCy Schubert 		bcopy(ethersave, ether, 6);
7941edb306SCy Schubert 		return 0;
8041edb306SCy Schubert 	}
8141edb306SCy Schubert 	fd = -1;
8241edb306SCy Schubert 	bzero((char *)&ar, sizeof(ar));
8341edb306SCy Schubert 	sin = (struct sockaddr_in *)&ar.arp_pa;
8441edb306SCy Schubert 	sin->sin_family = AF_INET;
8541edb306SCy Schubert 	bcopy(ip, (char *)&sin->sin_addr.s_addr, 4);
8641edb306SCy Schubert 	if ((hp = gethostbyaddr(ip, 4, AF_INET)))
8741edb306SCy Schubert # if SOLARIS && (SOLARIS2 >= 10)
8841edb306SCy Schubert 		if (!(ether_hostton(hp->h_name, (struct ether_addr *)ether)))
8941edb306SCy Schubert # else
9041edb306SCy Schubert 		if (!(ether_hostton(hp->h_name, ether)))
9141edb306SCy Schubert # endif
9241edb306SCy Schubert 			goto savearp;
9341edb306SCy Schubert 
9441edb306SCy Schubert 	if (sfd == -1)
9541edb306SCy Schubert 		if ((sfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
9641edb306SCy Schubert 		    {
9741edb306SCy Schubert 			perror("arp: socket");
9841edb306SCy Schubert 			return -1;
9941edb306SCy Schubert 		    }
10041edb306SCy Schubert tryagain:
10141edb306SCy Schubert 	if (ioctl(sfd, SIOCGARP, (caddr_t)&ar) == -1)
10241edb306SCy Schubert 	    {
10341edb306SCy Schubert 		if (fd == -1)
10441edb306SCy Schubert 		    {
10541edb306SCy Schubert 			bzero((char *)&san, sizeof(san));
10641edb306SCy Schubert 			san.sin_family = AF_INET;
10741edb306SCy Schubert 			san.sin_port = htons(1);
10841edb306SCy Schubert 			bcopy(ip, &san.sin_addr.s_addr, 4);
10941edb306SCy Schubert 			fd = socket(AF_INET, SOCK_DGRAM, 0);
11041edb306SCy Schubert 			(void) sendto(fd, ip, 4, 0,
11141edb306SCy Schubert 				      (struct sockaddr *)&san, sizeof(san));
11241edb306SCy Schubert 			sleep(1);
11341edb306SCy Schubert 			(void) close(fd);
11441edb306SCy Schubert 			goto tryagain;
11541edb306SCy Schubert 		    }
11641edb306SCy Schubert 		fprintf(stderr, "(%s):", inet_ntoa(sin->sin_addr));
11741edb306SCy Schubert 		if (errno != ENXIO)
11841edb306SCy Schubert 			perror("SIOCGARP");
11941edb306SCy Schubert 		return -1;
12041edb306SCy Schubert 	    }
12141edb306SCy Schubert 
12241edb306SCy Schubert 	if ((ar.arp_ha.sa_data[0] == 0) && (ar.arp_ha.sa_data[1] == 0) &&
12341edb306SCy Schubert 	    (ar.arp_ha.sa_data[2] == 0) && (ar.arp_ha.sa_data[3] == 0) &&
12441edb306SCy Schubert 	    (ar.arp_ha.sa_data[4] == 0) && (ar.arp_ha.sa_data[5] == 0)) {
12541edb306SCy Schubert 		fprintf(stderr, "(%s):", inet_ntoa(sin->sin_addr));
12641edb306SCy Schubert 		return -1;
12741edb306SCy Schubert 	}
12841edb306SCy Schubert 
12941edb306SCy Schubert 	bcopy(ar.arp_ha.sa_data, ether, 6);
13041edb306SCy Schubert savearp:
13141edb306SCy Schubert 	bcopy(ether, ethersave, 6);
13241edb306SCy Schubert 	bcopy(ip, ipsave, 4);
13341edb306SCy Schubert 	return 0;
13441edb306SCy Schubert }
135