Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

net ipv6: Prevent neighbor add if protocol is disabled on device

Disabling IPv6 on an interface removes existing entries but nothing prevents
new entries from being manually added. To that end, add a new neigh_table
operation, allow_add, that is called on RTM_NEWNEIGH to see if neighbor
entries are allowed on a given device. If IPv6 is disabled on the device,
allow_add returns false and passes a message back to the user via extack.

$ echo 1 > /proc/sys/net/ipv6/conf/eth1/disable_ipv6
$ ip -6 neigh add fe80::4c88:bff:fe21:2704 dev eth1 lladdr de:ad:be:ef:01:01
Error: IPv6 is disabled on this device.

Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

David Ahern and committed by
David S. Miller
b8fb1ab4 cea29a70

+24
+2
include/net/neighbour.h
··· 205 205 int (*pconstructor)(struct pneigh_entry *); 206 206 void (*pdestructor)(struct pneigh_entry *); 207 207 void (*proxy_redo)(struct sk_buff *skb); 208 + bool (*allow_add)(const struct net_device *dev, 209 + struct netlink_ext_ack *extack); 208 210 char *id; 209 211 struct neigh_parms parms; 210 212 struct list_head parms_list;
+5
net/core/neighbour.c
··· 1920 1920 goto out; 1921 1921 } 1922 1922 1923 + if (tbl->allow_add && !tbl->allow_add(dev, extack)) { 1924 + err = -EINVAL; 1925 + goto out; 1926 + } 1927 + 1923 1928 neigh = neigh_lookup(tbl, dst, dev); 1924 1929 if (neigh == NULL) { 1925 1930 bool exempt_from_gc;
+17
net/ipv6/ndisc.c
··· 77 77 const struct net_device *dev, 78 78 __u32 *hash_rnd); 79 79 static bool ndisc_key_eq(const struct neighbour *neigh, const void *pkey); 80 + static bool ndisc_allow_add(const struct net_device *dev, 81 + struct netlink_ext_ack *extack); 80 82 static int ndisc_constructor(struct neighbour *neigh); 81 83 static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb); 82 84 static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb); ··· 119 117 .pconstructor = pndisc_constructor, 120 118 .pdestructor = pndisc_destructor, 121 119 .proxy_redo = pndisc_redo, 120 + .allow_add = ndisc_allow_add, 122 121 .id = "ndisc_cache", 123 122 .parms = { 124 123 .tbl = &nd_tbl, ··· 393 390 return; 394 391 addrconf_addr_solict_mult(addr, &maddr); 395 392 ipv6_dev_mc_dec(dev, &maddr); 393 + } 394 + 395 + /* called with rtnl held */ 396 + static bool ndisc_allow_add(const struct net_device *dev, 397 + struct netlink_ext_ack *extack) 398 + { 399 + struct inet6_dev *idev = __in6_dev_get(dev); 400 + 401 + if (!idev || idev->cnf.disable_ipv6) { 402 + NL_SET_ERR_MSG(extack, "IPv6 is disabled on this device"); 403 + return false; 404 + } 405 + 406 + return true; 396 407 } 397 408 398 409 static struct sk_buff *ndisc_alloc_skb(struct net_device *dev,