From chellberg@juniper.net  Fri Jun 24 22:59:53 2005
Return-Path: <chellberg@juniper.net>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 5E69F16A41C
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 24 Jun 2005 22:59:53 +0000 (GMT)
	(envelope-from chellberg@juniper.net)
Received: from ssh2.juniper.net (ssh2.juniper.net [207.17.136.44])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 48B3D43D55
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 24 Jun 2005 22:59:53 +0000 (GMT)
	(envelope-from chellberg@juniper.net)
Received: from ssh2.juniper.net (localhost [127.0.0.1])
	by ssh2.juniper.net (8.12.11/8.12.3) with ESMTP id j5OMxrXZ062370
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 24 Jun 2005 15:59:53 -0700 (PDT)
	(envelope-from chellberg@ssh2.juniper.net)
Received: (from chellberg@localhost)
	by ssh2.juniper.net (8.12.11/8.12.3/Submit) id j5OMxr6u062369;
	Fri, 24 Jun 2005 15:59:53 -0700 (PDT)
Message-Id: <200506242259.j5OMxr6u062369@ssh2.juniper.net>
Date: Fri, 24 Jun 2005 15:59:53 -0700 (PDT)
From: Chris Hellberg <chellberg@juniper.net>
Reply-To: Chris Hellberg <chellberg@juniper.net>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: [PATCH] Enhancement to ping to ping through
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         82625
>Category:       bin
>Synopsis:       [PATCH] Enhancement to ping to ping through
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    glebius
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Fri Jun 24 23:00:26 GMT 2005
>Closed-Date:    Thu Nov 03 12:42:44 GMT 2005
>Last-Modified:  Thu Nov 03 12:42:44 GMT 2005
>Originator:     Chris Hellberg <chellberg@juniper.net>
>Release:        FreeBSD 5.3-STABLE i386
>Organization:
Juniper Networks
>Environment:
System: FreeBSD  5.3-RELEASE FreeBSD 5.3-RELEASE #0: Fri Nov
5 04:19:18 UTC 2004   chellberg@localhost:/usr/obj/usr/src/sys/GENERIC  i386


	
>Description:
	A useful function to test MTU issues and traffic
policing functions in networks is to gradually increment
packet sizes in pings in a sweeping fashion.
	
>How-To-Repeat:
	
>Fix:

The diffs implment the changes needed to ping.c and updates
the ping manpage. To get the ping sweep working, you need to
specify pingsweepmax as a minimum. This is the maximum data
size that will be sent.

If pingsweepmin is set, the data size will start from the
specified value. The default data size is 0.

If pingsweepincr is set, after each _count_ number of packets
has been sent, the data size is increased by the current
data size + pingsweepincr. This cycle repeated until the
current data size is equal or less to pingsweepmax. If 
pingsweepincr doesn't divide evenly in to pingsweepmax, the
sweep will stop before it would exceed pingsweepmax.

If "-s count" is included, each sweep of a particular data size
will consist of "count" bytes.

>Release-Note:
>Audit-Trail:

From: Chris Hellberg <chellberg@juniper.net>
To: bug-followup@freebsd.org
Cc:  
Subject: Re: bin/82625: [PATCH] Enhancement to ping to ping through
Date: Fri, 24 Jun 2005 16:06:17 -0700

 --y0ulUmNC+osPPQO6
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 
 Pathces attached
 
 
 --y0ulUmNC+osPPQO6
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: attachment; filename="ping.8.diff"
 
 --- src/sbin/ping/ping.8	2004-04-09 15:58:34.000000000 -0400
 +++ ping.8	2005-06-24 18:26:05.000000000 -0400
 @@ -40,6 +40,9 @@
  .Nm
  .Op Fl AaDdfnoQqRrv
  .Op Fl c Ar count
 +.Op Fl G Ar sweepminsize
 +.Op Fl g Ar sweepminsize
 +.Op Fl h Ar sweepincrsize
  .Op Fl i Ar wait
  .Op Fl l Ar preload
  .Op Fl M Cm mask | time
 @@ -115,7 +118,9 @@
  packets.
  If this option is not specified,
  .Nm
 -will operate until interrupted.
 +will operate until interrupted. If this option is specified in 
 +conjunction with ping sweeps, each sweep will consist of .Ar count
 +packets.
  .It Fl D
  Set the Don't Fragment bit.
  .It Fl d
 @@ -138,6 +143,15 @@
  .Bf -emphasis
  This can be very hard on a network and should be used with caution.
  .Ef
 +.It Fl G Ar sweepmaxsize
 +Specify the maximum number of data bytes to increment to when sending
 +sweeping pings. This option is required for ping sweeps. 
 +.It Fl g Ar sweepminsize
 +Specify the number of data bytes to begin incrementing from when sending
 +sweeping pings. 
 +.It Fl H Ar sweepincrsize
 +Specify the number of data bytes to increment by after each sweep when
 +sending sweeping pings. 
  .It Fl I Ar iface
  Source multicast packets with the given interface address.
  This flag only applies if the ping destination is a multicast address.
 @@ -269,7 +283,8 @@
  with the 8 bytes of
  .Tn ICMP
  header data.
 -Only the super-user may specify values more than default.
 +Only the super-user may specify values more than default. This option
 +cannot be used with ping sweeps.
  .It Fl T Ar ttl
  Set the IP Time To Live for multicasted packets.
  This flag only applies if the ping destination is a multicast address.
 
 --y0ulUmNC+osPPQO6
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: attachment; filename="ping.c.diff"
 
 --- src/sbin/ping/ping.c	2004-09-30 03:35:56.000000000 -0400
 +++ ping.c	2005-06-24 18:13:31.000000000 -0400
 @@ -42,7 +42,7 @@
  #endif /* not lint */
  #endif
  #include <sys/cdefs.h>
 -__FBSDID("$FreeBSD: src/sbin/ping/ping.c,v 1.106 2004/09/30 07:35:56 maxim Exp $");
 +__FBSDID("$FreeBSD: src/sbin/ping/ping.c,v 1.105 2004/08/14 17:46:10 stefanf Exp $");
  
  /*
   *			P I N G . C
 @@ -111,8 +111,8 @@
  #define	TST(bit)	(A(bit) & B(bit))
  
  struct tv32 {
 -	int32_t tv32_sec;
 -	int32_t tv32_usec;
 +       int32_t tv32_sec;
 +       int32_t tv32_usec;
  };
  
  /* various options */
 @@ -142,6 +142,7 @@
  #define	F_HDRINCL	0x40000
  #define	F_MASK		0x80000
  #define	F_TIME		0x100000
 +#define F_SWEEP		0x200000
  
  /*
   * MAX_DUP_CHK is the number of bits in received table, i.e. the maximum
 @@ -175,8 +176,12 @@
  long nreceived;			/* # of packets we got back */
  long nrepeats;			/* number of duplicates */
  long ntransmitted;		/* sequence # for outbound packets = #sent */
 +int sweepmax;
 +int sweepmin = 0;
 +int sweepincr = 1;
  int interval = 1000;		/* interval between packets, ms */
  
 +
  /* timing */
  int timing;			/* flag to do timing */
  double tmin = 999999999.0;	/* minimum round trip time */
 @@ -226,7 +231,7 @@
  	double t;
  	u_long alarmtimeout, ultmp;
  	int almost_done, ch, df, hold, i, icmp_len, mib[4], preload, sockerrno,
 -	    tos, ttl;
 +	    tos, ttl, ninsweep=0, totpackets;
  	char ctrl[CMSG_SPACE(sizeof(struct timeval))];
  	char hnamebuf[MAXHOSTNAMELEN], snamebuf[MAXHOSTNAMELEN];
  #ifdef IP_OPTIONS
 @@ -254,7 +259,7 @@
  
  	outpack = outpackhdr + sizeof(struct ip);
  	while ((ch = getopt(argc, argv,
 -		"Aac:DdfI:i:Ll:M:m:nop:QqRrS:s:T:t:vz:"
 +		"Aac:DdfI:i:g:G:h:Ll:M:m:nop:QqRrS:s:T:t:vz:"
  #ifdef IPSEC
  #ifdef IPSEC_POLICY_IPSEC
  		"P:"
 @@ -292,6 +297,48 @@
  			options |= F_FLOOD;
  			setbuf(stdout, (char *)NULL);
  			break;
 +		case 'g': /* Minimum packet size for ping sweep */
 +			ultmp = strtoul(optarg, &ep, 0);
 +			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);
 +			}
 +			options |= F_SWEEP;
 +			sweepmin = ultmp;
 +			break;
 +		case 'G': /* Maximum packet size for ping sweep */
 +			ultmp = strtoul(optarg, &ep, 0);
 +			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);
 +			}
 +			options |= F_SWEEP;
 +			sweepmax = ultmp;
 +			break;
 +		case 'h': /* Packet size increment for ping sweep */
 +			ultmp = strtoul(optarg, &ep, 0);
 +			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);
 +			}
 +			options |= F_SWEEP;
 +			sweepincr = ultmp;
 +			break;
  		case 'I':		/* multicast interface */
  			if (inet_aton(optarg, &ifaddr) == 0)
  				errx(EX_USAGE,
 @@ -643,6 +690,21 @@
  		err(EX_OSERR, "setsockopt SO_TIMESTAMP");
  	}
  #endif
 +	if (sweepmax) {
 +	    if (sweepmin >= sweepmax)
 + 	    errx(EX_USAGE,"Maximum packet size must be greater than the minimum packet size");
 +
 +	    if (datalen != DEFDATALEN)
 + 	    errx(EX_USAGE,"Packet size and ping sweep are mutually exclusive");
 +
 +	    if (!npackets)
 +		npackets = 1;
 +		totpackets = npackets * (1+(sweepmax-sweepmin)/sweepincr);
 +		datalen = sweepmin;
 +		send_len = icmp_len + sweepmin;
 +	}
 +	if (options & F_SWEEP && !sweepmax) 
 +	    errx(EX_USAGE, "Maximum sweep size must be specified");
  
  	/*
  	 * When pinging the broadcast address, you can get a lot of answers.
 @@ -668,9 +730,19 @@
  		    inet_ntoa(to->sin_addr));
  		if (source)
  			(void)printf(" from %s", shostname);
 -		(void)printf(": %d data bytes\n", datalen);
 -	} else
 -		(void)printf("PING %s: %d data bytes\n", hostname, datalen);
 +		if (sweepmax) {
 +			(void)printf(": (%d...%d) data bytes\n", sweepmin,sweepmax);
 +		} else 
 +			(void)printf(": %d data bytes\n", datalen);
 +		
 +	} else {
 +		if (sweepmax) {
 +		   (void)printf("PING %s: (%d...%d) data bytes\n", hostname, sweepmin,sweepmax);
 +
 +	       } else {
 +		   (void)printf("PING %s: %d data bytes\n", hostname, datalen);
 +		}
 +	}
  
  	/*
  	 * Use sigaction() instead of signal() to get unambiguous semantics,
 @@ -706,9 +778,10 @@
  	iov.iov_base = packet;
  	iov.iov_len = IP_MAXPACKET;
  
 -	if (preload == 0)
 +	if (preload == 0) {
  		pinger();		/* send the first ping */
 -	else {
 +		ninsweep++;
 +	} else {
  		if (npackets != 0 && preload > npackets)
  			preload = npackets;
  		while (preload--)	/* fire off them quickies */
 @@ -729,7 +802,6 @@
  		struct timeval now, timeout;
  		fd_set rfds;
  		int cc, n;
 -
  		check_status();
  		if ((unsigned)s >= FD_SETSIZE)
  			errx(EX_OSERR, "descriptor too large");
 @@ -779,14 +851,24 @@
  				tv = &now;
  			}
  			pr_pack((char *)packet, cc, &from, tv);
 -			if ((options & F_ONCE && nreceived) ||
 -			    (npackets && nreceived >= npackets))
 -				break;
 +			 if ((options & F_ONCE && nreceived) ||	 
 +			       (totpackets && ntransmitted >= totpackets))
 +			     break;
 +				 
  		}
 +
  		if (n == 0 || options & F_FLOOD) {
 -			if (!npackets || ntransmitted < npackets)
 +		        if (totpackets && ninsweep == npackets) {
 +		                for (i = 0; i < sweepincr ; ++i) 
 +			            *datap++ = i;
 +	 	           datalen = datalen+sweepincr;
 +		           send_len = icmp_len + datalen;
 +			   ninsweep = 0;
 +                        } 
 +			if (!npackets || ntransmitted < totpackets) {
  				pinger();
 -			else {
 +				ninsweep++;
 +		 	} else {
  				if (almost_done)
  					break;
  				almost_done = 1;
 @@ -805,7 +887,7 @@
  					(void)write(STDOUT_FILENO, &BBELL, 1);
  			}
  		}
 -	}
 +            }
  	finish();
  	/* NOTREACHED */
  	exit(0);	/* Make the compiler happy */
 @@ -1600,12 +1682,14 @@
  usage()
  {
  
 -	(void)fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n",
 +	(void)fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
  "usage: ping [-AaDdfnoQqRrv] [-c count] [-i wait] [-l preload] [-M mask | time]",
  "            [-m ttl]" SECOPT " [-p pattern] [-S src_addr] [-s packetsize]",
 -"            [-t timeout] [-z tos] host",
 -"       ping [-AaDdfLnoQqRrv] [-c count] [-I iface] [-i wait] [-l preload]",
 -"            [-M mask | time] [-m ttl]" SECOPT " [-p pattern] [-S src_addr]",
 -"            [-s packetsize] [-T ttl] [-t timeout] [-z tos] mcast-group");
 +"            [-t timeout] [-z tos] host [ -G sweepmaxsize ] [ -g sweepminsize ]",
 +"            [ -h sweepincrsize ] ", 
 +"       ping [-AaDdfLnoQqRrv] [-c count] [-i wait] [-I iface] [-l preload]",
 +"            [-M mask | time] [-m ttl]" SECOPT " [-p pattern] ",
 +"            [-S src_addr] [-s packetsize] [-T ttl] [-t timeout] ",
 +"            [-z tos] mcast-group ");
  	exit(EX_USAGE);
  }
 
 --y0ulUmNC+osPPQO6--

From: Gleb Smirnoff <glebius@FreeBSD.org>
To: Chris Hellberg <chellberg@juniper.net>
Cc: FreeBSD-gnats-submit@FreeBSD.org
Subject: Re: bin/82625: [PATCH] Enhancement to ping to ping through
Date: Mon, 15 Aug 2005 15:52:20 +0400

   Chris,
 
 can you please comment this change? I can't understand it:
 
 @@ -780,13 +853,21 @@
                         }
                         pr_pack((char *)packet, cc, &from, tv);
                         if ((options & F_ONCE && nreceived) ||
 -                           (npackets && nreceived >= npackets))
 +                           (totpackets && ntransmitted >= totpackets))
                                 break;
                 }
 
 -- 
 Totus tuus, Glebius.
 GLEBIUS-RIPN GLEB-RIPE
State-Changed-From-To: open->patched 
State-Changed-By: glebius 
State-Changed-When: Mon Aug 15 14:16:37 GMT 2005 
State-Changed-Why:  
Functionality committed. 


Responsible-Changed-From-To: freebsd-bugs->glebius 
Responsible-Changed-By: glebius 
Responsible-Changed-When: Mon Aug 15 14:16:37 GMT 2005 
Responsible-Changed-Why:  
I find the functionality very useful. In the past I made this 
by hand or with shell scripts. I have committed slightly edited 
patch version. 

The submitted patch breaks '-c' switch used without sweep. Also, 
the patch had several style(9) and mdoc(7) problems. Please, 
next time clean your patch thoroughly. Thanks. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=82625 
State-Changed-From-To: patched->closed 
State-Changed-By: glebius 
State-Changed-When: Thu Nov 3 12:42:32 GMT 2005 
State-Changed-Why:  
Merged to RELENG_5. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=82625 
>Unformatted:
 a range of data sizes
