Source-Changes-HG archive

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

[src/trunk]: src/sys/netinet6 cleanup AH/policy processing.



details:   https://anonhg.NetBSD.org/src/rev/ffd632f4a1e0
branches:  trunk
changeset: 483962:ffd632f4a1e0
user:      itojun <itojun%NetBSD.org@localhost>
date:      Tue Mar 21 23:53:30 2000 +0000

description:
cleanup AH/policy processing.
- parse IPv6 header by using common function, ip6_{last,next}hdr.
- fix behaivior in multiple AH cases.
  make strict boundary checks on mbuf chasing.
(sync with latest kame)

diffstat:

 sys/netinet6/ah_core.c   |  654 ++++++++++++++++++++++------------------------
 sys/netinet6/ah_input.c  |   51 ++-
 sys/netinet6/ah_output.c |   14 +-
 sys/netinet6/ip6_input.c |  111 +++++++-
 sys/netinet6/ip6_var.h   |    6 +-
 sys/netinet6/ipsec.c     |  103 ++----
 6 files changed, 517 insertions(+), 422 deletions(-)

diffs (truncated from 1267 to 300 lines):

diff -r e5ab5b94aeb1 -r ffd632f4a1e0 sys/netinet6/ah_core.c
--- a/sys/netinet6/ah_core.c    Tue Mar 21 21:30:33 2000 +0000
+++ b/sys/netinet6/ah_core.c    Tue Mar 21 23:53:30 2000 +0000
@@ -1,4 +1,5 @@
-/*     $NetBSD: ah_core.c,v 1.16 2000/02/06 12:49:40 itojun Exp $      */
+/*     $NetBSD: ah_core.c,v 1.17 2000/03/21 23:53:30 itojun Exp $      */
+/*     $KAME: ah_core.c,v 1.29 2000/03/11 09:20:21 itojun Exp $        */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -92,11 +93,6 @@
 
 #define        HMACSIZE        16
 
-#ifdef INET6
-#define ZEROBUFLEN     256
-static char zerobuf[ZEROBUFLEN];
-#endif
-
 static int ah_sumsiz_1216 __P((struct secasvar *));
 static int ah_sumsiz_zero __P((struct secasvar *));
 static int ah_none_mature __P((struct secasvar *));
@@ -129,8 +125,11 @@
        size_t));
 static void ah_hmac_sha1_result __P((struct ah_algorithm_state *, caddr_t));
 
+static void ah_update_mbuf __P((struct mbuf *, int, int, struct ah_algorithm *,
+       struct ah_algorithm_state *));
+
 /* checksum algorithms */
-/* NOTE: The order depends on SADB_AALG_x in net/pfkeyv2.h.h */
+/* NOTE: The order depends on SADB_AALG_x in net/pfkeyv2.h */
 struct ah_algorithm ah_algorithms[] = {
        { 0, 0, 0, 0, 0, 0, },
        { ah_sumsiz_1216, ah_hmac_md5_mature, 128, 128,
@@ -655,27 +654,78 @@
 /*
  * go generate the checksum.
  */
+static void
+ah_update_mbuf(m, off, len, algo, algos)
+       struct mbuf *m;
+       int off;
+       int len;
+       struct ah_algorithm *algo;
+       struct ah_algorithm_state *algos;
+{
+       struct mbuf *n;
+       int tlen;
+
+       /* easy case first */
+       if (off + len <= m->m_len) {
+               (algo->update)(algos, mtod(m, caddr_t) + off, len);
+               return;
+       }
+
+       for (n = m; n; n = n->m_next) {
+               if (off < n->m_len)
+                       break;
+
+               off -= n->m_len;
+       }
+
+       if (!n)
+               panic("ah_update_mbuf: wrong offset specified");
+
+       for (/*nothing*/; n && len > 0; n = n->m_next) {
+               if (n->m_len == 0)
+                       continue;
+               if (n->m_len - off < len)
+                       tlen = n->m_len - off;
+               else
+                       tlen = len;
+
+               (algo->update)(algos, mtod(n, caddr_t) + off, tlen);
+
+               len -= tlen;
+               off = 0;
+       }
+}
+
+/*
+ * Go generate the checksum. This function won't modify the mbuf chain
+ * except AH itself.
+ *
+ * NOTE: the function does not free mbuf on failure.
+ * Don't use m_copy(), it will try to share cluster mbuf by using refcnt.
+ */
 int
-ah4_calccksum(m0, ahdat, algo, sav)
-       struct mbuf *m0;
+ah4_calccksum(m, ahdat, algo, sav)
+       struct mbuf *m;
        caddr_t ahdat;
        struct ah_algorithm *algo;
        struct secasvar *sav;
 {
-       struct mbuf *m;
+       int off;
        int hdrtype;
-       u_char *p;
        size_t advancewidth;
        struct ah_algorithm_state algos;
-       int tlen;
        u_char sumbuf[AH_MAXSUMSIZE];
        int error = 0;
+       int ahseen;
+       struct mbuf *n = NULL;
 
+       if ((m->m_flags & M_PKTHDR) == 0)
+               return EINVAL;
+
+       ahseen = 0;
        hdrtype = -1;   /*dummy, it is called IPPROTO_IP*/
 
-       m = m0;
-
-       p = mtod(m, u_char *);
+       off = 0;
 
        (algo->init)(&algos, sav);
 
@@ -684,17 +734,16 @@
 again:
        /* gory. */
        switch (hdrtype) {
-       case -1:        /*first one*/
+       case -1:        /*first one only*/
            {
                /*
                 * copy ip hdr, modify to fit the AH checksum rule,
                 * then take a checksum.
-                * XXX need to care about source routing... jesus.
                 */
                struct ip iphdr;
                size_t hlen;
 
-               bcopy((caddr_t)p, (caddr_t)&iphdr, sizeof(struct ip));
+               m_copydata(m, off, sizeof(iphdr), (caddr_t)&iphdr);
 #ifdef _IP_VHL
                hlen = IP_VHL_HL(iphdr.ip_vhl) << 2;
 #else
@@ -702,22 +751,38 @@
 #endif
                iphdr.ip_ttl = 0;
                iphdr.ip_sum = htons(0);
-               if (ip4_ah_cleartos) iphdr.ip_tos = 0;
+               if (ip4_ah_cleartos)
+                       iphdr.ip_tos = 0;
                iphdr.ip_off = htons(ntohs(iphdr.ip_off) & ip4_ah_offsetmask);
                (algo->update)(&algos, (caddr_t)&iphdr, sizeof(struct ip));
 
                if (hlen != sizeof(struct ip)) {
                        u_char *p;
-                       int i, j;
-                       int l, skip;
-                       u_char dummy[4];
+                       int i, l, skip;
+
+                       if (hlen > MCLBYTES) {
+                               error = EMSGSIZE;
+                               goto fail;
+                       }
+                       MGET(n, M_DONTWAIT, MT_DATA);
+                       if (n && hlen > MLEN) {
+                               MCLGET(n, M_DONTWAIT);
+                               if ((n->m_flags & M_EXT) == 0) {
+                                       m_free(n);
+                                       n = NULL;
+                               }
+                       }
+                       if (n == NULL) {
+                               error = ENOBUFS;
+                               goto fail;
+                       }
+                       m_copydata(m, off, hlen, mtod(n, caddr_t));
 
                        /*
                         * IP options processing.
                         * See RFC2402 appendix A.
                         */
-                       bzero(dummy, sizeof(dummy));
-                       p = mtod(m, u_char *);
+                       p = mtod(n, u_char *);
                        i = sizeof(struct ip);
                        while (i < hlen) {
                                skip = 1;
@@ -746,19 +811,22 @@
                                            "(type=%02x len=%02x)\n",
                                            p[i + IPOPT_OPTVAL],
                                            p[i + IPOPT_OLEN]));
-                                       break;
+                                       m_free(n);
+                                       n = NULL;
+                                       error = EINVAL;
+                                       goto fail;
                                }
-                               if (skip) {
-                                       for (j = 0; j < l / sizeof(dummy); j++)
-                                               (algo->update)(&algos, dummy, sizeof(dummy));
-
-                                       (algo->update)(&algos, dummy, l % sizeof(dummy));
-                               } else
-                                       (algo->update)(&algos, p + i, l);
+                               if (skip)
+                                       bzero(p + i, l);
                                if (p[i + IPOPT_OPTVAL] == IPOPT_EOL)
                                        break;
                                i += l;
                        }
+                       p = mtod(n, u_char *) + sizeof(struct ip);
+                       (algo->update)(&algos, p, hlen - sizeof(struct ip));
+
+                       m_free(n);
+                       n = NULL;
                }
 
                hdrtype = (iphdr.ip_p) & 0xff;
@@ -768,375 +836,293 @@
 
        case IPPROTO_AH:
            {
-               u_char dummy[4];
+               struct ah ah;
                int siz;
                int hdrsiz;
-
-               hdrsiz = (sav->flags & SADB_X_EXT_OLD) ?
-                               sizeof(struct ah) : sizeof(struct newah);
+               int totlen;
 
-               (algo->update)(&algos, p, hdrsiz);
-
-               /* key data region. */
+               m_copydata(m, off, sizeof(ah), (caddr_t)&ah);
+               hdrsiz = (sav->flags & SADB_X_EXT_OLD)
+                               ? sizeof(struct ah)
+                               : sizeof(struct newah);
                siz = (*algo->sumsiz)(sav);
-               bzero(&dummy[0], sizeof(dummy));
-               while (sizeof(dummy) <= siz) {
-                       (algo->update)(&algos, dummy, sizeof(dummy));
-                       siz -= sizeof(dummy);
-               }
-               /* can't happen, but just in case */
-               if (siz)
-                       (algo->update)(&algos, dummy, siz);
+               totlen = (ah.ah_len + 2) << 2;
 
-               /* padding region, just in case */
-               siz = (((struct ah *)p)->ah_len << 2) - (*algo->sumsiz)(sav);
-               if ((sav->flags & SADB_X_EXT_OLD) == 0)
-                       siz -= 4;               /* sequence number field */
-               if (0 < siz) {
-                       /* RFC 1826 */
-                       (algo->update)(&algos, p + hdrsiz + (*algo->sumsiz)(sav),
-                               siz);
-               }
+               /*
+                * special treatment is necessary for the first one, not others
+                */
+               if (!ahseen) {
+                       if (totlen > m->m_pkthdr.len - off ||
+                           totlen > MCLBYTES) {
+                               error = EMSGSIZE;
+                               goto fail;
+                       }
+                       MGET(n, M_DONTWAIT, MT_DATA);
+                       if (n && totlen > MLEN) {
+                               MCLGET(n, M_DONTWAIT);
+                               if ((n->m_flags & M_EXT) == 0) {
+                                       m_free(n);
+                                       n = NULL;
+                               }
+                       }
+                       if (n == NULL) {
+                               error = ENOBUFS;
+                               goto fail;
+                       }
+                       m_copydata(m, off, totlen, mtod(n, caddr_t));
+                       n->m_len = totlen;
+                       bzero(mtod(n, caddr_t) + hdrsiz, siz);
+                       (algo->update)(&algos, mtod(n, caddr_t), n->m_len);
+                       m_free(n);
+                       n = NULL;
+               } else
+                       ah_update_mbuf(m, off, totlen, algo, &algos);
+               ahseen++;
 
-               hdrtype = ((struct ah *)p)->ah_nxt;
-               advancewidth = hdrsiz;
-               advancewidth += ((struct ah *)p)->ah_len << 2;
-               if ((sav->flags & SADB_X_EXT_OLD) == 0)
-                       advancewidth -= 4;      /* sequence number field */
+               hdrtype = ah.ah_nxt;
+               advancewidth = totlen;
                break;
            }
 
        default:



Home | Main Index | Thread Index | Old Index