summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sbin/ping/ping.87
-rw-r--r--sbin/ping/ping.c64
2 files changed, 63 insertions, 8 deletions
diff --git a/sbin/ping/ping.8 b/sbin/ping/ping.8
index c371907..105e5f1 100644
--- a/sbin/ping/ping.8
+++ b/sbin/ping/ping.8
@@ -42,7 +42,7 @@
packets to network hosts
.Sh SYNOPSIS
.Nm
-.Op Fl AQRadfnoqrv
+.Op Fl ADQRadfnoqrv
.Op Fl c Ar count
.Op Fl i Ar wait
.Op Fl l Ar preload
@@ -52,6 +52,7 @@ packets to network hosts
.Op Fl s Ar packetsize
.Op Fl S Ar src_addr
.Op Fl t Ar timeout
+.Op Fl z Ar tos
.Bo
.Ar host |
.Op Fl L
@@ -111,6 +112,8 @@ will operate until interrupted.
Set the
.Dv SO_DEBUG
option on the socket being used.
+.It Fl D
+Set the Don't Fragment bit.
.It Fl f
Flood ping.
Outputs packets as fast as they come back or one hundred times per second,
@@ -252,6 +255,8 @@ Verbose output.
packets other than
.Tn ECHO_RESPONSE
that are received are listed.
+.It Fl z Ar tos
+Use the specified type of service.
.El
.Pp
When using
diff --git a/sbin/ping/ping.c b/sbin/ping/ping.c
index f38c3b7..90c0b8a 100644
--- a/sbin/ping/ping.c
+++ b/sbin/ping/ping.c
@@ -67,6 +67,7 @@ static const char rcsid[] =
*/
#include <sys/param.h> /* NB: we rely on this for <sys/types.h> */
+#include <sys/sysctl.h>
#include <ctype.h>
#include <err.h>
@@ -107,6 +108,7 @@ static const char rcsid[] =
#define MAXPAYLOAD (IP_MAXPACKET - MAXIPLEN - MINICMPLEN)
#define MAXWAIT 10 /* max seconds to wait for response */
#define MAXALARM (60 * 60) /* max seconds for alarm timeout */
+#define MAXTOS 255
#define A(bit) rcvd_tbl[(bit)>>3] /* identify byte in array */
#define B(bit) (1 << ((bit) & 0x07)) /* identify bit in byte */
@@ -138,6 +140,7 @@ int options;
#define F_TTL 0x8000
#define F_MISSED 0x10000
#define F_ONCE 0x20000
+#define F_HDRINCL 0x40000
/*
* MAX_DUP_CHK is the number of bits in received table, i.e. the maximum
@@ -151,7 +154,7 @@ char rcvd_tbl[MAX_DUP_CHK / 8];
struct sockaddr_in whereto; /* who to ping */
int datalen = DEFDATALEN;
int s; /* socket file descriptor */
-u_char outpack[MINICMPLEN + MAXPAYLOAD];
+u_char outpackhdr[IP_MAXPACKET], *outpack;
char BSPACE = '\b'; /* characters written for flood */
char BBELL = '\a'; /* characters written for MISSED and AUDIBLE */
char DOT = '.';
@@ -201,6 +204,7 @@ main(argc, argv)
{
struct in_addr ifaddr;
struct iovec iov;
+ struct ip *ip;
struct msghdr msg;
struct sigaction si_sa;
struct sockaddr_in from, sin;
@@ -209,13 +213,15 @@ main(argc, argv)
struct hostent *hp;
struct sockaddr_in *to;
double t;
+ size_t sz;
u_char *datap, packet[IP_MAXPACKET];
char *ep, *source, *target;
#ifdef IPSEC_POLICY_IPSEC
char *policy_in, *policy_out;
#endif
u_long alarmtimeout, ultmp;
- int ch, hold, i, packlen, preload, sockerrno, almost_done = 0, ttl;
+ int ch, df, hold, i, mib[4], packlen, preload, sockerrno,
+ almost_done = 0, tos, ttl;
char ctrl[CMSG_SPACE(sizeof(struct timeval))];
char hnamebuf[MAXHOSTNAMELEN], snamebuf[MAXHOSTNAMELEN];
#ifdef IP_OPTIONS
@@ -239,11 +245,12 @@ main(argc, argv)
setuid(getuid());
uid = getuid();
- alarmtimeout = preload = 0;
+ alarmtimeout = df = preload = tos = 0;
+ outpack = outpackhdr + sizeof(struct ip);
datap = &outpack[MINICMPLEN + PHDR_LEN];
while ((ch = getopt(argc, argv,
- "AI:LQRS:T:c:adfi:l:m:nop:qrs:t:v"
+ "ADI:LQRS:T:c:adfi:l:m:nop:qrs:t:vz:"
#ifdef IPSEC
#ifdef IPSEC_POLICY_IPSEC
"P:"
@@ -266,6 +273,10 @@ main(argc, argv)
optarg);
npackets = ultmp;
break;
+ case 'D':
+ options |= F_HDRINCL;
+ df = 1;
+ break;
case 'd':
options |= F_SO_DEBUG;
break;
@@ -390,6 +401,13 @@ main(argc, argv)
else
errx(1, "invalid security policy");
break;
+ case 'z':
+ options |= F_HDRINCL;
+ ultmp = strtoul(optarg, &ep, 0);
+ if (*ep || ep == optarg || ultmp > MAXTOS)
+ errx(EX_USAGE, "invalid TOS: `%s'", optarg);
+ tos = ultmp;
+ break;
#endif /*IPSEC_POLICY_IPSEC*/
#endif /*IPSEC*/
default:
@@ -509,6 +527,28 @@ main(argc, argv)
#endif /*IPSEC_POLICY_IPSEC*/
#endif /*IPSEC*/
+ if (options & F_HDRINCL) {
+ ip = (struct ip*)outpackhdr;
+ if (!(options & (F_TTL | F_MTTL))) {
+ mib[0] = CTL_NET;
+ mib[1] = PF_INET;
+ mib[2] = IPPROTO_IP;
+ mib[3] = IPCTL_DEFTTL;
+ sz = sizeof(ttl);
+ if (sysctl(mib, 4, &ttl, &sz, NULL, 0) == -1)
+ err(1, "sysctl(net.inet.ip.ttl)");
+ }
+ 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 = IPPROTO_ICMP;
+ ip->ip_src.s_addr = source ? sin.sin_addr.s_addr : INADDR_ANY;
+ ip->ip_dst = to->sin_addr;
+ }
/* record route option */
if (options & F_RROUTE) {
#ifdef IP_OPTIONS
@@ -758,9 +798,12 @@ stopit(sig)
static void
pinger(void)
{
+ struct ip *ip;
struct icmp *icp;
int cc, i;
+ u_char *packet;
+ packet = outpack;
icp = (struct icmp *)outpack;
icp->icmp_type = ICMP_ECHO;
icp->icmp_code = 0;
@@ -779,7 +822,14 @@ pinger(void)
/* compute ICMP checksum here */
icp->icmp_cksum = in_cksum((u_short *)icp, cc);
- i = sendto(s, (char *)outpack, cc, 0, (struct sockaddr *)&whereto,
+ if (options & F_HDRINCL) {
+ cc += sizeof(struct ip);
+ ip = (struct ip *)outpackhdr;
+ ip->ip_len = cc;
+ ip->ip_sum = in_cksum((u_short *)outpackhdr, cc);
+ packet = outpackhdr;
+ }
+ i = sendto(s, (char *)packet, cc, 0, (struct sockaddr *)&whereto,
sizeof(whereto));
if (i < 0 || i != cc) {
@@ -1449,7 +1499,7 @@ static void
usage()
{
(void)fprintf(stderr, "%s\n%s\n%s\n",
-"usage: ping [-AQRadfnoqrv] [-c count] [-i wait] [-l preload] [-m ttl]",
+"usage: ping [-ADQRadfnoqrv] [-c count] [-i wait] [-l preload] [-m ttl]",
" [-p pattern] "
#ifdef IPSEC
#ifdef IPSEC_POLICY_IPSEC
@@ -1457,6 +1507,6 @@ usage()
#endif
#endif
"[-s packetsize] [-S src_addr] [-t timeout]",
-" [host | [-L] [-I iface] [-T ttl] mcast-group]");
+" [-z tos ] [host | [-L] [-I iface] [-T ttl] mcast-group]");
exit(EX_USAGE);
}
OpenPOWER on IntegriCloud