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);