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