aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv4/devinet.c49
1 files changed, 34 insertions, 15 deletions
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index d122ebbe5980..67f382c560ba 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1713,6 +1713,32 @@ static int inet_valid_dump_ifaddr_req(const struct nlmsghdr *nlh,
1713 return 0; 1713 return 0;
1714} 1714}
1715 1715
1716static int in_dev_dump_addr(struct in_device *in_dev, struct sk_buff *skb,
1717 struct netlink_callback *cb, int s_ip_idx,
1718 struct inet_fill_args *fillargs)
1719{
1720 struct in_ifaddr *ifa;
1721 int ip_idx = 0;
1722 int err;
1723
1724 for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next, ip_idx++) {
1725 if (ip_idx < s_ip_idx)
1726 continue;
1727
1728 err = inet_fill_ifaddr(skb, ifa, fillargs);
1729 if (err < 0)
1730 goto done;
1731
1732 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
1733 }
1734 err = 0;
1735
1736done:
1737 cb->args[2] = ip_idx;
1738
1739 return err;
1740}
1741
1716static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) 1742static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
1717{ 1743{
1718 const struct nlmsghdr *nlh = cb->nlh; 1744 const struct nlmsghdr *nlh = cb->nlh;
@@ -1727,19 +1753,17 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
1727 struct net *tgt_net = net; 1753 struct net *tgt_net = net;
1728 int h, s_h; 1754 int h, s_h;
1729 int idx, s_idx; 1755 int idx, s_idx;
1730 int ip_idx, s_ip_idx; 1756 int s_ip_idx;
1731 struct net_device *dev; 1757 struct net_device *dev;
1732 struct in_device *in_dev; 1758 struct in_device *in_dev;
1733 struct in_ifaddr *ifa;
1734 struct hlist_head *head; 1759 struct hlist_head *head;
1760 int err;
1735 1761
1736 s_h = cb->args[0]; 1762 s_h = cb->args[0];
1737 s_idx = idx = cb->args[1]; 1763 s_idx = idx = cb->args[1];
1738 s_ip_idx = ip_idx = cb->args[2]; 1764 s_ip_idx = cb->args[2];
1739 1765
1740 if (cb->strict_check) { 1766 if (cb->strict_check) {
1741 int err;
1742
1743 err = inet_valid_dump_ifaddr_req(nlh, &fillargs, &tgt_net, 1767 err = inet_valid_dump_ifaddr_req(nlh, &fillargs, &tgt_net,
1744 skb->sk, cb->extack); 1768 skb->sk, cb->extack);
1745 if (err < 0) 1769 if (err < 0)
@@ -1761,15 +1785,11 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
1761 if (!in_dev) 1785 if (!in_dev)
1762 goto cont; 1786 goto cont;
1763 1787
1764 for (ifa = in_dev->ifa_list, ip_idx = 0; ifa; 1788 err = in_dev_dump_addr(in_dev, skb, cb, s_ip_idx,
1765 ifa = ifa->ifa_next, ip_idx++) { 1789 &fillargs);
1766 if (ip_idx < s_ip_idx) 1790 if (err < 0) {
1767 continue; 1791 rcu_read_unlock();
1768 if (inet_fill_ifaddr(skb, ifa, &fillargs) < 0) { 1792 goto done;
1769 rcu_read_unlock();
1770 goto done;
1771 }
1772 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
1773 } 1793 }
1774cont: 1794cont:
1775 idx++; 1795 idx++;
@@ -1780,7 +1800,6 @@ cont:
1780done: 1800done:
1781 cb->args[0] = h; 1801 cb->args[0] = h;
1782 cb->args[1] = idx; 1802 cb->args[1] = idx;
1783 cb->args[2] = ip_idx;
1784 if (fillargs.netnsid >= 0) 1803 if (fillargs.netnsid >= 0)
1785 put_net(tgt_net); 1804 put_net(tgt_net);
1786 1805