hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/net/ipv6/ndisc.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Neighbour Discovery for IPv6
34 * Linux INET6 implementation
....@@ -5,11 +6,6 @@
56 * Authors:
67 * Pedro Roque <roque@di.fc.ul.pt>
78 * Mike Shaver <shaver@ingenia.com>
8
- *
9
- * This program is free software; you can redistribute it and/or
10
- * modify it under the terms of the GNU General Public License
11
- * as published by the Free Software Foundation; either version
12
- * 2 of the License, or (at your option) any later version.
139 */
1410
1511 /*
....@@ -77,12 +73,15 @@
7773 const struct net_device *dev,
7874 __u32 *hash_rnd);
7975 static bool ndisc_key_eq(const struct neighbour *neigh, const void *pkey);
76
+static bool ndisc_allow_add(const struct net_device *dev,
77
+ struct netlink_ext_ack *extack);
8078 static int ndisc_constructor(struct neighbour *neigh);
8179 static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb);
8280 static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb);
8381 static int pndisc_constructor(struct pneigh_entry *n);
8482 static void pndisc_destructor(struct pneigh_entry *n);
8583 static void pndisc_redo(struct sk_buff *skb);
84
+static int ndisc_is_multicast(const void *pkey);
8685
8786 static const struct neigh_ops ndisc_generic_ops = {
8887 .family = AF_INET6,
....@@ -117,6 +116,8 @@
117116 .pconstructor = pndisc_constructor,
118117 .pdestructor = pndisc_destructor,
119118 .proxy_redo = pndisc_redo,
119
+ .is_multicast = ndisc_is_multicast,
120
+ .allow_add = ndisc_allow_add,
120121 .id = "ndisc_cache",
121122 .parms = {
122123 .tbl = &nd_tbl,
....@@ -195,7 +196,8 @@
195196 static inline int ndisc_is_useropt(const struct net_device *dev,
196197 struct nd_opt_hdr *opt)
197198 {
198
- return opt->nd_opt_type == ND_OPT_RDNSS ||
199
+ return opt->nd_opt_type == ND_OPT_PREFIX_INFO ||
200
+ opt->nd_opt_type == ND_OPT_RDNSS ||
199201 opt->nd_opt_type == ND_OPT_DNSSL ||
200202 opt->nd_opt_type == ND_OPT_CAPTIVE_PORTAL ||
201203 opt->nd_opt_type == ND_OPT_PREF64 ||
....@@ -392,6 +394,20 @@
392394 return;
393395 addrconf_addr_solict_mult(addr, &maddr);
394396 ipv6_dev_mc_dec(dev, &maddr);
397
+}
398
+
399
+/* called with rtnl held */
400
+static bool ndisc_allow_add(const struct net_device *dev,
401
+ struct netlink_ext_ack *extack)
402
+{
403
+ struct inet6_dev *idev = __in6_dev_get(dev);
404
+
405
+ if (!idev || idev->cnf.disable_ipv6) {
406
+ NL_SET_ERR_MSG(extack, "IPv6 is disabled on this device");
407
+ return false;
408
+ }
409
+
410
+ return true;
395411 }
396412
397413 static struct sk_buff *ndisc_alloc_skb(struct net_device *dev,
....@@ -1274,12 +1290,11 @@
12741290 !in6_dev->cnf.accept_ra_rtr_pref)
12751291 pref = ICMPV6_ROUTER_PREF_MEDIUM;
12761292 #endif
1277
-
1293
+ /* routes added from RAs do not use nexthop objects */
12781294 rt = rt6_get_dflt_router(net, &ipv6_hdr(skb)->saddr, skb->dev);
1279
-
12801295 if (rt) {
1281
- neigh = ip6_neigh_lookup(&rt->fib6_nh.nh_gw,
1282
- rt->fib6_nh.nh_dev, NULL,
1296
+ neigh = ip6_neigh_lookup(&rt->fib6_nh->fib_nh_gw6,
1297
+ rt->fib6_nh->fib_nh_dev, NULL,
12831298 &ipv6_hdr(skb)->saddr);
12841299 if (!neigh) {
12851300 ND_PRINTK(0, err,
....@@ -1290,7 +1305,7 @@
12901305 }
12911306 }
12921307 if (rt && lifetime == 0) {
1293
- ip6_del_rt(net, rt);
1308
+ ip6_del_rt(net, rt, false);
12941309 rt = NULL;
12951310 }
12961311
....@@ -1308,8 +1323,8 @@
13081323 return;
13091324 }
13101325
1311
- neigh = ip6_neigh_lookup(&rt->fib6_nh.nh_gw,
1312
- rt->fib6_nh.nh_dev, NULL,
1326
+ neigh = ip6_neigh_lookup(&rt->fib6_nh->fib_nh_gw6,
1327
+ rt->fib6_nh->fib_nh_dev, NULL,
13131328 &ipv6_hdr(skb)->saddr);
13141329 if (!neigh) {
13151330 ND_PRINTK(0, err,
....@@ -1347,8 +1362,8 @@
13471362
13481363 if (rtime && rtime/1000 < MAX_SCHEDULE_TIMEOUT/HZ) {
13491364 rtime = (rtime*HZ)/1000;
1350
- if (rtime < HZ/10)
1351
- rtime = HZ/10;
1365
+ if (rtime < HZ/100)
1366
+ rtime = HZ/100;
13521367 NEIGH_VAR_SET(in6_dev->nd_parms, RETRANS_TIME, rtime);
13531368 in6_dev->tstamp = jiffies;
13541369 send_ifinfo_notify = true;
....@@ -1535,7 +1550,7 @@
15351550
15361551 if (!ndopts.nd_opts_rh) {
15371552 ip6_redirect_no_header(skb, dev_net(skb->dev),
1538
- skb->dev->ifindex, 0);
1553
+ skb->dev->ifindex);
15391554 return;
15401555 }
15411556
....@@ -1694,6 +1709,11 @@
16941709 kfree_skb(skb);
16951710 }
16961711
1712
+static int ndisc_is_multicast(const void *pkey)
1713
+{
1714
+ return ipv6_addr_is_multicast((struct in6_addr *)pkey);
1715
+}
1716
+
16971717 static bool ndisc_suppress_frag_ndisc(struct sk_buff *skb)
16981718 {
16991719 struct inet6_dev *idev = __in6_dev_get(skb->dev);
....@@ -1771,7 +1791,7 @@
17711791 case NETDEV_CHANGEADDR:
17721792 neigh_changeaddr(&nd_tbl, dev);
17731793 fib6_run_gc(0, net, false);
1774
- /* fallthrough */
1794
+ fallthrough;
17751795 case NETDEV_UP:
17761796 idev = in6_dev_get(dev);
17771797 if (!idev)
....@@ -1785,6 +1805,8 @@
17851805 change_info = ptr;
17861806 if (change_info->flags_changed & IFF_NOARP)
17871807 neigh_changeaddr(&nd_tbl, dev);
1808
+ if (!netif_carrier_ok(dev))
1809
+ neigh_carrier_down(&nd_tbl, dev);
17881810 break;
17891811 case NETDEV_DOWN:
17901812 neigh_ifdown(&nd_tbl, dev);
....@@ -1821,7 +1843,8 @@
18211843 }
18221844 }
18231845
1824
-int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
1846
+int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, void *buffer,
1847
+ size_t *lenp, loff_t *ppos)
18251848 {
18261849 struct net_device *dev = ctl->extra1;
18271850 struct inet6_dev *idev;