forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-11 072de836f53be56a70cecf70b43ae43b7ce17376
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,
....@@ -392,6 +393,20 @@
392393 return;
393394 addrconf_addr_solict_mult(addr, &maddr);
394395 ipv6_dev_mc_dec(dev, &maddr);
396
+}
397
+
398
+/* called with rtnl held */
399
+static bool ndisc_allow_add(const struct net_device *dev,
400
+ struct netlink_ext_ack *extack)
401
+{
402
+ struct inet6_dev *idev = __in6_dev_get(dev);
403
+
404
+ if (!idev || idev->cnf.disable_ipv6) {
405
+ NL_SET_ERR_MSG(extack, "IPv6 is disabled on this device");
406
+ return false;
407
+ }
408
+
409
+ return true;
395410 }
396411
397412 static struct sk_buff *ndisc_alloc_skb(struct net_device *dev,
....@@ -1274,12 +1289,11 @@
12741289 !in6_dev->cnf.accept_ra_rtr_pref)
12751290 pref = ICMPV6_ROUTER_PREF_MEDIUM;
12761291 #endif
1277
-
1292
+ /* routes added from RAs do not use nexthop objects */
12781293 rt = rt6_get_dflt_router(net, &ipv6_hdr(skb)->saddr, skb->dev);
1279
-
12801294 if (rt) {
1281
- neigh = ip6_neigh_lookup(&rt->fib6_nh.nh_gw,
1282
- rt->fib6_nh.nh_dev, NULL,
1295
+ neigh = ip6_neigh_lookup(&rt->fib6_nh->fib_nh_gw6,
1296
+ rt->fib6_nh->fib_nh_dev, NULL,
12831297 &ipv6_hdr(skb)->saddr);
12841298 if (!neigh) {
12851299 ND_PRINTK(0, err,
....@@ -1290,7 +1304,7 @@
12901304 }
12911305 }
12921306 if (rt && lifetime == 0) {
1293
- ip6_del_rt(net, rt);
1307
+ ip6_del_rt(net, rt, false);
12941308 rt = NULL;
12951309 }
12961310
....@@ -1308,8 +1322,8 @@
13081322 return;
13091323 }
13101324
1311
- neigh = ip6_neigh_lookup(&rt->fib6_nh.nh_gw,
1312
- rt->fib6_nh.nh_dev, NULL,
1325
+ neigh = ip6_neigh_lookup(&rt->fib6_nh->fib_nh_gw6,
1326
+ rt->fib6_nh->fib_nh_dev, NULL,
13131327 &ipv6_hdr(skb)->saddr);
13141328 if (!neigh) {
13151329 ND_PRINTK(0, err,
....@@ -1347,8 +1361,8 @@
13471361
13481362 if (rtime && rtime/1000 < MAX_SCHEDULE_TIMEOUT/HZ) {
13491363 rtime = (rtime*HZ)/1000;
1350
- if (rtime < HZ/10)
1351
- rtime = HZ/10;
1364
+ if (rtime < HZ/100)
1365
+ rtime = HZ/100;
13521366 NEIGH_VAR_SET(in6_dev->nd_parms, RETRANS_TIME, rtime);
13531367 in6_dev->tstamp = jiffies;
13541368 send_ifinfo_notify = true;
....@@ -1535,7 +1549,7 @@
15351549
15361550 if (!ndopts.nd_opts_rh) {
15371551 ip6_redirect_no_header(skb, dev_net(skb->dev),
1538
- skb->dev->ifindex, 0);
1552
+ skb->dev->ifindex);
15391553 return;
15401554 }
15411555
....@@ -1694,6 +1708,11 @@
16941708 kfree_skb(skb);
16951709 }
16961710
1711
+static int ndisc_is_multicast(const void *pkey)
1712
+{
1713
+ return ipv6_addr_is_multicast((struct in6_addr *)pkey);
1714
+}
1715
+
16971716 static bool ndisc_suppress_frag_ndisc(struct sk_buff *skb)
16981717 {
16991718 struct inet6_dev *idev = __in6_dev_get(skb->dev);
....@@ -1771,7 +1790,7 @@
17711790 case NETDEV_CHANGEADDR:
17721791 neigh_changeaddr(&nd_tbl, dev);
17731792 fib6_run_gc(0, net, false);
1774
- /* fallthrough */
1793
+ fallthrough;
17751794 case NETDEV_UP:
17761795 idev = in6_dev_get(dev);
17771796 if (!idev)
....@@ -1785,6 +1804,8 @@
17851804 change_info = ptr;
17861805 if (change_info->flags_changed & IFF_NOARP)
17871806 neigh_changeaddr(&nd_tbl, dev);
1807
+ if (!netif_carrier_ok(dev))
1808
+ neigh_carrier_down(&nd_tbl, dev);
17881809 break;
17891810 case NETDEV_DOWN:
17901811 neigh_ifdown(&nd_tbl, dev);
....@@ -1821,7 +1842,8 @@
18211842 }
18221843 }
18231844
1824
-int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
1845
+int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, void *buffer,
1846
+ size_t *lenp, loff_t *ppos)
18251847 {
18261848 struct net_device *dev = ctl->extra1;
18271849 struct inet6_dev *idev;