The branch main has been updated by melifaro:

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

commit c35a43b261f807fd85b8cc30306112eee9dd62ce
Author:     Alexander V. Chernikov <[email protected]>
AuthorDate: 2023-04-02 13:47:10 +0000
Commit:     Alexander V. Chernikov <[email protected]>
CommitDate: 2023-04-02 13:47:10 +0000

    netlink: allow exact-match route lookups via RTM_GETROUTE.
    
    Use already-existing RTM_F_PREFIX rtm_flag to indicate that the
     request assumes exact-prefix lookup instead of the
     longest-prefix-match.
    
    MFC after:      2 weeks
---
 sys/net/route/route_ctl.c | 14 ++++++++++++++
 sys/net/route/route_ctl.h |  6 ++----
 sys/netlink/route/rt.c    | 13 ++++++++++---
 3 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/sys/net/route/route_ctl.c b/sys/net/route/route_ctl.c
index 755765869e84..db3728c3cd88 100644
--- a/sys/net/route/route_ctl.c
+++ b/sys/net/route/route_ctl.c
@@ -96,6 +96,8 @@ static int delete_route(struct rib_head *rnh, struct rtentry 
*rt,
 static int rt_delete_conditional(struct rib_head *rnh, struct rtentry *rt,
     int prio, rib_filter_f_t *cb, void *cbdata, struct rib_cmd_info *rc);
 
+static bool fill_pxmask_family(int family, int plen, struct sockaddr *_dst,
+    struct sockaddr **pmask);
 static int get_prio_from_info(const struct rt_addrinfo *info);
 static int nhop_get_prio(const struct nhop_object *nh);
 
@@ -391,6 +393,18 @@ lookup_prefix(struct rib_head *rnh, const struct 
rt_addrinfo *info,
        return (rt);
 }
 
+const struct rtentry *
+rib_lookup_prefix_plen(struct rib_head *rnh, struct sockaddr *dst, int plen,
+    struct route_nhop_data *rnd)
+{
+       union sockaddr_union mask_storage;
+       struct sockaddr *netmask = &mask_storage.sa;
+
+       if (fill_pxmask_family(dst->sa_family, plen, dst, &netmask))
+               return (lookup_prefix_bysa(rnh, dst, netmask, rnd));
+       return (NULL);
+}
+
 static bool
 fill_pxmask_family(int family, int plen, struct sockaddr *_dst,
     struct sockaddr **pmask)
diff --git a/sys/net/route/route_ctl.h b/sys/net/route/route_ctl.h
index b65b64fcdaa0..7a4ed804feb7 100644
--- a/sys/net/route/route_ctl.h
+++ b/sys/net/route/route_ctl.h
@@ -123,11 +123,9 @@ struct nhop_object;
 struct nhgrp_object;
 struct ucred;
 
-const struct rtentry *rib_lookup_prefix(uint32_t fibnum, int family,
-    const struct sockaddr *dst, const struct sockaddr *netmask,
+const struct rtentry *
+rib_lookup_prefix_plen(struct rib_head *rnh, struct sockaddr *dst, int plen,
     struct route_nhop_data *rnd);
-const struct rtentry *rib_lookup_lpm(uint32_t fibnum, int family,
-    const struct sockaddr *dst, struct route_nhop_data *rnd);
 
 /* rtentry accessors */
 bool rt_is_host(const struct rtentry *rt);
diff --git a/sys/netlink/route/rt.c b/sys/netlink/route/rt.c
index 6d76390016dd..288ff111a038 100644
--- a/sys/netlink/route/rt.c
+++ b/sys/netlink/route/rt.c
@@ -461,6 +461,7 @@ struct nl_parsed_route {
        uint8_t                 rtm_dst_len;
        uint8_t                 rtm_protocol;
        uint8_t                 rtm_type;
+       uint32_t                rtm_flags;
 };
 
 #define        _IN(_field)     offsetof(struct rtmsg, _field)
@@ -488,6 +489,7 @@ static const struct nlfield_parser nlf_p_rtmsg[] = {
        { .off_in = _IN(rtm_dst_len), .off_out = _OUT(rtm_dst_len), .cb = 
nlf_get_u8 },
        { .off_in = _IN(rtm_protocol), .off_out = _OUT(rtm_protocol), .cb = 
nlf_get_u8 },
        { .off_in = _IN(rtm_type), .off_out = _OUT(rtm_type), .cb = nlf_get_u8 
},
+       { .off_in = _IN(rtm_flags), .off_out = _OUT(rtm_flags), .cb = 
nlf_get_u32 },
 };
 #undef _IN
 #undef _OUT
@@ -581,7 +583,8 @@ handle_rtm_getroute(struct nlpcb *nlp, struct 
nl_parsed_route *attrs,
 {
        RIB_RLOCK_TRACKER;
        struct rib_head *rnh;
-       struct rtentry *rt;
+       const struct rtentry *rt;
+       struct route_nhop_data rnd;
        uint32_t fibnum = attrs->rta_table;
        sa_family_t family = attrs->rtm_family;
 
@@ -596,13 +599,17 @@ handle_rtm_getroute(struct nlpcb *nlp, struct 
nl_parsed_route *attrs,
 
        RIB_RLOCK(rnh);
 
-       rt = (struct rtentry *)rnh->rnh_matchaddr(attrs->rta_dst, &rnh->head);
+       struct sockaddr *dst = attrs->rta_dst;
+
+       if (attrs->rtm_flags & RTM_F_PREFIX)
+               rt = rib_lookup_prefix_plen(rnh, dst, attrs->rtm_dst_len, &rnd);
+       else
+               rt = (const struct rtentry *)rnh->rnh_matchaddr(dst, 
&rnh->head);
        if (rt == NULL) {
                RIB_RUNLOCK(rnh);
                return (ESRCH);
        }
 
-       struct route_nhop_data rnd;
        rt_get_rnd(rt, &rnd);
        rnd.rnd_nhop = nhop_select_func(rnd.rnd_nhop, 0);
 

Reply via email to