aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/neighbour.c
diff options
context:
space:
mode:
authorWANG Cong <xiyou.wangcong@gmail.com>2014-11-10 18:59:36 -0500
committerDavid S. Miller <davem@davemloft.net>2014-11-11 15:23:54 -0500
commitd7480fd3b1738a8eae6a76098b17af318cf9b9cc (patch)
tree559ba1e8e583fec97c223f31b3657023e71febfb /net/core/neighbour.c
parentb2e2f0c779fefede3a871781c8827bd8e76c7c0f (diff)
neigh: remove dynamic neigh table registration support
Currently there are only three neigh tables in the whole kernel: arp table, ndisc table and decnet neigh table. What's more, we don't support registering multiple tables per family. Therefore we can just make these tables statically built-in. Cc: David S. Miller <davem@davemloft.net> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/neighbour.c')
-rw-r--r--net/core/neighbour.c247
1 files changed, 112 insertions, 135 deletions
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index edd04116ecb7..8e38f17288d3 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -56,7 +56,6 @@ static void __neigh_notify(struct neighbour *n, int type, int flags);
56static void neigh_update_notify(struct neighbour *neigh); 56static void neigh_update_notify(struct neighbour *neigh);
57static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev); 57static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
58 58
59static struct neigh_table *neigh_tables;
60#ifdef CONFIG_PROC_FS 59#ifdef CONFIG_PROC_FS
61static const struct file_operations neigh_stat_seq_fops; 60static const struct file_operations neigh_stat_seq_fops;
62#endif 61#endif
@@ -87,13 +86,8 @@ static const struct file_operations neigh_stat_seq_fops;
87 the most complicated procedure, which we allow is dev->hard_header. 86 the most complicated procedure, which we allow is dev->hard_header.
88 It is supposed, that dev->hard_header is simplistic and does 87 It is supposed, that dev->hard_header is simplistic and does
89 not make callbacks to neighbour tables. 88 not make callbacks to neighbour tables.
90
91 The last lock is neigh_tbl_lock. It is pure SMP lock, protecting
92 list of neighbour tables. This list is used only in process context,
93 */ 89 */
94 90
95static DEFINE_RWLOCK(neigh_tbl_lock);
96
97static int neigh_blackhole(struct neighbour *neigh, struct sk_buff *skb) 91static int neigh_blackhole(struct neighbour *neigh, struct sk_buff *skb)
98{ 92{
99 kfree_skb(skb); 93 kfree_skb(skb);
@@ -1520,7 +1514,9 @@ static void neigh_parms_destroy(struct neigh_parms *parms)
1520 1514
1521static struct lock_class_key neigh_table_proxy_queue_class; 1515static struct lock_class_key neigh_table_proxy_queue_class;
1522 1516
1523static void neigh_table_init_no_netlink(struct neigh_table *tbl) 1517static struct neigh_table *neigh_tables[NEIGH_NR_TABLES] __read_mostly;
1518
1519void neigh_table_init(int index, struct neigh_table *tbl)
1524{ 1520{
1525 unsigned long now = jiffies; 1521 unsigned long now = jiffies;
1526 unsigned long phsize; 1522 unsigned long phsize;
@@ -1566,34 +1562,14 @@ static void neigh_table_init_no_netlink(struct neigh_table *tbl)
1566 1562
1567 tbl->last_flush = now; 1563 tbl->last_flush = now;
1568 tbl->last_rand = now + tbl->parms.reachable_time * 20; 1564 tbl->last_rand = now + tbl->parms.reachable_time * 20;
1569}
1570
1571void neigh_table_init(struct neigh_table *tbl)
1572{
1573 struct neigh_table *tmp;
1574 1565
1575 neigh_table_init_no_netlink(tbl); 1566 neigh_tables[index] = tbl;
1576 write_lock(&neigh_tbl_lock);
1577 for (tmp = neigh_tables; tmp; tmp = tmp->next) {
1578 if (tmp->family == tbl->family)
1579 break;
1580 }
1581 tbl->next = neigh_tables;
1582 neigh_tables = tbl;
1583 write_unlock(&neigh_tbl_lock);
1584
1585 if (unlikely(tmp)) {
1586 pr_err("Registering multiple tables for family %d\n",
1587 tbl->family);
1588 dump_stack();
1589 }
1590} 1567}
1591EXPORT_SYMBOL(neigh_table_init); 1568EXPORT_SYMBOL(neigh_table_init);
1592 1569
1593int neigh_table_clear(struct neigh_table *tbl) 1570int neigh_table_clear(int index, struct neigh_table *tbl)
1594{ 1571{
1595 struct neigh_table **tp; 1572 neigh_tables[index] = NULL;
1596
1597 /* It is not clean... Fix it to unload IPv6 module safely */ 1573 /* It is not clean... Fix it to unload IPv6 module safely */
1598 cancel_delayed_work_sync(&tbl->gc_work); 1574 cancel_delayed_work_sync(&tbl->gc_work);
1599 del_timer_sync(&tbl->proxy_timer); 1575 del_timer_sync(&tbl->proxy_timer);
@@ -1601,14 +1577,6 @@ int neigh_table_clear(struct neigh_table *tbl)
1601 neigh_ifdown(tbl, NULL); 1577 neigh_ifdown(tbl, NULL);
1602 if (atomic_read(&tbl->entries)) 1578 if (atomic_read(&tbl->entries))
1603 pr_crit("neighbour leakage\n"); 1579 pr_crit("neighbour leakage\n");
1604 write_lock(&neigh_tbl_lock);
1605 for (tp = &neigh_tables; *tp; tp = &(*tp)->next) {
1606 if (*tp == tbl) {
1607 *tp = tbl->next;
1608 break;
1609 }
1610 }
1611 write_unlock(&neigh_tbl_lock);
1612 1580
1613 call_rcu(&rcu_dereference_protected(tbl->nht, 1)->rcu, 1581 call_rcu(&rcu_dereference_protected(tbl->nht, 1)->rcu,
1614 neigh_hash_free_rcu); 1582 neigh_hash_free_rcu);
@@ -1626,12 +1594,32 @@ int neigh_table_clear(struct neigh_table *tbl)
1626} 1594}
1627EXPORT_SYMBOL(neigh_table_clear); 1595EXPORT_SYMBOL(neigh_table_clear);
1628 1596
1597static struct neigh_table *neigh_find_table(int family)
1598{
1599 struct neigh_table *tbl = NULL;
1600
1601 switch (family) {
1602 case AF_INET:
1603 tbl = neigh_tables[NEIGH_ARP_TABLE];
1604 break;
1605 case AF_INET6:
1606 tbl = neigh_tables[NEIGH_ND_TABLE];
1607 break;
1608 case AF_DECnet:
1609 tbl = neigh_tables[NEIGH_DN_TABLE];
1610 break;
1611 }
1612
1613 return tbl;
1614}
1615
1629static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh) 1616static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh)
1630{ 1617{
1631 struct net *net = sock_net(skb->sk); 1618 struct net *net = sock_net(skb->sk);
1632 struct ndmsg *ndm; 1619 struct ndmsg *ndm;
1633 struct nlattr *dst_attr; 1620 struct nlattr *dst_attr;
1634 struct neigh_table *tbl; 1621 struct neigh_table *tbl;
1622 struct neighbour *neigh;
1635 struct net_device *dev = NULL; 1623 struct net_device *dev = NULL;
1636 int err = -EINVAL; 1624 int err = -EINVAL;
1637 1625
@@ -1652,39 +1640,31 @@ static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh)
1652 } 1640 }
1653 } 1641 }
1654 1642
1655 read_lock(&neigh_tbl_lock); 1643 tbl = neigh_find_table(ndm->ndm_family);
1656 for (tbl = neigh_tables; tbl; tbl = tbl->next) { 1644 if (tbl == NULL)
1657 struct neighbour *neigh; 1645 return -EAFNOSUPPORT;
1658
1659 if (tbl->family != ndm->ndm_family)
1660 continue;
1661 read_unlock(&neigh_tbl_lock);
1662
1663 if (nla_len(dst_attr) < tbl->key_len)
1664 goto out;
1665 1646
1666 if (ndm->ndm_flags & NTF_PROXY) { 1647 if (nla_len(dst_attr) < tbl->key_len)
1667 err = pneigh_delete(tbl, net, nla_data(dst_attr), dev); 1648 goto out;
1668 goto out;
1669 }
1670 1649
1671 if (dev == NULL) 1650 if (ndm->ndm_flags & NTF_PROXY) {
1672 goto out; 1651 err = pneigh_delete(tbl, net, nla_data(dst_attr), dev);
1652 goto out;
1653 }
1673 1654
1674 neigh = neigh_lookup(tbl, nla_data(dst_attr), dev); 1655 if (dev == NULL)
1675 if (neigh == NULL) { 1656 goto out;
1676 err = -ENOENT;
1677 goto out;
1678 }
1679 1657
1680 err = neigh_update(neigh, NULL, NUD_FAILED, 1658 neigh = neigh_lookup(tbl, nla_data(dst_attr), dev);
1681 NEIGH_UPDATE_F_OVERRIDE | 1659 if (neigh == NULL) {
1682 NEIGH_UPDATE_F_ADMIN); 1660 err = -ENOENT;
1683 neigh_release(neigh);
1684 goto out; 1661 goto out;
1685 } 1662 }
1686 read_unlock(&neigh_tbl_lock); 1663
1687 err = -EAFNOSUPPORT; 1664 err = neigh_update(neigh, NULL, NUD_FAILED,
1665 NEIGH_UPDATE_F_OVERRIDE |
1666 NEIGH_UPDATE_F_ADMIN);
1667 neigh_release(neigh);
1688 1668
1689out: 1669out:
1690 return err; 1670 return err;
@@ -1692,11 +1672,14 @@ out:
1692 1672
1693static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh) 1673static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh)
1694{ 1674{
1675 int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE;
1695 struct net *net = sock_net(skb->sk); 1676 struct net *net = sock_net(skb->sk);
1696 struct ndmsg *ndm; 1677 struct ndmsg *ndm;
1697 struct nlattr *tb[NDA_MAX+1]; 1678 struct nlattr *tb[NDA_MAX+1];
1698 struct neigh_table *tbl; 1679 struct neigh_table *tbl;
1699 struct net_device *dev = NULL; 1680 struct net_device *dev = NULL;
1681 struct neighbour *neigh;
1682 void *dst, *lladdr;
1700 int err; 1683 int err;
1701 1684
1702 ASSERT_RTNL(); 1685 ASSERT_RTNL();
@@ -1720,70 +1703,60 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh)
1720 goto out; 1703 goto out;
1721 } 1704 }
1722 1705
1723 read_lock(&neigh_tbl_lock); 1706 tbl = neigh_find_table(ndm->ndm_family);
1724 for (tbl = neigh_tables; tbl; tbl = tbl->next) { 1707 if (tbl == NULL)
1725 int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE; 1708 return -EAFNOSUPPORT;
1726 struct neighbour *neigh;
1727 void *dst, *lladdr;
1728 1709
1729 if (tbl->family != ndm->ndm_family) 1710 if (nla_len(tb[NDA_DST]) < tbl->key_len)
1730 continue; 1711 goto out;
1731 read_unlock(&neigh_tbl_lock); 1712 dst = nla_data(tb[NDA_DST]);
1713 lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;
1732 1714
1733 if (nla_len(tb[NDA_DST]) < tbl->key_len) 1715 if (ndm->ndm_flags & NTF_PROXY) {
1734 goto out; 1716 struct pneigh_entry *pn;
1735 dst = nla_data(tb[NDA_DST]); 1717
1736 lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL; 1718 err = -ENOBUFS;
1719 pn = pneigh_lookup(tbl, net, dst, dev, 1);
1720 if (pn) {
1721 pn->flags = ndm->ndm_flags;
1722 err = 0;
1723 }
1724 goto out;
1725 }
1737 1726
1738 if (ndm->ndm_flags & NTF_PROXY) { 1727 if (dev == NULL)
1739 struct pneigh_entry *pn; 1728 goto out;
1740 1729
1741 err = -ENOBUFS; 1730 neigh = neigh_lookup(tbl, dst, dev);
1742 pn = pneigh_lookup(tbl, net, dst, dev, 1); 1731 if (neigh == NULL) {
1743 if (pn) { 1732 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
1744 pn->flags = ndm->ndm_flags; 1733 err = -ENOENT;
1745 err = 0;
1746 }
1747 goto out; 1734 goto out;
1748 } 1735 }
1749 1736
1750 if (dev == NULL) 1737 neigh = __neigh_lookup_errno(tbl, dst, dev);
1738 if (IS_ERR(neigh)) {
1739 err = PTR_ERR(neigh);
1740 goto out;
1741 }
1742 } else {
1743 if (nlh->nlmsg_flags & NLM_F_EXCL) {
1744 err = -EEXIST;
1745 neigh_release(neigh);
1751 goto out; 1746 goto out;
1752
1753 neigh = neigh_lookup(tbl, dst, dev);
1754 if (neigh == NULL) {
1755 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
1756 err = -ENOENT;
1757 goto out;
1758 }
1759
1760 neigh = __neigh_lookup_errno(tbl, dst, dev);
1761 if (IS_ERR(neigh)) {
1762 err = PTR_ERR(neigh);
1763 goto out;
1764 }
1765 } else {
1766 if (nlh->nlmsg_flags & NLM_F_EXCL) {
1767 err = -EEXIST;
1768 neigh_release(neigh);
1769 goto out;
1770 }
1771
1772 if (!(nlh->nlmsg_flags & NLM_F_REPLACE))
1773 flags &= ~NEIGH_UPDATE_F_OVERRIDE;
1774 } 1747 }
1775 1748
1776 if (ndm->ndm_flags & NTF_USE) { 1749 if (!(nlh->nlmsg_flags & NLM_F_REPLACE))
1777 neigh_event_send(neigh, NULL); 1750 flags &= ~NEIGH_UPDATE_F_OVERRIDE;
1778 err = 0;
1779 } else
1780 err = neigh_update(neigh, lladdr, ndm->ndm_state, flags);
1781 neigh_release(neigh);
1782 goto out;
1783 } 1751 }
1784 1752
1785 read_unlock(&neigh_tbl_lock); 1753 if (ndm->ndm_flags & NTF_USE) {
1786 err = -EAFNOSUPPORT; 1754 neigh_event_send(neigh, NULL);
1755 err = 0;
1756 } else
1757 err = neigh_update(neigh, lladdr, ndm->ndm_state, flags);
1758 neigh_release(neigh);
1759
1787out: 1760out:
1788 return err; 1761 return err;
1789} 1762}
@@ -1982,7 +1955,8 @@ static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh)
1982 struct neigh_table *tbl; 1955 struct neigh_table *tbl;
1983 struct ndtmsg *ndtmsg; 1956 struct ndtmsg *ndtmsg;
1984 struct nlattr *tb[NDTA_MAX+1]; 1957 struct nlattr *tb[NDTA_MAX+1];
1985 int err; 1958 bool found = false;
1959 int err, tidx;
1986 1960
1987 err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX, 1961 err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX,
1988 nl_neightbl_policy); 1962 nl_neightbl_policy);
@@ -1995,19 +1969,21 @@ static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh)
1995 } 1969 }
1996 1970
1997 ndtmsg = nlmsg_data(nlh); 1971 ndtmsg = nlmsg_data(nlh);
1998 read_lock(&neigh_tbl_lock); 1972
1999 for (tbl = neigh_tables; tbl; tbl = tbl->next) { 1973 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
1974 tbl = neigh_tables[tidx];
1975 if (!tbl)
1976 continue;
2000 if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family) 1977 if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
2001 continue; 1978 continue;
2002 1979 if (nla_strcmp(tb[NDTA_NAME], tbl->id) == 0) {
2003 if (nla_strcmp(tb[NDTA_NAME], tbl->id) == 0) 1980 found = true;
2004 break; 1981 break;
1982 }
2005 } 1983 }
2006 1984
2007 if (tbl == NULL) { 1985 if (!found)
2008 err = -ENOENT; 1986 return -ENOENT;
2009 goto errout_locked;
2010 }
2011 1987
2012 /* 1988 /*
2013 * We acquire tbl->lock to be nice to the periodic timers and 1989 * We acquire tbl->lock to be nice to the periodic timers and
@@ -2118,8 +2094,6 @@ static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh)
2118 2094
2119errout_tbl_lock: 2095errout_tbl_lock:
2120 write_unlock_bh(&tbl->lock); 2096 write_unlock_bh(&tbl->lock);
2121errout_locked:
2122 read_unlock(&neigh_tbl_lock);
2123errout: 2097errout:
2124 return err; 2098 return err;
2125} 2099}
@@ -2134,10 +2108,13 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
2134 2108
2135 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family; 2109 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
2136 2110
2137 read_lock(&neigh_tbl_lock); 2111 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
2138 for (tbl = neigh_tables, tidx = 0; tbl; tbl = tbl->next, tidx++) {
2139 struct neigh_parms *p; 2112 struct neigh_parms *p;
2140 2113
2114 tbl = neigh_tables[tidx];
2115 if (!tbl)
2116 continue;
2117
2141 if (tidx < tbl_skip || (family && tbl->family != family)) 2118 if (tidx < tbl_skip || (family && tbl->family != family))
2142 continue; 2119 continue;
2143 2120
@@ -2168,7 +2145,6 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
2168 neigh_skip = 0; 2145 neigh_skip = 0;
2169 } 2146 }
2170out: 2147out:
2171 read_unlock(&neigh_tbl_lock);
2172 cb->args[0] = tidx; 2148 cb->args[0] = tidx;
2173 cb->args[1] = nidx; 2149 cb->args[1] = nidx;
2174 2150
@@ -2351,7 +2327,6 @@ static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
2351 int proxy = 0; 2327 int proxy = 0;
2352 int err; 2328 int err;
2353 2329
2354 read_lock(&neigh_tbl_lock);
2355 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family; 2330 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
2356 2331
2357 /* check for full ndmsg structure presence, family member is 2332 /* check for full ndmsg structure presence, family member is
@@ -2363,8 +2338,11 @@ static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
2363 2338
2364 s_t = cb->args[0]; 2339 s_t = cb->args[0];
2365 2340
2366 for (tbl = neigh_tables, t = 0; tbl; 2341 for (t = 0; t < NEIGH_NR_TABLES; t++) {
2367 tbl = tbl->next, t++) { 2342 tbl = neigh_tables[t];
2343
2344 if (!tbl)
2345 continue;
2368 if (t < s_t || (family && tbl->family != family)) 2346 if (t < s_t || (family && tbl->family != family))
2369 continue; 2347 continue;
2370 if (t > s_t) 2348 if (t > s_t)
@@ -2377,7 +2355,6 @@ static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
2377 if (err < 0) 2355 if (err < 0)
2378 break; 2356 break;
2379 } 2357 }
2380 read_unlock(&neigh_tbl_lock);
2381 2358
2382 cb->args[0] = t; 2359 cb->args[0] = t;
2383 return skb->len; 2360 return skb->len;