diff options
author | David Ahern <dsahern@gmail.com> | 2018-10-19 21:45:30 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-10-23 04:33:29 +0200 |
commit | 6371a71f3a3b2bc47880dd76c2f176495802d0df (patch) | |
tree | 266dc6ae02e10fac338a693a94b7372375ba1af9 /net/ipv6 | |
parent | net/ipv4: Add support for dumping addresses for a specific device (diff) | |
download | linux-6371a71f3a3b2bc47880dd76c2f176495802d0df.tar.xz linux-6371a71f3a3b2bc47880dd76c2f176495802d0df.zip |
net/ipv6: Add support for dumping addresses for a specific device
If an RTM_GETADDR dump request has ifa_index set in the ifaddrmsg
header, then return only the addresses for that device.
Since inet6_dump_addr is reused for multicast and anycast addresses,
this adds support for device specfic dumps of RTM_GETMULTICAST and
RTM_GETANYCAST as well.
Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 6b659846ff8a..45b84dd5c4eb 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -4821,6 +4821,7 @@ struct inet6_fill_args { int event; unsigned int flags; int netnsid; + int ifindex; enum addr_type_t type; }; @@ -5018,8 +5019,9 @@ next: static int inet6_valid_dump_ifaddr_req(const struct nlmsghdr *nlh, struct inet6_fill_args *fillargs, struct net **tgt_net, struct sock *sk, - struct netlink_ext_ack *extack) + struct netlink_callback *cb) { + struct netlink_ext_ack *extack = cb->extack; struct nlattr *tb[IFA_MAX+1]; struct ifaddrmsg *ifm; int err, i; @@ -5034,9 +5036,11 @@ static int inet6_valid_dump_ifaddr_req(const struct nlmsghdr *nlh, NL_SET_ERR_MSG_MOD(extack, "Invalid values in header for address dump request"); return -EINVAL; } - if (ifm->ifa_index) { - NL_SET_ERR_MSG_MOD(extack, "Filter by device index not supported for address dump"); - return -EINVAL; + + fillargs->ifindex = ifm->ifa_index; + if (fillargs->ifindex) { + cb->answer_flags |= NLM_F_DUMP_FILTERED; + fillargs->flags |= NLM_F_DUMP_FILTERED; } err = nlmsg_parse_strict(nlh, sizeof(*ifm), tb, IFA_MAX, @@ -5094,9 +5098,21 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb, int err; err = inet6_valid_dump_ifaddr_req(nlh, &fillargs, &tgt_net, - skb->sk, cb->extack); + skb->sk, cb); if (err < 0) return err; + + if (fillargs.ifindex) { + dev = __dev_get_by_index(tgt_net, fillargs.ifindex); + if (!dev) + return -ENODEV; + idev = __in6_dev_get(dev); + if (idev) { + err = in6_dump_addrs(idev, skb, cb, s_ip_idx, + &fillargs); + } + goto put_tgt_net; + } } rcu_read_lock(); @@ -5124,6 +5140,7 @@ done: rcu_read_unlock(); cb->args[0] = h; cb->args[1] = idx; +put_tgt_net: if (fillargs.netnsid >= 0) put_net(tgt_net); |