routefilter currently filters the default route,
if it's priority is higher than the filter prio.
This might not be a good idea - for example you might want to
redistribute a default route into ospf, for that you need it in the
routing table but it is configured with a low priority (high value) as
a route of last resort or maybe even as a reject/blackhole.
Treat the default route as a special case and always pass it.
ok?
diff --git sys/net/rtsock.c sys/net/rtsock.c
index 70497d29a93..2e94fdbc0b1 100644
--- sys/net/rtsock.c
+++ sys/net/rtsock.c
@@ -110,7 +110,9 @@ int route_output(struct mbuf *, struct socket *, struct
sockaddr *,
int route_ctloutput(int, struct socket *, int, int, struct mbuf *);
int route_usrreq(struct socket *, int, struct mbuf *, struct mbuf *,
struct mbuf *, struct proc *);
-void route_input(struct mbuf *m0, struct socket *, sa_family_t);
+int route_is_default(struct sockaddr *, struct sockaddr *);
+void route_input(struct mbuf *m0, struct socket *, struct rt_addrinfo *,
+ sa_family_t);
int route_arp_conflict(struct rtentry *, struct rt_addrinfo *);
int route_cleargateway(struct rtentry *, void *, unsigned int);
void route_senddesync(void *);
@@ -403,8 +405,33 @@ route_senddesync(void *data)
timeout_add(&rop->timeout, ROUTE_DESYNC_RESEND_TIMEOUT);
}
+int
+route_is_default(struct sockaddr *dst, struct sockaddr *mask)
+{
+ /* see if.c if_group_routechange() */
+ switch (dst->sa_family) {
+ case AF_INET:
+ if (satosin(dst)->sin_addr.s_addr == INADDR_ANY &&
+ mask && (mask->sa_len == 0 ||
+ satosin(mask)->sin_addr.s_addr == INADDR_ANY))
+ return (1);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ if (IN6_ARE_ADDR_EQUAL(&(satosin6(dst))->sin6_addr,
+ &in6addr_any) && mask && (mask->sa_len == 0 ||
+ IN6_ARE_ADDR_EQUAL(&(satosin6(mask))->sin6_addr,
+ &in6addr_any)))
+ return (1);
+ break;
+#endif
+ }
+ return (0);
+}
+
void
-route_input(struct mbuf *m0, struct socket *so, sa_family_t sa_family)
+route_input(struct mbuf *m0, struct socket *so, struct rt_addrinfo *info,
+ sa_family_t sa_family)
{
struct routecb *rop;
struct rawcb *rp;
@@ -447,8 +474,16 @@ route_input(struct mbuf *m0, struct socket *so,
sa_family_t sa_family)
if (rtm->rtm_type != RTM_DESYNC && rop->msgfilter != 0 &&
!(rop->msgfilter & (1 << rtm->rtm_type)))
continue;
- if (rop->priority != 0 && rop->priority < rtm->rtm_priority)
- continue;
+ /* priority filter */
+ if (rop->priority != 0)
+ if ((info == NULL &&
+ rop->priority < rtm->rtm_priority) ||
+ (info != NULL &&
+ !route_is_default(info->rti_info[RTAX_DST],
+ info->rti_info[RTAX_NETMASK]) &&
+ rop->priority < rtm->rtm_priority))
+ continue;
+
switch (rtm->rtm_type) {
case RTM_IFANNOUNCE:
case RTM_DESYNC:
@@ -767,7 +802,7 @@ fail:
free(rtm, M_RTABLE, len);
}
if (m)
- route_input(m, so, info.rti_info[RTAX_DST] ?
+ route_input(m, so, &info, info.rti_info[RTAX_DST] ?
info.rti_info[RTAX_DST]->sa_family : AF_UNSPEC);
return (error);
@@ -1472,7 +1507,7 @@ rtm_miss(int type, struct rt_addrinfo *rtinfo, int flags,
uint8_t prio,
rtm->rtm_tableid = tableid;
rtm->rtm_addrs = rtinfo->rti_addrs;
rtm->rtm_index = ifidx;
- route_input(m, NULL, sa ? sa->sa_family : AF_UNSPEC);
+ route_input(m, NULL, NULL, sa ? sa->sa_family : AF_UNSPEC);
}
/*
@@ -1497,7 +1532,7 @@ rtm_ifchg(struct ifnet *ifp)
ifm->ifm_xflags = ifp->if_xflags;
if_getdata(ifp, &ifm->ifm_data);
ifm->ifm_addrs = 0;
- route_input(m, NULL, AF_UNSPEC);
+ route_input(m, NULL, NULL, AF_UNSPEC);
}
/*
@@ -1533,7 +1568,7 @@ rtm_addr(struct rtentry *rt, int cmd, struct ifaddr *ifa)
ifam->ifam_addrs = info.rti_addrs;
ifam->ifam_tableid = ifp->if_rdomain;
- route_input(m, NULL,
+ route_input(m, NULL, NULL,
ifa->ifa_addr ? ifa->ifa_addr->sa_family : AF_UNSPEC);
}
@@ -1556,7 +1591,7 @@ rtm_ifannounce(struct ifnet *ifp, int what)
ifan->ifan_index = ifp->if_index;
strlcpy(ifan->ifan_name, ifp->if_xname, sizeof(ifan->ifan_name));
ifan->ifan_what = what;
- route_input(m, NULL, AF_UNSPEC);
+ route_input(m, NULL, NULL, AF_UNSPEC);
}
#ifdef BFD
@@ -1587,7 +1622,7 @@ rtm_bfd(struct bfd_config *bfd)
bfd2sa(bfd->bc_rt, &sa_bfd);
memcpy(&bfdm->bm_sa, &sa_bfd, sizeof(sa_bfd));
- route_input(m, NULL, info.rti_info[RTAX_DST]->sa_family);
+ route_input(m, NULL, NULL, info.rti_info[RTAX_DST]->sa_family);
}
#endif /* BFD */