#include <net/net_osdep.h>
-static void add_each_addr __P((struct socket *so, struct rr_prefix *rpp,
- struct rp_addr *rap));
-static int create_ra_entry __P((struct rp_addr **rapp));
-static int add_each_prefix __P((struct socket *so, struct rr_prefix *rpp));
-static void free_rp_entries __P((struct rr_prefix *rpp));
-static int link_stray_ia6s __P((struct rr_prefix *rpp));
-static void rp_remove __P((struct rr_prefix *rpp));
+static void add_each_addr(struct socket *so, struct rr_prefix *rpp,
+ struct rp_addr *rap);
+static int create_ra_entry(struct rp_addr **rapp);
+static int add_each_prefix(struct socket *so, struct rr_prefix *rpp);
+static void free_rp_entries(struct rr_prefix *rpp);
+static int link_stray_ia6s(struct rr_prefix *rpp);
+static void rp_remove(struct rr_prefix *rpp);
+extern lck_mtx_t *prefix6_mutex;
/*
* Copy bits from src to tgt, from off bit for len bits.
struct ifprefix *ifpr;
/* search matched prefix */
+ ifnet_lock_shared(ifp);
for (ifpr = TAILQ_FIRST(&ifp->if_prefixhead); ifpr;
ifpr = TAILQ_NEXT(ifpr, ifpr_list))
{
if (plen <= in6_matchlen(dst, IFPR_IN6(ifpr)))
break;
}
+ ifnet_lock_done(ifp);
return (ifpr);
}
* which matches the addr
*/
+ ifnet_lock_shared(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
{
if (ifa->ifa_addr->sa_family != AF_INET6)
in6_matchlen(&ipr->ipr_prefix.sin6_addr, IFA_IN6(ifa)))
break;
}
- if (ifa == NULL)
+ if (ifa == NULL) {
+ ifnet_lock_done(ifp);
return NULL;
+ }
rpp = ifpr2rp(((struct in6_ifaddr *)ifa)->ia6_ifpr);
- if (rpp != 0)
+ if (rpp != 0) {
+ ifnet_lock_done(ifp);
return rpp;
-
+ }
+
for (ifpr = TAILQ_FIRST(&ifp->if_prefixhead); ifpr;
ifpr = TAILQ_NEXT(ifpr, ifpr_list))
{
IFPR_IN6(ifpr)))
break;
}
+ ifnet_lock_done(ifp);
if (ifpr != NULL)
log(LOG_ERR, "in6_prefix.c: search_matched_prefix: addr %s"
"has no pointer to prefix %s\n", ip6_sprintf(IFA_IN6(ifa)),
int matchlen, matched = 0;
/* search matched prefixes */
+ ifnet_lock_exclusive(ifp); /* Should if_prefixhead be protected by IPv6?? */
for (ifpr = TAILQ_FIRST(&ifp->if_prefixhead); ifpr;
ifpr = TAILQ_NEXT(ifpr, ifpr_list))
{
"ND autoconfigured addr?\n",
ip6_sprintf(IFA_IN6(ifa)));
}
+ ifnet_lock_done(ifp);
return matched;
}
struct ifprefix *ifpr;
/* search matched prefixes */
+ ifnet_lock_exclusive(ifp);
for (ifpr = TAILQ_FIRST(&ifp->if_prefixhead); ifpr;
ifpr = TAILQ_NEXT(ifpr, ifpr_list))
{
IPV6_ADDR_SCOPE_GLOBAL)
ifpr2rp(ifpr)->rp_statef_delmark = 1;
}
+ ifnet_lock_done(ifp);
}
/* Unmark prefixes */
struct ifprefix *ifpr;
/* unmark all prefix */
+ ifnet_lock_exclusive(ifp);
for (ifpr = TAILQ_FIRST(&ifp->if_prefixhead); ifpr;
ifpr = TAILQ_NEXT(ifpr, ifpr_list))
{
ifpr2rp(ifpr)->rp_statef_addmark = 0;
ifpr2rp(ifpr)->rp_statef_delmark = 0;
}
+ ifnet_lock_done(ifp);
}
static void
init_prefix_ltimes(struct rr_prefix *rpp)
{
+ struct timeval timenow;
+
+ getmicrotime(&timenow);
if (rpp->rp_pltime == RR_INFINITE_LIFETIME ||
rpp->rp_rrf_decrprefd == 0)
rpp->rp_preferred = 0;
else
- rpp->rp_preferred = time_second + rpp->rp_pltime;
+ rpp->rp_preferred = timenow.tv_sec + rpp->rp_pltime;
if (rpp->rp_vltime == RR_INFINITE_LIFETIME ||
rpp->rp_rrf_decrvalid == 0)
rpp->rp_expire = 0;
else
- rpp->rp_expire = time_second + rpp->rp_vltime;
+ rpp->rp_expire = timenow.tv_sec + rpp->rp_vltime;
}
static int
{
struct rp_addr *rap;
+ lck_mtx_lock(prefix6_mutex);
LIST_FOREACH(rap, &rpp->rp_addrhead, ra_entry)
{
if (rr_are_ifid_equal(ifid, &rap->ra_ifid,
rpp->rp_plen))
break;
}
+ lck_mtx_unlock(prefix6_mutex);
return rap;
}
#if 0 /* Can't do this now, because rpp may be on th stack. should fix it? */
ia->ia6_ifpr = rp2ifpr(rpp);
#endif
- s = splnet();
+ lck_mtx_lock(prefix6_mutex);
LIST_INSERT_HEAD(&rpp->rp_addrhead, rap, ra_entry);
- splx(s);
+ lck_mtx_unlock(prefix6_mutex);
return 0;
}
struct rr_prefix *rpp;
struct rp_addr *rap;
struct socket so;
- int error, s;
+ int error;
if ((error = create_ra_entry(&rap)) != 0)
return(error);
/* XXX: init dummy so */
bzero(&so, sizeof(so));
/* insert into list */
+ lck_mtx_lock(prefix6_mutex);
LIST_FOREACH(rpp, &rr_prefix, rp_entry)
{
/*
if (rpp->rp_ifp != ia->ia_ifp)
continue;
- s = splnet();
LIST_INSERT_HEAD(&rpp->rp_addrhead, rap, ra_entry);
- splx(s);
add_each_addr(&so, rpp, rap);
}
+ lck_mtx_unlock(prefix6_mutex);
return 0;
}
return;
rap = search_ifidwithprefix(ifpr2rp(ia->ia6_ifpr), IA6_IN6(ia));
if (rap != NULL) {
- int s = splnet();
+ lck_mtx_lock(prefix6_mutex);
LIST_REMOVE(rap, ra_entry);
- splx(s);
+ lck_mtx_unlock(prefix6_mutex);
if (rap->ra_addr)
ifafree(&rap->ra_addr->ia_ifa);
FREE(rap, M_RR_ADDR);
}
void
-in6_purgeprefix(ifp)
- struct ifnet *ifp;
+in6_purgeprefix(
+ struct ifnet *ifp)
{
struct ifprefix *ifpr, *nextifpr;
/* delete prefixes before ifnet goes away */
+ ifnet_lock_exclusive(ifp);
for (ifpr = TAILQ_FIRST(&ifp->if_prefixhead); ifpr;
ifpr = nextifpr)
{
continue;
(void)delete_each_prefix(ifpr2rp(ifpr), PR_ORIG_KERNEL);
}
+ ifnet_lock_done(ifp);
}
static void
int s;
/* search existing prefix */
+ ifnet_lock_exclusive(new->rp_ifp);
for (ifpr = TAILQ_FIRST(&new->rp_ifp->if_prefixhead); ifpr;
ifpr = TAILQ_NEXT(ifpr, ifpr_list))
{
* If the origin of the already-installed prefix is more
* preferable than the new one, ignore installation request.
*/
- if (rpp->rp_origin > new->rp_origin)
+ if (rpp->rp_origin > new->rp_origin) {
+ ifnet_lock_done(new->rp_ifp);
return(EPERM);
+ }
/* update prefix information */
rpp->rp_flags.prf_ra = new->rp_flags.prf_ra;
* add rp_addr entries in new into rpp, if they have not
* been already included in rpp.
*/
+ lck_mtx_lock(prefix6_mutex);
while (!LIST_EMPTY(&new->rp_addrhead))
{
rap = LIST_FIRST(&new->rp_addrhead);
FREE(rap, M_RR_ADDR);
continue;
}
- s = splnet();
LIST_INSERT_HEAD(&rpp->rp_addrhead, rap, ra_entry);
- splx(s);
}
+ lck_mtx_unlock(prefix6_mutex);
} else {
/*
* We got a fresh prefix.
if (rpp == NULL) {
log(LOG_ERR, "in6_prefix.c: rrpr_update:%d"
": ENOBUFS for rr_prefix\n", __LINE__);
+ ifnet_lock_done(new->rp_ifp);
return(ENOBUFS);
}
/* initilization */
+ lck_mtx_lock(prefix6_mutex);
*rpp = *new;
LIST_INIT(&rpp->rp_addrhead);
/* move rp_addr entries of new to rpp */
LIST_REMOVE(rap, ra_entry);
LIST_INSERT_HEAD(&rpp->rp_addrhead, rap, ra_entry);
}
+ lck_mtx_unlock(prefix6_mutex);
/* let rp_ifpr.ifpr_prefix point rr_prefix. */
rpp->rp_ifpr.ifpr_prefix = (struct sockaddr *)&rpp->rp_prefix;
rp2ifpr(rpp)->ifpr_type = IN6_PREFIX_RR;
}
/* link rr_prefix entry to rr_prefix list */
- s = splnet();
+ lck_mtx_lock(prefix6_mutex);
LIST_INSERT_HEAD(&rr_prefix, rpp, rp_entry);
- splx(s);
+ lck_mtx_unlock(prefix6_mutex);
}
+ ifnet_lock_done(new->rp_ifp);
if (!new->rp_raf_auto)
return 0;
* If it existed but not pointing to the prefix yet,
* init the prefix pointer.
*/
+ lck_mtx_lock(prefix6_mutex);
LIST_FOREACH(rap, &rpp->rp_addrhead, ra_entry)
{
if (rap->ra_addr != NULL) {
}
add_each_addr(so, rpp, rap);
}
+ lck_mtx_unlock(prefix6_mutex);
return 0;
}
static void
rp_remove(struct rr_prefix *rpp)
{
- int s;
- s = splnet();
/* unlink rp_entry from if_prefixlist */
+ lck_mtx_lock(prefix6_mutex);
{
struct ifnet *ifp = rpp->rp_ifp;
struct ifprefix *ifpr;
+ ifnet_lock_exclusive(ifp);
if ((ifpr = TAILQ_FIRST(&ifp->if_prefixhead)) == rp2ifpr(rpp))
TAILQ_FIRST(&ifp->if_prefixhead) =
TAILQ_NEXT(ifpr, ifpr_list);
else
printf("Couldn't unlink rr_prefix from ifp\n");
}
+ ifnet_lock_done(ifp);
}
/* unlink rp_entry from rr_prefix list */
LIST_REMOVE(rpp, rp_entry);
- splx(s);
+ lck_mtx_unlock(prefix6_mutex);
FREE(rpp, M_IP6RR);
}
irr->irr_u_uselen,
min(ifpr->ifpr_plen - irr->irr_u_uselen,
irr->irr_u_keeplen));
+ lck_mtx_lock(prefix6_mutex);
LIST_FOREACH(orap, &(ifpr2rp(ifpr)->rp_addrhead), ra_entry)
{
struct rp_addr *rap;
/* Is some FlagMasks for rrf necessary? */
rpp->rp_rrf = irr->irr_rrf;
rpp->rp_origin = irr->irr_origin;
+ lck_mtx_unlock(prefix6_mutex);
return 0;
}
* This func is only called with rpp on stack(not on list).
* So no splnet() here
*/
+ lck_mtx_lock(prefix6_mutex);
while (!LIST_EMPTY(&rpp->rp_addrhead))
{
struct rp_addr *rap;
ifafree(&rap->ra_addr->ia_ifa);
FREE(rap, M_RR_ADDR);
}
+ lck_mtx_unlock(prefix6_mutex);
}
static int
int error = 0;
/* add prefixes to each of marked prefix */
+ ifnet_lock_exclusive(ifp);
for (ifpr = TAILQ_FIRST(&ifp->if_prefixhead); ifpr; ifpr = nextifpr)
{
nextifpr = TAILQ_NEXT(ifpr, ifpr_list);
error = add_each_prefix(so, &rp);
}
}
+ ifnet_lock_done(ifp);
/* free each rp_addr entry */
free_rp_entries(&rp);
unprefer_prefix(struct rr_prefix *rpp)
{
struct rp_addr *rap;
+ struct timeval timenow;
+ getmicrotime(&timenow);
+
+ lck_mtx_lock(prefix6_mutex);
for (rap = rpp->rp_addrhead.lh_first; rap != NULL;
rap = rap->ra_entry.le_next) {
if (rap->ra_addr == NULL)
continue;
- rap->ra_addr->ia6_lifetime.ia6t_preferred = time_second;
+ rap->ra_addr->ia6_lifetime.ia6t_preferred = timenow.tv_sec;
rap->ra_addr->ia6_lifetime.ia6t_pltime = 0;
}
+ lck_mtx_unlock(prefix6_mutex);
+
}
int
if (rpp->rp_origin > origin)
return(EPERM);
+ lck_mtx_lock(prefix6_mutex);
while (rpp->rp_addrhead.lh_first != NULL) {
struct rp_addr *rap;
int s;
- s = splnet();
rap = LIST_FIRST(&rpp->rp_addrhead);
if (rap == NULL) {
- splx(s);
break;
}
LIST_REMOVE(rap, ra_entry);
- splx(s);
if (rap->ra_addr == NULL) {
FREE(rap, M_RR_ADDR);
continue;
}
rap->ra_addr->ia6_ifpr = NULL;
- in6_purgeaddr(&rap->ra_addr->ia_ifa);
+ in6_purgeaddr(&rap->ra_addr->ia_ifa, 0);
ifafree(&rap->ra_addr->ia_ifa);
FREE(rap, M_RR_ADDR);
}
rp_remove(rpp);
+ lck_mtx_unlock(prefix6_mutex);
return error;
}
struct ifprefix *ifpr, *nextifpr;
/* delete prefixes marked as tobe deleted */
+ ifnet_lock_exclusive(ifp);
for (ifpr = TAILQ_FIRST(&ifp->if_prefixhead); ifpr; ifpr = nextifpr)
{
nextifpr = TAILQ_NEXT(ifpr, ifpr_list);
if (ifpr2rp(ifpr)->rp_statef_delmark)
(void)delete_each_prefix(ifpr2rp(ifpr), origin);
}
+ ifnet_lock_done(ifp);
}
static int
int error = 0;
/*
- * Failsafe for errneous address config program.
+ * Failsafe for erroneous address config program.
* Let's hope rrenumd don't make a mistakes.
*/
if (ipr->ipr_origin <= PR_ORIG_RA)
free_rp_entries(&rp_tmp);
break;
}
+ ifnet_lock_exclusive(ifp);
for (ifa = ifp->if_addrlist.tqh_first;
ifa;
ifa = ifa->ifa_list.tqe_next)
rp_tmp.rp_plen,
(sizeof(rap->ra_ifid) << 3) - rp_tmp.rp_plen);
/* insert into list */
+ lck_mtx_lock(prefix6_mutex);
LIST_INSERT_HEAD(&rp_tmp.rp_addrhead, rap, ra_entry);
+ lck_mtx_unlock(prefix6_mutex);
}
+ ifnet_lock_done(ifp);
error = add_each_prefix(so, &rp_tmp);
if (rpp == NULL || ifp != rpp->rp_ifp)
return (EADDRNOTAVAIL);
+ ifnet_lock_exclusive(ifp);
error = delete_each_prefix(rpp, ipr->ipr_origin);
+ ifnet_lock_done(ifp);
break;
}
bad:
return error;
}
-void
-in6_rr_timer_funneled(void *ignored_arg)
-{
-#ifdef __APPLE__
- boolean_t funnel_state;
- funnel_state = thread_funnel_set(network_flock, TRUE);
-#endif
- in6_rr_timer(ignored_arg);
-#ifdef __APPLE__
- (void) thread_funnel_set(network_flock, FALSE);
-#endif
-}
-
void
in6_rr_timer(void *ignored_arg)
{
- int s;
struct rr_prefix *rpp;
+ struct timeval timenow;
- timeout(in6_rr_timer_funneled, (caddr_t)0, ip6_rr_prune * hz);
+ getmicrotime(&timenow);
- s = splnet();
/* expire */
+ lck_mtx_lock(prefix6_mutex);
rpp = LIST_FIRST(&rr_prefix);
while (rpp) {
- if (rpp->rp_expire && rpp->rp_expire < time_second) {
+ if (rpp->rp_expire && rpp->rp_expire < timenow.tv_sec) {
struct rr_prefix *next_rpp;
next_rpp = LIST_NEXT(rpp, rp_entry);
rpp = next_rpp;
continue;
}
- if (rpp->rp_preferred && rpp->rp_preferred < time_second)
+ if (rpp->rp_preferred && rpp->rp_preferred < timenow.tv_sec)
unprefer_prefix(rpp);
rpp = LIST_NEXT(rpp, rp_entry);
}
- splx(s);
+ lck_mtx_unlock(prefix6_mutex);
+ timeout(in6_rr_timer, (caddr_t)0, ip6_rr_prune * hz);
}