Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/netinet Improve robustness of icmp_error():



details:   https://anonhg.NetBSD.org/src/rev/809accf267de
branches:  trunk
changeset: 495193:809accf267de
user:      sommerfeld <sommerfeld%NetBSD.org@localhost>
date:      Mon Jul 24 03:32:31 2000 +0000

description:
Improve robustness of icmp_error():
 - allow it to work when icmpreturndatabytes is sufficiently large that the
icmp error message doesn't fit in a header mbuf.
 - defend against mbuf chains shorter than their contained ip->ip_len.

diffstat:

 sys/netinet/ip_icmp.c |  38 ++++++++++++++++++++++++++++++++++----
 1 files changed, 34 insertions(+), 4 deletions(-)

diffs (63 lines):

diff -r 228e103b1119 -r 809accf267de sys/netinet/ip_icmp.c
--- a/sys/netinet/ip_icmp.c     Mon Jul 24 02:54:22 2000 +0000
+++ b/sys/netinet/ip_icmp.c     Mon Jul 24 03:32:31 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ip_icmp.c,v 1.51 2000/07/10 09:31:30 itojun Exp $      */
+/*     $NetBSD: ip_icmp.c,v 1.52 2000/07/24 03:32:31 sommerfeld Exp $  */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -179,7 +179,7 @@
        unsigned oiplen = oip->ip_hl << 2;
        struct icmp *icp;
        struct mbuf *m;
-       unsigned icmplen;
+       unsigned icmplen, mblen;
 
 #ifdef ICMPPRINTFS
        if (icmpprintfs)
@@ -218,12 +218,42 @@
        /*
         * Now, formulate icmp message
         */
+       icmplen = oiplen + min(icmpreturndatabytes, oip->ip_len - oiplen);
+       /*
+        * Defend against mbuf chains shorter than oip->ip_len:
+        */
+       mblen = 0;
+       for (m = n; m && (mblen < icmplen); m = m->m_next)
+               mblen += m->m_len;
+       icmplen = min(mblen, icmplen);
+
+       /*
+        * As we are not required to return everything we have,
+        * we return whatever we can return at ease.
+        *
+        * Note that ICMP datagrams longer than 576 octets are out of spec
+        * according to RFC1812; the limit on icmpreturndatabytes below in
+        * icmp_sysctl will keep things below that limit.
+        */
+
+       KASSERT(ICMP_MINLEN <= MCLBYTES);
+
+       if (icmplen + ICMP_MINLEN > MCLBYTES)
+               icmplen = MCLBYTES - ICMP_MINLEN;
+
        m = m_gethdr(M_DONTWAIT, MT_HEADER);
+       if (m && (icmplen + ICMP_MINLEN > MHLEN)) {
+               MCLGET(m, M_DONTWAIT);
+               if ((m->m_flags & M_EXT) == 0) {
+                       m_freem(m);
+                       m = NULL;
+               }
+       }
        if (m == NULL)
                goto freeit;
-       icmplen = oiplen + min(icmpreturndatabytes, oip->ip_len - oiplen);
        m->m_len = icmplen + ICMP_MINLEN;
-       MH_ALIGN(m, m->m_len);
+       if ((m->m_flags & M_EXT) == 0)
+               MH_ALIGN(m, m->m_len);
        icp = mtod(m, struct icmp *);
        if ((u_int)type > ICMP_MAXTYPE)
                panic("icmp_error");



Home | Main Index | Thread Index | Old Index