Index: sys/net/route.c =================================================================== --- sys/net/route.c (revision 192799) +++ sys/net/route.c (working copy) @@ -1228,41 +1228,41 @@ rtinit1(struct ifaddr *ifa, int cmd, int if (rt_add_addr_allfibs == 0 && cmd == (int)RTM_ADD) { startfib = endfib = curthread->td_proc->p_fibnum; } else { startfib = 0; endfib = rt_numfibs - 1; } } else { KASSERT((fibnum < rt_numfibs), ("rtinit1: bad fibnum")); startfib = fibnum; endfib = fibnum; } if (dst->sa_len == 0) return(EINVAL); /* * If it's a delete, check that if it exists, * it's on the correct interface or we might scrub * a route to another ifa which would * be confusing at best and possibly worse. */ - if (cmd == RTM_DELETE) { + if (cmd == RTM_DELETE || cmd == RTM_ADD) { /* * It's a delete, so it should already exist.. * If it's a net, mask off the host bits * (Assuming we have a mask) * XXX this is kinda inet specific.. */ if (netmask != NULL) { rt_maskedcopy(dst, (struct sockaddr *)tempbuf, netmask); dst = (struct sockaddr *)tempbuf; } } /* * Now go through all the requested tables (fibs) and do the * requested action. Realistically, this will either be fib 0 * for protocols that don't do multiple tables or all the * tables for those that do. XXX For this version only AF_INET. * When that changes code should be refactored to protocol * independent parts and protocol dependent parts. */ for ( fibnum = startfib; fibnum <= endfib; fibnum++) { @@ -1310,40 +1310,52 @@ rtinit1(struct ifaddr *ifa, int cmd, int /* this is only an error if bad on ALL tables */ continue; } } /* * Do the actual request */ bzero((caddr_t)&info, sizeof(info)); info.rti_ifa = ifa; info.rti_flags = flags | ifa->ifa_flags; info.rti_info[RTAX_DST] = dst; /* * doing this for compatibility reasons */ if (cmd == RTM_ADD) info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&null_sdl; else info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr; info.rti_info[RTAX_NETMASK] = netmask; + /* + * When adding an interface route - using 'ifconfig up', + * for example - overwrite the route that was already there + * for that subnet. This fixes a scenario where we take + * an interface down, routing daemon installs new route + * for the subnet formerly reachable through that interface, + * then we bring the interface up, but it remains + * unusable - the routing daemon can't send advertisements + * through it, as there is no route. + */ + if (cmd == RTM_ADD) + rtrequest1_fib(RTM_DELETE, &info, NULL, fibnum); error = rtrequest1_fib(cmd, &info, &rt, fibnum); if (error == 0 && rt != NULL) { /* * notify any listening routing agents of the change */ RT_LOCK(rt); #ifdef RADIX_MPATH /* * in case address alias finds the first address * e.g. ifconfig bge0 192.103.54.246/24 * e.g. ifconfig bge0 192.103.54.247/24 * the address set in the route is 192.103.54.246 * so we need to replace it with 192.103.54.247 */ if (memcmp(rt->rt_ifa->ifa_addr, ifa->ifa_addr, ifa->ifa_addr->sa_len)) { IFAFREE(rt->rt_ifa); IFAREF(ifa); rt->rt_ifp = ifa->ifa_ifp; rt->rt_ifa = ifa;