Page MenuHomeFreeBSD

D42526.diff
No OneTemporary

D42526.diff

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

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)

Event Timeline