diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-10-07 15:10:20 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2017-01-10 09:53:31 +0100 |
commit | c40e45b75eb76d79a05c7fa85c1fa9b5c728a12f (patch) | |
tree | ad4f2519067709f00ab98b3c591186c26dc3a21f /freebsd/sys/netinet6/ip6_forward.c | |
parent | userspace-header-gen.py: Simplify program ports (diff) | |
download | rtems-libbsd-c40e45b75eb76d79a05c7fa85c1fa9b5c728a12f.tar.bz2 |
Update to FreeBSD head 2016-08-23
Git mirror commit 9fe7c416e6abb28b1398fd3e5687099846800cfd.
Diffstat (limited to 'freebsd/sys/netinet6/ip6_forward.c')
-rw-r--r-- | freebsd/sys/netinet6/ip6_forward.c | 216 |
1 files changed, 82 insertions, 134 deletions
diff --git a/freebsd/sys/netinet6/ip6_forward.c b/freebsd/sys/netinet6/ip6_forward.c index 6efae91a..50583537 100644 --- a/freebsd/sys/netinet6/ip6_forward.c +++ b/freebsd/sys/netinet6/ip6_forward.c @@ -36,7 +36,6 @@ __FBSDID("$FreeBSD$"); #include <rtems/bsd/local/opt_inet.h> #include <rtems/bsd/local/opt_inet6.h> -#include <rtems/bsd/local/opt_ipfw.h> #include <rtems/bsd/local/opt_ipsec.h> #include <rtems/bsd/local/opt_ipstealth.h> @@ -53,6 +52,7 @@ __FBSDID("$FreeBSD$"); #include <sys/syslog.h> #include <net/if.h> +#include <net/if_var.h> #include <net/netisr.h> #include <net/route.h> #include <net/pfil.h> @@ -72,13 +72,12 @@ __FBSDID("$FreeBSD$"); #include <netinet/in_pcb.h> #ifdef IPSEC +#include <netinet6/ip6_ipsec.h> #include <netipsec/ipsec.h> #include <netipsec/ipsec6.h> #include <netipsec/key.h> #endif /* IPSEC */ -#include <netinet6/ip6protosw.h> - /* * Forward a packet. If some error occurs return the sender * an icmp packet. Note we can't always generate a meaningful @@ -105,29 +104,10 @@ ip6_forward(struct mbuf *m, int srcrt) struct in6_addr src_in6, dst_in6, odst; #ifdef IPSEC struct secpolicy *sp = NULL; - int ipsecrt = 0; -#endif -#ifdef SCTP - int sw_csum; #endif struct m_tag *fwd_tag; char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN]; -#ifdef IPSEC - /* - * Check AH/ESP integrity. - */ - /* - * Don't increment ip6s_cantforward because this is the check - * before forwarding packet actually. - */ - if (ipsec6_in_reject(m, NULL)) { - IPSEC6STAT_INC(in_polvio); - m_freem(m); - return; - } -#endif /* IPSEC */ - /* * Do not forward packets to multicast destination (should be handled * by ip6_mforward(). @@ -139,8 +119,8 @@ ip6_forward(struct mbuf *m, int srcrt) IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) { IP6STAT_INC(ip6s_cantforward); /* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard) */ - if (V_ip6_log_time + V_ip6_log_interval < time_second) { - V_ip6_log_time = time_second; + if (V_ip6_log_time + V_ip6_log_interval < time_uptime) { + V_ip6_log_time = time_uptime; log(LOG_DEBUG, "cannot forward " "from %s to %s nxt %d received on %s\n", @@ -152,6 +132,17 @@ ip6_forward(struct mbuf *m, int srcrt) m_freem(m); return; } +#ifdef IPSEC + /* + * Check if this packet has an active SA and needs to be dropped + * instead of forwarded. + */ + if (ip6_ipsec_fwd(m) != 0) { + IP6STAT_INC(ip6s_cantforward); + m_freem(m); + return; + } +#endif /* IPSEC */ #ifdef IPSTEALTH if (!V_ip6stealth) { @@ -181,10 +172,9 @@ ip6_forward(struct mbuf *m, int srcrt) #ifdef IPSEC /* get a security policy for this packet */ - sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, - IP_FORWARDING, &error); + sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, &error); if (sp == NULL) { - IPSEC6STAT_INC(out_inval); + IPSEC6STAT_INC(ips_out_inval); IP6STAT_INC(ip6s_cantforward); if (mcopy) { #if 0 @@ -205,7 +195,7 @@ ip6_forward(struct mbuf *m, int srcrt) /* * This packet is just discarded. */ - IPSEC6STAT_INC(out_polvio); + IPSEC6STAT_INC(ips_out_polvio); IP6STAT_INC(ip6s_cantforward); KEY_FREESP(&sp); if (mcopy) { @@ -253,12 +243,10 @@ ip6_forward(struct mbuf *m, int srcrt) { struct ipsecrequest *isr = NULL; - struct ipsec_output_state state; /* * when the kernel forwards a packet, it is not proper to apply - * IPsec transport mode to the packet is not proper. this check - * avoid from this. + * IPsec transport mode to the packet. This check avoid from this. * at present, if there is even a transport mode SA request in the * security policy, the kernel does not apply IPsec to the packet. * this check is not enough because the following case is valid. @@ -286,18 +274,27 @@ ip6_forward(struct mbuf *m, int srcrt) * * IPv6 [ESP|AH] IPv6 [extension headers] payload */ - bzero(&state, sizeof(state)); - state.m = m; - state.ro = NULL; /* update at ipsec6_output_tunnel() */ - state.dst = NULL; /* update at ipsec6_output_tunnel() */ - - error = ipsec6_output_tunnel(&state, sp, 0); - m = state.m; - KEY_FREESP(&sp); + /* + * If we need to encapsulate the packet, do it here + * ipsec6_proces_packet will send the packet using ip6_output + */ + error = ipsec6_process_packet(m, sp->req); + /* Release SP if an error occurred */ + if (error != 0) + KEY_FREESP(&sp); + 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. + */ + error = 0; + goto skip_ipsec; + } if (error) { - /* mbuf is already reclaimed in ipsec6_output_tunnel. */ + /* mbuf is already reclaimed in ipsec6_process_packet. */ switch (error) { case EHOSTUNREACH: case ENETUNREACH: @@ -320,7 +317,6 @@ ip6_forward(struct mbuf *m, int srcrt) m_freem(mcopy); #endif } - m_freem(m); return; } else { /* @@ -332,25 +328,7 @@ ip6_forward(struct mbuf *m, int srcrt) m = NULL; goto freecopy; } - - if ((m != NULL) && (ip6 != mtod(m, struct ip6_hdr *)) ){ - /* - * now tunnel mode headers are added. we are originating - * packet instead of forwarding the packet. - */ - ip6_output(m, NULL, NULL, IPV6_FORWARDING/*XXX*/, NULL, NULL, - NULL); - goto freecopy; - } - - /* adjust pointer */ - dst = (struct sockaddr_in6 *)state.dst; - rt = state.ro ? state.ro->ro_rt : NULL; - if (dst != NULL && rt != NULL) - ipsecrt = 1; } - if (ipsecrt) - goto skip_routing; skip_ipsec: #endif again: @@ -361,6 +339,7 @@ again: dst->sin6_addr = ip6->ip6_dst; again2: rin6.ro_rt = in6_rtalloc1((struct sockaddr *)dst, 0, 0, M_GETFIB(m)); + rt = rin6.ro_rt; if (rin6.ro_rt != NULL) RT_UNLOCK(rin6.ro_rt); else { @@ -372,10 +351,6 @@ again2: } goto bad; } - rt = rin6.ro_rt; -#ifdef IPSEC -skip_routing: -#endif /* * Source scope check: if a packet can't be delivered to its @@ -398,17 +373,13 @@ skip_routing: IP6STAT_INC(ip6s_badscope); goto bad; } - if (inzone != outzone -#ifdef IPSEC - && !ipsecrt -#endif - ) { + if (inzone != outzone) { IP6STAT_INC(ip6s_cantforward); IP6STAT_INC(ip6s_badscope); in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard); - if (V_ip6_log_time + V_ip6_log_interval < time_second) { - V_ip6_log_time = time_second; + if (V_ip6_log_time + V_ip6_log_interval < time_uptime) { + V_ip6_log_time = time_uptime; log(LOG_DEBUG, "cannot forward " "src %s, dst %s, nxt %d, rcvif %s, outif %s\n", @@ -439,46 +410,6 @@ skip_routing: goto bad; } - if (m->m_pkthdr.len > IN6_LINKMTU(rt->rt_ifp)) { - in6_ifstat_inc(rt->rt_ifp, ifs6_in_toobig); - if (mcopy) { - u_long mtu; -#ifdef IPSEC - struct secpolicy *sp; - int ipsecerror; - size_t ipsechdrsiz; -#endif /* IPSEC */ - - mtu = IN6_LINKMTU(rt->rt_ifp); -#ifdef IPSEC - /* - * When we do IPsec tunnel ingress, we need to play - * with the link value (decrement IPsec header size - * from mtu value). The code is much simpler than v4 - * case, as we have the outgoing interface for - * encapsulated packet as "rt->rt_ifp". - */ - sp = ipsec_getpolicybyaddr(mcopy, IPSEC_DIR_OUTBOUND, - IP_FORWARDING, &ipsecerror); - if (sp) { - ipsechdrsiz = ipsec_hdrsiz(mcopy, - IPSEC_DIR_OUTBOUND, NULL); - if (ipsechdrsiz < mtu) - mtu -= ipsechdrsiz; - } - - /* - * if mtu becomes less than minimum MTU, - * tell minimum MTU (and I'll need to fragment it). - */ - if (mtu < IPV6_MMTU) - mtu = IPV6_MMTU; -#endif /* IPSEC */ - icmp6_error(mcopy, ICMP6_PACKET_TOO_BIG, 0, mtu); - } - goto bad; - } - if (rt->rt_flags & RTF_GATEWAY) dst = (struct sockaddr_in6 *)rt->rt_gateway; @@ -492,9 +423,6 @@ skip_routing: * modified by a redirect. */ if (V_ip6_sendredirects && rt->rt_ifp == m->m_pkthdr.rcvif && !srcrt && -#ifdef IPSEC - !ipsecrt && -#endif /* IPSEC */ (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0) { if ((rt->rt_ifp->if_flags & IFF_POINTOPOINT) != 0) { /* @@ -573,23 +501,12 @@ skip_routing: if (!IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst)) { m->m_flags |= M_SKIP_FIREWALL; /* If destination is now ourself drop to ip6_input(). */ - if (in6_localip(&ip6->ip6_dst)) { + if (in6_localip(&ip6->ip6_dst)) m->m_flags |= M_FASTFWD_OURS; - if (m->m_pkthdr.rcvif == NULL) - m->m_pkthdr.rcvif = V_loif; - if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) { - m->m_pkthdr.csum_flags |= - CSUM_DATA_VALID_IPV6 | CSUM_PSEUDO_HDR; - m->m_pkthdr.csum_data = 0xffff; - } -#ifdef SCTP - if (m->m_pkthdr.csum_flags & CSUM_SCTP_IPV6) - m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID; -#endif - error = netisr_queue(NETISR_IPV6, m); - goto out; - } else + else { + RTFREE(rt); goto again; /* Redo the routing table lookup. */ + } } /* See if local, if yes, send it to netisr. */ @@ -616,11 +533,46 @@ skip_routing: m->m_flags |= M_SKIP_FIREWALL; m->m_flags &= ~M_IP6_NEXTHOP; m_tag_delete(m, fwd_tag); + RTFREE(rt); goto again2; } pass: - error = nd6_output(rt->rt_ifp, origifp, m, dst, rt); + /* See if the size was changed by the packet filter. */ + if (m->m_pkthdr.len > IN6_LINKMTU(rt->rt_ifp)) { + in6_ifstat_inc(rt->rt_ifp, ifs6_in_toobig); + if (mcopy) { + u_long mtu; +#ifdef IPSEC + size_t ipsechdrsiz; +#endif /* IPSEC */ + + mtu = IN6_LINKMTU(rt->rt_ifp); +#ifdef IPSEC + /* + * When we do IPsec tunnel ingress, we need to play + * with the link value (decrement IPsec header size + * from mtu value). The code is much simpler than v4 + * case, as we have the outgoing interface for + * encapsulated packet as "rt->rt_ifp". + */ + ipsechdrsiz = ipsec_hdrsiz(mcopy, IPSEC_DIR_OUTBOUND, + NULL); + if (ipsechdrsiz < mtu) + mtu -= ipsechdrsiz; + /* + * if mtu becomes less than minimum MTU, + * tell minimum MTU (and I'll need to fragment it). + */ + if (mtu < IPV6_MMTU) + mtu = IPV6_MMTU; +#endif /* IPSEC */ + icmp6_error(mcopy, ICMP6_PACKET_TOO_BIG, 0, mtu); + } + goto bad; + } + + error = nd6_output_ifp(rt->rt_ifp, origifp, m, dst, NULL); if (error) { in6_ifstat_inc(rt->rt_ifp, ifs6_out_discard); IP6STAT_INC(ip6s_cantforward); @@ -671,10 +623,6 @@ pass: bad: m_freem(m); out: - if (rt != NULL -#ifdef IPSEC - && !ipsecrt -#endif - ) + if (rt != NULL) RTFREE(rt); } |