summaryrefslogtreecommitdiff
path: root/sys/netinet/ip_ah.c
diff options
context:
space:
mode:
authorJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2007-02-08 15:25:31 +0000
committerJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2007-02-08 15:25:31 +0000
commit0a289dde6d7a0ac669dbd63759e45050b4113552 (patch)
treec9292255327902271e8501ccb3fe895d00cce4a3 /sys/netinet/ip_ah.c
parent84d3708bda21c7bfce2c56744285d7ed3afeec9a (diff)
- AH: when computing crypto checksum for output, massage source-routing
header. - ipsec_input: fix mistake in IPv6 next-header chasing. - ipsec_output: look for the position to insert AH more carefully. - ip6_output: enable use of AH with extension headers. avoid tunnellinng when source-routing header is present. ok by deraad, naddy, hshoexer
Diffstat (limited to 'sys/netinet/ip_ah.c')
-rw-r--r--sys/netinet/ip_ah.c68
1 files changed, 54 insertions, 14 deletions
diff --git a/sys/netinet/ip_ah.c b/sys/netinet/ip_ah.c
index 88e5f09e09c..85d8fd0c245 100644
--- a/sys/netinet/ip_ah.c
+++ b/sys/netinet/ip_ah.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ah.c,v 1.87 2006/12/15 09:32:30 otto Exp $ */
+/* $OpenBSD: ip_ah.c,v 1.88 2007/02/08 15:25:30 itojun Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr) and
@@ -206,7 +206,7 @@ ah_massage_headers(struct mbuf **m0, int proto, int skip, int alg, int out)
#ifdef INET6
struct ip6_ext *ip6e;
struct ip6_hdr ip6;
- int alloc, len, ad;
+ int ad, alloc, nxt;
#endif /* INET6 */
switch (proto) {
@@ -401,28 +401,28 @@ ah_massage_headers(struct mbuf **m0, int proto, int skip, int alg, int out)
} else
break;
- off = ip6.ip6_nxt & 0xff; /* Next header type. */
+ nxt = ip6.ip6_nxt & 0xff; /* Next header type. */
- for (len = 0; len < skip - sizeof(struct ip6_hdr);)
- switch (off) {
+ for (off = 0; off < skip - sizeof(struct ip6_hdr);) {
+ switch (nxt) {
case IPPROTO_HOPOPTS:
case IPPROTO_DSTOPTS:
- ip6e = (struct ip6_ext *) (ptr + len);
+ ip6e = (struct ip6_ext *) (ptr + off);
/*
* Process the mutable/immutable
* options -- borrows heavily from the
* KAME code.
*/
- for (count = len + sizeof(struct ip6_ext);
- count < len + ((ip6e->ip6e_len + 1) << 3);) {
+ for (count = off + sizeof(struct ip6_ext);
+ count < off + ((ip6e->ip6e_len + 1) << 3);) {
if (ptr[count] == IP6OPT_PAD1) {
count++;
continue; /* Skip padding. */
}
/* Sanity check. */
- if (count > len +
+ if (count > off +
((ip6e->ip6e_len + 1) << 3)) {
ahstat.ahs_hdrops++;
m_freem(m);
@@ -456,8 +456,8 @@ ah_massage_headers(struct mbuf **m0, int proto, int skip, int alg, int out)
}
/* Advance. */
- len += ((ip6e->ip6e_len + 1) << 3);
- off = ip6e->ip6e_nxt;
+ off += ((ip6e->ip6e_len + 1) << 3);
+ nxt = ip6e->ip6e_nxt;
break;
case IPPROTO_ROUTING:
@@ -465,10 +465,49 @@ ah_massage_headers(struct mbuf **m0, int proto, int skip, int alg, int out)
* Always include routing headers in
* computation.
*/
- ip6e = (struct ip6_ext *) (ptr + len);
- len += ((ip6e->ip6e_len + 1) << 3);
- off = ip6e->ip6e_nxt;
+ {
+ struct ip6_rthdr *rh;
+
+ ip6e = (struct ip6_ext *) (ptr + off);
+ rh = (struct ip6_rthdr *)(ptr + off);
+ /*
+ * must adjust content to make it look like
+ * its final form (as seen at the final
+ * destination).
+ * we only know how to massage type 0 routing
+ * header.
+ */
+ if (out && rh->ip6r_type == IPV6_RTHDR_TYPE_0) {
+ struct ip6_rthdr0 *rh0;
+ struct in6_addr *addr, finaldst;
+ int i;
+
+ rh0 = (struct ip6_rthdr0 *)rh;
+ addr = (struct in6_addr *)(rh0 + 1);
+
+ for (i = 0; i < rh0->ip6r0_segleft; i++)
+ if (IN6_IS_SCOPE_EMBED(&addr[i]))
+ addr[i].s6_addr16[1] = 0;
+
+ finaldst = addr[rh0->ip6r0_segleft - 1];
+ ovbcopy(&addr[0], &addr[1],
+ sizeof(struct in6_addr) *
+ (rh0->ip6r0_segleft - 1));
+
+ m_copydata(m, 0, sizeof(ip6),
+ (caddr_t)&ip6);
+ addr[0] = ip6.ip6_dst;
+ ip6.ip6_dst = finaldst;
+ m_copyback(m, 0, sizeof(ip6), &ip6);
+
+ rh0->ip6r0_segleft = 0;
+ }
+
+ /* advance */
+ off += ((ip6e->ip6e_len + 1) << 3);
+ nxt = ip6e->ip6e_nxt;
break;
+ }
default:
DPRINTF(("ah_massage_headers(): unexpected "
@@ -479,6 +518,7 @@ ah_massage_headers(struct mbuf **m0, int proto, int skip, int alg, int out)
m_freem(m);
return EINVAL;
}
+ }
/* Copyback and free, if we allocated. */
if (alloc) {