diff options
author | ume <ume@FreeBSD.org> | 2001-06-11 12:39:29 +0000 |
---|---|---|
committer | ume <ume@FreeBSD.org> | 2001-06-11 12:39:29 +0000 |
commit | 832f8d224926758a9ae0b23a6b45353e44fbc87a (patch) | |
tree | a79fc7ad2b97862c4a404f352f0211ad93a7b5f1 /sys/netinet6/ipcomp_input.c | |
parent | 2693854b01a52b0395a91322aa3edf926bddff38 (diff) | |
download | FreeBSD-src-832f8d224926758a9ae0b23a6b45353e44fbc87a.zip FreeBSD-src-832f8d224926758a9ae0b23a6b45353e44fbc87a.tar.gz |
Sync with recent KAME.
This work was based on kame-20010528-freebsd43-snap.tgz and some
critical problem after the snap was out were fixed.
There are many many changes since last KAME merge.
TODO:
- The definitions of SADB_* in sys/net/pfkeyv2.h are still different
from RFC2407/IANA assignment because of binary compatibility
issue. It should be fixed under 5-CURRENT.
- ip6po_m member of struct ip6_pktopts is no longer used. But, it
is still there because of binary compatibility issue. It should
be removed under 5-CURRENT.
Reviewed by: itojun
Obtained from: KAME
MFC after: 3 weeks
Diffstat (limited to 'sys/netinet6/ipcomp_input.c')
-rw-r--r-- | sys/netinet6/ipcomp_input.c | 160 |
1 files changed, 56 insertions, 104 deletions
diff --git a/sys/netinet6/ipcomp_input.c b/sys/netinet6/ipcomp_input.c index da0184c..0a6e2f5 100644 --- a/sys/netinet6/ipcomp_input.c +++ b/sys/netinet6/ipcomp_input.c @@ -1,5 +1,5 @@ /* $FreeBSD$ */ -/* $KAME: ipcomp_input.c,v 1.15 2000/07/03 13:23:28 itojun Exp $ */ +/* $KAME: ipcomp_input.c,v 1.25 2001/03/01 09:12:09 itojun Exp $ */ /* * Copyright (C) 1999 WIDE Project. @@ -95,9 +95,10 @@ ipcomp4_input(m, va_alist) va_dcl #endif { + struct mbuf *md; struct ip *ip; struct ipcomp *ipcomp; - struct ipcomp_algorithm *algo; + const struct ipcomp_algorithm *algo; u_int16_t cpi; /* host order */ u_int16_t nxt; size_t hlen; @@ -112,42 +113,23 @@ ipcomp4_input(m, va_alist) proto = va_arg(ap, int); va_end(ap); - if (off + sizeof(struct ipcomp) > MHLEN) { - /*XXX the restriction should be relaxed*/ + if (m->m_pkthdr.len < off + sizeof(struct ipcomp)) { ipseclog((LOG_DEBUG, "IPv4 IPComp input: assumption failed " - "(header too long)\n")); + "(packet too short)\n")); ipsecstat.in_inval++; goto fail; } - if (m->m_len < off + sizeof(struct ipcomp)) { - m = m_pullup(m, off + sizeof(struct ipcomp)); - if (!m) { - ipseclog((LOG_DEBUG, "IPv4 IPComp input: can't pullup;" - "dropping the packet for simplicity\n")); - ipsecstat.in_nomem++; - goto fail; - } - } else if (m->m_len > off + sizeof(struct ipcomp)) { - /* chop header part from the packet header chain */ - struct mbuf *n; - MGETHDR(n, M_DONTWAIT, MT_HEADER); - if (!n) { - ipsecstat.in_nomem++; - goto fail; - } - M_COPY_PKTHDR(n, m); - MH_ALIGN(n, off + sizeof(struct ipcomp)); - n->m_len = off + sizeof(struct ipcomp); - bcopy(mtod(m, caddr_t), mtod(n, caddr_t), - off + sizeof(struct ipcomp)); - m_adj(m, off + sizeof(struct ipcomp)); - m->m_flags &= ~M_PKTHDR; - n->m_next = m; - m = n; - } + md = m_pulldown(m, off, sizeof(*ipcomp), NULL); + if (!m) { + m = NULL; /*already freed*/ + ipseclog((LOG_DEBUG, "IPv4 IPComp input: assumption failed " + "(pulldown failure)\n")); + ipsecstat.in_inval++; + goto fail; + } + ipcomp = mtod(md, struct ipcomp *); ip = mtod(m, struct ip *); - ipcomp = (struct ipcomp *)(((caddr_t)ip) + off); nxt = ipcomp->comp_nxt; #ifdef _IP_VHL hlen = IP_VHL_HL(ip->ip_vhl) << 2; @@ -167,10 +149,7 @@ ipcomp4_input(m, va_alist) /* other parameters to look at? */ } } - if (cpi < IPCOMP_MAX && ipcomp_algorithms[cpi].decompress != NULL) - algo = &ipcomp_algorithms[cpi]; - else - algo = NULL; + algo = ipcomp_algorithm_lookup(cpi); if (!algo) { ipseclog((LOG_WARNING, "IPv4 IPComp input: unknown cpi %u\n", cpi)); @@ -180,7 +159,8 @@ ipcomp4_input(m, va_alist) /* chop ipcomp header */ ipcomp = NULL; - m->m_len -= sizeof(struct ipcomp); + md->m_data += sizeof(struct ipcomp); + md->m_len -= sizeof(struct ipcomp); m->m_pkthdr.len -= sizeof(struct ipcomp); #ifdef IPLEN_FLIPPED ip->ip_len -= sizeof(struct ipcomp); @@ -237,13 +217,22 @@ ipcomp4_input(m, va_alist) if (sav) { key_sa_recordxfer(sav, m); + if (ipsec_addhist(m, IPPROTO_IPCOMP, (u_int32_t)cpi) != 0) { + ipsecstat.in_nomem++; + goto fail; + } key_freesav(sav); sav = NULL; } - if (nxt != IPPROTO_DONE) + if (nxt != IPPROTO_DONE) { + if ((inetsw[ip_protox[nxt]].pr_flags & PR_LASTHDR) != 0 && + ipsec4_in_reject(m, NULL)) { + ipsecstat.in_polvio++; + goto fail; + } (*inetsw[ip_protox[nxt]].pr_input)(m, off, nxt); - else + } else m_freem(m); m = NULL; @@ -268,66 +257,30 @@ ipcomp6_input(mp, offp, proto) struct mbuf *m, *md; int off; struct ip6_hdr *ip6; - struct mbuf *ipcompm; struct ipcomp *ipcomp; - struct ipcomp_algorithm *algo; + const struct ipcomp_algorithm *algo; u_int16_t cpi; /* host order */ u_int16_t nxt; int error; size_t newlen; struct secasvar *sav = NULL; + char *prvnxtp; m = *mp; off = *offp; - IP6_EXTHDR_CHECK(m, off, sizeof(struct ipcomp), IPPROTO_DONE); - - { - int skip; - struct mbuf *n; - struct mbuf *p, *q; - size_t l; - - skip = off; - for (n = m; n && skip > 0; n = n->m_next) { - if (n->m_len <= skip) { - skip -= n->m_len; - continue; - } - break; - } - if (!n) { - ipseclog((LOG_DEBUG, "IPv6 IPComp input: wrong mbuf chain\n")); - ipsecstat.in_inval++; - goto fail; - } - if (n->m_len < skip + sizeof(struct ipcomp)) { - ipseclog((LOG_DEBUG, "IPv6 IPComp input: wrong mbuf chain\n")); - ipsecstat.in_inval++; + md = m_pulldown(m, off, sizeof(*ipcomp), NULL); + if (!m) { + m = NULL; /*already freed*/ + ipseclog((LOG_DEBUG, "IPv6 IPComp input: assumption failed " + "(pulldown failure)\n")); + ipsec6stat.in_inval++; goto fail; } + ipcomp = mtod(md, struct ipcomp *); ip6 = mtod(m, struct ip6_hdr *); - ipcompm = n; - ipcomp = (struct ipcomp *)(mtod(n, caddr_t) + skip); - if (n->m_len > skip + sizeof(struct ipcomp)) { - /* split mbuf to ease the following steps*/ - l = n->m_len - (skip + sizeof(struct ipcomp)); - p = m_copym(n, skip + sizeof(struct ipcomp), l , M_DONTWAIT); - if (!p) { - ipsecstat.in_nomem++; - goto fail; - } - for (q = p; q && q->m_next; q = q->m_next) - ; - q->m_next = n->m_next; - n->m_next = p; - n->m_len -= l; - md = p; - } else - md = n->m_next; - } - nxt = ipcomp->comp_nxt; + cpi = ntohs(ipcomp->comp_cpi); if (cpi >= IPCOMP_CPI_NEGOTIATE_MIN) { @@ -340,10 +293,7 @@ ipcomp6_input(mp, offp, proto) /* other parameters to look at? */ } } - if (cpi < IPCOMP_MAX && ipcomp_algorithms[cpi].decompress != NULL) - algo = &ipcomp_algorithms[cpi]; - else - algo = NULL; + algo = ipcomp_algorithm_lookup(cpi); if (!algo) { ipseclog((LOG_WARNING, "IPv6 IPComp input: unknown cpi %u; " "dropping the packet for simplicity\n", cpi)); @@ -351,7 +301,13 @@ ipcomp6_input(mp, offp, proto) goto fail; } - newlen = m->m_pkthdr.len - off - sizeof(struct ipcomp); + /* chop ipcomp header */ + ipcomp = NULL; + md->m_data += sizeof(struct ipcomp); + md->m_len -= sizeof(struct ipcomp); + m->m_pkthdr.len -= sizeof(struct ipcomp); + + newlen = m->m_pkthdr.len - off; error = (*algo->decompress)(m, md, &newlen); if (error != 0) { if (error == EINVAL) @@ -362,7 +318,7 @@ ipcomp6_input(mp, offp, proto) goto fail; } ipsec6stat.in_comphist[cpi]++; - m->m_pkthdr.len = off + sizeof(struct ipcomp) + newlen; + m->m_pkthdr.len = off + newlen; /* * returning decompressed packet onto icmp is meaningless. @@ -370,25 +326,21 @@ ipcomp6_input(mp, offp, proto) */ m->m_flags |= M_DECRYPTED; - { - char *prvnxtp; - - /* chop IPComp header */ + /* update next header field */ prvnxtp = ip6_get_prevhdr(m, off); *prvnxtp = nxt; - ipcompm->m_len -= sizeof(struct ipcomp); - ipcompm->m_pkthdr.len -= sizeof(struct ipcomp); - /* adjust payload length */ - ip6 = mtod(m, struct ip6_hdr *); - if (((m->m_pkthdr.len - sizeof(struct ip6_hdr)) & ~0xffff) != 0) - ip6->ip6_plen = 0; /*now a jumbogram*/ - else - ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr)); - } + /* + * no need to adjust payload length, as all the IPv6 protocols + * look at m->m_pkthdr.len + */ if (sav) { key_sa_recordxfer(sav, m); + if (ipsec_addhist(m, IPPROTO_IPCOMP, (u_int32_t)cpi) != 0) { + ipsec6stat.in_nomem++; + goto fail; + } key_freesav(sav); sav = NULL; } |