aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/neighbour.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/neighbour.c')
-rw-r--r--net/core/neighbour.c317
1 files changed, 314 insertions, 3 deletions
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 43bdc521e20d..0841ac78c67d 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1276,9 +1276,14 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
1276 INIT_RCU_HEAD(&p->rcu_head); 1276 INIT_RCU_HEAD(&p->rcu_head);
1277 p->reachable_time = 1277 p->reachable_time =
1278 neigh_rand_reach_time(p->base_reachable_time); 1278 neigh_rand_reach_time(p->base_reachable_time);
1279 if (dev && dev->neigh_setup && dev->neigh_setup(dev, p)) { 1279 if (dev) {
1280 kfree(p); 1280 if (dev->neigh_setup && dev->neigh_setup(dev, p)) {
1281 return NULL; 1281 kfree(p);
1282 return NULL;
1283 }
1284
1285 dev_hold(dev);
1286 p->dev = dev;
1282 } 1287 }
1283 p->sysctl_table = NULL; 1288 p->sysctl_table = NULL;
1284 write_lock_bh(&tbl->lock); 1289 write_lock_bh(&tbl->lock);
@@ -1309,6 +1314,8 @@ void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
1309 *p = parms->next; 1314 *p = parms->next;
1310 parms->dead = 1; 1315 parms->dead = 1;
1311 write_unlock_bh(&tbl->lock); 1316 write_unlock_bh(&tbl->lock);
1317 if (parms->dev)
1318 dev_put(parms->dev);
1312 call_rcu(&parms->rcu_head, neigh_rcu_free_parms); 1319 call_rcu(&parms->rcu_head, neigh_rcu_free_parms);
1313 return; 1320 return;
1314 } 1321 }
@@ -1546,6 +1553,308 @@ out:
1546 return err; 1553 return err;
1547} 1554}
1548 1555
1556static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
1557{
1558 struct rtattr *nest = RTA_NEST(skb, NDTA_PARMS);
1559
1560 if (parms->dev)
1561 RTA_PUT_U32(skb, NDTPA_IFINDEX, parms->dev->ifindex);
1562
1563 RTA_PUT_U32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt));
1564 RTA_PUT_U32(skb, NDTPA_QUEUE_LEN, parms->queue_len);
1565 RTA_PUT_U32(skb, NDTPA_PROXY_QLEN, parms->proxy_qlen);
1566 RTA_PUT_U32(skb, NDTPA_APP_PROBES, parms->app_probes);
1567 RTA_PUT_U32(skb, NDTPA_UCAST_PROBES, parms->ucast_probes);
1568 RTA_PUT_U32(skb, NDTPA_MCAST_PROBES, parms->mcast_probes);
1569 RTA_PUT_MSECS(skb, NDTPA_REACHABLE_TIME, parms->reachable_time);
1570 RTA_PUT_MSECS(skb, NDTPA_BASE_REACHABLE_TIME,
1571 parms->base_reachable_time);
1572 RTA_PUT_MSECS(skb, NDTPA_GC_STALETIME, parms->gc_staletime);
1573 RTA_PUT_MSECS(skb, NDTPA_DELAY_PROBE_TIME, parms->delay_probe_time);
1574 RTA_PUT_MSECS(skb, NDTPA_RETRANS_TIME, parms->retrans_time);
1575 RTA_PUT_MSECS(skb, NDTPA_ANYCAST_DELAY, parms->anycast_delay);
1576 RTA_PUT_MSECS(skb, NDTPA_PROXY_DELAY, parms->proxy_delay);
1577 RTA_PUT_MSECS(skb, NDTPA_LOCKTIME, parms->locktime);
1578
1579 return RTA_NEST_END(skb, nest);
1580
1581rtattr_failure:
1582 return RTA_NEST_CANCEL(skb, nest);
1583}
1584
1585static int neightbl_fill_info(struct neigh_table *tbl, struct sk_buff *skb,
1586 struct netlink_callback *cb)
1587{
1588 struct nlmsghdr *nlh;
1589 struct ndtmsg *ndtmsg;
1590
1591 nlh = NLMSG_PUT_ANSWER(skb, cb, RTM_NEWNEIGHTBL, sizeof(struct ndtmsg));
1592 ndtmsg = NLMSG_DATA(nlh);
1593
1594 NLMSG_SET_MULTIPART(nlh);
1595
1596 read_lock_bh(&tbl->lock);
1597 ndtmsg->ndtm_family = tbl->family;
1598
1599 RTA_PUT_STRING(skb, NDTA_NAME, tbl->id);
1600 RTA_PUT_MSECS(skb, NDTA_GC_INTERVAL, tbl->gc_interval);
1601 RTA_PUT_U32(skb, NDTA_THRESH1, tbl->gc_thresh1);
1602 RTA_PUT_U32(skb, NDTA_THRESH2, tbl->gc_thresh2);
1603 RTA_PUT_U32(skb, NDTA_THRESH3, tbl->gc_thresh3);
1604
1605 {
1606 unsigned long now = jiffies;
1607 unsigned int flush_delta = now - tbl->last_flush;
1608 unsigned int rand_delta = now - tbl->last_rand;
1609
1610 struct ndt_config ndc = {
1611 .ndtc_key_len = tbl->key_len,
1612 .ndtc_entry_size = tbl->entry_size,
1613 .ndtc_entries = atomic_read(&tbl->entries),
1614 .ndtc_last_flush = jiffies_to_msecs(flush_delta),
1615 .ndtc_last_rand = jiffies_to_msecs(rand_delta),
1616 .ndtc_hash_rnd = tbl->hash_rnd,
1617 .ndtc_hash_mask = tbl->hash_mask,
1618 .ndtc_hash_chain_gc = tbl->hash_chain_gc,
1619 .ndtc_proxy_qlen = tbl->proxy_queue.qlen,
1620 };
1621
1622 RTA_PUT(skb, NDTA_CONFIG, sizeof(ndc), &ndc);
1623 }
1624
1625 {
1626 int cpu;
1627 struct ndt_stats ndst;
1628
1629 memset(&ndst, 0, sizeof(ndst));
1630
1631 for (cpu = 0; cpu < NR_CPUS; cpu++) {
1632 struct neigh_statistics *st;
1633
1634 if (!cpu_possible(cpu))
1635 continue;
1636
1637 st = per_cpu_ptr(tbl->stats, cpu);
1638 ndst.ndts_allocs += st->allocs;
1639 ndst.ndts_destroys += st->destroys;
1640 ndst.ndts_hash_grows += st->hash_grows;
1641 ndst.ndts_res_failed += st->res_failed;
1642 ndst.ndts_lookups += st->lookups;
1643 ndst.ndts_hits += st->hits;
1644 ndst.ndts_rcv_probes_mcast += st->rcv_probes_mcast;
1645 ndst.ndts_rcv_probes_ucast += st->rcv_probes_ucast;
1646 ndst.ndts_periodic_gc_runs += st->periodic_gc_runs;
1647 ndst.ndts_forced_gc_runs += st->forced_gc_runs;
1648 }
1649
1650 RTA_PUT(skb, NDTA_STATS, sizeof(ndst), &ndst);
1651 }
1652
1653 BUG_ON(tbl->parms.dev);
1654 if (neightbl_fill_parms(skb, &tbl->parms) < 0)
1655 goto rtattr_failure;
1656
1657 read_unlock_bh(&tbl->lock);
1658 return NLMSG_END(skb, nlh);
1659
1660rtattr_failure:
1661 read_unlock_bh(&tbl->lock);
1662 return NLMSG_CANCEL(skb, nlh);
1663
1664nlmsg_failure:
1665 return -1;
1666}
1667
1668static int neightbl_fill_param_info(struct neigh_table *tbl,
1669 struct neigh_parms *parms,
1670 struct sk_buff *skb,
1671 struct netlink_callback *cb)
1672{
1673 struct ndtmsg *ndtmsg;
1674 struct nlmsghdr *nlh;
1675
1676 nlh = NLMSG_PUT_ANSWER(skb, cb, RTM_NEWNEIGHTBL, sizeof(struct ndtmsg));
1677 ndtmsg = NLMSG_DATA(nlh);
1678
1679 NLMSG_SET_MULTIPART(nlh);
1680
1681 read_lock_bh(&tbl->lock);
1682 ndtmsg->ndtm_family = tbl->family;
1683 RTA_PUT_STRING(skb, NDTA_NAME, tbl->id);
1684
1685 if (neightbl_fill_parms(skb, parms) < 0)
1686 goto rtattr_failure;
1687
1688 read_unlock_bh(&tbl->lock);
1689 return NLMSG_END(skb, nlh);
1690
1691rtattr_failure:
1692 read_unlock_bh(&tbl->lock);
1693 return NLMSG_CANCEL(skb, nlh);
1694
1695nlmsg_failure:
1696 return -1;
1697}
1698
1699static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl,
1700 int ifindex)
1701{
1702 struct neigh_parms *p;
1703
1704 for (p = &tbl->parms; p; p = p->next)
1705 if ((p->dev && p->dev->ifindex == ifindex) ||
1706 (!p->dev && !ifindex))
1707 return p;
1708
1709 return NULL;
1710}
1711
1712int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
1713{
1714 struct neigh_table *tbl;
1715 struct ndtmsg *ndtmsg = NLMSG_DATA(nlh);
1716 struct rtattr **tb = arg;
1717 int err = -EINVAL;
1718
1719 if (!tb[NDTA_NAME - 1] || !RTA_PAYLOAD(tb[NDTA_NAME - 1]))
1720 return -EINVAL;
1721
1722 read_lock(&neigh_tbl_lock);
1723 for (tbl = neigh_tables; tbl; tbl = tbl->next) {
1724 if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
1725 continue;
1726
1727 if (!rtattr_strcmp(tb[NDTA_NAME - 1], tbl->id))
1728 break;
1729 }
1730
1731 if (tbl == NULL) {
1732 err = -ENOENT;
1733 goto errout;
1734 }
1735
1736 /*
1737 * We acquire tbl->lock to be nice to the periodic timers and
1738 * make sure they always see a consistent set of values.
1739 */
1740 write_lock_bh(&tbl->lock);
1741
1742 if (tb[NDTA_THRESH1 - 1])
1743 tbl->gc_thresh1 = RTA_GET_U32(tb[NDTA_THRESH1 - 1]);
1744
1745 if (tb[NDTA_THRESH2 - 1])
1746 tbl->gc_thresh2 = RTA_GET_U32(tb[NDTA_THRESH2 - 1]);
1747
1748 if (tb[NDTA_THRESH3 - 1])
1749 tbl->gc_thresh3 = RTA_GET_U32(tb[NDTA_THRESH3 - 1]);
1750
1751 if (tb[NDTA_GC_INTERVAL - 1])
1752 tbl->gc_interval = RTA_GET_MSECS(tb[NDTA_GC_INTERVAL - 1]);
1753
1754 if (tb[NDTA_PARMS - 1]) {
1755 struct rtattr *tbp[NDTPA_MAX];
1756 struct neigh_parms *p;
1757 u32 ifindex = 0;
1758
1759 if (rtattr_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS - 1]) < 0)
1760 goto rtattr_failure;
1761
1762 if (tbp[NDTPA_IFINDEX - 1])
1763 ifindex = RTA_GET_U32(tbp[NDTPA_IFINDEX - 1]);
1764
1765 p = lookup_neigh_params(tbl, ifindex);
1766 if (p == NULL) {
1767 err = -ENOENT;
1768 goto rtattr_failure;
1769 }
1770
1771 if (tbp[NDTPA_QUEUE_LEN - 1])
1772 p->queue_len = RTA_GET_U32(tbp[NDTPA_QUEUE_LEN - 1]);
1773
1774 if (tbp[NDTPA_PROXY_QLEN - 1])
1775 p->proxy_qlen = RTA_GET_U32(tbp[NDTPA_PROXY_QLEN - 1]);
1776
1777 if (tbp[NDTPA_APP_PROBES - 1])
1778 p->app_probes = RTA_GET_U32(tbp[NDTPA_APP_PROBES - 1]);
1779
1780 if (tbp[NDTPA_UCAST_PROBES - 1])
1781 p->ucast_probes =
1782 RTA_GET_U32(tbp[NDTPA_UCAST_PROBES - 1]);
1783
1784 if (tbp[NDTPA_MCAST_PROBES - 1])
1785 p->mcast_probes =
1786 RTA_GET_U32(tbp[NDTPA_MCAST_PROBES - 1]);
1787
1788 if (tbp[NDTPA_BASE_REACHABLE_TIME - 1])
1789 p->base_reachable_time =
1790 RTA_GET_MSECS(tbp[NDTPA_BASE_REACHABLE_TIME - 1]);
1791
1792 if (tbp[NDTPA_GC_STALETIME - 1])
1793 p->gc_staletime =
1794 RTA_GET_MSECS(tbp[NDTPA_GC_STALETIME - 1]);
1795
1796 if (tbp[NDTPA_DELAY_PROBE_TIME - 1])
1797 p->delay_probe_time =
1798 RTA_GET_MSECS(tbp[NDTPA_DELAY_PROBE_TIME - 1]);
1799
1800 if (tbp[NDTPA_RETRANS_TIME - 1])
1801 p->retrans_time =
1802 RTA_GET_MSECS(tbp[NDTPA_RETRANS_TIME - 1]);
1803
1804 if (tbp[NDTPA_ANYCAST_DELAY - 1])
1805 p->anycast_delay =
1806 RTA_GET_MSECS(tbp[NDTPA_ANYCAST_DELAY - 1]);
1807
1808 if (tbp[NDTPA_PROXY_DELAY - 1])
1809 p->proxy_delay =
1810 RTA_GET_MSECS(tbp[NDTPA_PROXY_DELAY - 1]);
1811
1812 if (tbp[NDTPA_LOCKTIME - 1])
1813 p->locktime = RTA_GET_MSECS(tbp[NDTPA_LOCKTIME - 1]);
1814 }
1815
1816 err = 0;
1817
1818rtattr_failure:
1819 write_unlock_bh(&tbl->lock);
1820errout:
1821 read_unlock(&neigh_tbl_lock);
1822 return err;
1823}
1824
1825int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
1826{
1827 int idx, family;
1828 int s_idx = cb->args[0];
1829 struct neigh_table *tbl;
1830
1831 family = ((struct rtgenmsg *)NLMSG_DATA(cb->nlh))->rtgen_family;
1832
1833 read_lock(&neigh_tbl_lock);
1834 for (tbl = neigh_tables, idx = 0; tbl; tbl = tbl->next) {
1835 struct neigh_parms *p;
1836
1837 if (idx < s_idx || (family && tbl->family != family))
1838 continue;
1839
1840 if (neightbl_fill_info(tbl, skb, cb) <= 0)
1841 break;
1842
1843 for (++idx, p = tbl->parms.next; p; p = p->next, idx++) {
1844 if (idx < s_idx)
1845 continue;
1846
1847 if (neightbl_fill_param_info(tbl, p, skb, cb) <= 0)
1848 goto out;
1849 }
1850
1851 }
1852out:
1853 read_unlock(&neigh_tbl_lock);
1854 cb->args[0] = idx;
1855
1856 return skb->len;
1857}
1549 1858
1550static int neigh_fill_info(struct sk_buff *skb, struct neighbour *n, 1859static int neigh_fill_info(struct sk_buff *skb, struct neighbour *n,
1551 u32 pid, u32 seq, int event) 1860 u32 pid, u32 seq, int event)
@@ -2352,6 +2661,8 @@ EXPORT_SYMBOL(neigh_update);
2352EXPORT_SYMBOL(neigh_update_hhs); 2661EXPORT_SYMBOL(neigh_update_hhs);
2353EXPORT_SYMBOL(pneigh_enqueue); 2662EXPORT_SYMBOL(pneigh_enqueue);
2354EXPORT_SYMBOL(pneigh_lookup); 2663EXPORT_SYMBOL(pneigh_lookup);
2664EXPORT_SYMBOL(neightbl_dump_info);
2665EXPORT_SYMBOL(neightbl_set);
2355 2666
2356#ifdef CONFIG_ARPD 2667#ifdef CONFIG_ARPD
2357EXPORT_SYMBOL(neigh_app_ns); 2668EXPORT_SYMBOL(neigh_app_ns);