From 0cbc51f29748968470e908657f79e070d656185e Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Tue, 6 Aug 2019 13:37:51 +0200 Subject: [PATCH] luci-lib-ip: support specifying source address in route() Signed-off-by: Jo-Philipp Wich (cherry picked from commit d73553e5303587ccecf05a91ead258054c9a70eb) --- libs/luci-lib-ip/src/ip.c | 58 +++++++++++++++++++++++----------- libs/luci-lib-ip/src/ip.luadoc | 2 ++ 2 files changed, 42 insertions(+), 18 deletions(-) diff --git a/libs/luci-lib-ip/src/ip.c b/libs/luci-lib-ip/src/ip.c index 854a0c09c2..188a70f144 100644 --- a/libs/luci-lib-ip/src/ip.c +++ b/libs/luci-lib-ip/src/ip.c @@ -1075,22 +1075,24 @@ static int cb_dump_route(struct nl_msg *msg, void *arg) bitlen = AF_BITS(rt->rtm_family); - if ((f->type && rt->rtm_type != f->type) || - (f->family && rt->rtm_family != f->family) || - (f->proto && rt->rtm_protocol != f->proto) || - (f->scope && rt->rtm_scope != f->scope) || - (f->iif && iif != f->iif) || - (f->oif && oif != f->oif) || - (f->table && table != f->table) || - diff_prefix(rt->rtm_family, from, rt->rtm_src_len, - f->from_exact, &f->from) || - diff_prefix(rt->rtm_family, dst, rt->rtm_dst_len, - f->dst_exact, &f->dst) || - diff_prefix(rt->rtm_family, gw, bitlen, - false, &f->gw) || - diff_prefix(rt->rtm_family, src, bitlen, - false, &f->src)) - goto out; + if (!f->get) { + if ((f->type && rt->rtm_type != f->type) || + (f->family && rt->rtm_family != f->family) || + (f->proto && rt->rtm_protocol != f->proto) || + (f->scope && rt->rtm_scope != f->scope) || + (f->iif && iif != f->iif) || + (f->oif && oif != f->oif) || + (f->table && table != f->table) || + diff_prefix(rt->rtm_family, from, rt->rtm_src_len, + f->from_exact, &f->from) || + diff_prefix(rt->rtm_family, dst, rt->rtm_dst_len, + f->dst_exact, &f->dst) || + diff_prefix(rt->rtm_family, gw, bitlen, + false, &f->gw) || + diff_prefix(rt->rtm_family, src, bitlen, + false, &f->src)) + goto out; + } if (s->callback) lua_pushvalue(s->L, 2); @@ -1216,10 +1218,15 @@ static int _route_dump(lua_State *L, struct dump_filter *filter) nlmsg_append(msg, &rtm, sizeof(rtm), 0); - if (filter->get) + if (filter->get) { nla_put(msg, RTA_DST, AF_BYTES(filter->dst.family), &filter->dst.addr.v6); + if (filter->src.family) + nla_put(msg, RTA_SRC, AF_BYTES(filter->src.family), + &filter->src.addr.v6); + } + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_dump_route, &s); nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_done, &s); nl_cb_err(cb, NL_CB_CUSTOM, cb_error, &s); @@ -1236,17 +1243,32 @@ static int _route_dump(lua_State *L, struct dump_filter *filter) out: nl_cb_put(cb); - return (s.callback == 0); + + if (s.callback) + return 0; + + if (!filter->get) + return 1; + + return (s.index > 0); } static int route_get(lua_State *L) { struct dump_filter filter = { .get = true }; const char *dest = luaL_checkstring(L, 1); + const char *from = luaL_optstring(L, 2, NULL); if (!parse_cidr(dest, &filter.dst)) return _error(L, -1, "Invalid destination"); + if (from && !parse_cidr(from, &filter.src)) + return _error(L, -1, "Invalid source"); + + if (filter.src.family != 0 && + filter.src.family != filter.dst.family) + return _error(L, -1, "Different source/destination family"); + filter.family = filter.dst.family; return _route_dump(L, &filter); diff --git a/libs/luci-lib-ip/src/ip.luadoc b/libs/luci-lib-ip/src/ip.luadoc index b1ecae1453..f4e9920455 100644 --- a/libs/luci-lib-ip/src/ip.luadoc +++ b/libs/luci-lib-ip/src/ip.luadoc @@ -178,6 +178,8 @@ Determine the route leading to the given destination. @name route @param address A `luci.ip.cidr` instance or a string containing a valid IPv4 or IPv6 range as specified by `luci.ip.new()`. +@param source A `luci.ip.cidr` instance or a string containing +the preferred source address for route selection (optional). @return

Table containing the fields described below.

-- 2.30.2
FieldDescription