Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 23 Jul 2001 16:56:53 +0400 (MSD)
From:      maxim@macomnet.ru
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   bin/29164: [PATCH] lack of 'Do not fragment' flag in ping(8) 
Message-ID:  <200107231256.f6NCurr04141@news1.macomnet.ru>

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

>Number:         29164
>Category:       bin
>Synopsis:       [PATCH] lack of 'Do not fragment' flag in ping(8)
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Mon Jul 23 06:00:01 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator:     Maxim Konovalov
>Release:        FreeBSD 5.0-CURRENT i386
>Organization:
>Environment:

	FreeBSD 5.0-CURRENT

>Description:

	There is no 'Do not fragment' flag in ping(8) which is
	useful with PMTU discovery problems.

>How-To-Repeat:

	N/A

>Fix:

Stolen from OpenBSD.

Index: ping.c
===================================================================
RCS file: /home/ncvs/src/sbin/ping/ping.c,v
retrieving revision 1.59
diff -u -r1.59 ping.c
--- ping.c	2001/07/07 19:09:21	1.59
+++ ping.c	2001/07/20 10:47:35
@@ -81,6 +81,7 @@
 #include <termios.h>
 #include <unistd.h>
 
+#include <sys/sysctl.h>
 #include <sys/socket.h>
 #include <sys/time.h>
 #include <sys/uio.h>
@@ -100,9 +101,9 @@
 #define	DEFDATALEN	(64 - PHDR_LEN)	/* default data length */
 #define	FLOOD_BACKOFF	20000		/* usecs to back off if F_FLOOD mode */
 					/* runs out of buffer space */
-#define	MAXIPLEN	60
+#define	MAXIPLEN	(sizeof(struct ip) + MAX_IPOPTLEN)
 #define	MAXICMPLEN	76
-#define	MAXPACKET	(65536 - 60 - 8)/* max packet size */
+#define	MAXPACKET	(IP_MAXPACKET - MAXIPLEN - ICMP_MINLEN) /* max packet size */
 #define	MAXWAIT		10		/* max seconds to wait for response */
 #define	MAXALARM	(60 * 60)	/* max seconds for alarm timeout */
 #define	NROUTES		9		/* number of record route slots */
@@ -136,6 +137,7 @@
 #endif /*IPSEC*/
 #define	F_TTL		0x8000
 #define	F_MISSED	0x10000
+#define	F_HDRINCL	0x20000
 
 /*
  * MAX_DUP_CHK is the number of bits in received table, i.e. the maximum
@@ -149,7 +151,8 @@
 struct sockaddr_in whereto;	/* who to ping */
 int datalen = DEFDATALEN;
 int s;				/* socket file descriptor */
-u_char outpack[MAXPACKET];
+u_char outpackhdr[IP_MAXPACKET]; /* Max packet size = 65535 */
+u_char *outpack = outpackhdr + sizeof(struct ip);
 char BSPACE = '\b';		/* characters written for flood */
 char BBELL = '\a';		/* characters written for MISSED and AUDIBLE */
 char DOT = '.';
@@ -204,7 +207,7 @@
 	int ch, hold, packlen, preload, sockerrno, almost_done = 0, ttl;
 	struct in_addr ifaddr;
 	unsigned char mttl, loop;
-	u_char *datap, *packet;
+	u_char *datap, *packet, df = 0;
 	char *source = NULL, *target, hnamebuf[MAXHOSTNAMELEN];
 	char snamebuf[MAXHOSTNAMELEN];
 	char *ep;
@@ -238,7 +241,7 @@
 
 	datap = &outpack[8 + PHDR_LEN];
 	while ((ch = getopt(argc, argv,
-		"AI:LQRS:T:c:adfi:l:m:np:qrs:t:v"
+		"ADI:LQRS:T:c:adfi:l:m:np:qrs:t:v"
 #ifdef IPSEC
 #ifdef IPSEC_POLICY_IPSEC
 		"P:"
@@ -261,6 +264,10 @@
 				    optarg);
 			npackets = ultmp;
 			break;
+		case 'D':
+			options |= F_HDRINCL;
+			df = 1;
+			break;
 		case 'd':
 			options |= F_SO_DEBUG;
 			break;
@@ -315,7 +322,7 @@
 			break;
 		case 'm':		/* TTL */
 			ultmp = strtoul(optarg, &ep, 0);
-			if (*ep || ep == optarg || ultmp > 255)
+			if (*ep || ep == optarg || ultmp > MAXTTL)
 				errx(EX_USAGE, "invalid TTL: `%s'",
 				     optarg);
 			ttl = ultmp;
@@ -369,7 +376,7 @@
 			break;
 		case 'T':		/* multicast TTL */
 			ultmp = strtoul(optarg, &ep, 0);
-			if (*ep || ep == optarg || ultmp > 255)
+			if (*ep || ep == optarg || ultmp > MAXTTL)
 				errx(EX_USAGE, "invalid multicast TTL: `%s'",
 				     optarg);
 			mttl = ultmp;
@@ -506,6 +513,33 @@
 #endif /*IPSEC_POLICY_IPSEC*/
 #endif /*IPSEC*/
 
+	if (options & F_HDRINCL) {
+		struct ip *ip = (struct ip*)outpackhdr;
+
+#ifdef IPCTL_DEFTTL
+
+		if (!((options & F_TTL) || (options & F_MTTL))) {
+			int mib[4] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_DEFTTL };
+			size_t sz = sizeof(ttl);
+
+			if (sysctl(mib, 4, &ttl, &sz, NULL, 0) == -1)
+				err(1, "sysctl(net.inet.ip.ttl)");
+		}
+
+#endif
+
+		setsockopt(s, IPPROTO_IP, IP_HDRINCL, &hold, sizeof(hold));
+		ip->ip_v = IPVERSION;
+		ip->ip_hl = sizeof(struct ip) >> 2;
+		ip->ip_tos = 0;
+		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
@@ -560,8 +594,11 @@
 	 * ethernet, or just want to fill the arp cache to get some stuff for
 	 * /etc/ethers.  But beware: RFC 1122 allows hosts to ignore broadcast
 	 * or multicast pings if they wish.
+	 *
+	 * We should have our buffers are at least 64K so we can ping with
+	 * IP_MAXPACKET packet size.
 	 */
-	hold = 48 * 1024;
+	hold = 64 * 1024;
 	(void)setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&hold,
 	    sizeof(hold));
 
@@ -742,6 +779,7 @@
 	register struct icmp *icp;
 	register int cc;
 	int i;
+	char *packet = outpack;
 
 	icp = (struct icmp *)outpack;
 	icp->icmp_type = ICMP_ECHO;
@@ -760,8 +798,17 @@
 
 	/* compute ICMP checksum here */
 	icp->icmp_cksum = in_cksum((u_short *)icp, cc);
+
+	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 *)outpack, cc, 0, (struct sockaddr *)&whereto,
+	i = sendto(s, (char *)packet, cc, 0, (struct sockaddr *)&whereto,
 	    sizeof(whereto));
 
 	if (i < 0 || i != cc)  {
Index: ping.8
===================================================================
RCS file: /home/ncvs/src/sbin/ping/ping.8,v
retrieving revision 1.31
diff -u -r1.31 ping.8
--- ping.8	2001/07/15 07:49:16	1.31
+++ ping.8	2001/07/20 10:47:36
@@ -42,7 +42,7 @@
 packets to network hosts
 .Sh SYNOPSIS
 .Nm
-.Op Fl AQRadfnqrv
+.Op Fl ADQRadfnqrv
 .Op Fl c Ar count
 .Op Fl i Ar wait
 .Op Fl l Ar preload
@@ -101,6 +101,9 @@
 If this option is not specified,
 .Nm
 will operate until interrupted.
+.It Fl D
+Set the
+.Dv Don't Fragment bit.
 .It Fl d
 Set the
 .Dv SO_DEBUG
>Release-Note:
>Audit-Trail:
>Unformatted:

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




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