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>