diff options
author | Thomas Graf <tgraf@suug.ch> | 2006-08-07 21:00:18 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-09-22 17:54:03 -0400 |
commit | ca860fb39b4aa1479e2fea67435a2c1eac9ce789 (patch) | |
tree | 02437f9e08c0cd001cef7e74adcb0f26c418f60c | |
parent | 6b3f8674bccbb2e784d01e44373fb730af6cb149 (diff) |
[NEIGH]: Convert neighbour table dumping to new netlink api
Also fixes skipping of already dumped neighbours.
Signed-off-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/core/neighbour.c | 141 |
1 files changed, 74 insertions, 67 deletions
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 5a0b8f48a099..2f4e06a13457 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
@@ -1597,56 +1597,59 @@ out: | |||
1597 | 1597 | ||
1598 | static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms) | 1598 | static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms) |
1599 | { | 1599 | { |
1600 | struct rtattr *nest = NULL; | 1600 | struct nlattr *nest; |
1601 | 1601 | ||
1602 | nest = RTA_NEST(skb, NDTA_PARMS); | 1602 | nest = nla_nest_start(skb, NDTA_PARMS); |
1603 | if (nest == NULL) | ||
1604 | return -ENOBUFS; | ||
1603 | 1605 | ||
1604 | if (parms->dev) | 1606 | if (parms->dev) |
1605 | RTA_PUT_U32(skb, NDTPA_IFINDEX, parms->dev->ifindex); | 1607 | NLA_PUT_U32(skb, NDTPA_IFINDEX, parms->dev->ifindex); |
1606 | 1608 | ||
1607 | RTA_PUT_U32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt)); | 1609 | NLA_PUT_U32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt)); |
1608 | RTA_PUT_U32(skb, NDTPA_QUEUE_LEN, parms->queue_len); | 1610 | NLA_PUT_U32(skb, NDTPA_QUEUE_LEN, parms->queue_len); |
1609 | RTA_PUT_U32(skb, NDTPA_PROXY_QLEN, parms->proxy_qlen); | 1611 | NLA_PUT_U32(skb, NDTPA_PROXY_QLEN, parms->proxy_qlen); |
1610 | RTA_PUT_U32(skb, NDTPA_APP_PROBES, parms->app_probes); | 1612 | NLA_PUT_U32(skb, NDTPA_APP_PROBES, parms->app_probes); |
1611 | RTA_PUT_U32(skb, NDTPA_UCAST_PROBES, parms->ucast_probes); | 1613 | NLA_PUT_U32(skb, NDTPA_UCAST_PROBES, parms->ucast_probes); |
1612 | RTA_PUT_U32(skb, NDTPA_MCAST_PROBES, parms->mcast_probes); | 1614 | NLA_PUT_U32(skb, NDTPA_MCAST_PROBES, parms->mcast_probes); |
1613 | RTA_PUT_MSECS(skb, NDTPA_REACHABLE_TIME, parms->reachable_time); | 1615 | NLA_PUT_MSECS(skb, NDTPA_REACHABLE_TIME, parms->reachable_time); |
1614 | RTA_PUT_MSECS(skb, NDTPA_BASE_REACHABLE_TIME, | 1616 | NLA_PUT_MSECS(skb, NDTPA_BASE_REACHABLE_TIME, |
1615 | parms->base_reachable_time); | 1617 | parms->base_reachable_time); |
1616 | RTA_PUT_MSECS(skb, NDTPA_GC_STALETIME, parms->gc_staletime); | 1618 | NLA_PUT_MSECS(skb, NDTPA_GC_STALETIME, parms->gc_staletime); |
1617 | RTA_PUT_MSECS(skb, NDTPA_DELAY_PROBE_TIME, parms->delay_probe_time); | 1619 | NLA_PUT_MSECS(skb, NDTPA_DELAY_PROBE_TIME, parms->delay_probe_time); |
1618 | RTA_PUT_MSECS(skb, NDTPA_RETRANS_TIME, parms->retrans_time); | 1620 | NLA_PUT_MSECS(skb, NDTPA_RETRANS_TIME, parms->retrans_time); |
1619 | RTA_PUT_MSECS(skb, NDTPA_ANYCAST_DELAY, parms->anycast_delay); | 1621 | NLA_PUT_MSECS(skb, NDTPA_ANYCAST_DELAY, parms->anycast_delay); |
1620 | RTA_PUT_MSECS(skb, NDTPA_PROXY_DELAY, parms->proxy_delay); | 1622 | NLA_PUT_MSECS(skb, NDTPA_PROXY_DELAY, parms->proxy_delay); |
1621 | RTA_PUT_MSECS(skb, NDTPA_LOCKTIME, parms->locktime); | 1623 | NLA_PUT_MSECS(skb, NDTPA_LOCKTIME, parms->locktime); |
1622 | 1624 | ||
1623 | return RTA_NEST_END(skb, nest); | 1625 | return nla_nest_end(skb, nest); |
1624 | 1626 | ||
1625 | rtattr_failure: | 1627 | nla_put_failure: |
1626 | return RTA_NEST_CANCEL(skb, nest); | 1628 | return nla_nest_cancel(skb, nest); |
1627 | } | 1629 | } |
1628 | 1630 | ||
1629 | static int neightbl_fill_info(struct neigh_table *tbl, struct sk_buff *skb, | 1631 | static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl, |
1630 | struct netlink_callback *cb) | 1632 | u32 pid, u32 seq, int type, int flags) |
1631 | { | 1633 | { |
1632 | struct nlmsghdr *nlh; | 1634 | struct nlmsghdr *nlh; |
1633 | struct ndtmsg *ndtmsg; | 1635 | struct ndtmsg *ndtmsg; |
1634 | 1636 | ||
1635 | nlh = NLMSG_NEW_ANSWER(skb, cb, RTM_NEWNEIGHTBL, sizeof(struct ndtmsg), | 1637 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags); |
1636 | NLM_F_MULTI); | 1638 | if (nlh == NULL) |
1639 | return -ENOBUFS; | ||
1637 | 1640 | ||
1638 | ndtmsg = NLMSG_DATA(nlh); | 1641 | ndtmsg = nlmsg_data(nlh); |
1639 | 1642 | ||
1640 | read_lock_bh(&tbl->lock); | 1643 | read_lock_bh(&tbl->lock); |
1641 | ndtmsg->ndtm_family = tbl->family; | 1644 | ndtmsg->ndtm_family = tbl->family; |
1642 | ndtmsg->ndtm_pad1 = 0; | 1645 | ndtmsg->ndtm_pad1 = 0; |
1643 | ndtmsg->ndtm_pad2 = 0; | 1646 | ndtmsg->ndtm_pad2 = 0; |
1644 | 1647 | ||
1645 | RTA_PUT_STRING(skb, NDTA_NAME, tbl->id); | 1648 | NLA_PUT_STRING(skb, NDTA_NAME, tbl->id); |
1646 | RTA_PUT_MSECS(skb, NDTA_GC_INTERVAL, tbl->gc_interval); | 1649 | NLA_PUT_MSECS(skb, NDTA_GC_INTERVAL, tbl->gc_interval); |
1647 | RTA_PUT_U32(skb, NDTA_THRESH1, tbl->gc_thresh1); | 1650 | NLA_PUT_U32(skb, NDTA_THRESH1, tbl->gc_thresh1); |
1648 | RTA_PUT_U32(skb, NDTA_THRESH2, tbl->gc_thresh2); | 1651 | NLA_PUT_U32(skb, NDTA_THRESH2, tbl->gc_thresh2); |
1649 | RTA_PUT_U32(skb, NDTA_THRESH3, tbl->gc_thresh3); | 1652 | NLA_PUT_U32(skb, NDTA_THRESH3, tbl->gc_thresh3); |
1650 | 1653 | ||
1651 | { | 1654 | { |
1652 | unsigned long now = jiffies; | 1655 | unsigned long now = jiffies; |
@@ -1665,7 +1668,7 @@ static int neightbl_fill_info(struct neigh_table *tbl, struct sk_buff *skb, | |||
1665 | .ndtc_proxy_qlen = tbl->proxy_queue.qlen, | 1668 | .ndtc_proxy_qlen = tbl->proxy_queue.qlen, |
1666 | }; | 1669 | }; |
1667 | 1670 | ||
1668 | RTA_PUT(skb, NDTA_CONFIG, sizeof(ndc), &ndc); | 1671 | NLA_PUT(skb, NDTA_CONFIG, sizeof(ndc), &ndc); |
1669 | } | 1672 | } |
1670 | 1673 | ||
1671 | { | 1674 | { |
@@ -1690,55 +1693,50 @@ static int neightbl_fill_info(struct neigh_table *tbl, struct sk_buff *skb, | |||
1690 | ndst.ndts_forced_gc_runs += st->forced_gc_runs; | 1693 | ndst.ndts_forced_gc_runs += st->forced_gc_runs; |
1691 | } | 1694 | } |
1692 | 1695 | ||
1693 | RTA_PUT(skb, NDTA_STATS, sizeof(ndst), &ndst); | 1696 | NLA_PUT(skb, NDTA_STATS, sizeof(ndst), &ndst); |
1694 | } | 1697 | } |
1695 | 1698 | ||
1696 | BUG_ON(tbl->parms.dev); | 1699 | BUG_ON(tbl->parms.dev); |
1697 | if (neightbl_fill_parms(skb, &tbl->parms) < 0) | 1700 | if (neightbl_fill_parms(skb, &tbl->parms) < 0) |
1698 | goto rtattr_failure; | 1701 | goto nla_put_failure; |
1699 | 1702 | ||
1700 | read_unlock_bh(&tbl->lock); | 1703 | read_unlock_bh(&tbl->lock); |
1701 | return NLMSG_END(skb, nlh); | 1704 | return nlmsg_end(skb, nlh); |
1702 | 1705 | ||
1703 | rtattr_failure: | 1706 | nla_put_failure: |
1704 | read_unlock_bh(&tbl->lock); | 1707 | read_unlock_bh(&tbl->lock); |
1705 | return NLMSG_CANCEL(skb, nlh); | 1708 | return nlmsg_cancel(skb, nlh); |
1706 | |||
1707 | nlmsg_failure: | ||
1708 | return -1; | ||
1709 | } | 1709 | } |
1710 | 1710 | ||
1711 | static int neightbl_fill_param_info(struct neigh_table *tbl, | 1711 | static int neightbl_fill_param_info(struct sk_buff *skb, |
1712 | struct neigh_table *tbl, | ||
1712 | struct neigh_parms *parms, | 1713 | struct neigh_parms *parms, |
1713 | struct sk_buff *skb, | 1714 | u32 pid, u32 seq, int type, |
1714 | struct netlink_callback *cb) | 1715 | unsigned int flags) |
1715 | { | 1716 | { |
1716 | struct ndtmsg *ndtmsg; | 1717 | struct ndtmsg *ndtmsg; |
1717 | struct nlmsghdr *nlh; | 1718 | struct nlmsghdr *nlh; |
1718 | 1719 | ||
1719 | nlh = NLMSG_NEW_ANSWER(skb, cb, RTM_NEWNEIGHTBL, sizeof(struct ndtmsg), | 1720 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags); |
1720 | NLM_F_MULTI); | 1721 | if (nlh == NULL) |
1722 | return -ENOBUFS; | ||
1721 | 1723 | ||
1722 | ndtmsg = NLMSG_DATA(nlh); | 1724 | ndtmsg = nlmsg_data(nlh); |
1723 | 1725 | ||
1724 | read_lock_bh(&tbl->lock); | 1726 | read_lock_bh(&tbl->lock); |
1725 | ndtmsg->ndtm_family = tbl->family; | 1727 | ndtmsg->ndtm_family = tbl->family; |
1726 | ndtmsg->ndtm_pad1 = 0; | 1728 | ndtmsg->ndtm_pad1 = 0; |
1727 | ndtmsg->ndtm_pad2 = 0; | 1729 | ndtmsg->ndtm_pad2 = 0; |
1728 | RTA_PUT_STRING(skb, NDTA_NAME, tbl->id); | ||
1729 | 1730 | ||
1730 | if (neightbl_fill_parms(skb, parms) < 0) | 1731 | if (nla_put_string(skb, NDTA_NAME, tbl->id) < 0 || |
1731 | goto rtattr_failure; | 1732 | neightbl_fill_parms(skb, parms) < 0) |
1733 | goto errout; | ||
1732 | 1734 | ||
1733 | read_unlock_bh(&tbl->lock); | 1735 | read_unlock_bh(&tbl->lock); |
1734 | return NLMSG_END(skb, nlh); | 1736 | return nlmsg_end(skb, nlh); |
1735 | 1737 | errout: | |
1736 | rtattr_failure: | ||
1737 | read_unlock_bh(&tbl->lock); | 1738 | read_unlock_bh(&tbl->lock); |
1738 | return NLMSG_CANCEL(skb, nlh); | 1739 | return nlmsg_cancel(skb, nlh); |
1739 | |||
1740 | nlmsg_failure: | ||
1741 | return -1; | ||
1742 | } | 1740 | } |
1743 | 1741 | ||
1744 | static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl, | 1742 | static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl, |
@@ -1905,34 +1903,43 @@ errout: | |||
1905 | 1903 | ||
1906 | int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb) | 1904 | int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb) |
1907 | { | 1905 | { |
1908 | int idx, family; | 1906 | int family, tidx, nidx = 0; |
1909 | int s_idx = cb->args[0]; | 1907 | int tbl_skip = cb->args[0]; |
1908 | int neigh_skip = cb->args[1]; | ||
1910 | struct neigh_table *tbl; | 1909 | struct neigh_table *tbl; |
1911 | 1910 | ||
1912 | family = ((struct rtgenmsg *)NLMSG_DATA(cb->nlh))->rtgen_family; | 1911 | family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family; |
1913 | 1912 | ||
1914 | read_lock(&neigh_tbl_lock); | 1913 | read_lock(&neigh_tbl_lock); |
1915 | for (tbl = neigh_tables, idx = 0; tbl; tbl = tbl->next) { | 1914 | for (tbl = neigh_tables, tidx = 0; tbl; tbl = tbl->next, tidx++) { |
1916 | struct neigh_parms *p; | 1915 | struct neigh_parms *p; |
1917 | 1916 | ||
1918 | if (idx < s_idx || (family && tbl->family != family)) | 1917 | if (tidx < tbl_skip || (family && tbl->family != family)) |
1919 | continue; | 1918 | continue; |
1920 | 1919 | ||
1921 | if (neightbl_fill_info(tbl, skb, cb) <= 0) | 1920 | if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).pid, |
1921 | cb->nlh->nlmsg_seq, RTM_NEWNEIGHTBL, | ||
1922 | NLM_F_MULTI) <= 0) | ||
1922 | break; | 1923 | break; |
1923 | 1924 | ||
1924 | for (++idx, p = tbl->parms.next; p; p = p->next, idx++) { | 1925 | for (nidx = 0, p = tbl->parms.next; p; p = p->next, nidx++) { |
1925 | if (idx < s_idx) | 1926 | if (nidx < neigh_skip) |
1926 | continue; | 1927 | continue; |
1927 | 1928 | ||
1928 | if (neightbl_fill_param_info(tbl, p, skb, cb) <= 0) | 1929 | if (neightbl_fill_param_info(skb, tbl, p, |
1930 | NETLINK_CB(cb->skb).pid, | ||
1931 | cb->nlh->nlmsg_seq, | ||
1932 | RTM_NEWNEIGHTBL, | ||
1933 | NLM_F_MULTI) <= 0) | ||
1929 | goto out; | 1934 | goto out; |
1930 | } | 1935 | } |
1931 | 1936 | ||
1937 | neigh_skip = 0; | ||
1932 | } | 1938 | } |
1933 | out: | 1939 | out: |
1934 | read_unlock(&neigh_tbl_lock); | 1940 | read_unlock(&neigh_tbl_lock); |
1935 | cb->args[0] = idx; | 1941 | cb->args[0] = tidx; |
1942 | cb->args[1] = nidx; | ||
1936 | 1943 | ||
1937 | return skb->len; | 1944 | return skb->len; |
1938 | } | 1945 | } |