Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 15 Oct 2002 16:41:04 +0400 (MSD)
From:      Maxim Konovalov <maxim@macomnet.ru>
To:        net@freebsd.org
Subject:   RFR: ping(8) patches: do not fragment, TOS, maximum payload
Message-ID:  <20021015162242.J54875-100000@news1.macomnet.ru>

next in thread | raw e-mail | index | archive | help

Hello,

I have made a patch set for ping(8). I'll appreciate your comments.

I did not include patches #3 and #4, they are stylistic mostly (based
on BDE's style patch).

A cumulative patch is there:

http://people.freebsd.org/~maxim/p.cumulative

#1, Print strict source routing option. Requested by David Wang
<dsw@juniper.net>.

Index: ping.c
===================================================================
RCS file: /home/maxim/cvs/ping/ping.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ping.c	15 Oct 2002 11:56:58 -0000	1.1
+++ ping.c	15 Oct 2002 11:57:53 -0000	1.2
@@ -953,7 +953,9 @@
 			hlen = 0;
 			break;
 		case IPOPT_LSRR:
-			(void)printf("\nLSRR: ");
+		case IPOPT_SSRR:
+			(void)printf(*cp == IPOPT_LSRR ?
+			    "\nLSRR: " : "\nSSRR: ");
 			j = cp[IPOPT_OLEN] - IPOPT_MINOFF + 1;
 			hlen -= 2;
 			cp += 2;

%%%

#2, Implement -D (do not fragment) and -z (TOS) options. Obtained from
OpenBSD, bin/35843.

Index: ping.c
===================================================================
RCS file: /home/maxim/cvs/ping/ping.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- ping.c	15 Oct 2002 11:57:53 -0000	1.2
+++ ping.c	15 Oct 2002 12:04:10 -0000	1.3
@@ -67,6 +67,7 @@
  */

 #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 @@
 #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 @@
 #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 @@
 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 @@
 {
 	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 @@
 	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 @@
 	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 @@
 				    optarg);
 			npackets = ultmp;
 			break;
+		case 'D':
+			options |= F_HDRINCL;
+			df = 1;
+			break;
 		case 'd':
 			options |= F_SO_DEBUG;
 			break;
@@ -390,6 +401,13 @@
 			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 @@
 #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 @@
 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 @@
 	/* 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)  {
@@ -1448,7 +1498,7 @@
 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
@@ -1456,6 +1506,6 @@
 #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);
 }
Index: ping.8
===================================================================
RCS file: /home/maxim/cvs/ping/ping.8,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ping.8	15 Oct 2002 11:56:58 -0000	1.1
+++ ping.8	15 Oct 2002 12:04:10 -0000	1.2
@@ -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 @@
 .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 @@
 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 @@
 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

%%%

#5 Do not constantify maximum payload size. It is 65467 with -R
(record route), and 65507 without it.

Index: ping.c
===================================================================
RCS file: /home/maxim/cvs/ping/ping.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- ping.c	15 Oct 2002 12:04:40 -0000	1.5
+++ ping.c	15 Oct 2002 12:04:59 -0000	1.6
@@ -104,7 +104,6 @@
 #define	MAXIPLEN	(sizeof(struct ip) + MAX_IPOPTLEN)
 #define	MAXICMPLEN	(ICMP_ADVLENMIN + MAX_IPOPTLEN)
 #define	MINICMPLEN	ICMP_MINLEN
-#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
@@ -151,6 +150,7 @@
 char rcvd_tbl[MAX_DUP_CHK / 8];

 struct sockaddr_in whereto;	/* who to ping */
+long maxpayload;
 int datalen = DEFDATALEN;
 int s;				/* socket file descriptor */
 u_char outpackhdr[IP_MAXPACKET], *outpack;
@@ -351,18 +351,16 @@
 			options |= F_SO_DONTROUTE;
 			break;
 		case 's':		/* size of packet to send */
-			if (uid) {
-				errno = EPERM;
-				err(EX_NOPERM, "-s flag");
-			}
 			ultmp = strtoul(optarg, &ep, 0);
-			if (ultmp > MAXPAYLOAD)
-				errx(EX_USAGE,
-				    "packet size too large: %lu > %u",
-				    ultmp, MAXPAYLOAD);
 			if (*ep || ep == optarg)
 				errx(EX_USAGE, "invalid packet size: `%s'",
 				    optarg);
+			if (uid != 0 && ultmp > DEFDATALEN) {
+				errno = EPERM;
+				err(EX_NOPERM,
+				    "packet size too large: %lu > %u",
+				    ultmp, DEFDATALEN);
+			}
 			datalen = ultmp;
 			break;
 		case 'S':
@@ -418,6 +416,12 @@
 		usage();
 	target = argv[optind];

+	maxpayload = IP_MAXPACKET - sizeof(struct ip) - MINICMPLEN;
+	if (options & F_RROUTE)
+		maxpayload -= MAX_IPOPTLEN;
+	if (datalen > maxpayload)
+		errx(EX_USAGE, "packet size too large: %lu > %u", datalen,
+		    maxpayload);
 	if (source) {
 		bzero((char *)&sin, sizeof(sin));
 		sin.sin_family = AF_INET;
@@ -1476,7 +1480,7 @@
 	    &pat[13], &pat[14], &pat[15]);

 	if (ii > 0)
-		for (kk = 0; kk <= MAXPAYLOAD - (PHDR_LEN + ii); kk += ii)
+		for (kk = 0; kk <= maxpayload - (PHDR_LEN + ii); kk += ii)
 			for (jj = 0; jj < ii; ++jj)
 				bp[jj + kk] = pat[jj];
 	if (!(options & F_QUIET)) {
Index: ping.8
===================================================================
RCS file: /home/maxim/cvs/ping/ping.8,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- ping.8	15 Oct 2002 12:04:10 -0000	1.2
+++ ping.8	15 Oct 2002 12:04:59 -0000	1.3
@@ -235,7 +235,7 @@
 with the 8 bytes of
 .Tn ICMP
 header data.
-Only the super-user may use this option.
+Only the super-user may specify values more then default.
 .It Fl S Ar src_addr
 Use the following IP address as the source address in outgoing packets.
 On hosts with more than one IP address, this option can be used to

%%%

Thank you very much.

-- 
Maxim Konovalov, MAcomnet, Internet Dept., system engineer
phone: +7 (095) 796-9079, mailto:maxim@macomnet.ru


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-net" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20021015162242.J54875-100000>