Make ping -Wall clean (except for one warning).

Do a better job of argument parsing.
Don't permit ping -f to a multicast address (very antisocial).
Don't permit -L, -I, -T options with unicast addresses.
Ensure that we ask for only AF_INET addresses (should close PR#2584).
Return <sysexits.h> error codes for failures.  Document this.
Fix man page to identify the author and put sections in correct order.
This commit is contained in:
Garrett Wollman 1997-03-01 20:19:18 +00:00
parent 67022bfc9f
commit 43470e3be8
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=23247
3 changed files with 219 additions and 174 deletions

View File

@ -4,5 +4,6 @@ PROG= ping
MAN8= ping.8 MAN8= ping.8
BINOWN= root BINOWN= root
BINMODE=4555 BINMODE=4555
COPTS+= -Wall -Wmissing-prototypes
.include <bsd.prog.mk> .include <bsd.prog.mk>

View File

@ -30,9 +30,9 @@
.\" SUCH DAMAGE. .\" SUCH DAMAGE.
.\" .\"
.\" @(#)ping.8 8.2 (Berkeley) 12/11/93 .\" @(#)ping.8 8.2 (Berkeley) 12/11/93
.\" $Id$ .\" $Id: ping.8,v 1.7 1997/02/22 14:33:06 peter Exp $
.\" .\"
.Dd December 11, 1993 .Dd March 1, 1997
.Dt PING 8 .Dt PING 8
.Os BSD 4.3 .Os BSD 4.3
.Sh NAME .Sh NAME
@ -154,8 +154,14 @@ option in the
.Tn ECHO_REQUEST .Tn ECHO_REQUEST
packet and displays packet and displays
the route buffer on returned packets. the route buffer on returned packets.
Note that the IP header is only large enough for nine such routes. Note that the IP header is only large enough for nine such routes;
Many hosts ignore or discard this option. the
.Xr traceroute 8
command is usually better at determining the route packets take to a
particular destination.
Many hosts ignore or discard the
.Tn RECORD_ROUTE
option.
.It Fl r .It Fl r
Bypass the normal routing tables and send directly to a host on an attached Bypass the normal routing tables and send directly to a host on an attached
network. network.
@ -337,6 +343,31 @@ packets that they use for
packets, for example either 30 or 60. packets, for example either 30 or 60.
Others may use completely wild values. Others may use completely wild values.
.El .El
.Sh RETURN VALUES
The
.Nm ping
command returns an exit status of zero if at least one response was
heard from the specified
.Ar host ;
a status of two if the transmission was successful but no responses
were received; or another value
.Pq from Aq Pa sysexits.h
if an error occurred.
.Sh SEE ALSO
.Xr netstat 1 ,
.Xr ifconfig 8 ,
.Xr routed 8 ,
.Xr traceroute 8
.Sh HISTORY
The
.Nm
command appeared in
.Bx 4.3 .
.Sh AUTHORS
The original
.Nm
command was written by Mike Muuss while at the US Army Ballistics
Research Laboratory.
.Sh BUGS .Sh BUGS
Many Hosts and Gateways ignore the Many Hosts and Gateways ignore the
.Tn RECORD_ROUTE .Tn RECORD_ROUTE
@ -354,12 +385,3 @@ broadcast address should only be done under very controlled conditions.
The The
.Fl v .Fl v
option is not worth much on busy hosts. option is not worth much on busy hosts.
.Sh SEE ALSO
.Xr netstat 1 ,
.Xr ifconfig 8 ,
.Xr routed 8
.Sh HISTORY
The
.Nm
command appeared in
.Bx 4.3 .

View File

@ -35,13 +35,17 @@
*/ */
#ifndef lint #ifndef lint
static char copyright[] = static const char copyright[] =
"@(#) Copyright (c) 1989, 1993\n\ "@(#) Copyright (c) 1989, 1993\n\
The Regents of the University of California. All rights reserved.\n"; The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */ #endif /* not lint */
#ifndef lint #ifndef lint
/*
static char sccsid[] = "@(#)ping.c 8.1 (Berkeley) 6/5/93"; static char sccsid[] = "@(#)ping.c 8.1 (Berkeley) 6/5/93";
*/
static const char rcsid[] =
"$Id$";
#endif /* not lint */ #endif /* not lint */
/* /*
@ -62,24 +66,30 @@ static char sccsid[] = "@(#)ping.c 8.1 (Berkeley) 6/5/93";
* This program has to run SUID to ROOT to access the ICMP socket. * This program has to run SUID to ROOT to access the ICMP socket.
*/ */
#include <sys/param.h> #include <sys/param.h> /* NB: we rely on this for <sys/types.h> */
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <netdb.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <termios.h>
#include <unistd.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/file.h> #include <sys/file.h>
#include <sys/time.h> #include <sys/time.h>
#include <signal.h>
#include <termios.h>
#include <netinet/in_systm.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h> #include <netinet/ip.h>
#include <netinet/ip_icmp.h> #include <netinet/ip_icmp.h>
#include <netinet/ip_var.h> #include <netinet/ip_var.h>
#include <netdb.h> #include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
#define DEFDATALEN (64 - 8) /* default data length */ #define DEFDATALEN (64 - 8) /* default data length */
#define MAXIPLEN 60 #define MAXIPLEN 60
@ -145,26 +155,38 @@ double tsum = 0.0; /* sum of all times, for doing average */
int reset_kerninfo; int reset_kerninfo;
sig_atomic_t siginfo_p; sig_atomic_t siginfo_p;
char *pr_addr(); static void fill(char *, char *);
void catcher(), finish(), status(), check_status(); static u_short in_cksum(u_short *, int);
static void catcher(int sig);
static void check_status(void);
static void finish(int) __dead2;
static void pinger(void);
static char *pr_addr(struct in_addr);
static void pr_icmph(struct icmp *);
static void pr_iph(struct ip *);
static void pr_pack(char *, int, struct sockaddr_in *);
static void pr_retip(struct ip *);
static void status(int);
static void tvsub(struct timeval *, struct timeval *);
static void usage(const char *) __dead2;
int
main(argc, argv) main(argc, argv)
int argc; int argc;
char **argv; char *const *argv;
{ {
extern int errno, optind;
extern char *optarg;
struct timeval timeout; struct timeval timeout;
struct hostent *hp; struct hostent *hp;
struct sockaddr_in *to; struct sockaddr_in *to;
struct protoent *proto;
struct termios ts; struct termios ts;
register int i; register int i;
int ch, fdmask, hold, packlen, preload, sockerrno; int ch, fdmask, hold, packlen, preload, sockerrno;
struct in_addr ifaddr; struct in_addr ifaddr;
unsigned char ttl, loop; unsigned char ttl, loop;
u_char *datap, *packet; u_char *datap, *packet;
char *target, hnamebuf[MAXHOSTNAMELEN], *malloc(); char *target, hnamebuf[MAXHOSTNAMELEN];
char *ep;
u_long ultmp;
#ifdef IP_OPTIONS #ifdef IP_OPTIONS
char rspace[3 + 4 * NROUTES + 1]; /* record route space */ char rspace[3 + 4 * NROUTES + 1]; /* record route space */
#endif #endif
@ -175,66 +197,59 @@ main(argc, argv)
* then drop our setuid bit. Save error reporting for * then drop our setuid bit. Save error reporting for
* after arg parsing. * after arg parsing.
*/ */
proto = getprotobyname("icmp"); s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (proto) { sockerrno = errno;
s = socket(AF_INET, SOCK_RAW, proto->p_proto);
sockerrno = errno;
}
setuid(getuid()); setuid(getuid());
preload = 0; preload = 0;
datap = &outpack[8 + sizeof(struct timeval)]; datap = &outpack[8 + sizeof(struct timeval)];
while ((ch = getopt(argc, argv, "I:LQRT:c:adfh:i:l:np:qrs:v")) != EOF) while ((ch = getopt(argc, argv, "I:LQRT:c:adfh:i:l:np:qrs:v")) != -1) {
switch(ch) { switch(ch) {
case 'a': case 'a':
options |= F_AUDIBLE; options |= F_AUDIBLE;
break; break;
case 'c': case 'c':
npackets = atoi(optarg); ultmp = strtoul(optarg, &ep, 0);
if (npackets <= 0) { if (*ep || ep == optarg || ultmp > LONG_MAX || !ultmp)
(void)fprintf(stderr, errx(EX_USAGE,
"ping: bad number of packets to transmit.\n"); "invalid count of packets to transmit: `%s'",
exit(1); optarg);
} npackets = ultmp;
break; break;
case 'd': case 'd':
options |= F_SO_DEBUG; options |= F_SO_DEBUG;
break; break;
case 'f': case 'f':
if (getuid()) { if (getuid()) {
(void)fprintf(stderr, errno = EPERM;
"ping: %s\n", strerror(EPERM)); err(EX_NOPERM, "-f flag");
exit(1);
} }
options |= F_FLOOD; options |= F_FLOOD;
setbuf(stdout, (char *)NULL); setbuf(stdout, (char *)NULL);
break; break;
case 'i': /* wait between sending packets */ case 'i': /* wait between sending packets */
interval = atoi(optarg); ultmp = strtoul(optarg, &ep, 0);
if (interval <= 0) { if (*ep || ep == optarg || ultmp > INT_MAX)
(void)fprintf(stderr, errx(EX_USAGE,
"ping: bad timing interval.\n"); "invalid timing interval: `%s'", optarg);
exit(1);
}
options |= F_INTERVAL; options |= F_INTERVAL;
interval = ultmp;
break; break;
case 'I': /* multicast interface */ case 'I': /* multicast interface */
if (inet_aton(optarg, &ifaddr) == 0) { if (inet_aton(optarg, &ifaddr) == 0)
(void)fprintf(stderr, errx(EX_USAGE,
"ping: bad multicast interface.\n"); "invalid multicast interface: `%s'",
exit(1); optarg);
}
options |= F_MIF; options |= F_MIF;
break; break;
case 'l': case 'l':
preload = atoi(optarg); ultmp = strtoul(optarg, &ep, 0);
if (preload < 0) { if (*ep || ep == optarg || ultmp > INT_MAX)
(void)fprintf(stderr, errx(EX_USAGE,
"ping: bad preload value.\n"); "invalid preload value: `%s'", optarg);
exit(1); preload = ultmp;
}
break; break;
case 'L': case 'L':
options |= F_NOLOOP; options |= F_NOLOOP;
@ -260,87 +275,80 @@ main(argc, argv)
options |= F_SO_DONTROUTE; options |= F_SO_DONTROUTE;
break; break;
case 's': /* size of packet to send */ case 's': /* size of packet to send */
datalen = atoi(optarg); ultmp = strtoul(optarg, &ep, 0);
if (datalen > MAXPACKET) { if (ultmp > MAXPACKET)
(void)fprintf(stderr, errx(EX_USAGE, "packet size too large: %lu",
"ping: packet size too large.\n"); ultmp);
exit(1); if (*ep || ep == optarg || !ultmp)
} errx(EX_USAGE, "invalid packet size: `%s'",
if (datalen <= 0) { optarg);
(void)fprintf(stderr, datalen = ultmp;
"ping: illegal packet size.\n");
exit(1);
}
break; break;
case 'T': /* multicast TTL */ case 'T': /* multicast TTL */
i = atoi(optarg); ultmp = strtoul(optarg, &ep, 0);
if (i < 0 || i > 255) { if (*ep || ep == optarg || ultmp > 255)
(void)fprintf(stderr, errx(EX_USAGE, "invalid multicast TTL: `%s'",
"ping: illegal multicast TTL.\n"); optarg);
exit(1); ttl = ultmp;
}
ttl = i;
options |= F_MTTL; options |= F_MTTL;
break; break;
case 'v': case 'v':
options |= F_VERBOSE; options |= F_VERBOSE;
break; break;
default: default:
usage();
}
argc -= optind;
argv += optind;
if (argc != 1) usage(argv[0]);
usage(); }
target = *argv; }
if (argc - optind != 1)
usage(argv[0]);
target = argv[optind];
bzero((char *)&whereto, sizeof(struct sockaddr)); bzero((char *)&whereto, sizeof(struct sockaddr));
to = (struct sockaddr_in *)&whereto; to = (struct sockaddr_in *)&whereto;
to->sin_family = AF_INET; to->sin_family = AF_INET;
to->sin_addr.s_addr = inet_addr(target); if (inet_aton(target, &to->sin_addr) != 0) {
if (to->sin_addr.s_addr != (u_int)-1)
hostname = target; hostname = target;
else { } else {
hp = gethostbyname(target); hp = gethostbyname2(target, AF_INET);
if (!hp) { if (!hp)
(void)fprintf(stderr, errx(EX_NOHOST, "cannot resolve %s: %s",
"ping: unknown host %s\n", target); target, hstrerror(h_errno));
exit(1);
} to->sin_len = sizeof *to;
to->sin_family = hp->h_addrtype; memcpy(&to->sin_addr, hp->h_addr_list[0], sizeof to->sin_addr);
bcopy(hp->h_addr, (caddr_t)&to->sin_addr, hp->h_length);
(void)strncpy(hnamebuf, hp->h_name, sizeof(hnamebuf) - 1); (void)strncpy(hnamebuf, hp->h_name, sizeof(hnamebuf) - 1);
hnamebuf[(sizeof hnamebuf) - 1] = '\0';
hostname = hnamebuf; hostname = hnamebuf;
} }
if (options & F_FLOOD && options & F_INTERVAL) { if (options & F_FLOOD && options & F_INTERVAL)
(void)fprintf(stderr, errx(EX_USAGE, "-f and -i: incompatible options");
"ping: -f and -i incompatible options.\n");
exit(1); if (options & F_FLOOD && IN_MULTICAST(ntohl(to->sin_addr.s_addr)))
} errx(EX_USAGE,
"-f flag cannot be used with multicast destination");
if (options & (F_MIF | F_NOLOOP | F_MTTL)
&& !IN_MULTICAST(ntohl(to->sin_addr.s_addr)))
errx(EX_USAGE,
"-I, -L, -T flags cannot be used with unicast destination");
if (datalen >= sizeof(struct timeval)) /* can we time transfer */ if (datalen >= sizeof(struct timeval)) /* can we time transfer */
timing = 1; timing = 1;
packlen = datalen + MAXIPLEN + MAXICMPLEN; packlen = datalen + MAXIPLEN + MAXICMPLEN;
if (!(packet = (u_char *)malloc((u_int)packlen))) { if (!(packet = (u_char *)malloc((size_t)packlen)))
(void)fprintf(stderr, "ping: out of memory.\n"); err(EX_UNAVAILABLE, "malloc");
exit(1);
}
if (!(options & F_PINGFILLED)) if (!(options & F_PINGFILLED))
for (i = 8; i < datalen; ++i) for (i = 8; i < datalen; ++i)
*datap++ = i; *datap++ = i;
ident = getpid() & 0xFFFF; ident = getpid() & 0xFFFF;
if (!proto) {
(void)fprintf(stderr, "ping: unknown protocol icmp.\n");
exit(1);
}
if (s < 0) { if (s < 0) {
errno = sockerrno; errno = sockerrno;
perror("ping: socket"); err(EX_OSERR, "socket");
exit(1);
} }
hold = 1; hold = 1;
if (options & F_SO_DEBUG) if (options & F_SO_DEBUG)
@ -357,36 +365,30 @@ main(argc, argv)
rspace[IPOPT_OLEN] = sizeof(rspace)-1; rspace[IPOPT_OLEN] = sizeof(rspace)-1;
rspace[IPOPT_OFFSET] = IPOPT_MINOFF; rspace[IPOPT_OFFSET] = IPOPT_MINOFF;
if (setsockopt(s, IPPROTO_IP, IP_OPTIONS, rspace, if (setsockopt(s, IPPROTO_IP, IP_OPTIONS, rspace,
sizeof(rspace)) < 0) { sizeof(rspace)) < 0)
perror("ping: record route"); err(EX_OSERR, "setsockopt IP_OPTIONS");
exit(1);
}
#else #else
(void)fprintf(stderr, errx(EX_UNAVAILABLE,
"ping: record route not available in this implementation.\n"); "record route not available in this implementation");
exit(1);
#endif /* IP_OPTIONS */ #endif /* IP_OPTIONS */
} }
if (options & F_NOLOOP) { if (options & F_NOLOOP) {
if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, &loop,
sizeof(loop)) < 0) { sizeof(loop)) < 0) {
perror("ping: IP_MULTICAST_LOOP"); err(EX_OSERR, "setsockopt IP_MULTICAST_LOOP");
exit(1);
} }
} }
if (options & F_MTTL) { if (options & F_MTTL) {
if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,
sizeof(ttl)) < 0) { sizeof(ttl)) < 0) {
perror("ping: IP_MULTICAST_TTL"); err(EX_OSERR, "setsockopt IP_MULTICAST_TTL");
exit(1);
} }
} }
if (options & F_MIF) { if (options & F_MIF) {
if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &ifaddr, if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &ifaddr,
sizeof(ifaddr)) < 0) { sizeof(ifaddr)) < 0) {
perror("ping: IP_MULTICAST_IF"); err(EX_OSERR, "setsockopt IP_MULTICAST_IF");
exit(1);
} }
} }
@ -394,7 +396,8 @@ main(argc, argv)
* When pinging the broadcast address, you can get a lot of answers. * When pinging the broadcast address, you can get a lot of answers.
* Doing something so evil is useful if you are trying to stress the * Doing something so evil is useful if you are trying to stress the
* ethernet, or just want to fill the arp cache to get some stuff for * ethernet, or just want to fill the arp cache to get some stuff for
* /etc/ethers. * /etc/ethers. But beware: RFC 1122 allows hosts to ignore broadcast
* or multicast pings if they wish.
*/ */
hold = 48 * 1024; hold = 48 * 1024;
(void)setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&hold, (void)setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&hold,
@ -402,7 +405,7 @@ main(argc, argv)
if (to->sin_family == AF_INET) if (to->sin_family == AF_INET)
(void)printf("PING %s (%s): %d data bytes\n", hostname, (void)printf("PING %s (%s): %d data bytes\n", hostname,
inet_ntoa(*(struct in_addr *)&to->sin_addr.s_addr), inet_ntoa(to->sin_addr),
datalen); datalen);
else else
(void)printf("PING %s: %d data bytes\n", hostname, datalen); (void)printf("PING %s: %d data bytes\n", hostname, datalen);
@ -418,8 +421,7 @@ main(argc, argv)
sigemptyset(&si_sa.sa_mask); sigemptyset(&si_sa.sa_mask);
si_sa.sa_flags = 0; si_sa.sa_flags = 0;
if (sigaction(SIGINFO, &si_sa, 0) == -1) { if (sigaction(SIGINFO, &si_sa, 0) == -1) {
perror("sigaction"); err(EX_OSERR, "sigsction");
exit(1);
} }
if (tcgetattr(STDOUT_FILENO, &ts) != -1) { if (tcgetattr(STDOUT_FILENO, &ts) != -1) {
@ -432,7 +434,7 @@ main(argc, argv)
pinger(); pinger();
if ((options & F_FLOOD) == 0) if ((options & F_FLOOD) == 0)
catcher(); /* start things going */ catcher(0); /* start things going */
for (;;) { for (;;) {
struct sockaddr_in from; struct sockaddr_in from;
@ -461,7 +463,7 @@ main(argc, argv)
if (npackets && nreceived >= npackets) if (npackets && nreceived >= npackets)
break; break;
} }
finish(); finish(0);
/* NOTREACHED */ /* NOTREACHED */
} }
@ -475,8 +477,8 @@ main(argc, argv)
* launched exactly at 1-second intervals). This does not affect the * launched exactly at 1-second intervals). This does not affect the
* quality of the delay and loss statistics. * quality of the delay and loss statistics.
*/ */
void static void
catcher() catcher(int sig)
{ {
int waittime; int waittime;
@ -504,7 +506,8 @@ catcher()
* of the data portion are used to hold a UNIX "timeval" struct in host * of the data portion are used to hold a UNIX "timeval" struct in host
* byte-order, to compute the round-trip time. * byte-order, to compute the round-trip time.
*/ */
pinger() static void
pinger(void)
{ {
register struct icmp *icp; register struct icmp *icp;
register int cc; register int cc;
@ -532,10 +535,12 @@ pinger()
sizeof(struct sockaddr)); sizeof(struct sockaddr));
if (i < 0 || i != cc) { if (i < 0 || i != cc) {
if (i < 0) if (i < 0) {
perror("ping: sendto"); warn("sendto");
(void)printf("ping: wrote %s %d chars, ret=%d\n", } else {
hostname, cc, i); warn("%s: partial write: %d of %d bytes",
hostname, cc, i);
}
} }
if (!(options & F_QUIET) && options & F_FLOOD) if (!(options & F_QUIET) && options & F_FLOOD)
(void)write(STDOUT_FILENO, &DOT, 1); (void)write(STDOUT_FILENO, &DOT, 1);
@ -548,6 +553,7 @@ pinger()
* which arrive ('tis only fair). This permits multiple copies of this * which arrive ('tis only fair). This permits multiple copies of this
* program to be run without having intermingled output (or statistics!). * program to be run without having intermingled output (or statistics!).
*/ */
static void
pr_pack(buf, cc, from) pr_pack(buf, cc, from)
char *buf; char *buf;
int cc; int cc;
@ -571,9 +577,8 @@ pr_pack(buf, cc, from)
hlen = ip->ip_hl << 2; hlen = ip->ip_hl << 2;
if (cc < hlen + ICMP_MINLEN) { if (cc < hlen + ICMP_MINLEN) {
if (options & F_VERBOSE) if (options & F_VERBOSE)
(void)fprintf(stderr, warn("packet too short (%d bytes) from %s", cc,
"ping: packet too short (%d bytes) from %s\n", cc, inet_ntoa(from->sin_addr));
inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr));
return; return;
} }
@ -664,7 +669,7 @@ pr_pack(buf, cc, from)
(oicmp->icmp_type == ICMP_ECHO) && (oicmp->icmp_type == ICMP_ECHO) &&
(oicmp->icmp_id == ident))) { (oicmp->icmp_id == ident))) {
(void)printf("%d bytes from %s: ", cc, (void)printf("%d bytes from %s: ", cc,
pr_addr(from->sin_addr.s_addr)); pr_addr(from->sin_addr));
pr_icmph(icp); pr_icmph(icp);
} else } else
return; return;
@ -689,10 +694,13 @@ pr_pack(buf, cc, from)
l = (l<<8) + *++cp; l = (l<<8) + *++cp;
l = (l<<8) + *++cp; l = (l<<8) + *++cp;
l = (l<<8) + *++cp; l = (l<<8) + *++cp;
if (l == 0) if (l == 0) {
(void)printf("\t0.0.0.0"); printf("\t0.0.0.0");
else } else {
(void)printf("\t%s", pr_addr(ntohl(l))); struct in_addr ina;
ina.s_addr = ntohl(l);
printf("\t%s", pr_addr(ina));
}
hlen -= 4; hlen -= 4;
j -= 4; j -= 4;
if (j <= IPOPT_MINOFF) if (j <= IPOPT_MINOFF)
@ -727,10 +735,13 @@ pr_pack(buf, cc, from)
l = (l<<8) + *++cp; l = (l<<8) + *++cp;
l = (l<<8) + *++cp; l = (l<<8) + *++cp;
l = (l<<8) + *++cp; l = (l<<8) + *++cp;
if (l == 0) if (l == 0) {
(void)printf("\t0.0.0.0"); printf("\t0.0.0.0");
else } else {
(void)printf("\t%s", pr_addr(ntohl(l))); struct in_addr ina;
ina.s_addr = ntohl(l);
printf("\t%s", pr_addr(ina));
}
hlen -= 4; hlen -= 4;
i -= 4; i -= 4;
if (i <= 0) if (i <= 0)
@ -755,6 +766,7 @@ pr_pack(buf, cc, from)
* in_cksum -- * in_cksum --
* Checksum routine for Internet Protocol family headers (C Version) * Checksum routine for Internet Protocol family headers (C Version)
*/ */
u_short
in_cksum(addr, len) in_cksum(addr, len)
u_short *addr; u_short *addr;
int len; int len;
@ -792,6 +804,7 @@ in_cksum(addr, len)
* Subtract 2 timeval structs: out = out - in. Out is assumed to * Subtract 2 timeval structs: out = out - in. Out is assumed to
* be >= in. * be >= in.
*/ */
static void
tvsub(out, in) tvsub(out, in)
register struct timeval *out, *in; register struct timeval *out, *in;
{ {
@ -807,14 +820,14 @@ tvsub(out, in)
* Print out statistics when SIGINFO is received. * Print out statistics when SIGINFO is received.
*/ */
void static void
status(sig) status(sig)
int sig; int sig;
{ {
siginfo_p = 1; siginfo_p = 1;
} }
void static void
check_status() check_status()
{ {
if (siginfo_p) { if (siginfo_p) {
@ -833,8 +846,8 @@ check_status()
* finish -- * finish --
* Print out statistics, and give up. * Print out statistics, and give up.
*/ */
void static void
finish() finish(int sig)
{ {
struct termios ts; struct termios ts;
@ -888,6 +901,7 @@ static char *ttab[] = {
* pr_icmph -- * pr_icmph --
* Print a descriptive string about an ICMP header. * Print a descriptive string about an ICMP header.
*/ */
static void
pr_icmph(icp) pr_icmph(icp)
struct icmp *icp; struct icmp *icp;
{ {
@ -1034,6 +1048,7 @@ pr_icmph(icp)
* pr_iph -- * pr_iph --
* Print an IP header with options. * Print an IP header with options.
*/ */
static void
pr_iph(ip) pr_iph(ip)
struct ip *ip; struct ip *ip;
{ {
@ -1047,7 +1062,7 @@ pr_iph(ip)
(void)printf(" %1x %1x %02x %04x %04x", (void)printf(" %1x %1x %02x %04x %04x",
ip->ip_v, ip->ip_hl, ip->ip_tos, ntohs(ip->ip_len), ip->ip_v, ip->ip_hl, ip->ip_tos, ntohs(ip->ip_len),
ntohs(ip->ip_id)); ntohs(ip->ip_id));
(void)printf(" %1x %04x", (ntohl(ip->ip_off) & 0xe000) >> 13, (void)printf(" %1lx %04lx", (ntohl(ip->ip_off) & 0xe000) >> 13,
ntohl(ip->ip_off) & 0x1fff); ntohl(ip->ip_off) & 0x1fff);
(void)printf(" %02x %02x %04x", ip->ip_ttl, ip->ip_p, (void)printf(" %02x %02x %04x", ip->ip_ttl, ip->ip_p,
ntohs(ip->ip_sum)); ntohs(ip->ip_sum));
@ -1065,20 +1080,19 @@ pr_iph(ip)
* Return an ascii host address as a dotted quad and optionally with * Return an ascii host address as a dotted quad and optionally with
* a hostname. * a hostname.
*/ */
char * static char *
pr_addr(l) pr_addr(ina)
u_long l; struct in_addr ina;
{ {
struct hostent *hp; struct hostent *hp;
static char buf[80]; static char buf[80];
if ((options & F_NUMERIC) || if ((options & F_NUMERIC) ||
!(hp = gethostbyaddr((char *)&l, 4, AF_INET))) !(hp = gethostbyaddr((char *)&ina, 4, AF_INET)))
(void)snprintf(buf, sizeof(buf), "%s", return inet_ntoa(ina);
inet_ntoa(*(struct in_addr *)&l));
else else
(void)snprintf(buf, sizeof(buf), "%s (%s)", hp->h_name, (void)snprintf(buf, sizeof(buf), "%s (%s)", hp->h_name,
inet_ntoa(*(struct in_addr *)&l)); inet_ntoa(ina));
return(buf); return(buf);
} }
@ -1086,6 +1100,7 @@ pr_addr(l)
* pr_retip -- * pr_retip --
* Dump some info on a returned (via ICMP) IP packet. * Dump some info on a returned (via ICMP) IP packet.
*/ */
static void
pr_retip(ip) pr_retip(ip)
struct ip *ip; struct ip *ip;
{ {
@ -1104,6 +1119,7 @@ pr_retip(ip)
(*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3))); (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3)));
} }
static void
fill(bp, patp) fill(bp, patp)
char *bp, *patp; char *bp, *patp;
{ {
@ -1111,12 +1127,12 @@ fill(bp, patp)
int pat[16]; int pat[16];
char *cp; char *cp;
for (cp = patp; *cp; cp++) for (cp = patp; *cp; cp++) {
if (!isxdigit(*cp)) { if (!isxdigit(*cp))
(void)fprintf(stderr, errx(EX_USAGE,
"ping: patterns must be specified as hex digits.\n"); "patterns must be specified as hex digits");
exit(1);
} }
ii = sscanf(patp, ii = sscanf(patp,
"%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x", "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
&pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6], &pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6],
@ -1137,9 +1153,15 @@ fill(bp, patp)
} }
} }
usage() static void
usage(argv0)
const char *argv0;
{ {
(void)fprintf(stderr, warnx("usage:");
"usage: ping [-LQRadfnqrv] [-c count] [-i wait] [-I interface]\n\t[-l preload] [-p pattern] [-s packetsize] [-T ttl] host\n"); fprintf(stderr,
exit(1); "\t%s [-QRadfnqrv] [-c count] [-i wait] [-l preload] "
"[-p pattern]\n\t\t[-s packetsize] "
"[host | [-L] [-I iface] [-T ttl] mcast-group]\n",
argv0);
exit(EX_USAGE);
} }