/* * Update the register vif in the multicast routing daemon and the * kernel because the interface used initially to get its local address * is DOWN. register_vifi is the index to the Register vif which needs * to be updated. As a result the Register vif has a new uv_lcl_addr and * is UP (virtually :)) */ int update_reg_vif( mifi_t register_vifi ) { register struct uvif *v; register mifi_t vifi; /* Find the first useable vif with solid physical background */ for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) { if (v->uv_flags & (VIFF_DISABLED | VIFF_DOWN | MIFF_REGISTER)) continue; /* Found. Stop the bogus Register vif first */ stop_vif(register_vifi); add_phaddr(v, &uvifs[vifi].uv_linklocal->pa_addr, &uvifs[vifi].uv_linklocal->pa_subnetmask, &uvifs[vifi].uv_linklocal->pa_prefix); start_vif(register_vifi); IF_DEBUG(DEBUG_PIM_REGISTER | DEBUG_IF) log_msg(LOG_NOTICE, 0, "%s has come up; vif #%u now in service", uvifs[register_vifi].uv_name, register_vifi); return 0; } vifs_down = TRUE; log_msg(LOG_WARNING, 0, "Cannot start Register vif: %s", uvifs[vifi].uv_name); return(-1); }
void start_all_vifs() { mifi_t vifi; struct uvif *v; u_int action; /* Start first the NON-REGISTER vifs */ for (action = 0; ; action = MIFF_REGISTER) { for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) { /* * If starting non-registers but the vif is a register * or if starting registers, but the interface is not * a register, then just continue. */ if ((v->uv_flags & MIFF_REGISTER) ^ action) continue; if (v->uv_flags & (VIFF_DISABLED | VIFF_DOWN)) { IF_DEBUG(DEBUG_IF) log_msg(LOG_DEBUG, 0, "%s is %s; vif #%u out of service", v->uv_name, v->uv_flags & VIFF_DISABLED ? "DISABLED" : "DOWN", vifi); continue; } start_vif(vifi); } if (action == MIFF_REGISTER) break; } }
/* * See if any interfaces have changed from up state to down, or vice versa, * including any non-multicast-capable interfaces that are in use as local * tunnel end-points. Ignore interfaces that have been administratively * disabled. */ void check_vif_state(void) { vifi_t vifi; struct uvif *v; struct ifreq ifr; static int checking_vifs = 0; /* * If we get an error while checking, (e.g. two interfaces go down * at once, and we decide to send a prune out one of the failed ones) * then don't go into an infinite loop! */ if (checking_vifs) return; vifs_down = FALSE; checking_vifs = 1; for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) { if (v->uv_flags & VIFF_DISABLED) continue; memcpy(ifr.ifr_name, v->uv_name, sizeof(ifr.ifr_name)); if (ioctl(udp_socket, SIOCGIFFLAGS, (char *)&ifr) < 0) logit(LOG_ERR, errno, "Failed ioctl SIOCGIFFLAGS for %s", ifr.ifr_name); if (v->uv_flags & VIFF_DOWN) { if (ifr.ifr_flags & IFF_UP) { logit(LOG_NOTICE, 0, "%s has come up; vif #%u now in service", v->uv_name, vifi); v->uv_flags &= ~VIFF_DOWN; start_vif(vifi); } else { vifs_down = TRUE; } } else { if (!(ifr.ifr_flags & IFF_UP)) { logit(LOG_NOTICE, 0, "%s has gone down; vif #%u taken out of service", v->uv_name, vifi); stop_vif(vifi); v->uv_flags |= VIFF_DOWN; vifs_down = TRUE; } } } checking_vifs = 0; }