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>
