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
This commit is contained in:
Alexander V. Chernikov 2023-04-02 13:47:10 +00:00
parent 4aeb939ecf
commit c35a43b261
3 changed files with 26 additions and 7 deletions

View File

@ -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)

View File

@ -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);

View File

@ -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);