X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/2d21ac55c334faf3a56e5634905ed6987fc787d4..060df5ea7c632b1ac8cc8aac1fb59758165c2084:/bsd/netinet/in_gif.c diff --git a/bsd/netinet/in_gif.c b/bsd/netinet/in_gif.c index 2076a730d..482aef5e4 100644 --- a/bsd/netinet/in_gif.c +++ b/bsd/netinet/in_gif.c @@ -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@ * @@ -111,6 +111,7 @@ in_gif_output( struct ip iphdr; /* capsule IP header, host byte ordered */ int proto, error; u_int8_t tos; + struct ip_out_args ipoa = { IFSCOPE_NONE }; if (sin_src == NULL || sin_dst == NULL || sin_src->sin_family != AF_INET || @@ -189,8 +190,11 @@ in_gif_output( bcopy(&iphdr, mtod(m, struct ip *), sizeof(struct ip)); if (dst->sin_family != sin_dst->sin_family || - dst->sin_addr.s_addr != sin_dst->sin_addr.s_addr) { - /* cache route doesn't match */ + dst->sin_addr.s_addr != sin_dst->sin_addr.s_addr || + (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 or recursive route */ dst->sin_family = sin_dst->sin_family; dst->sin_len = sizeof(struct sockaddr_in); dst->sin_addr = sin_dst->sin_addr; @@ -211,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*/ } @@ -219,9 +225,10 @@ 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, 0, NULL, NULL); + error = ip_output(m, NULL, &sc->gif_ro, IP_OUTARGS, NULL, &ipoa); return(error); } @@ -243,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; } @@ -291,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; } @@ -339,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; @@ -358,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 && @@ -381,17 +388,23 @@ gif_encapcheck4( sin.sin_family = AF_INET; sin.sin_len = sizeof(struct sockaddr_in); sin.sin_addr = ip.ip_src; - rt = rtalloc1((struct sockaddr *)&sin, 0, 0UL); - if (!rt || rt->rt_ifp != m->m_pkthdr.rcvif) { + rt = rtalloc1_scoped((struct sockaddr *)&sin, 0, 0, + m->m_pkthdr.rcvif->if_index); + 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); }