- TAILQ_FOREACH(dr, &nd_defrouter, dr_entry) {
- NDDR_LOCK(dr);
- VERIFY((dr->stateflags & NDDRF_PROCESSED) == 0);
- NDDR_UNLOCK(dr);
- }
- /* Remove conflicting entries */
- dr = TAILQ_FIRST(&nd_defrouter);
- while (dr) {
- NDDR_LOCK(dr);
- if (!(dr->stateflags & NDDRF_INSTALLED) ||
- dr->stateflags & NDDRF_PROCESSED) {
- NDDR_UNLOCK(dr);
- dr = TAILQ_NEXT(dr, dr_entry);
- continue;
- }
- dr->stateflags |= NDDRF_PROCESSED;
-
- /* A NULL selected_dr will remove primary default route */
- if ((dr == selected_dr && (dr->stateflags & NDDRF_IFSCOPE)) ||
- (dr != selected_dr && !(dr->stateflags & NDDRF_IFSCOPE))) {
- NDDR_ADDREF_LOCKED(dr);
- NDDR_UNLOCK(dr);
- lck_mtx_unlock(nd6_mutex);
- defrouter_delreq(dr);
- lck_mtx_lock(nd6_mutex);
- NDDR_LOCK(dr);
- if (dr && dr != installed_dr0)
- dr->genid = -1;
- NDDR_UNLOCK(dr);
- NDDR_REMREF(dr);
- /*
- * Since we lost nd6_mutex, we have to start over.
- */
- dr = TAILQ_FIRST(&nd_defrouter);
- continue;
- }
- NDDR_UNLOCK(dr);
- dr = TAILQ_NEXT(dr, dr_entry);
- }
-
- /* -1 is a special number, make sure we don't use it for genid */
- if (++nd6_defrouter_genid == -1)
- nd6_defrouter_genid = 1;
-
- TAILQ_FOREACH(dr, &nd_defrouter, dr_entry) {
- NDDR_LOCK(dr);
- dr->stateflags &= ~NDDRF_PROCESSED;
- NDDR_UNLOCK(dr);
- }
- /* Add the entries back */
- dr = TAILQ_FIRST(&nd_defrouter);
- while (dr) {
- struct nd_defrouter *_dr;
-
- NDDR_LOCK(dr);
- if (dr->stateflags & NDDRF_PROCESSED ||
- dr->genid != -1) {
- NDDR_UNLOCK(dr);
- dr = TAILQ_NEXT(dr, dr_entry);
- continue;
- }
- dr->stateflags |= NDDRF_PROCESSED;
-
- /* Handle case (b) */
- for (_dr = TAILQ_FIRST(&nd_defrouter); _dr;
- _dr = TAILQ_NEXT(_dr, dr_entry)) {
- if (_dr == dr)
- continue;
- /*
- * This is safe because we previously checked if
- * _dr == dr.
- */
- NDDR_LOCK(_dr);
- if (_dr->ifp == dr->ifp && rtpref(_dr) >= rtpref(dr) &&
- (_dr->stateflags & NDDRF_INSTALLED)) {
- NDDR_ADDREF_LOCKED(_dr);
- NDDR_UNLOCK(_dr);
- break;
- }
- NDDR_UNLOCK(_dr);
- }
-
- /* If same preference and i/f, static entry takes precedence */
- if (_dr != NULL && rtpref(_dr) == rtpref(dr) &&
- !(_dr->stateflags & NDDRF_STATIC) &&
- (dr->stateflags & NDDRF_STATIC)) {
- lck_mtx_unlock(nd6_mutex);
- defrouter_delreq(_dr);
- lck_mtx_lock(nd6_mutex);
- NDDR_REMREF(_dr);
- _dr = NULL;
- }
-
- if (_dr == NULL && !(dr->stateflags & NDDRF_INSTALLED)) {
- NDDR_ADDREF_LOCKED(dr);
- NDDR_UNLOCK(dr);
- lck_mtx_unlock(nd6_mutex);
- defrouter_addreq(dr, (selected_dr == NULL ||
- dr->ifp != selected_dr->ifp));
- dr->genid = nd6_defrouter_genid;
- lck_mtx_lock(nd6_mutex);
- NDDR_REMREF(dr);
- /*
- * Since we lost nd6_mutex, we have to start over.
- */
- dr = TAILQ_FIRST(&nd_defrouter);
- continue;