Page MenuHomeFreeBSD

D22444.1783844671.diff
No OneTemporary

Size
10 KB
Referenced Files
None
Subscribers
None

D22444.1783844671.diff

Index: sys/netinet6/in6_proto.c
===================================================================
--- sys/netinet6/in6_proto.c
+++ sys/netinet6/in6_proto.c
@@ -161,7 +161,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(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);
@@ -684,6 +693,78 @@
SYSCTL_PROC(_net_inet6_udp6, OID_AUTO, getcred, CTLTYPE_OPAQUE|CTLFLAG_RW, 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(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(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,7 @@
}
key_freesp(&sp), sp = NULL; /* Release reference to SP */
-#ifdef INET
+#if defined(INET) || defined(INET6)
/*
* Do UDP encapsulation if SA requires it.
*/
@@ -784,7 +784,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).
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>
@@ -117,6 +121,7 @@
{
union sockaddr_union dst;
struct secasvar *sav;
+ struct ip6_hdr *ip6;
struct udphdr *udp;
struct ip *ip;
uint32_t spi;
@@ -154,8 +159,13 @@
#endif
#ifdef INET6
case AF_INET6:
- /* Not yet */
- /* FALLTHROUGH */
+ 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 +208,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.
@@ -212,6 +238,7 @@
int
udp_ipsec_output(struct mbuf *m, struct secasvar *sav)
{
+ struct ip6_hdr *ip6;
struct udphdr *udp;
struct mbuf *n;
struct ip *ip;
@@ -219,11 +246,25 @@
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:
+ ip = mtod(m, struct ip *);
+ hlen = ip->ip_hl << 2;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ ip6 = mtod(m, struct ip6_hdr *);
+ 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 +277,30 @@
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:
+ 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:
+ 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,6 +308,7 @@
udp_ipsec_adjust_cksum(struct mbuf *m, struct secasvar *sav, int proto,
int skip)
{
+ struct ip6_hdr *ip6;
struct ip *ip;
uint16_t cksum, off;
@@ -272,23 +335,59 @@
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:
+ 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:
+ 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
Sun, Jul 12, 8:24 AM (5 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29091331
Default Alt Text
D22444.1783844671.diff (10 KB)

Event Timeline