Hi, Routing daemons like ospfd use two interfaces to obtain route information from the kernel: - sysctl - route messages
Route information from sysctl contain correct route priorities, route messages not. This can lead to incorrect routes inside the daemons. If daemons see routes with different priorities, they assume to see different routes. My attached patch adds route priorities to route messages to offer a consistent view to kernel routes with both interfaces. Here an example of a problem, caused by this bug: /etc/hostname.em3: rtlabel EXPORT_DIRECT inet 192.168.58.57 255.255.255.0 192.168.58.255 inet alias 1.0.0.1 255.255.255.0 192.168.58.255 /etc/ospfd.conf: area 10.188.0.0 { interface em3:192.168.58.57 { } } redistribute rtlabel EXPORT_DIRECT If the interface address 1.0.0.1 is set before starting the ospfd, we have ha route with a priority of 4: $ ospfctl show fib | grep 1.0.0 *C 4 1.0.0.0/24 link#4 Now we delete the route with ifconfig and take a look to the generated route message: $ ifconfig em3 inet delete 1.0.0.1 RTM_DELETE: Delete Route: len 224, priority 0, table 0, ifidx 4, pid: 0, seq 0, errno 0 flags:<DONE,CLONING> use: 0 mtu: 0 expire: 0 locks: inits: sockaddrs: <DST,GATEWAY,NETMASK,IFP,IFA,LABEL> 1.0.0.0 1.0.0.1 255.255.255.0 08:00:27:fd:b8:81 1.0.0.1 EXPORT_DIRECT Because the priority 0 of the deleted cloning route doesn't match to the priority of the fib route, ospfd is still seeing/announcing the network: $ ospfctl show fib | grep 1.0.0 *C 4 1.0.0.0/24 link#4 Please take a look to my patch. Thanks and Regards Florian Index: net/route.c =================================================================== RCS file: /openbsd//src/sys/net/route.c,v retrieving revision 1.296 diff -u -p -r1.296 route.c --- net/route.c 7 Mar 2016 18:44:00 -0000 1.296 +++ net/route.c 24 Mar 2016 08:36:17 -0000 @@ -248,8 +248,8 @@ rt_match(struct sockaddr *dst, uint32_t error = rtrequest(RTM_RESOLVE, &info, RTP_DEFAULT, &rt, tableid); if (error) { - rt_missmsg(RTM_MISS, &info, 0, 0, error, - tableid); + rt_missmsg(RTM_MISS, &info, 0, RTP_NONE, 0, + error, tableid); } else { /* Inform listeners of the new route */ rt_sendmsg(rt, RTM_ADD, tableid); @@ -488,7 +488,8 @@ rt_sendmsg(struct rtentry *rt, int cmd, info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr; } - rt_missmsg(cmd, &info, rt->rt_flags, rt->rt_ifidx, 0, rtableid); + rt_missmsg(cmd, &info, rt->rt_flags, rt->rt_priority, rt->rt_ifidx, 0, + rtableid); if_put(ifp); } @@ -522,6 +523,7 @@ rtredirect(struct sockaddr *dst, struct struct ifaddr *ifa; unsigned int ifidx = 0; int flags = RTF_GATEWAY|RTF_HOST; + uint8_t prio = RTP_NONE; splsoftassert(IPL_SOFTNET); @@ -578,8 +580,10 @@ create: rt = NULL; error = rtrequest(RTM_ADD, &info, RTP_DEFAULT, &rt, rdomain); - if (error == 0) + if (error == 0) { flags = rt->rt_flags; + prio = rt->rt_priority; + } stat = &rtstat.rts_dynamic; } else { /* @@ -588,6 +592,7 @@ create: */ rt->rt_flags |= RTF_MODIFIED; flags |= RTF_MODIFIED; + prio = rt->rt_priority; stat = &rtstat.rts_newgateway; rt_setgate(rt, gateway); } @@ -609,7 +614,7 @@ out: info.rti_info[RTAX_DST] = dst; info.rti_info[RTAX_GATEWAY] = gateway; info.rti_info[RTAX_AUTHOR] = src; - rt_missmsg(RTM_REDIRECT, &info, flags, ifidx, error, rdomain); + rt_missmsg(RTM_REDIRECT, &info, flags, prio, ifidx, error, rdomain); } /* @@ -638,7 +643,8 @@ rtdeletemsg(struct rtentry *rt, struct i info.rti_flags = rt->rt_flags; ifidx = rt->rt_ifidx; error = rtrequest_delete(&info, rt->rt_priority, ifp, &rt, tableid); - rt_missmsg(RTM_DELETE, &info, info.rti_flags, ifidx, error, tableid); + rt_missmsg(RTM_DELETE, &info, info.rti_flags, rt->rt_priority, ifidx, + error, tableid); if (error == 0) rtfree(rt); return (error); Index: net/route.h =================================================================== RCS file: /openbsd//src/sys/net/route.h,v retrieving revision 1.132 diff -u -p -r1.132 route.h --- net/route.h 24 Feb 2016 22:41:53 -0000 1.132 +++ net/route.h 24 Mar 2016 08:36:17 -0000 @@ -360,7 +360,7 @@ void rt_maskedcopy(struct sockaddr *, struct sockaddr *rt_plen2mask(struct rtentry *, struct sockaddr_in6 *); void rt_sendmsg(struct rtentry *, int, u_int); void rt_sendaddrmsg(struct rtentry *, int); -void rt_missmsg(int, struct rt_addrinfo *, int, u_int, int, u_int); +void rt_missmsg(int, struct rt_addrinfo *, int, u_char, u_int, int, u_int); int rt_setgate(struct rtentry *, struct sockaddr *); int rt_checkgate(struct ifnet *, struct rtentry *, struct sockaddr *, unsigned int, struct rtentry **); Index: net/rtsock.c =================================================================== RCS file: /openbsd//src/sys/net/rtsock.c,v retrieving revision 1.186 diff -u -p -r1.186 rtsock.c --- net/rtsock.c 12 Jan 2016 09:27:46 -0000 1.186 +++ net/rtsock.c 24 Mar 2016 08:36:17 -0000 @@ -1063,8 +1063,8 @@ again: * destination. */ void -rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, u_int ifidx, - int error, u_int tableid) +rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, uint8_t prio, + u_int ifidx, int error, u_int tableid) { struct rt_msghdr *rtm; struct mbuf *m; @@ -1077,6 +1077,7 @@ rt_missmsg(int type, struct rt_addrinfo return; rtm = mtod(m, struct rt_msghdr *); rtm->rtm_flags = RTF_DONE | flags; + rtm->rtm_priority = prio; rtm->rtm_errno = error; rtm->rtm_tableid = tableid; rtm->rtm_addrs = rtinfo->rti_addrs; Index: netinet/in_pcb.c =================================================================== RCS file: /openbsd//src/sys/netinet/in_pcb.c,v retrieving revision 1.197 diff -u -p -r1.197 in_pcb.c --- netinet/in_pcb.c 23 Mar 2016 15:50:36 -0000 1.197 +++ netinet/in_pcb.c 24 Mar 2016 08:36:17 -0000 @@ -692,8 +692,8 @@ in_losing(struct inpcb *inp) info.rti_info[RTAX_DST] = &inp->inp_route.ro_dst; info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; info.rti_info[RTAX_NETMASK] = rt_plen2mask(rt, &sa_mask); - rt_missmsg(RTM_LOSING, &info, rt->rt_flags, rt->rt_ifidx, 0, - inp->inp_rtableid); + rt_missmsg(RTM_LOSING, &info, rt->rt_flags, rt->rt_priority, + rt->rt_ifidx, 0, inp->inp_rtableid); if (rt->rt_flags & RTF_DYNAMIC) (void)rtrequest(RTM_DELETE, &info, rt->rt_priority, NULL, inp->inp_rtableid);