I found this from src.doc.ic.ac.uk:/computing/comms/tcpip/misc/EHP.1
Just type
/bin/sh EPH.1
to unpack the archive.
-Bruce
#!/bin/sh
# to extract, remove the header and type "sh filename"
if `test ! -s ./etherhostprobe.1`
then
echo "writing ./etherhostprobe.1"
cat > ./etherhostprobe.1 << '\Rogue\Monster\'
.TH ETHERHOSTPROBE 1 "SRI Information Sciences and Technology Center" 18-Jul-88
.SH ETHERHOSTPROBE
etherhostprobe \- Ethernet Host Prober
.SH ORIGIN
SRI Information Sciences and Technology Center
.SH SYNOPSIS
.B "etherhostprobe begin-addr end-addr"
.SH DESCRIPTION
Probes each Internet address in the range starting with ``begin-addr'' and
ending with ``end-addr'' (both ``begin-addr' and ``end-addr'' can be either
hostnames or dotted-decimal Internet addresses) by forcing an ARP
packet to be sent to each Internet address in the range specified.
Up to 5 ARPs per hosts will be send at 0.25 second intervals.
This program uses the operating system's ARP tables, and thus may degrade
performance somewhat while running.
For example:
.nf
.RS
.sp 0.5v
etherhostprobe 128.18.0.1 128.18.255.254
.sp 0.5v
.fi
.RE
would probe the entire SRINET address space with the exception of the
128.18.0.0 and 128.18.255.255 broadcast addresses.
A list of hosts found will be sent to standard output. The format of each
line is:
.nf
.RS
.sp 0.5v
ethernet-addr internet-addr hostname
.sp 0.5v
.fi
.RE
The ``ethernet-addr'' is the colon-separated six-octet Ethernet address of
the host,
the ``internet-addr'' is the dotted-decimal Internet address of the host,
and the ``hostname'' is the primary name of the host as supplied by the
gethostbyaddr library routine.
The ``hostname'' will be omitted if the Internet address is unknown to
gethostbyaddr.
.SH "RETURN VALUE"
Returns 0 if all went well, -1 if problems occurred.
.SH BUGS
Does not detect hosts that do not respond to ARP (either because they are
down or because they are not running ARP).
.SH HISTORY
.IP 18-Jul-88 0.75i
Written by Paul E. McKenney, SRI Information Sciences and Technology Center.
\Rogue\Monster\
else
echo "will not overwrite ./etherhostprobe.1"
fi
if [ `wc -c ./etherhostprobe.1 | awk '{printf $1}'` -ne 1742 ]
then
echo `wc -c ./etherhostprobe.1 | awk '{print "Got " $1 ", Expected " 1742}'`
fi
if `test ! -s ./Makefile`
then
echo "writing ./Makefile"
cat > ./Makefile << '\Rogue\Monster\'
#########################################################################
# #
# Makefile for network datagram test programs. #
# #
#########################################################################
CFLAGS = -gx
BINS = etherhostprobe
all: $(BINS)
OBJS = \
etherhostprobe.o \
ethertoa.o \
fastsleep.o \
mk_udp_ncon.o \
tx_arp.o \
tx_hostname.o
etherhostprobe: ${OBJS}
cc -o etherhostprobe ${OBJS}
.c.o:; cc $(CFLAGS) -c $<
\Rogue\Monster\
else
echo "will not overwrite ./Makefile"
fi
if [ `wc -c ./Makefile | awk '{printf $1}'` -ne 459 ]
then
echo `wc -c ./Makefile | awk '{print "Got " $1 ", Expected " 459}'`
fi
if `test ! -s ./etherhostprobe.c`
then
echo "writing ./etherhostprobe.c"
cat > ./etherhostprobe.c << '\Rogue\Monster\'
/************************************************************************
* *
* File: etherhostprobe.c *
* *
* ETHERnet HOST PROBE routine. Probes the ethernet (by forcing *
* ARP's) for the specified range of IP addresses. *
* This program is unable to probe the IP address of the host on *
* which it is running. *
* *
* Usage: *
* etherhostprobe begin end *
* where `begin' is the first IP address (or host name) in the *
* range to be probed, and `end' is the last IP address (or host *
* name in the range to be probed. *
* *
* Written 25-Nov-87 by Paul E. McKenney, SRI International. *
* Copyright (c) 1987 SRI International. *
* *
************************************************************************/
/*
* $Log: etherhostprobe.c,v $
* Revision 1.1 87/12/02 08:12:34 mckenney
* Initial revision
*
*/
/* Include files. */
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <netdb.h>
/* Type definitions local to this file. */
#define INCR_IP(ip_addr) \
{ \
if ((++ip_addr.s_b4 == 0) && \
(++ip_addr.s_b3 == 0) && \
(++ip_addr.s_b2 == 0)) \
ip_addr.s_b1++; \
}
/* Functions exported from this file. */
/* Functions local to this file. */
/* Variables exported from this file. */
/* Variables local to this file. */
main(argc, argv)
int argc;
char *argv[];
{
struct sockaddr_in bsa; /* Beginning Socket Address. */
struct ether_addr ea; /* Ethernet Address. */
char *em; /* Error Message pointer. */
struct sockaddr_in esa; /* Ending Socket Address. */
int i;
int retval; /* RETurn VALue. */
struct sockaddr_in sa; /* current Socket Address. */
/* Check command line arguments. */
if (argc != 3)
{
fprintf(stderr, "Usage: %s begin-IP end_IP\n", argv[0]);
exit(-1);
}
/* Translate beginning IP address into socket address struct. */
bzero((caddr_t)&bsa, sizeof(bsa));
switch (tx_hostname(argv[1], &bsa, &em))
{
case -2:
perror(em);
exit(-1);
case -1:
fprintf(stderr, "%s", em);
exit(-1);
}
/* Translate ending IP address into socket address struct. */
bzero((caddr_t)&esa, sizeof(esa));
switch (tx_hostname(argv[2], &esa, &em))
{
case -2:
perror(em);
exit(-1);
case -1:
fprintf(stderr, "%s", em);
exit(-1);
}
/* Initialize for scan loop. */
bcopy((caddr_t)&bsa, (caddr_t)&sa, sizeof(sa));
/* Each pass through the following loop looks for one IP */
/* address, with up to one second delay. This means 18 hours */
/* to completely scan a class B network. */
#define SA_IP (sa.sin_addr.S_un.S_un_b)
#define ESA_IP (esa.sin_addr.S_un.S_un_b)
while ((SA_IP.s_b1 < ESA_IP.s_b1) ||
((SA_IP.s_b1 == ESA_IP.s_b1) &&
((SA_IP.s_b2 < ESA_IP.s_b2) ||
((SA_IP.s_b2 == ESA_IP.s_b2) &&
((SA_IP.s_b3 < ESA_IP.s_b3) ||
((SA_IP.s_b3 == ESA_IP.s_b3) &&
(SA_IP.s_b4 <= ESA_IP.s_b4)))))))
{
/* Initiate the arp. If this fails immediately, ditch */
/* and go to the next address. */
if ((retval = tx_arp_init(&sa, &ea, &em)) < 0)
{
INCR_IP(SA_IP);
continue;
}
/* If we did not get an immediate answer, wait a bit */
/* and check again. */
if (retval != 1)
for (i = 0; i < 4; i++)
{
fastsleep(0L, 250000L);
if ((retval = tx_arp_chk(&sa, &ea, &em)) == 1)
break;
}
/* If we got something, print it out. */
if (retval == 1)
{
struct hostent *hostent;
char *hostname;
hostname = "";
if ((hostent = gethostbyaddr(&sa.sin_addr,
sizeof(sa.sin_addr),
AF_INET)) != NULL)
hostname = hostent->h_name;
(void)printf("%-17s %-15s %s\n",
ethertoa(&ea),
inet_ntoa(sa.sin_addr),
hostname);
fflush(stdout);
}
/* Increment to the next IP address. */
INCR_IP(SA_IP);
}
/* When done, leave! */
exit(0);
}
\Rogue\Monster\
else
echo "will not overwrite ./etherhostprobe.c"
fi
if [ `wc -c ./etherhostprobe.c | awk '{printf $1}'` -ne 4043 ]
then
echo `wc -c ./etherhostprobe.c | awk '{print "Got " $1 ", Expected " 4043}'`
fi
if `test ! -s ./ethertoa.c`
then
echo "writing ./ethertoa.c"
cat > ./ethertoa.c << '\Rogue\Monster\'
/************************************************************************
* *
* File: ethertoa.c *
* *
* ETHERnet address TO Ascii (and vice versa). *
* *
* Written 08-Sep-87 by Paul E. McKenney, SRI International. *
* *
************************************************************************/
/*
* $Log: ethertoa.c,v $
* Revision 2.0 88/09/23 18:27:40 mckenney
* .
*
*/
/* Include files. */
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
/* Type definitions local to this file. */
/* Functions exported from this file. */
extern int atoether(); /* Ascii TO ETHERnet address. */
extern char *ethertoa(); /* ETHERnet address TO Ascii. */
/* Functions local to this file. */
/* Variables exported from this file. */
/* Variables local to this file. */
/* Ascii TO ETHERnet address conversion. Returns TRUE if the string */
/* can be converted, FALSE otherwise. Address must be of form: */
/* xx:xx:xx:xx:xx:xx */
int
atoether(a, ea)
char *a; /* Ascii address. */
struct ether_addr *ea; /* Ethernet Address. */
{
int o0;
int o1;
int o2;
int o3;
int o4;
int o5;
if (sscanf(a, "%x:%x:%x:%x:%x:%x", &o0, &o1, &o2, &o3, &o4, &o5) != 6)
return (0);
ea->ether_addr_octet[0] = o0;
ea->ether_addr_octet[1] = o1;
ea->ether_addr_octet[2] = o2;
ea->ether_addr_octet[3] = o3;
ea->ether_addr_octet[4] = o4;
ea->ether_addr_octet[5] = o5;
return (1);
}
/* ETHERnet address TO Ascii conversion. Note that the returned string */
/* is kept in a static buffer, so copy it if you want to keep it! */
extern char *
ethertoa(ea)
struct ether_addr *ea; /* Ethernet Address. */
{
static char addr[25]; /* ascii-ized ADDRess. */
(void)sprintf(addr, "%02x:%02x:%02x:%02x:%02x:%02x",
ea->ether_addr_octet[0],
ea->ether_addr_octet[1],
ea->ether_addr_octet[2],
ea->ether_addr_octet[3],
ea->ether_addr_octet[4],
ea->ether_addr_octet[5]);
return (addr);
}
\Rogue\Monster\
else
echo "will not overwrite ./ethertoa.c"
fi
if [ `wc -c ./ethertoa.c | awk '{printf $1}'` -ne 2122 ]
then
echo `wc -c ./ethertoa.c | awk '{print "Got " $1 ", Expected " 2122}'`
fi
if `test ! -s ./fastsleep.c`
then
echo "writing ./fastsleep.c"
cat > ./fastsleep.c << '\Rogue\Monster\'
/*
* Copyright (c) 1980 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*
* Hacked from sleep.c 04-Feb-87 Paul E. McKenney, SRI International
*/
#include <sys/time.h>
#include <signal.h>
#define setvec(vec, a) \
vec.sv_handler = a; vec.sv_mask = vec.sv_onstack = 0
static int ringring;
fastsleep(n, frac)
unsigned n;
unsigned frac;
{
int sleepx(), omask;
struct itimerval itv, oitv;
register struct itimerval *itp = &itv;
struct sigvec vec, ovec;
while (frac > 999999) {
frac -= 1000000;
n += 1;
}
if ((n == 0) &&
(frac == 0))
return;
timerclear(&itp->it_interval);
timerclear(&itp->it_value);
if (setitimer(ITIMER_REAL, itp, &oitv) < 0)
return;
itp->it_value.tv_sec = n;
itp->it_value.tv_usec = frac;
if (timerisset(&oitv.it_value)) {
if (timercmp(&oitv.it_value, &itp->it_value, >)) {
oitv.it_value.tv_sec -= itp->it_value.tv_sec;
oitv.it_value.tv_usec -= itp->it_value.tv_usec;
} else {
itp->it_value = oitv.it_value;
/*
* This is a hack, but we must have time to
* return from the setitimer after the alarm
* or else it'll be restarted. And, anyway,
* sleep never did anything more than this before.
*/
oitv.it_value.tv_sec = 1;
oitv.it_value.tv_usec = 0;
}
}
setvec(vec, sleepx);
(void) sigvec(SIGALRM, &vec, &ovec);
omask = sigblock(sigmask(SIGALRM));
ringring = 0;
(void) setitimer(ITIMER_REAL, itp, (struct itimerval *)0);
while (!ringring)
sigpause(omask &~ sigmask(SIGALRM));
(void) sigvec(SIGALRM, &ovec, (struct sigvec *)0);
(void) sigsetmask(omask);
(void) setitimer(ITIMER_REAL, &oitv, (struct itimerval *)0);
}
static
sleepx()
{
ringring = 1;
}
\Rogue\Monster\
else
echo "will not overwrite ./fastsleep.c"
fi
if [ `wc -c ./fastsleep.c | awk '{printf $1}'` -ne 1774 ]
then
echo `wc -c ./fastsleep.c | awk '{print "Got " $1 ", Expected " 1774}'`
fi
if `test ! -s ./mk_udp_ncon.c`
then
echo "writing ./mk_udp_ncon.c"
cat > ./mk_udp_ncon.c << '\Rogue\Monster\'
/************************************************************************
* *
* File: mk_udp_ncon.c *
* *
* MaKe UDP No-CONnection socket. *
* *
* Written by Paul E. McKenney, SRI International. *
* *
************************************************************************/
/*
* $Log: mk_udp_ncon.c,v $
* Revision 2.0 88/09/23 18:28:08 mckenney
* .
*
* Revision 1.1 87/09/02 10:16:53 mckenney
* Initial revision
*
*/
/* Include files. */
#include <stdio.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <strings.h>
/* Type definitions local to this file. */
/* Functions exported from this file. */
extern int mk_udp_ncon(); /* MaKe UDP No_CONnect. socket. */
/* Functions local to this file. */
/* Variables exported from this file. */
/* Variables local to this file. */
/* MaKe UPD No-CONnection socket. Return file descriptor of socket. */
/* Returns -1 if there was a system call problem, points em to a string */
/* containing the system call name. */
/* Returns -2 if there were other problems and points em to a */
/* string containing a human-readable error message. */
/* Creates a connectionless UDP socket. */
extern int mk_udp_ncon(em)
char **em; /* Error Message pointer. */
{
int s; /* Socket. */
/* Create the socket, yielding a file descriptor we can do I/O */
/* on and connect to. */
if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
{
*em = "socket";
return (-1);
}
return (s);
}
\Rogue\Monster\
else
echo "will not overwrite ./mk_udp_ncon.c"
fi
if [ `wc -c ./mk_udp_ncon.c | awk '{printf $1}'` -ne 1635 ]
then
echo `wc -c ./mk_udp_ncon.c | awk '{print "Got " $1 ", Expected " 1635}'`
fi
if `test ! -s ./tx_arp.c`
then
echo "writing ./tx_arp.c"
cat > ./tx_arp.c << '\Rogue\Monster\'
/************************************************************************
* *
* File: tx_arp.c *
* *
* TranlateX (x is silent) ip address to ethernet address using *
* Address Resolution Protocol. *
* The most convenient routine to use is tx_arp itself, but be *
* aware that it can hang (on sleep's) for several minutes waiting *
* for an ARP attempt to time out. Programs that cannot wait *
* that long or that can't spare SIGALRM should use the routines: *
* tx_arp_init to start the arp. *
* tx_arp_chk to check on its progress. *
* tx_arp_wait to hang waiting for the arp to complete.*
* (uses SIGALRM). *
* *
* Written 08-Sep-87 by Paul E. McKenney, SRI International. *
* *
************************************************************************/
/*
* $Log: tx_arp.c,v $
* Revision 2.0 88/09/23 18:28:23 mckenney
* .
*
* Revision 1.2 88/09/19 09:15:37 mckenney
* Added tx_arp_perm and tx_arp_tmp routines
*
*/
/* Include files. */
#include <stdio.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <signal.h>
/* Type definitions local to this file. */
/* Functions exported from this file. */
extern int tx_arp(); /* TX using ARP. */
extern int tx_arp_chk(); /* TX ARP CHecK. */
extern int tx_arp_init(); /* TX ARP INITiate. */
extern int tx_arp_perm(); /* make entry PERManent.*/
extern int tx_arp_tmp(); /* make entry TeMPorary.*/
extern int tx_arp_wait(); /* TX ARP WAIT for done.*/
/* Functions local to this file. */
/* Variables exported from this file. */
/* Variables local to this file. */
/* TranslateX using Address Resolution Protocol. Internet address */
/* (in the form of a sockaddr_in *) is passed in through sa, puts */
/* resulting ethernet address into ea. Returns 0 if all went well, */
/* -1 if a system call failed (em is pointed to the name of the system */
/* call in this case). */
/* Note that no arp will actually be transmitted if the address is */
/* already in the cache. */
extern int
tx_arp(sa, ea, em)
struct sockaddr_in *sa; /* Socket Address. */
struct ether_addr *ea; /* Ethernet Address. */
char **em; /* Error Message pointer. */
{
int retval; /* RETurn VALue. */
/* Initiate the arp. If this succeeds immediately (because the */
/* arp was already cached), just return. */
if ((retval = tx_arp_init(sa, ea, em)) < 0)
return (retval);
if (retval == 1)
return (0);
/* Wait for the arp to complete. */
while ((retval = tx_arp_wait(sa, ea, em)) == 0)
sleep(1);
return (retval);
}
/* TranslateX using ARP, CHecK results. Internet address */
/* (in the form of a sockaddr_in *) is passed in through sa, puts */
/* resulting ethernet address into ea. Returns 1 if the desired entry */
/* is in the cache, 0 if the arp is in process, and -1 if a system call */
/* failed (em is pointed to the name of the system call in this case). */
extern int
tx_arp_chk(sa, ea, em)
struct sockaddr_in *sa; /* Socket Address. */
struct ether_addr *ea; /* Ethernet Address. */
char **em; /* Error Message pointer. */
{
static struct arpreq arpreq; /* ARP REQuest structure. */
int s; /* Socket file descriptor. */
/* Set up arp request struct. */
bzero((caddr_t)&arpreq, sizeof(arpreq));
bcopy(sa, (caddr_t)&arpreq.arp_pa, sizeof(*sa));
arpreq.arp_pa.sa_family = AF_INET;
arpreq.arp_ha.sa_family = AF_UNSPEC;
/* Open a socket to do ioctls on (just to arp!). */
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
*em = "socket";
return (-1);
}
/* Do the ioctl, check the result. */
if (ioctl(s, SIOCGARP, (caddr_t)&arpreq) == -1)
{
*em = "ioctl SIOCGARP";
close(s);
return (-1);
}
close(s);
(void)bcopy(arpreq.arp_ha.sa_data, ea, sizeof(struct ether_addr));
return ((arpreq.arp_flags & ATF_COM) != 0);
}
/* TranslateX using ARP, INITiate process. Internet address */
/* (in the form of a sockaddr_in *) is passed in through sa, puts */
/* resulting ethernet address into ea. Returns 1 if the desired entry */
/* is already in the cache, 0 if the arp is in process, and -1 if a */
/* system call failed (em is pointed to the name of the system call in */
/* this case). */
int
tx_arp_init(sa, ea, em)
struct sockaddr_in *sa; /* Socket Address. */
struct ether_addr *ea; /* Ethernet Address. */
char **em; /* Error Message pointer. */
{
static struct arpreq arpreq;
int discard = -1;
int (*oldsig)();
int retval;
int s = -1;
/* Set up arp request struct. */
bzero((caddr_t)&arpreq, sizeof(arpreq));
bcopy(sa, (caddr_t)&arpreq.arp_pa, sizeof(*sa));
arpreq.arp_pa.sa_family = AF_INET;
arpreq.arp_ha.sa_family = AF_UNSPEC;
/* Get a socket suitable for arp'ing. */
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
*em = "socket";
retval = -1;
goto cleanup;
}
/* Check to see if it is already in cache. */
if ((ioctl(s, SIOCGARP, (caddr_t)&arpreq) != -1) &&
((arpreq.arp_flags & ATF_COM) != 0))
{
(void)bcopy(arpreq.arp_ha.sa_data, ea,
sizeof(struct ether_addr));
retval = 1;
goto cleanup;
}
/* Send a udp packet to force the system to send an arp. We */
/* send to the echo port to minimize impact on the net. */
/* Note that we could use an NIT socket for this, but that */
/* would require super-user privileges. */
if ((discard = mk_udp_ncon(em)) < 0)
{
retval = discard;
goto cleanup;
}
oldsig = signal(SIGPIPE, SIG_IGN);
sa->sin_family = AF_INET;
sa->sin_port = IPPORT_ECHO;
if (sendto(discard, "abcd", 5, 0, sa, sizeof(*sa)) != 5)
{
*em = "sendto";
retval = -1;
goto cleanup;
}
(void)signal(SIGPIPE, oldsig);
/* Check cache again just in case . . . */
if (ioctl(s, SIOCGARP, (caddr_t)&arpreq) == -1)
{
*em = "ioctl SIOCGARP";
retval = -1;
goto cleanup;
}
if ((arpreq.arp_flags & ATF_COM) != 0)
{
(void)bcopy(arpreq.arp_ha.sa_data, ea,
sizeof(struct ether_addr));
retval = 1;
goto cleanup;
}
retval = 0;
cleanup:
/* Close file descriptors. */
if (s != -1)
close(s);
if (discard != -1)
close(discard);
return (retval);
}
/* TranslateX using ARP, force existing entry to be PERManent. */
/* Internet address (in the form of a sockaddr_in *) is passed in */
/* through sa, ethernet address (in the form of a struct ether_addr) */
/* is optionally passed through ea (if ea is NULL, the address will */
/* be looked up in the arp cache). Returns 1 if the desired entry */
/* has been cached, 0 if the arp is in process, and -1 if a system call */
/* failed (em is pointed to the name of the system call in this case). */
extern int
tx_arp_perm(sa, ea, em)
struct sockaddr_in *sa; /* Socket Address. */
struct ether_addr *ea; /* Ethernet Address. */
char **em; /* Error Message pointer. */
{
static struct arpreq arpreq; /* ARP REQuest structure. */
int retval; /* RETurn VALue. */
int s; /* Socket file descriptor. */
/* Set up arp request struct. */
bzero((caddr_t)&arpreq, sizeof(arpreq));
bcopy(sa, (caddr_t)&arpreq.arp_pa, sizeof(*sa));
arpreq.arp_pa.sa_family = AF_INET;
arpreq.arp_ha.sa_family = AF_UNSPEC;
/* Open a socket to do ioctls on (just to arp!). */
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
*em = "socket";
return (-1);
}
/* Do the ioctl, check the result. */
if (((retval = ioctl(s, SIOCGARP, (caddr_t)&arpreq)) == -1) &&
(ea == NULL))
{
*em = "ioctl SIOCGARP";
close(s);
return (-1);
}
if ((retval != -1) &&
((arpreq.arp_flags & ATF_COM) == 0))
{
close(s);
return (0);
}
/* Set the ethernet address if requested, mark the entry */
/* permanent. */
if (ea != NULL)
(void)bcopy(ea, (caddr_t)arpreq.arp_ha.sa_data, sizeof(*ea));
arpreq.arp_flags |= ATF_PERM;
/* Delete the existing entry. */
/* if (ioctl(s, SIOCDARP, (caddr_t)&arpreq) == -1)
{
*em = "ioctl SIOCDARP";
close(s);
return (-1);
}
*/
/* Do the ioctl, check the result. */
if (ioctl(s, SIOCSARP, (caddr_t)&arpreq) == -1)
{
*em = "ioctl SIOCSARP";
close(s);
return (-1);
}
close(s);
return (1);
}
/* TranslateX using ARP, force existing entry to be TeMPorary. */
/* Internet address (in the form of a sockaddr_in *) is passed in */
/* through sa, ethernet address (in the form of a struct ether_addr) */
/* is optionally passed through ea (if ea is NULL, the address will */
/* be looked up in the arp cache). Returns 1 if the desired entry */
/* has been cached, 0 if the arp is in process, and -1 if a system call */
/* failed (em is pointed to the name of the system call in this case). */
extern int
tx_arp_tmp(sa, ea, em)
struct sockaddr_in *sa; /* Socket Address. */
struct ether_addr *ea; /* Ethernet Address. */
char **em; /* Error Message pointer. */
{
static struct arpreq arpreq; /* ARP REQuest structure. */
int retval; /* RETurn VALue. */
int s; /* Socket file descriptor. */
/* Set up arp request struct. */
bzero((caddr_t)&arpreq, sizeof(arpreq));
bcopy(sa, (caddr_t)&arpreq.arp_pa, sizeof(*sa));
arpreq.arp_pa.sa_family = AF_INET;
arpreq.arp_ha.sa_family = AF_UNSPEC;
/* Open a socket to do ioctls on (just to arp!). */
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
*em = "socket";
return (-1);
}
/* Do the ioctl, check the result. */
if (((retval = ioctl(s, SIOCGARP, (caddr_t)&arpreq)) == -1) &&
(ea == NULL))
{
*em = "ioctl SIOCGARP";
close(s);
return (-1);
}
if ((retval != -1) &&
((arpreq.arp_flags & ATF_COM) == 0))
{
close(s);
return (0);
}
/* Set the ethernet address if requested, mark the entry */
/* permanent. */
if (ea != NULL)
(void)bcopy(ea, (caddr_t)arpreq.arp_ha.sa_data, sizeof(*ea));
arpreq.arp_flags &= ~ATF_PERM;
/* Delete the existing entry. */
/* if (ioctl(s, SIOCDARP, (caddr_t)&arpreq) == -1)
{
*em = "ioctl SIOCDARP";
close(s);
return (-1);
}
*/
/* Do the ioctl, check the result. */
if (ioctl(s, SIOCSARP, (caddr_t)&arpreq) == -1)
{
*em = "ioctl SIOCSARP";
close(s);
return (-1);
}
close(s);
return (1);
}
/* TranslateX using ARP, WAIT for completion. Internet address */
/* (in the form of a sockaddr_in *) is passed in through sa, puts */
/* resulting ethernet address into ea. Returns 1 all went well, and -1 */
/* if a system call failed (em is pointed to the name of the system */
/* call in this case). Note that this routine can hang for several */
/* minutes while the system waits for an arp response, and that this */
/* routine (indirectly) uses SIGALRM. */
int
tx_arp_wait(sa, ea, em)
struct sockaddr_in *sa; /* Socket Address. */
struct ether_addr *ea; /* Ethernet Address. */
char **em; /* Error Message pointer. */
{
int retval;
/* check status until we get a definite answer. */
while ((retval = tx_arp_chk(sa, ea, em)) == 0)
sleep(1);
return (retval);
}
\Rogue\Monster\
else
echo "will not overwrite ./tx_arp.c"
fi
if [ `wc -c ./tx_arp.c | awk '{printf $1}'` -ne 11372 ]
then
echo `wc -c ./tx_arp.c | awk '{print "Got " $1 ", Expected " 11372}'`
fi
if `test ! -s ./tx_hostname.c`
then
echo "writing ./tx_hostname.c"
cat > ./tx_hostname.c << '\Rogue\Monster\'
/************************************************************************
* *
* File: tx_hostname.c *
* *
* TranslateX HOSTNAME to internet address. *
* *
* Written by Paul E. McKenney, SRI International. *
* *
************************************************************************/
/*
* $Log: tx_hostname.c,v $
* Revision 2.0 88/09/23 18:28:31 mckenney
* .
*
*/
/* Include files. */
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <strings.h>
/* Type definitions local to this file. */
/* Functions exported from this file. */
extern int tx_hostname(); /* TranslateX HOSTNAME. */
/* Functions local to this file. */
/* Variables exported from this file. */
/* Variables local to this file. */
/* TranslateX HOSTNAME to internet address (the 'X' is silent). */
/* Returns -1 if there was a system call problem, points em to a string */
/* containing the system call name. */
/* Returns -2 if there were other problems and points em to a */
/* string containing a human-readable error message. */
/* Returns host address in sa. */
extern int tx_hostname(host, sa, em)
char *host; /* HOST name or id. */
struct sockaddr_in *sa; /* Socket Address. */
char **em; /* Error Message pointer. */
{
char errmsg[BUFSIZ]; /* ERRor MeSsaGe buffer. */
struct hostent *hp; /* Host entry Pointer. */
char *rerrmsg; /* Regex ERRor MeSsaGe. */
char *re_comp(); /* regex library routines. No */
int re_exec(); /* include files!!!!!! */
/* Initialize socket address. */
bzero((char *)sa, sizeof(*sa));
sa->sin_family = AF_INET;
/* Get host name -- check for internet address. */
if ((rerrmsg =
re_comp("[0-9][0-9]*\\.[0-9][0-9]*\\.[0-9][0-9]*\\.[0-9][0-9]*"))
!=
(char *)0)
{
sprintf(errmsg, "re_comp error: %s\n", rerrmsg);
*em = errmsg;
return (-2);
}
if (re_exec(host) == 1)
{
u_long inet_addr(); /* Kludge around C bug. */
sa->sin_addr.s_addr = inet_addr(host);
}
else if ((hp = gethostbyname(host)) == NULL)
{
sprintf(errmsg, "\"%s\" not found in /etc/hosts!!\n", host);
*em = errmsg;
return (-2);
}
else
sa->sin_addr.s_addr = *(u_long *)hp->h_addr;
return (0);
}
\Rogue\Monster\
else
echo "will not overwrite ./tx_hostname.c"
fi
if [ `wc -c ./tx_hostname.c | awk '{printf $1}'` -ne 2332 ]
then
echo `wc -c ./tx_hostname.c | awk '{print "Got " $1 ", Expected " 2332}'`
fi
echo "Finished archive 1 of 1"
exit
This archive was generated by hypermail 2.1.2 : Fri Sep 28 2001 - 23:12:01 CDT