From nobody Thu Apr 30 22:07:52 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4g67Zx3vrCz6cMdb for ; Thu, 30 Apr 2026 22:07:53 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R13" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4g67Zw6lvFz3kGH for ; Thu, 30 Apr 2026 22:07:52 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1777586873; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=bJDgBVvNcDG+4vZkjUGh+2oZiYvoaD4uGN+D6emAZ54=; b=KD64qiTMwQ0lIHQDV61JfSTEH0wKY5888WeFi2sVhGjbVbjGuB4kTSxKHV2v5Ru+pc2csb 6n+OY87NmsiFS0BPupb9XZFIeFzxMXam0Yj6sl8lulB+WSMEYdj6lrRvxH1lkMXriynmEC L+r1bbO246XEtUB20bbxYA/zvuLMOYzVGfEFTiniVKx0nkiBowA7+qGbnMVFkckkzjxiN6 4GjZNK18k3AzXogY4fU3eIu80eC6jMY1NOP5yyJwYVPQFkf+fXYE9Ekt/2UVIdwcX7Pjdo hjniO1uWj3ZsTivBstt/NAV7Yy3LM8hQykgwpj60yW3MudzieeUbIOsz1pD1wQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1777586873; a=rsa-sha256; cv=none; b=ZyZP34V7gBSWO/I2ME2YpRHVQ3/aTsH6rmICkpN1uwtzM1l73WEn6iBMdwNJ91i0ZGhvyW 0/+DNQQ7fTTe2Z+N9GH+DOv7EMwoVA7We456Vzur7Mg110UoDBid5okMnJ5xA6WqJzTOqd q/EtUCIlc+PQ6Ib6nE61nScVwqOETa4BhLNNtU2ONEhLvDoyyCgywK5v8qYLe0jzX9hcYy h/5GXjzJKd8TYmjPZi6Vp4heGsyHbZuLYZdEi3hYLSUwhQe1Rl8eyC2gAvdcr/fxSwgnIc 4xTcV4MPFVORqdsREqjWJ6903MawAR5NHF2jZVLC7uxV49shKIaT8y9eUKoqMQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1777586873; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=bJDgBVvNcDG+4vZkjUGh+2oZiYvoaD4uGN+D6emAZ54=; b=VnZV9ZkcagQsZA/U8aKILlpr9X+Dg1Z41jQ1jOZrcLIxJZm2FuLOOYVgTnu1TGnRsepKaQ udiPwi3ae5ctARc7HrHniQIKH3rKcFdR58vNVw0jTgTlwR9SZ0ImuYaHLrhiknW2RV0hLG xefUTsCziPgdLoFcSYKSJAwNxEEBGZctup6SCZQ9/tUkfAErRcG8w8SJILzJOJ1ivRGngM zH5qDu3BWuV8REIZYufFKjkj4L9j1edWZuhxiz9E9dXAc7v3GMp4n6SlxxAAbEBVAHOkyU c1kPmTV/ycmgVosD6yLS/8ljZU5kBZhFhLC15quqms3I4cLIpETGGKLLPs91jw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4g67Zw6JqTzVYZ for ; Thu, 30 Apr 2026 22:07:52 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 1c029 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Thu, 30 Apr 2026 22:07:52 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Pouria Mousavizadeh Tehrani Subject: git: 39b19ce77bc0 - main - route(8): Add route get for multipath routes with -o flag List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: pouria X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 39b19ce77bc0f1b9a6a685fff22f52932dcb7cf3 Auto-Submitted: auto-generated Date: Thu, 30 Apr 2026 22:07:52 +0000 Message-Id: <69f3d2b8.1c029.4ecffa88@gitrepo.freebsd.org> The branch main has been updated by pouria: URL: https://cgit.FreeBSD.org/src/commit/?id=39b19ce77bc0f1b9a6a685fff22f52932dcb7cf3 commit 39b19ce77bc0f1b9a6a685fff22f52932dcb7cf3 Author: Pouria Mousavizadeh Tehrani AuthorDate: 2026-04-19 11:07:22 +0000 Commit: Pouria Mousavizadeh Tehrani CommitDate: 2026-04-30 22:06:31 +0000 route(8): Add route get for multipath routes with -o flag Get the next hops of the specified route. route.8 manual will be updated when other actions for this option are implemented. Reviewed by: glebius Differential Revision: https://reviews.freebsd.org/D56191 --- sbin/route/route.c | 9 +++++--- sbin/route/route_netlink.c | 57 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/sbin/route/route.c b/sbin/route/route.c index f37d23d25c2c..f0d9515f9892 100644 --- a/sbin/route/route.c +++ b/sbin/route/route.c @@ -81,7 +81,7 @@ static struct keytab { {0, 0} }; -int verbose, debugonly; +int verbose, debugonly, nexthop; #ifdef JAIL char * jail_name; #endif @@ -166,7 +166,7 @@ usage(const char *cp) { if (cp != NULL) warnx("bad keyword: %s", cp); - errx(EX_USAGE, "usage: route [-j jail] [-46dnqtv] command [[modifiers] args]"); + errx(EX_USAGE, "usage: route [-j jail] [-46dnqtvo] command [[modifiers] args]"); /* NOTREACHED */ } @@ -182,7 +182,7 @@ main(int argc, char **argv) if (argc < 2) usage(NULL); - while ((ch = getopt(argc, argv, "46nqdtvj:")) != -1) + while ((ch = getopt(argc, argv, "46nqdtvoj:")) != -1) switch(ch) { case '4': #ifdef INET @@ -215,6 +215,9 @@ main(int argc, char **argv) case 'd': debugonly = 1; break; + case 'o': + nexthop = 1; + break; case 'j': #ifdef JAIL if (optarg == NULL) diff --git a/sbin/route/route_netlink.c b/sbin/route/route_netlink.c index 01817dcbb850..531336903896 100644 --- a/sbin/route/route_netlink.c +++ b/sbin/route/route_netlink.c @@ -31,7 +31,7 @@ const char *routename(struct sockaddr *); const char *netname(struct sockaddr *); void printb(int, const char *); extern const char routeflags[]; -extern int verbose, debugonly; +extern int verbose, debugonly, nexthop; int rtmsg_nl(int cmd, int rtm_flags, int fib, int rtm_addrs, struct sockaddr_storage *so, struct rt_metrics *rt_metrics); @@ -42,8 +42,12 @@ struct nl_helper; struct snl_msg_info; static void print_getmsg(struct nl_helper *h, struct nlmsghdr *hdr, struct sockaddr *dst); +static void print_nhop_getmsg(struct nl_helper *h, struct nlmsghdr *hdr, + struct sockaddr *dst); static void print_nlmsg(struct nl_helper *h, struct nlmsghdr *hdr, struct snl_msg_info *cinfo); +static void print_nlmsg_route_nhop(struct nl_helper *, struct snl_parsed_route *, + struct rta_mpath_nh *, bool); #define s6_addr32 __u6_addr.__u6_addr32 #define bitcount32(x) __bitcount32((uint32_t)(x)) @@ -275,7 +279,10 @@ rtmsg_nl_int(struct nl_helper *h, int cmd, int rtm_flags, int fib, int rtm_addrs hdr = snl_read_reply(ss, hdr->nlmsg_seq); if (nl_type == NL_RTM_GETROUTE) { if (hdr->nlmsg_type == NL_RTM_NEWROUTE) { - print_getmsg(h, hdr, dst); + if (!nexthop) + print_getmsg(h, hdr, dst); + else + print_nhop_getmsg(h, hdr, dst); return (0); } } @@ -390,6 +397,52 @@ print_getmsg(struct nl_helper *h, struct nlmsghdr *hdr, struct sockaddr *dst) printf("%8ld \n", rmx.rmx_expire); } +static void +print_nhop_getmsg(struct nl_helper *h, struct nlmsghdr *hdr, struct sockaddr *dst) +{ + struct snl_state *ss = &h->ss_cmd; + struct snl_parsed_route r = { .rtax_weight = RT_DEFAULT_WEIGHT }; + struct snl_parsed_link_simple link = {}; + struct sockaddr *mask; + + if (!snl_parse_nlmsg(ss, hdr, &snl_rtm_route_parser, &r)) + return; + + get_ifdata(h, r.rta_oif, &link); + r.rta_rtflags |= (RTF_UP | RTF_DONE); + + printf(" route to: %s\n", routename(dst)); + + if (r.rta_dst) + printf("destination: %s\n", routename(r.rta_dst)); + mask = get_netmask(ss, r.rtm_family, r.rtm_dst_len); + if (mask) + printf(" mask: %s\n", routename(mask)); + printf(" fib: %u\n", (unsigned int)r.rta_table); + printf(" flags: "); + printb(r.rta_rtflags, routeflags); + printf("\n nhops: %u\n", r.rta_multipath.num_nhops); + if (r.rta_multipath.num_nhops != 0) { + bool first = true; + for (uint32_t i = 0; i < r.rta_multipath.num_nhops; i++) { + struct rta_mpath_nh *nh = r.rta_multipath.nhops[i]; + + printf("\tvia "); + print_nlmsg_route_nhop(h, &r, nh, first); + first = false; + } + } else { + struct rta_mpath_nh nh = { + .gw = r.rta_gw, + .ifindex = r.rta_oif, + .rtax_mtu = link.ifla_mtu, + }; + printf("\tvia "); + print_nlmsg_route_nhop(h, &r, &nh, true); + } +} + + static void print_prefix(struct nl_helper *h, char *buf, int bufsize, struct sockaddr *sa, int plen) {