aboutsummaryrefslogtreecommitdiff
path: root/sbin/ipf/ipsend/arp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/ipf/ipsend/arp.c')
-rw-r--r--sbin/ipf/ipsend/arp.c129
1 files changed, 129 insertions, 0 deletions
diff --git a/sbin/ipf/ipsend/arp.c b/sbin/ipf/ipsend/arp.c
new file mode 100644
index 000000000000..a9409093213f
--- /dev/null
+++ b/sbin/ipf/ipsend/arp.c
@@ -0,0 +1,129 @@
+
+/*
+ * arp.c (C) 1995-1998 Darren Reed
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+#include <sys/types.h>
+#include <sys/socket.h>
+# include <sys/sockio.h>
+#include <sys/ioctl.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <netinet/if_ether.h>
+# include <net/if_arp.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <stdio.h>
+#include <errno.h>
+#include <netdb.h>
+#include "ipsend.h"
+#include "iplang/iplang.h"
+
+
+/*
+ * lookup host and return
+ * its IP address in address
+ * (4 bytes)
+ */
+int resolve(char *host, char *address)
+{
+ struct hostent *hp;
+ u_long add;
+
+ add = inet_addr(host);
+ if (add == -1)
+ {
+ if (!(hp = gethostbyname(host)))
+ {
+ fprintf(stderr, "unknown host: %s\n", host);
+ return (-1);
+ }
+ bcopy((char *)hp->h_addr, (char *)address, 4);
+ return (0);
+ }
+ bcopy((char*)&add, address, 4);
+ return (0);
+}
+
+/*
+ * ARP for the MAC address corresponding
+ * to the IP address. This taken from
+ * some BSD program, I cant remember which.
+ */
+int arp(ip, ether)
+ char *ip;
+ char *ether;
+{
+ static int sfd = -1;
+ static char ethersave[6], ipsave[4];
+ struct arpreq ar;
+ struct sockaddr_in *sin, san;
+ struct hostent *hp;
+ int fd;
+
+#ifdef IPSEND
+ if (arp_getipv4(ip, ether) == 0)
+ return (0);
+#endif
+ if (!bcmp(ipsave, ip, 4)) {
+ bcopy(ethersave, ether, 6);
+ return (0);
+ }
+ fd = -1;
+ bzero((char *)&ar, sizeof(ar));
+ sin = (struct sockaddr_in *)&ar.arp_pa;
+ sin->sin_family = AF_INET;
+ bcopy(ip, (char *)&sin->sin_addr.s_addr, 4);
+ if ((hp = gethostbyaddr(ip, 4, AF_INET)))
+# if SOLARIS && (SOLARIS2 >= 10)
+ if (!(ether_hostton(hp->h_name, (struct ether_addr *)ether)))
+# else
+ if (!(ether_hostton(hp->h_name, ether)))
+# endif
+ goto savearp;
+
+ if (sfd == -1)
+ if ((sfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
+ {
+ perror("arp: socket");
+ return (-1);
+ }
+tryagain:
+ if (ioctl(sfd, SIOCGARP, (caddr_t)&ar) == -1)
+ {
+ if (fd == -1)
+ {
+ bzero((char *)&san, sizeof(san));
+ san.sin_family = AF_INET;
+ san.sin_port = htons(1);
+ bcopy(ip, &san.sin_addr.s_addr, 4);
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ (void) sendto(fd, ip, 4, 0,
+ (struct sockaddr *)&san, sizeof(san));
+ sleep(1);
+ (void) close(fd);
+ goto tryagain;
+ }
+ fprintf(stderr, "(%s):", inet_ntoa(sin->sin_addr));
+ if (errno != ENXIO)
+ perror("SIOCGARP");
+ return (-1);
+ }
+
+ if ((ar.arp_ha.sa_data[0] == 0) && (ar.arp_ha.sa_data[1] == 0) &&
+ (ar.arp_ha.sa_data[2] == 0) && (ar.arp_ha.sa_data[3] == 0) &&
+ (ar.arp_ha.sa_data[4] == 0) && (ar.arp_ha.sa_data[5] == 0)) {
+ fprintf(stderr, "(%s):", inet_ntoa(sin->sin_addr));
+ return (-1);
+ }
+
+ bcopy(ar.arp_ha.sa_data, ether, 6);
+savearp:
+ bcopy(ether, ethersave, 6);
+ bcopy(ip, ipsave, 4);
+ return (0);
+}