summaryrefslogtreecommitdiffstats
path: root/sys/netipsec/ipsec_output.c
diff options
context:
space:
mode:
authorvanhu <vanhu@FreeBSD.org>2009-06-12 15:44:35 +0000
committervanhu <vanhu@FreeBSD.org>2009-06-12 15:44:35 +0000
commit16c1346b9a6c737fd054d4d0644bf5104fcb32aa (patch)
treee75e977677e2ddd8c5e3a47752c3693ea92b15e3 /sys/netipsec/ipsec_output.c
parent76ddf574294a7a39ca62f55ea127233303bcf29e (diff)
downloadFreeBSD-src-16c1346b9a6c737fd054d4d0644bf5104fcb32aa.zip
FreeBSD-src-16c1346b9a6c737fd054d4d0644bf5104fcb32aa.tar.gz
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele (julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense team, and all people who used / tried the NAT-T patch for years and reported bugs, patches, etc... X-MFC: never Reviewed by: bz Approved by: gnn(mentor) Obtained from: NETASQ
Diffstat (limited to 'sys/netipsec/ipsec_output.c')
-rw-r--r--sys/netipsec/ipsec_output.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/sys/netipsec/ipsec_output.c b/sys/netipsec/ipsec_output.c
index ec6b41e..b953786 100644
--- a/sys/netipsec/ipsec_output.c
+++ b/sys/netipsec/ipsec_output.c
@@ -84,6 +84,10 @@
#include <machine/in_cksum.h>
+#ifdef IPSEC_NAT_T
+#include <netinet/udp.h>
+#endif
+
#ifdef DEV_ENC
#include <net/if_enc.h>
#endif
@@ -180,6 +184,57 @@ ipsec_process_done(struct mbuf *m, struct ipsecrequest *isr)
ip->ip_len = ntohs(ip->ip_len);
ip->ip_off = ntohs(ip->ip_off);
+#ifdef IPSEC_NAT_T
+ /*
+ * If NAT-T is enabled, now that all IPsec processing is done
+ * insert UDP encapsulation header after IP header.
+ */
+ if (sav->natt_type) {
+#ifdef _IP_VHL
+ const int hlen = IP_VHL_HL(ip->ip_vhl);
+#else
+ const int hlen = (ip->ip_hl << 2);
+#endif
+ int size, off;
+ struct mbuf *mi;
+ struct udphdr *udp;
+
+ size = sizeof(struct udphdr);
+ if (sav->natt_type == UDP_ENCAP_ESPINUDP_NON_IKE) {
+ /*
+ * draft-ietf-ipsec-nat-t-ike-0[01].txt and
+ * draft-ietf-ipsec-udp-encaps-(00/)01.txt,
+ * ignoring possible AH mode
+ * non-IKE marker + non-ESP marker
+ * from draft-ietf-ipsec-udp-encaps-00.txt.
+ */
+ size += sizeof(u_int64_t);
+ }
+ mi = m_makespace(m, hlen, size, &off);
+ if (mi == NULL) {
+ DPRINTF(("%s: m_makespace for udphdr failed\n",
+ __func__));
+ error = ENOBUFS;
+ goto bad;
+ }
+
+ udp = (struct udphdr *)(mtod(mi, caddr_t) + off);
+ if (sav->natt_type == UDP_ENCAP_ESPINUDP_NON_IKE)
+ udp->uh_sport = htons(UDP_ENCAP_ESPINUDP_PORT);
+ else
+ udp->uh_sport =
+ KEY_PORTFROMSADDR(&sav->sah->saidx.src);
+ udp->uh_dport = KEY_PORTFROMSADDR(&sav->sah->saidx.dst);
+ udp->uh_sum = 0;
+ udp->uh_ulen = htons(m->m_pkthdr.len - hlen);
+ ip->ip_len = m->m_pkthdr.len;
+ ip->ip_p = IPPROTO_UDP;
+
+ if (sav->natt_type == UDP_ENCAP_ESPINUDP_NON_IKE)
+ *(u_int64_t *)(udp + 1) = 0;
+ }
+#endif /* IPSEC_NAT_T */
+
return ip_output(m, NULL, NULL, IP_RAWOUTPUT, NULL, NULL);
#endif /* INET */
#ifdef INET6
OpenPOWER on IntegriCloud