aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander V. Chernikov <melifaro@FreeBSD.org>2021-02-08 23:29:05 +0000
committerAlexander V. Chernikov <melifaro@FreeBSD.org>2021-03-28 20:40:48 +0000
commit367fcd5bce34bcd9aff540443a0d2e7fa5dbe90a (patch)
tree248d76eff61c4aafa466dd4fa709267e2ef841a9
parentd6616e3dbaeeb0cf336dda3eec1c5fa7faf8a5c5 (diff)
downloadsrc-367fcd5bce34bcd9aff540443a0d2e7fa5dbe90a.tar.gz
src-367fcd5bce34bcd9aff540443a0d2e7fa5dbe90a.zip
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 Approved by: re (gjb) (cherry picked from commit 3489286a5f368e7fcf11a9691f9bb5df77abe9a3)
-rw-r--r--sys/net/rtsock.c62
1 files changed, 60 insertions, 2 deletions
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index d9294441b2bc..f13c3189ba26 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -564,6 +564,54 @@ 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) {
+#ifdef INET
+ 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;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ saun->sin6.sin6_family = AF_INET6;
+ saun->sin6.sin6_len = sizeof(struct sockaddr_in6);
+ saun->sin6.sin6_addr = in6addr_loopback;
+ break;
+#endif
+ 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.
*
@@ -951,7 +999,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;
@@ -979,7 +1026,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) {
@@ -1011,6 +1057,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: