summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/ip6_output.c
diff options
context:
space:
mode:
authorae <ae@FreeBSD.org>2014-11-05 09:23:29 +0000
committerae <ae@FreeBSD.org>2014-11-05 09:23:29 +0000
commit6933957ccb7c9d3685e51d3aae7e3a8ab8d91c8f (patch)
tree4c59a543f83db7eb244721ea9d542127873cf105 /sys/netinet6/ip6_output.c
parentf5ef39c5536cbd1ec407ea4507e695db17fe32c1 (diff)
downloadFreeBSD-src-6933957ccb7c9d3685e51d3aae7e3a8ab8d91c8f.zip
FreeBSD-src-6933957ccb7c9d3685e51d3aae7e3a8ab8d91c8f.tar.gz
MFC r266800 by vanhu:
IPv4-in-IPv6 and IPv6-in-IPv4 IPsec tunnels. For IPv6-in-IPv4, you may need to do the following command on the tunnel interface if it is configured as IPv4 only: ifconfig <interface> inet6 -ifdisabled Code logic inspired from NetBSD. PR: kern/169438 MC r266822 by bz: Use IPv4 statistics in ipsec4_process_packet() rather than the IPv6 version. This also unbreaks the NOINET6 builds after r266800. MFC r268083 by zec: The assumption in ipsec4_process_packet() that the payload may be only IPv4 is wrong, so check the IP version before mangling the payload header. MFC r272394: Do not strip outer header when operating in transport mode. Instead requeue mbuf back to IPv4 protocol handler. If there is one extra IP-IP encapsulation, it will be handled with tunneling interface. And thus proper interface will be exposed into mbuf's rcvif. Also, tcpdump that listens on tunneling interface will see packets in both directions. PR: 194761
Diffstat (limited to 'sys/netinet6/ip6_output.c')
-rw-r--r--sys/netinet6/ip6_output.c178
1 files changed, 7 insertions, 171 deletions
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c
index b1d27d4..fe720ad 100644
--- a/sys/netinet6/ip6_output.c
+++ b/sys/netinet6/ip6_output.c
@@ -184,7 +184,7 @@ static int copypktopts(struct ip6_pktopts *, struct ip6_pktopts *, int);
}\
} while (/*CONSTCOND*/ 0)
-static void
+void
in6_delayed_cksum(struct mbuf *m, uint32_t plen, u_short offset)
{
u_short csum;
@@ -248,15 +248,7 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt,
u_int32_t zone;
struct route_in6 *ro_pmtu = NULL;
int hdrsplit = 0;
- int needipsec = 0;
int sw_csum, tso;
-#ifdef IPSEC
- struct ipsec_output_state state;
- struct ip6_rthdr *rh = NULL;
- int needipsectun = 0;
- int segleft_org = 0;
- struct secpolicy *sp = NULL;
-#endif /* IPSEC */
struct m_tag *fwd_tag = NULL;
ip6 = mtod(m, struct ip6_hdr *);
@@ -298,26 +290,12 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt,
* IPSec checking which handles several cases.
* FAST IPSEC: We re-injected the packet.
*/
- switch(ip6_ipsec_output(&m, inp, &flags, &error, &ifp, &sp))
+ switch(ip6_ipsec_output(&m, inp, &flags, &error, &ifp))
{
case 1: /* Bad packet */
goto freehdrs;
- case -1: /* Do IPSec */
- needipsec = 1;
- /*
- * Do delayed checksums now, as we may send before returning.
- */
- if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) {
- plen = m->m_pkthdr.len - sizeof(*ip6);
- in6_delayed_cksum(m, plen, sizeof(struct ip6_hdr));
- m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA_IPV6;
- }
-#ifdef SCTP
- if (m->m_pkthdr.csum_flags & CSUM_SCTP_IPV6) {
- sctp_delayed_cksum(m, sizeof(struct ip6_hdr));
- m->m_pkthdr.csum_flags &= ~CSUM_SCTP_IPV6;
- }
-#endif
+ case -1: /* IPSec done */
+ goto done;
case 0: /* No IPSec */
default:
break;
@@ -337,15 +315,15 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt,
optlen += exthdrs.ip6e_rthdr->m_len;
unfragpartlen = optlen + sizeof(struct ip6_hdr);
- /* NOTE: we don't add AH/ESP length here. do that later. */
+ /* NOTE: we don't add AH/ESP length here (done in ip6_ipsec_output) */
if (exthdrs.ip6e_dest2)
optlen += exthdrs.ip6e_dest2->m_len;
/*
- * If we need IPsec, or there is at least one extension header,
+ * If there is at least one extension header,
* separate IP6 header from the payload.
*/
- if ((needipsec || optlen) && !hdrsplit) {
+ if (optlen && !hdrsplit) {
if ((error = ip6_splithdr(m, &exthdrs)) != 0) {
m = NULL;
goto freehdrs;
@@ -420,72 +398,6 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt,
MAKE_CHAIN(exthdrs.ip6e_rthdr, mprev, nexthdrp,
IPPROTO_ROUTING);
-#ifdef IPSEC
- if (!needipsec)
- goto skip_ipsec2;
-
- /*
- * pointers after IPsec headers are not valid any more.
- * other pointers need a great care too.
- * (IPsec routines should not mangle mbufs prior to AH/ESP)
- */
- exthdrs.ip6e_dest2 = NULL;
-
- if (exthdrs.ip6e_rthdr) {
- rh = mtod(exthdrs.ip6e_rthdr, struct ip6_rthdr *);
- segleft_org = rh->ip6r_segleft;
- rh->ip6r_segleft = 0;
- }
-
- bzero(&state, sizeof(state));
- state.m = m;
- error = ipsec6_output_trans(&state, nexthdrp, mprev, sp, flags,
- &needipsectun);
- m = state.m;
- if (error == EJUSTRETURN) {
- /*
- * We had a SP with a level of 'use' and no SA. We
- * will just continue to process the packet without
- * IPsec processing.
- */
- ;
- } else if (error) {
- /* mbuf is already reclaimed in ipsec6_output_trans. */
- m = NULL;
- switch (error) {
- case EHOSTUNREACH:
- case ENETUNREACH:
- case EMSGSIZE:
- case ENOBUFS:
- case ENOMEM:
- break;
- default:
- printf("[%s:%d] (ipsec): error code %d\n",
- __func__, __LINE__, error);
- /* FALLTHROUGH */
- case ENOENT:
- /* don't show these error codes to the user */
- error = 0;
- break;
- }
- goto bad;
- } else if (!needipsectun) {
- /*
- * In the FAST IPSec case we have already
- * re-injected the packet and it has been freed
- * by the ipsec_done() function. So, just clean
- * up after ourselves.
- */
- m = NULL;
- goto done;
- }
- if (exthdrs.ip6e_rthdr) {
- /* ah6_output doesn't modify mbuf chain */
- rh->ip6r_segleft = segleft_org;
- }
-skip_ipsec2:;
-#endif /* IPSEC */
-
/*
* If there is a routing header, discard the packet.
*/
@@ -551,77 +463,6 @@ again:
ip6->ip6_hlim = V_ip6_defmcasthlim;
}
-#ifdef IPSEC
- /*
- * We may re-inject packets into the stack here.
- */
- if (needipsec && needipsectun) {
- struct ipsec_output_state state;
-
- /*
- * All the extension headers will become inaccessible
- * (since they can be encrypted).
- * Don't panic, we need no more updates to extension headers
- * on inner IPv6 packet (since they are now encapsulated).
- *
- * IPv6 [ESP|AH] IPv6 [extension headers] payload
- */
- bzero(&exthdrs, sizeof(exthdrs));
- exthdrs.ip6e_ip6 = m;
-
- bzero(&state, sizeof(state));
- state.m = m;
- state.ro = (struct route *)ro;
- state.dst = (struct sockaddr *)dst;
-
- error = ipsec6_output_tunnel(&state, sp, flags);
-
- m = state.m;
- ro = (struct route_in6 *)state.ro;
- dst = (struct sockaddr_in6 *)state.dst;
- if (error == EJUSTRETURN) {
- /*
- * We had a SP with a level of 'use' and no SA. We
- * will just continue to process the packet without
- * IPsec processing.
- */
- ;
- } else if (error) {
- /* mbuf is already reclaimed in ipsec6_output_tunnel. */
- m0 = m = NULL;
- m = NULL;
- switch (error) {
- case EHOSTUNREACH:
- case ENETUNREACH:
- case EMSGSIZE:
- case ENOBUFS:
- case ENOMEM:
- break;
- default:
- printf("[%s:%d] (ipsec): error code %d\n",
- __func__, __LINE__, error);
- /* FALLTHROUGH */
- case ENOENT:
- /* don't show these error codes to the user */
- error = 0;
- break;
- }
- goto bad;
- } else {
- /*
- * In the FAST IPSec case we have already
- * re-injected the packet and it has been freed
- * by the ipsec_done() function. So, just clean
- * up after ourselves.
- */
- m = NULL;
- goto done;
- }
-
- exthdrs.ip6e_ip6 = m;
- }
-#endif /* IPSEC */
-
/* adjust pointer */
ip6 = mtod(m, struct ip6_hdr *);
@@ -1182,11 +1023,6 @@ done:
RO_RTFREE(ro);
if (ro_pmtu == &ip6route)
RO_RTFREE(ro_pmtu);
-#ifdef IPSEC
- if (sp != NULL)
- KEY_FREESP(&sp);
-#endif
-
return (error);
freehdrs:
OpenPOWER on IntegriCloud