aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/rtnetlink.h107
-rw-r--r--include/net/neighbour.h4
-rw-r--r--net/core/neighbour.c317
-rw-r--r--net/core/rtnetlink.c20
-rw-r--r--security/selinux/nlmsgtab.c2
5 files changed, 439 insertions, 11 deletions
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index a09b5d42babf..5a5cda160267 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -89,6 +89,13 @@ enum {
89 RTM_GETANYCAST = 62, 89 RTM_GETANYCAST = 62,
90#define RTM_GETANYCAST RTM_GETANYCAST 90#define RTM_GETANYCAST RTM_GETANYCAST
91 91
92 RTM_NEWNEIGHTBL = 64,
93#define RTM_NEWNEIGHTBL RTM_NEWNEIGHTBL
94 RTM_GETNEIGHTBL = 66,
95#define RTM_GETNEIGHTBL RTM_GETNEIGHTBL
96 RTM_SETNEIGHTBL,
97#define RTM_SETNEIGHTBL RTM_SETNEIGHTBL
98
92 __RTM_MAX, 99 __RTM_MAX,
93#define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1) 100#define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1)
94}; 101};
@@ -493,6 +500,106 @@ struct nda_cacheinfo
493 __u32 ndm_refcnt; 500 __u32 ndm_refcnt;
494}; 501};
495 502
503
504/*****************************************************************
505 * Neighbour tables specific messages.
506 *
507 * To retrieve the neighbour tables send RTM_GETNEIGHTBL with the
508 * NLM_F_DUMP flag set. Every neighbour table configuration is
509 * spread over multiple messages to avoid running into message
510 * size limits on systems with many interfaces. The first message
511 * in the sequence transports all not device specific data such as
512 * statistics, configuration, and the default parameter set.
513 * This message is followed by 0..n messages carrying device
514 * specific parameter sets.
515 * Although the ordering should be sufficient, NDTA_NAME can be
516 * used to identify sequences. The initial message can be identified
517 * by checking for NDTA_CONFIG. The device specific messages do
518 * not contain this TLV but have NDTPA_IFINDEX set to the
519 * corresponding interface index.
520 *
521 * To change neighbour table attributes, send RTM_SETNEIGHTBL
522 * with NDTA_NAME set. Changeable attribute include NDTA_THRESH[1-3],
523 * NDTA_GC_INTERVAL, and all TLVs in NDTA_PARMS unless marked
524 * otherwise. Device specific parameter sets can be changed by
525 * setting NDTPA_IFINDEX to the interface index of the corresponding
526 * device.
527 ****/
528
529struct ndt_stats
530{
531 __u64 ndts_allocs;
532 __u64 ndts_destroys;
533 __u64 ndts_hash_grows;
534 __u64 ndts_res_failed;
535 __u64 ndts_lookups;
536 __u64 ndts_hits;
537 __u64 ndts_rcv_probes_mcast;
538 __u64 ndts_rcv_probes_ucast;
539 __u64 ndts_periodic_gc_runs;
540 __u64 ndts_forced_gc_runs;
541};
542
543enum {
544 NDTPA_UNSPEC,
545 NDTPA_IFINDEX, /* u32, unchangeable */
546 NDTPA_REFCNT, /* u32, read-only */
547 NDTPA_REACHABLE_TIME, /* u64, read-only, msecs */
548 NDTPA_BASE_REACHABLE_TIME, /* u64, msecs */
549 NDTPA_RETRANS_TIME, /* u64, msecs */
550 NDTPA_GC_STALETIME, /* u64, msecs */
551 NDTPA_DELAY_PROBE_TIME, /* u64, msecs */
552 NDTPA_QUEUE_LEN, /* u32 */
553 NDTPA_APP_PROBES, /* u32 */
554 NDTPA_UCAST_PROBES, /* u32 */
555 NDTPA_MCAST_PROBES, /* u32 */
556 NDTPA_ANYCAST_DELAY, /* u64, msecs */
557 NDTPA_PROXY_DELAY, /* u64, msecs */
558 NDTPA_PROXY_QLEN, /* u32 */
559 NDTPA_LOCKTIME, /* u64, msecs */
560 __NDTPA_MAX
561};
562#define NDTPA_MAX (__NDTPA_MAX - 1)
563
564struct ndtmsg
565{
566 __u8 ndtm_family;
567 __u8 ndtm_pad1;
568 __u16 ndtm_pad2;
569};
570
571struct ndt_config
572{
573 __u16 ndtc_key_len;
574 __u16 ndtc_entry_size;
575 __u32 ndtc_entries;
576 __u32 ndtc_last_flush; /* delta to now in msecs */
577 __u32 ndtc_last_rand; /* delta to now in msecs */
578 __u32 ndtc_hash_rnd;
579 __u32 ndtc_hash_mask;
580 __u32 ndtc_hash_chain_gc;
581 __u32 ndtc_proxy_qlen;
582};
583
584enum {
585 NDTA_UNSPEC,
586 NDTA_NAME, /* char *, unchangeable */
587 NDTA_THRESH1, /* u32 */
588 NDTA_THRESH2, /* u32 */
589 NDTA_THRESH3, /* u32 */
590 NDTA_CONFIG, /* struct ndt_config, read-only */
591 NDTA_PARMS, /* nested TLV NDTPA_* */
592 NDTA_STATS, /* struct ndt_stats, read-only */
593 NDTA_GC_INTERVAL, /* u64, msecs */
594 __NDTA_MAX
595};
596#define NDTA_MAX (__NDTA_MAX - 1)
597
598#define NDTA_RTA(r) ((struct rtattr*)(((char*)(r)) + \
599 NLMSG_ALIGN(sizeof(struct ndtmsg))))
600#define NDTA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndtmsg))
601
602
496/**** 603/****
497 * General form of address family dependent message. 604 * General form of address family dependent message.
498 ****/ 605 ****/
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 4f33bbc21e7f..17191ac9be70 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -65,6 +65,7 @@ struct neighbour;
65 65
66struct neigh_parms 66struct neigh_parms
67{ 67{
68 struct net_device *dev;
68 struct neigh_parms *next; 69 struct neigh_parms *next;
69 int (*neigh_setup)(struct neighbour *); 70 int (*neigh_setup)(struct neighbour *);
70 struct neigh_table *tbl; 71 struct neigh_table *tbl;
@@ -252,6 +253,9 @@ extern int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
252extern int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg); 253extern int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
253extern void neigh_app_ns(struct neighbour *n); 254extern void neigh_app_ns(struct neighbour *n);
254 255
256extern int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb);
257extern int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
258
255extern void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie); 259extern void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie);
256extern void __neigh_for_each_release(struct neigh_table *tbl, int (*cb)(struct neighbour *)); 260extern void __neigh_for_each_release(struct neigh_table *tbl, int (*cb)(struct neighbour *));
257extern void pneigh_for_each(struct neigh_table *tbl, void (*cb)(struct pneigh_entry *)); 261extern void pneigh_for_each(struct neigh_table *tbl, void (*cb)(struct pneigh_entry *));
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);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 00caf4b318b2..56a20f014b8a 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -100,6 +100,7 @@ static const int rtm_min[RTM_NR_FAMILIES] =
100 [RTM_FAM(RTM_NEWPREFIX)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)), 100 [RTM_FAM(RTM_NEWPREFIX)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
101 [RTM_FAM(RTM_GETMULTICAST)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)), 101 [RTM_FAM(RTM_GETMULTICAST)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
102 [RTM_FAM(RTM_GETANYCAST)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)), 102 [RTM_FAM(RTM_GETANYCAST)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
103 [RTM_FAM(RTM_NEWNEIGHTBL)] = NLMSG_LENGTH(sizeof(struct ndtmsg)),
103}; 104};
104 105
105static const int rta_max[RTM_NR_FAMILIES] = 106static const int rta_max[RTM_NR_FAMILIES] =
@@ -113,6 +114,7 @@ static const int rta_max[RTM_NR_FAMILIES] =
113 [RTM_FAM(RTM_NEWTCLASS)] = TCA_MAX, 114 [RTM_FAM(RTM_NEWTCLASS)] = TCA_MAX,
114 [RTM_FAM(RTM_NEWTFILTER)] = TCA_MAX, 115 [RTM_FAM(RTM_NEWTFILTER)] = TCA_MAX,
115 [RTM_FAM(RTM_NEWACTION)] = TCAA_MAX, 116 [RTM_FAM(RTM_NEWACTION)] = TCAA_MAX,
117 [RTM_FAM(RTM_NEWNEIGHTBL)] = NDTA_MAX,
116}; 118};
117 119
118void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data) 120void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data)
@@ -649,14 +651,16 @@ static void rtnetlink_rcv(struct sock *sk, int len)
649 651
650static struct rtnetlink_link link_rtnetlink_table[RTM_NR_MSGTYPES] = 652static struct rtnetlink_link link_rtnetlink_table[RTM_NR_MSGTYPES] =
651{ 653{
652 [RTM_GETLINK - RTM_BASE] = { .dumpit = rtnetlink_dump_ifinfo }, 654 [RTM_GETLINK - RTM_BASE] = { .dumpit = rtnetlink_dump_ifinfo },
653 [RTM_SETLINK - RTM_BASE] = { .doit = do_setlink }, 655 [RTM_SETLINK - RTM_BASE] = { .doit = do_setlink },
654 [RTM_GETADDR - RTM_BASE] = { .dumpit = rtnetlink_dump_all }, 656 [RTM_GETADDR - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
655 [RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnetlink_dump_all }, 657 [RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
656 [RTM_NEWNEIGH - RTM_BASE] = { .doit = neigh_add }, 658 [RTM_NEWNEIGH - RTM_BASE] = { .doit = neigh_add },
657 [RTM_DELNEIGH - RTM_BASE] = { .doit = neigh_delete }, 659 [RTM_DELNEIGH - RTM_BASE] = { .doit = neigh_delete },
658 [RTM_GETNEIGH - RTM_BASE] = { .dumpit = neigh_dump_info }, 660 [RTM_GETNEIGH - RTM_BASE] = { .dumpit = neigh_dump_info },
659 [RTM_GETRULE - RTM_BASE] = { .dumpit = rtnetlink_dump_all }, 661 [RTM_GETRULE - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
662 [RTM_GETNEIGHTBL - RTM_BASE] = { .dumpit = neightbl_dump_info },
663 [RTM_SETNEIGHTBL - RTM_BASE] = { .doit = neightbl_set },
660}; 664};
661 665
662static int rtnetlink_event(struct notifier_block *this, unsigned long event, void *ptr) 666static int rtnetlink_event(struct notifier_block *this, unsigned long event, void *ptr)
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
index f0fb6d76f7c5..92b057becb4b 100644
--- a/security/selinux/nlmsgtab.c
+++ b/security/selinux/nlmsgtab.c
@@ -63,6 +63,8 @@ static struct nlmsg_perm nlmsg_route_perms[] =
63 { RTM_GETPREFIX, NETLINK_ROUTE_SOCKET__NLMSG_READ }, 63 { RTM_GETPREFIX, NETLINK_ROUTE_SOCKET__NLMSG_READ },
64 { RTM_GETMULTICAST, NETLINK_ROUTE_SOCKET__NLMSG_READ }, 64 { RTM_GETMULTICAST, NETLINK_ROUTE_SOCKET__NLMSG_READ },
65 { RTM_GETANYCAST, NETLINK_ROUTE_SOCKET__NLMSG_READ }, 65 { RTM_GETANYCAST, NETLINK_ROUTE_SOCKET__NLMSG_READ },
66 { RTM_GETNEIGHTBL, NETLINK_ROUTE_SOCKET__NLMSG_READ },
67 { RTM_SETNEIGHTBL, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
66}; 68};
67 69
68static struct nlmsg_perm nlmsg_firewall_perms[] = 70static struct nlmsg_perm nlmsg_firewall_perms[] =