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