iproute: "list/flush/save default" selected all of the routes

When running "ip route list default" and not specifying address family,
one will get all of the routes instead of just default only. The same
is for "exact default" and "match default".

It behaves in such a way because default route with unspecified family
has the same all-zeroes value like no prefix specified at all. Thus
following code blindly ignores the fact, that prefix was actually
specified.

This patch adds the flag PREFIXLEN_SPECIFIED to the default route too.
And then checks its value when filtering routes.

Signed-off-by: Alexander Zubkov <green@msu.ru>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
This commit is contained in:
Alexander Zubkov 2017-12-17 12:09:00 +01:00 committed by Stephen Hemminger
parent ed7fdc950d
commit 9135c4d603
2 changed files with 47 additions and 19 deletions

View File

@ -191,20 +191,42 @@ static int filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len)
return 0;
if ((filter.tos^r->rtm_tos)&filter.tosmask)
return 0;
if (filter.rdst.family &&
(r->rtm_family != filter.rdst.family || filter.rdst.bitlen > r->rtm_dst_len))
return 0;
if (filter.mdst.family &&
(r->rtm_family != filter.mdst.family ||
(filter.mdst.bitlen >= 0 && filter.mdst.bitlen < r->rtm_dst_len)))
return 0;
if (filter.rsrc.family &&
(r->rtm_family != filter.rsrc.family || filter.rsrc.bitlen > r->rtm_src_len))
return 0;
if (filter.msrc.family &&
(r->rtm_family != filter.msrc.family ||
(filter.msrc.bitlen >= 0 && filter.msrc.bitlen < r->rtm_src_len)))
return 0;
if (filter.rdst.family) {
if (r->rtm_family != filter.rdst.family ||
filter.rdst.bitlen > r->rtm_dst_len)
return 0;
} else if (filter.rdst.flags & PREFIXLEN_SPECIFIED) {
if (filter.rdst.bitlen > r->rtm_dst_len)
return 0;
}
if (filter.mdst.family) {
if (r->rtm_family != filter.mdst.family ||
(filter.mdst.bitlen >= 0 &&
filter.mdst.bitlen < r->rtm_dst_len))
return 0;
} else if (filter.mdst.flags & PREFIXLEN_SPECIFIED) {
if (filter.mdst.bitlen >= 0 &&
filter.mdst.bitlen < r->rtm_dst_len)
return 0;
}
if (filter.rsrc.family) {
if (r->rtm_family != filter.rsrc.family ||
filter.rsrc.bitlen > r->rtm_src_len)
return 0;
} else if (filter.rsrc.flags & PREFIXLEN_SPECIFIED) {
if (filter.rsrc.bitlen > r->rtm_src_len)
return 0;
}
if (filter.msrc.family) {
if (r->rtm_family != filter.msrc.family ||
(filter.msrc.bitlen >= 0 &&
filter.msrc.bitlen < r->rtm_src_len))
return 0;
} else if (filter.msrc.flags & PREFIXLEN_SPECIFIED) {
if (filter.msrc.bitlen >= 0 &&
filter.msrc.bitlen < r->rtm_src_len)
return 0;
}
if (filter.rvia.family) {
int family = r->rtm_family;
@ -221,7 +243,9 @@ static int filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len)
if (tb[RTA_DST])
memcpy(&dst.data, RTA_DATA(tb[RTA_DST]), (r->rtm_dst_len+7)/8);
if (filter.rsrc.family || filter.msrc.family) {
if (filter.rsrc.family || filter.msrc.family ||
filter.rsrc.flags & PREFIXLEN_SPECIFIED ||
filter.msrc.flags & PREFIXLEN_SPECIFIED) {
if (tb[RTA_SRC])
memcpy(&src.data, RTA_DATA(tb[RTA_SRC]), (r->rtm_src_len+7)/8);
}
@ -241,15 +265,18 @@ static int filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len)
memcpy(&prefsrc.data, RTA_DATA(tb[RTA_PREFSRC]), host_len/8);
}
if (filter.rdst.family && inet_addr_match(&dst, &filter.rdst, filter.rdst.bitlen))
if ((filter.rdst.family || filter.rdst.flags & PREFIXLEN_SPECIFIED) &&
inet_addr_match(&dst, &filter.rdst, filter.rdst.bitlen))
return 0;
if (filter.mdst.family && filter.mdst.bitlen >= 0 &&
if ((filter.mdst.family || filter.mdst.flags & PREFIXLEN_SPECIFIED) &&
inet_addr_match(&dst, &filter.mdst, r->rtm_dst_len))
return 0;
if (filter.rsrc.family && inet_addr_match(&src, &filter.rsrc, filter.rsrc.bitlen))
if ((filter.rsrc.family || filter.rsrc.flags & PREFIXLEN_SPECIFIED) &&
inet_addr_match(&src, &filter.rsrc, filter.rsrc.bitlen))
return 0;
if (filter.msrc.family && filter.msrc.bitlen >= 0 &&
if ((filter.msrc.family || filter.msrc.flags & PREFIXLEN_SPECIFIED) &&
filter.msrc.bitlen >= 0 &&
inet_addr_match(&src, &filter.msrc, r->rtm_src_len))
return 0;

View File

@ -658,6 +658,7 @@ int get_prefix_1(inet_prefix *dst, char *arg, int family)
dst->family = family;
dst->bytelen = 0;
dst->bitlen = 0;
dst->flags |= PREFIXLEN_SPECIFIED;
return 0;
}