diff options
author | 2000-12-17 17:48:05 +0000 | |
---|---|---|
committer | 2000-12-17 17:48:05 +0000 | |
commit | bf3ee19952c7b5c3bdf6a283b096d81ea9380f6c (patch) | |
tree | dfac5c8f535c4417f3b5efcdafb7b3ac28be04bf /net-misc | |
parent | *** empty log message *** (diff) | |
download | historical-bf3ee19952c7b5c3bdf6a283b096d81ea9380f6c.tar.gz historical-bf3ee19952c7b5c3bdf6a283b096d81ea9380f6c.tar.bz2 historical-bf3ee19952c7b5c3bdf6a283b096d81ea9380f6c.zip |
*** empty log message ***
Diffstat (limited to 'net-misc')
-rw-r--r-- | net-misc/fping/files/digest-fping-2.2_beta1 | 1 | ||||
-rw-r--r-- | net-misc/fping/files/fping.c | 1719 | ||||
-rw-r--r-- | net-misc/fping/fping-2.2_beta1.ebuild | 32 |
3 files changed, 1752 insertions, 0 deletions
diff --git a/net-misc/fping/files/digest-fping-2.2_beta1 b/net-misc/fping/files/digest-fping-2.2_beta1 new file mode 100644 index 000000000000..8409bbc34251 --- /dev/null +++ b/net-misc/fping/files/digest-fping-2.2_beta1 @@ -0,0 +1 @@ +MD5 172b26466af221c5f4c637b8453ecc23 fping-2.2b1.tar.bz2 diff --git a/net-misc/fping/files/fping.c b/net-misc/fping/files/fping.c new file mode 100644 index 000000000000..cad0bcf9cb0f --- /dev/null +++ b/net-misc/fping/files/fping.c @@ -0,0 +1,1719 @@ +/* + * fping: fast-ping, file-ping, favorite-ping, funky-ping + * + * Ping a list of target hosts in a round robin fashion. + * A better ping overall. + * + */ + +/* + *************************************************** + * + * Standard RCS Header information (see co(1)) + * + * $Author: achim $ + * + * $Date: 2000/12/17 17:48:05 $ + * + * $Revision: 1.1 $ + * + * $Locker: $ + * + * $Source: /var/cvsroot/gentoo-x86/net-misc/fping/files/fping.c,v $ + * + * $State: Exp $ + * + * $Log: not supported by cvs2svn $ + * Revision 2.2 1997/01/08 20:29:33 schemers + * changes for autoconf/automake + * + * Revision 2.1 1997/01/08 19:07:18 schemers + * checked in RL "Bob"'s changes before configure'ing + * + * Revision 2.0 1994/10/31 21:26:23 schemers + * many changes by RL "Bob" Morgan + * add timing data collection, loop mode, per-packet output, etc + * + * Revision 1.24 1993/12/10 23:11:39 schemers + * commented out seteuid(getuid()) since it isn't needed + * + * Revision 1.23 1993/12/10 18:33:41 schemers + * Took out the -f option for non-root users. This can be enabled by + * defining ENABLE_F_OPTION before compiling. There is a call to + * access before opening the file, but there is a race condition. + * Reading from stdin is much safer. + * + * Revision 1.22 1993/11/16 19:49:24 schemers + * Took out setuid(getuid()) and used access() system call to + * check for access to the file specified with "-f". + * + * Revision 1.21 1993/07/20 18:08:19 schemers + * commented out the test to make sure the ping packet came from the + * same IP address as the one we sent to. This could cause problems on + * multi-homed hosts. + * + * Revision 1.20 1993/02/23 00:16:38 schemers + * fixed syntax error (should have compiled before checking in...) + * + * Revision 1.19 1993/02/23 00:15:15 schemers + * turned off printing of "is alive" when -a is specified. + * + * Revision 1.18 1992/07/28 15:16:44 schemers + * added a fflush(stdout) call before the summary is sent to stderr, so + * everything shows up in the right order. + * + * Revision 1.17 1992/07/23 03:29:42 schemers + * fixed declaration of timeval_diff. + * + * Revision 1.16 1992/07/22 19:24:37 schemers + * Modified file reading so it would skip blanks lines or lines starting + * with a '#'. Now you can do something like: + * + * fping -ad < /etc/hosts + * + * Revision 1.15 1992/07/21 17:07:18 schemers + * Put in sanity checks so only root can specify "dangerous" options. + * Changed usage to show switchs in alphabetical order. + * + * Revision 1.14 1992/07/21 16:40:52 schemers + * Now when sendto returns an error, the host is considered unreachable and + * and the error message (from errno) is displayed. + * + * Revision 1.13 1992/07/17 21:02:17 schemers + * changed default timeout to 2500 msec (for WANs), and default try + * to 3. This gives 10 second overall timeout. + * + * Added -e option for showing elapsed (round-trip) time on packets + * + * Modified -s option to inlude to round-trip stats + * + * Added #ifndef DEFAULT_* stuff its easier to change the defaults + * + * Reorganized main loop. + * + * cleaned up timeval stuff. removed set_timeval and timeval_expired + * since they aren't needed anymore. Just use timeval_diff. + * + * Revision 1.12 1992/07/17 16:38:54 schemers + * move socket create call so I could do a setuid(getuid()) before the + * fopen call is made. Once the socket is created root privs aren't needed + * to send stuff out on it. + * + * Revision 1.11 1992/07/17 16:28:38 schemers + * moved num_timeout counter. It really was for debug purposes and didn't + * make sense to the general public :-) Now it is the number of timeouts + * (pings that didn't get received with the time limit). + * + * Revision 1.10 1992/07/16 16:24:38 schemers + * changed usage() to use fprintf(stderr,"..."); + * + * Revision 1.9 1992/07/16 16:00:04 schemers + * Added _NO_PROTO stuff for older compilers, and _POSIX_SOURCE + * for unistd.h, and _POSIX_SOURCE for stdlib.h. Also added + * check for __cplusplus. + * + * Revision 1.8 1992/07/16 05:44:41 schemers + * changed -a and -u to only show hostname in results. This is + * for easier parsing. Also added -v flag + * + * Revision 1.7 1992/07/14 18:45:23 schemers + * initialized last_time in add_host function + * + * Revision 1.6 1992/07/14 18:32:40 schemers + * changed select to use FD_ macros + * + * Revision 1.5 1992/07/14 17:21:22 schemers + * standardized exit status codes + * + * Revision 1.4 1992/06/26 15:25:35 schemers + * changed name from rrping to fping + * + * Revision 1.3 1992/06/24 15:39:32 schemers + * added -d option for unreachable systems + * + * Revision 1.2 1992/06/23 03:01:23 schemers + * misc fixes from R.L. "Bob" Morgan + * + * Revision 1.1 1992/06/19 18:23:52 schemers + * Initial revision + * + *-------------------------------------------------- + * Copyright (c) 1992, 1994, 1997 Board of Trustees + * Leland Stanford Jr. University + *************************************************** + */ + +/* + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Stanford University. The name of the University may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef _NO_PROTO +#if !__STDC__ && !defined(__cplusplus) && !defined(FUNCPROTO) \ + && !defined(_POSIX_SOURCE) +#define _NO_PROTO +#endif /* __STDC__ */ +#endif /* _NO_PROTO */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <config.h> + + +#include <stdio.h> +#include <errno.h> +#include <time.h> +#include <signal.h> + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif + +#include <string.h> + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/socket.h> + +#if HAVE_SYS_FILE_H +#include <sys/file.h> +#endif + +#include <netinet/in_systm.h> +#include <netinet/in.h> + +/* Linux has bizarre ip.h and ip_icmp.h */ +#if defined(__linux__) +#include "linux.h" +#else +#include <netinet/ip.h> +#include <netinet/ip_icmp.h> +#endif + +#include <arpa/inet.h> +#include <netdb.h> + +/* RS6000 has sys/select.h */ +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif + +#include "options.h" + +/* externals */ + +extern char *optarg; +extern int optind,opterr; +//extern char *sys_errlist[]; +extern int h_errno; + +#ifdef __cplusplus +} +#endif + +/* Ping packet defines */ + +/* data added after ICMP header for our nefarious purposes */ + +typedef struct ping_data { + int ping_count; /* counts up to -c count or 1 */ + struct timeval ping_ts; /* time sent */ +} PING_DATA; + +#define MIN_PING_DATA sizeof(PING_DATA) +#define MAX_IP_PACKET 65536 /* (theoretical) max IP packet size */ +#define SIZE_IP_HDR 20 +#define SIZE_ICMP_HDR ICMP_MINLEN /* from ip_icmp.h */ +#define MAX_PING_DATA (MAX_IP_PACKET - SIZE_IP_HDR - SIZE_ICMP_HDR) +/* sized so as to be like traditional ping */ +#define DEFAULT_PING_DATA_SIZE (MIN_PING_DATA + 44) + +/* maxima and minima */ +#define MAX_COUNT 10000 +#define MIN_INTERVAL 10 /* in millisec */ +#define MIN_PERHOST_INTERVAL 20 /* in millisec */ +#define MIN_TIMEOUT 50 /* in millisec */ +#define MAX_RETRY 20 + +/* response time array flags */ +#define RESP_WAITING -1 +#define RESP_UNUSED -2 + +/* debugging flags */ +#ifdef DEBUG +#define DBG_TRACE 1 +#define DBG_SENT_TIMES 2 +#define DBG_RANDOM_LOSE_FEW 4 +#define DBG_RANDOM_LOSE_MANY 8 +#define DBG_PRINT_PER_SYSTEM 16 +#define DBG_REPORT_ALL_RTTS 32 +#endif + +/* Long names for ICMP packet types */ +char *icmp_type_str[19] = { + "ICMP Echo Reply", /* 0 */ + "", + "", + "ICMP Unreachable", /* 3 */ + "ICMP Source Quench", /* 4 */ + "ICMP Redirect", /* 5 */ + "", + "", + "ICMP Echo", /* 8 */ + "", + "", + "ICMP Time Exceeded", /* 11 */ + "ICMP Paramter Problem", /* 12 */ + "ICMP Timestamp Request", /* 13 */ + "ICMP Timestamp Reply", /* 14 */ + "ICMP Information Request", /* 15 */ + "ICMP Information Reply", /* 16 */ + "ICMP Mask Request", /* 17 */ + "ICMP Mask Reply" /* 18 */ +}; +char *icmp_unreach_str[16] = { + "ICMP Network Unreachable", /* 0 */ + "ICMP Host Unreachable", /* 1 */ + "ICMP Protocol Unreachable", /* 2 */ + "ICMP Port Unreachable", /* 3 */ + "ICMP Unreachable (Fragmentation Needed)", /* 4 */ + "ICMP Unreachable (Source Route Failed)" /* 5 */ + "ICMP Unreachable (Destination Network Unknown)", /* 6 */ + "ICMP Unreachable (Destination Host Unknown)", /* 7 */ + "ICMP Unreachable (Source Host Isolated)", /* 8 */ + "ICMP Unreachable (Communication with Network Prohibited)", /* 9 */ + "ICMP Unreachable (Communication with Host Prohibited)", /* 10 */ + "ICMP Unreachable (Network Unreachable For Type Of Service)", /* 11 */ + "ICMP Unreachable (Host Unreachable For Type Of Service)", /* 12 */ + "ICMP Unreachable (Communication Administratively Prohibited)", /* 13 */ + "ICMP Unreachable (Host Precedence Violation)", /* 14 */ + "ICMP Unreachable (Precedence cutoff in effect)" /* 15 */ +}; +#define ICMP_UNREACH_MAXTYPE 15 + +/* entry used to keep track of each host we are pinging */ + +typedef struct host_entry { + struct host_entry *prev,*next; /* doubly linked list */ + int i; /* index into array */ + char *name; /* name as given by user */ + char *host; /* text description of host */ + char *pad; /* pad to align print names */ + struct sockaddr_in saddr; /* internet address */ + int timeout; /* time to wait for response */ + u_char running; /* unset when through sending */ + u_char waiting; /* waiting for response */ + struct timeval last_send_time; /* time of last packet sent */ + int num_sent; /* number of ping packets sent */ + int num_recv; /* number of pings received */ + int max_reply; /* longest response time */ + int min_reply; /* shortest response time */ + int total_time; /* sum of response times */ + int num_sent_i; /* number of ping packets sent */ + int num_recv_i; /* number of pings received */ + int max_reply_i; /* longest response time */ + int min_reply_i; /* shortest response time */ + int total_time_i; /* sum of response times */ + int *resp_times; /* individual response times */ +#ifdef DEBUG + int *sent_times; /* per-sent-ping timestamp */ +#endif +} HOST_ENTRY; + +/* globals */ + +HOST_ENTRY *rrlist=NULL; /* linked list of hosts be pinged */ +HOST_ENTRY **table=NULL; /* array of pointers to items in the list */ +HOST_ENTRY *cursor; + +char *prog; +int ident; /* our pid */ +int s; /* socket */ +u_int debugging = 0; + +/* times get *100 because all times are calculated in 10 usec units, not ms */ +u_int retry = DEFAULT_RETRY; +u_int timeout = DEFAULT_TIMEOUT * 100; +u_int interval = DEFAULT_INTERVAL * 100; +u_int perhost_interval = DEFAULT_PERHOST_INTERVAL * 100; +float backoff = DEFAULT_BACKOFF_FACTOR; +u_int select_time = DEFAULT_SELECT_TIME * 100; +u_int ping_data_size = DEFAULT_PING_DATA_SIZE; +u_int ping_pkt_size; +u_int count = 1; +u_int trials; +u_int report_interval = 0; + +/* global stats */ +long max_reply=0; +long min_reply=1000000; +int total_replies=0; +double sum_replies=0; +int max_hostname_len = 0; +int num_jobs=0; /* number of hosts still to do */ +int num_hosts; /* total number of hosts */ +int num_alive=0, /* total number alive */ + num_unreachable=0, /* total number unreachable */ + num_noaddress=0; /* total number of addresses not found */ +int num_timeout=0, /* number of times select timed out */ + num_pingsent=0, /* total pings sent */ + num_pingreceived=0, /* total pings received */ + num_othericmprcvd=0; /* total non-echo-reply ICMP received */ + +struct timeval current_time; /* current time (pseudo) */ +struct timeval start_time; +struct timeval end_time; +struct timeval last_send_time; /* time last ping was sent */ +struct timeval last_report_time; /* time last report was printed */ +struct timezone tz; + +/* switches */ +int verbose_flag,quiet_flag,stats_flag,unreachable_flag,alive_flag; +int elapsed_flag,version_flag,count_flag,loop_flag; +int per_recv_flag,report_all_rtts_flag,name_flag,addr_flag,backoff_flag; +int multif_flag; +#ifdef DEBUG +int randomly_lose_flag,sent_times_flag,trace_flag,print_per_system_flag; +int lose_factor; +#endif + +char *filename=NULL; /* file containing hosts to ping */ + +/* forward declarations */ + +#ifdef _NO_PROTO + +void add_name(); +void add_addr(); +char *na_cat(); +char *cpystr(); +void crash_and_burn(); +void errno_crash_and_burn(); +char *get_host_by_address(); +int in_cksum(); +void u_sleep(); +int recvfrom_wto (); +void remove_job(); +void send_ping(); +void usage(); +int wait_for_reply(); +long timeval_diff(); +void print_per_system_stats(); +void print_per_system_splits(); +void print_global_stats(); +void finish(); +int handle_random_icmp(); +char *sprint_tm(); + +#else + +void add_name(char *name); +void add_addr(char *name, char *host, struct in_addr ipaddr); +char *na_cat(char *name, struct in_addr ipaddr); +char *cpystr(char *string); +void crash_and_burn(char *message); +void errno_crash_and_burn(char *message); +char *get_host_by_address(struct in_addr in); +int in_cksum(u_short *p, int n); +void u_sleep(int u_sec); +int recvfrom_wto (int s, char *buf, int len, struct sockaddr *saddr, int timo); +void remove_job(HOST_ENTRY *h); +void send_ping(int s,HOST_ENTRY *h); +long timeval_diff(struct timeval *a,struct timeval *b); +void usage(); +int wait_for_reply(); +void print_per_system_stats(); +void print_per_system_splits(); +void print_global_stats(); +void finish(); +int handle_random_icmp(struct icmp *p, int psize, struct sockaddr_in *addr); +char *sprint_tm(int t); + +#endif + +#ifdef _NO_PROTO +int main(argc,argv) +int argc; char **argv; +#else +int main(int argc, char **argv) +#endif +{ + + int c, i, n; + u_int lt, ht; + int advance; + struct protoent *proto; + char *buf; + + /* check if we are root */ + + if (geteuid()) { + fprintf(stderr, + "This program can only be run by root, or it must be setuid root.\n"); + exit(3); + } + + if ((proto = getprotobyname("icmp")) == NULL) + crash_and_burn("icmp: unknown protocol"); + s = socket(AF_INET, SOCK_RAW, proto->p_proto); + if (s<0) errno_crash_and_burn("can't create raw socket"); + + /*seteuid(getuid());*/ + + prog = argv[0]; + ident = getpid() & 0xFFFF; + + verbose_flag = 1; + backoff_flag = 1; + + opterr = 1; + + while ((c = getopt(argc, argv, + "edhlmnqusaAvz:t:i:p:f:r:c:b:C:Q:B:")) != EOF) { + switch (c) { + case 't': if (!(timeout = (u_int)atoi(optarg)*10)) + usage(); break; + case 'r': if (!(retry = (u_int)atoi(optarg))) + usage(); break; + case 'i': if (!(interval = (u_int)atoi(optarg)*10)) + usage(); break; + case 'p': if (!(perhost_interval = (u_int)atoi(optarg)*10)) + usage(); break; + case 'c': if (!(count = (u_int)atoi(optarg))) + usage(); + count_flag = 1; break; + case 'C': if (!(count = (u_int)atoi(optarg))) + usage(); + count_flag = 1; + report_all_rtts_flag = 1; break; + case 'b': if(!(ping_data_size = (u_int)atoi(optarg))) + usage(); break; + case 'h': usage(); break; + case 'q': verbose_flag = 0; quiet_flag = 1; break; + case 'Q': verbose_flag = 0; quiet_flag = 1; + if (!(report_interval = (u_int)atoi(optarg) *100000)) + usage(); break; + case 'e': elapsed_flag = 1; break; + case 'd': + case 'm': multif_flag = 1; break; + case 'n': name_flag = 1; break; + case 'A': addr_flag = 1; break; + case 'B': if (!(backoff = atof(optarg))) + usage(); break; + case 's': stats_flag = 1; break; + case 'l': loop_flag = 1; backoff_flag = 0; break; + case 'u': unreachable_flag = 1; break; + case 'a': alive_flag = 1; break; +#ifdef DEBUG + case 'z': if (!(debugging = (u_int)atoi(optarg))) + usage(); break; +#endif + case 'v': + printf("%s: Version %s $Date: 2000/12/17 17:48:05 $\n",argv[0], VERSION); + printf("%s: comments to fping@networking.Stanford.EDU\n",argv[0]); + exit(0); + case 'f': +#ifdef ENABLE_F_OPTION + filename= optarg; break; +#else + if (getuid()) { + printf("%s: this option can only be used by root.\n",argv[0]); + printf("%s: fping will read from stdin by default.\n",argv[0]); + exit(3); + } else { + filename= optarg; + break; + } +#endif + default : usage(); break; + } + } + + /* muck about based on various option settings */ + + if (unreachable_flag && alive_flag) { + fprintf(stderr,"%s: specify only one of a, u\n",argv[0]); + usage(); + } + + if (count_flag && loop_flag) { + fprintf(stderr, "%s: specify only one of c, l\n", argv[0]); + usage(); + } + + if ( (interval < MIN_INTERVAL * 10 || + perhost_interval < MIN_PERHOST_INTERVAL * 10 || + retry > MAX_RETRY || + timeout < MIN_TIMEOUT * 10) + && getuid() ) { + fprintf(stderr,"%s: these options are too risky for mere mortals.\n",prog); + fprintf(stderr, + "%s: You need i >= %u, p >= %u, r < %u, and t >= %u\n", + prog, MIN_INTERVAL, MIN_PERHOST_INTERVAL, + MAX_RETRY, MIN_TIMEOUT); + usage(); + } + + if ((ping_data_size > MAX_PING_DATA) || + (ping_data_size < MIN_PING_DATA)) { + fprintf(stderr, + "%s: data size %u not valid, must be between %u and %u\n", + prog, ping_data_size, MIN_PING_DATA, MAX_PING_DATA); + usage(); + } + + if ((backoff > MAX_BACKOFF_FACTOR) || + (backoff < MIN_BACKOFF_FACTOR)) { + fprintf(stderr, + "%s: backoff factor %.1f not valid, must be between %.1f and %.1f\n", + prog, backoff, MIN_BACKOFF_FACTOR, MAX_BACKOFF_FACTOR); + usage(); + } + + if (count > MAX_COUNT) { + fprintf(stderr, + "%s: count %u not valid, must be less than %u\n", + prog, count, MAX_COUNT); + usage(); + } + + if (alive_flag || unreachable_flag) verbose_flag=0; + if (count_flag) { + if (verbose_flag) + per_recv_flag = 1; + alive_flag = unreachable_flag = verbose_flag = 0; + } + if (loop_flag) { + if (!report_interval) + per_recv_flag = 1; + alive_flag = unreachable_flag = verbose_flag = 0; + } + + trials = (count > retry+1) ? count : retry+1; + +#ifdef DEBUG + if (debugging & DBG_TRACE) + trace_flag = 1; + if ((debugging & DBG_SENT_TIMES) && !loop_flag) + sent_times_flag = 1; + if (debugging & DBG_RANDOM_LOSE_FEW) { + randomly_lose_flag = 1; + lose_factor = 1; /* ie, 1/4 */ + } + if (debugging & DBG_RANDOM_LOSE_MANY) { + randomly_lose_flag = 1; + lose_factor = 5; /* ie, 3/4 */ + } + if (debugging & DBG_PRINT_PER_SYSTEM) + print_per_system_flag = 1; + if ((debugging & DBG_REPORT_ALL_RTTS) && !loop_flag) + report_all_rtts_flag = 1; + + if (trace_flag) { + fprintf(stderr, "%s:\n count: %u, retry: %u, interval: %u\n", + prog, count, retry, interval/10); + fprintf(stderr, " perhost_interval: %u, timeout: %u\n", + perhost_interval/10, timeout/10); + fprintf(stderr, " ping_data_size = %u, trials = %u\n", + ping_data_size, trials); + if (verbose_flag) fprintf(stderr, " verbose_flag set\n"); + if (multif_flag) fprintf(stderr, " multif_flag set\n"); + if (name_flag) fprintf(stderr, " name_flag set\n"); + if (addr_flag) fprintf(stderr, " addr_flag set\n"); + if (stats_flag) fprintf(stderr, " stats_flag set\n"); + if (unreachable_flag) fprintf(stderr, " unreachable_flag set\n"); + if (alive_flag) fprintf(stderr, " alive_flag set\n"); + if (elapsed_flag) fprintf(stderr, " elapsed_flag set\n"); + if (version_flag) fprintf(stderr, " version_flag set\n"); + if (count_flag) fprintf(stderr, " count_flag set\n"); + if (loop_flag) fprintf(stderr, " loop_flag set\n"); + if (backoff_flag) fprintf(stderr, " backoff_flag set\n"); + if (per_recv_flag) fprintf(stderr, " per_recv_flag set\n"); + if (report_all_rtts_flag) fprintf(stderr, " report_all_rtts_flag set\n"); + if (randomly_lose_flag) fprintf(stderr, " randomly_lose_flag set\n"); + if (sent_times_flag) fprintf(stderr, " sent_times_flag set\n"); + if (print_per_system_flag) fprintf(stderr, " print_per_system_flag set\n"); + } +#endif + + /* handle host names supplied on command line or in a file */ + + argv = &argv[optind]; + if (*argv && filename) { usage(); } + if (!*argv && !filename) { filename = "-"; } + + if (*argv) while (*argv) { + add_name(*argv); + ++argv; + } else if (filename) { + FILE *ping_file; + char line[132]; + char host[132],*p; + if (strcmp(filename,"-")==0) { + ping_file=fdopen(0,"r"); + } else { + ping_file=fopen(filename,"r"); + } + if (!ping_file) errno_crash_and_burn("fopen"); + while(fgets(line,132,ping_file)) { + if (sscanf(line,"%s",host) != 1) + continue; + if ((!*host) || (host[0]=='#')) /* magic to avoid comments */ + continue; + p = cpystr(host); + add_name(p); + } + fclose(ping_file); + } else usage(); + + if (!num_hosts) exit(2); + + /* allocate array to hold outstanding ping requests */ + + table = (HOST_ENTRY **) malloc(sizeof(HOST_ENTRY *)*num_hosts); + if (!table) crash_and_burn("Can't malloc array of hosts"); + + cursor=rrlist; + + for( num_jobs=0; num_jobs < num_hosts; num_jobs++ ) { + table[num_jobs]=cursor; + cursor->i = num_jobs; + /* as long as we're here, put this in so names print out nicely */ + if (count_flag || loop_flag) { + n = max_hostname_len - strlen(cursor->host); + buf = (char *) malloc(n + 1); + if (!buf) crash_and_burn("can't malloc host pad"); + for (i = 0; i < n; i++) + buf[i] = ' '; + buf[n] = '\0'; + cursor->pad = buf; + } + cursor=cursor->next; + } + + ping_pkt_size = ping_data_size + SIZE_ICMP_HDR; + signal(SIGINT, finish); + gettimeofday(&start_time,&tz); + current_time = start_time; + if (report_interval) + last_report_time = start_time; + last_send_time.tv_sec = current_time.tv_sec - 10000; +#ifdef DEBUG + if (randomly_lose_flag) + srandom(start_time.tv_usec); +#endif + cursor=rrlist; + advance = 0; + + /* main loop */ + while (num_jobs) { + if (num_pingsent) + while(wait_for_reply()) { /* call wfr until we timeout */ + /* wait! */ + }; + if (cursor && advance) cursor = cursor->next; + gettimeofday(¤t_time,&tz); + lt = timeval_diff(¤t_time, &last_send_time); + ht = timeval_diff(¤t_time, &cursor->last_send_time); + if (report_interval && + (loop_flag || count_flag) && + (timeval_diff(¤t_time, &last_report_time) + > report_interval)) { + print_per_system_splits(); + gettimeofday(¤t_time,&tz); + lt = timeval_diff(¤t_time, &last_send_time); + ht = timeval_diff(¤t_time, &cursor->last_send_time); + last_report_time = current_time; + } + + advance = 1; +#ifdef DEBUG + if (trace_flag) + printf( + "main loop:\n [%s, wait/run/sent/recv/timeout = %u/%u/%u/%u/%u], jobs/lt/ht = %u/%u/%u\n", + cursor->host, cursor->waiting, cursor->running, cursor->num_sent, + cursor->num_recv, cursor->timeout, num_jobs, lt, ht); +#endif + /* if it's OK to send while counting or looping or starting */ + if ((lt > interval) && (ht > perhost_interval)) { + /* send if starting or looping */ + if ((cursor->num_sent == 0) || loop_flag) { + send_ping(s, cursor); + continue; + } + /* send if counting and count not exceeded */ + if (count_flag) { + if (cursor->num_sent < count) { + send_ping(s,cursor); + continue; + } + } + } + /* is-it-alive mode, and timeout exceeded while waiting for a reply */ + /* and we haven't exceeded our retries */ + if ((lt > interval) && !count_flag && !loop_flag && + !cursor->num_recv && + (ht > cursor->timeout) && + (cursor->waiting < retry+1)) { +#ifdef DEBUG + if (trace_flag) + printf("main loop: timeout for %s\n", cursor->host); +#endif + num_timeout++; + /* try again */ + if (backoff_flag) + cursor->timeout *= backoff; + send_ping(s,cursor); + continue; + } + /* didn't send, can we remove? */ +#ifdef DEBUG + if (trace_flag) + printf("main loop: didn't send to %s\n", cursor->host); +#endif + /* never remove if looping */ + if (loop_flag) + continue; + /* remove if counting and count exceeded */ + /* but allow time for the last one to come in */ + if (count_flag) { + if ((cursor->num_sent >= count) && + (ht > cursor->timeout)) { + remove_job(cursor); + continue; + } + } else { + /* normal mode, and we got one */ + if (cursor->num_recv) { + remove_job(cursor); + continue; + } + /* normal mode, and timeout exceeded while waiting for a reply */ + /* and we've run out of retries, so node is unreachable */ + if ((ht > cursor->timeout) && + (cursor->waiting >= retry+1)) { +#ifdef DEBUG + if (trace_flag) + printf("main loop: timeout for %s\n", cursor->host); +#endif + num_timeout++; + remove_job(cursor); + continue; + } + } + /* could send to this host, so keep considering it */ + if (ht > interval) + advance = 0; + } + finish(); +} + +#ifdef _NO_PROTO +void finish() +#else +void finish() +#endif +{ + int i; + HOST_ENTRY *h; + + gettimeofday(&end_time,&tz); + + /* tot up unreachables */ + for (i = 0; i < num_hosts; i++) { + h = table[i]; + if (!h->num_recv) { + num_unreachable++; + if(verbose_flag || unreachable_flag) { + printf("%s", h->host); + if (verbose_flag) + printf(" is unreachable"); + printf("\n"); + } + } + } + + if (count_flag || loop_flag) { + print_per_system_stats(); + } +#ifdef DEBUG + else if (print_per_system_flag) + print_per_system_stats(); +#endif + + if (stats_flag) + print_global_stats(); + + if (num_noaddress) exit(2); + else if (num_alive != num_hosts) exit(1); + + exit(0); + +} + +#ifdef _NO_PROTO +void print_per_system_stats () +#else +void print_per_system_stats () +#endif +{ + int i, j, k, avg; + HOST_ENTRY *h; + char *buf; + int bufsize; + int resp; + + bufsize = max_hostname_len + 1; + buf = (char *) malloc(bufsize); + if (!buf) crash_and_burn("can't malloc print buf"); + memset(buf, 0, bufsize); + + fflush(stdout); + if (verbose_flag || per_recv_flag) fprintf(stderr,"\n"); + for (i = 0; i < num_hosts; i++) { + h = table[i]; + fprintf(stderr, "%s%s :", h->host, h->pad); + if (report_all_rtts_flag) { + for (j = 0; j < h->num_sent; j++) + if ((resp = h->resp_times[j]) >= 0) + fprintf(stderr, " %d.%d", resp/10, resp%10); + else fprintf(stderr, " -"); + fprintf(stderr, "\n"); + } else { + if (h->num_recv <= h->num_sent) { + fprintf(stderr, " xmt/rcv/%%loss = %d/%d/%d%%", + h->num_sent, h->num_recv, + ((h->num_sent - h->num_recv) * 100) / h->num_sent); + } else { + fprintf(stderr, " xmt/rcv/%%return = %d/%d/%d%%", + h->num_sent, h->num_recv, + ((h->num_recv * 100) / h->num_sent)); + } + if (h->num_recv) { + avg = h->total_time / h->num_recv; + fprintf(stderr, ", min/avg/max = %s", sprint_tm(h->min_reply)); + fprintf(stderr, "/%s", sprint_tm(avg)); + fprintf(stderr, "/%s", sprint_tm(h->max_reply)); + } + fprintf(stderr, "\n"); + } +#ifdef DEBUG + if (sent_times_flag) { + for (j = 0; j < h->num_sent; j++) + if ((resp = h->sent_times[j]) >= 0) + fprintf(stderr, " %s", sprint_tm(resp)); + else fprintf(stderr, " -"); + fprintf(stderr, "\n"); + } +#endif + } + free(buf); +} + + +#ifdef _NO_PROTO +void print_per_system_splits () +#else +void print_per_system_splits () +#endif +{ + int i, j, k, avg; + HOST_ENTRY *h; + char *buf; + int bufsize; + int resp; + struct tm *curr_tm; + + bufsize = max_hostname_len + 1; + buf = (char *) malloc(bufsize); + if (!buf) crash_and_burn("can't malloc print buf"); + memset(buf, 0, bufsize); + + fflush(stdout); + if (verbose_flag || per_recv_flag) fprintf(stderr,"\n"); + curr_tm = localtime((time_t *)¤t_time.tv_sec); + fprintf(stderr, "[%2.2d:%2.2d:%2.2d]\n", curr_tm->tm_hour, + curr_tm->tm_min, curr_tm->tm_sec); + for (i = 0; i < num_hosts; i++) { + h = table[i]; + fprintf(stderr, "%s%s :", h->host, h->pad); + if (h->num_recv_i <= h->num_sent_i) { + fprintf(stderr, " xmt/rcv/%%loss = %d/%d/%d%%", + h->num_sent_i, h->num_recv_i, + ((h->num_sent_i - h->num_recv_i) * 100) / h->num_sent_i); + } else { + fprintf(stderr, " xmt/rcv/%%return = %d/%d/%d%%", + h->num_sent_i, h->num_recv_i, + ((h->num_recv_i * 100) / h->num_sent_i)); + } + if (h->num_recv_i) { + avg = h->total_time_i / h->num_recv_i; + fprintf(stderr, ", min/avg/max = %s", sprint_tm(h->min_reply_i)); + fprintf(stderr, "/%s", sprint_tm(avg)); + fprintf(stderr, "/%s", sprint_tm(h->max_reply_i)); + } + fprintf(stderr, "\n"); + h->num_sent_i = h->num_recv_i = h->max_reply_i = h->min_reply_i = + h->total_time_i = 0; + } + free(buf); +} + +#ifdef _NO_PROTO +void print_global_stats() +#else +void print_global_stats() +#endif +{ + fflush(stdout); + fprintf(stderr,"\n"); + fprintf(stderr," %7d targets\n",num_hosts); + fprintf(stderr," %7d alive\n",num_alive); + fprintf(stderr," %7d unreachable\n",num_unreachable); + fprintf(stderr," %7d unknown addresses\n",num_noaddress); + fprintf(stderr,"\n"); + fprintf(stderr," %7d timeouts (waiting for response)\n",num_timeout); + fprintf(stderr," %7d ICMP Echos sent\n",num_pingsent); + fprintf(stderr," %7d ICMP Echo Replies received\n",num_pingreceived); + fprintf(stderr," %7d other ICMP received\n",num_othericmprcvd); + fprintf(stderr,"\n"); + + if (total_replies==0) { + min_reply=0; max_reply=0; total_replies=1; sum_replies=0; + } + + fprintf(stderr," %s ms (min round trip time)\n", sprint_tm(min_reply)); + fprintf(stderr," %s ms (avg round trip time)\n", + sprint_tm((int)(sum_replies/total_replies))); + fprintf(stderr," %s ms (max round trip time)\n", sprint_tm(max_reply)); + fprintf(stderr," %12.3f sec (elapsed real time)\n", + timeval_diff( &end_time,&start_time)/100000.0); + fprintf(stderr,"\n"); +} + +/* + * + * Compose and transmit an ICMP_ECHO REQUEST packet. The IP packet + * will be added on by the kernel. The ID field is our UNIX process ID, + * and the sequence number is an index into an array of outstanding + * ping requests. The sequence number will later be used to quickly + * figure out who the ping reply came from. + * + */ + +#ifdef _NO_PROTO +void send_ping(s,h) +int s; HOST_ENTRY *h; +#else +void send_ping(int s,HOST_ENTRY *h) +#endif +{ + char *buffer; + struct icmp *icp; + PING_DATA *pdp; + int n; + + buffer = (char *) malloc ((size_t)ping_pkt_size); + if (!buffer) crash_and_burn("can't malloc ping packet"); + memset(buffer, 0, ping_pkt_size * sizeof(char)); + icp = (struct icmp *) buffer; + + gettimeofday(&h->last_send_time,&tz); + icp->icmp_type = ICMP_ECHO; + icp->icmp_code = 0; + icp->icmp_cksum = 0; + icp->icmp_seq = h->i; + icp->icmp_id = ident; + + pdp = (PING_DATA *) (buffer + SIZE_ICMP_HDR); + pdp->ping_ts = h->last_send_time; + pdp->ping_count = h->num_sent; + + icp->icmp_cksum = in_cksum( (u_short *)icp, ping_pkt_size ); + +#ifdef DEBUG + if (trace_flag) + printf("sending [%d] to %s\n", h->num_sent, h->host); +#endif + n = sendto( s, buffer, ping_pkt_size, 0, (struct sockaddr *)&h->saddr, + sizeof(struct sockaddr_in) ); + if( n < 0 || n != ping_pkt_size ) { + if (verbose_flag || unreachable_flag) { + printf("%s", h->host); + if (verbose_flag) printf(" error while sending ping: %s\n", + sys_errlist[errno]); + printf("\n"); + } + num_unreachable++; + remove_job(h); + } else { + /* mark this trial as outstanding */ + if (!loop_flag) + h->resp_times[h->num_sent] = RESP_WAITING; +#ifdef DEBUG + if (sent_times_flag) + h->sent_times[h->num_sent] = + timeval_diff(&h->last_send_time, &start_time); +#endif + h->num_sent++; h->num_sent_i++; + h->waiting++; + num_pingsent++; + last_send_time = h->last_send_time; + } + free(buffer); +} + +#ifdef _NO_PROTO +int wait_for_reply() +#else +int wait_for_reply() +#endif +{ + int result; + static char buffer[4096]; + struct sockaddr_in response_addr; + struct ip *ip; + int hlen; + struct icmp *icp; + int n, avg; + HOST_ENTRY *h; + PING_DATA *pdp; + long this_reply; + int this_count; + struct timeval sent_time; + + result=recvfrom_wto(s,buffer,4096, + (struct sockaddr *)&response_addr,select_time); + if (result<0) { return 0; } /* timeout */ + +#ifdef DEBUG + if (randomly_lose_flag) + if ((random() & 0x07) <= lose_factor) + return 0; +#endif + ip = (struct ip *) buffer; +#if defined(__alpha__) && __STDC__ + /* The alpha headers are decidedly broken. + * Using an ANSI compiler, it provides ip_vhl instead of ip_hl and + * ip_v. So, to get ip_hl, we mask off the bottom four bits. + */ + hlen = (ip->ip_vhl & 0x0F) << 2; +#else + hlen = ip->ip_hl << 2; +#endif + + if (result < hlen+ICMP_MINLEN) { + if (verbose_flag) + printf("received packet too short for ICMP (%d bytes from %s)\n", + result, inet_ntoa(response_addr.sin_addr)); + return(1); /* too short */ + } + + icp = (struct icmp *)(buffer + hlen); + if (icp->icmp_type != ICMP_ECHOREPLY) { + /* handle some problem */ + if (handle_random_icmp(icp, result, &response_addr)) + num_othericmprcvd++; + return 1; + } + + if (icp->icmp_id != ident) + return 1; /* packet received, but not the one we are looking for! */ + + num_pingreceived++; + + if (icp->icmp_seq >= (n_short)num_hosts) + return(1); /* packet received, don't worry about it anymore */ + + n=icp->icmp_seq; + h=table[n]; + + /* received ping is cool, so process it */ + gettimeofday(¤t_time,&tz); + h->waiting = 0; + h->timeout = timeout; + h->num_recv++; h->num_recv_i++; + + pdp = (PING_DATA *)icp->icmp_data; + sent_time = pdp->ping_ts; + this_count = pdp->ping_count; +#ifdef DEBUG + if (trace_flag) + printf("received [%d] from %s\n", this_count, h->host); +#endif + this_reply = timeval_diff(¤t_time,&sent_time); + if (this_reply > max_reply) max_reply=this_reply; + if (this_reply < min_reply) min_reply=this_reply; + if (this_reply > h->max_reply) h->max_reply=this_reply; + if (this_reply < h->min_reply) h->min_reply=this_reply; + if (this_reply > h->max_reply_i) h->max_reply_i=this_reply; + if (this_reply < h->min_reply_i) h->min_reply_i=this_reply; + sum_replies += this_reply; + h->total_time += this_reply; + h->total_time_i += this_reply; + total_replies++; + /* note reply time in array, probably */ + if (!loop_flag) { + if ((this_count >= 0) && (this_count < trials)) { + if (h->resp_times[this_count] != RESP_WAITING) { + if (!per_recv_flag) { + fprintf(stderr, + "%s : duplicate for [%d], %d bytes, %s ms", + h->host, this_count, result, + sprint_tm(this_reply)); + if (response_addr.sin_addr.s_addr != h->saddr.sin_addr.s_addr) + fprintf(stderr, " [<- %s]", inet_ntoa(response_addr.sin_addr)); + fprintf(stderr, "\n"); + } + } else { + h->resp_times[this_count] = this_reply; + } + } else { + /* count is out of bounds?? */ + fprintf(stderr, + "%s : duplicate for [%d], %d bytes, %s ms\n", + h->host, this_count, result, + sprint_tm(this_reply)); + } + } + + if (h->num_recv == 1) { + num_alive++; + if(verbose_flag||alive_flag) { + printf("%s",h->host); + if (verbose_flag) printf(" is alive"); + if (elapsed_flag) printf(" (%s ms)", sprint_tm(this_reply)); + if (response_addr.sin_addr.s_addr != h->saddr.sin_addr.s_addr) + printf(" [<- %s]", inet_ntoa(response_addr.sin_addr)); + printf("\n"); + } + } + + if (per_recv_flag) { + avg = h->total_time / h->num_recv; + printf("%s%s : [%d], %d bytes, %s ms", + h->host, h->pad, + this_count, + result, + sprint_tm(this_reply)); + printf(" (%s avg, ", sprint_tm(avg)); + if (h->num_recv <= h->num_sent) { + printf("%d%% loss)", + ((h->num_sent - h->num_recv) * 100) + / h->num_sent); + } else { + printf("%d%% return)", + (h->num_recv * 100) + / h->num_sent); + } + if (response_addr.sin_addr.s_addr != h->saddr.sin_addr.s_addr) + printf(" [<- %s]", inet_ntoa(response_addr.sin_addr)); + printf("\n"); + } + return num_jobs; +} + +#ifdef _NO_PROTO +int handle_random_icmp(p, psize, addr) + struct icmp *p; + int psize; + struct sockaddr_in *addr; +#else +int handle_random_icmp(struct icmp *p, int psize, struct sockaddr_in *addr) +#endif +{ + struct icmp *sent_icmp; + struct ip *sent_ip; + u_char *c; + HOST_ENTRY *h; + + c = (u_char *)p; + switch (p->icmp_type) { + case ICMP_UNREACH: + sent_icmp = (struct icmp *) (c + 28); + if ((sent_icmp->icmp_type == ICMP_ECHO) && + (sent_icmp->icmp_id == ident) && + (sent_icmp->icmp_seq < (n_short)num_hosts)) { + /* this is a response to a ping we sent */ + h = table[sent_icmp->icmp_seq]; + if (p->icmp_code > ICMP_UNREACH_MAXTYPE) { + fprintf(stderr, + "ICMP Unreachable (Invalid Code) from %s for ICMP Echo sent to %s", + inet_ntoa(addr->sin_addr), h->host); } + else { + fprintf(stderr, "%s from %s for ICMP Echo sent to %s", + icmp_unreach_str[p->icmp_code], + inet_ntoa(addr->sin_addr), h->host); + } + if (inet_addr(h->host) == -1) + fprintf(stderr, " (%s)", inet_ntoa(h->saddr.sin_addr)); + fprintf(stderr, "\n"); + } + return 1; + case ICMP_SOURCEQUENCH: + case ICMP_REDIRECT: + case ICMP_TIMXCEED: + case ICMP_PARAMPROB: + sent_icmp = (struct icmp *) (c + 28); + if ((sent_icmp->icmp_type = ICMP_ECHO) && + (sent_icmp->icmp_id = ident) && + (sent_icmp->icmp_seq < (n_short)num_hosts)) { + /* this is a response to a ping we sent */ + h = table[sent_icmp->icmp_seq]; + fprintf(stderr, "%s from %s for ICMP Echo sent to %s", + icmp_type_str[p->icmp_type], + inet_ntoa(addr->sin_addr), h->host); + if (inet_addr(h->host) == -1) + fprintf(stderr, " (%s)", inet_ntoa(h->saddr.sin_addr)); + fprintf(stderr, "\n"); + } + return 2; + /* no way to tell whether any of these are sent due to our ping */ + /* or not (shouldn't be, of course), so just discard */ + case ICMP_TSTAMP: + case ICMP_TSTAMPREPLY: + case ICMP_IREQ: + case ICMP_IREQREPLY: + case ICMP_MASKREQ: + case ICMP_MASKREPLY: + default: + return 0; + } +} + +/* + * Checksum routine for Internet Protocol family headers (C Version) + * From ping examples in W.Richard Stevens "UNIX NETWORK PROGRAMMING" book. + */ + +#ifdef _NO_PROTO +int in_cksum(p,n) +u_short *p; int n; +#else +int in_cksum(u_short *p, int n) +#endif +{ + register u_short answer; + register long sum = 0; + u_short odd_byte = 0; + + while( n > 1 ) { sum += *p++; n -= 2; } + + /* mop up an odd byte, if necessary */ + if( n == 1 ) { + *(u_char *)(&odd_byte) = *(u_char *)p; + sum += odd_byte; + } + + sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ + sum += (sum >> 16); /* add carry */ + answer = ~sum; /* ones-complement, truncate*/ + return (answer); +} + + +/* process input name for addition to target list */ +/* name can turn into multiple targets via multiple interfaces (-m) */ +/* or via NIS groups */ + +#ifdef _NO_PROTO +void add_name(name) +char *name; +#else +void add_name(char *name) +#endif +{ + struct hostent *host_ent; + u_int ipaddress; + struct in_addr *ipa = (struct in_addr *)&ipaddress; + struct in_addr *host_add; + char *nm; + int i = 0; + + if ((ipaddress = inet_addr(name)) != -1) { + /* input name is an IP addr, go with it */ + if (name_flag) { + if (addr_flag) { + add_addr(name, na_cat(get_host_by_address(*ipa), *ipa), *ipa); + } else { + nm = cpystr(get_host_by_address(*ipa)); + add_addr(name, nm, *ipa); + } + } else { + add_addr(name, name, *ipa); + } + return; + } + /* input name is not an IP addr, maybe it's a host name */ + host_ent = gethostbyname(name); + if (host_ent == NULL) { + if (h_errno == TRY_AGAIN) { + u_sleep(DNS_TIMEOUT) ; + host_ent = gethostbyname(name) ; + } + if (host_ent == NULL) { +#ifdef NIS_GROUPS + /* maybe it's the name of a NIS netgroup */ + char *machine, *user_ignored, *domain_ignored; + setnetgrent(name); + if (getnetgrent(&machine, &user_ignored, &domain_ignored)==0){ + endnetgrent(); + if (!quiet_flag) fprintf(stderr,"%s address not found\n", name); + num_noaddress++; + return; + } else { + add_name(cpystr(machine)); + } + while(getnetgrent(&machine, &user_ignored, &domain_ignored)) + add_name(cpystr(machine)); + endnetgrent(); + return; +#else + if (!quiet_flag) fprintf(stderr,"%s address not found\n", name); + num_noaddress++; + return ; +#endif + } + } + host_add = (struct in_addr *) *(host_ent->h_addr_list) ; + if (host_add == NULL) { + if (!quiet_flag) fprintf(stderr,"%s has no address data\n", name); + num_noaddress++; + return ; + } else { + /* it is indeed a hostname with a real address */ + while (host_add) { + if (name_flag && addr_flag) { + add_addr(name, na_cat(name, *host_add), *host_add); + } else if (addr_flag) { + nm = cpystr(inet_ntoa(*host_add)); + add_addr(name, nm, *host_add); + } else { + add_addr(name, name, *host_add); + } + if (!multif_flag) break; + host_add = (struct in_addr *) (host_ent->h_addr_list[++i]) ; + } + } +} + +#ifdef _NO_PROTO +char *na_cat(name, ipaddr) +char *name; +struct in_addr ipaddr; +#else +char *na_cat(char *name, struct in_addr ipaddr) +#endif +{ + char *nm, *as; + + as = inet_ntoa(ipaddr); + nm = (char *) malloc(strlen(name) + strlen(as) + 4); + if (!nm) crash_and_burn("can't allocate some space for a string"); + strcpy(nm, name); + strcat(nm, " ("); + strcat(nm, as); + strcat(nm, ")"); + return(nm); +} + +/* add address to linked list of targets to be pinged */ +/* assume memory for *name and *host is ours!!! */ + +#ifdef _NO_PROTO +void add_addr(name, host, ipaddr) +char *name; +char *host; +struct in_addr ipaddr; +#else +void add_addr(char *name, char *host, struct in_addr ipaddr) +#endif +{ + HOST_ENTRY *p; + int n, *i; + + p = (HOST_ENTRY *) malloc(sizeof(HOST_ENTRY)); + if (!p) crash_and_burn("can't allocate HOST_ENTRY"); + memset((char *) p, 0, sizeof(HOST_ENTRY)); + + p->name = name; + p->host = host; + p->saddr.sin_family = AF_INET; + p->saddr.sin_addr = ipaddr; + p->timeout = timeout; + p->running = 1; + p->min_reply = 10000000; + + if (strlen(p->host) > max_hostname_len) + max_hostname_len = strlen(p->host); + + /* array for response time results */ + if (!loop_flag) { + i = (int *) malloc(trials * sizeof(int)); + if (!i) crash_and_burn("can't allocate resp_times array"); + for (n = 1; n < trials; n++) + i[n] = RESP_UNUSED; + p->resp_times = i; + } +#ifdef DEBUG + /* likewise for sent times */ + if (sent_times_flag) { + i = (int *) malloc(trials * sizeof(int)); + if (!i) crash_and_burn("can't allocate sent_times array"); + for (n = 1; n < trials; n++) + i[n] = RESP_UNUSED; + p->sent_times = i; + } +#endif + + if (!rrlist) { + rrlist = p; + p->next = p; + p->prev = p; + } else { + p->next = rrlist; + p->prev = rrlist->prev; + p->prev->next = p; + p->next->prev = p; + } + num_hosts++; +} + +#ifdef _NO_PROTO +void remove_job(h) +HOST_ENTRY *h; +#else +void remove_job(HOST_ENTRY *h) +#endif +{ + +#ifdef DEBUG + if (trace_flag) + printf("removing job for %s\n", h->host); +#endif + h->running = 0; + h->waiting = 0; + --num_jobs; + + if (num_jobs) { /* remove us from list of active jobs */ + h->prev->next = h->next; + h->next->prev = h->prev; + if (h==cursor) { cursor = h->next; } + } else { + cursor=NULL; + rrlist=NULL; + } + +} + +#ifdef _NO_PROTO +char *get_host_by_address(in) +struct in_addr in; +#else +char *get_host_by_address(struct in_addr in) +#endif +{ + struct hostent *h; + h=gethostbyaddr((char *) &in,sizeof(struct in_addr),AF_INET); + if (h==NULL || h->h_name==NULL) return inet_ntoa(in); + else return (char*)h->h_name; +} + + +#ifdef _NO_PROTO +char *cpystr(string) +char *string; +#else +char *cpystr(char *string) +#endif +{ + char *dst; + + if (string) { + dst = (char *) malloc (1+strlen (string)); + if (!dst) crash_and_burn("can't allocate some space for a string"); + strcpy (dst, string); + return dst; + } + else + return NULL; +} + +#ifdef _NO_PROTO +void crash_and_burn(message) +char *message; +#else +void crash_and_burn(char *message) +#endif +{ + if (verbose_flag) fprintf(stderr,"%s: %s\n",prog,message); + exit(4); +} + +#ifdef _NO_PROTO +void errno_crash_and_burn(message) +char *message; +#else +void errno_crash_and_burn(char *message) +#endif +{ + if (verbose_flag) + fprintf(stderr,"%s: %s : %s\n",prog,message,sys_errlist[errno]); + exit(4); +} + +/* timeval_diff now returns result in hundredths of milliseconds */ +/* ie, tens of microseconds */ +#ifdef _NO_PROTO +long timeval_diff(a,b) +struct timeval *a,*b; +#else +long timeval_diff(struct timeval *a,struct timeval *b) +#endif +{ +double temp; + +temp = + (((a->tv_sec*1000000)+ a->tv_usec) - + ((b->tv_sec*1000000)+ b->tv_usec))/10; + +return (long) temp; + +} + +/* + * sprint_time: render time into a string with three digits of precision + * input is in tens of microseconds + */ + +#ifdef _NO_PROTO +char * sprint_tm(t) +int t; +#else +char * sprint_tm(int t) +#endif +{ + static char buf[10]; + + /* <= 0.99 ms */ + if (t < 100) { + sprintf(buf, "0.%02d", t); + return(buf); + } + /* 1.00 - 9.99 ms */ + if (t < 1000) { + sprintf(buf, "%d.%02d", t/100, t%100); + return(buf); + } + /* 10.0 - 99.9 ms */ + if (t < 10000) { + sprintf(buf, "%d.%d", t/100, (t%100)/10); + return(buf); + } + /* >= 100 ms */ + sprintf(buf, "%d", t/100); + return(buf); +} + +#ifdef _NO_PROTO +void u_sleep (u_sec) +int u_sec; +#else +void u_sleep (int u_sec) +#endif +{ + int nfound,slen,n; + struct timeval to; + fd_set readset,writeset; + + to.tv_sec = u_sec/1000000; + to.tv_usec = u_sec - (to.tv_sec*1000000); + + FD_ZERO(&readset); + FD_ZERO(&writeset); + nfound = select(0, &readset, &writeset, NULL, &to); + if (nfound<0) errno_crash_and_burn("select"); + return; +} + +/* + * recvfrom_wto: receive with timeout + * returns length of data read or -1 if timeout + * crash_and_burn on any other errrors + * + */ + +#ifdef _NO_PROTO +int recvfrom_wto (s,buf,len, saddr, timo) +int s; char *buf; int len; struct sockaddr *saddr; int timo; +#else +int recvfrom_wto (int s, char *buf, int len, struct sockaddr *saddr, int timo) +#endif +{ + int nfound,slen,n; + struct timeval to; + fd_set readset,writeset; + + to.tv_sec = timo/100000; + to.tv_usec = (timo - (to.tv_sec*100000))*10; + + FD_ZERO(&readset); + FD_ZERO(&writeset); + FD_SET(s,&readset); + nfound = select(s+1,&readset,&writeset,NULL,&to); + if (nfound<0) errno_crash_and_burn("select"); + if (nfound==0) return -1; /* timeout */ + slen=sizeof(struct sockaddr); + n=recvfrom(s,buf,len,0,saddr,&slen); + if (n<0) errno_crash_and_burn("recvfrom"); + return n; +} + +#ifdef _NO_PROTO +void usage() +#else +void usage() +#endif +{ + fprintf(stderr,"\n"); + fprintf(stderr,"Usage: %s [options] [targets...]\n",prog); + fprintf(stderr," -a show targets that are alive\n"); + fprintf(stderr," -A show targets by address\n"); + fprintf(stderr," -b n amount of ping data to send, in bytes (default %d)\n", ping_data_size); + fprintf(stderr," -B f set exponential backoff factor to f\n"); + fprintf(stderr," -c n count of pings to send to each target (default %d)\n", count); + fprintf(stderr," -C n same as -c, report results in verbose format\n"); + fprintf(stderr," -e show elapsed time on return packets\n"); + fprintf(stderr," -f file read list of targets from a file ( - means stdin)\n"); + fprintf(stderr," -i n interval between sending ping packets (in millisec) (default %d)\n",interval/100); + fprintf(stderr," -l loop sending pings forever\n"); + fprintf(stderr," -m ping multiple interfaces on target host\n"); + fprintf(stderr," -n show targets by name (-d is equivalent)\n"); + fprintf(stderr," -p n interval between ping packets to one target (in millisec)\n"); + fprintf(stderr," (in looping and counting modes, default %d)\n", perhost_interval/100); + fprintf(stderr," -q quiet (don't show per-target/per-ping results)\n"); + fprintf(stderr," -Q n same as -q, but show summary every n seconds\n"); + fprintf(stderr," -r n number of retries (default %d)\n",retry); + fprintf(stderr," -s print final stats\n"); + fprintf(stderr," -t n individual target initial timeout (in millisec) (default %d)\n",timeout/100); + fprintf(stderr," -u show targets that are unreachable\n"); + fprintf(stderr," -v show version\n"); + fprintf(stderr," targets list of targets to check (if no -f specified)\n"); + fprintf(stderr,"\n"); + exit(3); +} diff --git a/net-misc/fping/fping-2.2_beta1.ebuild b/net-misc/fping/fping-2.2_beta1.ebuild new file mode 100644 index 000000000000..15e16b0edfc2 --- /dev/null +++ b/net-misc/fping/fping-2.2_beta1.ebuild @@ -0,0 +1,32 @@ +# Copyright 1999-2000 Gentoo Technologies, Inc. +# Distributed under the terms of the GNU General Public License, v2 or later +# Author Your Name <your email> +# $Header: /var/cvsroot/gentoo-x86/net-misc/fping/fping-2.2_beta1.ebuild,v 1.1 2000/12/17 17:48:05 achim Exp $ + +S=${WORKDIR}/fping-2.2b1 +DESCRIPTION="A utility to ping multiple hosts at once" +SRC_URI="ftp://ftp.kernel.org/pub/software/admin/mon/fping-2.2b1.tar.bz2" +HOMEPAGE="http://www.stanford.edu/~schemers/docs/fping/fping.html" + +src_unpack() { + unpack ${A} + cp ${FILESDIR}/fping.c ${S} +} + +src_compile() { + + cd ${S} + try ./configure --prefix=/usr --host=${CHOST} + try make + +} + +src_install () { + + cd ${S} + dobin fping + doman fping.8 + dodoc COPYING ChangeLog README + +} + |