diff options
author | ume <ume@FreeBSD.org> | 2001-10-17 13:03:37 +0000 |
---|---|---|
committer | ume <ume@FreeBSD.org> | 2001-10-17 13:03:37 +0000 |
commit | 737d8ec1500304779377273b905a619d16e0b6ae (patch) | |
tree | 11a7590290049346bb42b6178d7cb755b66b2a69 /sys/netinet6/ipsec.c | |
parent | b44023b126535b8854d9ccdc4d6969ed312fb1f8 (diff) | |
download | FreeBSD-src-737d8ec1500304779377273b905a619d16e0b6ae.zip FreeBSD-src-737d8ec1500304779377273b905a619d16e0b6ae.tar.gz |
Fixed to process a IPv6 packet when ah transport after esp tunnel
should be applied. the SA of AH transport could not be selected
from the SAD because of this bug.
Obtained from: KAME
MFC after: 1 week
Diffstat (limited to 'sys/netinet6/ipsec.c')
-rw-r--r-- | sys/netinet6/ipsec.c | 45 |
1 files changed, 42 insertions, 3 deletions
diff --git a/sys/netinet6/ipsec.c b/sys/netinet6/ipsec.c index 3cb835d..6f4bd7d 100644 --- a/sys/netinet6/ipsec.c +++ b/sys/netinet6/ipsec.c @@ -2902,9 +2902,48 @@ ipsec6_output_tunnel(state, sp, flags) break; } - for (/*already initialized*/; isr; isr = isr->next) { - /* When tunnel mode, SA peers must be specified. */ - bcopy(&isr->saidx, &saidx, sizeof(saidx)); + for (/* already initialized */; isr; isr = isr->next) { + if (isr->saidx.mode == IPSEC_MODE_TUNNEL) { + /* When tunnel mode, SA peers must be specified. */ + bcopy(&isr->saidx, &saidx, sizeof(saidx)); + } else { + /* make SA index to look for a proper SA */ + struct sockaddr_in6 *sin6; + + bzero(&saidx, sizeof(saidx)); + saidx.proto = isr->saidx.proto; + saidx.mode = isr->saidx.mode; + saidx.reqid = isr->saidx.reqid; + + ip6 = mtod(state->m, struct ip6_hdr *); + sin6 = (struct sockaddr_in6 *)&saidx.src; + if (sin6->sin6_len == 0) { + sin6->sin6_len = sizeof(*sin6); + sin6->sin6_family = AF_INET6; + sin6->sin6_port = IPSEC_PORT_ANY; + bcopy(&ip6->ip6_src, &sin6->sin6_addr, + sizeof(ip6->ip6_src)); + if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) { + /* fix scope id for comparing SPD */ + sin6->sin6_addr.s6_addr16[1] = 0; + sin6->sin6_scope_id = ntohs(ip6->ip6_src.s6_addr16[1]); + } + } + sin6 = (struct sockaddr_in6 *)&saidx.dst; + if (sin6->sin6_len == 0) { + sin6->sin6_len = sizeof(*sin6); + sin6->sin6_family = AF_INET6; + sin6->sin6_port = IPSEC_PORT_ANY; + bcopy(&ip6->ip6_dst, &sin6->sin6_addr, + sizeof(ip6->ip6_dst)); + if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) { + /* fix scope id for comparing SPD */ + sin6->sin6_addr.s6_addr16[1] = 0; + sin6->sin6_scope_id = ntohs(ip6->ip6_dst.s6_addr16[1]); + } + } + } + if (key_checkrequest(isr, &saidx) == ENOENT) { /* * IPsec processing is required, but no SA found. |