SUMMARY: searching for program 'etherhostprobe'

From: Bruce Cheng (bcheng@aspect.com)
Date: Tue Sep 02 1997 - 18:59:58 CDT


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