Index: sys/net/route.c =================================================================== --- sys/net/route.c (revision 194233) +++ sys/net/route.c (working copy) @@ -61,6 +61,8 @@ static void rtable_init(void **); /* compare two sockaddr structures */ #define sa_equal(a1, a2) (bcmp((a1), (a2), (a1)->sa_len) == 0) +#define _SOCKADDR_TMPSIZE 128 /* Not too big.. kernel stack size is limited */ + /* * Convert a 'struct radix_node *' to a 'struct rtentry *'. * The operation can be done safely (in this code) because a @@ -1139,6 +1141,7 @@ rtinit(struct ifaddr *ifa, int cmd, int flags) struct rtentry *rt = NULL; struct rt_addrinfo info; int error; + char tempbuf[_SOCKADDR_TMPSIZE]; if (flags & RTF_HOST) { dst = ifa->ifa_dstaddr; @@ -1189,6 +1192,14 @@ bad: return (flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); } } + + if (cmd == RTM_ADD) { + if (netmask != NULL) { + rt_maskedcopy(dst, (struct sockaddr *)tempbuf, netmask); + dst = (struct sockaddr *)tempbuf; + } + } + /* * Do the actual request */ @@ -1198,6 +1209,18 @@ bad: info.rti_info[RTAX_DST] = dst; 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(RTM_DELETE, &info, NULL); error = rtrequest1(cmd, &info, &rt); if (error == 0 && rt != NULL) { /*