]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/netinet6/ip6_forward.c
xnu-3789.70.16.tar.gz
[apple/xnu.git] / bsd / netinet6 / ip6_forward.c
index 6fdaa10698321bcd55b294ee3c09b11a7e6ba693..e6beab89a101b355b72997322a537c2d12159ec2 100644 (file)
@@ -1,8 +1,8 @@
 /*
 /*
- * Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+ * Copyright (c) 2009-2016 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * unlawful or unlicensed copies of an Apple operating system, or to
  * circumvent, violate, or enable the circumvention or violation of, any
  * terms of an Apple operating system software license agreement.
  * unlawful or unlicensed copies of an Apple operating system, or to
  * circumvent, violate, or enable the circumvention or violation of, any
  * terms of an Apple operating system software license agreement.
- * 
+ *
  * Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this file.
  * Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
@@ -22,7 +22,7 @@
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 
  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 
 extern int ipsec_bypass;
 #endif /* IPSEC */
 
 extern int ipsec_bypass;
 #endif /* IPSEC */
 
-#include <netinet6/ip6_fw.h>
-
 #include <net/net_osdep.h>
 
 #include <net/net_osdep.h>
 
+#if DUMMYNET
+#include <netinet/ip_fw.h>
+#include <netinet/ip_dummynet.h>
+#endif /* DUMMYNET */
+
 #if PF
 #include <net/pfvar.h>
 #endif /* PF */
 #if PF
 #include <net/pfvar.h>
 #endif /* PF */
@@ -198,8 +201,7 @@ ip6_forward(struct mbuf *m, struct route_in6 *ip6forward_rt,
 #endif /*IPSEC*/
 
        /*
 #endif /*IPSEC*/
 
        /*
-        * Do not forward packets to multicast destination (should be handled
-        * by ip6_mforward().
+        * Do not forward packets to multicast destination.
         * Do not forward packets with unspecified source.  It was discussed
         * in July 2000, on ipngwg mailing list.
         */
         * Do not forward packets with unspecified source.  It was discussed
         * in July 2000, on ipngwg mailing list.
         */
@@ -224,8 +226,8 @@ ip6_forward(struct mbuf *m, struct route_in6 *ip6forward_rt,
 
        if (ip6->ip6_hlim <= IPV6_HLIMDEC) {
                /* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard) */
 
        if (ip6->ip6_hlim <= IPV6_HLIMDEC) {
                /* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard) */
-               icmp6_error(m, ICMP6_TIME_EXCEEDED,
-                               ICMP6_TIME_EXCEED_TRANSIT, 0);
+               icmp6_error_flag(m, ICMP6_TIME_EXCEEDED,
+                               ICMP6_TIME_EXCEED_TRANSIT, 0, 0);
                return (NULL);
        }
 
                return (NULL);
        }
 
@@ -473,6 +475,8 @@ ip6_forward(struct mbuf *m, struct route_in6 *ip6forward_rt,
         */
        src_in6 = ip6->ip6_src;
        if (in6_setscope(&src_in6, rt->rt_ifp, &outzone)) {
         */
        src_in6 = ip6->ip6_src;
        if (in6_setscope(&src_in6, rt->rt_ifp, &outzone)) {
+               RT_REMREF_LOCKED(rt);
+               RT_UNLOCK(rt);
                /* XXX: this should not happen */
                ip6stat.ip6s_cantforward++;
                ip6stat.ip6s_badscope++;
                /* XXX: this should not happen */
                ip6stat.ip6s_cantforward++;
                ip6stat.ip6s_badscope++;
@@ -480,6 +484,8 @@ ip6_forward(struct mbuf *m, struct route_in6 *ip6forward_rt,
                return (NULL);
        }
        if (in6_setscope(&src_in6, m->m_pkthdr.rcvif, &inzone)) {
                return (NULL);
        }
        if (in6_setscope(&src_in6, m->m_pkthdr.rcvif, &inzone)) {
+               RT_REMREF_LOCKED(rt);
+               RT_UNLOCK(rt);
                ip6stat.ip6s_cantforward++;
                ip6stat.ip6s_badscope++;
                m_freem(m);
                ip6stat.ip6s_cantforward++;
                ip6stat.ip6s_badscope++;
                m_freem(m);
@@ -523,6 +529,8 @@ ip6_forward(struct mbuf *m, struct route_in6 *ip6forward_rt,
        if (in6_setscope(&dst_in6, m->m_pkthdr.rcvif, &inzone) != 0 ||
            in6_setscope(&dst_in6, rt->rt_ifp, &outzone) != 0 ||
            inzone != outzone) {
        if (in6_setscope(&dst_in6, m->m_pkthdr.rcvif, &inzone) != 0 ||
            in6_setscope(&dst_in6, rt->rt_ifp, &outzone) != 0 ||
            inzone != outzone) {
+               RT_REMREF_LOCKED(rt);
+               RT_UNLOCK(rt);
                ip6stat.ip6s_cantforward++;
                ip6stat.ip6s_badscope++;
                m_freem(m);
                ip6stat.ip6s_cantforward++;
                ip6stat.ip6s_badscope++;
                m_freem(m);
@@ -612,29 +620,6 @@ ip6_forward(struct mbuf *m, struct route_in6 *ip6forward_rt,
                }
                type = ND_REDIRECT;
        }
                }
                type = ND_REDIRECT;
        }
-
-#if IPFW2
-       /*
-        * Check with the firewall...
-        */
-       if (ip6_fw_enable && ip6_fw_chk_ptr) {
-               u_short port = 0;
-               ifp = rt->rt_ifp;
-               /* Drop the lock but retain the extra ref */
-               RT_UNLOCK(rt);
-               /* If ipfw says divert, we have to just drop packet */
-               if (ip6_fw_chk_ptr(&ip6, ifp, &port, &m)) {
-                       m_freem(m);
-                       goto freecopy;
-               }
-               if (!m) {
-                       goto freecopy;
-               }
-               /* We still have the extra ref on rt */
-               RT_LOCK(rt);
-       }
-#endif
-
        /*
         * Fake scoped addresses. Note that even link-local source or
         * destinaion can appear, if the originating node just sends the
        /*
         * Fake scoped addresses. Note that even link-local source or
         * destinaion can appear, if the originating node just sends the
@@ -654,7 +639,7 @@ ip6_forward(struct mbuf *m, struct route_in6 *ip6forward_rt,
                 *      rthdr. (itojun)
                 */
 #if 1
                 *      rthdr. (itojun)
                 */
 #if 1
-               if (0)
+               if ((0))
 #else
                if ((rt->rt_flags & (RTF_BLACKHOLE|RTF_REJECT)) == 0)
 #endif
 #else
                if ((rt->rt_flags & (RTF_BLACKHOLE|RTF_REJECT)) == 0)
 #endif
@@ -704,25 +689,47 @@ ip6_forward(struct mbuf *m, struct route_in6 *ip6forward_rt,
                return (m);
        }
 
                return (m);
        }
 
-#if PF
-       /* Invoke outbound packet filter */
-       error = pf_af_hook(ifp, NULL, &m, AF_INET6, FALSE, NULL);
+       /* Mark this packet as being forwarded from another interface */
+       m->m_pkthdr.pkt_flags |= PKTF_FORWARDED;
 
 
-       if (error != 0 || m == NULL) {
-               if (m != NULL) {
-                       panic("%s: unexpected packet %p\n", __func__, m);
-                       /* NOTREACHED */
+#if PF
+       if (PF_IS_ENABLED) {
+#if DUMMYNET
+               struct ip_fw_args args;
+               bzero(&args, sizeof(args));
+
+               args.fwa_m = m;
+               args.fwa_oif = ifp;
+               args.fwa_oflags = 0;
+               args.fwa_ro6 = ip6forward_rt;
+               args.fwa_ro6_pmtu = ip6forward_rt;
+               args.fwa_mtu = rt->rt_ifp->if_mtu;
+               args.fwa_dst6 = dst;
+               args.fwa_origifp = origifp;
+               /* Invoke outbound packet filter */
+               error = pf_af_hook(ifp, NULL, &m, AF_INET6, FALSE, &args);
+#else /* !DUMMYNET */
+               error = pf_af_hook(ifp, NULL, &m, AF_INET6, FALSE, NULL);
+#endif /* !DUMMYNET */
+               if (error != 0 || m == NULL) {
+                       if (m != NULL) {
+                               panic("%s: unexpected packet %p\n", __func__, m);
+                               /* NOTREACHED */
+                       }
+                       /* Already freed by callee */
+                       goto senderr;
                }
                }
-               /* Already freed by callee */
-               goto senderr;
+               /*
+                * We do not use ip6 header again in the code below,
+                * however still adding the bit here so that any new
+                * code in future doesn't end up working with the
+                * wrong pointer
+                */
+               ip6 = mtod(m, struct ip6_hdr *);
        }
        }
-       ip6 = mtod(m, struct ip6_hdr *);
 #endif /* PF */
 
 #endif /* PF */
 
-       /* Mark this packet as being forwarded from another interface */
-       m->m_pkthdr.pkt_flags |= PKTF_FORWARDED;
        len = m_pktlen(m);
        len = m_pktlen(m);
-
        error = nd6_output(ifp, origifp, m, dst, rt, NULL);
        if (error) {
                in6_ifstat_inc(ifp, ifs6_out_discard);
        error = nd6_output(ifp, origifp, m, dst, rt, NULL);
        if (error) {
                in6_ifstat_inc(ifp, ifs6_out_discard);