]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/netinet/in_gif.c
xnu-1456.1.26.tar.gz
[apple/xnu.git] / bsd / netinet / in_gif.c
index 787c688ceb67b420b46847bf2b95c923f6331c0a..482aef5e46baeac9b14431f789eecd5f7a5ef517 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2008 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
@@ -93,8 +93,6 @@
 
 #include <net/net_osdep.h>
 
-extern u_long  route_generation;
-
 int ip_gif_ttl = GIF_TTL;
 SYSCTL_INT(_net_inet_ip, IPCTL_GIF_TTL, gifttl, CTLFLAG_RW,
        &ip_gif_ttl,    0, "");
@@ -196,7 +194,7 @@ in_gif_output(
            (sc->gif_ro.ro_rt != NULL &&
            (sc->gif_ro.ro_rt->generation_id != route_generation ||
            sc->gif_ro.ro_rt->rt_ifp == ifp))) {
-               /* cache route doesn't match */
+               /* cache route doesn't match or recursive route */
                dst->sin_family = sin_dst->sin_family;
                dst->sin_len = sizeof(struct sockaddr_in);
                dst->sin_addr = sin_dst->sin_addr;
@@ -217,7 +215,9 @@ in_gif_output(
                }
 
                /* if it constitutes infinite encapsulation, punt. */
+               RT_LOCK(sc->gif_ro.ro_rt);
                if (sc->gif_ro.ro_rt->rt_ifp == ifp) {
+                       RT_UNLOCK(sc->gif_ro.ro_rt);
                        m_freem(m);
                        return ENETUNREACH;     /*XXX*/
                }
@@ -225,6 +225,7 @@ in_gif_output(
                ifp->if_mtu = sc->gif_ro.ro_rt->rt_ifp->if_mtu
                        - sizeof(struct ip);
 #endif
+               RT_UNLOCK(sc->gif_ro.ro_rt);
        }
 
        error = ip_output(m, NULL, &sc->gif_ro, IP_OUTARGS, NULL, &ipoa);
@@ -249,7 +250,7 @@ in_gif_input(m, off)
 
        if (gifp == NULL || (gifp->if_flags & IFF_UP) == 0) {
                m_freem(m);
-               OSAddAtomic(1, (SInt32*)&ipstat.ips_nogif);
+               OSAddAtomic(1, &ipstat.ips_nogif);
                return;
        }
 
@@ -297,7 +298,7 @@ in_gif_input(m, off)
            }
 #endif /* INET6 */
        default:
-               OSAddAtomic(1, (SInt32*)&ipstat.ips_nogif);
+               OSAddAtomic(1, &ipstat.ips_nogif);
                m_freem(m);
                return;
        }
@@ -345,7 +346,7 @@ gif_encapcheck4(
        src = (struct sockaddr_in *)sc->gif_psrc;
        dst = (struct sockaddr_in *)sc->gif_pdst;
 
-       mbuf_copydata(m, 0, sizeof(ip), &ip);
+       mbuf_copydata((struct mbuf *)(size_t)m, 0, sizeof(ip), &ip);
 
        /* check for address match */
        addrmatch = 0;
@@ -364,18 +365,18 @@ gif_encapcheck4(
                return 0;
        }
        /* reject packets with broadcast on source */
-       lck_mtx_lock(rt_mtx);
+       lck_rw_lock_shared(in_ifaddr_rwlock);
        for (ia4 = TAILQ_FIRST(&in_ifaddrhead); ia4;
             ia4 = TAILQ_NEXT(ia4, ia_link))
        {
                if ((ifnet_flags(ia4->ia_ifa.ifa_ifp) & IFF_BROADCAST) == 0)
                        continue;
                if (ip.ip_src.s_addr == ia4->ia_broadaddr.sin_addr.s_addr) {
-                       lck_mtx_unlock(rt_mtx);
+                       lck_rw_done(in_ifaddr_rwlock);
                        return 0;
                }
        }
-       lck_mtx_unlock(rt_mtx);
+       lck_rw_done(in_ifaddr_rwlock);
 
        /* ingress filters on outer source */
        if ((ifnet_flags(sc->gif_if) & IFF_LINK2) == 0 &&
@@ -387,20 +388,23 @@ gif_encapcheck4(
                sin.sin_family = AF_INET;
                sin.sin_len = sizeof(struct sockaddr_in);
                sin.sin_addr = ip.ip_src;
-               lck_mtx_lock(rt_mtx);
-               rt = rtalloc1_scoped_locked((struct sockaddr *)&sin, 0, 0,
+               rt = rtalloc1_scoped((struct sockaddr *)&sin, 0, 0,
                    m->m_pkthdr.rcvif->if_index);
-               lck_mtx_unlock(rt_mtx);
-               if (!rt || rt->rt_ifp != m->m_pkthdr.rcvif) {
+               if (rt != NULL)
+                       RT_LOCK(rt);
+               if (rt == NULL || rt->rt_ifp != m->m_pkthdr.rcvif) {
 #if 0
                        log(LOG_WARNING, "%s: packet from 0x%x dropped "
                            "due to ingress filter\n", if_name(&sc->gif_if),
                            (u_int32_t)ntohl(sin.sin_addr.s_addr));
 #endif
-                       if (rt)
+                       if (rt != NULL) {
+                               RT_UNLOCK(rt);
                                rtfree(rt);
+                       }
                        return 0;
                }
+               RT_UNLOCK(rt);
                rtfree(rt);
        }