Page MenuHomeFreeBSD

D22444.id71994.diff
No OneTemporary

D22444.id71994.diff

Index: sys/conf/files
===================================================================
--- sys/conf/files
+++ sys/conf/files
@@ -4356,7 +4356,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
Index: sys/netinet/udp_usrreq.c
===================================================================
--- sys/netinet/udp_usrreq.c
+++ sys/netinet/udp_usrreq.c
@@ -332,7 +332,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 */
@@ -1005,7 +1005,7 @@
INP_WUNLOCK(inp);
return (ENOPROTOOPT);
}
- error = UDPENCAP_PCBCTL(inp, sopt);
+ error = UDPENCAP_PCBCTL(ipv4, inp, sopt);
break;
#endif /* INET */
#endif /* IPSEC */
@@ -1052,7 +1052,7 @@
INP_WUNLOCK(inp);
return (ENOPROTOOPT);
}
- error = UDPENCAP_PCBCTL(inp, sopt);
+ error = UDPENCAP_PCBCTL(ipv4, inp, sopt);
break;
#endif /* INET */
#endif /* IPSEC */
Index: sys/netinet6/in6_proto.c
===================================================================
--- sys/netinet6/in6_proto.c
+++ sys/netinet6/in6_proto.c
@@ -158,7 +158,7 @@
.pr_flags = PR_ATOMIC|PR_ADDR,
.pr_input = udp6_input,
.pr_ctlinput = udp6_ctlinput,
- .pr_ctloutput = ip6_ctloutput,
+ .pr_ctloutput = udp6_ctloutput,
#ifndef INET /* Do not call initialization twice. */
.pr_init = udp_init,
#endif
Index: sys/netinet6/udp6_usrreq.c
===================================================================
--- sys/netinet6/udp6_usrreq.c
+++ sys/netinet6/udp6_usrreq.c
@@ -78,6 +78,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>
@@ -154,6 +155,9 @@
INP_RLOCK(inp);
return (in_pcbrele_rlocked(inp));
}
+
+ off += sizeof(struct udphdr);
+
#if defined(IPSEC) || defined(IPSEC_SUPPORT)
/* Check AH/ESP integrity. */
if (IPSEC_ENABLED(ipv6)) {
@@ -162,6 +166,11 @@
return (0);
}
}
+ if (up->u_flags & UF_ESPINUDP) {/* IPSec UDP encaps. */
+ if (IPSEC_ENABLED(ipv6) &&
+ UDPENCAP_INPUT(ipv6, n, off, AF_INET6) != 0)
+ return (0); /* Consumed. */
+ }
#endif /* IPSEC */
#ifdef MAC
if (mac_inpcb_check_deliver(inp, n) != 0) {
@@ -185,7 +194,7 @@
}
}
- m_adj(n, off + sizeof(struct udphdr));
+ m_adj(n, off);
so = inp->inp_socket;
SOCKBUF_LOCK(&so->so_rcv);
@@ -687,6 +696,78 @@
0, 0, udp6_getcred, "S,xucred",
"Get the xucred of a UDP6 connection");
+int
+udp6_ctloutput(struct socket *so, struct sockopt *sopt)
+{
+ struct inpcb *inp;
+ int error;
+
+ error = 0;
+ inp = sotoinpcb(so);
+ KASSERT(inp != NULL, ("%s: inp == NULL", __func__));
+ INP_WLOCK(inp);
+ if (sopt->sopt_level != so->so_proto->pr_protocol) {
+#ifdef INET6
+ if (INP_CHECK_SOCKAF(so, AF_INET6)) {
+ INP_WUNLOCK(inp);
+ error = ip6_ctloutput(so, sopt);
+ }
+#endif
+#if defined(INET) && defined(INET6)
+ else
+#endif
+#ifdef INET
+ {
+ INP_WUNLOCK(inp);
+ error = ip_ctloutput(so, sopt);
+ }
+#endif
+ return (error);
+ }
+
+ switch (sopt->sopt_dir) {
+ case SOPT_SET:
+ switch (sopt->sopt_name) {
+#if defined(IPSEC) || defined(IPSEC_SUPPORT)
+#ifdef INET6
+ case UDP_ENCAP:
+ if (!IPSEC_ENABLED(ipv6)) {
+ INP_WUNLOCK(inp);
+ return (ENOPROTOOPT);
+ }
+ error = UDPENCAP_PCBCTL(ipv6, inp, sopt);
+ break;
+#endif /* INET */
+#endif /* IPSEC */
+ default:
+ INP_WUNLOCK(inp);
+ error = ENOPROTOOPT;
+ break;
+ }
+ break;
+ case SOPT_GET:
+ switch (sopt->sopt_name) {
+#if defined(IPSEC) || defined(IPSEC_SUPPORT)
+#ifdef INET6
+ case UDP_ENCAP:
+ if (!IPSEC_ENABLED(ipv6)) {
+ INP_WUNLOCK(inp);
+ return (ENOPROTOOPT);
+ }
+ error = UDPENCAP_PCBCTL(ipv6, inp, sopt);
+ break;
+#endif /* INET6 */
+#endif /* IPSEC */
+ default:
+ INP_WUNLOCK(inp);
+ error = ENOPROTOOPT;
+ break;
+ }
+ break;
+ }
+ return (error);
+}
+
static int
udp6_output(struct socket *so, int flags_arg, struct mbuf *m,
struct sockaddr *addr6, struct mbuf *control, struct thread *td)
Index: sys/netinet6/udp6_var.h
===================================================================
--- sys/netinet6/udp6_var.h
+++ sys/netinet6/udp6_var.h
@@ -72,6 +72,7 @@
void udp6_ctlinput(int, struct sockaddr *, void *);
void udplite6_ctlinput(int, struct sockaddr *, void *);
+int udp6_ctloutput(struct socket *, struct sockopt *);
int udp6_input(struct mbuf **, int *, int);
#endif
Index: sys/netipsec/ipsec_input.c
===================================================================
--- sys/netipsec/ipsec_input.c
+++ sys/netipsec/ipsec_input.c
@@ -533,6 +533,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) {
Index: sys/netipsec/ipsec_mod.c
===================================================================
--- sys/netipsec/ipsec_mod.c
+++ sys/netipsec/ipsec_mod.c
@@ -85,6 +85,8 @@
.capability = ipsec6_capability,
.check_policy = ipsec6_in_reject,
.hdrsize = ipsec_hdrsiz_inpcb,
+ .udp_input = udp_ipsec_input,
+ .udp_pcbctl = udp_ipsec_pcbctl,
};
#ifndef KLD_MODULE
static const struct ipsec_support ipv6_ipsec = {
Index: sys/netipsec/ipsec_output.c
===================================================================
--- sys/netipsec/ipsec_output.c
+++ sys/netipsec/ipsec_output.c
@@ -775,7 +775,6 @@
}
key_freesp(&sp), sp = NULL; /* Release reference to SP */
-#ifdef INET
/*
* Do UDP encapsulation if SA requires it.
*/
@@ -784,7 +783,6 @@
if (error != 0)
goto bad;
}
-#endif /* INET */
/*
* We're done with IPsec processing, transmit the packet using the
* appropriate network protocol (IP or IPv6).
Index: sys/netipsec/ipsec_support.h
===================================================================
--- sys/netipsec/ipsec_support.h
+++ sys/netipsec/ipsec_support.h
@@ -135,10 +135,10 @@
#define IPSEC_HDRSIZE(proto, inp) \
(*(proto ## _ipsec_support)->methods->hdrsize)(inp)
-#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 {
@@ -166,10 +166,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__)
Index: sys/netipsec/key.c
===================================================================
--- sys/netipsec/key.c
+++ sys/netipsec/key.c
@@ -5705,6 +5705,7 @@
struct sockaddr *sa;
uint32_t addr;
uint16_t cksum;
+ int i;
IPSEC_ASSERT(sav->natt == NULL, ("natt is already initialized"));
/*
@@ -5791,51 +5792,113 @@
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)) {
- 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);
+ 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, 16) != 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);
}
}
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)) {
- 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);
+ 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);
}
}
sav->natt->cksum = cksum;
Index: sys/netipsec/udpencap.c
===================================================================
--- sys/netipsec/udpencap.c
+++ sys/netipsec/udpencap.c
@@ -28,6 +28,7 @@
__FBSDID("$FreeBSD$");
#include "opt_inet.h"
+#include "opt_inet6.h"
#include "opt_ipsec.h"
#include <sys/param.h>
@@ -44,11 +45,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>
@@ -118,7 +122,6 @@
union sockaddr_union dst;
struct secasvar *sav;
struct udphdr *udp;
- struct ip *ip;
uint32_t spi;
int hlen;
@@ -143,7 +146,8 @@
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;
@@ -151,11 +155,19 @@
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);
@@ -198,8 +210,24 @@
* 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.
@@ -214,16 +242,30 @@
{
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)
- return (EAFNOSUPPORT);
+ 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:
+ 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__));
@@ -236,9 +278,34 @@
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);
}
@@ -246,7 +313,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"));
@@ -272,23 +338,63 @@
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
Thu, Apr 2, 9:43 PM (14 h, 46 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30737190
Default Alt Text
D22444.id71994.diff (19 KB)

Event Timeline