diff options
author | vanhu <vanhu@FreeBSD.org> | 2009-06-12 15:44:35 +0000 |
---|---|---|
committer | vanhu <vanhu@FreeBSD.org> | 2009-06-12 15:44:35 +0000 |
commit | 16c1346b9a6c737fd054d4d0644bf5104fcb32aa (patch) | |
tree | e75e977677e2ddd8c5e3a47752c3693ea92b15e3 /sys/netipsec/ipsec_output.c | |
parent | 76ddf574294a7a39ca62f55ea127233303bcf29e (diff) | |
download | FreeBSD-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.c | 55 |
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 |