The branch main has been updated by melifaro:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=f262b06a57b03a2025bdc0ce628514cd68af73db

commit f262b06a57b03a2025bdc0ce628514cd68af73db
Author:     Alexander V. Chernikov <melif...@freebsd.org>
AuthorDate: 2023-04-04 08:37:14 +0000
Commit:     Alexander V. Chernikov <melif...@freebsd.org>
CommitDate: 2023-04-04 08:42:33 +0000

    route: fix route get netlink translation.
    
    route.c uses newroute() to handle the "route get" command. The logic
     inside newroute() adds RTF_GATEWAY flag if "-interface" flag is not
     specified. That results in the inconsistent RTM_GET message with
     RTF_GATEWAY set but no RTAX_GATEWAY provided. Address this in the
     translation code by checking if the gateway is actually provided.
---
 sbin/route/route.c         |  4 ++--
 sbin/route/route_netlink.c | 48 +++++++++++++++++++++++++++++-----------------
 2 files changed, 32 insertions(+), 20 deletions(-)

diff --git a/sbin/route/route.c b/sbin/route/route.c
index 947c97ce794a..4002cbe5867b 100644
--- a/sbin/route/route.c
+++ b/sbin/route/route.c
@@ -118,7 +118,7 @@ static int  rtmsg_rtsock(int, int, int);
 static int     flushroutes_fib_rtsock(int);
 static void    monitor_rtsock(void);
 #else
-int            rtmsg_nl(int, int, int, struct sockaddr_storage *, struct 
rt_metrics *);
+int            rtmsg_nl(int, int, int, int, struct sockaddr_storage *, struct 
rt_metrics *);
 int            flushroutes_fib_nl(int, int);
 void           monitor_nl(int);
 #endif
@@ -1524,7 +1524,7 @@ rtmsg(int cmd, int flags, int fib)
 #ifdef WITHOUT_NETLINK
        return (rtmsg_rtsock(cmd, flags, fib));
 #else
-       errno = rtmsg_nl(cmd, flags, fib, so, &rt_metrics);
+       errno = rtmsg_nl(cmd, flags, fib, rtm_addrs, so, &rt_metrics);
        return (errno == 0 ? 0 : -1);
 #endif
 }
diff --git a/sbin/route/route_netlink.c b/sbin/route/route_netlink.c
index ce7da288496f..a3e9860244a9 100644
--- a/sbin/route/route_netlink.c
+++ b/sbin/route/route_netlink.c
@@ -33,7 +33,7 @@ void printb(int, const char *);
 extern const char routeflags[];
 extern int verbose, debugonly;
 
-int rtmsg_nl(int cmd, int rtm_flags, int fib, struct sockaddr_storage *so,
+int rtmsg_nl(int cmd, int rtm_flags, int fib, int rtm_addrs, struct 
sockaddr_storage *so,
     struct rt_metrics *rt_metrics);
 int flushroutes_fib_nl(int fib, int af);
 void monitor_nl(int fib);
@@ -125,8 +125,18 @@ nl_helper_free(struct nl_helper *h)
        snl_free(&h->ss_cmd);
 }
 
+static struct sockaddr *
+get_addr(struct sockaddr_storage *so, int rtm_addrs, int addr_type)
+{
+       struct sockaddr *sa = NULL;
+
+       if (rtm_addrs & (1 << addr_type))
+               sa = (struct sockaddr *)&so[addr_type];
+       return (sa);
+}
+
 static int
-rtmsg_nl_int(struct nl_helper *h, int cmd, int rtm_flags, int fib,
+rtmsg_nl_int(struct nl_helper *h, int cmd, int rtm_flags, int fib, int 
rtm_addrs,
     struct sockaddr_storage *so, struct rt_metrics *rt_metrics)
 {
        struct snl_state *ss = &h->ss_cmd;
@@ -154,9 +164,9 @@ rtmsg_nl_int(struct nl_helper *h, int cmd, int rtm_flags, 
int fib,
                exit(1);
        }
 
-       struct sockaddr *dst = (struct sockaddr *)&so[RTAX_DST];
-       struct sockaddr *mask = (struct sockaddr *)&so[RTAX_NETMASK];
-       struct sockaddr *gw = (struct sockaddr *)&so[RTAX_GATEWAY];
+       struct sockaddr *dst = get_addr(so, rtm_addrs, RTAX_DST);
+       struct sockaddr *mask = get_addr(so, rtm_addrs, RTAX_NETMASK);
+       struct sockaddr *gw = get_addr(so, rtm_addrs, RTAX_GATEWAY);
 
        if (dst == NULL)
                return (EINVAL);
@@ -210,16 +220,18 @@ rtmsg_nl_int(struct nl_helper *h, int cmd, int rtm_flags, 
int fib,
        snl_add_msg_attr_ip(&nw, RTA_DST, dst);
        snl_add_msg_attr_u32(&nw, RTA_TABLE, fib);
 
-       if (rtm_flags & RTF_GATEWAY) {
-               if (gw->sa_family == dst->sa_family)
-                       snl_add_msg_attr_ip(&nw, RTA_GATEWAY, gw);
-               else
-                       snl_add_msg_attr_ipvia(&nw, RTA_VIA, gw);
-       } else if (gw != NULL) {
-               /* Should be AF_LINK */
-               struct sockaddr_dl *sdl = (struct sockaddr_dl *)gw;
-               if (sdl->sdl_index != 0)
-                       snl_add_msg_attr_u32(&nw, RTA_OIF, sdl->sdl_index);
+       if (gw != NULL) {
+               if (rtm_flags & RTF_GATEWAY) {
+                       if (gw->sa_family == dst->sa_family)
+                               snl_add_msg_attr_ip(&nw, RTA_GATEWAY, gw);
+                       else
+                               snl_add_msg_attr_ipvia(&nw, RTA_VIA, gw);
+               } else {
+                       /* Should be AF_LINK */
+                       struct sockaddr_dl *sdl = (struct sockaddr_dl *)gw;
+                       if (sdl->sdl_index != 0)
+                               snl_add_msg_attr_u32(&nw, RTA_OIF, 
sdl->sdl_index);
+               }
        }
 
        if (rtm_flags != 0)
@@ -259,13 +271,13 @@ rtmsg_nl_int(struct nl_helper *h, int cmd, int rtm_flags, 
int fib,
 }
 
 int
-rtmsg_nl(int cmd, int rtm_flags, int fib, struct sockaddr_storage *so,
-    struct rt_metrics *rt_metrics)
+rtmsg_nl(int cmd, int rtm_flags, int fib, int rtm_addrs,
+    struct sockaddr_storage *so, struct rt_metrics *rt_metrics)
 {
        struct nl_helper h = {};
 
        nl_helper_init(&h);
-       int error = rtmsg_nl_int(&h, cmd, rtm_flags, fib, so, rt_metrics);
+       int error = rtmsg_nl_int(&h, cmd, rtm_flags, fib, rtm_addrs, so, 
rt_metrics);
        nl_helper_free(&h);
 
        return (error);

Reply via email to