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