1145519Sdarrenr/*	$FreeBSD$	*/
2145510Sdarrenr
322514Sdarrenr/*
453024Sguido * arp.c (C) 1995-1998 Darren Reed
522514Sdarrenr *
680486Sdarrenr * See the IPFILTER.LICENCE file for details on licencing.
722514Sdarrenr */
8145510Sdarrenr#if !defined(lint)
9145510Sdarrenrstatic const char sccsid[] = "@(#)arp.c	1.4 1/11/96 (C)1995 Darren Reed";
10255332Scystatic const char rcsid[] = "@(#)$Id$";
1192686Sdarrenr#endif
1222514Sdarrenr#include <sys/types.h>
1322514Sdarrenr#include <sys/socket.h>
14153881Sguido#if !defined(ultrix) && !defined(hpux) && !defined(__hpux) && !defined(__osf__) && !defined(_AIX51)
15170268Sdarrenr# include <sys/sockio.h>
1631183Speter#endif
1722514Sdarrenr#include <sys/ioctl.h>
18145510Sdarrenr#include <netinet/in_systm.h>
1922514Sdarrenr#include <netinet/in.h>
2022514Sdarrenr#include <net/if.h>
2153024Sguido#include <netinet/if_ether.h>
2231183Speter#ifndef	ultrix
23170268Sdarrenr# include <net/if_arp.h>
2431183Speter#endif
2524583Sdarrenr#include <netinet/in.h>
26145510Sdarrenr#include <netinet/ip.h>
2724583Sdarrenr#include <netinet/ip_var.h>
2824583Sdarrenr#include <netinet/tcp.h>
29145510Sdarrenr#include <stdio.h>
30145510Sdarrenr#include <errno.h>
31145510Sdarrenr#include <netdb.h>
3224583Sdarrenr#include "ipsend.h"
3353024Sguido#include "iplang/iplang.h"
3422514Sdarrenr
3522514Sdarrenr
3622514Sdarrenr/*
3722514Sdarrenr * lookup host and return
3822514Sdarrenr * its IP address in address
3922514Sdarrenr * (4 bytes)
4022514Sdarrenr */
41145510Sdarrenrint	resolve(host, address)
42255332Scy	char	*host, *address;
4322514Sdarrenr{
4422514Sdarrenr        struct	hostent	*hp;
4522514Sdarrenr        u_long	add;
4622514Sdarrenr
4722514Sdarrenr	add = inet_addr(host);
4822514Sdarrenr	if (add == -1)
4922514Sdarrenr	    {
5022514Sdarrenr		if (!(hp = gethostbyname(host)))
5122514Sdarrenr		    {
5222514Sdarrenr			fprintf(stderr, "unknown host: %s\n", host);
5322514Sdarrenr			return -1;
5422514Sdarrenr		    }
5522514Sdarrenr		bcopy((char *)hp->h_addr, (char *)address, 4);
5622514Sdarrenr		return 0;
5722514Sdarrenr	}
5822514Sdarrenr	bcopy((char*)&add, address, 4);
5922514Sdarrenr	return 0;
6022514Sdarrenr}
6122514Sdarrenr
6222514Sdarrenr/*
6322514Sdarrenr * ARP for the MAC address corresponding
6422514Sdarrenr * to the IP address.  This taken from
6522514Sdarrenr * some BSD program, I cant remember which.
6622514Sdarrenr */
6722514Sdarrenrint	arp(ip, ether)
68255332Scy	char	*ip;
69255332Scy	char	*ether;
7022514Sdarrenr{
7122514Sdarrenr	static	int	sfd = -1;
7222514Sdarrenr	static	char	ethersave[6], ipsave[4];
7322514Sdarrenr	struct	arpreq	ar;
7422514Sdarrenr	struct	sockaddr_in	*sin, san;
7522514Sdarrenr	struct	hostent	*hp;
7622514Sdarrenr	int	fd;
7722514Sdarrenr
7853024Sguido#ifdef	IPSEND
7953024Sguido	if (arp_getipv4(ip, ether) == 0)
8053024Sguido		return 0;
8153024Sguido#endif
8222514Sdarrenr	if (!bcmp(ipsave, ip, 4)) {
8322514Sdarrenr		bcopy(ethersave, ether, 6);
8422514Sdarrenr		return 0;
8522514Sdarrenr	}
8622514Sdarrenr	fd = -1;
8722514Sdarrenr	bzero((char *)&ar, sizeof(ar));
8822514Sdarrenr	sin = (struct sockaddr_in *)&ar.arp_pa;
8922514Sdarrenr	sin->sin_family = AF_INET;
9022514Sdarrenr	bcopy(ip, (char *)&sin->sin_addr.s_addr, 4);
9131183Speter#ifndef	hpux
9222514Sdarrenr	if ((hp = gethostbyaddr(ip, 4, AF_INET)))
93145510Sdarrenr# if SOLARIS && (SOLARIS2 >= 10)
94145510Sdarrenr		if (!(ether_hostton(hp->h_name, (struct ether_addr *)ether)))
95145510Sdarrenr# else
9622514Sdarrenr		if (!(ether_hostton(hp->h_name, ether)))
97145510Sdarrenr# endif
9822514Sdarrenr			goto savearp;
9931183Speter#endif
10022514Sdarrenr
10122514Sdarrenr	if (sfd == -1)
10222514Sdarrenr		if ((sfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
10322514Sdarrenr		    {
10422514Sdarrenr			perror("arp: socket");
10522514Sdarrenr			return -1;
10622514Sdarrenr		    }
10722514Sdarrenrtryagain:
10822514Sdarrenr	if (ioctl(sfd, SIOCGARP, (caddr_t)&ar) == -1)
10922514Sdarrenr	    {
11022514Sdarrenr		if (fd == -1)
11122514Sdarrenr		    {
11222514Sdarrenr			bzero((char *)&san, sizeof(san));
11322514Sdarrenr			san.sin_family = AF_INET;
11422514Sdarrenr			san.sin_port = htons(1);
11522514Sdarrenr			bcopy(ip, &san.sin_addr.s_addr, 4);
11622514Sdarrenr			fd = socket(AF_INET, SOCK_DGRAM, 0);
11722514Sdarrenr			(void) sendto(fd, ip, 4, 0,
11822514Sdarrenr				      (struct sockaddr *)&san, sizeof(san));
11922514Sdarrenr			sleep(1);
12022514Sdarrenr			(void) close(fd);
12122514Sdarrenr			goto tryagain;
12222514Sdarrenr		    }
12322514Sdarrenr		fprintf(stderr, "(%s):", inet_ntoa(sin->sin_addr));
12422514Sdarrenr		if (errno != ENXIO)
12522514Sdarrenr			perror("SIOCGARP");
12622514Sdarrenr		return -1;
12722514Sdarrenr	    }
12822514Sdarrenr
129145510Sdarrenr	if ((ar.arp_ha.sa_data[0] == 0) && (ar.arp_ha.sa_data[1] == 0) &&
130145510Sdarrenr	    (ar.arp_ha.sa_data[2] == 0) && (ar.arp_ha.sa_data[3] == 0) &&
131145510Sdarrenr	    (ar.arp_ha.sa_data[4] == 0) && (ar.arp_ha.sa_data[5] == 0)) {
132145510Sdarrenr		fprintf(stderr, "(%s):", inet_ntoa(sin->sin_addr));
133145510Sdarrenr		return -1;
134145510Sdarrenr	}
135145510Sdarrenr
13622514Sdarrenr	bcopy(ar.arp_ha.sa_data, ether, 6);
13722514Sdarrenrsavearp:
13822514Sdarrenr	bcopy(ether, ethersave, 6);
13922514Sdarrenr	bcopy(ip, ipsave, 4);
14022514Sdarrenr	return 0;
14122514Sdarrenr}
142