FreeBSD/sys/netinet6/nd6.c
/*
 * ND6 timer routine to expire default route list and prefix list
 */
ND6 timer routine to expire default route list and prefix list
ND6 timer routine to expire default route list and prefix list
void
nd6_timer(void *arg)
{
	CURVNET_SET((struct vnet *) arg);
	struct nd_drhead drq;
	struct nd_defrouter *dr, *ndr;
	struct nd_prefix *pr, *npr;
	struct in6_ifaddr *ia6, *nia6;
	TAILQ_INIT(&drq);
	ND6_WLOCK();
	TAILQ_FOREACH_SAFE(dr, &V_nd_defrouter, dr_entry, ndr)
		if (dr->expire && dr->expire < time_uptime)
			defrouter_unlink(dr, &drq);
	ND6_WUNLOCK();
	while ((dr = TAILQ_FIRST(&drq)) != NULL) {
		TAILQ_REMOVE(&drq, dr, dr_entry);
		defrouter_del(dr);
	}
  addrloop:
	TAILQ_FOREACH_SAFE(ia6, &V_in6_ifaddrhead, ia_link, nia6) {
		if (IFA6_IS_INVALID(ia6)) {
			int regen = 0;
			if (V_ip6_use_tempaddr &&
			    (ia6->ia6_flags & IN6_IFF_TEMPORARY) != 0) {
				if (regen_tmpaddr(ia6) == 0)
					regen = 1;
			}
			in6_purgeaddr(&ia6->ia_ifa);
			if (regen)
				goto addrloop; 
		} else if (IFA6_IS_DEPRECATED(ia6)) {
			int oldflags = ia6->ia6_flags;
			ia6->ia6_flags |= IN6_IFF_DEPRECATED;
			if (V_ip6_use_tempaddr &&
			    (ia6->ia6_flags & IN6_IFF_TEMPORARY) != 0 &&
			    (oldflags & IN6_IFF_DEPRECATED) == 0) {
				if (regen_tmpaddr(ia6) == 0) {
					goto addrloop;
				}
			}
		} else if ((ia6->ia6_flags & IN6_IFF_TENTATIVE) != 0) {
			int delay;
			delay = arc4random() %
			    (MAX_RTR_SOLICITATION_DELAY * hz);
			nd6_dad_start((struct ifaddr *)ia6, delay);
		} else {
			if ((ia6->ia_ifp->if_flags & IFF_UP) == 0 ||
			    (ia6->ia_ifp->if_drv_flags & IFF_DRV_RUNNING)
				== 0 ||
			    (ND_IFINFO(ia6->ia_ifp)->flags &
				ND6_IFF_IFDISABLED) != 0) {
				ia6->ia6_flags &= ~IN6_IFF_DUPLICATED;
				ia6->ia6_flags |= IN6_IFF_TENTATIVE;
			}
			ia6->ia6_flags &= ~IN6_IFF_DEPRECATED;
		}
	}
	LIST_FOREACH_SAFE(pr, &V_nd_prefix, ndpr_entry, npr) {
		if (pr->ndpr_vltime != ND6_INFINITE_LIFETIME &&
		    time_uptime - pr->ndpr_lastupdate > pr->ndpr_vltime) {
			prelist_remove(pr);
		}
	}
	callout_reset(&V_nd6_timer_ch, V_nd6_prune * hz,
	    nd6_timer, curvnet);
	CURVNET_RESTORE();
}
void nd6_timer ( void * arg ) { CURVNET_SET ( ( struct vnet * ) arg ) ; struct nd_drhead drq ; struct nd_defrouter * dr , * ndr ; struct nd_prefix * pr , * npr ; struct in6_ifaddr * ia6 , * nia6 ; TAILQ_INIT ( & drq ) ; ND6_WLOCK ( ) ; TAILQ_FOREACH_SAFE ( dr , & V_nd_defrouter , dr_entry , ndr ) if ( dr -> expire && dr -> expire < time_uptime ) defrouter_unlink ( dr , & drq ) ; ND6_WUNLOCK ( ) ; while ( ( dr = TAILQ_FIRST ( & drq ) ) != NULL ) { TAILQ_REMOVE ( & drq , dr , dr_entry ) ; defrouter_del ( dr ) ; } addrloop : TAILQ_FOREACH_SAFE ( ia6 , & V_in6_ifaddrhead , ia_link , nia6 ) { if ( IFA6_IS_INVALID ( ia6 ) ) { int regen = 0 ; if ( V_ip6_use_tempaddr && ( ia6 -> ia6_flags & IN6_IFF_TEMPORARY ) != 0 ) { if ( regen_tmpaddr ( ia6 ) == 0 ) regen = 1 ; } in6_purgeaddr ( & ia6 -> ia_ifa ) ; if ( regen ) goto addrloop ; } else if ( IFA6_IS_DEPRECATED ( ia6 ) ) { int oldflags = ia6 -> ia6_flags ; ia6 -> ia6_flags |= IN6_IFF_DEPRECATED ; if ( V_ip6_use_tempaddr && ( ia6 -> ia6_flags & IN6_IFF_TEMPORARY ) != 0 && ( oldflags & IN6_IFF_DEPRECATED ) == 0 ) { if ( regen_tmpaddr ( ia6 ) == 0 ) { goto addrloop ; } } } else if ( ( ia6 -> ia6_flags & IN6_IFF_TENTATIVE ) != 0 ) { int delay ; delay = arc4random ( ) % ( MAX_RTR_SOLICITATION_DELAY * hz ) ; nd6_dad_start ( ( struct ifaddr * ) ia6 , delay ) ; } else { if ( ( ia6 -> ia_ifp -> if_flags & IFF_UP ) == 0 || ( ia6 -> ia_ifp -> if_drv_flags & IFF_DRV_RUNNING ) == 0 || ( ND_IFINFO ( ia6 -> ia_ifp ) -> flags & ND6_IFF_IFDISABLED ) != 0 ) { ia6 -> ia6_flags &= ~ IN6_IFF_DUPLICATED ; ia6 -> ia6_flags |= IN6_IFF_TENTATIVE ; } ia6 -> ia6_flags &= ~ IN6_IFF_DEPRECATED ; } } LIST_FOREACH_SAFE ( pr , & V_nd_prefix , ndpr_entry , npr ) { if ( pr -> ndpr_vltime != ND6_INFINITE_LIFETIME && time_uptime - pr -> ndpr_lastupdate > pr -> ndpr_vltime ) { prelist_remove ( pr ) ; } } callout_reset ( & V_nd6_timer_ch , V_nd6_prune * hz , nd6_timer , curvnet ) ; CURVNET_RESTORE ( ) ; }
ND6 timer routine to expire default route list and prefix list
ND6 timer routine to expire default route list and prefix list
/* expire default router list */ /*
	 * expire interface addresses.
	 * in the past the loop was inside prefix expiry processing.
	 * However, from a stricter speci-confrmance standpoint, we should
	 * rather separate address lifetimes and prefix lifetimes.
	 *
	 * XXXRW: in6_ifaddrhead locking.
	 */ /* check address lifetime */ /*
			 * If the expiring address is temporary, try
			 * regenerating a new one.  This would be useful when
			 * we suspended a laptop PC, then turned it on after a
			 * period that could invalidate all temporary
			 * addresses.  Although we may have to restart the
			 * loop (see below), it must be after purging the
			 * address.  Otherwise, we'd see an infinite loop of
			 * regeneration.
			 */ /* XXX: see below */ /*
			 * If a temporary address has just become deprecated,
			 * regenerate a new one if possible.
			 */ /*
					 * A new temporary address is
					 * generated.
					 * XXX: this means the address chain
					 * has changed while we are still in
					 * the loop.  Although the change
					 * would not cause disaster (because
					 * it's not a deletion, but an
					 * addition,) we'd rather restart the
					 * loop just for safety.  Or does this
					 * significantly reduce performance??
					 */ /*
			 * Schedule DAD for a tentative address.  This happens
			 * if the interface was down or not running
			 * when the address was configured.
			 */ /*
			 * Check status of the interface.  If it is down,
			 * mark the address as tentative for future DAD.
			 */ /*
			 * A new RA might have made a deprecated address
			 * preferred.
			 */ /* expire prefix list */ /*
		 * check prefix lifetime.
		 * since pltime is just for autoconf, pltime processing for
		 * prefix is not necessary.
		 */ /*
			 * address expiration and prefix expiration are
			 * separate.  NEVER perform in6_purgeaddr here.
			 */