Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F109417789
D42526.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
18 KB
Referenced Files
None
Subscribers
None
D42526.diff
View Options
diff --git a/sys/conf/files b/sys/conf/files
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -4430,7 +4430,7 @@
ipsec_support inet | ipsec_support inet6
netipsec/subr_ipsec.c optional ipsec inet | ipsec inet6 | \
ipsec_support inet | ipsec_support inet6
-netipsec/udpencap.c optional ipsec inet
+netipsec/udpencap.c optional ipsec inet | ipsec inet6
netipsec/xform_ah.c optional ipsec inet | ipsec inet6
netipsec/xform_esp.c optional ipsec inet | ipsec inet6
netipsec/xform_ipcomp.c optional ipsec inet | ipsec inet6
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -269,7 +269,7 @@
}
if (up->u_flags & UF_ESPINUDP) {/* IPSec UDP encaps. */
if (IPSEC_ENABLED(ipv4) &&
- UDPENCAP_INPUT(n, off, AF_INET) != 0)
+ UDPENCAP_INPUT(ipv4, n, off, AF_INET) != 0)
return (0); /* Consumed. */
}
#endif /* IPSEC */
@@ -895,19 +895,32 @@
case SOPT_SET:
switch (sopt->sopt_name) {
#if defined(IPSEC) || defined(IPSEC_SUPPORT)
-#ifdef INET
+#if defined(INET) || defined(INET6)
case UDP_ENCAP:
- if (!INP_CHECK_SOCKAF(so, AF_INET)) {
- INP_WUNLOCK(inp);
- return (EINVAL);
- }
- if (!IPSEC_ENABLED(ipv4)) {
- INP_WUNLOCK(inp);
- return (ENOPROTOOPT);
+#ifdef INET
+ if (INP_SOCKAF(so) == AF_INET) {
+ if (!IPSEC_ENABLED(ipv4)) {
+ INP_WUNLOCK(inp);
+ return (ENOPROTOOPT);
+ }
+ error = UDPENCAP_PCBCTL(ipv4, inp, sopt);
+ break;
}
- error = UDPENCAP_PCBCTL(inp, sopt);
- break;
#endif /* INET */
+#ifdef INET6
+ if (INP_SOCKAF(so) == AF_INET6) {
+ if (!IPSEC_ENABLED(ipv6)) {
+ INP_WUNLOCK(inp);
+ return (ENOPROTOOPT);
+ }
+ error = UDPENCAP_PCBCTL(ipv6, inp, sopt);
+ break;
+ }
+#endif /* INET6 */
+ INP_WUNLOCK(inp);
+ return (EINVAL);
+#endif /* INET || INET6 */
+
#endif /* IPSEC */
case UDPLITE_SEND_CSCOV:
case UDPLITE_RECV_CSCOV:
@@ -946,19 +959,32 @@
case SOPT_GET:
switch (sopt->sopt_name) {
#if defined(IPSEC) || defined(IPSEC_SUPPORT)
-#ifdef INET
+#if defined(INET) || defined(INET6)
case UDP_ENCAP:
- if (!INP_CHECK_SOCKAF(so, AF_INET)) {
- INP_WUNLOCK(inp);
- return (EINVAL);
- }
- if (!IPSEC_ENABLED(ipv4)) {
- INP_WUNLOCK(inp);
- return (ENOPROTOOPT);
+#ifdef INET
+ if (INP_SOCKAF(so) == AF_INET) {
+ if (!IPSEC_ENABLED(ipv4)) {
+ INP_WUNLOCK(inp);
+ return (ENOPROTOOPT);
+ }
+ error = UDPENCAP_PCBCTL(ipv4, inp, sopt);
+ break;
}
- error = UDPENCAP_PCBCTL(inp, sopt);
- break;
#endif /* INET */
+#ifdef INET6
+ if (INP_SOCKAF(so) == AF_INET6) {
+ if (!IPSEC_ENABLED(ipv6)) {
+ INP_WUNLOCK(inp);
+ return (ENOPROTOOPT);
+ }
+ error = UDPENCAP_PCBCTL(ipv6, inp, sopt);
+ break;
+ }
+#endif /* INET6 */
+ INP_WUNLOCK(inp);
+ return (EINVAL);
+#endif /* INET || INET6 */
+
#endif /* IPSEC */
case UDPLITE_SEND_CSCOV:
case UDPLITE_RECV_CSCOV:
diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c
--- a/sys/netinet6/udp6_usrreq.c
+++ b/sys/netinet6/udp6_usrreq.c
@@ -77,6 +77,7 @@
#include "opt_rss.h"
#include <sys/param.h>
+#include <sys/domain.h>
#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/lock.h>
@@ -160,6 +161,9 @@
if (filtered)
return (in_pcbrele_rlocked(inp));
}
+
+ off += sizeof(struct udphdr);
+
#if defined(IPSEC) || defined(IPSEC_SUPPORT)
/* Check AH/ESP integrity. */
if (IPSEC_ENABLED(ipv6)) {
@@ -167,6 +171,12 @@
m_freem(n);
return (0);
}
+
+ /* IPSec UDP encaps. */
+ if ((up->u_flags & UF_ESPINUDP) != 0 &&
+ UDPENCAP_INPUT(ipv6, n, off, AF_INET6) != 0) {
+ return (0); /* Consumed. */
+ }
}
#endif /* IPSEC */
#ifdef MAC
@@ -191,7 +201,7 @@
opts = tmp_opts;
}
}
- m_adj(n, off + sizeof(struct udphdr));
+ m_adj(n, off);
so = inp->inp_socket;
SOCKBUF_LOCK(&so->so_rcv);
diff --git a/sys/netipsec/ipsec_input.c b/sys/netipsec/ipsec_input.c
--- a/sys/netipsec/ipsec_input.c
+++ b/sys/netipsec/ipsec_input.c
@@ -628,6 +628,15 @@
m_copydata(m, protoff, 1, &nxt8);
prot = nxt8;
+ /*
+ * Check that we have NAT-T enabled and apply transport mode
+ * decapsulation NAT procedure (RFC3948).
+ * Do this before invoking into the PFIL.
+ */
+ if (sav->natt != NULL &&
+ (prot == IPPROTO_UDP || prot == IPPROTO_TCP))
+ udp_ipsec_adjust_cksum(m, sav, prot, skip);
+
/* IPv6-in-IP encapsulation */
if (prot == IPPROTO_IPV6 &&
saidx->mode != IPSEC_MODE_TRANSPORT) {
diff --git a/sys/netipsec/ipsec_mod.c b/sys/netipsec/ipsec_mod.c
--- a/sys/netipsec/ipsec_mod.c
+++ b/sys/netipsec/ipsec_mod.c
@@ -85,6 +85,8 @@
.check_policy = ipsec6_in_reject,
.ctlinput = ipsec6_ctlinput,
.hdrsize = ipsec_hdrsiz_inpcb,
+ .udp_input = udp_ipsec_input,
+ .udp_pcbctl = udp_ipsec_pcbctl,
};
#ifndef KLD_MODULE
static const struct ipsec_support ipv6_ipsec = {
diff --git a/sys/netipsec/ipsec_output.c b/sys/netipsec/ipsec_output.c
--- a/sys/netipsec/ipsec_output.c
+++ b/sys/netipsec/ipsec_output.c
@@ -935,7 +935,7 @@
}
key_freesp(&sp), sp = NULL; /* Release reference to SP */
-#ifdef INET
+#if defined(INET) || defined(INET6)
/*
* Do UDP encapsulation if SA requires it.
*/
@@ -944,7 +944,7 @@
if (error != 0)
goto bad;
}
-#endif /* INET */
+#endif /* INET || INET6 */
/*
* We're done with IPsec processing, transmit the packet using the
* appropriate network protocol (IP or IPv6).
diff --git a/sys/netipsec/ipsec_support.h b/sys/netipsec/ipsec_support.h
--- a/sys/netipsec/ipsec_support.h
+++ b/sys/netipsec/ipsec_support.h
@@ -164,10 +164,10 @@
#define IPSEC_CTLINPUT(proto, param) \
(*(proto ## _ipsec_support)->methods->ctlinput)(param)
-#define UDPENCAP_INPUT(m, ...) \
- (*ipv4_ipsec_support->methods->udp_input)(m, __VA_ARGS__)
-#define UDPENCAP_PCBCTL(inp, sopt) \
- (*ipv4_ipsec_support->methods->udp_pcbctl)(inp, sopt)
+#define UDPENCAP_INPUT(proto, m, ...) \
+ (*(proto ## _ipsec_support)->methods->udp_input)(m, __VA_ARGS__)
+#define UDPENCAP_PCBCTL(proto, inp, sopt) \
+ (*(proto ## _ipsec_support)->methods->udp_pcbctl)(inp, sopt)
#elif defined(IPSEC_SUPPORT)
struct ipsec_support {
@@ -196,10 +196,10 @@
int ipsec_kmod_udp_pcbctl(struct ipsec_support * const, struct inpcb *,
struct sockopt *);
-#define UDPENCAP_INPUT(m, ...) \
- ipsec_kmod_udp_input(ipv4_ipsec_support, m, __VA_ARGS__)
-#define UDPENCAP_PCBCTL(inp, sopt) \
- ipsec_kmod_udp_pcbctl(ipv4_ipsec_support, inp, sopt)
+#define UDPENCAP_INPUT(proto, m, ...) \
+ ipsec_kmod_udp_input(proto ## _ipsec_support, m, __VA_ARGS__)
+#define UDPENCAP_PCBCTL(proto, inp, sopt) \
+ ipsec_kmod_udp_pcbctl(proto ## _ipsec_support, inp, sopt)
#define IPSEC_INPUT(proto, ...) \
ipsec_kmod_input(proto ## _ipsec_support, __VA_ARGS__)
diff --git a/sys/netipsec/key.c b/sys/netipsec/key.c
--- a/sys/netipsec/key.c
+++ b/sys/netipsec/key.c
@@ -5752,6 +5752,7 @@
struct sockaddr *sa;
uint32_t addr;
uint16_t cksum;
+ int i;
IPSEC_ASSERT(sav->natt == NULL, ("natt is already initialized"));
/*
@@ -5838,52 +5839,117 @@
if (sav->sah->saidx.mode != IPSEC_MODE_TUNNEL) {
cksum = 0;
if (oai != NULL) {
- /* Currently we support only AF_INET */
sa = (struct sockaddr *)(oai + 1);
- if (sa->sa_family != AF_INET ||
- sa->sa_len != sizeof(struct sockaddr_in)) {
+ switch (sa->sa_family) {
+#ifdef AF_INET
+ case AF_INET:
+ if (sa->sa_len != sizeof(struct sockaddr_in)) {
+ ipseclog((LOG_DEBUG,
+ "%s: wrong NAT-OAi header.\n",
+ __func__));
+ return (EINVAL);
+ }
+ /* Ignore address if it the same */
+ if (((struct sockaddr_in *)sa)->sin_addr.s_addr !=
+ sav->sah->saidx.src.sin.sin_addr.s_addr) {
+ bcopy(sa, &sav->natt->oai.sa, sa->sa_len);
+ sav->natt->flags |= IPSEC_NATT_F_OAI;
+ /* Calculate checksum delta */
+ addr = sav->sah->saidx.src.sin.sin_addr.s_addr;
+ cksum = in_addword(cksum, ~addr >> 16);
+ cksum = in_addword(cksum, ~addr & 0xffff);
+ addr = sav->natt->oai.sin.sin_addr.s_addr;
+ cksum = in_addword(cksum, addr >> 16);
+ cksum = in_addword(cksum, addr & 0xffff);
+ }
+ break;
+#endif
+#ifdef AF_INET6
+ case AF_INET6:
+ if (sa->sa_len != sizeof(struct sockaddr_in6)) {
+ ipseclog((LOG_DEBUG,
+ "%s: wrong NAT-OAi header.\n",
+ __func__));
+ return (EINVAL);
+ }
+ /* Ignore address if it the same */
+ if (memcmp(&((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr,
+ &sav->sah->saidx.src.sin6.sin6_addr.s6_addr,
+ sizeof(struct in6_addr)) != 0) {
+ bcopy(sa, &sav->natt->oai.sa, sa->sa_len);
+ sav->natt->flags |= IPSEC_NATT_F_OAI;
+ /* Calculate checksum delta */
+ for (i = 0; i < 8; i++) {
+ cksum = in_addword(cksum,
+ ~sav->sah->saidx.src.sin6.sin6_addr.s6_addr16[i]);
+ cksum = in_addword(cksum,
+ sav->natt->oai.sin6.sin6_addr.s6_addr16[i]);
+ }
+ }
+ break;
+#endif
+ default:
ipseclog((LOG_DEBUG,
"%s: wrong NAT-OAi header.\n",
__func__));
return (EINVAL);
}
- /* Ignore address if it the same */
- if (((struct sockaddr_in *)sa)->sin_addr.s_addr !=
- sav->sah->saidx.src.sin.sin_addr.s_addr) {
- bcopy(sa, &sav->natt->oai.sa, sa->sa_len);
- sav->natt->flags |= IPSEC_NATT_F_OAI;
- /* Calculate checksum delta */
- addr = sav->sah->saidx.src.sin.sin_addr.s_addr;
- cksum = in_addword(cksum, ~addr >> 16);
- cksum = in_addword(cksum, ~addr & 0xffff);
- addr = sav->natt->oai.sin.sin_addr.s_addr;
- cksum = in_addword(cksum, addr >> 16);
- cksum = in_addword(cksum, addr & 0xffff);
- }
}
if (oar != NULL) {
- /* Currently we support only AF_INET */
sa = (struct sockaddr *)(oar + 1);
- if (sa->sa_family != AF_INET ||
- sa->sa_len != sizeof(struct sockaddr_in)) {
+ switch (sa->sa_family) {
+#ifdef AF_INET
+ case AF_INET:
+ if (sa->sa_len != sizeof(struct sockaddr_in)) {
+ ipseclog((LOG_DEBUG,
+ "%s: wrong NAT-OAr header.\n",
+ __func__));
+ return (EINVAL);
+ }
+ /* Ignore address if it the same */
+ if (((struct sockaddr_in *)sa)->sin_addr.s_addr !=
+ sav->sah->saidx.dst.sin.sin_addr.s_addr) {
+ bcopy(sa, &sav->natt->oar.sa, sa->sa_len);
+ sav->natt->flags |= IPSEC_NATT_F_OAR;
+ /* Calculate checksum delta */
+ addr = sav->sah->saidx.dst.sin.sin_addr.s_addr;
+ cksum = in_addword(cksum, ~addr >> 16);
+ cksum = in_addword(cksum, ~addr & 0xffff);
+ addr = sav->natt->oar.sin.sin_addr.s_addr;
+ cksum = in_addword(cksum, addr >> 16);
+ cksum = in_addword(cksum, addr & 0xffff);
+ }
+ break;
+#endif
+#ifdef AF_INET6
+ case AF_INET6:
+ if (sa->sa_len != sizeof(struct sockaddr_in6)) {
+ ipseclog((LOG_DEBUG,
+ "%s: wrong NAT-OAr header.\n",
+ __func__));
+ return (EINVAL);
+ }
+ /* Ignore address if it the same */
+ if (memcmp(&((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr,
+ &sav->sah->saidx.dst.sin6.sin6_addr.s6_addr, 16) != 0) {
+ bcopy(sa, &sav->natt->oar.sa, sa->sa_len);
+ sav->natt->flags |= IPSEC_NATT_F_OAR;
+ /* Calculate checksum delta */
+ for (i = 0; i < 8; i++) {
+ cksum = in_addword(cksum,
+ ~sav->sah->saidx.dst.sin6.sin6_addr.s6_addr16[i]);
+ cksum = in_addword(cksum,
+ sav->natt->oar.sin6.sin6_addr.s6_addr16[i]);
+ }
+ }
+ break;
+#endif
+ default:
ipseclog((LOG_DEBUG,
"%s: wrong NAT-OAr header.\n",
__func__));
return (EINVAL);
}
- /* Ignore address if it the same */
- if (((struct sockaddr_in *)sa)->sin_addr.s_addr !=
- sav->sah->saidx.dst.sin.sin_addr.s_addr) {
- bcopy(sa, &sav->natt->oar.sa, sa->sa_len);
- sav->natt->flags |= IPSEC_NATT_F_OAR;
- /* Calculate checksum delta */
- addr = sav->sah->saidx.dst.sin.sin_addr.s_addr;
- cksum = in_addword(cksum, ~addr >> 16);
- cksum = in_addword(cksum, ~addr & 0xffff);
- addr = sav->natt->oar.sin.sin_addr.s_addr;
- cksum = in_addword(cksum, addr >> 16);
- cksum = in_addword(cksum, addr & 0xffff);
- }
}
sav->natt->cksum = cksum;
}
diff --git a/sys/netipsec/udpencap.c b/sys/netipsec/udpencap.c
--- a/sys/netipsec/udpencap.c
+++ b/sys/netipsec/udpencap.c
@@ -26,6 +26,7 @@
#include <sys/cdefs.h>
#include "opt_inet.h"
+#include "opt_inet6.h"
#include "opt_ipsec.h"
#include <sys/param.h>
@@ -42,11 +43,14 @@
#include <netinet/in_pcb.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
+#include <netinet/ip6.h>
#include <netinet/ip_var.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
+#include <netinet6/ip6_var.h>
+
#include <net/vnet.h>
#include <netipsec/ipsec.h>
@@ -116,7 +120,6 @@
union sockaddr_union dst;
struct secasvar *sav;
struct udphdr *udp;
- struct ip *ip;
uint32_t spi;
int hlen;
@@ -141,7 +144,9 @@
dst.sa.sa_family = af;
switch (af) {
#ifdef INET
- case AF_INET:
+ case AF_INET: {
+ struct ip *ip;
+
dst.sin.sin_len = sizeof(struct sockaddr_in);
ip = mtod(m, struct ip *);
ip->ip_p = IPPROTO_ESP;
@@ -149,11 +154,20 @@
hlen = ip->ip_hl << 2;
dst.sin.sin_addr = ip->ip_dst;
break;
+ }
#endif
#ifdef INET6
- case AF_INET6:
- /* Not yet */
- /* FALLTHROUGH */
+ case AF_INET6: {
+ struct ip6_hdr *ip6;
+
+ dst.sin6.sin6_len = sizeof(struct sockaddr_in6);
+ ip6 = mtod(m, struct ip6_hdr *);
+ ip6->ip6_nxt = IPPROTO_ESP;
+ off = offsetof(struct ip6_hdr, ip6_nxt);
+ hlen = sizeof(struct ip6_hdr);
+ dst.sin6.sin6_addr = ip6->ip6_dst;
+ break;
+ }
#endif
default:
ESPSTAT_INC(esps_nopf);
@@ -192,12 +206,30 @@
* <-skip->
*/
m_striphdr(m, hlen, sizeof(*udp));
+
/*
* We cannot yet update the cksums so clear any h/w cksum flags
* as they are no longer valid.
*/
- if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID)
- m->m_pkthdr.csum_flags &= ~(CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID)
+ m->m_pkthdr.csum_flags &= ~(CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID_IPV6)
+ m->m_pkthdr.csum_flags &= ~(CSUM_DATA_VALID_IPV6 | CSUM_PSEUDO_HDR);
+ break;
+#endif /* INET6 */
+ default:
+ ESPSTAT_INC(esps_nopf);
+ m_freem(m);
+ return (EPFNOSUPPORT);
+ }
+
/*
* We can update ip_len and ip_sum here, but ipsec4_input_cb()
* will do this anyway, so don't touch them here.
@@ -212,16 +244,31 @@
{
struct udphdr *udp;
struct mbuf *n;
- struct ip *ip;
int hlen, off;
IPSEC_ASSERT(sav->natt != NULL, ("UDP encapsulation isn't required."));
- if (sav->sah->saidx.dst.sa.sa_family == AF_INET6)
+ switch (sav->sah->saidx.dst.sa.sa_family) {
+#ifdef INET
+ case AF_INET: {
+ struct ip *ip;
+ ip = mtod(m, struct ip *);
+ hlen = ip->ip_hl << 2;
+ break;
+ }
+#endif
+#ifdef INET6
+ case AF_INET6:
+ KASSERT(ip6->ip6_nxt == IPPROTO_ESP,
+ ("unexpected next header type %d", ip->ip6_nxt));
+ hlen = sizeof(struct ip6_hdr);
+ break;
+#endif
+ default:
+ ESPSTAT_INC(esps_nopf);
return (EAFNOSUPPORT);
+ }
- ip = mtod(m, struct ip *);
- hlen = ip->ip_hl << 2;
n = m_makespace(m, hlen, sizeof(*udp), &off);
if (n == NULL) {
DPRINTF(("%s: m_makespace for udphdr failed\n", __func__));
@@ -234,9 +281,36 @@
udp->uh_sum = 0;
udp->uh_ulen = htons(m->m_pkthdr.len - hlen);
- ip = mtod(m, struct ip *);
- ip->ip_len = htons(m->m_pkthdr.len);
- ip->ip_p = IPPROTO_UDP;
+ switch (sav->sah->saidx.dst.sa.sa_family) {
+#ifdef INET
+ case AF_INET: {
+ struct ip *ip;
+
+ ip = mtod(m, struct ip *);
+ ip->ip_len = htons(m->m_pkthdr.len);
+ ip->ip_p = IPPROTO_UDP;
+ break;
+ }
+#endif
+#ifdef INET6
+ case AF_INET6: {
+ struct ip6_hdr *ip6;
+
+ ip6 = mtod(m, struct ip6_hdr *);
+ ip6->ip6_plen = htons(m->m_pkthdr.len);
+ ip6->ip6_nxt = IPPROTO_UDP;
+ udp->uh_sum = in6_cksum_pseudo(ip6,
+ m->m_pkthdr.len - hlen, ip6->ip6_nxt, 0);
+ m->m_pkthdr.csum_flags = CSUM_UDP_IPV6;
+ m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum);
+ break;
+ }
+#endif
+ default:
+ ESPSTAT_INC(esps_nopf);
+ return (EAFNOSUPPORT);
+ }
+
return (0);
}
@@ -244,7 +318,6 @@
udp_ipsec_adjust_cksum(struct mbuf *m, struct secasvar *sav, int proto,
int skip)
{
- struct ip *ip;
uint16_t cksum, off;
IPSEC_ASSERT(sav->natt != NULL, ("NAT-T isn't required"));
@@ -270,22 +343,67 @@
if (proto == IPPROTO_TCP) {
/* Ignore for TCP. */
m->m_pkthdr.csum_data = 0xffff;
- m->m_pkthdr.csum_flags |= (CSUM_DATA_VALID |
- CSUM_PSEUDO_HDR);
+ switch (sav->sah->saidx.dst.sa.sa_family) {
+#ifdef INET
+ case AF_INET:
+ m->m_pkthdr.csum_flags |= (CSUM_DATA_VALID |
+ CSUM_PSEUDO_HDR);
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ m->m_pkthdr.csum_flags |= (CSUM_DATA_VALID_IPV6 |
+ CSUM_PSEUDO_HDR);
+ break;
+#endif
+ default:
+ break;
+ }
return;
}
cksum = 0; /* Reset for UDP. */
}
m_copyback(m, skip + off, sizeof(cksum), (caddr_t)&cksum);
} else { /* Fully recompute */
- ip = mtod(m, struct ip *);
- cksum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr,
- htons(m->m_pkthdr.len - skip + proto));
- m_copyback(m, skip + off, sizeof(cksum), (caddr_t)&cksum);
- m->m_pkthdr.csum_flags =
- (proto == IPPROTO_UDP) ? CSUM_UDP: CSUM_TCP;
- m->m_pkthdr.csum_data = off;
- in_delayed_cksum(m);
- m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
+ switch (sav->sah->saidx.dst.sa.sa_family) {
+#ifdef INET
+ case AF_INET: {
+ struct ip *ip;
+
+ ip = mtod(m, struct ip *);
+ cksum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr,
+ htons(m->m_pkthdr.len - skip + proto));
+ m_copyback(m, skip + off, sizeof(cksum),
+ (caddr_t)&cksum);
+ m->m_pkthdr.csum_flags =
+ (proto == IPPROTO_UDP) ? CSUM_UDP : CSUM_TCP;
+ m->m_pkthdr.csum_data = off;
+ in_delayed_cksum(m);
+ m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
+ break;
+ }
+#endif
+#ifdef INET6
+ case AF_INET6: {
+ struct ip6_hdr *ip6;
+
+ ip6 = mtod(m, struct ip6_hdr *);
+ cksum = in6_cksum_pseudo(ip6, m->m_pkthdr.len - skip,
+ proto, 0);
+ m_copyback(m, skip + off, sizeof(cksum),
+ (caddr_t)&cksum);
+ m->m_pkthdr.csum_flags =
+ (proto == IPPROTO_UDP) ? CSUM_UDP_IPV6 : CSUM_TCP_IPV6;
+ m->m_pkthdr.csum_data = off;
+ in6_delayed_cksum(m,
+ m->m_pkthdr.len - sizeof(struct ip6_hdr),
+ sizeof(struct ip6_hdr));
+ m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA_IPV6;
+ break;
+ }
+#endif
+ default:
+ break;
+ }
}
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Feb 5, 7:33 PM (20 h, 52 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16479570
Default Alt Text
D42526.diff (18 KB)
Attached To
Mode
D42526: Add UDP encapsulation of ESP in IPv6
Attached
Detach File
Event Timeline
Log In to Comment