cs.utexas.edu!wupost!uunet!stanford.edu!leland.Stanford.EDU!schemers Wed Jul 15 23:38:33 CDT 1992
Article: 6158 of alt.sources
Newsgroups: alt.sources
Path: cse.uta.edu!cs.utexas.edu!wupost!uunet!stanford.edu!leland.Stanford.EDU!schemers
From: schemers@leland.Stanford.EDU (Roland Schemers)
#Subject: fping
Message-ID: <1992Jul15.155805.16812@leland.Stanford.EDU>
Summary: ping program to check on n number of hosts very quickly
Keywords: fping
Sender: schemers@slapshot.stanford.edu
Organization: Distributed Computing Group, Stanford University
Date: Wed, 15 Jul 92 15:58:05 GMT
Lines: 869

      fping is a ping(1) like program which uses the Internet Control
      Message Protocol (ICMP) echo request to determine if a host is
      up. fping is different from ping in that you can specify any
      number of hosts on the command line, or specify a file containing
      the lists of hosts to ping. Instead of trying one host until it
      timeouts or replies, fping will send out a ping packet and move
      on to the next host in a round-robin fashion. If a host replies,
      it is noted and removed from the list of hosts to check. If a host
      does not respond within a certain time limit and/or retry limit it 
      will be considered unreachable. 


# /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  README fping.c fping.man Makefile
# Wrapped by schemers@Slapshot.Stanford.EDU on Wed Jul 15 08:53:27 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(3126 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X
X        fping - A tool to quickly ping N number of hosts to determine
X        their reachability without flooding the network.
X
X             Roland J. Schemers III - Stanford University
X                   schemers@Slapshot.Stanford.EDU
X
X      fping is a ping(1) like program which uses the Internet Control
X      Message Protocol (ICMP) echo request to determine if a host is
X      up. fping is different from ping in that you can specify any
X      number of hosts on the command line, or specify a file containing
X      the lists of hosts to ping. Instead of trying one host until it
X      timeouts or replies, fping will send out a ping packet and move
X      on to the next host in a round-robin fashion. If a host replies,
X      it is noted and removed from the list of hosts to check. If a host
X      does not respond within a certain time limit and/or retry limit it 
X      will be considered unreachable. 
X
XSite
X      Stanford University has a large TCP/IP network with over 12,000 
X      assigned IP addresses and over 100 IP subnets.
X
XProblem and Issues
X
X      With a large a number of IP addresses in use, its becomes more and
X      more time consuming to check on which IP addresses are actively
X      in use, and which critical machines (routers, bridges, servers, etc)
X      are reachable. One example is we have a program which goes through
X      all of our routers arp caches looking for IP addresses that are in 
X      use. After finding a list of IP addresses that aren't in any arp
X      caches fping can then be used to see if these IP addresses really
X      aren't being used, or are just behind the routers. Checking 2500
X      hosts (99% of which are unreachable) via ping can take hours.
X       
XSolution
X      
X       fping was written to solve the problem of pinging N number of hosts
X       in an efficient manner. By sending out pings in a round-robin fashion
X       and checking on responses as they come in at random, a large number of 
X       hosts can be checked at once. Checking 2500 hosts (5 packets per host, 
X       10 msec between ping packets) takes under 3 minutes. Also, using fping
X       to check 30 routers that are currently reachable takes about 300 
X       milliseconds.
X
X       fping does not give statistics on how long it took for a host to 
X       reply, etc, as its main goal is simply to determine if a system
X       is up. Unlike ping, fping is meant to be used in scripts and its
X       output is easy to parse.
X
X------------------------------------------------------------------------------
X
XUsage: fping [options] [systems...]
X   -f file    read list of systems from a file ( - means stdin)
X   -i n       interval (between ping packets) in mili-seconds (default 10)
X   -t n       individual host timeout in mili-seconds (default 1000)
X   -r n       retry limit (default 4)
X   -s         dump final stats
X   -q         quiet (don't show per host results)
X   -a         show systems that are alive
X   -u         show systems that are unreachable
X   -d         use dns to lookup address for return ping packet
X   systems    list of systems to check (if no -f specified)
X
X
X
END_OF_FILE
if test 3126 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'fping.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'fping.c'\"
else
echo shar: Extracting \"'fping.c'\" \(16358 characters\)
sed "s/^X//" >'fping.c' <<'END_OF_FILE'
X/* 
X * fping: fast-ping, file-ping
X *
X * Used to send out ping requests to a list of hosts in a round robin
X * fashion. 
X *
X *
X *   fping has been compiled tested under the following systems:
X *
X *  Ultrix 4.2a DECstation
X *  NeXT 2.1
X *  SunOS 4.1.1 Sparcstation
X *  AIX 3.1 RISC System/6000
X *
X */
X
X/* 
X ***************************************************
X *
X * Standard RCS Header information (see co(1))
X *
X * $Author: schemers $
X *
X * $Date: 1992/07/14 18:45:23 $
X *
X * $Revision: 1.7 $
X *
X * $Locker: schemers $
X *
X * $Source: /networking/src/fping/RCS/fping.c,v $
X *
X * $State: Exp $
X *
X * $Log: fping.c,v $
X * Revision 1.7  1992/07/14  18:45:23  schemers
X * initialized last_time in add_host function
X *
X * Revision 1.6  1992/07/14  18:32:40  schemers
X * changed select to use FD_ macros
X *
X * Revision 1.5  1992/07/14  17:21:22  schemers
X * standardized exit status codes
X *
X * Revision 1.4  1992/06/26  15:25:35  schemers
X * changed name from rrping to fping
X *
X * Revision 1.3  1992/06/24  15:39:32  schemers
X * added -d option for unreachable systems
X *
X * Revision 1.2  1992/06/23  03:01:23  schemers
X * misc fixes from R.L. "Bob" Morgan
X *
X * Revision 1.1  1992/06/19  18:23:52  schemers
X * Initial revision
X *
X *--------------------------------------------------
X * Copyright (c) 1992 Board of Trustees
X *            Leland Stanford Jr. University
X ***************************************************
X */
X
X/*
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by Stanford University.  The name of the University may not be used 
X * to endorse or promote products derived from this software without 
X * specific prior written permission.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X */
X
X#include <stdio.h>
X#include <errno.h>
X#include <time.h>
X
X#ifdef ultrix 
X#include <unistd.h>
X#endif
X
X#include <stdlib.h>
X#include <string.h>
X
X#include <sys/types.h>
X#include <sys/time.h>
X#include <sys/socket.h>
X
X
X#include <netinet/in_systm.h>
X#include <netinet/in.h>
X#include <netinet/ip.h>
X#include <netinet/ip_icmp.h>
X#include <arpa/inet.h>
X
X#include <netdb.h>
X
X/* RS6000 has sys/select.h */
X#ifndef FD_SET
X#include <sys/select.h>
X#endif
X
X/* externals */
X
Xint getopt (int argc, char **argv, char *optstring);
Xextern char *optarg;
Xextern int optind,opterr;
Xextern char *sys_errlist[];
X
X/* constants */
X
X#define DEFAULT_INTERVAL 10        /* default time between packets (msec) */
X#define DEFAULT_TIMEOUT 1000       /* individual host timeouts */
X#define DEFAULT_RETRY 4            /* number of times to retry a host */
X
X/* typedef's */
X
X/* entry used to keep track of each host we are pinging */
X
Xtypedef struct host_entry {
X     char                 *host;              /* text description of host */
X     struct sockaddr_in   saddr;              /* internet address */
X     int                  i;                  /* index into array */
X     int                  num_packets_sent;   /* number of ping packets sent */
X     struct host_entry    *prev,*next;        /* doubly linked list */
X     struct timeval       last_time;          /* time of last packet sent */
X} HOST_ENTRY;
X
X/* globals */
X
XHOST_ENTRY *rrlist=NULL;    /* linked list of hosts be pinged */
XHOST_ENTRY **table=NULL;    /* array of pointers to items in the list */
XHOST_ENTRY *cursor;
X
Xchar *prog;
Xint ident;                  /* our pid */
Xint s;                      /* socket */
X
Xint retry = DEFAULT_RETRY;
Xint timeout = DEFAULT_TIMEOUT;
Xint interval = DEFAULT_INTERVAL;
X
Xstruct timeval timeout_timeval;
Xstruct timezone tz;
X
Xint num_waiting=0;                 /* number of hosts we are pinging */
Xint num_hosts;                     /* total number of hosts */
X
Xint num_alive=0,                  /* total number alive */
X    num_unreachable=0,            /* total number unreachable */
X    num_noaddress=0;              /* total number of addresses not found */
X
Xint num_timeout=0,                /* number of times select timed out */
X    num_pingsent=0,               /* total pings sent */
X    num_pingreceived=0;           /* total pings received */
X
Xstruct timeval current_time;      /* current time (pseudo) */
X
X/* switches */
Xint verbose_flag,dns_flag,stats_flag,unreachable_flag,alive_flag;
X
Xchar *filename=NULL;               /* file containing hosts to ping */
X
X/* forward declarations */
X
Xvoid add_host(char *host);
Xvoid crash_and_burn(char *message);
Xvoid errno_crash_and_burn(char *message);
Xchar *get_host_by_address(struct in_addr in);
Xint in_cksum(u_short *p, int n);
Xint recvfrom_wto (int s, char *buf, int len, struct sockaddr *saddr, int timo);
Xvoid remove_job(HOST_ENTRY *h);
Xvoid send_ping(int s,HOST_ENTRY *h);
Xvoid set_timeval(struct timeval *t, int milisec);
Xint timeval_expired(struct timeval *stamp,struct timeval *current, 
X                                                        struct timeval *delay);
Xvoid usage();
Xint wait_for_reply();
X
Xint main(int argc, char **argv)
X{
X
X  int c;
X
X  struct protoent *proto;
X
X  /* check if we are root */
X
X  if (geteuid()) {
X      fprintf(stderr,
X        "This program can only be run by root, or it must be setuid root.\n");
X      exit(3);
X  }
X
X  prog = argv[0];
X  ident = getpid() & 0xFFFF;
X
X  verbose_flag=1;
X
X  opterr=0;
X
X  while ((c = getopt(argc,argv,"dhqusat:i:f:r:")) != EOF) 
X     switch (c) {
X	   case 't': if ( (timeout=atoi(optarg)) <0) usage();  break;
X	   case 'f': filename= optarg;                         break;
X	   case 'r': if ((retry=atoi(optarg))<0) usage();      break;
X	   case 'i': if ((interval=atoi(optarg))<0) usage();   break;
X	   case 'h': usage();                                  break;
X	   case 'q': verbose_flag = 0;	                       break;
X	   case 'd': dns_flag = 1;                             break;
X	   case 's': stats_flag = 1;                           break;
X	   case 'u': unreachable_flag = 1;                     break;
X	   case 'a': alive_flag = 1;                           break;
X           default : printf("Unknown flag: %s\n",argv[0]); 
X                     usage(); break;
X     }
X
X  set_timeval(&timeout_timeval,timeout);
X
X  if (alive_flag || unreachable_flag) verbose_flag=0;
X
X  argv = &argv[optind];
X  if (*argv && filename)   { usage(); }
X  if (!*argv && !filename) { filename = "-"; }
X
X  if (*argv) while (*argv) {
X             add_host(*argv);
X             ++argv;
X  } else if (filename) {
X         FILE *ping_file;
X         char line[132];
X         char host[132],*p;
X         if (strcmp(filename,"-")==0) {
X             ping_file=fdopen(0,"r");
X         } else {
X             ping_file=fopen(filename,"r");
X         }
X         if (!ping_file) errno_crash_and_burn("fopen");
X         while(fgets(line,132,ping_file)) {
X           sscanf(line,"%s",host);
X           p=(char*)malloc(strlen(host)+1);
X           if (!p) crash_and_burn("can't malloc host");
X           strcpy(p,host);
X           add_host(p);
X         }
X         fclose(ping_file);
X  } else usage();
X
X  if (!num_hosts) exit(2);
X
X  if ((proto = getprotobyname("icmp")) == NULL) 
X             crash_and_burn("icmp: unknown protocol");
X
X  s = socket(AF_INET, SOCK_RAW, proto->p_proto);
X  if (s<0) errno_crash_and_burn("can't create raw socket");
X
X  /* allocate array to hold outstanding ping requests */
X
X  table = (HOST_ENTRY **) malloc(sizeof(HOST_ENTRY *)*num_hosts);
X  if (!table) crash_and_burn("Can't malloc array of hosts");
X
X  cursor=rrlist;
X
X  for( num_waiting=0; num_waiting < num_hosts; num_waiting++ ) {
X      table[num_waiting]=cursor;
X      cursor->i = num_waiting;
X      cursor=cursor->next;
X  }
X
X  cursor=rrlist;
X  while (num_waiting) {  /* while pings are outstanding */
X      if (cursor->num_packets_sent == retry+1) {
X           if(verbose_flag || unreachable_flag) {
X                      if (dns_flag) printf("%s is unreachable\n", 
X                             get_host_by_address(cursor->saddr.sin_addr));
X                      else    printf("%s is unreachable\n",cursor->host);
X
X	  }
X          num_unreachable++;
X          remove_job(cursor); 
X      } else {
X        if (timeval_expired(&cursor->last_time,
X                                      &current_time,&timeout_timeval) ||
X                    cursor->num_packets_sent==0) 
X                   send_ping(s,cursor);
X        }
X      while(wait_for_reply() && num_waiting) {  /* call wfr until we timeout */
X                    /* wait! */
X      }
X      gettimeofday(&current_time,&tz);
X      num_timeout++;
X      if (cursor) cursor = cursor->next;
X  }  
X
X  if (stats_flag) {
X     printf("\n");
X     printf(" %8d hosts\n",num_hosts);
X     printf(" %8d alive\n",num_alive);
X     printf(" %8d unreachable\n",num_unreachable);
X     printf(" %8d unknown addresses\n",num_noaddress);
X     printf("\n");
X     printf(" %8d timeouts (waiting for response)\n",num_timeout);
X     printf(" %8d pings sent\n",num_pingsent);
X     printf(" %8d pings received\n",num_pingreceived);
X     printf("\n");
X  }
X
X  if (num_noaddress) exit(2);
X  else if (num_alive != num_hosts) exit(1); 
X  
X  return 0;
X
X}
X
Xint wait_for_reply()
X{
Xint result;
Xstatic char buffer[4096];
Xstruct sockaddr_in response_addr;
Xstruct ip *ip;
Xint hlen;
Xstruct icmp *icp;
Xint n;
XHOST_ENTRY *h;
X
X result=recvfrom_wto(s,buffer,4096,
X                     (struct sockaddr *)&response_addr,interval);
X
X  if (result<0) { return 0; } /* timeout */
X  
X  ip = (struct ip *) buffer;
X  hlen = ip->ip_hl << 2;
X  if (result < hlen+ICMP_MINLEN) { return(1); /* too short */ }
X
X  icp = (struct icmp *)(buffer + hlen);
X
X  if ( 
X       ( icp->icmp_type != ICMP_ECHOREPLY ) ||   
X       ( icp->icmp_id   != ident          ) 
X  ) {
X       return 1; /* packet received, but not the one we are looking for! */
X  }
X
X      num_pingreceived++;
X
X  if ( ( icp->icmp_seq  >= num_hosts    ) ||
X       ( !table[icp->icmp_seq]          ) ||
X       ( table[icp->icmp_seq]->saddr.sin_addr.s_addr 
X                                != response_addr.sin_addr.s_addr)) { 
X       return 1; /* packet received, don't about it anymore */
X  }
X
X    n=icp->icmp_seq;
X    h=table[n];
X
X    if(verbose_flag||alive_flag) {
X        if (dns_flag) printf("%s is alive\n", 
X                  get_host_by_address(response_addr.sin_addr));
X        else printf("%s is alive\n",  h->host);
X    }
X    num_alive++;
X    remove_job(h); /* remove job */
X    return num_waiting;
X}
X
X/*
X * 
X * Compose and transmit an ICMP_ECHO REQUEST packet.  The IP packet
X * will be added on by the kernel.  The ID field is our UNIX process ID,
X * and the sequence number is an index into an array of outstanding
X * ping requests. The sequence number will later be used to quickly
X * figure out who the ping reply came from.
X *
X */
X
Xvoid send_ping(int s,HOST_ENTRY *h)
X{
X  static char buffer[32];
X  struct icmp *icp = (struct icmp *) buffer;
X  int n;
X  icp->icmp_type = ICMP_ECHO;
X  icp->icmp_code = 0;
X  icp->icmp_cksum = 0;
X  icp->icmp_seq = h->i;
X  icp->icmp_id = ident;
X  icp->icmp_cksum = in_cksum( (u_short *)icp, 32 );
X
X  n = sendto( s, buffer, 32, 0, (struct sockaddr *)&h->saddr, sizeof(struct sockaddr_in) );
X  if( n < 0 || n != 32 ) errno_crash_and_burn("sendto");
X  h->num_packets_sent++;
X  num_pingsent++;
X  h->last_time = current_time;
X}
X
X/*
X * Checksum routine for Internet Protocol family headers (C Version)
X * From ping examples in W.Richard Stevens "UNIX NETWORK PROGRAMMING" book.
X */
X
Xint in_cksum(u_short *p, int n)
X{
X  register u_short answer;
X  register long sum = 0;
X  u_short odd_byte = 0;
X
X  while( n > 1 )  { sum += *p++; n -= 2; }
X
X  /* mop up an odd byte, if necessary */
X  if( n == 1 ) {
X      *(u_char *)(&odd_byte) = *(u_char *)p;
X      sum += odd_byte;
X  }
X
X  sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
X  sum += (sum >> 16);			/* add carry */
X  answer = ~sum;			/* ones-complement, truncate*/
X  return (answer);
X}
X
X
X/* add host to linked list of hosts to be pinged */
X/* assume memory for *host is ours!!!            */
X
Xvoid add_host(char *host)
X{
X  HOST_ENTRY *p;
X  struct hostent *host_ent;
X  struct in_addr *host_add;
X
X  u_long ipaddress = inet_addr(host);
X
X  if ( (ipaddress == -1) &&
X       ( ((host_ent=gethostbyname(host)) == 0) ||
X          ((host_add = (struct in_addr *) *(host_ent->h_addr_list))==0))
X     )  {
X          if (verbose_flag) printf("%s address not found\n",host);
X          num_noaddress++;
X          return;
X       }
X
X  p = (HOST_ENTRY *) malloc(sizeof(HOST_ENTRY));
X  if (!p) crash_and_burn("can't allocate HOST_ENTRY");
X
X  p->host=host;
X  p->num_packets_sent = 0;
X  p->last_time.tv_sec =0;
X  p->last_time.tv_usec =0;
X
X  bzero((char*) &p->saddr, sizeof(p->saddr));
X  p->saddr.sin_family      = AF_INET;
X
X  if (ipaddress==-1) p->saddr.sin_addr = *host_add; 
X  else p->saddr.sin_addr.s_addr = ipaddress;
X
X  if (!rrlist) {
X      rrlist = p;
X      p->next = p;
X      p->prev = p;
X  } else {
X      p->next = rrlist;
X      p->prev = rrlist->prev;
X      p->prev->next = p;
X      p->next->prev = p;
X      rrlist = p;
X  }
X  num_hosts++;
X}
X
Xvoid remove_job(HOST_ENTRY *h)
X{
X
X  table[h->i]=NULL;
X
X  --num_waiting;
X
X  if (num_waiting) {                    /* remove us from list of jobs */
X       h->prev->next = h->next;
X       h->next->prev = h->prev;
X       if (h==cursor) { cursor = h-> next; }
X  } else {     
X       cursor=NULL;
X       rrlist=NULL;
X  }
X
X}
X
Xchar *get_host_by_address(struct in_addr in)
X{
X  struct hostent *h;
X   h=gethostbyaddr((char *) &in,sizeof(struct in_addr),AF_INET);
X   if (h==NULL || h->h_name==NULL) return inet_ntoa(in);
X   else return h->h_name;
X}
X
X
Xvoid crash_and_burn(char *message)
X{
X  if (verbose_flag) fprintf(stderr,"%s: %s\n",prog,message);
X  exit(4);
X}
X
Xvoid errno_crash_and_burn(char *message)
X{
X  if (verbose_flag)
X        fprintf(stderr,"%s: %s : %s\n",prog,message,sys_errlist[errno]);
X  exit(4);
X}
X
Xvoid set_timeval(struct timeval *t, int msec) 
X{
X  t->tv_sec  = msec/1000;
X  t->tv_usec = (msec - (t->tv_sec*1000))*1000;
X}
X
X
Xint timeval_expired(struct timeval *stamp, 
X             struct timeval *current, 
X             struct timeval *delay)
X{
Xstruct timeval temp_current,temp_stamp,diff;
X
X  temp_current= *current;
X  temp_stamp =  *stamp;
X
X  if (temp_current.tv_usec < temp_stamp.tv_usec ) {
X       temp_current.tv_usec +=1000000;
X       temp_current.tv_sec--;
X  }
X
X  diff.tv_usec = temp_current.tv_usec - temp_stamp.tv_usec;
X  diff.tv_sec  = temp_current.tv_sec  - temp_stamp.tv_sec;
X
X  if (diff.tv_sec > delay->tv_sec) return 1;
X  else if ( (diff.tv_sec == delay->tv_sec) &&
X            (diff.tv_usec >= delay->tv_usec) ) return 1;
X  else return 0;
X
X}
X
X
X/*
X * recvfrom_wto: receive with timeout
X *      returns length of data read or -1 if timeout
X *      crash_and_burn on any other errrors
X *
X */
X
X
Xint recvfrom_wto (int s, char *buf, int len, struct sockaddr *saddr, int timo)
X{
X  int nfound,slen,n;
X  struct timeval to;
X  fd_set readset,writeset;
X
X  to.tv_sec  = timo/1000;
X  to.tv_usec = (timo - (to.tv_sec*1000))*1000;
X
X  FD_ZERO(&readset);
X  FD_ZERO(&writeset);
X  FD_SET(s,&readset);
X  nfound = select(s+1,&readset,&writeset,NULL,&to);
X  if (nfound<0) errno_crash_and_burn("select");
X  if (nfound==0) return -1;  /* timeout */
X  slen=sizeof(struct sockaddr);
X  n=recvfrom(s,buf,len,0,saddr,&slen);
X  if (n<0) errno_crash_and_burn("recvfrom");
X  return n;
X}
X
Xvoid usage()
X{
X  printf("\n");
X  printf("Usage: %s [options] [systems...]\n",prog);
X  printf("   -f file    read list of systems from a file ( - means stdin)\n");
X  printf("   -i n       interval (between ping packets) in milli-seconds (default %d)\n",interval);
X  printf("   -t n       individual host timeout in milli-seconds (default %d)\n",timeout);
X  printf("   -r n       retry limit (default %d)\n",retry);
X  printf("   -s         dump final stats\n");
X  printf("   -q         quiet (don't show per host results)\n");
X  printf("   -a         show systems that are alive\n");
X  printf("   -u         show systems that are unreachable\n");
X  printf("   -d         use dns to lookup address for return ping packet\n");
X  printf("   systems    list of systems to check (if no -f specified)\n");
X  printf("\n");
X  exit(3);
X}
END_OF_FILE
if test 16358 -ne `wc -c <'fping.c'`; then
    echo shar: \"'fping.c'\" unpacked with wrong size!
fi
# end of 'fping.c'
fi
if test -f 'fping.man' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'fping.man'\"
else
echo shar: Extracting \"'fping.man'\" \(3293 characters\)
sed "s/^X//" >'fping.man' <<'END_OF_FILE'
X.TH fping l
X.SH NAME
Xfping \- send ICMP ECHO_REQUEST packets to network hosts
X.SH SYNOPSIS
X.B fping
X[ \fIoptions\fR ]
X[ \fIsystems...\fR ]
X
X.SH DESCRIPTION
X.NXR "fping command"
X.NXR "ICMP ECHO_REQUEST"
X
X      
X.PN fping 
Xis a 
X.MS ping 8
Xlike program which uses the Internet Control
XMessage Protocol (ICMP) echo request to determine if a host is
Xup. 
X.PN fping 
Xis different from ping in that you can specify any
Xnumber of hosts on the command line, or specify a file containing
Xthe lists of hosts to ping. Instead of trying one host until it
Xtimeouts or replies, 
X.PN fping 
Xwill send out a ping packet and move
Xon to the next host in a round-robin fashion. If a host replies,
Xit is noted and removed from the list of hosts to check. If a host
Xdoes not respond within a certain time limit and/or retry limit it 
Xwill be considered unreachable. 
X.PP
X.PN fping 
Xdoes not give statistics on how long it took for a host to 
Xreply, as its main goal is simply to determine if a system
Xis up. Unlike 
X.MS ping 8
X,
X.PN fping 
Xis meant to be used in scripts and its output is easy to parse.
X.SH OPTIONS
X.IP \fB-f\fR 5
XRead list of system from a file.
X.IP \fB-i\fIn\fR 5
XInterval (between ping packets) in milliseconds (default is 10).
X.IP \fB-t\fIn\fR 5
XIndividual host timeout in milliseconds (default 1000). This is the 
Xminimum number of seconds between ping packets directed towards a given
Xhost.
X.IP \fB-r\fIn\fR 5
XRetry limit (default 4). This is the number of times an attempt at pinging
Xa host will be made, not including the first try.
X.IP \fB-d\fR 5
XDump final statistics.
X.IP \fB-q\fR 5
XQuiet. Don't show per host results, just set final exit status.
X.IP \fB-a\fR 5
XShow systems that are alive.
X.IP \fB-u\fR 5
XShow ststems that are unreachable.
X.IP \fB-d\fR 5
XUse DNS to lookup address of return ping packet. This allows you to give
X.PN fping
Xa list of IP addresses as input and have the results printed as hostnames.
X.SH EXAMPLES
XThe following perl script will check a list of hosts and send mail if
Xany are unreachable. It uses the open2 function which allows a program
Xto be opened for reading and writing. fping does not start pinging the
Xlist of systems until it reads EOF, which it gets after INPUT is closed. 
X.nf
X
X#!/usr/local/bin/perl
Xrequire 'open2.pl';
X
X$MAILTO = "root";
X
X$pid = &open2("OUTPUT","INPUT","/usr/local/bin/fping -u");
X
X@check=("slapshot","foo","foobar");
X
Xforeach(@check) {  print INPUT "$_\\n"; }
Xclose(INPUT);
X@output=<OUTPUT>;
X
Xif ($#output != -1) {
X chop($date=`date`);
X open(MAIL,"|mail -s 'unreachable systems' $MAILTO");
X print MAIL "\\nThe following systems are unreachable as of: $date\\n\\n";
X print MAIL @output;
X close MAIL;
X}
X
X.ni
X.SH AUTHOR
XRoland J. Schemers III, Stanford University
X.SH DIAGNOSTICS
XExit status is 0 if all the hosts are reachable, 1 if some hosts were
Xunreachable, 2 if any IP addresses were not found, 3 for invalid
Xcommand line arguments, and 4 for a system call failure.
X.SH BUGS
XHa! If there were any I knew of I would have fixed them!
X.SH RESTRICTIONS
XIf certain options are used (i.e, a low value for -i and -t, and a 
Xhigh value for -r) it is possible to flood the network. This program
Xmust be installed as setuid root in order to open up a raw socket,
Xor must be run by root.
X.SH SEE ALSO
Xnetstat(1), ping(8), ifconfig(8c)
END_OF_FILE
if test 3293 -ne `wc -c <'fping.man'`; then
    echo shar: \"'fping.man'\" unpacked with wrong size!
fi
# end of 'fping.man'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(583 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X
XPROG= fping
XOBJS= fping.o
XSRC= fping.c
XBIN= /usr/local/bin
XMAN= /usr/man/manl
XMANSRC= fping.man
XMANDST= fping.l
X
X
Xall: $(PROG)
X
X$(PROG) : $(OBJS)
X	cc $(OBJS) -o $(PROG)
X
X$(OBJS) : $(SRC)
X
X
X# if you don't have install type:
X# cp $(PROG) /usr/local/bin
X# chown root /usr/local/bin/$(PROG)
X# chmod 4555 /usr/local/bin/$(PROG)
X# strip      /usr/local/bin/$(PROG)
X#
X
Xinstall:
X	install -c -m 4555 -o root -s $(PROG) $(BIN)/$(PROG)
X	install -c -m 0444 -o root $(MANSRC) $(MAN)/$(MANDST)
X
Xclean:
X	rm -f a.out core *~  *.o $(PROG)
X
Xshar:
X	shar README fping.c fping.man Makefile > fping.shar
END_OF_FILE
if test 583 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
echo shar: End of shell archive.
exit 0


-- 
Roland J. Schemers III              |            Networking Systems
Systems Programmer                  |            168 Pine Hall   (415)-723-6740
Distributed Computing Group         |            Stanford, CA 94305-4122
Stanford University                 |            schemers@Slapshot.Stanford.EDU