summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2000-06-18 05:58:47 +0000
committerJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2000-06-18 05:58:47 +0000
commitb672eae5ccdbbdec72ab25962e2c17e75e416de2 (patch)
tree8bf88859e0ee505d9305c4f5cd822db441b2f72a
parent8b127cfeb8ae891e3242a84ec42bf7b24486e146 (diff)
IPv6 AH/ESP support, inbound side only. tested with KAME.
-rw-r--r--sys/netinet/ip_ipsp.h6
-rw-r--r--sys/netinet/ipsec_input.c89
2 files changed, 68 insertions, 27 deletions
diff --git a/sys/netinet/ip_ipsp.h b/sys/netinet/ip_ipsp.h
index effc3dfef65..4228307df3d 100644
--- a/sys/netinet/ip_ipsp.h
+++ b/sys/netinet/ip_ipsp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ipsp.h,v 1.67 2000/06/06 04:49:29 angelos Exp $ */
+/* $OpenBSD: ip_ipsp.h,v 1.68 2000/06/18 05:58:46 itojun Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -519,7 +519,7 @@ extern int ah4_input_cb __P((struct mbuf *, ...));
#ifdef INET6
extern int ah6_input __P((struct mbuf **, int *, int));
-extern int ah6_input_cb __P((struct mbuf *, int));
+extern int ah6_input_cb __P((struct mbuf *, int, int));
#endif /* INET6 */
/* XF_ESP */
@@ -539,7 +539,7 @@ extern int esp4_input_cb __P((struct mbuf *, ...));
#ifdef INET6
extern int esp6_input __P((struct mbuf **, int *, int));
-extern int esp6_input_cb __P((struct mbuf *, int));
+extern int esp6_input_cb __P((struct mbuf *, int, int));
#endif /* INET6 */
/* XF_TCPSIGNATURE */
diff --git a/sys/netinet/ipsec_input.c b/sys/netinet/ipsec_input.c
index 63045f9a12f..ff0d3c40c7b 100644
--- a/sys/netinet/ipsec_input.c
+++ b/sys/netinet/ipsec_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ipsec_input.c,v 1.24 2000/06/18 00:24:11 angelos Exp $ */
+/* $OpenBSD: ipsec_input.c,v 1.25 2000/06/18 05:58:46 itojun Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -61,8 +61,12 @@
#include <netinet/udp.h>
#ifdef INET6
+#ifndef INET
#include <netinet/in.h>
+#endif
#include <netinet/ip6.h>
+#include <netinet6/ip6_var.h>
+#include <netinet6/ip6protosw.h>
#endif /* INET6 */
#include <netinet/ip_ipsp.h>
@@ -89,6 +93,11 @@ int ipsec_common_input(struct mbuf *, int, int, int, int);
int esp_enable = 0;
int ah_enable = 0;
+#ifdef INET6
+extern struct ip6protosw inet6sw[];
+extern u_char ip6_protox[];
+#endif
+
/*
* ipsec_common_input() gets called when we receive an IPsec-protected packet
* in IPv4 or IPv6. All it does is find the right TDB and call the appropriate
@@ -363,7 +372,7 @@ ipsec_common_input_cb(struct mbuf *m, struct tdb *tdbp, int skip, int protoff)
}
ip6 = mtod(m, struct ip6_hdr *);
- ip6->ip6_plen = htons(m->m_pkthdr.len);
+ ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
/* Save protocol */
m_copydata(m, protoff, 1, (unsigned char *) &prot);
@@ -607,10 +616,10 @@ ipsec_common_input_cb(struct mbuf *m, struct tdb *tdbp, int skip, int protoff)
switch (sproto)
{
case IPPROTO_ESP:
- return esp6_input_cb(m, protoff);
+ return esp6_input_cb(m, skip, protoff);
case IPPROTO_AH:
- return ah6_input_cb(m, protoff);
+ return ah6_input_cb(m, skip, protoff);
default:
DPRINTF(("ipsec_common_input_cb(): unknown/unsupported security protocol %d\n", sproto));
@@ -760,8 +769,15 @@ ah6_input(struct mbuf **mp, int *offp, int proto)
u_int8_t nxt = 0;
int protoff;
- if (*offp == sizeof(struct ip6_hdr))
- protoff = offsetof(struct ip6_hdr, ip6_nxt);
+ if (*offp < sizeof(struct ip6_hdr))
+ {
+ DPRINTF(("ah6_input(): bad offset\n"));
+ return IPPROTO_DONE;
+ }
+ else if (*offp == sizeof(struct ip6_hdr))
+ {
+ protoff = offsetof(struct ip6_hdr, ip6_nxt);
+ }
else
{
/* Chase down the header chain... */
@@ -794,17 +810,44 @@ ah6_input(struct mbuf **mp, int *offp, int proto)
/* IPv6 AH callback */
int
-ah6_input_cb(struct mbuf *mp, int protoff)
+ah6_input_cb(struct mbuf *m, int off, int protoff)
{
- u_int8_t nxt = 0;
+ int nxt;
+ u_int8_t nxt8;
+ int nest = 0;
/* Retrieve new protocol */
- m_copydata(mp, protoff, sizeof(u_int8_t), (caddr_t) &nxt);
+ m_copydata(m, protoff, sizeof(u_int8_t), (caddr_t) &nxt8);
+ nxt = nxt8;
+
+ /*
+ * see the end of ip6_input for this logic.
+ * IPPROTO_IPV[46] case will be processed just like other ones
+ */
+ while (nxt != IPPROTO_DONE) {
+ if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) {
+ ip6stat.ip6s_toomanyhdr++;
+ goto bad;
+ }
+
+ /*
+ * protection against faulty packet - there should be
+ * more sanity checks in header chain processing.
+ */
+ if (m->m_pkthdr.len < off) {
+ ip6stat.ip6s_tooshort++;
+ in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
+ goto bad;
+ }
- /* XXX Requeue -- for now, drop packet */
- m_freem(mp);
+ nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt);
+ }
return 0;
+
+bad:
+ m_freem(m);
+ return EINVAL; /*?*/
}
/* IPv6 ESP wrapper */
@@ -814,8 +857,15 @@ esp6_input(struct mbuf **mp, int *offp, int proto)
u_int8_t nxt = 0;
int protoff;
- if (*offp == sizeof(struct ip6_hdr))
- protoff = offsetof(struct ip6_hdr, ip6_nxt);
+ if (*offp < sizeof(struct ip6_hdr))
+ {
+ DPRINTF(("esp6_input(): bad offset\n"));
+ return IPPROTO_DONE;
+ }
+ else if (*offp == sizeof(struct ip6_hdr))
+ {
+ protoff = offsetof(struct ip6_hdr, ip6_nxt);
+ }
else
{
/* Chase down the header chain... */
@@ -842,23 +892,14 @@ esp6_input(struct mbuf **mp, int *offp, int proto)
protoff += offsetof(struct ip6_ext, ip6e_nxt);
}
- protoff = offsetof(struct ip6_hdr, ip6_nxt);
ipsec_common_input(*mp, *offp, protoff, AF_INET6, proto);
return IPPROTO_DONE;
}
/* IPv6 ESP callback */
int
-esp6_input_cb(struct mbuf *mp, int protoff)
+esp6_input_cb(struct mbuf *m, int skip, int protoff)
{
- u_int8_t nxt = 0;
-
- /* Retrieve new protocol */
- m_copydata(mp, protoff, sizeof(u_int8_t), (caddr_t) &nxt);
-
- /* XXX Requeue -- for now, drop packet */
- m_freem(mp);
-
- return 0;
+ return ah6_input_cb(m, skip, protoff);
}
#endif /* INET6 */