aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander V. Chernikov <melifaro@FreeBSD.org>2023-04-04 08:37:14 +0000
committerAlexander V. Chernikov <melifaro@FreeBSD.org>2023-04-04 08:42:33 +0000
commitf262b06a57b03a2025bdc0ce628514cd68af73db (patch)
tree79c2fdd336cd7185572624250841d5c64c7f6f74
parente46be58cca6bd180dadfb36e98a673ae6d8d2cd1 (diff)
downloadsrc-f262b06a57b03a2025bdc0ce628514cd68af73db.tar.gz
src-f262b06a57b03a2025bdc0ce628514cd68af73db.zip
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.
-rw-r--r--sbin/route/route.c4
-rw-r--r--sbin/route/route_netlink.c48
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);