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