aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2006-08-07 21:00:18 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-09-22 17:54:03 -0400
commitca860fb39b4aa1479e2fea67435a2c1eac9ce789 (patch)
tree02437f9e08c0cd001cef7e74adcb0f26c418f60c
parent6b3f8674bccbb2e784d01e44373fb730af6cb149 (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.c141
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
1598static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms) 1598static 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
1625rtattr_failure: 1627nla_put_failure:
1626 return RTA_NEST_CANCEL(skb, nest); 1628 return nla_nest_cancel(skb, nest);
1627} 1629}
1628 1630
1629static int neightbl_fill_info(struct neigh_table *tbl, struct sk_buff *skb, 1631static 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
1703rtattr_failure: 1706nla_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
1707nlmsg_failure:
1708 return -1;
1709} 1709}
1710 1710
1711static int neightbl_fill_param_info(struct neigh_table *tbl, 1711static 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 1737errout:
1736rtattr_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
1740nlmsg_failure:
1741 return -1;
1742} 1740}
1743 1741
1744static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl, 1742static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl,
@@ -1905,34 +1903,43 @@ errout:
1905 1903
1906int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb) 1904int 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 }
1933out: 1939out:
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}