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