+/*
+ * Copyright (c) 2000-2008 Apple Inc. All rights reserved.
+ *
+ * @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
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * 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.
+ *
+ * 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,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * 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@
+ */
+
/* $FreeBSD: src/sys/net/if_stf.c,v 1.1.2.6 2001/07/24 19:10:18 brooks Exp $ */
/* $KAME: if_stf.c,v 1.62 2001/06/07 22:32:16 itojun Exp $ */
struct stf_softc {
ifnet_t sc_if; /* common area */
- u_long sc_protocol_family; /* dlil protocol attached */
+ u_int32_t sc_protocol_family; /* dlil protocol attached */
union {
struct route __sc_ro4;
struct route_in6 __sc_ro6; /* just for safety */
static int stf_checkaddr6(struct stf_softc *, struct in6_addr *,
struct ifnet *);
static void stf_rtrequest(int, struct rtentry *, struct sockaddr *);
-static errno_t stf_ioctl(ifnet_t ifp, u_int32_t cmd, void *data);
+static errno_t stf_ioctl(ifnet_t ifp, u_long cmd, void *data);
static errno_t stf_output(ifnet_t ifp, mbuf_t m);
/*
if (proto != IPPROTO_IPV6)
return 0;
- /* LINTED const cast */
- mbuf_copydata(m, 0, sizeof(ip), &ip);
+ mbuf_copydata((struct mbuf *)(size_t)m, 0, sizeof(ip), &ip);
if (ip.ip_v != 4)
return 0;
* success on: dst = 10.1.1.1, ia6->ia_addr = 2002:0a01:0101:...
*/
if (bcmp(GET_V4(&ia6->ia_addr.sin6_addr), &ip.ip_dst,
- sizeof(ip.ip_dst)) != 0)
+ sizeof(ip.ip_dst)) != 0) {
+ ifafree(&ia6->ia_ifa);
return 0;
-
+ }
/*
* check if IPv4 src matches the IPv4 address derived from the
* local 6to4 address masked by prefixmask.
a.s_addr &= GET_V4(&ia6->ia_prefixmask.sin6_addr)->s_addr;
b = ip.ip_src;
b.s_addr &= GET_V4(&ia6->ia_prefixmask.sin6_addr)->s_addr;
- if (a.s_addr != b.s_addr)
+ if (a.s_addr != b.s_addr) {
+ ifafree(&ia6->ia_ifa);
return 0;
-
+ }
/* stf interface makes single side match only */
+ ifafree(&ia6->ia_ifa);
return 32;
}
continue;
bcopy(GET_V4(&sin6->sin6_addr), &in, sizeof(in));
- 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 (ia4->ia_addr.sin_addr.s_addr == in.s_addr)
break;
}
- lck_mtx_unlock(rt_mtx);
+ lck_rw_done(in_ifaddr_rwlock);
if (ia4 == NULL)
continue;
+ ifaref(ia);
ifnet_lock_done(ifp);
return (struct in6_ifaddr *)ia;
}
m = m_pullup(m, sizeof(*ip6));
if (!m) {
*m0 = NULL; /* makes sure this won't be double freed */
+ ifafree(&ia6->ia_ifa);
return ENOBUFS;
}
}
else if (IN6_IS_ADDR_6TO4(&dst6->sin6_addr))
in4 = GET_V4(&dst6->sin6_addr);
else {
+ ifafree(&ia6->ia_ifa);
return ENETUNREACH;
}
m = m_pullup(m, sizeof(struct ip));
if (m == NULL) {
*m0 = NULL;
+ ifafree(&ia6->ia_ifa);
return ENOBUFS;
}
ip = mtod(m, struct ip *);
if (sc->sc_ro.ro_rt == NULL) {
rtalloc(&sc->sc_ro);
if (sc->sc_ro.ro_rt == NULL) {
+ ifafree(&ia6->ia_ifa);
return ENETUNREACH;
}
}
if (result == 0)
result = EJUSTRETURN;
*m0 = NULL;
+ ifafree(&ia6->ia_ifa);
return result;
}
static errno_t
/*
* reject packets with broadcast
*/
- 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 ((ia4->ia_ifa.ifa_ifp->if_flags & IFF_BROADCAST) == 0)
continue;
if (in->s_addr == ia4->ia_broadaddr.sin_addr.s_addr) {
- lck_mtx_unlock(rt_mtx);
+ lck_rw_done(in_ifaddr_rwlock);
return -1;
}
}
- lck_mtx_unlock(rt_mtx);
+ lck_rw_done(in_ifaddr_rwlock);
/*
* perform ingress filter
sin.sin_family = AF_INET;
sin.sin_len = sizeof(struct sockaddr_in);
sin.sin_addr = *in;
- rt = rtalloc1((struct sockaddr *)&sin, 0, 0UL);
- if (!rt || rt->rt_ifp != inifp) {
+ rt = rtalloc1((struct sockaddr *)&sin, 0, 0);
+ if (rt != NULL)
+ RT_LOCK(rt);
+ if (rt == NULL || rt->rt_ifp != inifp) {
#if 1
log(LOG_WARNING, "%s: packet from 0x%x dropped "
"due to ingress filter\n", if_name(sc->sc_if),
(u_int32_t)ntohl(sin.sin_addr.s_addr));
#endif
- if (rt)
+ if (rt != NULL) {
+ RT_UNLOCK(rt);
rtfree(rt);
+ }
return -1;
}
+ RT_UNLOCK(rt);
rtfree(rt);
}
struct rtentry *rt,
__unused struct sockaddr *sa)
{
-
- if (rt)
+ if (rt != NULL) {
+ RT_LOCK_ASSERT_HELD(rt);
rt->rt_rmx.rmx_mtu = IPV6_MMTU;
+ }
}
static errno_t
stf_ioctl(
ifnet_t ifp,
- u_int32_t cmd,
+ u_long cmd,
void *data)
{
struct ifaddr *ifa;