summaryrefslogtreecommitdiff
path: root/sbin/ping
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1996-06-19 11:18:59 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1996-06-19 11:18:59 +0000
commit93bf84b9943da76a70e9a1d3ff612fb11c739869 (patch)
treef05b7c306697e2c1904388b4b6c36959b92ba912 /sbin/ping
parenta6b7a98425f17460635347cb76351f42ae626ed5 (diff)
let user set TOS, DF bit, and TTL. also use strtol() instead of atoi() so
that other bases work; netbsd pr#2017; jhawk@mit.edu
Diffstat (limited to 'sbin/ping')
-rw-r--r--sbin/ping/ping.830
-rw-r--r--sbin/ping/ping.c123
2 files changed, 110 insertions, 43 deletions
diff --git a/sbin/ping/ping.8 b/sbin/ping/ping.8
index cd6cad0b7cc..07a5ebfef8f 100644
--- a/sbin/ping/ping.8
+++ b/sbin/ping/ping.8
@@ -78,6 +78,10 @@ Stop after sending (and receiving)
.Ar count
.Tn ECHO_RESPONSE
packets.
+.It Fl D
+Set the
+.Dv Don't Fragment
+bit.
.It Fl d
Set the
.Dv SO_DEBUG
@@ -96,6 +100,9 @@ Only the super-user may use this option.
.Bf -emphasis
This can be very hard on a network and should be used with caution.
.Ef
+.It Fl I Ar ifaddr
+Specify the interface to transmit from on machines with multiple
+interfaces. For unicast and multicast pings.
.It Fl i Ar wait
Wait
.Ar wait
@@ -143,9 +150,6 @@ If the host is not on a directly-attached network, an error is returned.
This option can be used to ping a local host through an interface
that has no route through it (e.g., after the interface was dropped by
.Xr routed 8 ) .
-.It Fl S Ar ifaddr
-Specify the interface to transmit from on machines with multiple
-interfaces. For unicast pings.
.It Fl s Ar packetsize
Specifies the number of data bytes to be sent.
The default is 56, which translates into 64
@@ -153,7 +157,19 @@ The default is 56, which translates into 64
data bytes when combined
with the 8 bytes of
.Tn ICMP
-header data.
+header data. If the
+.Fl D
+or
+.Fl T
+options are specified, or the
+.Fl t
+option to a unicast destination, a raw socket will be used and the 8 bytes of
+header data are included in
+.Ar packetsize .
+.It Fl T Ar tos
+Use the specified type of service.
+.It Fl t Ar ttl
+Use the specified time-to-live.
.It Fl v
Verbose output.
.Tn ICMP
@@ -165,15 +181,11 @@ Specifies the number of seconds to wait for a response to a packet
before transmitting the next one. The default is 10.
.El
.Pp
-In addition, the following options may be used for multicast pings:
+In addition, the following option may be used for multicast pings:
.Bl -tag -width Ds
-.It Fl I Ar ifaddr
-Transmit using the specified interface address.
.It Fl L
Disable the loopback, so the transmitting host doesn't see the ICMP
requests.
-.It Fl t Ar ttl
-Use the specified time-to-live.
.El
.Pp
When using
diff --git a/sbin/ping/ping.c b/sbin/ping/ping.c
index 153a39b92c2..3bc8a50fb66 100644
--- a/sbin/ping/ping.c
+++ b/sbin/ping/ping.c
@@ -115,6 +115,8 @@ int options;
#define F_SO_DONTROUTE 0x080
#define F_VERBOSE 0x100
#define F_SADDR 0x200
+#define F_HDRINCL 0x400
+#define F_TTL 0x800
/* multicast options */
int moptions;
@@ -135,7 +137,8 @@ struct sockaddr whereto; /* who to ping */
struct sockaddr_in whence; /* Which interface we come from */
int datalen = DEFDATALEN;
int s; /* socket file descriptor */
-u_char outpack[MAXPACKET];
+u_char outpackhdr[MAXPACKET];
+u_char *outpack = outpackhdr+sizeof(struct ip);
char BSPACE = '\b'; /* characters written for flood */
char DOT = '.';
char *hostname;
@@ -176,26 +179,31 @@ main(argc, argv)
struct hostent *hp;
struct sockaddr_in *to;
struct protoent *proto;
- struct in_addr ifaddr, saddr;
+ struct in_addr saddr;
register int i;
int ch, fdmask, hold, packlen, preload;
u_char *datap, *packet;
char *target, hnamebuf[MAXHOSTNAMELEN];
- u_char ttl, loop = 1;
+ u_char ttl = MAXTTL, loop = 1, df = 0;
+ int tos = 0;
#ifdef IP_OPTIONS
char rspace[3 + 4 * NROUTES + 1]; /* record route space */
#endif
preload = 0;
datap = &outpack[8 + sizeof(struct timeval)];
- while ((ch = getopt(argc, argv, "I:LRS:c:dfh:i:l:np:qrs:t:vw:")) != EOF)
+ while ((ch = getopt(argc, argv, "DI:LRS:c:dfh:i:l:np:qrs:T:t:vw:")) != EOF)
switch(ch) {
case 'c':
- npackets = atoi(optarg);
+ npackets = strtol(optarg, 0, NULL);
if (npackets <= 0)
errx(1, "bad number of packets to transmit: %s",
optarg);
break;
+ case 'D':
+ options |= F_HDRINCL;
+ df = -1;
+ break;
case 'd':
options |= F_SO_DEBUG;
break;
@@ -206,12 +214,17 @@ main(argc, argv)
setbuf(stdout, (char *)NULL);
break;
case 'I':
- if (inet_aton(optarg, &ifaddr) == 0)
- errx(1, "bad interface address: %s", optarg);
- moptions |= MULTICAST_IF;
+ case 'S': /* deprecated */
+ if (inet_aton(optarg, &saddr) == 0) {
+ if ((hp = gethostbyname(optarg)) == NULL)
+ errx(1, "bad interface address: %s",
+ optarg);
+ memcpy(&saddr, hp->h_addr, sizeof(saddr));
+ }
+ options |= F_SADDR;
break;
case 'i': /* wait between sending packets */
- interval = atoi(optarg);
+ interval = strtol(optarg, NULL, 0);
if (interval <= 0)
errx(1, "bad timing interval: %s", optarg);
options |= F_INTERVAL;
@@ -221,7 +234,7 @@ main(argc, argv)
loop = 0;
break;
case 'l':
- preload = atoi(optarg);
+ preload = strtol(optarg, NULL, 0);
if (preload < 0)
errx(1, "bad preload value: %s", optarg);
break;
@@ -241,35 +254,32 @@ main(argc, argv)
case 'r':
options |= F_SO_DONTROUTE;
break;
- case 'S':
- if (inet_aton(optarg, &saddr) == 0) {
- if ((hp = gethostbyname(optarg)) == NULL)
- errx(1, "bad interface address: %s",
- optarg);
- memcpy(&saddr, hp->h_addr, sizeof(saddr));
- }
- options |= F_SADDR;
- break;
case 's': /* size of packet to send */
- datalen = atoi(optarg);
+ datalen = strtol(optarg, NULL, 0);
if (datalen <= 0)
errx(1, "bad packet size: %s", optarg);
if (datalen > MAXPACKET)
errx(1, "packet size too large: %s", optarg);
break;
+ case 'T':
+ options |= F_HDRINCL;
+ tos = strtoul(optarg, NULL, 0);
+ if (tos > 0xFF)
+ errx(1, "bad tos value: %s", optarg);
+ break;
case 't':
- ttl = atoi(optarg);
+ options |= F_TTL;
+ ttl = strtol(optarg, NULL, 0);
if (ttl <= 0)
errx(1, "bad ttl value: %s", optarg);
if (ttl > 255)
errx(1, "ttl value too large: %s", optarg);
- moptions |= MULTICAST_TTL;
break;
case 'v':
options |= F_VERBOSE;
break;
case 'w':
- maxwait = atoi(optarg);
+ maxwait = strtol(optarg, NULL, 0);
if (maxwait <= 0)
errx(1, "bad maxwait value: %s", optarg);
break;
@@ -320,12 +330,17 @@ main(argc, argv)
hold = 1;
if (options & F_SADDR) {
- memset(&whence, 0, sizeof(whence));
- whence.sin_len = sizeof(whence);
- whence.sin_family = AF_INET;
- memcpy(&whence.sin_addr.s_addr, &saddr, sizeof(saddr));
- if (bind(s, (struct sockaddr*)&whence, sizeof(whence)) < 0)
- err(1, "bind");
+ if (IN_MULTICAST(ntohl(to->sin_addr.s_addr)))
+ moptions |= MULTICAST_IF;
+ else {
+ memset(&whence, 0, sizeof(whence));
+ whence.sin_len = sizeof(whence);
+ whence.sin_family = AF_INET;
+ memcpy(&whence.sin_addr.s_addr, &saddr, sizeof(saddr));
+ if (bind(s, (struct sockaddr*)&whence,
+ sizeof(whence)) < 0)
+ err(1, "bind");
+ }
}
if (options & F_SO_DEBUG)
@@ -335,8 +350,36 @@ main(argc, argv)
(void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&hold,
sizeof(hold));
+ if (options & F_TTL) {
+ if (IN_MULTICAST(ntohl(to->sin_addr.s_addr)))
+ moptions |= MULTICAST_TTL;
+ else
+ options |= F_HDRINCL;
+ }
+
+ if (options & F_RROUTE && options & F_HDRINCL)
+ errx(1, "-R option and -D or -T, or -t to unicast destinations"
+ " are incompatible");
+
+ if (options & F_HDRINCL) {
+ struct ip *ip = (struct ip*)outpackhdr;
+
+ setsockopt(s, IPPROTO_IP, IP_HDRINCL, &hold, sizeof(hold));
+ ip->ip_v = IPVERSION;
+ ip->ip_hl = sizeof(struct ip) >> 2;
+ ip->ip_tos = tos;
+ ip->ip_id = 0;
+ ip->ip_off = (df?IP_DF:0);
+ ip->ip_ttl = ttl;
+ ip->ip_p = proto->p_proto;
+ ip->ip_src.s_addr = INADDR_ANY;
+ ip->ip_dst = to->sin_addr;
+ }
+
/* record route option */
if (options & F_RROUTE) {
+ if (IN_MULTICAST(ntohl(to->sin_addr.s_addr)))
+ errx(1, "record route not valid to multicast destinations");
#ifdef IP_OPTIONS
rspace[IPOPT_OPTVAL] = IPOPT_RR;
rspace[IPOPT_OLEN] = sizeof(rspace)-1;
@@ -360,8 +403,8 @@ main(argc, argv)
sizeof(ttl)) < 0)
err(1, "setsockopt IP_MULTICAST_TTL");
if ((moptions & MULTICAST_IF) &&
- setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &ifaddr,
- sizeof(ifaddr)) < 0)
+ setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &saddr,
+ sizeof(saddr)) < 0)
err(1, "setsockopt IP_MULTICAST_IF");
/*
@@ -466,6 +509,7 @@ pinger()
register struct icmp *icp;
register int cc;
int i;
+ char *packet = outpack;
icp = (struct icmp *)outpack;
icp->icmp_type = ICMP_ECHO;
@@ -485,8 +529,17 @@ pinger()
/* compute ICMP checksum here */
icp->icmp_cksum = in_cksum((u_short *)icp, cc);
- i = sendto(s, (char *)outpack, cc, 0, &whereto,
- sizeof(struct sockaddr));
+ if (options & F_HDRINCL) {
+ struct ip *ip = (struct ip*)outpackhdr;
+
+ packet = (char*)ip;
+ cc += sizeof(struct ip);
+ ip->ip_len = cc;
+ ip->ip_sum = in_cksum((u_short *)outpackhdr, cc);
+ }
+
+ i = sendto(s, (char *)packet, cc, 0, &whereto,
+ sizeof(struct sockaddr));
if (i < 0 || i != cc) {
if (i < 0)
@@ -1027,6 +1080,8 @@ void
usage()
{
(void)fprintf(stderr,
- "usage: ping [-dfLnqRrv] [-c count] [-I ifaddr] [ -S ifaddr ] [-i wait]\n\t[-l preload] [-p pattern] [-s packetsize] [-t ttl] [-w maxwait] host\n");
+ "usage: ping [-DdfLnqRrv] [-c count] [-I ifaddr] [-i wait]\n"
+ "\t[-l preload] [-p pattern] [-s packetsize] [-t ttl]"
+ " [-w maxwait] host\n");
exit(1);
}