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>
This commit is contained in:
		
				
					committed by
					
						 David S. Miller
						David S. Miller
					
				
			
			
				
	
			
			
			
						parent
						
							5fcd266a9f
						
					
				
				
					commit
					6371a71f3a
				
			| @@ -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); | ||||
| 
 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user