Fix blackhole/reject routes.
Traditionally *BSD routing stack required to supply some interface data for blackhole/reject routes. This lead to varieties of hacks in routing daemons when inserting such routes. With the recent routeing stack changes, gateway sockaddr without RTF_GATEWAY started to be treated differently, purely as link identifier. This change broke net/bird, which installs blackhole routes with 127.0.0.1 gateway without RTF_GATEWAY flags. Fix this by automatically constructing necessary gateway data at rtsock level if RTF_REJECT/RTF_BLACKHOLE is set. Reported by: Marek Zarychta <zarychtam at plan-b.pwste.edu.pl> Reviewed by: donner MFC after: 1 week
This commit is contained in:
parent
e6405c8c37
commit
145bf6c0af
@ -562,6 +562,50 @@ rtm_get_jailed(struct rt_addrinfo *info, struct ifnet *ifp,
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
fill_blackholeinfo(struct rt_addrinfo *info, union sockaddr_union *saun)
|
||||
{
|
||||
struct ifaddr *ifa;
|
||||
sa_family_t saf;
|
||||
|
||||
if (V_loif == NULL) {
|
||||
printf("Unable to add blackhole/reject nhop without loopback");
|
||||
return (ENOTSUP);
|
||||
}
|
||||
info->rti_ifp = V_loif;
|
||||
|
||||
saf = info->rti_info[RTAX_DST]->sa_family;
|
||||
|
||||
CK_STAILQ_FOREACH(ifa, &info->rti_ifp->if_addrhead, ifa_link) {
|
||||
if (ifa->ifa_addr->sa_family == saf) {
|
||||
info->rti_ifa = ifa;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (info->rti_ifa == NULL)
|
||||
return (ENOTSUP);
|
||||
|
||||
bzero(saun, sizeof(union sockaddr_union));
|
||||
switch (saf) {
|
||||
case AF_INET:
|
||||
saun->sin.sin_family = AF_INET;
|
||||
saun->sin.sin_len = sizeof(struct sockaddr_in);
|
||||
saun->sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
break;
|
||||
case AF_INET6:
|
||||
saun->sin6.sin6_family = AF_INET6;
|
||||
saun->sin6.sin6_len = sizeof(struct sockaddr_in6);
|
||||
saun->sin6.sin6_addr = in6addr_loopback;
|
||||
break;
|
||||
default:
|
||||
return (ENOTSUP);
|
||||
}
|
||||
info->rti_info[RTAX_GATEWAY] = &saun->sa;
|
||||
info->rti_flags |= RTF_GATEWAY;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fills in @info based on userland-provided @rtm message.
|
||||
*
|
||||
@ -944,7 +988,6 @@ route_output(struct mbuf *m, struct socket *so, ...)
|
||||
#endif
|
||||
int alloc_len = 0, len, error = 0, fibnum;
|
||||
sa_family_t saf = AF_UNSPEC;
|
||||
struct walkarg w;
|
||||
struct rib_cmd_info rc;
|
||||
struct nhop_object *nh;
|
||||
|
||||
@ -972,7 +1015,6 @@ route_output(struct mbuf *m, struct socket *so, ...)
|
||||
|
||||
m_copydata(m, 0, len, (caddr_t)rtm);
|
||||
bzero(&info, sizeof(info));
|
||||
bzero(&w, sizeof(w));
|
||||
nh = NULL;
|
||||
|
||||
if (rtm->rtm_version != RTM_VERSION) {
|
||||
@ -1004,6 +1046,18 @@ route_output(struct mbuf *m, struct socket *so, ...)
|
||||
goto flush;
|
||||
}
|
||||
|
||||
union sockaddr_union gw_saun;
|
||||
int blackhole_flags = rtm->rtm_flags & (RTF_BLACKHOLE|RTF_REJECT);
|
||||
if (blackhole_flags != 0) {
|
||||
if (blackhole_flags != (RTF_BLACKHOLE | RTF_REJECT))
|
||||
error = fill_blackholeinfo(&info, &gw_saun);
|
||||
else
|
||||
error = EINVAL;
|
||||
if (error != 0)
|
||||
senderr(error);
|
||||
/* TODO: rebuild rtm from scratch */
|
||||
}
|
||||
|
||||
switch (rtm->rtm_type) {
|
||||
case RTM_ADD:
|
||||
case RTM_CHANGE:
|
||||
|
Loading…
Reference in New Issue
Block a user