summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/ipcomp_input.c
diff options
context:
space:
mode:
authorume <ume@FreeBSD.org>2001-06-11 12:39:29 +0000
committerume <ume@FreeBSD.org>2001-06-11 12:39:29 +0000
commit832f8d224926758a9ae0b23a6b45353e44fbc87a (patch)
treea79fc7ad2b97862c4a404f352f0211ad93a7b5f1 /sys/netinet6/ipcomp_input.c
parent2693854b01a52b0395a91322aa3edf926bddff38 (diff)
downloadFreeBSD-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.c160
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;
}
OpenPOWER on IntegriCloud