Date: Tue, 2 Apr 2002 13:11:31 +0400 (MSD) From: Maxim Konovalov <maxim@macomnet.ru> To: freebsd-audit@freebsd.org Subject: a couple of ping(8) patches for review Message-ID: <20020402114845.U76561-100000@news1.macomnet.ru>
index | next in thread | raw e-mail
Hello -audit,
I am going to commit two patches below. Bruce Evans has already
reviewed them and now I would like to ask -audit. The first patch is
based on Kris's code.
#1
o correct a maximum payload size,
o replace serveral magic numbers by constants,
o allow zero payload,
o increase an input buffer size.
Index: ping.c
===================================================================
RCS file: /home/ncvs/src/sbin/ping/ping.c,v
retrieving revision 1.64
diff -u -r1.64 ping.c
--- ping.c 23 Mar 2002 18:10:59 -0000 1.64
+++ ping.c 2 Apr 2002 08:23:42 -0000
@@ -100,12 +100,12 @@
#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 MAXICMPLEN 76
-#define MAXPACKET (65536 - 60 - 8)/* max packet size */
+#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 NROUTES 9 /* number of record route slots */
#define A(bit) rcvd_tbl[(bit)>>3] /* identify byte in array */
#define B(bit) (1 << ((bit) & 0x07)) /* identify bit in byte */
@@ -149,7 +149,7 @@
struct sockaddr_in whereto; /* who to ping */
int datalen = DEFDATALEN;
int s; /* socket file descriptor */
-u_char outpack[MAXPACKET];
+u_char outpack[MINICMPLEN + MAXPAYLOAD];
char BSPACE = '\b'; /* characters written for flood */
char BBELL = '\a'; /* characters written for MISSED and AUDIBLE */
char DOT = '.';
@@ -206,7 +206,7 @@
struct timeval last, intvl;
struct hostent *hp;
struct sockaddr_in *to;
- u_char *datap, *packet;
+ u_char *datap, packet[IP_MAXPACKET];
char *ep, *source, *target;
#ifdef IPSEC_POLICY_IPSEC
char *policy_in, *policy_out;
@@ -216,7 +216,7 @@
char ctrl[CMSG_SPACE(sizeof(struct timeval))];
char hnamebuf[MAXHOSTNAMELEN], snamebuf[MAXHOSTNAMELEN];
#ifdef IP_OPTIONS
- char rspace[3 + 4 * NROUTES + 1]; /* record route space */
+ char rspace[MAX_IPOPTLEN]; /* record route space */
#endif
unsigned char mttl, loop;
@@ -238,7 +238,7 @@
alarmtimeout = preload = 0;
- datap = &outpack[8 + PHDR_LEN];
+ datap = &outpack[MINICMPLEN + PHDR_LEN];
while ((ch = getopt(argc, argv,
"AI:LQRS:T:c:adfi:l:m:np:qrs:t:v"
#ifdef IPSEC
@@ -348,10 +348,11 @@
err(EX_NOPERM, "-s flag");
}
ultmp = strtoul(optarg, &ep, 0);
- if (ultmp > MAXPACKET)
- errx(EX_USAGE, "packet size too large: %lu",
- ultmp);
- if (*ep || ep == optarg || !ultmp)
+ 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);
datalen = ultmp;
@@ -414,7 +415,8 @@
source, hstrerror(h_errno));
sin.sin_len = sizeof sin;
- if (hp->h_length > sizeof(sin.sin_addr))
+ if (hp->h_length > sizeof(sin.sin_addr) ||
+ hp->h_length < 0)
errx(1,"gethostbyname2: illegal address");
memcpy(&sin.sin_addr, hp->h_addr_list[0],
sizeof (sin.sin_addr));
@@ -460,9 +462,8 @@
if (datalen >= PHDR_LEN) /* can we time transfer */
timing = 1;
- packlen = datalen + MAXIPLEN + MAXICMPLEN;
- if (!(packet = (u_char *)malloc((size_t)packlen)))
- err(EX_UNAVAILABLE, "malloc");
+ packlen = MAXIPLEN + MAXICMPLEN + datalen;
+ packlen = packlen > IP_MAXPACKET ? IP_MAXPACKET : packlen;
if (!(options & F_PINGFILLED))
for (i = PHDR_LEN; i < datalen; ++i)
@@ -563,7 +564,12 @@
* /etc/ethers. But beware: RFC 1122 allows hosts to ignore broadcast
* or multicast pings if they wish.
*/
- hold = 48 * 1024;
+
+ /*
+ * XXX receive buffer needs undetermined space for mbuf overhead
+ * as well.
+ */
+ hold = IP_MAXPACKET + 128;
(void)setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&hold,
sizeof(hold));
@@ -742,9 +748,9 @@
* pinger --
* Compose and transmit an ICMP ECHO REQUEST packet. The IP packet
* will be added on by the kernel. The ID field is our UNIX process ID,
- * and the sequence number is an ascending integer. The first 8 bytes
- * of the data portion are used to hold a UNIX "timeval" struct in host
- * byte-order, to compute the round-trip time.
+ * and the sequence number is an ascending integer. The first PHDR_LEN
+ * bytes of the data portion are used to hold a UNIX "timeval" struct in
+ * host byte-order, to compute the round-trip time.
*/
static void
pinger(void)
@@ -762,10 +768,10 @@
CLR(ntransmitted % mx_dup_ck);
if (timing)
- (void)gettimeofday((struct timeval *)&outpack[8],
+ (void)gettimeofday((struct timeval *)&outpack[MINICMPLEN],
(struct timezone *)NULL);
- cc = datalen + PHDR_LEN; /* skips ICMP portion */
+ cc = MINICMPLEN + datalen;
/* compute ICMP checksum here */
icp->icmp_cksum = in_cksum((u_short *)icp, cc);
@@ -881,7 +887,7 @@
(void)write(STDOUT_FILENO, &BBELL, 1);
/* check the data */
cp = (u_char*)&icp->icmp_data[PHDR_LEN];
- dp = &outpack[8 + PHDR_LEN];
+ dp = &outpack[MINICMPLEN + PHDR_LEN];
for (i = PHDR_LEN; i < datalen; ++i, ++cp, ++dp) {
if (*cp != *dp) {
(void)printf("\nwrong data byte #%d should be 0x%x but was 0x%x",
@@ -894,7 +900,7 @@
(void)printf("%x ", *cp);
}
printf("\ndp:");
- cp = &outpack[8];
+ cp = &outpack[MINICMPLEN];
for (i = 0; i < datalen; ++i, ++cp) {
if ((i % 32) == 8)
(void)printf("\n\t");
@@ -1416,7 +1422,7 @@
{
char *cp;
int pat[16];
- int ii, jj, kk;
+ u_int ii, jj, kk;
for (cp = patp; *cp; cp++) {
if (!isxdigit(*cp))
@@ -1431,9 +1437,7 @@
&pat[13], &pat[14], &pat[15]);
if (ii > 0)
- for (kk = 0;
- kk <= MAXPACKET - (8 + 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)) {
%%%
#2
Rewrote IP options parsing:
o more strict boundary checks,
o replace magic numbers by constants.
The diff is practically unreadable, sorry.
Index: ping.c
===================================================================
RCS file: /home/ncvs/src/sbin/ping/ping.c,v
retrieving revision 1.64
diff -u -r1.64 ping.c
--- ping.c 23 Mar 2002 18:10:59 -0000 1.64
+++ ping.c 2 Apr 2002 08:20:16 -0000
@@ -96,6 +96,7 @@
#include <netinet6/ipsec.h>
#endif /*IPSEC*/
+#define INADDR_LEN ((int)sizeof(in_addr_t))
#define PHDR_LEN sizeof(struct timeval)
#define DEFDATALEN (64 - PHDR_LEN) /* default data length */
#define FLOOD_BACKOFF 20000 /* usecs to back off if F_FLOOD mode */
@@ -806,10 +807,10 @@
{
struct icmp *icp;
struct ip *ip;
+ struct in_addr ina;
struct timeval *tp;
u_char *cp, *dp;
double triptime;
- u_long l;
int dupflag, hlen, i, j, seq;
static int old_rrlen;
static char old_rr[MAX_IPOPTLEN];
@@ -945,79 +946,68 @@
break;
case IPOPT_LSRR:
(void)printf("\nLSRR: ");
+ j = cp[IPOPT_OLEN] - IPOPT_MINOFF + 1;
hlen -= 2;
- j = *++cp;
- ++cp;
- if (j > IPOPT_MINOFF)
+ cp += 2;
+ if (j >= INADDR_LEN && j <= hlen - INADDR_LEN) {
for (;;) {
- l = *++cp;
- l = (l<<8) + *++cp;
- l = (l<<8) + *++cp;
- l = (l<<8) + *++cp;
- if (l == 0) {
+ bcopy(++cp, &ina.s_addr, INADDR_LEN);
+ if (ina.s_addr == 0)
printf("\t0.0.0.0");
- } else {
- struct in_addr ina;
- ina.s_addr = ntohl(l);
+ else
printf("\t%s", pr_addr(ina));
- }
- hlen -= 4;
- j -= 4;
- if (j <= IPOPT_MINOFF)
- break;
- (void)putchar('\n');
- }
+ hlen -= INADDR_LEN;
+ cp += INADDR_LEN - 1;
+ j -= INADDR_LEN;
+ if (j < INADDR_LEN)
+ break;
+ (void)putchar('\n');
+ }
+ } else
+ (void)printf("\t(truncated route)\n");
break;
case IPOPT_RR:
- j = *++cp; /* get length */
- i = *++cp; /* and pointer */
+ j = cp[IPOPT_OLEN]; /* get length */
+ i = cp[IPOPT_OFFSET]; /* and pointer */
hlen -= 2;
+ cp += 2;
if (i > j)
i = j;
- i -= IPOPT_MINOFF;
- if (i <= 0)
+ i = i - IPOPT_MINOFF + 1;
+ if (i < 0 || i > (hlen - (int)sizeof(struct ip))) {
+ old_rrlen = 0;
continue;
+ }
if (i == old_rrlen
- && cp == (u_char *)buf + sizeof(struct ip) + 2
&& !bcmp((char *)cp, old_rr, i)
&& !(options & F_FLOOD)) {
(void)printf("\t(same route)");
- i = ((i + 3) / 4) * 4;
hlen -= i;
cp += i;
break;
}
- if (i < MAX_IPOPTLEN) {
- old_rrlen = i;
- bcopy((char *)cp, old_rr, i);
- } else
- old_rrlen = 0;
+ old_rrlen = i;
+ bcopy((char *)cp, old_rr, i);
(void)printf("\nRR: ");
- j = 0;
- for (;;) {
- l = *++cp;
- l = (l<<8) + *++cp;
- l = (l<<8) + *++cp;
- l = (l<<8) + *++cp;
- if (l == 0) {
- printf("\t0.0.0.0");
- } else {
- struct in_addr ina;
- ina.s_addr = ntohl(l);
- printf("\t%s", pr_addr(ina));
- }
- hlen -= 4;
- i -= 4;
- j += 4;
- if (i <= 0)
- break;
- if (j >= MAX_IPOPTLEN) {
- (void) printf("\t(truncated route)");
- break;
+
+ if (i >= INADDR_LEN &&
+ i <= hlen - (int)sizeof(struct ip)) {
+ for (;;) {
+ bcopy(++cp, &ina.s_addr, INADDR_LEN);
+ if (ina.s_addr == 0)
+ printf("\t0.0.0.0");
+ else
+ printf("\t%s", pr_addr(ina));
+ hlen -= INADDR_LEN;
+ cp += INADDR_LEN - 1;
+ i -= INADDR_LEN;
+ if (i < INADDR_LEN)
+ break;
+ (void)putchar('\n');
}
- (void)putchar('\n');
- }
+ } else
+ (void)printf("\t(truncated route)");
break;
case IPOPT_NOP:
(void)printf("\nNOP");
%%%
Thanks,
Maxim.
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-audit" in the body of the message
home |
help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020402114845.U76561-100000>
