blob: 840bfdb3d7bd8da2d7a8bd77649c51a3a7e197c4 [file] [log] [blame]
Thomas Gleixner2874c5f2019-05-27 08:55:01 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
3 * IPv6 Address [auto]configuration
4 * Linux INET6 implementation
5 *
6 * Authors:
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09007 * Pedro Roque <roque@di.fc.ul.pt>
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 */
10
11/*
12 * Changes:
13 *
14 * Janos Farkas : delete timer on ifdown
15 * <chexum@bankinf.banki.hu>
16 * Andi Kleen : kill double kfree on module
17 * unload.
18 * Maciej W. Rozycki : FDDI support
19 * sekiya@USAGI : Don't send too many RS
20 * packets.
21 * yoshfuji@USAGI : Fixed interval between DAD
22 * packets.
23 * YOSHIFUJI Hideaki @USAGI : improved accuracy of
24 * address validation timer.
25 * YOSHIFUJI Hideaki @USAGI : Privacy Extensions (RFC3041)
26 * support.
27 * Yuji SEKIYA @USAGI : Don't assign a same IPv6
28 * address on a same interface.
29 * YOSHIFUJI Hideaki @USAGI : ARCnet support
30 * YOSHIFUJI Hideaki @USAGI : convert /proc/net/if_inet6 to
31 * seq_file.
YOSHIFUJI Hideakib1cacb62005-11-08 09:38:12 -080032 * YOSHIFUJI Hideaki @USAGI : improved source address
33 * selection; consider scope,
34 * status etc.
Linus Torvalds1da177e2005-04-16 15:20:36 -070035 */
36
Joe Perchesf3213832012-05-15 14:11:53 +000037#define pr_fmt(fmt) "IPv6: " fmt
38
Linus Torvalds1da177e2005-04-16 15:20:36 -070039#include <linux/errno.h>
40#include <linux/types.h>
Ilpo Järvinena0bffff2009-03-21 13:36:17 -070041#include <linux/kernel.h>
Ingo Molnar174cd4b2017-02-02 19:15:33 +010042#include <linux/sched/signal.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/socket.h>
44#include <linux/sockios.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include <linux/net.h>
Hannes Frederic Sowa3d1bec92015-03-23 23:36:00 +010046#include <linux/inet.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include <linux/in6.h>
48#include <linux/netdevice.h>
Thomas Graf18237302006-08-04 23:04:54 -070049#include <linux/if_addr.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070050#include <linux/if_arp.h>
51#include <linux/if_arcnet.h>
52#include <linux/if_infiniband.h>
53#include <linux/route.h>
54#include <linux/inetdevice.h>
55#include <linux/init.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090056#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070057#ifdef CONFIG_SYSCTL
58#include <linux/sysctl.h>
59#endif
Randy Dunlap4fc268d2006-01-11 12:17:47 -080060#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070061#include <linux/delay.h>
62#include <linux/notifier.h>
Paulo Marques543537b2005-06-23 00:09:02 -070063#include <linux/string.h>
Eric Dumazetddbe5032012-07-18 08:11:12 +000064#include <linux/hash.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070065
Eric W. Biederman457c4cb2007-09-12 12:01:34 +020066#include <net/net_namespace.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070067#include <net/sock.h>
68#include <net/snmp.h>
69
Alexander Aring5241c2d2015-12-14 20:55:22 +010070#include <net/6lowpan.h>
YOSHIFUJI Hideaki / 吉藤英明cb6bf352013-03-25 08:26:24 +000071#include <net/firewire.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070072#include <net/ipv6.h>
73#include <net/protocol.h>
74#include <net/ndisc.h>
75#include <net/ip6_route.h>
76#include <net/addrconf.h>
77#include <net/tcp.h>
78#include <net/ip.h>
Thomas Graf5d620262006-08-15 00:35:02 -070079#include <net/netlink.h>
Mitsuru Chinenf24e3d62007-10-10 02:53:43 -070080#include <net/pkt_sched.h>
David Ahernca254492015-10-12 11:47:10 -070081#include <net/l3mdev.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070082#include <linux/if_tunnel.h>
83#include <linux/rtnetlink.h>
Nicolas Dichtelf3a1bfb2012-10-25 22:28:50 +000084#include <linux/netconf.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070085#include <linux/random.h>
Stephen Hemmingere21e8462010-03-20 16:09:01 -070086#include <linux/uaccess.h>
Herbert Xu7f7d9a62007-04-24 21:54:09 -070087#include <asm/unaligned.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070088
89#include <linux/proc_fs.h>
90#include <linux/seq_file.h>
Paul Gortmakerbc3b2d72011-07-15 11:47:34 -040091#include <linux/export.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070092
Linus Torvalds1da177e2005-04-16 15:20:36 -070093#define INFINITY_LIFE_TIME 0xFFFFFFFF
Thomas Graf18a31e12010-11-17 04:12:02 +000094
Hannes Frederic Sowa3d1bec92015-03-23 23:36:00 +010095#define IPV6_MAX_STRLEN \
96 sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")
97
Thomas Graf18a31e12010-11-17 04:12:02 +000098static inline u32 cstamp_delta(unsigned long cstamp)
99{
100 return (cstamp - INITIAL_JIFFIES) * 100UL / HZ;
101}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102
Maciej Żenczykowskibd11f072016-09-27 23:57:58 -0700103static inline s32 rfc3315_s14_backoff_init(s32 irt)
104{
105 /* multiply 'initial retransmission time' by 0.9 .. 1.1 */
106 u64 tmp = (900000 + prandom_u32() % 200001) * (u64)irt;
107 do_div(tmp, 1000000);
108 return (s32)tmp;
109}
110
111static inline s32 rfc3315_s14_backoff_update(s32 rt, s32 mrt)
112{
113 /* multiply 'retransmission timeout' by 1.9 .. 2.1 */
114 u64 tmp = (1900000 + prandom_u32() % 200001) * (u64)rt;
115 do_div(tmp, 1000000);
116 if ((s32)tmp > mrt) {
117 /* multiply 'maximum retransmission time' by 0.9 .. 1.1 */
118 tmp = (900000 + prandom_u32() % 200001) * (u64)mrt;
119 do_div(tmp, 1000000);
120 }
121 return (s32)tmp;
122}
123
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124#ifdef CONFIG_SYSCTL
WANG Conga317a2f2014-07-25 15:25:09 -0700125static int addrconf_sysctl_register(struct inet6_dev *idev);
Pavel Emelyanov408c4762008-01-10 17:41:21 -0800126static void addrconf_sysctl_unregister(struct inet6_dev *idev);
127#else
WANG Conga317a2f2014-07-25 15:25:09 -0700128static inline int addrconf_sysctl_register(struct inet6_dev *idev)
Pavel Emelyanov408c4762008-01-10 17:41:21 -0800129{
WANG Conga317a2f2014-07-25 15:25:09 -0700130 return 0;
Pavel Emelyanov408c4762008-01-10 17:41:21 -0800131}
132
133static inline void addrconf_sysctl_unregister(struct inet6_dev *idev)
134{
135}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136#endif
137
Fernando Gont969c5462020-05-01 00:51:47 -0300138static void ipv6_gen_rnd_iid(struct in6_addr *addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139
YOSHIFUJI Hideaki1b34be72008-06-28 14:18:38 +0900140static int ipv6_generate_eui64(u8 *eui, struct net_device *dev);
Eric Dumazetd9bf82c2017-10-07 19:30:24 -0700141static int ipv6_count_addresses(const struct inet6_dev *idev);
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +0100142static int ipv6_generate_stable_address(struct in6_addr *addr,
143 u8 dad_count,
144 const struct inet6_dev *idev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145
Eric Dumazet27c565a2017-11-04 08:53:27 -0700146#define IN6_ADDR_HSIZE_SHIFT 8
147#define IN6_ADDR_HSIZE (1 << IN6_ADDR_HSIZE_SHIFT)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148/*
149 * Configured unicast address hash table
150 */
stephen hemmingerc2e21292010-03-17 20:31:10 +0000151static struct hlist_head inet6_addr_lst[IN6_ADDR_HSIZE];
stephen hemminger5c578aed2010-03-17 20:31:11 +0000152static DEFINE_SPINLOCK(addrconf_hash_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +0100154static void addrconf_verify(void);
155static void addrconf_verify_rtnl(void);
156static void addrconf_verify_work(struct work_struct *);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +0100158static struct workqueue_struct *addrconf_wq;
159static DECLARE_DELAYED_WORK(addr_chk_work, addrconf_verify_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160
161static void addrconf_join_anycast(struct inet6_ifaddr *ifp);
162static void addrconf_leave_anycast(struct inet6_ifaddr *ifp);
163
Jiri Pirko93d9b7d2010-03-10 10:28:56 +0000164static void addrconf_type_change(struct net_device *dev,
165 unsigned long event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166static int addrconf_ifdown(struct net_device *dev, int how);
167
David Ahern8d1c8022018-04-17 17:33:26 -0700168static struct fib6_info *addrconf_get_prefix_route(const struct in6_addr *pfx,
Romain Kuntz21caa662013-01-09 21:06:03 +0000169 int plen,
170 const struct net_device *dev,
David Ahern2b2450c2019-03-27 20:53:52 -0700171 u32 flags, u32 noflags,
172 bool no_gw);
Romain Kuntz21caa662013-01-09 21:06:03 +0000173
David S. Millercf22f9a2012-04-14 21:37:40 -0400174static void addrconf_dad_start(struct inet6_ifaddr *ifp);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +0100175static void addrconf_dad_work(struct work_struct *w);
David Ahernc76fe2d2018-01-25 20:16:29 -0800176static void addrconf_dad_completed(struct inet6_ifaddr *ifp, bool bump_id,
177 bool send_na);
Hangbin Liu896585d2018-11-21 21:52:33 +0800178static void addrconf_dad_run(struct inet6_dev *idev, bool restart);
Kees Cooke99e88a2017-10-16 14:43:17 -0700179static void addrconf_rs_timer(struct timer_list *t);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa);
181static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa);
182
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +0900183static void inet6_prefix_notify(int event, struct inet6_dev *idev,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 struct prefix_info *pinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185
Adrian Bunk888c8482008-07-22 14:21:58 -0700186static struct ipv6_devconf ipv6_devconf __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187 .forwarding = 0,
188 .hop_limit = IPV6_DEFAULT_HOPLIMIT,
189 .mtu6 = IPV6_MIN_MTU,
190 .accept_ra = 1,
191 .accept_redirects = 1,
192 .autoconf = 1,
193 .force_mld_version = 0,
Hannes Frederic Sowafc4eba52013-08-14 01:03:46 +0200194 .mldv1_unsolicited_report_interval = 10 * HZ,
195 .mldv2_unsolicited_report_interval = HZ,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196 .dad_transmits = 1,
197 .rtr_solicits = MAX_RTR_SOLICITATIONS,
198 .rtr_solicit_interval = RTR_SOLICITATION_INTERVAL,
Maciej Żenczykowskibd11f072016-09-27 23:57:58 -0700199 .rtr_solicit_max_interval = RTR_SOLICITATION_MAX_INTERVAL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 .rtr_solicit_delay = MAX_RTR_SOLICITATION_DELAY,
Ian Morris67ba4152014-08-24 21:53:10 +0100201 .use_tempaddr = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 .temp_valid_lft = TEMP_VALID_LIFETIME,
203 .temp_prefered_lft = TEMP_PREFERRED_LIFETIME,
204 .regen_max_retry = REGEN_MAX_RETRY,
205 .max_desync_factor = MAX_DESYNC_FACTOR,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206 .max_addresses = IPV6_MAX_ADDRESSES,
YOSHIFUJI Hideaki65f5c7c2006-03-20 16:55:08 -0800207 .accept_ra_defrtr = 1,
Ben Greeard9333192014-06-25 14:44:53 -0700208 .accept_ra_from_local = 0,
Hangbin Liu8013d1d2015-07-30 14:28:42 +0800209 .accept_ra_min_hop_limit= 1,
YOSHIFUJI Hideakic4fd30e2006-03-20 16:55:26 -0800210 .accept_ra_pinfo = 1,
YOSHIFUJI Hideaki930d6ff2006-03-20 17:05:30 -0800211#ifdef CONFIG_IPV6_ROUTER_PREF
212 .accept_ra_rtr_pref = 1,
YOSHIFUJI Hideaki52e163562006-03-20 17:05:47 -0800213 .rtr_probe_interval = 60 * HZ,
YOSHIFUJI Hideaki09c884d2006-03-20 17:07:03 -0800214#ifdef CONFIG_IPV6_ROUTE_INFO
Joel Scherpelzbbea1242017-03-22 18:19:04 +0900215 .accept_ra_rt_info_min_plen = 0,
YOSHIFUJI Hideaki09c884d2006-03-20 17:07:03 -0800216 .accept_ra_rt_info_max_plen = 0,
217#endif
YOSHIFUJI Hideaki930d6ff2006-03-20 17:05:30 -0800218#endif
YOSHIFUJI Hideakifbea49e2006-09-22 14:43:49 -0700219 .proxy_ndp = 0,
YOSHIFUJI Hideaki0bcbc922007-04-24 14:58:30 -0700220 .accept_source_route = 0, /* we do not accept RH0 by default. */
YOSHIFUJI Hideaki778d80b2008-06-28 14:17:11 +0900221 .disable_ipv6 = 0,
Nicolas Dichtel09400952017-11-14 14:21:32 +0100222 .accept_dad = 0,
Hannes Frederic Sowab800c3b2013-08-27 01:36:51 +0200223 .suppress_frag_ndisc = 1,
Harout Hedeshianc2943f12015-01-20 10:06:05 -0700224 .accept_ra_mtu = 1,
Hannes Frederic Sowa3d1bec92015-03-23 23:36:00 +0100225 .stable_secret = {
226 .initialized = false,
Erik Kline3985e8a2015-07-22 16:38:25 +0900227 },
228 .use_oif_addrs_only = 0,
Andy Gospodarek35103d12015-08-13 10:39:01 -0400229 .ignore_routes_with_linkdown = 0,
David Ahernf1705ec2016-02-24 09:25:37 -0800230 .keep_addr_on_down = 0,
David Lebrun1ababeb2016-11-08 14:57:39 +0100231 .seg6_enabled = 0,
David Lebrunbf355b82016-11-08 14:57:42 +0100232#ifdef CONFIG_IPV6_SEG6_HMAC
233 .seg6_require_hmac = 0,
234#endif
Erik Nordmarkadc176c2016-12-02 14:00:08 -0800235 .enhanced_dad = 1,
Felix Jiad35a00b2017-01-26 16:59:17 +1300236 .addr_gen_mode = IN6_ADDR_GEN_MODE_EUI64,
David Forsterdf789fe2017-02-23 16:27:18 +0000237 .disable_policy = 0,
Alexander Aring8610c7c2020-03-27 18:00:20 -0400238 .rpl_seg_enabled = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239};
240
Brian Haleyab32ea52006-09-22 14:15:41 -0700241static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 .forwarding = 0,
243 .hop_limit = IPV6_DEFAULT_HOPLIMIT,
244 .mtu6 = IPV6_MIN_MTU,
245 .accept_ra = 1,
246 .accept_redirects = 1,
247 .autoconf = 1,
Hannes Frederic Sowafc4eba52013-08-14 01:03:46 +0200248 .force_mld_version = 0,
249 .mldv1_unsolicited_report_interval = 10 * HZ,
250 .mldv2_unsolicited_report_interval = HZ,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 .dad_transmits = 1,
252 .rtr_solicits = MAX_RTR_SOLICITATIONS,
253 .rtr_solicit_interval = RTR_SOLICITATION_INTERVAL,
Maciej Żenczykowskibd11f072016-09-27 23:57:58 -0700254 .rtr_solicit_max_interval = RTR_SOLICITATION_MAX_INTERVAL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 .rtr_solicit_delay = MAX_RTR_SOLICITATION_DELAY,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256 .use_tempaddr = 0,
257 .temp_valid_lft = TEMP_VALID_LIFETIME,
258 .temp_prefered_lft = TEMP_PREFERRED_LIFETIME,
259 .regen_max_retry = REGEN_MAX_RETRY,
260 .max_desync_factor = MAX_DESYNC_FACTOR,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 .max_addresses = IPV6_MAX_ADDRESSES,
YOSHIFUJI Hideaki65f5c7c2006-03-20 16:55:08 -0800262 .accept_ra_defrtr = 1,
Ben Greeard9333192014-06-25 14:44:53 -0700263 .accept_ra_from_local = 0,
Hangbin Liu8013d1d2015-07-30 14:28:42 +0800264 .accept_ra_min_hop_limit= 1,
YOSHIFUJI Hideakic4fd30e2006-03-20 16:55:26 -0800265 .accept_ra_pinfo = 1,
YOSHIFUJI Hideaki930d6ff2006-03-20 17:05:30 -0800266#ifdef CONFIG_IPV6_ROUTER_PREF
267 .accept_ra_rtr_pref = 1,
YOSHIFUJI Hideaki52e163562006-03-20 17:05:47 -0800268 .rtr_probe_interval = 60 * HZ,
YOSHIFUJI Hideaki09c884d2006-03-20 17:07:03 -0800269#ifdef CONFIG_IPV6_ROUTE_INFO
Joel Scherpelzbbea1242017-03-22 18:19:04 +0900270 .accept_ra_rt_info_min_plen = 0,
YOSHIFUJI Hideaki09c884d2006-03-20 17:07:03 -0800271 .accept_ra_rt_info_max_plen = 0,
272#endif
YOSHIFUJI Hideaki930d6ff2006-03-20 17:05:30 -0800273#endif
YOSHIFUJI Hideakifbea49e2006-09-22 14:43:49 -0700274 .proxy_ndp = 0,
YOSHIFUJI Hideaki0bcbc922007-04-24 14:58:30 -0700275 .accept_source_route = 0, /* we do not accept RH0 by default. */
YOSHIFUJI Hideaki778d80b2008-06-28 14:17:11 +0900276 .disable_ipv6 = 0,
YOSHIFUJI Hideaki1b34be72008-06-28 14:18:38 +0900277 .accept_dad = 1,
Hannes Frederic Sowab800c3b2013-08-27 01:36:51 +0200278 .suppress_frag_ndisc = 1,
Harout Hedeshianc2943f12015-01-20 10:06:05 -0700279 .accept_ra_mtu = 1,
Hannes Frederic Sowa3d1bec92015-03-23 23:36:00 +0100280 .stable_secret = {
281 .initialized = false,
282 },
Erik Kline3985e8a2015-07-22 16:38:25 +0900283 .use_oif_addrs_only = 0,
Andy Gospodarek35103d12015-08-13 10:39:01 -0400284 .ignore_routes_with_linkdown = 0,
David Ahernf1705ec2016-02-24 09:25:37 -0800285 .keep_addr_on_down = 0,
David Lebrun1ababeb2016-11-08 14:57:39 +0100286 .seg6_enabled = 0,
David Lebrunbf355b82016-11-08 14:57:42 +0100287#ifdef CONFIG_IPV6_SEG6_HMAC
288 .seg6_require_hmac = 0,
289#endif
Erik Nordmarkadc176c2016-12-02 14:00:08 -0800290 .enhanced_dad = 1,
Felix Jiad35a00b2017-01-26 16:59:17 +1300291 .addr_gen_mode = IN6_ADDR_GEN_MODE_EUI64,
David Forsterdf789fe2017-02-23 16:27:18 +0000292 .disable_policy = 0,
Alexander Aring8610c7c2020-03-27 18:00:20 -0400293 .rpl_seg_enabled = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294};
295
Mike Manning1f372c72017-09-25 22:01:36 +0100296/* Check if link is ready: is it up and is a valid qdisc available */
297static inline bool addrconf_link_ready(const struct net_device *dev)
Mitsuru Chinenf24e3d62007-10-10 02:53:43 -0700298{
Mike Manning1f372c72017-09-25 22:01:36 +0100299 return netif_oper_up(dev) && !qdisc_tx_is_noop(dev);
Mitsuru Chinenf24e3d62007-10-10 02:53:43 -0700300}
301
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +0200302static void addrconf_del_rs_timer(struct inet6_dev *idev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303{
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +0200304 if (del_timer(&idev->rs_timer))
305 __in6_dev_put(idev);
306}
307
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +0100308static void addrconf_del_dad_work(struct inet6_ifaddr *ifp)
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +0200309{
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +0100310 if (cancel_delayed_work(&ifp->dad_work))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 __in6_ifa_put(ifp);
312}
313
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +0200314static void addrconf_mod_rs_timer(struct inet6_dev *idev,
315 unsigned long when)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316{
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +0200317 if (!timer_pending(&idev->rs_timer))
318 in6_dev_hold(idev);
319 mod_timer(&idev->rs_timer, jiffies + when);
320}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +0100322static void addrconf_mod_dad_work(struct inet6_ifaddr *ifp,
323 unsigned long delay)
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +0200324{
Xin Longf8a894b2017-06-15 16:33:58 +0800325 in6_ifa_hold(ifp);
326 if (mod_delayed_work(addrconf_wq, &ifp->dad_work, delay))
327 in6_ifa_put(ifp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328}
329
Herbert Xu7f7d9a62007-04-24 21:54:09 -0700330static int snmp6_alloc_dev(struct inet6_dev *idev)
331{
John Stultz827da442013-10-07 15:51:58 -0700332 int i;
333
WANG Cong698365f2014-05-05 15:55:55 -0700334 idev->stats.ipv6 = alloc_percpu(struct ipstats_mib);
335 if (!idev->stats.ipv6)
Herbert Xu7f7d9a62007-04-24 21:54:09 -0700336 goto err_ip;
John Stultz827da442013-10-07 15:51:58 -0700337
338 for_each_possible_cpu(i) {
339 struct ipstats_mib *addrconf_stats;
WANG Cong698365f2014-05-05 15:55:55 -0700340 addrconf_stats = per_cpu_ptr(idev->stats.ipv6, i);
John Stultz827da442013-10-07 15:51:58 -0700341 u64_stats_init(&addrconf_stats->syncp);
John Stultz827da442013-10-07 15:51:58 -0700342 }
343
344
Eric Dumazetbe281e52011-05-19 01:14:23 +0000345 idev->stats.icmpv6dev = kzalloc(sizeof(struct icmpv6_mib_device),
346 GFP_KERNEL);
347 if (!idev->stats.icmpv6dev)
Herbert Xu7f7d9a62007-04-24 21:54:09 -0700348 goto err_icmp;
Eric Dumazetbe281e52011-05-19 01:14:23 +0000349 idev->stats.icmpv6msgdev = kzalloc(sizeof(struct icmpv6msg_mib_device),
350 GFP_KERNEL);
351 if (!idev->stats.icmpv6msgdev)
David L Stevens14878f72007-09-16 16:52:35 -0700352 goto err_icmpmsg;
Herbert Xu7f7d9a62007-04-24 21:54:09 -0700353
354 return 0;
355
David L Stevens14878f72007-09-16 16:52:35 -0700356err_icmpmsg:
Eric Dumazetbe281e52011-05-19 01:14:23 +0000357 kfree(idev->stats.icmpv6dev);
Herbert Xu7f7d9a62007-04-24 21:54:09 -0700358err_icmp:
WANG Cong698365f2014-05-05 15:55:55 -0700359 free_percpu(idev->stats.ipv6);
Herbert Xu7f7d9a62007-04-24 21:54:09 -0700360err_ip:
Pavel Emelyanovaaf70ec2007-10-17 21:25:32 -0700361 return -ENOMEM;
Herbert Xu7f7d9a62007-04-24 21:54:09 -0700362}
363
Eldad Zack8e5e8f32012-04-01 07:49:08 +0000364static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365{
366 struct inet6_dev *ndev;
WANG Conga317a2f2014-07-25 15:25:09 -0700367 int err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368
369 ASSERT_RTNL();
370
371 if (dev->mtu < IPV6_MIN_MTU)
WANG Conga317a2f2014-07-25 15:25:09 -0700372 return ERR_PTR(-EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +0900374 ndev = kzalloc(sizeof(struct inet6_dev), GFP_KERNEL);
Ian Morris63159f22015-03-29 14:00:04 +0100375 if (!ndev)
WANG Conga317a2f2014-07-25 15:25:09 -0700376 return ERR_PTR(err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377
Ingo Oeser322f74a2006-03-20 23:01:47 -0800378 rwlock_init(&ndev->lock);
379 ndev->dev = dev;
stephen hemminger502a2ff2010-03-17 20:31:13 +0000380 INIT_LIST_HEAD(&ndev->addr_list);
Kees Cooke99e88a2017-10-16 14:43:17 -0700381 timer_setup(&ndev->rs_timer, addrconf_rs_timer, 0);
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +0900382 memcpy(&ndev->cnf, dev_net(dev)->ipv6.devconf_dflt, sizeof(ndev->cnf));
Hannes Frederic Sowa9b29c692015-12-15 22:59:12 +0100383
384 if (ndev->cnf.stable_secret.initialized)
Felix Jiad35a00b2017-01-26 16:59:17 +1300385 ndev->cnf.addr_gen_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
Hannes Frederic Sowa9b29c692015-12-15 22:59:12 +0100386
Ingo Oeser322f74a2006-03-20 23:01:47 -0800387 ndev->cnf.mtu6 = dev->mtu;
Ingo Oeser322f74a2006-03-20 23:01:47 -0800388 ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl);
Ian Morris63159f22015-03-29 14:00:04 +0100389 if (!ndev->nd_parms) {
Ingo Oeser322f74a2006-03-20 23:01:47 -0800390 kfree(ndev);
WANG Conga317a2f2014-07-25 15:25:09 -0700391 return ERR_PTR(err);
Ingo Oeser322f74a2006-03-20 23:01:47 -0800392 }
Ben Hutchings0187bdf2008-06-19 16:15:47 -0700393 if (ndev->cnf.forwarding)
394 dev_disable_lro(dev);
Ingo Oeser322f74a2006-03-20 23:01:47 -0800395 /* We refer to the device */
396 dev_hold(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397
Ingo Oeser322f74a2006-03-20 23:01:47 -0800398 if (snmp6_alloc_dev(ndev) < 0) {
Joe Perchese32ac252018-03-26 08:35:01 -0700399 netdev_dbg(dev, "%s: cannot allocate memory for statistics\n",
400 __func__);
Ingo Oeser322f74a2006-03-20 23:01:47 -0800401 neigh_parms_release(&nd_tbl, ndev->nd_parms);
Roy Li8603e332011-09-20 15:10:16 -0400402 dev_put(dev);
403 kfree(ndev);
WANG Conga317a2f2014-07-25 15:25:09 -0700404 return ERR_PTR(err);
Ingo Oeser322f74a2006-03-20 23:01:47 -0800405 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406
Ingo Oeser322f74a2006-03-20 23:01:47 -0800407 if (snmp6_register_dev(ndev) < 0) {
Joe Perchese32ac252018-03-26 08:35:01 -0700408 netdev_dbg(dev, "%s: cannot create /proc/net/dev_snmp6/%s\n",
409 __func__, dev->name);
WANG Conga317a2f2014-07-25 15:25:09 -0700410 goto err_release;
Ingo Oeser322f74a2006-03-20 23:01:47 -0800411 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412
Jiri Bohac9d6280d2016-10-13 18:50:02 +0200413 /* One reference from device. */
Reshetova, Elena1be92462017-07-04 09:34:55 +0300414 refcount_set(&ndev->refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415
YOSHIFUJI Hideaki1b34be72008-06-28 14:18:38 +0900416 if (dev->flags & (IFF_NOARP | IFF_LOOPBACK))
417 ndev->cnf.accept_dad = -1;
418
Amerigo Wang07a93622012-10-29 16:23:10 +0000419#if IS_ENABLED(CONFIG_IPV6_SIT)
YOSHIFUJI Hideakib077d7a2008-04-13 23:42:18 -0700420 if (dev->type == ARPHRD_SIT && (dev->priv_flags & IFF_ISATAP)) {
Joe Perchesf3213832012-05-15 14:11:53 +0000421 pr_info("%s: Disabled Multicast RS\n", dev->name);
YOSHIFUJI Hideakib077d7a2008-04-13 23:42:18 -0700422 ndev->cnf.rtr_solicits = 0;
423 }
424#endif
425
stephen hemminger372e6c82010-03-17 20:31:09 +0000426 INIT_LIST_HEAD(&ndev->tempaddr_list);
Jiri Bohac76506a92016-10-13 18:52:15 +0200427 ndev->desync_factor = U32_MAX;
Ingo Oeser322f74a2006-03-20 23:01:47 -0800428 if ((dev->flags&IFF_LOOPBACK) ||
429 dev->type == ARPHRD_TUNNEL ||
YOSHIFUJI Hideaki9625ed72008-04-13 23:47:11 -0700430 dev->type == ARPHRD_TUNNEL6 ||
Joerg Roedel0be669b2006-10-10 14:49:53 -0700431 dev->type == ARPHRD_SIT ||
Joerg Roedel0be669b2006-10-10 14:49:53 -0700432 dev->type == ARPHRD_NONE) {
Ingo Oeser322f74a2006-03-20 23:01:47 -0800433 ndev->cnf.use_tempaddr = -1;
Fernando Gont969c5462020-05-01 00:51:47 -0300434 }
David S. Miller5d9efa72013-10-28 20:07:50 -0400435
Daniel Borkmann914faa12013-04-09 03:47:14 +0000436 ndev->token = in6addr_any;
Ingo Oeser322f74a2006-03-20 23:01:47 -0800437
Mike Manning1f372c72017-09-25 22:01:36 +0100438 if (netif_running(dev) && addrconf_link_ready(dev))
Herbert Xu53aadcc2007-03-27 14:31:52 -0700439 ndev->if_flags |= IF_READY;
440
Ingo Oeser322f74a2006-03-20 23:01:47 -0800441 ipv6_mc_init_dev(ndev);
442 ndev->tstamp = jiffies;
WANG Conga317a2f2014-07-25 15:25:09 -0700443 err = addrconf_sysctl_register(ndev);
444 if (err) {
445 ipv6_mc_destroy_dev(ndev);
Sabrina Dubroca2a189f9e2015-11-04 14:47:53 +0100446 snmp6_unregister_dev(ndev);
WANG Conga317a2f2014-07-25 15:25:09 -0700447 goto err_release;
448 }
David L Stevens30c4cf52007-01-04 12:31:14 -0800449 /* protected by rtnl_lock */
Eric Dumazetcf778b02012-01-12 04:41:32 +0000450 rcu_assign_pointer(dev->ip6_ptr, ndev);
YOSHIFUJI Hideakid88ae4c2007-01-14 21:48:40 -0800451
Hannes Frederic Sowa2c5e8932013-02-10 03:50:18 +0000452 /* Join interface-local all-node multicast group */
453 ipv6_dev_mc_inc(dev, &in6addr_interfacelocal_allnodes);
454
YOSHIFUJI Hideakid88ae4c2007-01-14 21:48:40 -0800455 /* Join all-node multicast group */
YOSHIFUJI Hideakif3ee4012008-04-10 15:42:11 +0900456 ipv6_dev_mc_inc(dev, &in6addr_linklocal_allnodes);
YOSHIFUJI Hideakid88ae4c2007-01-14 21:48:40 -0800457
Li Weid6ddef92012-03-05 14:45:17 +0000458 /* Join all-router multicast group if forwarding is set */
Li Wei8b2aaed2012-03-07 14:58:07 +0000459 if (ndev->cnf.forwarding && (dev->flags & IFF_MULTICAST))
Li Weid6ddef92012-03-05 14:45:17 +0000460 ipv6_dev_mc_inc(dev, &in6addr_linklocal_allrouters);
461
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 return ndev;
WANG Conga317a2f2014-07-25 15:25:09 -0700463
464err_release:
465 neigh_parms_release(&nd_tbl, ndev->nd_parms);
466 ndev->dead = 1;
467 in6_dev_finish_destroy(ndev);
468 return ERR_PTR(err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469}
470
Eldad Zack8e5e8f32012-04-01 07:49:08 +0000471static struct inet6_dev *ipv6_find_idev(struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472{
473 struct inet6_dev *idev;
474
475 ASSERT_RTNL();
476
Stephen Hemmingere21e8462010-03-20 16:09:01 -0700477 idev = __in6_dev_get(dev);
478 if (!idev) {
479 idev = ipv6_add_dev(dev);
WANG Conga317a2f2014-07-25 15:25:09 -0700480 if (IS_ERR(idev))
Sabrina Dubrocadb0b99f2019-08-23 15:44:36 +0200481 return idev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 }
YOSHIFUJI Hideakic5e33bd2005-12-21 22:57:44 +0900483
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 if (dev->flags&IFF_UP)
485 ipv6_mc_up(idev);
486 return idev;
487}
488
Nicolas Dichtelf3a1bfb2012-10-25 22:28:50 +0000489static int inet6_netconf_msgsize_devconf(int type)
490{
491 int size = NLMSG_ALIGN(sizeof(struct netconfmsg))
492 + nla_total_size(4); /* NETCONFA_IFINDEX */
Zhang Shengju136ba622016-03-10 08:55:50 +0000493 bool all = false;
Nicolas Dichtelf3a1bfb2012-10-25 22:28:50 +0000494
Zhang Shengju136ba622016-03-10 08:55:50 +0000495 if (type == NETCONFA_ALL)
496 all = true;
497
498 if (all || type == NETCONFA_FORWARDING)
Nicolas Dichtelf3a1bfb2012-10-25 22:28:50 +0000499 size += nla_total_size(4);
David S. Millerb1afce92012-12-04 14:46:34 -0500500#ifdef CONFIG_IPV6_MROUTE
Zhang Shengju136ba622016-03-10 08:55:50 +0000501 if (all || type == NETCONFA_MC_FORWARDING)
Nicolas Dichteld67b8c62012-12-04 01:13:35 +0000502 size += nla_total_size(4);
David S. Millerb1afce92012-12-04 14:46:34 -0500503#endif
Zhang Shengju136ba622016-03-10 08:55:50 +0000504 if (all || type == NETCONFA_PROXY_NEIGH)
stephen hemmingerc92d5492013-12-17 22:37:14 -0800505 size += nla_total_size(4);
Nicolas Dichtelf3a1bfb2012-10-25 22:28:50 +0000506
Zhang Shengju136ba622016-03-10 08:55:50 +0000507 if (all || type == NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN)
Andy Gospodarek35103d12015-08-13 10:39:01 -0400508 size += nla_total_size(4);
509
Nicolas Dichtelf3a1bfb2012-10-25 22:28:50 +0000510 return size;
511}
512
513static int inet6_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
514 struct ipv6_devconf *devconf, u32 portid,
515 u32 seq, int event, unsigned int flags,
516 int type)
517{
518 struct nlmsghdr *nlh;
519 struct netconfmsg *ncm;
Zhang Shengju136ba622016-03-10 08:55:50 +0000520 bool all = false;
Nicolas Dichtelf3a1bfb2012-10-25 22:28:50 +0000521
522 nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct netconfmsg),
523 flags);
Ian Morris63159f22015-03-29 14:00:04 +0100524 if (!nlh)
Nicolas Dichtelf3a1bfb2012-10-25 22:28:50 +0000525 return -EMSGSIZE;
526
Zhang Shengju136ba622016-03-10 08:55:50 +0000527 if (type == NETCONFA_ALL)
528 all = true;
529
Nicolas Dichtelf3a1bfb2012-10-25 22:28:50 +0000530 ncm = nlmsg_data(nlh);
531 ncm->ncm_family = AF_INET6;
532
533 if (nla_put_s32(skb, NETCONFA_IFINDEX, ifindex) < 0)
534 goto nla_put_failure;
535
David Ahern23452172017-03-28 14:28:05 -0700536 if (!devconf)
537 goto out;
538
Zhang Shengju136ba622016-03-10 08:55:50 +0000539 if ((all || type == NETCONFA_FORWARDING) &&
Nicolas Dichtelf3a1bfb2012-10-25 22:28:50 +0000540 nla_put_s32(skb, NETCONFA_FORWARDING, devconf->forwarding) < 0)
541 goto nla_put_failure;
David S. Millerb1afce92012-12-04 14:46:34 -0500542#ifdef CONFIG_IPV6_MROUTE
Zhang Shengju136ba622016-03-10 08:55:50 +0000543 if ((all || type == NETCONFA_MC_FORWARDING) &&
Nicolas Dichteld67b8c62012-12-04 01:13:35 +0000544 nla_put_s32(skb, NETCONFA_MC_FORWARDING,
545 devconf->mc_forwarding) < 0)
546 goto nla_put_failure;
David S. Millerb1afce92012-12-04 14:46:34 -0500547#endif
Zhang Shengju136ba622016-03-10 08:55:50 +0000548 if ((all || type == NETCONFA_PROXY_NEIGH) &&
stephen hemmingerc92d5492013-12-17 22:37:14 -0800549 nla_put_s32(skb, NETCONFA_PROXY_NEIGH, devconf->proxy_ndp) < 0)
550 goto nla_put_failure;
551
Zhang Shengju136ba622016-03-10 08:55:50 +0000552 if ((all || type == NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN) &&
Andy Gospodarek35103d12015-08-13 10:39:01 -0400553 nla_put_s32(skb, NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN,
554 devconf->ignore_routes_with_linkdown) < 0)
555 goto nla_put_failure;
556
David Ahern23452172017-03-28 14:28:05 -0700557out:
Johannes Berg053c0952015-01-16 22:09:00 +0100558 nlmsg_end(skb, nlh);
559 return 0;
Nicolas Dichtelf3a1bfb2012-10-25 22:28:50 +0000560
561nla_put_failure:
562 nlmsg_cancel(skb, nlh);
563 return -EMSGSIZE;
564}
565
David Ahern85b3daa2017-03-28 14:28:04 -0700566void inet6_netconf_notify_devconf(struct net *net, int event, int type,
567 int ifindex, struct ipv6_devconf *devconf)
Nicolas Dichtelf3a1bfb2012-10-25 22:28:50 +0000568{
569 struct sk_buff *skb;
570 int err = -ENOBUFS;
571
Eric Dumazet927265b2016-07-08 05:46:04 +0200572 skb = nlmsg_new(inet6_netconf_msgsize_devconf(type), GFP_KERNEL);
Ian Morris63159f22015-03-29 14:00:04 +0100573 if (!skb)
Nicolas Dichtelf3a1bfb2012-10-25 22:28:50 +0000574 goto errout;
575
576 err = inet6_netconf_fill_devconf(skb, ifindex, devconf, 0, 0,
David Ahern85b3daa2017-03-28 14:28:04 -0700577 event, 0, type);
Nicolas Dichtelf3a1bfb2012-10-25 22:28:50 +0000578 if (err < 0) {
579 /* -EMSGSIZE implies BUG in inet6_netconf_msgsize_devconf() */
580 WARN_ON(err == -EMSGSIZE);
581 kfree_skb(skb);
582 goto errout;
583 }
Eric Dumazet927265b2016-07-08 05:46:04 +0200584 rtnl_notify(skb, net, 0, RTNLGRP_IPV6_NETCONF, NULL, GFP_KERNEL);
Nicolas Dichtelf3a1bfb2012-10-25 22:28:50 +0000585 return;
586errout:
Cong Dingbd779022012-12-18 12:08:56 +0000587 rtnl_set_sk_err(net, RTNLGRP_IPV6_NETCONF, err);
Nicolas Dichtelf3a1bfb2012-10-25 22:28:50 +0000588}
589
Nicolas Dichtel76f8f6c2012-10-25 22:28:51 +0000590static const struct nla_policy devconf_ipv6_policy[NETCONFA_MAX+1] = {
591 [NETCONFA_IFINDEX] = { .len = sizeof(int) },
592 [NETCONFA_FORWARDING] = { .len = sizeof(int) },
stephen hemmingerc92d5492013-12-17 22:37:14 -0800593 [NETCONFA_PROXY_NEIGH] = { .len = sizeof(int) },
Andy Gospodarek35103d12015-08-13 10:39:01 -0400594 [NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN] = { .len = sizeof(int) },
Nicolas Dichtel76f8f6c2012-10-25 22:28:51 +0000595};
596
Jakub Kicinski38d51812019-01-18 10:46:22 -0800597static int inet6_netconf_valid_get_req(struct sk_buff *skb,
598 const struct nlmsghdr *nlh,
599 struct nlattr **tb,
600 struct netlink_ext_ack *extack)
601{
602 int i, err;
603
604 if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(struct netconfmsg))) {
605 NL_SET_ERR_MSG_MOD(extack, "Invalid header for netconf get request");
606 return -EINVAL;
607 }
608
609 if (!netlink_strict_get_check(skb))
Johannes Berg8cb08172019-04-26 14:07:28 +0200610 return nlmsg_parse_deprecated(nlh, sizeof(struct netconfmsg),
611 tb, NETCONFA_MAX,
612 devconf_ipv6_policy, extack);
Jakub Kicinski38d51812019-01-18 10:46:22 -0800613
Johannes Berg8cb08172019-04-26 14:07:28 +0200614 err = nlmsg_parse_deprecated_strict(nlh, sizeof(struct netconfmsg),
615 tb, NETCONFA_MAX,
616 devconf_ipv6_policy, extack);
Jakub Kicinski38d51812019-01-18 10:46:22 -0800617 if (err)
618 return err;
619
620 for (i = 0; i <= NETCONFA_MAX; i++) {
621 if (!tb[i])
622 continue;
623
624 switch (i) {
625 case NETCONFA_IFINDEX:
626 break;
627 default:
628 NL_SET_ERR_MSG_MOD(extack, "Unsupported attribute in netconf get request");
629 return -EINVAL;
630 }
631 }
632
633 return 0;
634}
635
Nicolas Dichtel76f8f6c2012-10-25 22:28:51 +0000636static int inet6_netconf_get_devconf(struct sk_buff *in_skb,
David Ahernc21ef3e2017-04-16 09:48:24 -0700637 struct nlmsghdr *nlh,
638 struct netlink_ext_ack *extack)
Nicolas Dichtel76f8f6c2012-10-25 22:28:51 +0000639{
640 struct net *net = sock_net(in_skb->sk);
641 struct nlattr *tb[NETCONFA_MAX+1];
Florian Westphal4ea26072017-10-11 10:28:00 +0200642 struct inet6_dev *in6_dev = NULL;
643 struct net_device *dev = NULL;
Nicolas Dichtel76f8f6c2012-10-25 22:28:51 +0000644 struct sk_buff *skb;
645 struct ipv6_devconf *devconf;
Nicolas Dichtel76f8f6c2012-10-25 22:28:51 +0000646 int ifindex;
647 int err;
648
Jakub Kicinski38d51812019-01-18 10:46:22 -0800649 err = inet6_netconf_valid_get_req(in_skb, nlh, tb, extack);
Nicolas Dichtel76f8f6c2012-10-25 22:28:51 +0000650 if (err < 0)
Florian Westphal4ea26072017-10-11 10:28:00 +0200651 return err;
652
653 if (!tb[NETCONFA_IFINDEX])
654 return -EINVAL;
Nicolas Dichtel76f8f6c2012-10-25 22:28:51 +0000655
Anton Protopopova97eb332016-02-16 21:43:16 -0500656 err = -EINVAL;
Nicolas Dichtel76f8f6c2012-10-25 22:28:51 +0000657 ifindex = nla_get_s32(tb[NETCONFA_IFINDEX]);
658 switch (ifindex) {
659 case NETCONFA_IFINDEX_ALL:
660 devconf = net->ipv6.devconf_all;
661 break;
662 case NETCONFA_IFINDEX_DEFAULT:
663 devconf = net->ipv6.devconf_dflt;
664 break;
665 default:
Florian Westphal4ea26072017-10-11 10:28:00 +0200666 dev = dev_get_by_index(net, ifindex);
Ian Morris63159f22015-03-29 14:00:04 +0100667 if (!dev)
Florian Westphal4ea26072017-10-11 10:28:00 +0200668 return -EINVAL;
669 in6_dev = in6_dev_get(dev);
Ian Morris63159f22015-03-29 14:00:04 +0100670 if (!in6_dev)
Nicolas Dichtel76f8f6c2012-10-25 22:28:51 +0000671 goto errout;
672 devconf = &in6_dev->cnf;
673 break;
674 }
675
676 err = -ENOBUFS;
Florian Westphal4ea26072017-10-11 10:28:00 +0200677 skb = nlmsg_new(inet6_netconf_msgsize_devconf(NETCONFA_ALL), GFP_KERNEL);
Ian Morris63159f22015-03-29 14:00:04 +0100678 if (!skb)
Nicolas Dichtel76f8f6c2012-10-25 22:28:51 +0000679 goto errout;
680
681 err = inet6_netconf_fill_devconf(skb, ifindex, devconf,
682 NETLINK_CB(in_skb).portid,
683 nlh->nlmsg_seq, RTM_NEWNETCONF, 0,
Zhang Shengju136ba622016-03-10 08:55:50 +0000684 NETCONFA_ALL);
Nicolas Dichtel76f8f6c2012-10-25 22:28:51 +0000685 if (err < 0) {
686 /* -EMSGSIZE implies BUG in inet6_netconf_msgsize_devconf() */
687 WARN_ON(err == -EMSGSIZE);
688 kfree_skb(skb);
689 goto errout;
690 }
691 err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
692errout:
Florian Westphal4ea26072017-10-11 10:28:00 +0200693 if (in6_dev)
694 in6_dev_put(in6_dev);
695 if (dev)
696 dev_put(dev);
Nicolas Dichtel76f8f6c2012-10-25 22:28:51 +0000697 return err;
698}
699
Nicolas Dichtel7a674202013-03-05 23:42:06 +0000700static int inet6_netconf_dump_devconf(struct sk_buff *skb,
701 struct netlink_callback *cb)
702{
David Ahernaddd3832018-10-07 20:16:41 -0700703 const struct nlmsghdr *nlh = cb->nlh;
Nicolas Dichtel7a674202013-03-05 23:42:06 +0000704 struct net *net = sock_net(skb->sk);
705 int h, s_h;
706 int idx, s_idx;
707 struct net_device *dev;
708 struct inet6_dev *idev;
709 struct hlist_head *head;
710
David Ahernaddd3832018-10-07 20:16:41 -0700711 if (cb->strict_check) {
712 struct netlink_ext_ack *extack = cb->extack;
713 struct netconfmsg *ncm;
714
715 if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ncm))) {
716 NL_SET_ERR_MSG_MOD(extack, "Invalid header for netconf dump request");
717 return -EINVAL;
718 }
719
720 if (nlmsg_attrlen(nlh, sizeof(*ncm))) {
721 NL_SET_ERR_MSG_MOD(extack, "Invalid data after header in netconf dump request");
722 return -EINVAL;
723 }
724 }
725
Nicolas Dichtel7a674202013-03-05 23:42:06 +0000726 s_h = cb->args[0];
727 s_idx = idx = cb->args[1];
728
729 for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
730 idx = 0;
731 head = &net->dev_index_head[h];
732 rcu_read_lock();
Nicolas Dichtel63998ac2013-03-22 06:28:43 +0000733 cb->seq = atomic_read(&net->ipv6.dev_addr_genid) ^
734 net->dev_base_seq;
Nicolas Dichtel7a674202013-03-05 23:42:06 +0000735 hlist_for_each_entry_rcu(dev, head, index_hlist) {
736 if (idx < s_idx)
737 goto cont;
738 idev = __in6_dev_get(dev);
739 if (!idev)
740 goto cont;
741
742 if (inet6_netconf_fill_devconf(skb, dev->ifindex,
743 &idev->cnf,
744 NETLINK_CB(cb->skb).portid,
David Ahernaddd3832018-10-07 20:16:41 -0700745 nlh->nlmsg_seq,
Nicolas Dichtel7a674202013-03-05 23:42:06 +0000746 RTM_NEWNETCONF,
747 NLM_F_MULTI,
Zhang Shengju136ba622016-03-10 08:55:50 +0000748 NETCONFA_ALL) < 0) {
Nicolas Dichtel7a674202013-03-05 23:42:06 +0000749 rcu_read_unlock();
750 goto done;
751 }
Nicolas Dichtel63998ac2013-03-22 06:28:43 +0000752 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
Nicolas Dichtel7a674202013-03-05 23:42:06 +0000753cont:
754 idx++;
755 }
756 rcu_read_unlock();
757 }
758 if (h == NETDEV_HASHENTRIES) {
759 if (inet6_netconf_fill_devconf(skb, NETCONFA_IFINDEX_ALL,
760 net->ipv6.devconf_all,
761 NETLINK_CB(cb->skb).portid,
David Ahernaddd3832018-10-07 20:16:41 -0700762 nlh->nlmsg_seq,
Nicolas Dichtel7a674202013-03-05 23:42:06 +0000763 RTM_NEWNETCONF, NLM_F_MULTI,
Zhang Shengju136ba622016-03-10 08:55:50 +0000764 NETCONFA_ALL) < 0)
Nicolas Dichtel7a674202013-03-05 23:42:06 +0000765 goto done;
766 else
767 h++;
768 }
769 if (h == NETDEV_HASHENTRIES + 1) {
770 if (inet6_netconf_fill_devconf(skb, NETCONFA_IFINDEX_DEFAULT,
771 net->ipv6.devconf_dflt,
772 NETLINK_CB(cb->skb).portid,
David Ahernaddd3832018-10-07 20:16:41 -0700773 nlh->nlmsg_seq,
Nicolas Dichtel7a674202013-03-05 23:42:06 +0000774 RTM_NEWNETCONF, NLM_F_MULTI,
Zhang Shengju136ba622016-03-10 08:55:50 +0000775 NETCONFA_ALL) < 0)
Nicolas Dichtel7a674202013-03-05 23:42:06 +0000776 goto done;
777 else
778 h++;
779 }
780done:
781 cb->args[0] = h;
782 cb->args[1] = idx;
783
784 return skb->len;
785}
786
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787#ifdef CONFIG_SYSCTL
788static void dev_forward_change(struct inet6_dev *idev)
789{
790 struct net_device *dev;
791 struct inet6_ifaddr *ifa;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792
793 if (!idev)
794 return;
795 dev = idev->dev;
Ben Hutchings0187bdf2008-06-19 16:15:47 -0700796 if (idev->cnf.forwarding)
797 dev_disable_lro(dev);
Amerigo Wang1a940832012-10-28 17:43:53 +0000798 if (dev->flags & IFF_MULTICAST) {
Hannes Frederic Sowa2c5e8932013-02-10 03:50:18 +0000799 if (idev->cnf.forwarding) {
YOSHIFUJI Hideakif3ee4012008-04-10 15:42:11 +0900800 ipv6_dev_mc_inc(dev, &in6addr_linklocal_allrouters);
Hannes Frederic Sowa2c5e8932013-02-10 03:50:18 +0000801 ipv6_dev_mc_inc(dev, &in6addr_interfacelocal_allrouters);
802 ipv6_dev_mc_inc(dev, &in6addr_sitelocal_allrouters);
803 } else {
YOSHIFUJI Hideakif3ee4012008-04-10 15:42:11 +0900804 ipv6_dev_mc_dec(dev, &in6addr_linklocal_allrouters);
Hannes Frederic Sowa2c5e8932013-02-10 03:50:18 +0000805 ipv6_dev_mc_dec(dev, &in6addr_interfacelocal_allrouters);
806 ipv6_dev_mc_dec(dev, &in6addr_sitelocal_allrouters);
807 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 }
stephen hemminger502a2ff2010-03-17 20:31:13 +0000809
810 list_for_each_entry(ifa, &idev->addr_list, if_list) {
Michal Wrobel2c12a742007-02-26 15:36:10 -0800811 if (ifa->flags&IFA_F_TENTATIVE)
812 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 if (idev->cnf.forwarding)
814 addrconf_join_anycast(ifa);
815 else
816 addrconf_leave_anycast(ifa);
817 }
David Ahern85b3daa2017-03-28 14:28:04 -0700818 inet6_netconf_notify_devconf(dev_net(dev), RTM_NEWNETCONF,
819 NETCONFA_FORWARDING,
Nicolas Dichtelf3a1bfb2012-10-25 22:28:50 +0000820 dev->ifindex, &idev->cnf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821}
822
823
Pavel Emelyanove1869322008-01-10 17:43:50 -0800824static void addrconf_forward_change(struct net *net, __s32 newf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825{
826 struct net_device *dev;
827 struct inet6_dev *idev;
828
Ben Hutchings4acd4942012-08-14 08:54:51 +0000829 for_each_netdev(net, dev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 idev = __in6_dev_get(dev);
831 if (idev) {
Pavel Emelyanove1869322008-01-10 17:43:50 -0800832 int changed = (!idev->cnf.forwarding) ^ (!newf);
833 idev->cnf.forwarding = newf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 if (changed)
835 dev_forward_change(idev);
836 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838}
Pavel Emelyanovc8fecf22007-12-05 01:50:24 -0800839
Francesco Ruggeri013d97e2012-01-16 10:40:10 +0000840static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf)
Pavel Emelyanovc8fecf22007-12-05 01:50:24 -0800841{
Pavel Emelyanovbff16c22008-01-10 17:42:13 -0800842 struct net *net;
Francesco Ruggeri013d97e2012-01-16 10:40:10 +0000843 int old;
844
845 if (!rtnl_trylock())
846 return restart_syscall();
Pavel Emelyanovbff16c22008-01-10 17:42:13 -0800847
848 net = (struct net *)table->extra2;
Francesco Ruggeri013d97e2012-01-16 10:40:10 +0000849 old = *p;
850 *p = newf;
Pavel Emelyanovc8fecf22007-12-05 01:50:24 -0800851
Francesco Ruggeri013d97e2012-01-16 10:40:10 +0000852 if (p == &net->ipv6.devconf_dflt->forwarding) {
Nicolas Dichtelf3a1bfb2012-10-25 22:28:50 +0000853 if ((!newf) ^ (!old))
David Ahern85b3daa2017-03-28 14:28:04 -0700854 inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
855 NETCONFA_FORWARDING,
Nicolas Dichtelf3a1bfb2012-10-25 22:28:50 +0000856 NETCONFA_IFINDEX_DEFAULT,
857 net->ipv6.devconf_dflt);
Francesco Ruggeri013d97e2012-01-16 10:40:10 +0000858 rtnl_unlock();
859 return 0;
Eric W. Biederman88af1822010-02-19 13:22:59 +0000860 }
Stephen Hemmingerb325fdd2009-02-26 06:55:31 +0000861
Pavel Emelyanove1869322008-01-10 17:43:50 -0800862 if (p == &net->ipv6.devconf_all->forwarding) {
Nicolas Dichteld26c6382016-08-30 10:09:21 +0200863 int old_dflt = net->ipv6.devconf_dflt->forwarding;
864
Pavel Emelyanove1869322008-01-10 17:43:50 -0800865 net->ipv6.devconf_dflt->forwarding = newf;
Nicolas Dichteld26c6382016-08-30 10:09:21 +0200866 if ((!newf) ^ (!old_dflt))
David Ahern85b3daa2017-03-28 14:28:04 -0700867 inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
868 NETCONFA_FORWARDING,
Nicolas Dichteld26c6382016-08-30 10:09:21 +0200869 NETCONFA_IFINDEX_DEFAULT,
870 net->ipv6.devconf_dflt);
871
Pavel Emelyanove1869322008-01-10 17:43:50 -0800872 addrconf_forward_change(net, newf);
Nicolas Dichtelf3a1bfb2012-10-25 22:28:50 +0000873 if ((!newf) ^ (!old))
David Ahern85b3daa2017-03-28 14:28:04 -0700874 inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
875 NETCONFA_FORWARDING,
Nicolas Dichtelf3a1bfb2012-10-25 22:28:50 +0000876 NETCONFA_IFINDEX_ALL,
877 net->ipv6.devconf_all);
Francesco Ruggeri013d97e2012-01-16 10:40:10 +0000878 } else if ((!newf) ^ (!old))
Pavel Emelyanovc8fecf22007-12-05 01:50:24 -0800879 dev_forward_change((struct inet6_dev *)table->extra1);
Ben Hutchings0187bdf2008-06-19 16:15:47 -0700880 rtnl_unlock();
Pavel Emelyanovc8fecf22007-12-05 01:50:24 -0800881
Francesco Ruggeri013d97e2012-01-16 10:40:10 +0000882 if (newf)
Daniel Lezcano7b4da532008-03-04 13:47:14 -0800883 rt6_purge_dflt_routers(net);
Stephen Hemmingerb325fdd2009-02-26 06:55:31 +0000884 return 1;
Pavel Emelyanovc8fecf22007-12-05 01:50:24 -0800885}
Andy Gospodarek35103d12015-08-13 10:39:01 -0400886
887static void addrconf_linkdown_change(struct net *net, __s32 newf)
888{
889 struct net_device *dev;
890 struct inet6_dev *idev;
891
892 for_each_netdev(net, dev) {
893 idev = __in6_dev_get(dev);
894 if (idev) {
895 int changed = (!idev->cnf.ignore_routes_with_linkdown) ^ (!newf);
896
897 idev->cnf.ignore_routes_with_linkdown = newf;
898 if (changed)
899 inet6_netconf_notify_devconf(dev_net(dev),
David Ahern85b3daa2017-03-28 14:28:04 -0700900 RTM_NEWNETCONF,
Andy Gospodarek35103d12015-08-13 10:39:01 -0400901 NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN,
902 dev->ifindex,
903 &idev->cnf);
904 }
905 }
906}
907
908static int addrconf_fixup_linkdown(struct ctl_table *table, int *p, int newf)
909{
910 struct net *net;
911 int old;
912
913 if (!rtnl_trylock())
914 return restart_syscall();
915
916 net = (struct net *)table->extra2;
917 old = *p;
918 *p = newf;
919
920 if (p == &net->ipv6.devconf_dflt->ignore_routes_with_linkdown) {
921 if ((!newf) ^ (!old))
922 inet6_netconf_notify_devconf(net,
David Ahern85b3daa2017-03-28 14:28:04 -0700923 RTM_NEWNETCONF,
Andy Gospodarek35103d12015-08-13 10:39:01 -0400924 NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN,
925 NETCONFA_IFINDEX_DEFAULT,
926 net->ipv6.devconf_dflt);
927 rtnl_unlock();
928 return 0;
929 }
930
931 if (p == &net->ipv6.devconf_all->ignore_routes_with_linkdown) {
932 net->ipv6.devconf_dflt->ignore_routes_with_linkdown = newf;
933 addrconf_linkdown_change(net, newf);
934 if ((!newf) ^ (!old))
935 inet6_netconf_notify_devconf(net,
David Ahern85b3daa2017-03-28 14:28:04 -0700936 RTM_NEWNETCONF,
Andy Gospodarek35103d12015-08-13 10:39:01 -0400937 NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN,
938 NETCONFA_IFINDEX_ALL,
939 net->ipv6.devconf_all);
940 }
941 rtnl_unlock();
942
943 return 1;
944}
945
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946#endif
947
stephen hemminger5c578aed2010-03-17 20:31:11 +0000948/* Nobody refers to this ifaddr, destroy it */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp)
950{
stephen hemmingerc2e21292010-03-17 20:31:10 +0000951 WARN_ON(!hlist_unhashed(&ifp->addr_lst));
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700952
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953#ifdef NET_REFCNT_DEBUG
Joe Perches91df42b2012-05-15 14:11:54 +0000954 pr_debug("%s\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955#endif
956
957 in6_dev_put(ifp->idev);
958
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +0100959 if (cancel_delayed_work(&ifp->dad_work))
960 pr_notice("delayed DAD work was pending while freeing ifa=%p\n",
961 ifp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962
Herbert Xue9d3e082010-05-18 15:36:06 -0700963 if (ifp->state != INET6_IFADDR_STATE_DEAD) {
Joe Perchesf3213832012-05-15 14:11:53 +0000964 pr_warn("Freeing alive inet6 address %p\n", ifp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 return;
966 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967
Lai Jiangshane5785982011-03-15 18:00:14 +0800968 kfree_rcu(ifp, rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969}
970
Brian Haleye55ffac2006-07-10 15:25:51 -0700971static void
972ipv6_link_dev_addr(struct inet6_dev *idev, struct inet6_ifaddr *ifp)
973{
stephen hemminger502a2ff2010-03-17 20:31:13 +0000974 struct list_head *p;
YOSHIFUJI Hideaki8a6ce0c2006-07-11 13:05:30 -0700975 int ifp_scope = ipv6_addr_src_scope(&ifp->addr);
Brian Haleye55ffac2006-07-10 15:25:51 -0700976
977 /*
978 * Each device address list is sorted in order of scope -
979 * global before linklocal.
980 */
stephen hemminger502a2ff2010-03-17 20:31:13 +0000981 list_for_each(p, &idev->addr_list) {
982 struct inet6_ifaddr *ifa
983 = list_entry(p, struct inet6_ifaddr, if_list);
YOSHIFUJI Hideaki8a6ce0c2006-07-11 13:05:30 -0700984 if (ifp_scope >= ipv6_addr_src_scope(&ifa->addr))
Brian Haleye55ffac2006-07-10 15:25:51 -0700985 break;
986 }
987
Eric Dumazet8ef802a2017-10-07 19:30:23 -0700988 list_add_tail_rcu(&ifp->if_list, p);
Brian Haleye55ffac2006-07-10 15:25:51 -0700989}
990
Eric Dumazet3f27fb22017-10-23 16:17:47 -0700991static u32 inet6_addr_hash(const struct net *net, const struct in6_addr *addr)
YOSHIFUJI Hideaki3eb84f42008-04-10 15:42:08 +0900992{
Eric Dumazet3f27fb22017-10-23 16:17:47 -0700993 u32 val = ipv6_addr_hash(addr) ^ net_hash_mix(net);
994
995 return hash_32(val, IN6_ADDR_HSIZE_SHIFT);
YOSHIFUJI Hideaki3eb84f42008-04-10 15:42:08 +0900996}
997
Eric Dumazet56fc7092017-10-23 16:17:45 -0700998static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr,
Eric Dumazet752a9292017-10-23 16:17:46 -0700999 struct net_device *dev, unsigned int hash)
Eric Dumazet56fc7092017-10-23 16:17:45 -07001000{
Eric Dumazet56fc7092017-10-23 16:17:45 -07001001 struct inet6_ifaddr *ifp;
1002
1003 hlist_for_each_entry(ifp, &inet6_addr_lst[hash], addr_lst) {
1004 if (!net_eq(dev_net(ifp->idev->dev), net))
1005 continue;
1006 if (ipv6_addr_equal(&ifp->addr, addr)) {
1007 if (!dev || ifp->idev->dev == dev)
1008 return true;
1009 }
1010 }
1011 return false;
1012}
1013
David Ahernf3d98322017-10-18 09:56:52 -07001014static int ipv6_add_addr_hash(struct net_device *dev, struct inet6_ifaddr *ifa)
1015{
Eric Dumazet3f27fb22017-10-23 16:17:47 -07001016 unsigned int hash = inet6_addr_hash(dev_net(dev), &ifa->addr);
David Ahernf3d98322017-10-18 09:56:52 -07001017 int err = 0;
1018
1019 spin_lock(&addrconf_hash_lock);
1020
1021 /* Ignore adding duplicate addresses on an interface */
Eric Dumazet752a9292017-10-23 16:17:46 -07001022 if (ipv6_chk_same_addr(dev_net(dev), &ifa->addr, dev, hash)) {
Joe Perchese32ac252018-03-26 08:35:01 -07001023 netdev_dbg(dev, "ipv6_add_addr: already assigned\n");
David Ahernf3d98322017-10-18 09:56:52 -07001024 err = -EEXIST;
Eric Dumazet752a9292017-10-23 16:17:46 -07001025 } else {
1026 hlist_add_head_rcu(&ifa->addr_lst, &inet6_addr_lst[hash]);
David Ahernf3d98322017-10-18 09:56:52 -07001027 }
1028
David Ahernf3d98322017-10-18 09:56:52 -07001029 spin_unlock(&addrconf_hash_lock);
1030
1031 return err;
1032}
1033
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034/* On success it returns ifp with increased reference count */
1035
1036static struct inet6_ifaddr *
David Aherne6464b82018-05-27 08:09:53 -07001037ipv6_add_addr(struct inet6_dev *idev, struct ifa6_config *cfg,
David Ahernde95e042017-10-18 09:56:54 -07001038 bool can_block, struct netlink_ext_ack *extack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039{
David Ahernf3d98322017-10-18 09:56:52 -07001040 gfp_t gfp_flags = can_block ? GFP_KERNEL : GFP_ATOMIC;
David Aherne6464b82018-05-27 08:09:53 -07001041 int addr_type = ipv6_addr_type(cfg->pfx);
David Forsterdf789fe2017-02-23 16:27:18 +00001042 struct net *net = dev_net(idev->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 struct inet6_ifaddr *ifa = NULL;
David Ahern360a9882018-04-18 15:39:00 -07001044 struct fib6_info *f6i = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 int err = 0;
YOSHIFUJI Hideakid68b8272008-06-25 16:26:47 +09001046
1047 if (addr_type == IPV6_ADDR_ANY ||
Hangbin Liuf17f7642019-08-20 10:19:47 +08001048 (addr_type & IPV6_ADDR_MULTICAST &&
1049 !(cfg->ifa_flags & IFA_F_MCAUTOJOIN)) ||
YOSHIFUJI Hideakid68b8272008-06-25 16:26:47 +09001050 (!(idev->dev->flags & IFF_LOOPBACK) &&
Robert Shearman3ede0bb2018-09-19 13:56:53 +01001051 !netif_is_l3_master(idev->dev) &&
YOSHIFUJI Hideakid68b8272008-06-25 16:26:47 +09001052 addr_type & IPV6_ADDR_LOOPBACK))
1053 return ERR_PTR(-EADDRNOTAVAIL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 if (idev->dead) {
1056 err = -ENODEV; /*XXX*/
David Ahernf3d98322017-10-18 09:56:52 -07001057 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 }
1059
Brian Haley56d417b2009-06-01 03:07:33 -07001060 if (idev->cnf.disable_ipv6) {
Brian Haley9bdd8d42009-03-18 18:22:48 -07001061 err = -EACCES;
David Ahernf3d98322017-10-18 09:56:52 -07001062 goto out;
Brian Haley9bdd8d42009-03-18 18:22:48 -07001063 }
1064
David Ahernff7883e2017-10-18 09:56:53 -07001065 /* validator notifier needs to be blocking;
1066 * do not call in atomic context
1067 */
1068 if (can_block) {
1069 struct in6_validator_info i6vi = {
David Aherne6464b82018-05-27 08:09:53 -07001070 .i6vi_addr = *cfg->pfx,
David Ahernff7883e2017-10-18 09:56:53 -07001071 .i6vi_dev = idev,
David Ahernde95e042017-10-18 09:56:54 -07001072 .extack = extack,
David Ahernff7883e2017-10-18 09:56:53 -07001073 };
1074
1075 err = inet6addr_validator_notifier_call_chain(NETDEV_UP, &i6vi);
1076 err = notifier_to_errno(err);
1077 if (err < 0)
1078 goto out;
1079 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080
David Ahernf3d98322017-10-18 09:56:52 -07001081 ifa = kzalloc(sizeof(*ifa), gfp_flags);
Ian Morris63159f22015-03-29 14:00:04 +01001082 if (!ifa) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 err = -ENOBUFS;
1084 goto out;
1085 }
1086
David Aherne6464b82018-05-27 08:09:53 -07001087 f6i = addrconf_f6i_alloc(net, idev, cfg->pfx, false, gfp_flags);
David Ahern360a9882018-04-18 15:39:00 -07001088 if (IS_ERR(f6i)) {
1089 err = PTR_ERR(f6i);
1090 f6i = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 goto out;
1092 }
1093
David Forsterdf789fe2017-02-23 16:27:18 +00001094 if (net->ipv6.devconf_all->disable_policy ||
1095 idev->cnf.disable_policy)
David Ahern360a9882018-04-18 15:39:00 -07001096 f6i->dst_nopolicy = true;
David Forsterdf789fe2017-02-23 16:27:18 +00001097
Jiri Pirkobba24892013-12-07 19:26:57 +01001098 neigh_parms_data_state_setall(idev->nd_parms);
1099
David Aherne6464b82018-05-27 08:09:53 -07001100 ifa->addr = *cfg->pfx;
1101 if (cfg->peer_pfx)
1102 ifa->peer_addr = *cfg->peer_pfx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103
1104 spin_lock_init(&ifa->lock);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01001105 INIT_DELAYED_WORK(&ifa->dad_work, addrconf_dad_work);
stephen hemmingerc2e21292010-03-17 20:31:10 +00001106 INIT_HLIST_NODE(&ifa->addr_lst);
David Aherne6464b82018-05-27 08:09:53 -07001107 ifa->scope = cfg->scope;
1108 ifa->prefix_len = cfg->plen;
David Ahern8308f3f2018-05-27 08:09:58 -07001109 ifa->rt_priority = cfg->rt_priority;
David Aherne6464b82018-05-27 08:09:53 -07001110 ifa->flags = cfg->ifa_flags;
Mahesh Bandewar66eb9f82017-05-12 17:03:39 -07001111 /* No need to add the TENTATIVE flag for addresses with NODAD */
David Aherne6464b82018-05-27 08:09:53 -07001112 if (!(cfg->ifa_flags & IFA_F_NODAD))
Mahesh Bandewar66eb9f82017-05-12 17:03:39 -07001113 ifa->flags |= IFA_F_TENTATIVE;
David Aherne6464b82018-05-27 08:09:53 -07001114 ifa->valid_lft = cfg->valid_lft;
1115 ifa->prefered_lft = cfg->preferred_lft;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 ifa->cstamp = ifa->tstamp = jiffies;
Daniel Borkmann617fe292013-04-09 03:47:16 +00001117 ifa->tokenized = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118
David Ahern360a9882018-04-18 15:39:00 -07001119 ifa->rt = f6i;
Keir Fraser57f5f542006-08-29 02:43:49 -07001120
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 ifa->idev = idev;
David Ahernf3d98322017-10-18 09:56:52 -07001122 in6_dev_hold(idev);
1123
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 /* For caller */
Reshetova, Elena271201c2017-07-04 09:34:56 +03001125 refcount_set(&ifa->refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126
David Ahernf3d98322017-10-18 09:56:52 -07001127 rcu_read_lock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128
David Ahernf3d98322017-10-18 09:56:52 -07001129 err = ipv6_add_addr_hash(idev->dev, ifa);
1130 if (err < 0) {
1131 rcu_read_unlock_bh();
1132 goto out;
1133 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134
1135 write_lock(&idev->lock);
David Ahernf3d98322017-10-18 09:56:52 -07001136
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 /* Add to inet6_dev unicast addr list. */
Brian Haleye55ffac2006-07-10 15:25:51 -07001138 ipv6_link_dev_addr(idev, ifa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 if (ifa->flags&IFA_F_TEMPORARY) {
stephen hemminger372e6c82010-03-17 20:31:09 +00001141 list_add(&ifa->tmp_list, &idev->tempaddr_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142 in6_ifa_hold(ifa);
1143 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 in6_ifa_hold(ifa);
1146 write_unlock(&idev->lock);
David Ahernf3d98322017-10-18 09:56:52 -07001147
YOSHIFUJI Hideaki8814c4b2006-09-22 14:44:24 -07001148 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149
David Ahernf3d98322017-10-18 09:56:52 -07001150 inet6addr_notifier_call_chain(NETDEV_UP, ifa);
1151out:
1152 if (unlikely(err < 0)) {
David Ahern360a9882018-04-18 15:39:00 -07001153 fib6_info_release(f6i);
David Ahern93531c62018-04-17 17:33:25 -07001154
David Ahernf3d98322017-10-18 09:56:52 -07001155 if (ifa) {
1156 if (ifa->idev)
1157 in6_dev_put(ifa->idev);
1158 kfree(ifa);
1159 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 ifa = ERR_PTR(err);
1161 }
1162
1163 return ifa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164}
1165
Thomas Haller5b84efe2014-01-15 15:36:59 +01001166enum cleanup_prefix_rt_t {
1167 CLEANUP_PREFIX_RT_NOP, /* no cleanup action for prefix route */
1168 CLEANUP_PREFIX_RT_DEL, /* delete the prefix route */
1169 CLEANUP_PREFIX_RT_EXPIRE, /* update the lifetime of the prefix route */
1170};
1171
1172/*
1173 * Check, whether the prefix for ifp would still need a prefix route
1174 * after deleting ifp. The function returns one of the CLEANUP_PREFIX_RT_*
1175 * constants.
1176 *
1177 * 1) we don't purge prefix if address was not permanent.
1178 * prefix is managed by its own lifetime.
1179 * 2) we also don't purge, if the address was IFA_F_NOPREFIXROUTE.
1180 * 3) if there are no addresses, delete prefix.
1181 * 4) if there are still other permanent address(es),
1182 * corresponding prefix is still permanent.
1183 * 5) if there are still other addresses with IFA_F_NOPREFIXROUTE,
1184 * don't purge the prefix, assume user space is managing it.
1185 * 6) otherwise, update prefix lifetime to the
1186 * longest valid lifetime among the corresponding
1187 * addresses on the device.
1188 * Note: subsequent RA will update lifetime.
1189 **/
1190static enum cleanup_prefix_rt_t
1191check_cleanup_prefix_route(struct inet6_ifaddr *ifp, unsigned long *expires)
1192{
1193 struct inet6_ifaddr *ifa;
1194 struct inet6_dev *idev = ifp->idev;
1195 unsigned long lifetime;
1196 enum cleanup_prefix_rt_t action = CLEANUP_PREFIX_RT_DEL;
1197
1198 *expires = jiffies;
1199
1200 list_for_each_entry(ifa, &idev->addr_list, if_list) {
1201 if (ifa == ifp)
1202 continue;
Zhiqiang Liue75913c2019-02-11 10:57:46 +08001203 if (ifa->prefix_len != ifp->prefix_len ||
1204 !ipv6_prefix_equal(&ifa->addr, &ifp->addr,
Thomas Haller5b84efe2014-01-15 15:36:59 +01001205 ifp->prefix_len))
1206 continue;
1207 if (ifa->flags & (IFA_F_PERMANENT | IFA_F_NOPREFIXROUTE))
1208 return CLEANUP_PREFIX_RT_NOP;
1209
1210 action = CLEANUP_PREFIX_RT_EXPIRE;
1211
1212 spin_lock(&ifa->lock);
1213
1214 lifetime = addrconf_timeout_fixup(ifa->valid_lft, HZ);
1215 /*
1216 * Note: Because this address is
1217 * not permanent, lifetime <
1218 * LONG_MAX / HZ here.
1219 */
1220 if (time_before(*expires, ifa->tstamp + lifetime * HZ))
1221 *expires = ifa->tstamp + lifetime * HZ;
1222 spin_unlock(&ifa->lock);
1223 }
1224
1225 return action;
1226}
1227
1228static void
Hangbin Liud0098e42020-03-03 14:37:35 +08001229cleanup_prefix_route(struct inet6_ifaddr *ifp, unsigned long expires,
1230 bool del_rt, bool del_peer)
Thomas Haller5b84efe2014-01-15 15:36:59 +01001231{
David Ahern93c2fb22018-04-18 15:38:59 -07001232 struct fib6_info *f6i;
Thomas Haller5b84efe2014-01-15 15:36:59 +01001233
Hangbin Liud0098e42020-03-03 14:37:35 +08001234 f6i = addrconf_get_prefix_route(del_peer ? &ifp->peer_addr : &ifp->addr,
1235 ifp->prefix_len,
David Ahern2b2450c2019-03-27 20:53:52 -07001236 ifp->idev->dev, 0, RTF_DEFAULT, true);
David Ahern93c2fb22018-04-18 15:38:59 -07001237 if (f6i) {
Thomas Haller5b84efe2014-01-15 15:36:59 +01001238 if (del_rt)
Roopa Prabhu11dd74b2020-04-27 13:56:45 -07001239 ip6_del_rt(dev_net(ifp->idev->dev), f6i, false);
Thomas Haller5b84efe2014-01-15 15:36:59 +01001240 else {
David Ahern93c2fb22018-04-18 15:38:59 -07001241 if (!(f6i->fib6_flags & RTF_EXPIRES))
1242 fib6_set_expires(f6i, expires);
1243 fib6_info_release(f6i);
Thomas Haller5b84efe2014-01-15 15:36:59 +01001244 }
1245 }
1246}
1247
1248
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249/* This function wants to get referenced ifp and releases it before return */
1250
1251static void ipv6_del_addr(struct inet6_ifaddr *ifp)
1252{
Herbert Xu4c5ff6a2010-05-18 15:54:18 -07001253 int state;
Thomas Haller5b84efe2014-01-15 15:36:59 +01001254 enum cleanup_prefix_rt_t action = CLEANUP_PREFIX_RT_NOP;
1255 unsigned long expires;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01001257 ASSERT_RTNL();
1258
Hannes Frederic Sowa8e8e6762015-03-23 23:36:03 +01001259 spin_lock_bh(&ifp->lock);
Herbert Xu4c5ff6a2010-05-18 15:54:18 -07001260 state = ifp->state;
Herbert Xue9d3e082010-05-18 15:36:06 -07001261 ifp->state = INET6_IFADDR_STATE_DEAD;
Hannes Frederic Sowa8e8e6762015-03-23 23:36:03 +01001262 spin_unlock_bh(&ifp->lock);
Herbert Xu4c5ff6a2010-05-18 15:54:18 -07001263
1264 if (state == INET6_IFADDR_STATE_DEAD)
1265 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266
stephen hemminger5c578aed2010-03-17 20:31:11 +00001267 spin_lock_bh(&addrconf_hash_lock);
1268 hlist_del_init_rcu(&ifp->addr_lst);
stephen hemminger5c578aed2010-03-17 20:31:11 +00001269 spin_unlock_bh(&addrconf_hash_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270
Thomas Haller5b84efe2014-01-15 15:36:59 +01001271 write_lock_bh(&ifp->idev->lock);
David S. Miller5d9efa72013-10-28 20:07:50 -04001272
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 if (ifp->flags&IFA_F_TEMPORARY) {
stephen hemminger372e6c82010-03-17 20:31:09 +00001274 list_del(&ifp->tmp_list);
1275 if (ifp->ifpub) {
1276 in6_ifa_put(ifp->ifpub);
1277 ifp->ifpub = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 }
stephen hemminger372e6c82010-03-17 20:31:09 +00001279 __in6_ifa_put(ifp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281
Thomas Haller5b84efe2014-01-15 15:36:59 +01001282 if (ifp->flags & IFA_F_PERMANENT && !(ifp->flags & IFA_F_NOPREFIXROUTE))
1283 action = check_cleanup_prefix_route(ifp, &expires);
stephen hemminger502a2ff2010-03-17 20:31:13 +00001284
Eric Dumazet8ef802a2017-10-07 19:30:23 -07001285 list_del_rcu(&ifp->if_list);
Thomas Haller5b84efe2014-01-15 15:36:59 +01001286 __in6_ifa_put(ifp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287
Thomas Haller5b84efe2014-01-15 15:36:59 +01001288 write_unlock_bh(&ifp->idev->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01001290 addrconf_del_dad_work(ifp);
Andrey Vaginb2238562008-07-08 15:13:31 -07001291
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 ipv6_ifa_notify(RTM_DELADDR, ifp);
1293
Cong Wangf88c91d2013-04-14 23:18:43 +08001294 inet6addr_notifier_call_chain(NETDEV_DOWN, ifp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295
Thomas Haller5b84efe2014-01-15 15:36:59 +01001296 if (action != CLEANUP_PREFIX_RT_NOP) {
1297 cleanup_prefix_route(ifp, expires,
Hangbin Liud0098e42020-03-03 14:37:35 +08001298 action == CLEANUP_PREFIX_RT_DEL, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 }
1300
Daniel Walterc3968a82011-04-13 21:10:57 +00001301 /* clean up prefsrc entries */
1302 rt6_remove_prefsrc(ifp);
Herbert Xu4c5ff6a2010-05-18 15:54:18 -07001303out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304 in6_ifa_put(ifp);
1305}
1306
Fernando Gont969c5462020-05-01 00:51:47 -03001307static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, bool block)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308{
1309 struct inet6_dev *idev = ifp->idev;
David Aherne6464b82018-05-27 08:09:53 -07001310 unsigned long tmp_tstamp, age;
Benoit Boissinoteac55bf2008-04-02 00:01:35 -07001311 unsigned long regen_advance;
Lorenzo Colitti76f793e2011-07-26 13:50:49 +00001312 unsigned long now = jiffies;
Jiri Bohac7aa8e632016-10-20 12:29:26 +02001313 s32 cnf_temp_preferred_lft;
Fernando Gont969c5462020-05-01 00:51:47 -03001314 struct inet6_ifaddr *ift;
1315 struct ifa6_config cfg;
1316 long max_desync_factor;
1317 struct in6_addr addr;
1318 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319
Jiri Pirko53bd6742013-12-06 09:45:22 +01001320 write_lock_bh(&idev->lock);
Fernando Gont969c5462020-05-01 00:51:47 -03001321
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322retry:
1323 in6_dev_hold(idev);
1324 if (idev->cnf.use_tempaddr <= 0) {
Jiri Pirko53bd6742013-12-06 09:45:22 +01001325 write_unlock_bh(&idev->lock);
Joe Perchesf3213832012-05-15 14:11:53 +00001326 pr_info("%s: use_tempaddr is disabled\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 in6_dev_put(idev);
1328 ret = -1;
1329 goto out;
1330 }
1331 spin_lock_bh(&ifp->lock);
1332 if (ifp->regen_count++ >= idev->cnf.regen_max_retry) {
1333 idev->cnf.use_tempaddr = -1; /*XXX*/
1334 spin_unlock_bh(&ifp->lock);
Jiri Pirko53bd6742013-12-06 09:45:22 +01001335 write_unlock_bh(&idev->lock);
Joe Perchesf3213832012-05-15 14:11:53 +00001336 pr_warn("%s: regeneration time exceeded - disabled temporary address support\n",
1337 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 in6_dev_put(idev);
1339 ret = -1;
1340 goto out;
1341 }
1342 in6_ifa_hold(ifp);
1343 memcpy(addr.s6_addr, ifp->addr.s6_addr, 8);
Fernando Gont969c5462020-05-01 00:51:47 -03001344 ipv6_gen_rnd_iid(&addr);
1345
Lorenzo Colitti76f793e2011-07-26 13:50:49 +00001346 age = (now - ifp->tstamp) / HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347
Benoit Boissinoteac55bf2008-04-02 00:01:35 -07001348 regen_advance = idev->cnf.regen_max_retry *
Ian Morris67ba4152014-08-24 21:53:10 +01001349 idev->cnf.dad_transmits *
Hangbin Liu19e16d22020-04-01 14:46:20 +08001350 max(NEIGH_VAR(idev->nd_parms, RETRANS_TIME), HZ/100) / HZ;
Jiri Bohac76506a92016-10-13 18:52:15 +02001351
1352 /* recalculate max_desync_factor each time and update
1353 * idev->desync_factor if it's larger
1354 */
Jiri Bohac7aa8e632016-10-20 12:29:26 +02001355 cnf_temp_preferred_lft = READ_ONCE(idev->cnf.temp_prefered_lft);
Jiri Bohac76506a92016-10-13 18:52:15 +02001356 max_desync_factor = min_t(__u32,
1357 idev->cnf.max_desync_factor,
Jiri Bohac7aa8e632016-10-20 12:29:26 +02001358 cnf_temp_preferred_lft - regen_advance);
Jiri Bohac76506a92016-10-13 18:52:15 +02001359
1360 if (unlikely(idev->desync_factor > max_desync_factor)) {
1361 if (max_desync_factor > 0) {
1362 get_random_bytes(&idev->desync_factor,
1363 sizeof(idev->desync_factor));
1364 idev->desync_factor %= max_desync_factor;
1365 } else {
1366 idev->desync_factor = 0;
1367 }
1368 }
1369
David Ahern3f2d67b2018-06-11 07:12:12 -07001370 memset(&cfg, 0, sizeof(cfg));
David Aherne6464b82018-05-27 08:09:53 -07001371 cfg.valid_lft = min_t(__u32, ifp->valid_lft,
Jiri Bohac76506a92016-10-13 18:52:15 +02001372 idev->cnf.temp_valid_lft + age);
David Aherne6464b82018-05-27 08:09:53 -07001373 cfg.preferred_lft = cnf_temp_preferred_lft + age - idev->desync_factor;
1374 cfg.preferred_lft = min_t(__u32, ifp->prefered_lft, cfg.preferred_lft);
1375
1376 cfg.plen = ifp->prefix_len;
Jiri Bohac76506a92016-10-13 18:52:15 +02001377 tmp_tstamp = ifp->tstamp;
1378 spin_unlock_bh(&ifp->lock);
1379
Jiri Pirko53bd6742013-12-06 09:45:22 +01001380 write_unlock_bh(&idev->lock);
Neil Horman95c385b2007-04-25 17:08:10 -07001381
Benoit Boissinoteac55bf2008-04-02 00:01:35 -07001382 /* A temporary address is created only if this calculated Preferred
1383 * Lifetime is greater than REGEN_ADVANCE time units. In particular,
1384 * an implementation must not create a temporary address with a zero
1385 * Preferred Lifetime.
Heiner Kallweitecab6702014-03-12 22:13:19 +01001386 * Use age calculation as in addrconf_verify to avoid unnecessary
1387 * temporary addresses being generated.
Benoit Boissinoteac55bf2008-04-02 00:01:35 -07001388 */
Heiner Kallweitecab6702014-03-12 22:13:19 +01001389 age = (now - tmp_tstamp + ADDRCONF_TIMER_FUZZ_MINUS) / HZ;
David Aherne6464b82018-05-27 08:09:53 -07001390 if (cfg.preferred_lft <= regen_advance + age) {
Benoit Boissinoteac55bf2008-04-02 00:01:35 -07001391 in6_ifa_put(ifp);
1392 in6_dev_put(idev);
1393 ret = -1;
1394 goto out;
1395 }
1396
David Aherne6464b82018-05-27 08:09:53 -07001397 cfg.ifa_flags = IFA_F_TEMPORARY;
Neil Horman95c385b2007-04-25 17:08:10 -07001398 /* set in addrconf_prefix_rcv() */
1399 if (ifp->flags & IFA_F_OPTIMISTIC)
David Aherne6464b82018-05-27 08:09:53 -07001400 cfg.ifa_flags |= IFA_F_OPTIMISTIC;
Neil Horman95c385b2007-04-25 17:08:10 -07001401
David Aherne6464b82018-05-27 08:09:53 -07001402 cfg.pfx = &addr;
1403 cfg.scope = ipv6_addr_scope(cfg.pfx);
1404
1405 ift = ipv6_add_addr(idev, &cfg, block, NULL);
Hannes Frederic Sowa4b08a8f2013-08-16 13:02:27 +02001406 if (IS_ERR(ift)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407 in6_ifa_put(ifp);
1408 in6_dev_put(idev);
Joe Perchesf3213832012-05-15 14:11:53 +00001409 pr_info("%s: retry temporary address regeneration\n", __func__);
Jiri Pirko53bd6742013-12-06 09:45:22 +01001410 write_lock_bh(&idev->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 goto retry;
1412 }
1413
1414 spin_lock_bh(&ift->lock);
1415 ift->ifpub = ifp;
Lorenzo Colitti76f793e2011-07-26 13:50:49 +00001416 ift->cstamp = now;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 ift->tstamp = tmp_tstamp;
1418 spin_unlock_bh(&ift->lock);
1419
David S. Millercf22f9a2012-04-14 21:37:40 -04001420 addrconf_dad_start(ift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 in6_ifa_put(ift);
1422 in6_dev_put(idev);
1423out:
1424 return ret;
1425}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426
1427/*
YOSHIFUJI Hideaki072047e2005-11-08 09:38:30 -08001428 * Choose an appropriate source address (RFC3484)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429 */
YOSHIFUJI Hideakia9b05722008-03-02 10:48:21 +09001430enum {
1431 IPV6_SADDR_RULE_INIT = 0,
1432 IPV6_SADDR_RULE_LOCAL,
1433 IPV6_SADDR_RULE_SCOPE,
1434 IPV6_SADDR_RULE_PREFERRED,
1435#ifdef CONFIG_IPV6_MIP6
1436 IPV6_SADDR_RULE_HOA,
1437#endif
1438 IPV6_SADDR_RULE_OIF,
1439 IPV6_SADDR_RULE_LABEL,
YOSHIFUJI Hideakia9b05722008-03-02 10:48:21 +09001440 IPV6_SADDR_RULE_PRIVACY,
YOSHIFUJI Hideakia9b05722008-03-02 10:48:21 +09001441 IPV6_SADDR_RULE_ORCHID,
1442 IPV6_SADDR_RULE_PREFIX,
Erik Kline7fd25612014-10-28 18:11:14 +09001443#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
1444 IPV6_SADDR_RULE_NOT_OPTIMISTIC,
1445#endif
YOSHIFUJI Hideakia9b05722008-03-02 10:48:21 +09001446 IPV6_SADDR_RULE_MAX
YOSHIFUJI Hideaki072047e2005-11-08 09:38:30 -08001447};
1448
YOSHIFUJI Hideakia9b05722008-03-02 10:48:21 +09001449struct ipv6_saddr_score {
1450 int rule;
1451 int addr_type;
1452 struct inet6_ifaddr *ifa;
1453 DECLARE_BITMAP(scorebits, IPV6_SADDR_RULE_MAX);
1454 int scopedist;
1455 int matchlen;
1456};
1457
1458struct ipv6_saddr_dst {
YOSHIFUJI Hideaki9acd9f32008-04-10 15:42:10 +09001459 const struct in6_addr *addr;
YOSHIFUJI Hideakia9b05722008-03-02 10:48:21 +09001460 int ifindex;
1461 int scope;
1462 int label;
YOSHIFUJI Hideaki7cbca672008-03-25 09:37:42 +09001463 unsigned int prefs;
YOSHIFUJI Hideakia9b05722008-03-02 10:48:21 +09001464};
YOSHIFUJI Hideaki072047e2005-11-08 09:38:30 -08001465
Dave Jonesb6f99a22007-03-22 12:27:49 -07001466static inline int ipv6_saddr_preferred(int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467{
Ulrich Weber45bb0062010-02-25 23:28:58 +00001468 if (type & (IPV6_ADDR_MAPPED|IPV6_ADDR_COMPATv4|IPV6_ADDR_LOOPBACK))
YOSHIFUJI Hideaki072047e2005-11-08 09:38:30 -08001469 return 1;
1470 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471}
1472
Matteo Croce35e015e2017-09-12 17:46:37 +02001473static bool ipv6_use_optimistic_addr(struct net *net,
1474 struct inet6_dev *idev)
Erik Kline7fd25612014-10-28 18:11:14 +09001475{
1476#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
Matteo Croce35e015e2017-09-12 17:46:37 +02001477 if (!idev)
1478 return false;
1479 if (!net->ipv6.devconf_all->optimistic_dad && !idev->cnf.optimistic_dad)
1480 return false;
1481 if (!net->ipv6.devconf_all->use_optimistic && !idev->cnf.use_optimistic)
1482 return false;
1483
1484 return true;
Erik Kline7fd25612014-10-28 18:11:14 +09001485#else
1486 return false;
1487#endif
1488}
1489
Sabrina Dubrocaf1c02cf2018-02-28 16:40:08 +01001490static bool ipv6_allow_optimistic_dad(struct net *net,
1491 struct inet6_dev *idev)
1492{
1493#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
1494 if (!idev)
1495 return false;
1496 if (!net->ipv6.devconf_all->optimistic_dad && !idev->cnf.optimistic_dad)
1497 return false;
1498
1499 return true;
1500#else
1501 return false;
1502#endif
1503}
1504
Benjamin Thery3de23252008-05-28 14:51:24 +02001505static int ipv6_get_saddr_eval(struct net *net,
1506 struct ipv6_saddr_score *score,
YOSHIFUJI Hideakia9b05722008-03-02 10:48:21 +09001507 struct ipv6_saddr_dst *dst,
1508 int i)
1509{
1510 int ret;
1511
1512 if (i <= score->rule) {
1513 switch (i) {
1514 case IPV6_SADDR_RULE_SCOPE:
1515 ret = score->scopedist;
1516 break;
1517 case IPV6_SADDR_RULE_PREFIX:
1518 ret = score->matchlen;
1519 break;
1520 default:
1521 ret = !!test_bit(i, score->scorebits);
1522 }
1523 goto out;
1524 }
1525
1526 switch (i) {
1527 case IPV6_SADDR_RULE_INIT:
1528 /* Rule 0: remember if hiscore is not ready yet */
1529 ret = !!score->ifa;
1530 break;
1531 case IPV6_SADDR_RULE_LOCAL:
1532 /* Rule 1: Prefer same address */
1533 ret = ipv6_addr_equal(&score->ifa->addr, dst->addr);
1534 break;
1535 case IPV6_SADDR_RULE_SCOPE:
1536 /* Rule 2: Prefer appropriate scope
1537 *
1538 * ret
1539 * ^
1540 * -1 | d 15
1541 * ---+--+-+---> scope
1542 * |
1543 * | d is scope of the destination.
1544 * B-d | \
1545 * | \ <- smaller scope is better if
stephen hemmingerdb9c7c32014-01-12 11:26:32 -08001546 * B-15 | \ if scope is enough for destination.
YOSHIFUJI Hideakia9b05722008-03-02 10:48:21 +09001547 * | ret = B - scope (-1 <= scope >= d <= 15).
1548 * d-C-1 | /
1549 * |/ <- greater is better
1550 * -C / if scope is not enough for destination.
1551 * /| ret = scope - C (-1 <= d < scope <= 15).
1552 *
1553 * d - C - 1 < B -15 (for all -1 <= d <= 15).
1554 * C > d + 14 - B >= 15 + 14 - B = 29 - B.
1555 * Assume B = 0 and we get C > 29.
1556 */
1557 ret = __ipv6_addr_src_scope(score->addr_type);
1558 if (ret >= dst->scope)
1559 ret = -ret;
1560 else
1561 ret -= 128; /* 30 is enough */
1562 score->scopedist = ret;
1563 break;
1564 case IPV6_SADDR_RULE_PREFERRED:
Erik Kline7fd25612014-10-28 18:11:14 +09001565 {
YOSHIFUJI Hideakia9b05722008-03-02 10:48:21 +09001566 /* Rule 3: Avoid deprecated and optimistic addresses */
Erik Kline7fd25612014-10-28 18:11:14 +09001567 u8 avoid = IFA_F_DEPRECATED;
1568
Matteo Croce35e015e2017-09-12 17:46:37 +02001569 if (!ipv6_use_optimistic_addr(net, score->ifa->idev))
Erik Kline7fd25612014-10-28 18:11:14 +09001570 avoid |= IFA_F_OPTIMISTIC;
YOSHIFUJI Hideakia9b05722008-03-02 10:48:21 +09001571 ret = ipv6_saddr_preferred(score->addr_type) ||
Erik Kline7fd25612014-10-28 18:11:14 +09001572 !(score->ifa->flags & avoid);
YOSHIFUJI Hideakia9b05722008-03-02 10:48:21 +09001573 break;
Erik Kline7fd25612014-10-28 18:11:14 +09001574 }
YOSHIFUJI Hideakia9b05722008-03-02 10:48:21 +09001575#ifdef CONFIG_IPV6_MIP6
1576 case IPV6_SADDR_RULE_HOA:
YOSHIFUJI Hideaki7cbca672008-03-25 09:37:42 +09001577 {
YOSHIFUJI Hideakia9b05722008-03-02 10:48:21 +09001578 /* Rule 4: Prefer home address */
YOSHIFUJI Hideaki7cbca672008-03-25 09:37:42 +09001579 int prefhome = !(dst->prefs & IPV6_PREFER_SRC_COA);
1580 ret = !(score->ifa->flags & IFA_F_HOMEADDRESS) ^ prefhome;
YOSHIFUJI Hideakia9b05722008-03-02 10:48:21 +09001581 break;
YOSHIFUJI Hideaki7cbca672008-03-25 09:37:42 +09001582 }
YOSHIFUJI Hideakia9b05722008-03-02 10:48:21 +09001583#endif
1584 case IPV6_SADDR_RULE_OIF:
1585 /* Rule 5: Prefer outgoing interface */
1586 ret = (!dst->ifindex ||
1587 dst->ifindex == score->ifa->idev->dev->ifindex);
1588 break;
1589 case IPV6_SADDR_RULE_LABEL:
1590 /* Rule 6: Prefer matching label */
Benjamin Thery3de23252008-05-28 14:51:24 +02001591 ret = ipv6_addr_label(net,
1592 &score->ifa->addr, score->addr_type,
YOSHIFUJI Hideakia9b05722008-03-02 10:48:21 +09001593 score->ifa->idev->dev->ifindex) == dst->label;
1594 break;
YOSHIFUJI Hideakia9b05722008-03-02 10:48:21 +09001595 case IPV6_SADDR_RULE_PRIVACY:
YOSHIFUJI Hideaki7cbca672008-03-25 09:37:42 +09001596 {
YOSHIFUJI Hideakia9b05722008-03-02 10:48:21 +09001597 /* Rule 7: Prefer public address
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001598 * Note: prefer temporary address if use_tempaddr >= 2
YOSHIFUJI Hideakia9b05722008-03-02 10:48:21 +09001599 */
YOSHIFUJI Hideaki7cbca672008-03-25 09:37:42 +09001600 int preftmp = dst->prefs & (IPV6_PREFER_SRC_PUBLIC|IPV6_PREFER_SRC_TMP) ?
1601 !!(dst->prefs & IPV6_PREFER_SRC_TMP) :
1602 score->ifa->idev->cnf.use_tempaddr >= 2;
1603 ret = (!(score->ifa->flags & IFA_F_TEMPORARY)) ^ preftmp;
YOSHIFUJI Hideakia9b05722008-03-02 10:48:21 +09001604 break;
YOSHIFUJI Hideaki7cbca672008-03-25 09:37:42 +09001605 }
YOSHIFUJI Hideakia9b05722008-03-02 10:48:21 +09001606 case IPV6_SADDR_RULE_ORCHID:
1607 /* Rule 8-: Prefer ORCHID vs ORCHID or
1608 * non-ORCHID vs non-ORCHID
1609 */
1610 ret = !(ipv6_addr_orchid(&score->ifa->addr) ^
1611 ipv6_addr_orchid(dst->addr));
1612 break;
1613 case IPV6_SADDR_RULE_PREFIX:
1614 /* Rule 8: Use longest matching prefix */
YOSHIFUJI Hideaki / 吉藤英明91b4b042012-09-10 18:41:07 +00001615 ret = ipv6_addr_diff(&score->ifa->addr, dst->addr);
1616 if (ret > score->ifa->prefix_len)
1617 ret = score->ifa->prefix_len;
1618 score->matchlen = ret;
YOSHIFUJI Hideakia9b05722008-03-02 10:48:21 +09001619 break;
Erik Kline7fd25612014-10-28 18:11:14 +09001620#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
1621 case IPV6_SADDR_RULE_NOT_OPTIMISTIC:
1622 /* Optimistic addresses still have lower precedence than other
1623 * preferred addresses.
1624 */
1625 ret = !(score->ifa->flags & IFA_F_OPTIMISTIC);
1626 break;
1627#endif
YOSHIFUJI Hideakia9b05722008-03-02 10:48:21 +09001628 default:
1629 ret = 0;
1630 }
1631
1632 if (ret)
1633 __set_bit(i, score->scorebits);
1634 score->rule = i;
1635out:
1636 return ret;
1637}
1638
YOSHIFUJI Hideaki/吉藤英明c0b8da12015-07-13 23:28:10 +09001639static int __ipv6_dev_get_saddr(struct net *net,
1640 struct ipv6_saddr_dst *dst,
YOSHIFUJI Hideaki/吉藤英明c0b8da12015-07-13 23:28:10 +09001641 struct inet6_dev *idev,
1642 struct ipv6_saddr_score *scores,
1643 int hiscore_idx)
YOSHIFUJI Hideaki/吉藤英明9131f3d2015-07-10 16:58:31 +09001644{
YOSHIFUJI Hideaki/吉藤英明c0b8da12015-07-13 23:28:10 +09001645 struct ipv6_saddr_score *score = &scores[1 - hiscore_idx], *hiscore = &scores[hiscore_idx];
YOSHIFUJI Hideaki/吉藤英明9131f3d2015-07-10 16:58:31 +09001646
Eric Dumazetf59c0312017-10-07 19:30:27 -07001647 list_for_each_entry_rcu(score->ifa, &idev->addr_list, if_list) {
YOSHIFUJI Hideaki/吉藤英明9131f3d2015-07-10 16:58:31 +09001648 int i;
1649
1650 /*
1651 * - Tentative Address (RFC2462 section 5.4)
1652 * - A tentative address is not considered
1653 * "assigned to an interface" in the traditional
1654 * sense, unless it is also flagged as optimistic.
1655 * - Candidate Source Address (section 4)
1656 * - In any case, anycast addresses, multicast
1657 * addresses, and the unspecified address MUST
1658 * NOT be included in a candidate set.
1659 */
1660 if ((score->ifa->flags & IFA_F_TENTATIVE) &&
1661 (!(score->ifa->flags & IFA_F_OPTIMISTIC)))
1662 continue;
1663
1664 score->addr_type = __ipv6_addr_type(&score->ifa->addr);
1665
1666 if (unlikely(score->addr_type == IPV6_ADDR_ANY ||
1667 score->addr_type & IPV6_ADDR_MULTICAST)) {
1668 net_dbg_ratelimited("ADDRCONF: unspecified / multicast address assigned as unicast address on %s",
1669 idev->dev->name);
1670 continue;
1671 }
1672
1673 score->rule = -1;
1674 bitmap_zero(score->scorebits, IPV6_SADDR_RULE_MAX);
1675
1676 for (i = 0; i < IPV6_SADDR_RULE_MAX; i++) {
1677 int minihiscore, miniscore;
1678
1679 minihiscore = ipv6_get_saddr_eval(net, hiscore, dst, i);
1680 miniscore = ipv6_get_saddr_eval(net, score, dst, i);
1681
1682 if (minihiscore > miniscore) {
1683 if (i == IPV6_SADDR_RULE_SCOPE &&
1684 score->scopedist > 0) {
1685 /*
1686 * special case:
1687 * each remaining entry
1688 * has too small (not enough)
1689 * scope, because ifa entries
1690 * are sorted by their scope
1691 * values.
1692 */
1693 goto out;
1694 }
1695 break;
1696 } else if (minihiscore < miniscore) {
YOSHIFUJI Hideaki/吉藤英明9131f3d2015-07-10 16:58:31 +09001697 swap(hiscore, score);
YOSHIFUJI Hideaki/吉藤英明c0b8da12015-07-13 23:28:10 +09001698 hiscore_idx = 1 - hiscore_idx;
YOSHIFUJI Hideaki/吉藤英明9131f3d2015-07-10 16:58:31 +09001699
1700 /* restore our iterator */
1701 score->ifa = hiscore->ifa;
1702
1703 break;
1704 }
1705 }
1706 }
1707out:
YOSHIFUJI Hideaki/吉藤英明c0b8da12015-07-13 23:28:10 +09001708 return hiscore_idx;
YOSHIFUJI Hideaki/吉藤英明9131f3d2015-07-10 16:58:31 +09001709}
1710
David Ahernafbac6012016-06-16 16:24:26 -07001711static int ipv6_get_saddr_master(struct net *net,
1712 const struct net_device *dst_dev,
1713 const struct net_device *master,
1714 struct ipv6_saddr_dst *dst,
1715 struct ipv6_saddr_score *scores,
1716 int hiscore_idx)
1717{
1718 struct inet6_dev *idev;
1719
1720 idev = __in6_dev_get(dst_dev);
1721 if (idev)
1722 hiscore_idx = __ipv6_dev_get_saddr(net, dst, idev,
1723 scores, hiscore_idx);
1724
1725 idev = __in6_dev_get(master);
1726 if (idev)
1727 hiscore_idx = __ipv6_dev_get_saddr(net, dst, idev,
1728 scores, hiscore_idx);
1729
1730 return hiscore_idx;
1731}
1732
Patrick McHardyb3f644f2012-08-26 19:14:14 +02001733int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev,
YOSHIFUJI Hideaki9acd9f32008-04-10 15:42:10 +09001734 const struct in6_addr *daddr, unsigned int prefs,
YOSHIFUJI Hideaki7cbca672008-03-25 09:37:42 +09001735 struct in6_addr *saddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736{
YOSHIFUJI Hideaki/吉藤英明c0b8da12015-07-13 23:28:10 +09001737 struct ipv6_saddr_score scores[2], *hiscore;
YOSHIFUJI Hideakia9b05722008-03-02 10:48:21 +09001738 struct ipv6_saddr_dst dst;
YOSHIFUJI Hideaki/吉藤英明9131f3d2015-07-10 16:58:31 +09001739 struct inet6_dev *idev;
YOSHIFUJI Hideaki072047e2005-11-08 09:38:30 -08001740 struct net_device *dev;
YOSHIFUJI Hideakia9b05722008-03-02 10:48:21 +09001741 int dst_type;
YOSHIFUJI Hideaki/吉藤英明9131f3d2015-07-10 16:58:31 +09001742 bool use_oif_addr = false;
YOSHIFUJI Hideaki/吉藤英明c0b8da12015-07-13 23:28:10 +09001743 int hiscore_idx = 0;
Eric Dumazetcc429c82017-10-07 19:30:28 -07001744 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745
YOSHIFUJI Hideakia9b05722008-03-02 10:48:21 +09001746 dst_type = __ipv6_addr_type(daddr);
1747 dst.addr = daddr;
1748 dst.ifindex = dst_dev ? dst_dev->ifindex : 0;
1749 dst.scope = __ipv6_addr_src_scope(dst_type);
Benjamin Thery3de23252008-05-28 14:51:24 +02001750 dst.label = ipv6_addr_label(net, daddr, dst_type, dst.ifindex);
YOSHIFUJI Hideaki7cbca672008-03-25 09:37:42 +09001751 dst.prefs = prefs;
YOSHIFUJI Hideakia9b05722008-03-02 10:48:21 +09001752
YOSHIFUJI Hideaki/吉藤英明c0b8da12015-07-13 23:28:10 +09001753 scores[hiscore_idx].rule = -1;
1754 scores[hiscore_idx].ifa = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755
YOSHIFUJI Hideaki8814c4b2006-09-22 14:44:24 -07001756 rcu_read_lock();
YOSHIFUJI Hideaki072047e2005-11-08 09:38:30 -08001757
YOSHIFUJI Hideaki/吉藤英明9131f3d2015-07-10 16:58:31 +09001758 /* Candidate Source Address (section 4)
1759 * - multicast and link-local destination address,
1760 * the set of candidate source address MUST only
1761 * include addresses assigned to interfaces
1762 * belonging to the same link as the outgoing
1763 * interface.
1764 * (- For site-local destination addresses, the
1765 * set of candidate source addresses MUST only
1766 * include addresses assigned to interfaces
1767 * belonging to the same site as the outgoing
1768 * interface.)
Erik Kline3985e8a2015-07-22 16:38:25 +09001769 * - "It is RECOMMENDED that the candidate source addresses
1770 * be the set of unicast addresses assigned to the
1771 * interface that will be used to send to the destination
1772 * (the 'outgoing' interface)." (RFC 6724)
YOSHIFUJI Hideaki/吉藤英明9131f3d2015-07-10 16:58:31 +09001773 */
1774 if (dst_dev) {
Erik Kline3985e8a2015-07-22 16:38:25 +09001775 idev = __in6_dev_get(dst_dev);
YOSHIFUJI Hideaki/吉藤英明9131f3d2015-07-10 16:58:31 +09001776 if ((dst_type & IPV6_ADDR_MULTICAST) ||
Erik Kline3985e8a2015-07-22 16:38:25 +09001777 dst.scope <= IPV6_ADDR_SCOPE_LINKLOCAL ||
1778 (idev && idev->cnf.use_oif_addrs_only)) {
YOSHIFUJI Hideaki/吉藤英明9131f3d2015-07-10 16:58:31 +09001779 use_oif_addr = true;
YOSHIFUJI Hideaki072047e2005-11-08 09:38:30 -08001780 }
YOSHIFUJI Hideaki/吉藤英明9131f3d2015-07-10 16:58:31 +09001781 }
1782
1783 if (use_oif_addr) {
YOSHIFUJI Hideaki/吉藤英明c0b8da12015-07-13 23:28:10 +09001784 if (idev)
YOSHIFUJI Hideakic15df302015-07-16 16:51:30 +09001785 hiscore_idx = __ipv6_dev_get_saddr(net, &dst, idev, scores, hiscore_idx);
YOSHIFUJI Hideaki/吉藤英明9131f3d2015-07-10 16:58:31 +09001786 } else {
David Ahernafbac6012016-06-16 16:24:26 -07001787 const struct net_device *master;
1788 int master_idx = 0;
1789
1790 /* if dst_dev exists and is enslaved to an L3 device, then
1791 * prefer addresses from dst_dev and then the master over
1792 * any other enslaved devices in the L3 domain.
1793 */
1794 master = l3mdev_master_dev_rcu(dst_dev);
1795 if (master) {
1796 master_idx = master->ifindex;
1797
1798 hiscore_idx = ipv6_get_saddr_master(net, dst_dev,
1799 master, &dst,
1800 scores, hiscore_idx);
1801
1802 if (scores[hiscore_idx].ifa)
1803 goto out;
1804 }
1805
YOSHIFUJI Hideaki/吉藤英明9131f3d2015-07-10 16:58:31 +09001806 for_each_netdev_rcu(net, dev) {
David Ahernafbac6012016-06-16 16:24:26 -07001807 /* only consider addresses on devices in the
1808 * same L3 domain
1809 */
1810 if (l3mdev_master_ifindex_rcu(dev) != master_idx)
1811 continue;
YOSHIFUJI Hideaki/吉藤英明9131f3d2015-07-10 16:58:31 +09001812 idev = __in6_dev_get(dev);
1813 if (!idev)
1814 continue;
YOSHIFUJI Hideakic15df302015-07-16 16:51:30 +09001815 hiscore_idx = __ipv6_dev_get_saddr(net, &dst, idev, scores, hiscore_idx);
YOSHIFUJI Hideaki/吉藤英明9131f3d2015-07-10 16:58:31 +09001816 }
YOSHIFUJI Hideaki072047e2005-11-08 09:38:30 -08001817 }
David Ahernafbac6012016-06-16 16:24:26 -07001818
1819out:
YOSHIFUJI Hideaki/吉藤英明c0b8da12015-07-13 23:28:10 +09001820 hiscore = &scores[hiscore_idx];
YOSHIFUJI Hideakia9b05722008-03-02 10:48:21 +09001821 if (!hiscore->ifa)
Eric Dumazetcc429c82017-10-07 19:30:28 -07001822 ret = -EADDRNOTAVAIL;
1823 else
1824 *saddr = hiscore->ifa->addr;
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09001825
Eric Dumazetcc429c82017-10-07 19:30:28 -07001826 rcu_read_unlock();
1827 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828}
YOSHIFUJI Hideaki5e5f3f02008-03-03 21:44:34 +09001829EXPORT_SYMBOL(ipv6_dev_get_saddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830
Amerigo Wang89657792013-06-29 21:30:49 +08001831int __ipv6_get_lladdr(struct inet6_dev *idev, struct in6_addr *addr,
Jiri Pirko479840f2013-12-06 09:45:21 +01001832 u32 banned_flags)
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02001833{
1834 struct inet6_ifaddr *ifp;
1835 int err = -EADDRNOTAVAIL;
1836
Hannes Frederic Sowa602582c2014-01-19 21:58:19 +01001837 list_for_each_entry_reverse(ifp, &idev->addr_list, if_list) {
1838 if (ifp->scope > IFA_LINK)
1839 break;
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02001840 if (ifp->scope == IFA_LINK &&
1841 !(ifp->flags & banned_flags)) {
1842 *addr = ifp->addr;
1843 err = 0;
1844 break;
1845 }
1846 }
1847 return err;
1848}
1849
Neil Horman95c385b2007-04-25 17:08:10 -07001850int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr,
Jiri Pirko479840f2013-12-06 09:45:21 +01001851 u32 banned_flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852{
1853 struct inet6_dev *idev;
1854 int err = -EADDRNOTAVAIL;
1855
YOSHIFUJI Hideaki8814c4b2006-09-22 14:44:24 -07001856 rcu_read_lock();
Stephen Hemmingere21e8462010-03-20 16:09:01 -07001857 idev = __in6_dev_get(dev);
1858 if (idev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859 read_lock_bh(&idev->lock);
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02001860 err = __ipv6_get_lladdr(idev, addr, banned_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 read_unlock_bh(&idev->lock);
1862 }
YOSHIFUJI Hideaki8814c4b2006-09-22 14:44:24 -07001863 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864 return err;
1865}
1866
Eric Dumazetd9bf82c2017-10-07 19:30:24 -07001867static int ipv6_count_addresses(const struct inet6_dev *idev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868{
Eric Dumazetd9bf82c2017-10-07 19:30:24 -07001869 const struct inet6_ifaddr *ifp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870 int cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871
Eric Dumazetd9bf82c2017-10-07 19:30:24 -07001872 rcu_read_lock();
1873 list_for_each_entry_rcu(ifp, &idev->addr_list, if_list)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874 cnt++;
Eric Dumazetd9bf82c2017-10-07 19:30:24 -07001875 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876 return cnt;
1877}
1878
Eric Dumazetb71d1d42011-04-22 04:53:02 +00001879int ipv6_chk_addr(struct net *net, const struct in6_addr *addr,
Florian Westphal2a7851b2013-05-17 03:56:10 +00001880 const struct net_device *dev, int strict)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881{
David Ahern232378e2018-03-13 08:29:37 -07001882 return ipv6_chk_addr_and_flags(net, addr, dev, !dev,
1883 strict, IFA_F_TENTATIVE);
Erik Klinec58da4c2015-02-04 20:01:23 +09001884}
1885EXPORT_SYMBOL(ipv6_chk_addr);
1886
David Ahern1893ff22018-03-13 08:29:38 -07001887/* device argument is used to find the L3 domain of interest. If
1888 * skip_dev_check is set, then the ifp device is not checked against
1889 * the passed in dev argument. So the 2 cases for addresses checks are:
1890 * 1. does the address exist in the L3 domain that dev is part of
1891 * (skip_dev_check = true), or
1892 *
1893 * 2. does the address exist on the specific device
1894 * (skip_dev_check = false)
1895 */
Erik Klinec58da4c2015-02-04 20:01:23 +09001896int ipv6_chk_addr_and_flags(struct net *net, const struct in6_addr *addr,
David Ahern232378e2018-03-13 08:29:37 -07001897 const struct net_device *dev, bool skip_dev_check,
1898 int strict, u32 banned_flags)
Erik Klinec58da4c2015-02-04 20:01:23 +09001899{
Eric Dumazet3f27fb22017-10-23 16:17:47 -07001900 unsigned int hash = inet6_addr_hash(net, addr);
David Ahern1893ff22018-03-13 08:29:38 -07001901 const struct net_device *l3mdev;
Stephen Hemmingereedf0422010-05-17 22:27:12 -07001902 struct inet6_ifaddr *ifp;
Erik Klinec58da4c2015-02-04 20:01:23 +09001903 u32 ifp_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904
Eric Dumazet480318a2017-10-23 16:17:48 -07001905 rcu_read_lock();
David Ahern232378e2018-03-13 08:29:37 -07001906
David Ahern1893ff22018-03-13 08:29:38 -07001907 l3mdev = l3mdev_master_dev_rcu(dev);
David Ahern232378e2018-03-13 08:29:37 -07001908 if (skip_dev_check)
1909 dev = NULL;
1910
Sasha Levinb67bfe02013-02-27 17:06:00 -08001911 hlist_for_each_entry_rcu(ifp, &inet6_addr_lst[hash], addr_lst) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09001912 if (!net_eq(dev_net(ifp->idev->dev), net))
Daniel Lezcanobfeade02008-01-10 22:43:18 -08001913 continue;
David Ahern1893ff22018-03-13 08:29:38 -07001914
1915 if (l3mdev_master_dev_rcu(ifp->idev->dev) != l3mdev)
1916 continue;
1917
Erik Klinec58da4c2015-02-04 20:01:23 +09001918 /* Decouple optimistic from tentative for evaluation here.
1919 * Ban optimistic addresses explicitly, when required.
1920 */
1921 ifp_flags = (ifp->flags&IFA_F_OPTIMISTIC)
1922 ? (ifp->flags&~IFA_F_TENTATIVE)
1923 : ifp->flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924 if (ipv6_addr_equal(&ifp->addr, addr) &&
Erik Klinec58da4c2015-02-04 20:01:23 +09001925 !(ifp_flags&banned_flags) &&
Ian Morris63159f22015-03-29 14:00:04 +01001926 (!dev || ifp->idev->dev == dev ||
Stephen Hemmingereedf0422010-05-17 22:27:12 -07001927 !(ifp->scope&(IFA_LINK|IFA_HOST) || strict))) {
Eric Dumazet480318a2017-10-23 16:17:48 -07001928 rcu_read_unlock();
Stephen Hemmingereedf0422010-05-17 22:27:12 -07001929 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930 }
1931 }
stephen hemminger5c578aed2010-03-17 20:31:11 +00001932
Eric Dumazet480318a2017-10-23 16:17:48 -07001933 rcu_read_unlock();
Stephen Hemmingereedf0422010-05-17 22:27:12 -07001934 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935}
Erik Klinec58da4c2015-02-04 20:01:23 +09001936EXPORT_SYMBOL(ipv6_chk_addr_and_flags);
YOSHIFUJI Hideaki71590392007-02-22 22:05:40 +09001937
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938
Catalin\(ux\) M. BOIE7df37ff2013-09-23 23:04:19 +03001939/* Compares an address/prefix_len with addresses on device @dev.
1940 * If one is found it returns true.
1941 */
1942bool ipv6_chk_custom_prefix(const struct in6_addr *addr,
1943 const unsigned int prefix_len, struct net_device *dev)
1944{
Eric Dumazet47e26942017-10-07 19:30:25 -07001945 const struct inet6_ifaddr *ifa;
1946 const struct inet6_dev *idev;
Catalin\(ux\) M. BOIE7df37ff2013-09-23 23:04:19 +03001947 bool ret = false;
1948
1949 rcu_read_lock();
1950 idev = __in6_dev_get(dev);
1951 if (idev) {
Eric Dumazet47e26942017-10-07 19:30:25 -07001952 list_for_each_entry_rcu(ifa, &idev->addr_list, if_list) {
Catalin\(ux\) M. BOIE7df37ff2013-09-23 23:04:19 +03001953 ret = ipv6_prefix_equal(addr, &ifa->addr, prefix_len);
1954 if (ret)
1955 break;
1956 }
Catalin\(ux\) M. BOIE7df37ff2013-09-23 23:04:19 +03001957 }
1958 rcu_read_unlock();
1959
1960 return ret;
1961}
1962EXPORT_SYMBOL(ipv6_chk_custom_prefix);
1963
Eric Dumazetb71d1d42011-04-22 04:53:02 +00001964int ipv6_chk_prefix(const struct in6_addr *addr, struct net_device *dev)
YOSHIFUJI Hideaki52eeeb82008-03-15 22:54:23 -04001965{
Eric Dumazet24ba3332017-10-07 19:30:26 -07001966 const struct inet6_ifaddr *ifa;
1967 const struct inet6_dev *idev;
YOSHIFUJI Hideaki52eeeb82008-03-15 22:54:23 -04001968 int onlink;
1969
1970 onlink = 0;
1971 rcu_read_lock();
1972 idev = __in6_dev_get(dev);
1973 if (idev) {
Eric Dumazet24ba3332017-10-07 19:30:26 -07001974 list_for_each_entry_rcu(ifa, &idev->addr_list, if_list) {
YOSHIFUJI Hideaki52eeeb82008-03-15 22:54:23 -04001975 onlink = ipv6_prefix_equal(addr, &ifa->addr,
1976 ifa->prefix_len);
1977 if (onlink)
1978 break;
1979 }
YOSHIFUJI Hideaki52eeeb82008-03-15 22:54:23 -04001980 }
1981 rcu_read_unlock();
1982 return onlink;
1983}
YOSHIFUJI Hideaki52eeeb82008-03-15 22:54:23 -04001984EXPORT_SYMBOL(ipv6_chk_prefix);
1985
YOSHIFUJI Hideaki9acd9f32008-04-10 15:42:10 +09001986struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *addr,
Daniel Lezcano1cab3da2008-01-10 22:44:09 -08001987 struct net_device *dev, int strict)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988{
Eric Dumazet3f27fb22017-10-23 16:17:47 -07001989 unsigned int hash = inet6_addr_hash(net, addr);
David S. Millerb79d1d52010-03-25 21:39:21 -07001990 struct inet6_ifaddr *ifp, *result = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991
Eric Dumazet24f226d2017-10-23 16:17:49 -07001992 rcu_read_lock();
1993 hlist_for_each_entry_rcu(ifp, &inet6_addr_lst[hash], addr_lst) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09001994 if (!net_eq(dev_net(ifp->idev->dev), net))
Daniel Lezcano1cab3da2008-01-10 22:44:09 -08001995 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996 if (ipv6_addr_equal(&ifp->addr, addr)) {
Ian Morris63159f22015-03-29 14:00:04 +01001997 if (!dev || ifp->idev->dev == dev ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998 !(ifp->scope&(IFA_LINK|IFA_HOST) || strict)) {
David S. Millerb79d1d52010-03-25 21:39:21 -07001999 result = ifp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000 in6_ifa_hold(ifp);
2001 break;
2002 }
2003 }
2004 }
Eric Dumazet24f226d2017-10-23 16:17:49 -07002005 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006
David S. Millerb79d1d52010-03-25 21:39:21 -07002007 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008}
2009
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010/* Gets referenced address, destroys ifaddr */
2011
Brian Haleycc411d02009-09-09 14:41:32 +00002012static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013{
Lubomir Rintel3d171f32016-01-08 13:47:23 +01002014 if (dad_failed)
2015 ifp->flags |= IFA_F_DADFAILED;
2016
Sabrina Dubrocaec8add22017-06-29 16:56:54 +02002017 if (ifp->flags&IFA_F_TEMPORARY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018 struct inet6_ifaddr *ifpub;
2019 spin_lock_bh(&ifp->lock);
2020 ifpub = ifp->ifpub;
2021 if (ifpub) {
2022 in6_ifa_hold(ifpub);
2023 spin_unlock_bh(&ifp->lock);
Fernando Gont969c5462020-05-01 00:51:47 -03002024 ipv6_create_tempaddr(ifpub, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025 in6_ifa_put(ifpub);
2026 } else {
2027 spin_unlock_bh(&ifp->lock);
2028 }
2029 ipv6_del_addr(ifp);
Sabrina Dubrocaec8add22017-06-29 16:56:54 +02002030 } else if (ifp->flags&IFA_F_PERMANENT || !dad_failed) {
2031 spin_lock_bh(&ifp->lock);
2032 addrconf_del_dad_work(ifp);
2033 ifp->flags |= IFA_F_TENTATIVE;
Sabrina Dubrocaf1c02cf2018-02-28 16:40:08 +01002034 if (dad_failed)
2035 ifp->flags &= ~IFA_F_OPTIMISTIC;
Sabrina Dubrocaec8add22017-06-29 16:56:54 +02002036 spin_unlock_bh(&ifp->lock);
2037 if (dad_failed)
2038 ipv6_ifa_notify(0, ifp);
2039 in6_ifa_put(ifp);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01002040 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041 ipv6_del_addr(ifp);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01002042 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043}
2044
Herbert Xuf2344a12010-05-18 15:55:27 -07002045static int addrconf_dad_end(struct inet6_ifaddr *ifp)
2046{
2047 int err = -ENOENT;
2048
Hannes Frederic Sowa8e8e6762015-03-23 23:36:03 +01002049 spin_lock_bh(&ifp->lock);
Herbert Xuf2344a12010-05-18 15:55:27 -07002050 if (ifp->state == INET6_IFADDR_STATE_DAD) {
2051 ifp->state = INET6_IFADDR_STATE_POSTDAD;
2052 err = 0;
2053 }
Hannes Frederic Sowa8e8e6762015-03-23 23:36:03 +01002054 spin_unlock_bh(&ifp->lock);
Herbert Xuf2344a12010-05-18 15:55:27 -07002055
2056 return err;
2057}
2058
Vishwanath Paida13c592017-10-30 19:38:52 -04002059void addrconf_dad_failure(struct sk_buff *skb, struct inet6_ifaddr *ifp)
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09002060{
YOSHIFUJI Hideaki1b34be72008-06-28 14:18:38 +09002061 struct inet6_dev *idev = ifp->idev;
Hannes Frederic Sowa1855b7c2015-03-23 23:36:05 +01002062 struct net *net = dev_net(ifp->idev->dev);
Brian Haley9bdd8d42009-03-18 18:22:48 -07002063
Ursula Braun853dc2e2010-10-24 23:06:43 +00002064 if (addrconf_dad_end(ifp)) {
2065 in6_ifa_put(ifp);
Herbert Xuf2344a12010-05-18 15:55:27 -07002066 return;
Ursula Braun853dc2e2010-10-24 23:06:43 +00002067 }
Herbert Xuf2344a12010-05-18 15:55:27 -07002068
Vishwanath Paida13c592017-10-30 19:38:52 -04002069 net_info_ratelimited("%s: IPv6 duplicate address %pI6c used by %pM detected!\n",
2070 ifp->idev->dev->name, &ifp->addr, eth_hdr(skb)->h_source);
Brian Haley9bdd8d42009-03-18 18:22:48 -07002071
Hannes Frederic Sowa5f40ef72015-03-23 23:36:04 +01002072 spin_lock_bh(&ifp->lock);
YOSHIFUJI Hideaki1b34be72008-06-28 14:18:38 +09002073
Hannes Frederic Sowa5f40ef72015-03-23 23:36:04 +01002074 if (ifp->flags & IFA_F_STABLE_PRIVACY) {
Hannes Frederic Sowa5f40ef72015-03-23 23:36:04 +01002075 struct in6_addr new_addr;
2076 struct inet6_ifaddr *ifp2;
Hannes Frederic Sowa5f40ef72015-03-23 23:36:04 +01002077 int retries = ifp->stable_privacy_retry + 1;
David Aherne6464b82018-05-27 08:09:53 -07002078 struct ifa6_config cfg = {
2079 .pfx = &new_addr,
2080 .plen = ifp->prefix_len,
2081 .ifa_flags = ifp->flags,
2082 .valid_lft = ifp->valid_lft,
2083 .preferred_lft = ifp->prefered_lft,
2084 .scope = ifp->scope,
2085 };
Hannes Frederic Sowa5f40ef72015-03-23 23:36:04 +01002086
Hannes Frederic Sowa1855b7c2015-03-23 23:36:05 +01002087 if (retries > net->ipv6.sysctl.idgen_retries) {
Hannes Frederic Sowa5f40ef72015-03-23 23:36:04 +01002088 net_info_ratelimited("%s: privacy stable address generation failed because of DAD conflicts!\n",
2089 ifp->idev->dev->name);
2090 goto errdad;
2091 }
2092
2093 new_addr = ifp->addr;
2094 if (ipv6_generate_stable_address(&new_addr, retries,
2095 idev))
2096 goto errdad;
2097
Hannes Frederic Sowa5f40ef72015-03-23 23:36:04 +01002098 spin_unlock_bh(&ifp->lock);
2099
2100 if (idev->cnf.max_addresses &&
2101 ipv6_count_addresses(idev) >=
2102 idev->cnf.max_addresses)
2103 goto lock_errdad;
2104
2105 net_info_ratelimited("%s: generating new stable privacy address because of DAD conflict\n",
2106 ifp->idev->dev->name);
2107
David Aherne6464b82018-05-27 08:09:53 -07002108 ifp2 = ipv6_add_addr(idev, &cfg, false, NULL);
Hannes Frederic Sowa5f40ef72015-03-23 23:36:04 +01002109 if (IS_ERR(ifp2))
2110 goto lock_errdad;
2111
2112 spin_lock_bh(&ifp2->lock);
2113 ifp2->stable_privacy_retry = retries;
2114 ifp2->state = INET6_IFADDR_STATE_PREDAD;
2115 spin_unlock_bh(&ifp2->lock);
2116
Hannes Frederic Sowa1855b7c2015-03-23 23:36:05 +01002117 addrconf_mod_dad_work(ifp2, net->ipv6.sysctl.idgen_delay);
Hannes Frederic Sowa5f40ef72015-03-23 23:36:04 +01002118 in6_ifa_put(ifp2);
2119lock_errdad:
2120 spin_lock_bh(&ifp->lock);
YOSHIFUJI Hideaki1b34be72008-06-28 14:18:38 +09002121 }
2122
Hannes Frederic Sowa5f40ef72015-03-23 23:36:04 +01002123errdad:
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01002124 /* transition from _POSTDAD to _ERRDAD */
2125 ifp->state = INET6_IFADDR_STATE_ERRDAD;
Hannes Frederic Sowa8e8e6762015-03-23 23:36:03 +01002126 spin_unlock_bh(&ifp->lock);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01002127
2128 addrconf_mod_dad_work(ifp, 0);
Wei Yongjun751eb6b2016-09-05 16:06:31 +08002129 in6_ifa_put(ifp);
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09002130}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131
Sabrina Dubrocaa9ed4a22014-09-02 10:29:29 +02002132/* Join to solicited addr multicast group.
2133 * caller must hold RTNL */
Eric Dumazetb71d1d42011-04-22 04:53:02 +00002134void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135{
2136 struct in6_addr maddr;
2137
2138 if (dev->flags&(IFF_LOOPBACK|IFF_NOARP))
2139 return;
2140
2141 addrconf_addr_solict_mult(addr, &maddr);
2142 ipv6_dev_mc_inc(dev, &maddr);
2143}
2144
Sabrina Dubrocaa9ed4a22014-09-02 10:29:29 +02002145/* caller must hold RTNL */
Eric Dumazetb71d1d42011-04-22 04:53:02 +00002146void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147{
2148 struct in6_addr maddr;
2149
2150 if (idev->dev->flags&(IFF_LOOPBACK|IFF_NOARP))
2151 return;
2152
2153 addrconf_addr_solict_mult(addr, &maddr);
2154 __ipv6_dev_mc_dec(idev, &maddr);
2155}
2156
Sabrina Dubrocaa9ed4a22014-09-02 10:29:29 +02002157/* caller must hold RTNL */
Arnaldo Carvalho de Melo20380732005-08-16 02:18:02 -03002158static void addrconf_join_anycast(struct inet6_ifaddr *ifp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159{
2160 struct in6_addr addr;
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01002161
Hannes Frederic Sowa88ad3142014-01-06 17:53:14 +01002162 if (ifp->prefix_len >= 127) /* RFC 6164 */
Bjørn Mork2bda8a02011-07-05 23:04:13 +00002163 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164 ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
2165 if (ipv6_addr_any(&addr))
2166 return;
WANG Cong013b4d92014-09-11 15:35:11 -07002167 __ipv6_dev_ac_inc(ifp->idev, &addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168}
2169
Sabrina Dubrocaa9ed4a22014-09-02 10:29:29 +02002170/* caller must hold RTNL */
Arnaldo Carvalho de Melo20380732005-08-16 02:18:02 -03002171static void addrconf_leave_anycast(struct inet6_ifaddr *ifp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172{
2173 struct in6_addr addr;
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01002174
Hannes Frederic Sowa88ad3142014-01-06 17:53:14 +01002175 if (ifp->prefix_len >= 127) /* RFC 6164 */
YOSHIFUJI Hideaki32019e62011-07-24 11:44:34 +00002176 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177 ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
2178 if (ipv6_addr_any(&addr))
2179 return;
2180 __ipv6_dev_ac_dec(ifp->idev, &addr);
2181}
2182
Alexander Aring8a7a4b42017-03-12 10:19:36 +02002183static int addrconf_ifid_6lowpan(u8 *eui, struct net_device *dev)
alex.bluesman.smirnov@gmail.com06a4c1c2012-05-10 03:25:52 +00002184{
Alexander Aring8a7a4b42017-03-12 10:19:36 +02002185 switch (dev->addr_len) {
2186 case ETH_ALEN:
Luiz Augusto von Dentz9dae2e02017-03-12 10:19:38 +02002187 memcpy(eui, dev->dev_addr, 3);
2188 eui[3] = 0xFF;
2189 eui[4] = 0xFE;
2190 memcpy(eui + 5, dev->dev_addr + 3, 3);
2191 break;
Alexander Aring8a7a4b42017-03-12 10:19:36 +02002192 case EUI64_ADDR_LEN:
2193 memcpy(eui, dev->dev_addr, EUI64_ADDR_LEN);
2194 eui[0] ^= 2;
2195 break;
2196 default:
alex.bluesman.smirnov@gmail.com06a4c1c2012-05-10 03:25:52 +00002197 return -1;
Alexander Aring8a7a4b42017-03-12 10:19:36 +02002198 }
2199
alex.bluesman.smirnov@gmail.com06a4c1c2012-05-10 03:25:52 +00002200 return 0;
2201}
2202
YOSHIFUJI Hideaki / 吉藤英明cb6bf352013-03-25 08:26:24 +00002203static int addrconf_ifid_ieee1394(u8 *eui, struct net_device *dev)
2204{
2205 union fwnet_hwaddr *ha;
2206
2207 if (dev->addr_len != FWNET_ALEN)
2208 return -1;
2209
2210 ha = (union fwnet_hwaddr *)dev->dev_addr;
2211
2212 memcpy(eui, &ha->uc.uniq_id, sizeof(ha->uc.uniq_id));
2213 eui[0] ^= 2;
2214 return 0;
2215}
2216
YOSHIFUJI Hideaki073a8e02006-03-20 16:54:49 -08002217static int addrconf_ifid_arcnet(u8 *eui, struct net_device *dev)
2218{
2219 /* XXX: inherit EUI-64 from other interface -- yoshfuji */
2220 if (dev->addr_len != ARCNET_ALEN)
2221 return -1;
2222 memset(eui, 0, 7);
Eldad Zack8e5e8f32012-04-01 07:49:08 +00002223 eui[7] = *(u8 *)dev->dev_addr;
YOSHIFUJI Hideaki073a8e02006-03-20 16:54:49 -08002224 return 0;
2225}
2226
2227static int addrconf_ifid_infiniband(u8 *eui, struct net_device *dev)
2228{
2229 if (dev->addr_len != INFINIBAND_ALEN)
2230 return -1;
2231 memcpy(eui, dev->dev_addr + 12, 8);
2232 eui[0] |= 2;
2233 return 0;
2234}
2235
stephen hemmingerc61393e2010-10-04 20:17:53 +00002236static int __ipv6_isatap_ifid(u8 *eui, __be32 addr)
YOSHIFUJI Hideakidfd982b2008-04-10 15:42:09 +09002237{
Sascha Hlusiak9af28512009-05-19 12:56:51 +00002238 if (addr == 0)
2239 return -1;
YOSHIFUJI Hideakidfd982b2008-04-10 15:42:09 +09002240 eui[0] = (ipv4_is_zeronet(addr) || ipv4_is_private_10(addr) ||
2241 ipv4_is_loopback(addr) || ipv4_is_linklocal_169(addr) ||
2242 ipv4_is_private_172(addr) || ipv4_is_test_192(addr) ||
2243 ipv4_is_anycast_6to4(addr) || ipv4_is_private_192(addr) ||
2244 ipv4_is_test_198(addr) || ipv4_is_multicast(addr) ||
2245 ipv4_is_lbcast(addr)) ? 0x00 : 0x02;
2246 eui[1] = 0;
2247 eui[2] = 0x5E;
2248 eui[3] = 0xFE;
2249 memcpy(eui + 4, &addr, 4);
2250 return 0;
2251}
YOSHIFUJI Hideakidfd982b2008-04-10 15:42:09 +09002252
2253static int addrconf_ifid_sit(u8 *eui, struct net_device *dev)
2254{
2255 if (dev->priv_flags & IFF_ISATAP)
2256 return __ipv6_isatap_ifid(eui, *(__be32 *)dev->dev_addr);
2257 return -1;
2258}
2259
stephen hemmingeraee80b52011-06-08 10:44:30 +00002260static int addrconf_ifid_gre(u8 *eui, struct net_device *dev)
2261{
2262 return __ipv6_isatap_ifid(eui, *(__be32 *)dev->dev_addr);
2263}
2264
Nicolas Dichtele8377352013-08-20 12:16:06 +02002265static int addrconf_ifid_ip6tnl(u8 *eui, struct net_device *dev)
2266{
2267 memcpy(eui, dev->perm_addr, 3);
2268 memcpy(eui + 5, dev->perm_addr + 3, 3);
2269 eui[3] = 0xFF;
2270 eui[4] = 0xFE;
2271 eui[0] ^= 2;
2272 return 0;
2273}
2274
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
2276{
2277 switch (dev->type) {
2278 case ARPHRD_ETHER:
2279 case ARPHRD_FDDI:
YOSHIFUJI Hideaki073a8e02006-03-20 16:54:49 -08002280 return addrconf_ifid_eui48(eui, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281 case ARPHRD_ARCNET:
YOSHIFUJI Hideaki073a8e02006-03-20 16:54:49 -08002282 return addrconf_ifid_arcnet(eui, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002283 case ARPHRD_INFINIBAND:
YOSHIFUJI Hideaki073a8e02006-03-20 16:54:49 -08002284 return addrconf_ifid_infiniband(eui, dev);
Fred L. Templinc7dc89c2007-11-29 22:11:40 +11002285 case ARPHRD_SIT:
YOSHIFUJI Hideakidfd982b2008-04-10 15:42:09 +09002286 return addrconf_ifid_sit(eui, dev);
stephen hemmingeraee80b52011-06-08 10:44:30 +00002287 case ARPHRD_IPGRE:
Felix Jia45ce0fd2017-01-26 16:59:18 +13002288 case ARPHRD_TUNNEL:
stephen hemmingeraee80b52011-06-08 10:44:30 +00002289 return addrconf_ifid_gre(eui, dev);
Jukka Rissanene74bccb82013-12-11 17:05:36 +02002290 case ARPHRD_6LOWPAN:
Alexander Aring8a7a4b42017-03-12 10:19:36 +02002291 return addrconf_ifid_6lowpan(eui, dev);
YOSHIFUJI Hideaki / 吉藤英明cb6bf352013-03-25 08:26:24 +00002292 case ARPHRD_IEEE1394:
2293 return addrconf_ifid_ieee1394(eui, dev);
Nicolas Dichtele8377352013-08-20 12:16:06 +02002294 case ARPHRD_TUNNEL6:
Felix Jia45ce0fd2017-01-26 16:59:18 +13002295 case ARPHRD_IP6GRE:
Subash Abhinov Kasiviswanathan9deb4412018-06-04 19:26:07 -06002296 case ARPHRD_RAWIP:
Nicolas Dichtele8377352013-08-20 12:16:06 +02002297 return addrconf_ifid_ip6tnl(eui, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298 }
2299 return -1;
2300}
2301
2302static int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev)
2303{
2304 int err = -1;
2305 struct inet6_ifaddr *ifp;
2306
2307 read_lock_bh(&idev->lock);
Hannes Frederic Sowa602582c2014-01-19 21:58:19 +01002308 list_for_each_entry_reverse(ifp, &idev->addr_list, if_list) {
2309 if (ifp->scope > IFA_LINK)
2310 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311 if (ifp->scope == IFA_LINK && !(ifp->flags&IFA_F_TENTATIVE)) {
2312 memcpy(eui, ifp->addr.s6_addr+8, 8);
2313 err = 0;
2314 break;
2315 }
2316 }
2317 read_unlock_bh(&idev->lock);
2318 return err;
2319}
2320
Fernando Gont969c5462020-05-01 00:51:47 -03002321/* Generation of a randomized Interface Identifier
2322 * draft-ietf-6man-rfc4941bis, Section 3.3.1
2323 */
2324
2325static void ipv6_gen_rnd_iid(struct in6_addr *addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327regen:
Fernando Gont969c5462020-05-01 00:51:47 -03002328 get_random_bytes(&addr->s6_addr[8], 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329
Fernando Gont969c5462020-05-01 00:51:47 -03002330 /* <draft-ietf-6man-rfc4941bis-08.txt>, Section 3.3.1:
2331 * check if generated address is not inappropriate:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332 *
Fernando Gont969c5462020-05-01 00:51:47 -03002333 * - Reserved IPv6 Interface Identifers
2334 * - XXX: already assigned to an address on the device
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336
Fernando Gont969c5462020-05-01 00:51:47 -03002337 /* Subnet-router anycast: 0000:0000:0000:0000 */
2338 if (!(addr->s6_addr32[2] | addr->s6_addr32[3]))
2339 goto regen;
2340
2341 /* IANA Ethernet block: 0200:5EFF:FE00:0000-0200:5EFF:FE00:5212
2342 * Proxy Mobile IPv6: 0200:5EFF:FE00:5213
2343 * IANA Ethernet block: 0200:5EFF:FE00:5214-0200:5EFF:FEFF:FFFF
2344 */
2345 if (ntohl(addr->s6_addr32[2]) == 0x02005eff &&
2346 (ntohl(addr->s6_addr32[3]) & 0Xff000000) == 0xfe000000)
2347 goto regen;
2348
2349 /* Reserved subnet anycast addresses */
2350 if (ntohl(addr->s6_addr32[2]) == 0xfdffffff &&
2351 ntohl(addr->s6_addr32[3]) >= 0Xffffff80)
2352 goto regen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354
2355/*
2356 * Add prefix route.
2357 */
2358
2359static void
David Ahern8308f3f2018-05-27 08:09:58 -07002360addrconf_prefix_route(struct in6_addr *pfx, int plen, u32 metric,
2361 struct net_device *dev, unsigned long expires,
2362 u32 flags, gfp_t gfp_flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363{
Thomas Graf86872cb2006-08-22 00:01:08 -07002364 struct fib6_config cfg = {
David Ahernca254492015-10-12 11:47:10 -07002365 .fc_table = l3mdev_fib_table(dev) ? : RT6_TABLE_PREFIX,
David Ahern8308f3f2018-05-27 08:09:58 -07002366 .fc_metric = metric ? : IP6_RT_PRIO_ADDRCONF,
Thomas Graf86872cb2006-08-22 00:01:08 -07002367 .fc_ifindex = dev->ifindex,
2368 .fc_expires = expires,
2369 .fc_dst_len = plen,
2370 .fc_flags = RTF_UP | flags,
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09002371 .fc_nlinfo.nl_net = dev_net(dev),
Stephen Hemmingerf410a1f2008-08-23 05:16:46 -07002372 .fc_protocol = RTPROT_KERNEL,
David Aherne8478e82018-04-17 17:33:13 -07002373 .fc_type = RTN_UNICAST,
Thomas Graf86872cb2006-08-22 00:01:08 -07002374 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +00002376 cfg.fc_dst = *pfx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377
2378 /* Prevent useless cloning on PtP SIT.
2379 This thing is done here expecting that the whole
2380 class of non-broadcast devices need not cloning.
2381 */
Amerigo Wang07a93622012-10-29 16:23:10 +00002382#if IS_ENABLED(CONFIG_IPV6_SIT)
Thomas Graf86872cb2006-08-22 00:01:08 -07002383 if (dev->type == ARPHRD_SIT && (dev->flags & IFF_POINTOPOINT))
2384 cfg.fc_flags |= RTF_NONEXTHOP;
Joerg Roedel0be669b2006-10-10 14:49:53 -07002385#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002386
David Ahernacb54e32018-04-17 17:33:22 -07002387 ip6_route_add(&cfg, gfp_flags, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388}
2389
Andreas Hofmeister14ef37b2011-10-26 03:24:29 +00002390
David Ahern8d1c8022018-04-17 17:33:26 -07002391static struct fib6_info *addrconf_get_prefix_route(const struct in6_addr *pfx,
Andreas Hofmeister14ef37b2011-10-26 03:24:29 +00002392 int plen,
2393 const struct net_device *dev,
David Ahern2b2450c2019-03-27 20:53:52 -07002394 u32 flags, u32 noflags,
2395 bool no_gw)
Andreas Hofmeister14ef37b2011-10-26 03:24:29 +00002396{
2397 struct fib6_node *fn;
David Ahern8d1c8022018-04-17 17:33:26 -07002398 struct fib6_info *rt = NULL;
Andreas Hofmeister14ef37b2011-10-26 03:24:29 +00002399 struct fib6_table *table;
David Ahernca254492015-10-12 11:47:10 -07002400 u32 tb_id = l3mdev_fib_table(dev) ? : RT6_TABLE_PREFIX;
Andreas Hofmeister14ef37b2011-10-26 03:24:29 +00002401
David Ahernca254492015-10-12 11:47:10 -07002402 table = fib6_get_table(dev_net(dev), tb_id);
Ian Morris63159f22015-03-29 14:00:04 +01002403 if (!table)
Andreas Hofmeister14ef37b2011-10-26 03:24:29 +00002404 return NULL;
2405
Wei Wang66f5d6c2017-10-06 12:06:10 -07002406 rcu_read_lock();
Wei Wang38fbeee2017-10-06 12:06:02 -07002407 fn = fib6_locate(&table->tb6_root, pfx, plen, NULL, 0, true);
Andreas Hofmeister14ef37b2011-10-26 03:24:29 +00002408 if (!fn)
2409 goto out;
Martin KaFai Lau1f56a01f2015-04-28 13:03:03 -07002410
Wei Wang66f5d6c2017-10-06 12:06:10 -07002411 for_each_fib6_node_rt_rcu(fn) {
David Ahernf88d8ea2019-06-03 20:19:52 -07002412 /* prefix routes only use builtin fib6_nh */
2413 if (rt->nh)
2414 continue;
2415
David Ahern1cf844c2019-05-22 20:27:59 -07002416 if (rt->fib6_nh->fib_nh_dev->ifindex != dev->ifindex)
Andreas Hofmeister14ef37b2011-10-26 03:24:29 +00002417 continue;
David Ahern1cf844c2019-05-22 20:27:59 -07002418 if (no_gw && rt->fib6_nh->fib_nh_gw_family)
David Ahern2b2450c2019-03-27 20:53:52 -07002419 continue;
David Ahern93c2fb22018-04-18 15:38:59 -07002420 if ((rt->fib6_flags & flags) != flags)
Andreas Hofmeister14ef37b2011-10-26 03:24:29 +00002421 continue;
David Ahern93c2fb22018-04-18 15:38:59 -07002422 if ((rt->fib6_flags & noflags) != 0)
Andreas Hofmeister14ef37b2011-10-26 03:24:29 +00002423 continue;
Wei Wange873e4b2018-07-21 20:56:32 -07002424 if (!fib6_info_hold_safe(rt))
2425 continue;
Andreas Hofmeister14ef37b2011-10-26 03:24:29 +00002426 break;
2427 }
2428out:
Wei Wang66f5d6c2017-10-06 12:06:10 -07002429 rcu_read_unlock();
Andreas Hofmeister14ef37b2011-10-26 03:24:29 +00002430 return rt;
2431}
2432
2433
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434/* Create "default" multicast route to the interface */
2435
2436static void addrconf_add_mroute(struct net_device *dev)
2437{
Thomas Graf86872cb2006-08-22 00:01:08 -07002438 struct fib6_config cfg = {
David Ahernca254492015-10-12 11:47:10 -07002439 .fc_table = l3mdev_fib_table(dev) ? : RT6_TABLE_LOCAL,
Thomas Graf86872cb2006-08-22 00:01:08 -07002440 .fc_metric = IP6_RT_PRIO_ADDRCONF,
2441 .fc_ifindex = dev->ifindex,
2442 .fc_dst_len = 8,
2443 .fc_flags = RTF_UP,
David Aherne8478e82018-04-17 17:33:13 -07002444 .fc_type = RTN_UNICAST,
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09002445 .fc_nlinfo.nl_net = dev_net(dev),
Thomas Graf86872cb2006-08-22 00:01:08 -07002446 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447
Thomas Graf86872cb2006-08-22 00:01:08 -07002448 ipv6_addr_set(&cfg.fc_dst, htonl(0xFF000000), 0, 0, 0);
2449
Cong Wange500c6d2018-08-22 12:58:34 -07002450 ip6_route_add(&cfg, GFP_KERNEL, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451}
2452
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453static struct inet6_dev *addrconf_add_dev(struct net_device *dev)
2454{
2455 struct inet6_dev *idev;
2456
2457 ASSERT_RTNL();
2458
Stephen Hemmingere21e8462010-03-20 16:09:01 -07002459 idev = ipv6_find_idev(dev);
Sabrina Dubrocadb0b99f2019-08-23 15:44:36 +02002460 if (IS_ERR(idev))
2461 return idev;
Brian Haley64e724f2010-07-20 10:34:30 +00002462
2463 if (idev->cnf.disable_ipv6)
2464 return ERR_PTR(-EACCES);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465
2466 /* Add default multicast route */
David Ahernba46ee42016-06-13 13:44:18 -07002467 if (!(dev->flags & IFF_LOOPBACK) && !netif_is_l3_master(dev))
Li Wei4af04ab2011-12-06 21:23:45 +00002468 addrconf_add_mroute(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470 return idev;
2471}
2472
Jiri Pirko53bd6742013-12-06 09:45:22 +01002473static void manage_tempaddrs(struct inet6_dev *idev,
2474 struct inet6_ifaddr *ifp,
2475 __u32 valid_lft, __u32 prefered_lft,
2476 bool create, unsigned long now)
2477{
2478 u32 flags;
2479 struct inet6_ifaddr *ift;
2480
2481 read_lock_bh(&idev->lock);
2482 /* update all temporary addresses in the list */
2483 list_for_each_entry(ift, &idev->tempaddr_list, tmp_list) {
2484 int age, max_valid, max_prefered;
2485
2486 if (ifp != ift->ifpub)
2487 continue;
2488
2489 /* RFC 4941 section 3.3:
2490 * If a received option will extend the lifetime of a public
2491 * address, the lifetimes of temporary addresses should
2492 * be extended, subject to the overall constraint that no
2493 * temporary addresses should ever remain "valid" or "preferred"
2494 * for a time longer than (TEMP_VALID_LIFETIME) or
2495 * (TEMP_PREFERRED_LIFETIME - DESYNC_FACTOR), respectively.
2496 */
2497 age = (now - ift->cstamp) / HZ;
2498 max_valid = idev->cnf.temp_valid_lft - age;
2499 if (max_valid < 0)
2500 max_valid = 0;
2501
2502 max_prefered = idev->cnf.temp_prefered_lft -
Jiri Bohac76506a92016-10-13 18:52:15 +02002503 idev->desync_factor - age;
Jiri Pirko53bd6742013-12-06 09:45:22 +01002504 if (max_prefered < 0)
2505 max_prefered = 0;
2506
2507 if (valid_lft > max_valid)
2508 valid_lft = max_valid;
2509
2510 if (prefered_lft > max_prefered)
2511 prefered_lft = max_prefered;
2512
2513 spin_lock(&ift->lock);
2514 flags = ift->flags;
2515 ift->valid_lft = valid_lft;
2516 ift->prefered_lft = prefered_lft;
2517 ift->tstamp = now;
2518 if (prefered_lft > 0)
2519 ift->flags &= ~IFA_F_DEPRECATED;
2520
2521 spin_unlock(&ift->lock);
2522 if (!(flags&IFA_F_TENTATIVE))
2523 ipv6_ifa_notify(0, ift);
2524 }
2525
2526 if ((create || list_empty(&idev->tempaddr_list)) &&
2527 idev->cnf.use_tempaddr > 0) {
2528 /* When a new public address is created as described
2529 * in [ADDRCONF], also create a new temporary address.
2530 * Also create a temporary address if it's enabled but
2531 * no temporary address currently exists.
2532 */
2533 read_unlock_bh(&idev->lock);
Fernando Gont969c5462020-05-01 00:51:47 -03002534 ipv6_create_tempaddr(ifp, false);
Jiri Pirko53bd6742013-12-06 09:45:22 +01002535 } else {
2536 read_unlock_bh(&idev->lock);
2537 }
2538}
2539
Bjørn Morkcc9da6c2015-12-16 16:44:38 +01002540static bool is_addr_mode_generate_stable(struct inet6_dev *idev)
2541{
Felix Jiad35a00b2017-01-26 16:59:17 +13002542 return idev->cnf.addr_gen_mode == IN6_ADDR_GEN_MODE_STABLE_PRIVACY ||
2543 idev->cnf.addr_gen_mode == IN6_ADDR_GEN_MODE_RANDOM;
Bjørn Morkcc9da6c2015-12-16 16:44:38 +01002544}
2545
Alexander Aringcc84b3c2016-06-15 21:20:24 +02002546int addrconf_prefix_rcv_add_addr(struct net *net, struct net_device *dev,
2547 const struct prefix_info *pinfo,
2548 struct inet6_dev *in6_dev,
2549 const struct in6_addr *addr, int addr_type,
2550 u32 addr_flags, bool sllao, bool tokenized,
2551 __u32 valid_lft, u32 prefered_lft)
Alexander Aring4f672232016-06-15 21:20:22 +02002552{
2553 struct inet6_ifaddr *ifp = ipv6_get_ifaddr(net, addr, dev, 1);
Fernando Gontb75326c2020-04-19 09:24:57 -03002554 int create = 0;
Alexander Aring4f672232016-06-15 21:20:22 +02002555
2556 if (!ifp && valid_lft) {
2557 int max_addresses = in6_dev->cnf.max_addresses;
David Aherne6464b82018-05-27 08:09:53 -07002558 struct ifa6_config cfg = {
2559 .pfx = addr,
2560 .plen = pinfo->prefix_len,
2561 .ifa_flags = addr_flags,
2562 .valid_lft = valid_lft,
2563 .preferred_lft = prefered_lft,
2564 .scope = addr_type & IPV6_ADDR_SCOPE_MASK,
2565 };
Alexander Aring4f672232016-06-15 21:20:22 +02002566
2567#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
Matteo Croce35e015e2017-09-12 17:46:37 +02002568 if ((net->ipv6.devconf_all->optimistic_dad ||
2569 in6_dev->cnf.optimistic_dad) &&
Alexander Aring4f672232016-06-15 21:20:22 +02002570 !net->ipv6.devconf_all->forwarding && sllao)
David Aherne6464b82018-05-27 08:09:53 -07002571 cfg.ifa_flags |= IFA_F_OPTIMISTIC;
Alexander Aring4f672232016-06-15 21:20:22 +02002572#endif
2573
2574 /* Do not allow to create too much of autoconfigured
2575 * addresses; this would be too easy way to crash kernel.
2576 */
2577 if (!max_addresses ||
2578 ipv6_count_addresses(in6_dev) < max_addresses)
David Aherne6464b82018-05-27 08:09:53 -07002579 ifp = ipv6_add_addr(in6_dev, &cfg, false, NULL);
Alexander Aring4f672232016-06-15 21:20:22 +02002580
2581 if (IS_ERR_OR_NULL(ifp))
2582 return -1;
2583
Alexander Aring4f672232016-06-15 21:20:22 +02002584 create = 1;
2585 spin_lock_bh(&ifp->lock);
2586 ifp->flags |= IFA_F_MANAGETEMPADDR;
2587 ifp->cstamp = jiffies;
2588 ifp->tokenized = tokenized;
2589 spin_unlock_bh(&ifp->lock);
2590 addrconf_dad_start(ifp);
2591 }
2592
2593 if (ifp) {
2594 u32 flags;
2595 unsigned long now;
2596 u32 stored_lft;
2597
Fernando Gontb75326c2020-04-19 09:24:57 -03002598 /* Update lifetime (RFC4862 5.5.3 e)
2599 * We deviate from RFC4862 by honoring all Valid Lifetimes to
2600 * improve the reaction of SLAAC to renumbering events
2601 * (draft-gont-6man-slaac-renum-06, Section 4.2)
2602 */
Alexander Aring4f672232016-06-15 21:20:22 +02002603 spin_lock_bh(&ifp->lock);
2604 now = jiffies;
2605 if (ifp->valid_lft > (now - ifp->tstamp) / HZ)
2606 stored_lft = ifp->valid_lft - (now - ifp->tstamp) / HZ;
2607 else
2608 stored_lft = 0;
Fernando Gontb75326c2020-04-19 09:24:57 -03002609
Lorenzo Bianconif85f94b2018-04-16 17:52:59 +02002610 if (!create && stored_lft) {
Alexander Aring4f672232016-06-15 21:20:22 +02002611 ifp->valid_lft = valid_lft;
2612 ifp->prefered_lft = prefered_lft;
2613 ifp->tstamp = now;
2614 flags = ifp->flags;
2615 ifp->flags &= ~IFA_F_DEPRECATED;
2616 spin_unlock_bh(&ifp->lock);
2617
2618 if (!(flags&IFA_F_TENTATIVE))
2619 ipv6_ifa_notify(0, ifp);
2620 } else
2621 spin_unlock_bh(&ifp->lock);
2622
2623 manage_tempaddrs(in6_dev, ifp, valid_lft, prefered_lft,
2624 create, now);
2625
2626 in6_ifa_put(ifp);
2627 addrconf_verify();
2628 }
2629
2630 return 0;
2631}
Alexander Aringcc84b3c2016-06-15 21:20:24 +02002632EXPORT_SYMBOL_GPL(addrconf_prefix_rcv_add_addr);
Alexander Aring4f672232016-06-15 21:20:22 +02002633
Neil Hormane6bff992012-01-04 10:49:15 +00002634void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635{
2636 struct prefix_info *pinfo;
2637 __u32 valid_lft;
2638 __u32 prefered_lft;
Alexander Aring4f672232016-06-15 21:20:22 +02002639 int addr_type, err;
Hannes Frederic Sowa64236f32015-03-23 23:36:02 +01002640 u32 addr_flags = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002641 struct inet6_dev *in6_dev;
Brian Haley56d417b2009-06-01 03:07:33 -07002642 struct net *net = dev_net(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643
2644 pinfo = (struct prefix_info *) opt;
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09002645
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646 if (len < sizeof(struct prefix_info)) {
Joe Perchese32ac252018-03-26 08:35:01 -07002647 netdev_dbg(dev, "addrconf: prefix option too short\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002648 return;
2649 }
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09002650
Linus Torvalds1da177e2005-04-16 15:20:36 -07002651 /*
2652 * Validation checks ([ADDRCONF], page 19)
2653 */
2654
2655 addr_type = ipv6_addr_type(&pinfo->prefix);
2656
2657 if (addr_type & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL))
2658 return;
2659
2660 valid_lft = ntohl(pinfo->valid);
2661 prefered_lft = ntohl(pinfo->prefered);
2662
2663 if (prefered_lft > valid_lft) {
Joe Perchese87cc472012-05-13 21:56:26 +00002664 net_warn_ratelimited("addrconf: prefix option has invalid lifetime\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665 return;
2666 }
2667
2668 in6_dev = in6_dev_get(dev);
2669
Ian Morris63159f22015-03-29 14:00:04 +01002670 if (!in6_dev) {
Joe Perchese87cc472012-05-13 21:56:26 +00002671 net_dbg_ratelimited("addrconf: device %s not configured\n",
2672 dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673 return;
2674 }
2675
2676 /*
2677 * Two things going on here:
2678 * 1) Add routes for on-link prefixes
2679 * 2) Configure prefixes with the auto flag set
2680 */
2681
YOSHIFUJI Hideaki4bed72e2008-05-27 17:37:49 +09002682 if (pinfo->onlink) {
David Ahern8d1c8022018-04-17 17:33:26 -07002683 struct fib6_info *rt;
YOSHIFUJI Hideaki4bed72e2008-05-27 17:37:49 +09002684 unsigned long rt_expires;
2685
YOSHIFUJI Hideaki6f704992008-05-19 16:56:11 -07002686 /* Avoid arithmetic overflow. Really, we could
2687 * save rt_expires in seconds, likely valid_lft,
2688 * but it would require division in fib gc, that it
2689 * not good.
2690 */
YOSHIFUJI Hideaki4bed72e2008-05-27 17:37:49 +09002691 if (HZ > USER_HZ)
2692 rt_expires = addrconf_timeout_fixup(valid_lft, HZ);
2693 else
2694 rt_expires = addrconf_timeout_fixup(valid_lft, USER_HZ);
YOSHIFUJI Hideaki3dd4bc62005-12-19 14:02:45 -08002695
YOSHIFUJI Hideaki4bed72e2008-05-27 17:37:49 +09002696 if (addrconf_finite_timeout(rt_expires))
2697 rt_expires *= HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002698
Andreas Hofmeister14ef37b2011-10-26 03:24:29 +00002699 rt = addrconf_get_prefix_route(&pinfo->prefix,
2700 pinfo->prefix_len,
2701 dev,
2702 RTF_ADDRCONF | RTF_PREFIX_RT,
David Ahern2b2450c2019-03-27 20:53:52 -07002703 RTF_DEFAULT, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002704
Andreas Hofmeister14ef37b2011-10-26 03:24:29 +00002705 if (rt) {
YOSHIFUJI Hideaki6f704992008-05-19 16:56:11 -07002706 /* Autoconf prefix route */
2707 if (valid_lft == 0) {
Roopa Prabhu11dd74b2020-04-27 13:56:45 -07002708 ip6_del_rt(net, rt, false);
YOSHIFUJI Hideaki6f704992008-05-19 16:56:11 -07002709 rt = NULL;
YOSHIFUJI Hideaki4bed72e2008-05-27 17:37:49 +09002710 } else if (addrconf_finite_timeout(rt_expires)) {
YOSHIFUJI Hideaki6f704992008-05-19 16:56:11 -07002711 /* not infinity */
David Ahern14895682018-04-17 17:33:17 -07002712 fib6_set_expires(rt, jiffies + rt_expires);
YOSHIFUJI Hideaki6f704992008-05-19 16:56:11 -07002713 } else {
David Ahern14895682018-04-17 17:33:17 -07002714 fib6_clean_expires(rt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002715 }
2716 } else if (valid_lft) {
YOSHIFUJI Hideaki6f704992008-05-19 16:56:11 -07002717 clock_t expires = 0;
YOSHIFUJI Hideaki4bed72e2008-05-27 17:37:49 +09002718 int flags = RTF_ADDRCONF | RTF_PREFIX_RT;
2719 if (addrconf_finite_timeout(rt_expires)) {
YOSHIFUJI Hideaki6f704992008-05-19 16:56:11 -07002720 /* not infinity */
2721 flags |= RTF_EXPIRES;
2722 expires = jiffies_to_clock_t(rt_expires);
2723 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724 addrconf_prefix_route(&pinfo->prefix, pinfo->prefix_len,
David Ahern8308f3f2018-05-27 08:09:58 -07002725 0, dev, expires, flags,
2726 GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727 }
David Ahern93531c62018-04-17 17:33:25 -07002728 fib6_info_release(rt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729 }
2730
2731 /* Try to figure out our local address for this prefix */
2732
2733 if (pinfo->autoconf && in6_dev->cnf.autoconf) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002734 struct in6_addr addr;
Alexander Aringf997c552016-06-15 21:20:23 +02002735 bool tokenized = false, dev_addr_generated = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736
2737 if (pinfo->prefix_len == 64) {
2738 memcpy(&addr, &pinfo->prefix, 8);
Daniel Borkmannf53adae2013-04-08 04:01:30 +00002739
2740 if (!ipv6_addr_any(&in6_dev->token)) {
2741 read_lock_bh(&in6_dev->lock);
2742 memcpy(addr.s6_addr + 8,
2743 in6_dev->token.s6_addr + 8, 8);
2744 read_unlock_bh(&in6_dev->lock);
Daniel Borkmann617fe292013-04-09 03:47:16 +00002745 tokenized = true;
Bjørn Morkcc9da6c2015-12-16 16:44:38 +01002746 } else if (is_addr_mode_generate_stable(in6_dev) &&
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01002747 !ipv6_generate_stable_address(&addr, 0,
2748 in6_dev)) {
Hannes Frederic Sowa64236f32015-03-23 23:36:02 +01002749 addr_flags |= IFA_F_STABLE_PRIVACY;
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01002750 goto ok;
Daniel Borkmannf53adae2013-04-08 04:01:30 +00002751 } else if (ipv6_generate_eui64(addr.s6_addr + 8, dev) &&
2752 ipv6_inherit_eui64(addr.s6_addr + 8, in6_dev)) {
Alexander Aring4f672232016-06-15 21:20:22 +02002753 goto put;
Alexander Aringf997c552016-06-15 21:20:23 +02002754 } else {
2755 dev_addr_generated = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002756 }
2757 goto ok;
2758 }
Joe Perchese87cc472012-05-13 21:56:26 +00002759 net_dbg_ratelimited("IPv6 addrconf: prefix with wrong length %d\n",
2760 pinfo->prefix_len);
Alexander Aring4f672232016-06-15 21:20:22 +02002761 goto put;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762
2763ok:
Alexander Aring4f672232016-06-15 21:20:22 +02002764 err = addrconf_prefix_rcv_add_addr(net, dev, pinfo, in6_dev,
2765 &addr, addr_type,
2766 addr_flags, sllao,
2767 tokenized, valid_lft,
2768 prefered_lft);
2769 if (err)
2770 goto put;
Alexander Aringf997c552016-06-15 21:20:23 +02002771
2772 /* Ignore error case here because previous prefix add addr was
2773 * successful which will be notified.
2774 */
2775 ndisc_ops_prefix_rcv_add_addr(net, dev, pinfo, in6_dev, &addr,
2776 addr_type, addr_flags, sllao,
2777 tokenized, valid_lft,
2778 prefered_lft,
2779 dev_addr_generated);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002780 }
2781 inet6_prefix_notify(RTM_NEWPREFIX, in6_dev, pinfo);
Alexander Aring4f672232016-06-15 21:20:22 +02002782put:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002783 in6_dev_put(in6_dev);
2784}
2785
Christoph Hellwig68ad6882020-05-19 15:03:18 +02002786static int addrconf_set_sit_dstaddr(struct net *net, struct net_device *dev,
2787 struct in6_ifreq *ireq)
2788{
2789 struct ip_tunnel_parm p = { };
Christoph Hellwig68ad6882020-05-19 15:03:18 +02002790 int err;
2791
2792 if (!(ipv6_addr_type(&ireq->ifr6_addr) & IPV6_ADDR_COMPATv4))
2793 return -EADDRNOTAVAIL;
2794
2795 p.iph.daddr = ireq->ifr6_addr.s6_addr32[3];
2796 p.iph.version = 4;
2797 p.iph.ihl = 5;
2798 p.iph.protocol = IPPROTO_IPV6;
2799 p.iph.ttl = 64;
Christoph Hellwig68ad6882020-05-19 15:03:18 +02002800
Christoph Hellwig8e3db0b2020-05-19 15:03:19 +02002801 if (!dev->netdev_ops->ndo_tunnel_ctl)
Christoph Hellwig68ad6882020-05-19 15:03:18 +02002802 return -EOPNOTSUPP;
Christoph Hellwig8e3db0b2020-05-19 15:03:19 +02002803 err = dev->netdev_ops->ndo_tunnel_ctl(dev, &p, SIOCADDTUNNEL);
Christoph Hellwig68ad6882020-05-19 15:03:18 +02002804 if (err)
2805 return err;
2806
2807 dev = __dev_get_by_name(net, p.name);
2808 if (!dev)
2809 return -ENOBUFS;
2810 return dev_open(dev, NULL);
2811}
2812
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813/*
2814 * Set destination address.
2815 * Special case for SIT interfaces where we create a new "virtual"
2816 * device.
2817 */
Daniel Lezcanoaf284932008-03-05 10:46:57 -08002818int addrconf_set_dstaddr(struct net *net, void __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820 struct net_device *dev;
Christoph Hellwig68ad6882020-05-19 15:03:18 +02002821 struct in6_ifreq ireq;
2822 int err = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823
Christoph Hellwigf0988462020-05-19 15:03:17 +02002824 if (!IS_ENABLED(CONFIG_IPV6_SIT))
2825 return -ENODEV;
Christoph Hellwig68ad6882020-05-19 15:03:18 +02002826 if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
2827 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002828
2829 rtnl_lock();
Daniel Lezcanoaf284932008-03-05 10:46:57 -08002830 dev = __dev_get_by_index(net, ireq.ifr6_ifindex);
Christoph Hellwig68ad6882020-05-19 15:03:18 +02002831 if (dev && dev->type == ARPHRD_SIT)
2832 err = addrconf_set_sit_dstaddr(net, dev, &ireq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002833 rtnl_unlock();
2834 return err;
2835}
2836
Madhu Challa93a714d2015-02-25 09:58:35 -08002837static int ipv6_mc_config(struct sock *sk, bool join,
2838 const struct in6_addr *addr, int ifindex)
2839{
2840 int ret;
2841
2842 ASSERT_RTNL();
2843
2844 lock_sock(sk);
2845 if (join)
Marcelo Ricardo Leitner54ff9ef2015-03-18 14:50:43 -03002846 ret = ipv6_sock_mc_join(sk, ifindex, addr);
Madhu Challa93a714d2015-02-25 09:58:35 -08002847 else
Marcelo Ricardo Leitner54ff9ef2015-03-18 14:50:43 -03002848 ret = ipv6_sock_mc_drop(sk, ifindex, addr);
Madhu Challa93a714d2015-02-25 09:58:35 -08002849 release_sock(sk);
2850
2851 return ret;
2852}
2853
Linus Torvalds1da177e2005-04-16 15:20:36 -07002854/*
2855 * Manual configuration of address on an interface
2856 */
Jiri Pirko479840f2013-12-06 09:45:21 +01002857static int inet6_addr_add(struct net *net, int ifindex,
David Ahern19b15182018-05-27 08:09:54 -07002858 struct ifa6_config *cfg,
David Ahernde95e042017-10-18 09:56:54 -07002859 struct netlink_ext_ack *extack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860{
2861 struct inet6_ifaddr *ifp;
2862 struct inet6_dev *idev;
2863 struct net_device *dev;
Madhu Challa93a714d2015-02-25 09:58:35 -08002864 unsigned long timeout;
2865 clock_t expires;
YOSHIFUJI Hideaki6f704992008-05-19 16:56:11 -07002866 u32 flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002867
2868 ASSERT_RTNL();
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09002869
David Ahern19b15182018-05-27 08:09:54 -07002870 if (cfg->plen > 128)
Thomas Graf24ef0da2008-05-28 16:54:22 +02002871 return -EINVAL;
2872
Noriaki TAKAMIYA0778769d2006-07-28 18:12:10 +09002873 /* check the lifetime */
David Ahern19b15182018-05-27 08:09:54 -07002874 if (!cfg->valid_lft || cfg->preferred_lft > cfg->valid_lft)
Noriaki TAKAMIYA0778769d2006-07-28 18:12:10 +09002875 return -EINVAL;
2876
David Ahern19b15182018-05-27 08:09:54 -07002877 if (cfg->ifa_flags & IFA_F_MANAGETEMPADDR && cfg->plen != 64)
Jiri Pirko53bd6742013-12-06 09:45:22 +01002878 return -EINVAL;
2879
Daniel Lezcanoaf284932008-03-05 10:46:57 -08002880 dev = __dev_get_by_index(net, ifindex);
2881 if (!dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002882 return -ENODEV;
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09002883
Brian Haley64e724f2010-07-20 10:34:30 +00002884 idev = addrconf_add_dev(dev);
2885 if (IS_ERR(idev))
2886 return PTR_ERR(idev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887
David Ahern19b15182018-05-27 08:09:54 -07002888 if (cfg->ifa_flags & IFA_F_MCAUTOJOIN) {
Madhu Challa93a714d2015-02-25 09:58:35 -08002889 int ret = ipv6_mc_config(net->ipv6.mc_autojoin_sk,
David Ahern19b15182018-05-27 08:09:54 -07002890 true, cfg->pfx, ifindex);
Madhu Challa93a714d2015-02-25 09:58:35 -08002891
2892 if (ret < 0)
2893 return ret;
2894 }
2895
David Ahern19b15182018-05-27 08:09:54 -07002896 cfg->scope = ipv6_addr_scope(cfg->pfx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002897
David Ahern19b15182018-05-27 08:09:54 -07002898 timeout = addrconf_timeout_fixup(cfg->valid_lft, HZ);
YOSHIFUJI Hideaki4bed72e2008-05-27 17:37:49 +09002899 if (addrconf_finite_timeout(timeout)) {
2900 expires = jiffies_to_clock_t(timeout * HZ);
David Ahern19b15182018-05-27 08:09:54 -07002901 cfg->valid_lft = timeout;
YOSHIFUJI Hideaki6f704992008-05-19 16:56:11 -07002902 flags = RTF_EXPIRES;
YOSHIFUJI Hideaki4bed72e2008-05-27 17:37:49 +09002903 } else {
2904 expires = 0;
2905 flags = 0;
David Ahern19b15182018-05-27 08:09:54 -07002906 cfg->ifa_flags |= IFA_F_PERMANENT;
YOSHIFUJI Hideaki6f704992008-05-19 16:56:11 -07002907 }
Noriaki TAKAMIYA0778769d2006-07-28 18:12:10 +09002908
David Ahern19b15182018-05-27 08:09:54 -07002909 timeout = addrconf_timeout_fixup(cfg->preferred_lft, HZ);
YOSHIFUJI Hideaki4bed72e2008-05-27 17:37:49 +09002910 if (addrconf_finite_timeout(timeout)) {
2911 if (timeout == 0)
David Ahern19b15182018-05-27 08:09:54 -07002912 cfg->ifa_flags |= IFA_F_DEPRECATED;
2913 cfg->preferred_lft = timeout;
YOSHIFUJI Hideaki4bed72e2008-05-27 17:37:49 +09002914 }
Noriaki TAKAMIYA0778769d2006-07-28 18:12:10 +09002915
David Ahern19b15182018-05-27 08:09:54 -07002916 ifp = ipv6_add_addr(idev, cfg, true, extack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002917 if (!IS_ERR(ifp)) {
David Ahern19b15182018-05-27 08:09:54 -07002918 if (!(cfg->ifa_flags & IFA_F_NOPREFIXROUTE)) {
David Ahern8308f3f2018-05-27 08:09:58 -07002919 addrconf_prefix_route(&ifp->addr, ifp->prefix_len,
2920 ifp->rt_priority, dev, expires,
2921 flags, GFP_KERNEL);
Thomas Haller761aac72014-01-15 15:36:58 +01002922 }
2923
Lorenzo Bianconia2d481b2018-04-17 11:54:39 +02002924 /* Send a netlink notification if DAD is enabled and
2925 * optimistic flag is not set
2926 */
2927 if (!(ifp->flags & (IFA_F_OPTIMISTIC | IFA_F_NODAD)))
2928 ipv6_ifa_notify(0, ifp);
Neil Horman95c385b2007-04-25 17:08:10 -07002929 /*
2930 * Note that section 3.1 of RFC 4429 indicates
2931 * that the Optimistic flag should not be set for
2932 * manually configured addresses
2933 */
David S. Millercf22f9a2012-04-14 21:37:40 -04002934 addrconf_dad_start(ifp);
David Ahern19b15182018-05-27 08:09:54 -07002935 if (cfg->ifa_flags & IFA_F_MANAGETEMPADDR)
2936 manage_tempaddrs(idev, ifp, cfg->valid_lft,
2937 cfg->preferred_lft, true, jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002938 in6_ifa_put(ifp);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01002939 addrconf_verify_rtnl();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940 return 0;
David Ahern19b15182018-05-27 08:09:54 -07002941 } else if (cfg->ifa_flags & IFA_F_MCAUTOJOIN) {
2942 ipv6_mc_config(net->ipv6.mc_autojoin_sk, false,
2943 cfg->pfx, ifindex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002944 }
2945
2946 return PTR_ERR(ifp);
2947}
2948
Heiner Kallweit6046d5b2014-04-20 21:29:36 +02002949static int inet6_addr_del(struct net *net, int ifindex, u32 ifa_flags,
2950 const struct in6_addr *pfx, unsigned int plen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002951{
2952 struct inet6_ifaddr *ifp;
2953 struct inet6_dev *idev;
2954 struct net_device *dev;
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09002955
Thomas Graf24ef0da2008-05-28 16:54:22 +02002956 if (plen > 128)
2957 return -EINVAL;
2958
Daniel Lezcanoaf284932008-03-05 10:46:57 -08002959 dev = __dev_get_by_index(net, ifindex);
2960 if (!dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002961 return -ENODEV;
2962
Ian Morrise5d08d72014-11-23 21:28:43 +00002963 idev = __in6_dev_get(dev);
Ian Morris63159f22015-03-29 14:00:04 +01002964 if (!idev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002965 return -ENXIO;
2966
2967 read_lock_bh(&idev->lock);
stephen hemminger502a2ff2010-03-17 20:31:13 +00002968 list_for_each_entry(ifp, &idev->addr_list, if_list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002969 if (ifp->prefix_len == plen &&
2970 ipv6_addr_equal(pfx, &ifp->addr)) {
2971 in6_ifa_hold(ifp);
2972 read_unlock_bh(&idev->lock);
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09002973
Heiner Kallweit6046d5b2014-04-20 21:29:36 +02002974 if (!(ifp->flags & IFA_F_TEMPORARY) &&
2975 (ifa_flags & IFA_F_MANAGETEMPADDR))
2976 manage_tempaddrs(idev, ifp, 0, 0, false,
2977 jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002978 ipv6_del_addr(ifp);
Heiner Kallweit6046d5b2014-04-20 21:29:36 +02002979 addrconf_verify_rtnl();
Madhu Challa93a714d2015-02-25 09:58:35 -08002980 if (ipv6_addr_is_multicast(pfx)) {
2981 ipv6_mc_config(net->ipv6.mc_autojoin_sk,
2982 false, pfx, dev->ifindex);
2983 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002984 return 0;
2985 }
2986 }
2987 read_unlock_bh(&idev->lock);
2988 return -EADDRNOTAVAIL;
2989}
2990
2991
Daniel Lezcanoaf284932008-03-05 10:46:57 -08002992int addrconf_add_ifaddr(struct net *net, void __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002993{
David Ahern19b15182018-05-27 08:09:54 -07002994 struct ifa6_config cfg = {
2995 .ifa_flags = IFA_F_PERMANENT,
2996 .preferred_lft = INFINITY_LIFE_TIME,
2997 .valid_lft = INFINITY_LIFE_TIME,
2998 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999 struct in6_ifreq ireq;
3000 int err;
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09003001
Eric W. Biedermanaf31f412012-11-16 03:03:06 +00003002 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003003 return -EPERM;
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09003004
Linus Torvalds1da177e2005-04-16 15:20:36 -07003005 if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
3006 return -EFAULT;
3007
David Ahern19b15182018-05-27 08:09:54 -07003008 cfg.pfx = &ireq.ifr6_addr;
3009 cfg.plen = ireq.ifr6_prefixlen;
3010
Linus Torvalds1da177e2005-04-16 15:20:36 -07003011 rtnl_lock();
David Ahern19b15182018-05-27 08:09:54 -07003012 err = inet6_addr_add(net, ireq.ifr6_ifindex, &cfg, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003013 rtnl_unlock();
3014 return err;
3015}
3016
Daniel Lezcanoaf284932008-03-05 10:46:57 -08003017int addrconf_del_ifaddr(struct net *net, void __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003018{
3019 struct in6_ifreq ireq;
3020 int err;
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09003021
Eric W. Biedermanaf31f412012-11-16 03:03:06 +00003022 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003023 return -EPERM;
3024
3025 if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
3026 return -EFAULT;
3027
3028 rtnl_lock();
Heiner Kallweit6046d5b2014-04-20 21:29:36 +02003029 err = inet6_addr_del(net, ireq.ifr6_ifindex, 0, &ireq.ifr6_addr,
Daniel Lezcanoaf284932008-03-05 10:46:57 -08003030 ireq.ifr6_prefixlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003031 rtnl_unlock();
3032 return err;
3033}
3034
Ilpo Järvinenb5f348e2009-02-06 23:48:01 -08003035static void add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
3036 int plen, int scope)
3037{
3038 struct inet6_ifaddr *ifp;
David Aherne6464b82018-05-27 08:09:53 -07003039 struct ifa6_config cfg = {
3040 .pfx = addr,
3041 .plen = plen,
3042 .ifa_flags = IFA_F_PERMANENT,
3043 .valid_lft = INFINITY_LIFE_TIME,
3044 .preferred_lft = INFINITY_LIFE_TIME,
3045 .scope = scope
3046 };
Ilpo Järvinenb5f348e2009-02-06 23:48:01 -08003047
David Aherne6464b82018-05-27 08:09:53 -07003048 ifp = ipv6_add_addr(idev, &cfg, true, NULL);
Ilpo Järvinenb5f348e2009-02-06 23:48:01 -08003049 if (!IS_ERR(ifp)) {
3050 spin_lock_bh(&ifp->lock);
3051 ifp->flags &= ~IFA_F_TENTATIVE;
3052 spin_unlock_bh(&ifp->lock);
Paolo Abeni764d3be2016-11-22 16:57:40 +01003053 rt_genid_bump_ipv6(dev_net(idev->dev));
Ilpo Järvinenb5f348e2009-02-06 23:48:01 -08003054 ipv6_ifa_notify(RTM_NEWADDR, ifp);
3055 in6_ifa_put(ifp);
3056 }
3057}
3058
Amerigo Wang07a93622012-10-29 16:23:10 +00003059#if IS_ENABLED(CONFIG_IPV6_SIT)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003060static void sit_add_v4_addrs(struct inet6_dev *idev)
3061{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003062 struct in6_addr addr;
3063 struct net_device *dev;
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09003064 struct net *net = dev_net(idev->dev);
Nicolas Dichtel929c9cf2013-11-14 13:51:05 +01003065 int scope, plen;
Nicolas Dichtelf0e2acf2013-11-14 13:51:06 +01003066 u32 pflags = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003067
3068 ASSERT_RTNL();
3069
3070 memset(&addr, 0, sizeof(struct in6_addr));
3071 memcpy(&addr.s6_addr32[3], idev->dev->dev_addr, 4);
3072
3073 if (idev->dev->flags&IFF_POINTOPOINT) {
3074 addr.s6_addr32[0] = htonl(0xfe800000);
3075 scope = IFA_LINK;
Nicolas Dichtel929c9cf2013-11-14 13:51:05 +01003076 plen = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003077 } else {
3078 scope = IPV6_ADDR_COMPATv4;
Nicolas Dichtel929c9cf2013-11-14 13:51:05 +01003079 plen = 96;
Nicolas Dichtelf0e2acf2013-11-14 13:51:06 +01003080 pflags |= RTF_NONEXTHOP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003081 }
3082
3083 if (addr.s6_addr32[3]) {
Nicolas Dichtel929c9cf2013-11-14 13:51:05 +01003084 add_addr(idev, &addr, plen, scope);
David Ahern8308f3f2018-05-27 08:09:58 -07003085 addrconf_prefix_route(&addr, plen, 0, idev->dev, 0, pflags,
Cong Wange500c6d2018-08-22 12:58:34 -07003086 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003087 return;
3088 }
3089
Benjamin Thery6fda7352008-03-05 10:47:47 -08003090 for_each_netdev(net, dev) {
Eldad Zack8e5e8f32012-04-01 07:49:08 +00003091 struct in_device *in_dev = __in_dev_get_rtnl(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003092 if (in_dev && (dev->flags & IFF_UP)) {
Eldad Zack8e5e8f32012-04-01 07:49:08 +00003093 struct in_ifaddr *ifa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003094 int flag = scope;
3095
Florian Westphalcd5a4112019-05-31 18:27:07 +02003096 in_dev_for_each_ifa_rtnl(ifa, in_dev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003097 addr.s6_addr32[3] = ifa->ifa_local;
3098
3099 if (ifa->ifa_scope == RT_SCOPE_LINK)
3100 continue;
3101 if (ifa->ifa_scope >= RT_SCOPE_HOST) {
3102 if (idev->dev->flags&IFF_POINTOPOINT)
3103 continue;
3104 flag |= IFA_HOST;
3105 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003106
Ilpo Järvinenb5f348e2009-02-06 23:48:01 -08003107 add_addr(idev, &addr, plen, flag);
David Ahern8308f3f2018-05-27 08:09:58 -07003108 addrconf_prefix_route(&addr, plen, 0, idev->dev,
Cong Wange500c6d2018-08-22 12:58:34 -07003109 0, pflags, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003110 }
3111 }
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09003112 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003113}
Joerg Roedel0be669b2006-10-10 14:49:53 -07003114#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003115
3116static void init_loopback(struct net_device *dev)
3117{
3118 struct inet6_dev *idev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003119
3120 /* ::1 */
3121
3122 ASSERT_RTNL();
3123
Ian Morrise5d08d72014-11-23 21:28:43 +00003124 idev = ipv6_find_idev(dev);
Sabrina Dubrocadb0b99f2019-08-23 15:44:36 +02003125 if (IS_ERR(idev)) {
Joe Perches91df42b2012-05-15 14:11:54 +00003126 pr_debug("%s: add_dev failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003127 return;
3128 }
3129
Ilpo Järvinenb5f348e2009-02-06 23:48:01 -08003130 add_addr(idev, &in6addr_loopback, 128, IFA_HOST);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003131}
3132
Alexander Aring2ad3ed52016-06-15 21:20:17 +02003133void addrconf_add_linklocal(struct inet6_dev *idev,
3134 const struct in6_addr *addr, u32 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003135{
David Aherne6464b82018-05-27 08:09:53 -07003136 struct ifa6_config cfg = {
3137 .pfx = addr,
3138 .plen = 64,
3139 .ifa_flags = flags | IFA_F_PERMANENT,
3140 .valid_lft = INFINITY_LIFE_TIME,
3141 .preferred_lft = INFINITY_LIFE_TIME,
3142 .scope = IFA_LINK
3143 };
Eldad Zack8e5e8f32012-04-01 07:49:08 +00003144 struct inet6_ifaddr *ifp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003145
Neil Horman95c385b2007-04-25 17:08:10 -07003146#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
Matteo Croce35e015e2017-09-12 17:46:37 +02003147 if ((dev_net(idev->dev)->ipv6.devconf_all->optimistic_dad ||
3148 idev->cnf.optimistic_dad) &&
David Miller702beb82008-07-20 18:17:02 -07003149 !dev_net(idev->dev)->ipv6.devconf_all->forwarding)
David Aherne6464b82018-05-27 08:09:53 -07003150 cfg.ifa_flags |= IFA_F_OPTIMISTIC;
Neil Horman95c385b2007-04-25 17:08:10 -07003151#endif
3152
David Aherne6464b82018-05-27 08:09:53 -07003153 ifp = ipv6_add_addr(idev, &cfg, true, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003154 if (!IS_ERR(ifp)) {
David Ahern8308f3f2018-05-27 08:09:58 -07003155 addrconf_prefix_route(&ifp->addr, ifp->prefix_len, 0, idev->dev,
David Ahernacb54e32018-04-17 17:33:22 -07003156 0, 0, GFP_ATOMIC);
David S. Millercf22f9a2012-04-14 21:37:40 -04003157 addrconf_dad_start(ifp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003158 in6_ifa_put(ifp);
3159 }
3160}
Alexander Aring2ad3ed52016-06-15 21:20:17 +02003161EXPORT_SYMBOL_GPL(addrconf_add_linklocal);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003162
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01003163static bool ipv6_reserved_interfaceid(struct in6_addr address)
3164{
3165 if ((address.s6_addr32[2] | address.s6_addr32[3]) == 0)
3166 return true;
3167
3168 if (address.s6_addr32[2] == htonl(0x02005eff) &&
3169 ((address.s6_addr32[3] & htonl(0xfe000000)) == htonl(0xfe000000)))
3170 return true;
3171
3172 if (address.s6_addr32[2] == htonl(0xfdffffff) &&
3173 ((address.s6_addr32[3] & htonl(0xffffff80)) == htonl(0xffffff80)))
3174 return true;
3175
3176 return false;
3177}
3178
3179static int ipv6_generate_stable_address(struct in6_addr *address,
3180 u8 dad_count,
3181 const struct inet6_dev *idev)
3182{
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01003183 static DEFINE_SPINLOCK(lock);
Eric Biggers6b0b0fa2020-05-02 11:24:25 -07003184 static __u32 digest[SHA1_DIGEST_WORDS];
3185 static __u32 workspace[SHA1_WORKSPACE_WORDS];
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01003186
3187 static union {
Eric Biggers6b0b0fa2020-05-02 11:24:25 -07003188 char __data[SHA1_BLOCK_SIZE];
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01003189 struct {
3190 struct in6_addr secret;
Hannes Frederic Sowaff402172015-03-24 11:05:28 +01003191 __be32 prefix[2];
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01003192 unsigned char hwaddr[MAX_ADDR_LEN];
3193 u8 dad_count;
3194 } __packed;
3195 } data;
3196
3197 struct in6_addr secret;
3198 struct in6_addr temp;
3199 struct net *net = dev_net(idev->dev);
3200
3201 BUILD_BUG_ON(sizeof(data.__data) != sizeof(data));
3202
3203 if (idev->cnf.stable_secret.initialized)
3204 secret = idev->cnf.stable_secret.secret;
3205 else if (net->ipv6.devconf_dflt->stable_secret.initialized)
3206 secret = net->ipv6.devconf_dflt->stable_secret.secret;
3207 else
3208 return -1;
3209
3210retry:
3211 spin_lock_bh(&lock);
3212
Eric Biggers6b0b0fa2020-05-02 11:24:25 -07003213 sha1_init(digest);
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01003214 memset(&data, 0, sizeof(data));
3215 memset(workspace, 0, sizeof(workspace));
3216 memcpy(data.hwaddr, idev->dev->perm_addr, idev->dev->addr_len);
Hannes Frederic Sowaff402172015-03-24 11:05:28 +01003217 data.prefix[0] = address->s6_addr32[0];
3218 data.prefix[1] = address->s6_addr32[1];
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01003219 data.secret = secret;
3220 data.dad_count = dad_count;
3221
Eric Biggers6b0b0fa2020-05-02 11:24:25 -07003222 sha1_transform(digest, data.__data, workspace);
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01003223
3224 temp = *address;
Hannes Frederic Sowaff402172015-03-24 11:05:28 +01003225 temp.s6_addr32[2] = (__force __be32)digest[0];
3226 temp.s6_addr32[3] = (__force __be32)digest[1];
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01003227
3228 spin_unlock_bh(&lock);
3229
3230 if (ipv6_reserved_interfaceid(temp)) {
3231 dad_count++;
Hannes Frederic Sowa1855b7c2015-03-23 23:36:05 +01003232 if (dad_count > dev_net(idev->dev)->ipv6.sysctl.idgen_retries)
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01003233 return -1;
3234 goto retry;
3235 }
3236
3237 *address = temp;
3238 return 0;
3239}
3240
Bjørn Morkcc9da6c2015-12-16 16:44:38 +01003241static void ipv6_gen_mode_random_init(struct inet6_dev *idev)
3242{
3243 struct ipv6_stable_secret *s = &idev->cnf.stable_secret;
3244
3245 if (s->initialized)
3246 return;
3247 s = &idev->cnf.stable_secret;
3248 get_random_bytes(&s->secret, sizeof(s->secret));
3249 s->initialized = true;
3250}
3251
Jiri Pirkobc91b0f2014-07-11 21:10:18 +02003252static void addrconf_addr_gen(struct inet6_dev *idev, bool prefix_route)
3253{
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01003254 struct in6_addr addr;
Jiri Pirkobc91b0f2014-07-11 21:10:18 +02003255
David Ahernca254492015-10-12 11:47:10 -07003256 /* no link local addresses on L3 master devices */
3257 if (netif_is_l3_master(idev->dev))
3258 return;
3259
Jarod Wilson744fdc822020-03-30 11:22:19 -04003260 /* no link local addresses on devices flagged as slaves */
3261 if (idev->dev->flags & IFF_SLAVE)
3262 return;
3263
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01003264 ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0);
3265
Felix Jiad35a00b2017-01-26 16:59:17 +13003266 switch (idev->cnf.addr_gen_mode) {
Bjørn Morkcc9da6c2015-12-16 16:44:38 +01003267 case IN6_ADDR_GEN_MODE_RANDOM:
3268 ipv6_gen_mode_random_init(idev);
Joe Perchesa8eceea2020-03-12 15:50:22 -07003269 fallthrough;
Bjørn Morkcc9da6c2015-12-16 16:44:38 +01003270 case IN6_ADDR_GEN_MODE_STABLE_PRIVACY:
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01003271 if (!ipv6_generate_stable_address(&addr, 0, idev))
Hannes Frederic Sowa64236f32015-03-23 23:36:02 +01003272 addrconf_add_linklocal(idev, &addr,
3273 IFA_F_STABLE_PRIVACY);
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01003274 else if (prefix_route)
David Ahern8308f3f2018-05-27 08:09:58 -07003275 addrconf_prefix_route(&addr, 64, 0, idev->dev,
David Ahernacb54e32018-04-17 17:33:22 -07003276 0, 0, GFP_KERNEL);
Bjørn Morkcc9da6c2015-12-16 16:44:38 +01003277 break;
3278 case IN6_ADDR_GEN_MODE_EUI64:
Jiri Pirkobc91b0f2014-07-11 21:10:18 +02003279 /* addrconf_add_linklocal also adds a prefix_route and we
3280 * only need to care about prefix routes if ipv6_generate_eui64
3281 * couldn't generate one.
3282 */
3283 if (ipv6_generate_eui64(addr.s6_addr + 8, idev->dev) == 0)
Hannes Frederic Sowa64236f32015-03-23 23:36:02 +01003284 addrconf_add_linklocal(idev, &addr, 0);
Jiri Pirkobc91b0f2014-07-11 21:10:18 +02003285 else if (prefix_route)
David Ahern8308f3f2018-05-27 08:09:58 -07003286 addrconf_prefix_route(&addr, 64, 0, idev->dev,
David Ahern27b10602018-04-18 15:39:06 -07003287 0, 0, GFP_KERNEL);
Bjørn Morkcc9da6c2015-12-16 16:44:38 +01003288 break;
3289 case IN6_ADDR_GEN_MODE_NONE:
3290 default:
3291 /* will not add any link local address */
3292 break;
Jiri Pirkobc91b0f2014-07-11 21:10:18 +02003293 }
3294}
3295
Linus Torvalds1da177e2005-04-16 15:20:36 -07003296static void addrconf_dev_config(struct net_device *dev)
3297{
Eldad Zack8e5e8f32012-04-01 07:49:08 +00003298 struct inet6_dev *idev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003299
3300 ASSERT_RTNL();
3301
Herbert Xu74235a22007-06-14 13:02:55 -07003302 if ((dev->type != ARPHRD_ETHER) &&
3303 (dev->type != ARPHRD_FDDI) &&
Herbert Xu74235a22007-06-14 13:02:55 -07003304 (dev->type != ARPHRD_ARCNET) &&
alex.bluesman.smirnov@gmail.com06a4c1c2012-05-10 03:25:52 +00003305 (dev->type != ARPHRD_INFINIBAND) &&
Nicolas Dichtele8377352013-08-20 12:16:06 +02003306 (dev->type != ARPHRD_IEEE1394) &&
Jukka Rissanene74bccb82013-12-11 17:05:36 +02003307 (dev->type != ARPHRD_TUNNEL6) &&
Bjørn Morkcc9da6c2015-12-16 16:44:38 +01003308 (dev->type != ARPHRD_6LOWPAN) &&
Felix Jia45ce0fd2017-01-26 16:59:18 +13003309 (dev->type != ARPHRD_IP6GRE) &&
3310 (dev->type != ARPHRD_IPGRE) &&
3311 (dev->type != ARPHRD_TUNNEL) &&
Subash Abhinov Kasiviswanathan9deb4412018-06-04 19:26:07 -06003312 (dev->type != ARPHRD_NONE) &&
3313 (dev->type != ARPHRD_RAWIP)) {
Herbert Xu74235a22007-06-14 13:02:55 -07003314 /* Alas, we support only Ethernet autoconfiguration. */
Hangbin Liu60380482020-03-10 15:27:37 +08003315 idev = __in6_dev_get(dev);
3316 if (!IS_ERR_OR_NULL(idev) && dev->flags & IFF_UP &&
3317 dev->flags & IFF_MULTICAST)
3318 ipv6_mc_up(idev);
Herbert Xu74235a22007-06-14 13:02:55 -07003319 return;
3320 }
3321
Linus Torvalds1da177e2005-04-16 15:20:36 -07003322 idev = addrconf_add_dev(dev);
Brian Haley64e724f2010-07-20 10:34:30 +00003323 if (IS_ERR(idev))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003324 return;
3325
Bjørn Morkcc9da6c2015-12-16 16:44:38 +01003326 /* this device type has no EUI support */
3327 if (dev->type == ARPHRD_NONE &&
Felix Jiad35a00b2017-01-26 16:59:17 +13003328 idev->cnf.addr_gen_mode == IN6_ADDR_GEN_MODE_EUI64)
3329 idev->cnf.addr_gen_mode = IN6_ADDR_GEN_MODE_RANDOM;
Bjørn Morkcc9da6c2015-12-16 16:44:38 +01003330
Jiri Pirkobc91b0f2014-07-11 21:10:18 +02003331 addrconf_addr_gen(idev, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003332}
3333
Amerigo Wang07a93622012-10-29 16:23:10 +00003334#if IS_ENABLED(CONFIG_IPV6_SIT)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003335static void addrconf_sit_config(struct net_device *dev)
3336{
3337 struct inet6_dev *idev;
3338
3339 ASSERT_RTNL();
3340
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09003341 /*
3342 * Configure the tunnel with one of our IPv4
3343 * addresses... we should configure all of
Linus Torvalds1da177e2005-04-16 15:20:36 -07003344 * our v4 addrs in the tunnel
3345 */
3346
Ian Morrise5d08d72014-11-23 21:28:43 +00003347 idev = ipv6_find_idev(dev);
Sabrina Dubrocadb0b99f2019-08-23 15:44:36 +02003348 if (IS_ERR(idev)) {
Joe Perches91df42b2012-05-15 14:11:54 +00003349 pr_debug("%s: add_dev failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003350 return;
3351 }
3352
Fred L. Templinc7dc89c2007-11-29 22:11:40 +11003353 if (dev->priv_flags & IFF_ISATAP) {
Jiri Pirkobc91b0f2014-07-11 21:10:18 +02003354 addrconf_addr_gen(idev, false);
Fred L. Templinc7dc89c2007-11-29 22:11:40 +11003355 return;
3356 }
3357
Linus Torvalds1da177e2005-04-16 15:20:36 -07003358 sit_add_v4_addrs(idev);
3359
Nicolas Dichtel62b54dd2012-10-01 23:19:14 +00003360 if (dev->flags&IFF_POINTOPOINT)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361 addrconf_add_mroute(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003362}
Joerg Roedel0be669b2006-10-10 14:49:53 -07003363#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003364
Amerigo Wang07a93622012-10-29 16:23:10 +00003365#if IS_ENABLED(CONFIG_NET_IPGRE)
stephen hemmingeraee80b52011-06-08 10:44:30 +00003366static void addrconf_gre_config(struct net_device *dev)
3367{
3368 struct inet6_dev *idev;
stephen hemmingeraee80b52011-06-08 10:44:30 +00003369
stephen hemmingeraee80b52011-06-08 10:44:30 +00003370 ASSERT_RTNL();
3371
Ian Morrise5d08d72014-11-23 21:28:43 +00003372 idev = ipv6_find_idev(dev);
Sabrina Dubrocadb0b99f2019-08-23 15:44:36 +02003373 if (IS_ERR(idev)) {
Joe Perches91df42b2012-05-15 14:11:54 +00003374 pr_debug("%s: add_dev failed\n", __func__);
stephen hemmingeraee80b52011-06-08 10:44:30 +00003375 return;
3376 }
3377
Jiri Pirkobc91b0f2014-07-11 21:10:18 +02003378 addrconf_addr_gen(idev, true);
Hannes Frederic Sowad9e4ce62015-10-08 18:19:39 +02003379 if (dev->flags & IFF_POINTOPOINT)
3380 addrconf_add_mroute(dev);
stephen hemmingeraee80b52011-06-08 10:44:30 +00003381}
3382#endif
3383
David Ahernafb1d4b52018-04-17 17:33:11 -07003384static int fixup_permanent_addr(struct net *net,
3385 struct inet6_dev *idev,
David Ahernf1705ec2016-02-24 09:25:37 -08003386 struct inet6_ifaddr *ifp)
3387{
David Ahern93c2fb22018-04-18 15:38:59 -07003388 /* !fib6_node means the host route was removed from the
David Ahern8048ced2017-04-25 09:17:29 -07003389 * FIB, for example, if 'lo' device is taken down. In that
3390 * case regenerate the host route.
3391 */
David Ahern93c2fb22018-04-18 15:38:59 -07003392 if (!ifp->rt || !ifp->rt->fib6_node) {
David Ahern360a9882018-04-18 15:39:00 -07003393 struct fib6_info *f6i, *prev;
David Ahernf1705ec2016-02-24 09:25:37 -08003394
David Ahern360a9882018-04-18 15:39:00 -07003395 f6i = addrconf_f6i_alloc(net, idev, &ifp->addr, false,
3396 GFP_ATOMIC);
3397 if (IS_ERR(f6i))
3398 return PTR_ERR(f6i);
David Ahernf1705ec2016-02-24 09:25:37 -08003399
David Ahern8048ced2017-04-25 09:17:29 -07003400 /* ifp->rt can be accessed outside of rtnl */
3401 spin_lock(&ifp->lock);
3402 prev = ifp->rt;
David Ahern360a9882018-04-18 15:39:00 -07003403 ifp->rt = f6i;
David Ahern8048ced2017-04-25 09:17:29 -07003404 spin_unlock(&ifp->lock);
3405
David Ahern93531c62018-04-17 17:33:25 -07003406 fib6_info_release(prev);
David Ahernf1705ec2016-02-24 09:25:37 -08003407 }
3408
3409 if (!(ifp->flags & IFA_F_NOPREFIXROUTE)) {
3410 addrconf_prefix_route(&ifp->addr, ifp->prefix_len,
David Ahern8308f3f2018-05-27 08:09:58 -07003411 ifp->rt_priority, idev->dev, 0, 0,
3412 GFP_ATOMIC);
David Ahernf1705ec2016-02-24 09:25:37 -08003413 }
3414
David Ahern6d717132017-05-02 14:43:44 -07003415 if (ifp->state == INET6_IFADDR_STATE_PREDAD)
3416 addrconf_dad_start(ifp);
David Ahernf1705ec2016-02-24 09:25:37 -08003417
3418 return 0;
3419}
3420
David Ahernafb1d4b52018-04-17 17:33:11 -07003421static void addrconf_permanent_addr(struct net *net, struct net_device *dev)
David Ahernf1705ec2016-02-24 09:25:37 -08003422{
3423 struct inet6_ifaddr *ifp, *tmp;
3424 struct inet6_dev *idev;
3425
3426 idev = __in6_dev_get(dev);
3427 if (!idev)
3428 return;
3429
3430 write_lock_bh(&idev->lock);
3431
3432 list_for_each_entry_safe(ifp, tmp, &idev->addr_list, if_list) {
3433 if ((ifp->flags & IFA_F_PERMANENT) &&
David Ahernafb1d4b52018-04-17 17:33:11 -07003434 fixup_permanent_addr(net, idev, ifp) < 0) {
David Ahernf1705ec2016-02-24 09:25:37 -08003435 write_unlock_bh(&idev->lock);
Eric Dumazete669b862017-10-30 22:47:09 -07003436 in6_ifa_hold(ifp);
David Ahernf1705ec2016-02-24 09:25:37 -08003437 ipv6_del_addr(ifp);
3438 write_lock_bh(&idev->lock);
3439
3440 net_info_ratelimited("%s: Failed to add prefix route for address %pI6c; dropping\n",
3441 idev->dev->name, &ifp->addr);
3442 }
3443 }
3444
3445 write_unlock_bh(&idev->lock);
3446}
3447
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09003448static int addrconf_notify(struct notifier_block *this, unsigned long event,
Jiri Pirko351638e2013-05-28 01:30:21 +00003449 void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003450{
Jiri Pirko351638e2013-05-28 01:30:21 +00003451 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
Hangbin Liu896585d2018-11-21 21:52:33 +08003452 struct netdev_notifier_change_info *change_info;
David Ahern4f7f34e2016-04-07 11:10:41 -07003453 struct netdev_notifier_changeupper_info *info;
Eric Dumazet748e2d92012-08-22 21:50:59 +00003454 struct inet6_dev *idev = __in6_dev_get(dev);
WANG Cong60abc0b2017-06-21 14:34:58 -07003455 struct net *net = dev_net(dev);
YOSHIFUJI Hideakic5e33bd2005-12-21 22:57:44 +09003456 int run_pending = 0;
Herbert Xub217d612007-07-30 17:04:52 -07003457 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003458
Stephen Hemmingere21e8462010-03-20 16:09:01 -07003459 switch (event) {
YOSHIFUJI Hideaki45ba9dd2007-02-15 02:07:27 +09003460 case NETDEV_REGISTER:
Herbert Xu74235a22007-06-14 13:02:55 -07003461 if (!idev && dev->mtu >= IPV6_MIN_MTU) {
YOSHIFUJI Hideaki45ba9dd2007-02-15 02:07:27 +09003462 idev = ipv6_add_dev(dev);
WANG Conga317a2f2014-07-25 15:25:09 -07003463 if (IS_ERR(idev))
3464 return notifier_from_errno(PTR_ERR(idev));
YOSHIFUJI Hideaki45ba9dd2007-02-15 02:07:27 +09003465 }
3466 break;
Stephen Hemmingerbcdd5532010-03-20 16:08:18 -07003467
Alexander Duyckb7b0b1d2015-10-26 11:06:33 -07003468 case NETDEV_CHANGEMTU:
3469 /* if MTU under IPV6_MIN_MTU stop IPv6 on this interface. */
3470 if (dev->mtu < IPV6_MIN_MTU) {
WANG Cong60abc0b2017-06-21 14:34:58 -07003471 addrconf_ifdown(dev, dev != net->loopback_dev);
Alexander Duyckb7b0b1d2015-10-26 11:06:33 -07003472 break;
3473 }
3474
3475 if (idev) {
3476 rt6_mtu_change(dev, dev->mtu);
3477 idev->cnf.mtu6 = dev->mtu;
3478 break;
3479 }
3480
3481 /* allocate new idev */
3482 idev = ipv6_add_dev(dev);
3483 if (IS_ERR(idev))
3484 break;
3485
3486 /* device is still not ready */
3487 if (!(idev->if_flags & IF_READY))
3488 break;
3489
3490 run_pending = 1;
Joe Perchesa8eceea2020-03-12 15:50:22 -07003491 fallthrough;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003492 case NETDEV_UP:
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003493 case NETDEV_CHANGE:
Jay Vosburghc2edacf2007-07-09 10:42:47 -07003494 if (dev->flags & IFF_SLAVE)
3495 break;
3496
WANG Cong3ce62a82014-09-11 15:07:16 -07003497 if (idev && idev->cnf.disable_ipv6)
3498 break;
3499
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003500 if (event == NETDEV_UP) {
David Ahern38bd10c2016-04-21 20:56:12 -07003501 /* restore routes for permanent addresses */
David Ahernafb1d4b52018-04-17 17:33:11 -07003502 addrconf_permanent_addr(net, dev);
David Ahern38bd10c2016-04-21 20:56:12 -07003503
Mike Manning1f372c72017-09-25 22:01:36 +01003504 if (!addrconf_link_ready(dev)) {
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003505 /* device is not ready yet. */
Lubomir Rintel7c62b8d2019-01-21 14:54:20 +01003506 pr_debug("ADDRCONF(NETDEV_UP): %s: link is not ready\n",
3507 dev->name);
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003508 break;
3509 }
Kristian Slavov99081042006-02-08 16:10:53 -08003510
Evgeniy Polyakovd31c7b82007-11-30 23:36:08 +11003511 if (!idev && dev->mtu >= IPV6_MIN_MTU)
3512 idev = ipv6_add_dev(dev);
3513
WANG Conga317a2f2014-07-25 15:25:09 -07003514 if (!IS_ERR_OR_NULL(idev)) {
Kristian Slavov99081042006-02-08 16:10:53 -08003515 idev->if_flags |= IF_READY;
Benjamin Therye3ec6cf2008-11-05 01:43:57 -08003516 run_pending = 1;
3517 }
Alexander Duyckb7b0b1d2015-10-26 11:06:33 -07003518 } else if (event == NETDEV_CHANGE) {
Mike Manning1f372c72017-09-25 22:01:36 +01003519 if (!addrconf_link_ready(dev)) {
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003520 /* device is still not ready. */
Ido Schimmel27c6fa72018-01-07 12:45:05 +02003521 rt6_sync_down_dev(dev, event);
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003522 break;
3523 }
3524
Hangbin Liu896585d2018-11-21 21:52:33 +08003525 if (!IS_ERR_OR_NULL(idev)) {
Linus Lüssinga088d1d2017-02-03 08:11:03 +01003526 if (idev->if_flags & IF_READY) {
3527 /* device is already configured -
3528 * but resend MLD reports, we might
3529 * have roamed and need to update
3530 * multicast snooping switches
3531 */
3532 ipv6_mc_up(idev);
Hangbin Liu896585d2018-11-21 21:52:33 +08003533 change_info = ptr;
3534 if (change_info->flags_changed & IFF_NOARP)
3535 addrconf_dad_run(idev, true);
Ido Schimmel27c6fa72018-01-07 12:45:05 +02003536 rt6_sync_up(dev, RTNH_F_LINKDOWN);
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003537 break;
Linus Lüssinga088d1d2017-02-03 08:11:03 +01003538 }
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003539 idev->if_flags |= IF_READY;
3540 }
3541
Joe Perchesf3213832012-05-15 14:11:53 +00003542 pr_info("ADDRCONF(NETDEV_CHANGE): %s: link becomes ready\n",
3543 dev->name);
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003544
YOSHIFUJI Hideakic5e33bd2005-12-21 22:57:44 +09003545 run_pending = 1;
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003546 }
3547
Stephen Hemmingere21e8462010-03-20 16:09:01 -07003548 switch (dev->type) {
Amerigo Wang07a93622012-10-29 16:23:10 +00003549#if IS_ENABLED(CONFIG_IPV6_SIT)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003550 case ARPHRD_SIT:
3551 addrconf_sit_config(dev);
3552 break;
Joerg Roedel0be669b2006-10-10 14:49:53 -07003553#endif
Amerigo Wang07a93622012-10-29 16:23:10 +00003554#if IS_ENABLED(CONFIG_NET_IPGRE)
stephen hemmingeraee80b52011-06-08 10:44:30 +00003555 case ARPHRD_IPGRE:
3556 addrconf_gre_config(dev);
3557 break;
3558#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003559 case ARPHRD_LOOPBACK:
3560 init_loopback(dev);
3561 break;
3562
3563 default:
3564 addrconf_dev_config(dev);
3565 break;
Stephen Hemminger3ff50b72007-04-20 17:09:22 -07003566 }
Stephen Hemmingerbcdd5532010-03-20 16:08:18 -07003567
WANG Conga317a2f2014-07-25 15:25:09 -07003568 if (!IS_ERR_OR_NULL(idev)) {
YOSHIFUJI Hideakic5e33bd2005-12-21 22:57:44 +09003569 if (run_pending)
Hangbin Liu896585d2018-11-21 21:52:33 +08003570 addrconf_dad_run(idev, false);
YOSHIFUJI Hideakic5e33bd2005-12-21 22:57:44 +09003571
Ido Schimmel2127d952018-01-07 12:45:03 +02003572 /* Device has an address by now */
3573 rt6_sync_up(dev, RTNH_F_DEAD);
3574
Stephen Hemmingerbcdd5532010-03-20 16:08:18 -07003575 /*
3576 * If the MTU changed during the interface down,
3577 * when the interface up, the changed MTU must be
3578 * reflected in the idev as well as routers.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003579 */
Stephen Hemmingerbcdd5532010-03-20 16:08:18 -07003580 if (idev->cnf.mtu6 != dev->mtu &&
3581 dev->mtu >= IPV6_MIN_MTU) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003582 rt6_mtu_change(dev, dev->mtu);
3583 idev->cnf.mtu6 = dev->mtu;
3584 }
3585 idev->tstamp = jiffies;
3586 inet6_ifinfo_notify(RTM_NEWLINK, idev);
Stephen Hemmingerbcdd5532010-03-20 16:08:18 -07003587
3588 /*
3589 * If the changed mtu during down is lower than
3590 * IPV6_MIN_MTU stop IPv6 on this interface.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003591 */
3592 if (dev->mtu < IPV6_MIN_MTU)
WANG Cong60abc0b2017-06-21 14:34:58 -07003593 addrconf_ifdown(dev, dev != net->loopback_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003594 }
3595 break;
3596
Linus Torvalds1da177e2005-04-16 15:20:36 -07003597 case NETDEV_DOWN:
3598 case NETDEV_UNREGISTER:
3599 /*
3600 * Remove all addresses from this interface.
3601 */
3602 addrconf_ifdown(dev, event != NETDEV_DOWN);
3603 break;
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003604
Linus Torvalds1da177e2005-04-16 15:20:36 -07003605 case NETDEV_CHANGENAME:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003606 if (idev) {
Stephen Hemminger5632c512007-04-28 21:16:39 -07003607 snmp6_unregister_dev(idev);
Pavel Emelyanov408c4762008-01-10 17:41:21 -08003608 addrconf_sysctl_unregister(idev);
WANG Conga317a2f2014-07-25 15:25:09 -07003609 err = addrconf_sysctl_register(idev);
Herbert Xub217d612007-07-30 17:04:52 -07003610 if (err)
3611 return notifier_from_errno(err);
WANG Conga317a2f2014-07-25 15:25:09 -07003612 err = snmp6_register_dev(idev);
3613 if (err) {
3614 addrconf_sysctl_unregister(idev);
3615 return notifier_from_errno(err);
3616 }
Stephen Hemminger5632c512007-04-28 21:16:39 -07003617 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003618 break;
Stephen Hemmingerbcdd5532010-03-20 16:08:18 -07003619
Jiri Pirko93d9b7d2010-03-10 10:28:56 +00003620 case NETDEV_PRE_TYPE_CHANGE:
3621 case NETDEV_POST_TYPE_CHANGE:
Andrew Lunn3ef09522015-12-03 21:12:32 +01003622 if (idev)
3623 addrconf_type_change(dev, event);
Moni Shoua75c78502009-09-15 02:37:40 -07003624 break;
David Ahern4f7f34e2016-04-07 11:10:41 -07003625
3626 case NETDEV_CHANGEUPPER:
3627 info = ptr;
3628
3629 /* flush all routes if dev is linked to or unlinked from
3630 * an L3 master device (e.g., VRF)
3631 */
3632 if (info->upper_dev && netif_is_l3_master(info->upper_dev))
3633 addrconf_ifdown(dev, 0);
Stephen Hemminger3ff50b72007-04-20 17:09:22 -07003634 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003635
3636 return NOTIFY_OK;
3637}
3638
3639/*
3640 * addrconf module should be notified of a device going up
3641 */
3642static struct notifier_block ipv6_dev_notf = {
3643 .notifier_call = addrconf_notify,
WANG Cong242d3a42017-05-08 10:12:13 -07003644 .priority = ADDRCONF_NOTIFY_PRIORITY,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003645};
3646
Jiri Pirko93d9b7d2010-03-10 10:28:56 +00003647static void addrconf_type_change(struct net_device *dev, unsigned long event)
Moni Shoua75c78502009-09-15 02:37:40 -07003648{
3649 struct inet6_dev *idev;
3650 ASSERT_RTNL();
3651
3652 idev = __in6_dev_get(dev);
3653
Jiri Pirko93d9b7d2010-03-10 10:28:56 +00003654 if (event == NETDEV_POST_TYPE_CHANGE)
Moni Shoua75c78502009-09-15 02:37:40 -07003655 ipv6_mc_remap(idev);
Jiri Pirko93d9b7d2010-03-10 10:28:56 +00003656 else if (event == NETDEV_PRE_TYPE_CHANGE)
Moni Shoua75c78502009-09-15 02:37:40 -07003657 ipv6_mc_unmap(idev);
3658}
3659
David Ahern70af9212016-04-08 12:01:21 -07003660static bool addr_is_local(const struct in6_addr *addr)
3661{
3662 return ipv6_addr_type(addr) &
3663 (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK);
3664}
3665
Linus Torvalds1da177e2005-04-16 15:20:36 -07003666static int addrconf_ifdown(struct net_device *dev, int how)
3667{
Ido Schimmel4c981e22018-01-07 12:45:04 +02003668 unsigned long event = how ? NETDEV_UNREGISTER : NETDEV_DOWN;
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09003669 struct net *net = dev_net(dev);
stephen hemminger502a2ff2010-03-17 20:31:13 +00003670 struct inet6_dev *idev;
David Ahernf1705ec2016-02-24 09:25:37 -08003671 struct inet6_ifaddr *ifa, *tmp;
Ivan Vecera0aef78a2018-04-24 19:51:29 +02003672 bool keep_addr = false;
David S. Miller73a8bd72011-01-23 23:27:15 -08003673 int state, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003674
3675 ASSERT_RTNL();
3676
Ido Schimmel4c981e22018-01-07 12:45:04 +02003677 rt6_disable_ip(dev, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003678
3679 idev = __in6_dev_get(dev);
Ian Morris63159f22015-03-29 14:00:04 +01003680 if (!idev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003681 return -ENODEV;
3682
Stephen Hemmingerbcdd5532010-03-20 16:08:18 -07003683 /*
3684 * Step 1: remove reference to ipv6 device from parent device.
3685 * Do not dev_put!
Linus Torvalds1da177e2005-04-16 15:20:36 -07003686 */
Denis V. Lunev439e2382008-04-03 13:30:17 -07003687 if (how) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003688 idev->dead = 1;
YOSHIFUJI Hideaki8814c4b2006-09-22 14:44:24 -07003689
3690 /* protected by rtnl_lock */
Stephen Hemmingera9b3cd72011-08-01 16:19:00 +00003691 RCU_INIT_POINTER(dev->ip6_ptr, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003692
3693 /* Step 1.5: remove snmp6 entry */
3694 snmp6_unregister_dev(idev);
3695
3696 }
3697
David Ahernf1705ec2016-02-24 09:25:37 -08003698 /* combine the user config with event to determine if permanent
3699 * addresses are to be removed from address hash table
3700 */
Ivan Vecera0aef78a2018-04-24 19:51:29 +02003701 if (!how && !idev->cnf.disable_ipv6) {
3702 /* aggregate the system setting and interface setting */
3703 int _keep_addr = net->ipv6.devconf_all->keep_addr_on_down;
3704
3705 if (!_keep_addr)
3706 _keep_addr = idev->cnf.keep_addr_on_down;
3707
3708 keep_addr = (_keep_addr > 0);
3709 }
David Ahernf1705ec2016-02-24 09:25:37 -08003710
David S. Miller73a8bd72011-01-23 23:27:15 -08003711 /* Step 2: clear hash table */
3712 for (i = 0; i < IN6_ADDR_HSIZE; i++) {
3713 struct hlist_head *h = &inet6_addr_lst[i];
David S. Miller73a8bd72011-01-23 23:27:15 -08003714
3715 spin_lock_bh(&addrconf_hash_lock);
Ian Morris67ba4152014-08-24 21:53:10 +01003716restart:
Sasha Levinb67bfe02013-02-27 17:06:00 -08003717 hlist_for_each_entry_rcu(ifa, h, addr_lst) {
David S. Miller73a8bd72011-01-23 23:27:15 -08003718 if (ifa->idev == idev) {
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01003719 addrconf_del_dad_work(ifa);
David Ahernf1705ec2016-02-24 09:25:37 -08003720 /* combined flag + permanent flag decide if
3721 * address is retained on a down event
3722 */
3723 if (!keep_addr ||
David Ahern70af9212016-04-08 12:01:21 -07003724 !(ifa->flags & IFA_F_PERMANENT) ||
3725 addr_is_local(&ifa->addr)) {
David Ahernf1705ec2016-02-24 09:25:37 -08003726 hlist_del_init_rcu(&ifa->addr_lst);
3727 goto restart;
3728 }
David S. Miller73a8bd72011-01-23 23:27:15 -08003729 }
3730 }
3731 spin_unlock_bh(&addrconf_hash_lock);
3732 }
3733
Linus Torvalds1da177e2005-04-16 15:20:36 -07003734 write_lock_bh(&idev->lock);
3735
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02003736 addrconf_del_rs_timer(idev);
3737
Stephen Hemmingerbcdd5532010-03-20 16:08:18 -07003738 /* Step 2: clear flags for stateless addrconf */
Denis V. Lunev439e2382008-04-03 13:30:17 -07003739 if (!how)
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003740 idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003741
Stephen Hemmingerbcdd5532010-03-20 16:08:18 -07003742 /* Step 3: clear tempaddr list */
stephen hemminger372e6c82010-03-17 20:31:09 +00003743 while (!list_empty(&idev->tempaddr_list)) {
3744 ifa = list_first_entry(&idev->tempaddr_list,
3745 struct inet6_ifaddr, tmp_list);
3746 list_del(&ifa->tmp_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003747 write_unlock_bh(&idev->lock);
3748 spin_lock_bh(&ifa->lock);
3749
3750 if (ifa->ifpub) {
3751 in6_ifa_put(ifa->ifpub);
3752 ifa->ifpub = NULL;
3753 }
3754 spin_unlock_bh(&ifa->lock);
3755 in6_ifa_put(ifa);
3756 write_lock_bh(&idev->lock);
3757 }
stephen hemminger8f37ada2010-03-03 08:19:59 +00003758
David Ahernf1705ec2016-02-24 09:25:37 -08003759 list_for_each_entry_safe(ifa, tmp, &idev->addr_list, if_list) {
David Ahern8d1c8022018-04-17 17:33:26 -07003760 struct fib6_info *rt = NULL;
Rabin Vincenta2d6cbb2017-04-10 08:36:39 +02003761 bool keep;
David Ahern38bd10c2016-04-21 20:56:12 -07003762
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01003763 addrconf_del_dad_work(ifa);
stephen hemminger84e8b802010-03-02 13:32:46 +00003764
Rabin Vincenta2d6cbb2017-04-10 08:36:39 +02003765 keep = keep_addr && (ifa->flags & IFA_F_PERMANENT) &&
3766 !addr_is_local(&ifa->addr);
Rabin Vincenta2d6cbb2017-04-10 08:36:39 +02003767
David S. Miller73a8bd72011-01-23 23:27:15 -08003768 write_unlock_bh(&idev->lock);
Hannes Frederic Sowa8e8e6762015-03-23 23:36:03 +01003769 spin_lock_bh(&ifa->lock);
David Ahernf1705ec2016-02-24 09:25:37 -08003770
Rabin Vincenta2d6cbb2017-04-10 08:36:39 +02003771 if (keep) {
David Ahernf1705ec2016-02-24 09:25:37 -08003772 /* set state to skip the notifier below */
3773 state = INET6_IFADDR_STATE_DEAD;
David Ahern6d717132017-05-02 14:43:44 -07003774 ifa->state = INET6_IFADDR_STATE_PREDAD;
David Ahernf1705ec2016-02-24 09:25:37 -08003775 if (!(ifa->flags & IFA_F_NODAD))
3776 ifa->flags |= IFA_F_TENTATIVE;
David Ahern38bd10c2016-04-21 20:56:12 -07003777
3778 rt = ifa->rt;
3779 ifa->rt = NULL;
David Ahernf1705ec2016-02-24 09:25:37 -08003780 } else {
3781 state = ifa->state;
3782 ifa->state = INET6_IFADDR_STATE_DEAD;
David Ahernf1705ec2016-02-24 09:25:37 -08003783 }
3784
Hannes Frederic Sowa8e8e6762015-03-23 23:36:03 +01003785 spin_unlock_bh(&ifa->lock);
stephen hemminger84e8b802010-03-02 13:32:46 +00003786
David Ahern38bd10c2016-04-21 20:56:12 -07003787 if (rt)
Roopa Prabhu11dd74b2020-04-27 13:56:45 -07003788 ip6_del_rt(net, rt, false);
David Ahern38bd10c2016-04-21 20:56:12 -07003789
David S. Miller73a8bd72011-01-23 23:27:15 -08003790 if (state != INET6_IFADDR_STATE_DEAD) {
3791 __ipv6_ifa_notify(RTM_DELADDR, ifa);
Cong Wangf88c91d2013-04-14 23:18:43 +08003792 inet6addr_notifier_call_chain(NETDEV_DOWN, ifa);
Mike Manningea06f712016-07-22 18:32:11 +01003793 } else {
3794 if (idev->cnf.forwarding)
3795 addrconf_leave_anycast(ifa);
3796 addrconf_leave_solict(ifa->idev, &ifa->addr);
stephen hemminger27bdb2a2010-04-12 05:41:32 +00003797 }
stephen hemminger8f37ada2010-03-03 08:19:59 +00003798
David S. Miller73a8bd72011-01-23 23:27:15 -08003799 write_lock_bh(&idev->lock);
Eric Dumazet8ef802a2017-10-07 19:30:23 -07003800 if (!keep) {
3801 list_del_rcu(&ifa->if_list);
3802 in6_ifa_put(ifa);
3803 }
David S. Miller73a8bd72011-01-23 23:27:15 -08003804 }
stephen hemminger8f37ada2010-03-03 08:19:59 +00003805
Linus Torvalds1da177e2005-04-16 15:20:36 -07003806 write_unlock_bh(&idev->lock);
3807
Sabrina Dubroca381f4dc2014-09-10 23:23:02 +02003808 /* Step 5: Discard anycast and multicast list */
3809 if (how) {
3810 ipv6_ac_destroy_dev(idev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003811 ipv6_mc_destroy_dev(idev);
Sabrina Dubroca381f4dc2014-09-10 23:23:02 +02003812 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003813 ipv6_mc_down(idev);
Sabrina Dubroca381f4dc2014-09-10 23:23:02 +02003814 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003815
Linus Torvalds1da177e2005-04-16 15:20:36 -07003816 idev->tstamp = jiffies;
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09003817
Stephen Hemmingerbcdd5532010-03-20 16:08:18 -07003818 /* Last: Shot the device (if unregistered) */
Denis V. Lunev439e2382008-04-03 13:30:17 -07003819 if (how) {
Pavel Emelyanov408c4762008-01-10 17:41:21 -08003820 addrconf_sysctl_unregister(idev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003821 neigh_parms_release(&nd_tbl, idev->nd_parms);
3822 neigh_ifdown(&nd_tbl, dev);
3823 in6_dev_put(idev);
3824 }
3825 return 0;
3826}
3827
Kees Cooke99e88a2017-10-16 14:43:17 -07003828static void addrconf_rs_timer(struct timer_list *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003829{
Kees Cooke99e88a2017-10-16 14:43:17 -07003830 struct inet6_dev *idev = from_timer(idev, t, rs_timer);
Cong Wangcaf92bc2013-08-31 13:44:32 +08003831 struct net_device *dev = idev->dev;
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02003832 struct in6_addr lladdr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003833
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02003834 write_lock(&idev->lock);
stephen hemminger5b2a1952010-03-02 13:32:45 +00003835 if (idev->dead || !(idev->if_flags & IF_READY))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003836 goto out;
3837
Shmulik Ladkani9ba2add2012-12-02 01:44:53 +00003838 if (!ipv6_accept_ra(idev))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003839 goto out;
stephen hemminger5b2a1952010-03-02 13:32:45 +00003840
3841 /* Announcement received after solicitation was sent */
3842 if (idev->if_flags & IF_RA_RCVD)
3843 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003844
Maciej Żenczykowskibd11f072016-09-27 23:57:58 -07003845 if (idev->rs_probes++ < idev->cnf.rtr_solicits || idev->cnf.rtr_solicits < 0) {
Cong Wangcaf92bc2013-08-31 13:44:32 +08003846 write_unlock(&idev->lock);
3847 if (!ipv6_get_lladdr(dev, &lladdr, IFA_F_TENTATIVE))
3848 ndisc_send_rs(dev, &lladdr,
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02003849 &in6addr_linklocal_allrouters);
3850 else
Cong Wangcaf92bc2013-08-31 13:44:32 +08003851 goto put;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003852
Cong Wangcaf92bc2013-08-31 13:44:32 +08003853 write_lock(&idev->lock);
Maciej Żenczykowskibd11f072016-09-27 23:57:58 -07003854 idev->rs_interval = rfc3315_s14_backoff_update(
3855 idev->rs_interval, idev->cnf.rtr_solicit_max_interval);
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02003856 /* The wait after the last probe can be shorter */
3857 addrconf_mod_rs_timer(idev, (idev->rs_probes ==
3858 idev->cnf.rtr_solicits) ?
3859 idev->cnf.rtr_solicit_delay :
Maciej Żenczykowskibd11f072016-09-27 23:57:58 -07003860 idev->rs_interval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003861 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862 /*
3863 * Note: we do not support deprecated "all on-link"
3864 * assumption any longer.
3865 */
Joe Perches91df42b2012-05-15 14:11:54 +00003866 pr_debug("%s: no IPv6 routers present\n", idev->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003867 }
3868
3869out:
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02003870 write_unlock(&idev->lock);
Cong Wangcaf92bc2013-08-31 13:44:32 +08003871put:
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02003872 in6_dev_put(idev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003873}
3874
3875/*
3876 * Duplicate Address Detection
3877 */
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003878static void addrconf_dad_kick(struct inet6_ifaddr *ifp)
3879{
3880 unsigned long rand_num;
3881 struct inet6_dev *idev = ifp->idev;
Erik Nordmarkadc176c2016-12-02 14:00:08 -08003882 u64 nonce;
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003883
Neil Horman95c385b2007-04-25 17:08:10 -07003884 if (ifp->flags & IFA_F_OPTIMISTIC)
3885 rand_num = 0;
3886 else
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -05003887 rand_num = prandom_u32() % (idev->cnf.rtr_solicit_delay ? : 1);
Neil Horman95c385b2007-04-25 17:08:10 -07003888
Erik Nordmarkadc176c2016-12-02 14:00:08 -08003889 nonce = 0;
3890 if (idev->cnf.enhanced_dad ||
3891 dev_net(idev->dev)->ipv6.devconf_all->enhanced_dad) {
3892 do
3893 get_random_bytes(&nonce, 6);
3894 while (nonce == 0);
3895 }
3896 ifp->dad_nonce = nonce;
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02003897 ifp->dad_probes = idev->cnf.dad_transmits;
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01003898 addrconf_mod_dad_work(ifp, rand_num);
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003899}
3900
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01003901static void addrconf_dad_begin(struct inet6_ifaddr *ifp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003902{
3903 struct inet6_dev *idev = ifp->idev;
3904 struct net_device *dev = idev->dev;
Paolo Abeni764d3be2016-11-22 16:57:40 +01003905 bool bump_id, notify = false;
David Ahernafb1d4b52018-04-17 17:33:11 -07003906 struct net *net;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003907
3908 addrconf_join_solict(dev, &ifp->addr);
3909
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -05003910 prandom_seed((__force u32) ifp->addr.s6_addr32[3]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003911
3912 read_lock_bh(&idev->lock);
Herbert Xu622ccdf2010-05-18 15:56:06 -07003913 spin_lock(&ifp->lock);
Herbert Xue9d3e082010-05-18 15:36:06 -07003914 if (ifp->state == INET6_IFADDR_STATE_DEAD)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003915 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003916
David Ahernafb1d4b52018-04-17 17:33:11 -07003917 net = dev_net(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003918 if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) ||
David Ahernafb1d4b52018-04-17 17:33:11 -07003919 (net->ipv6.devconf_all->accept_dad < 1 &&
Matteo Crocea2d3f3e2017-10-05 19:03:05 +02003920 idev->cnf.accept_dad < 1) ||
Noriaki TAKAMIYA55ebaef2006-09-22 14:45:27 -07003921 !(ifp->flags&IFA_F_TENTATIVE) ||
3922 ifp->flags & IFA_F_NODAD) {
David Ahernc76fe2d2018-01-25 20:16:29 -08003923 bool send_na = false;
3924
3925 if (ifp->flags & IFA_F_TENTATIVE &&
3926 !(ifp->flags & IFA_F_OPTIMISTIC))
3927 send_na = true;
Paolo Abeni764d3be2016-11-22 16:57:40 +01003928 bump_id = ifp->flags & IFA_F_TENTATIVE;
Brian Haleycc411d02009-09-09 14:41:32 +00003929 ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED);
stephen hemminger21809fa2010-02-08 19:48:52 +00003930 spin_unlock(&ifp->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003931 read_unlock_bh(&idev->lock);
3932
David Ahernc76fe2d2018-01-25 20:16:29 -08003933 addrconf_dad_completed(ifp, bump_id, send_na);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003934 return;
3935 }
3936
YOSHIFUJI Hideaki6732bad2005-12-27 13:35:15 -08003937 if (!(idev->if_flags & IF_READY)) {
stephen hemminger21809fa2010-02-08 19:48:52 +00003938 spin_unlock(&ifp->lock);
YOSHIFUJI Hideaki6732bad2005-12-27 13:35:15 -08003939 read_unlock_bh(&idev->lock);
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003940 /*
Masatake YAMATO590a9882009-06-09 10:41:12 +09003941 * If the device is not ready:
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003942 * - keep it tentative if it is a permanent address.
3943 * - otherwise, kill it.
3944 */
3945 in6_ifa_hold(ifp);
Brian Haleycc411d02009-09-09 14:41:32 +00003946 addrconf_dad_stop(ifp, 0);
YOSHIFUJI Hideaki6732bad2005-12-27 13:35:15 -08003947 return;
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003948 }
Neil Horman95c385b2007-04-25 17:08:10 -07003949
3950 /*
3951 * Optimistic nodes can start receiving
3952 * Frames right away
3953 */
Erik Kline7fd25612014-10-28 18:11:14 +09003954 if (ifp->flags & IFA_F_OPTIMISTIC) {
David Ahernafb1d4b52018-04-17 17:33:11 -07003955 ip6_ins_rt(net, ifp->rt);
3956 if (ipv6_use_optimistic_addr(net, idev)) {
Erik Kline7fd25612014-10-28 18:11:14 +09003957 /* Because optimistic nodes can use this address,
3958 * notify listeners. If DAD fails, RTM_DELADDR is sent.
3959 */
subashab@codeaurora.org16186a82016-02-02 02:11:10 +00003960 notify = true;
Erik Kline7fd25612014-10-28 18:11:14 +09003961 }
3962 }
Neil Horman95c385b2007-04-25 17:08:10 -07003963
YOSHIFUJI Hideaki6732bad2005-12-27 13:35:15 -08003964 addrconf_dad_kick(ifp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003965out:
Herbert Xu622ccdf2010-05-18 15:56:06 -07003966 spin_unlock(&ifp->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003967 read_unlock_bh(&idev->lock);
subashab@codeaurora.org16186a82016-02-02 02:11:10 +00003968 if (notify)
3969 ipv6_ifa_notify(RTM_NEWADDR, ifp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003970}
3971
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01003972static void addrconf_dad_start(struct inet6_ifaddr *ifp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003973{
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01003974 bool begin_dad = false;
3975
Hannes Frederic Sowa8e8e6762015-03-23 23:36:03 +01003976 spin_lock_bh(&ifp->lock);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01003977 if (ifp->state != INET6_IFADDR_STATE_DEAD) {
3978 ifp->state = INET6_IFADDR_STATE_PREDAD;
3979 begin_dad = true;
3980 }
Hannes Frederic Sowa8e8e6762015-03-23 23:36:03 +01003981 spin_unlock_bh(&ifp->lock);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01003982
3983 if (begin_dad)
3984 addrconf_mod_dad_work(ifp, 0);
3985}
3986
3987static void addrconf_dad_work(struct work_struct *w)
3988{
3989 struct inet6_ifaddr *ifp = container_of(to_delayed_work(w),
3990 struct inet6_ifaddr,
3991 dad_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003992 struct inet6_dev *idev = ifp->idev;
Paolo Abeni764d3be2016-11-22 16:57:40 +01003993 bool bump_id, disable_ipv6 = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003994 struct in6_addr mcaddr;
3995
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01003996 enum {
3997 DAD_PROCESS,
3998 DAD_BEGIN,
3999 DAD_ABORT,
4000 } action = DAD_PROCESS;
4001
4002 rtnl_lock();
4003
Hannes Frederic Sowa8e8e6762015-03-23 23:36:03 +01004004 spin_lock_bh(&ifp->lock);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004005 if (ifp->state == INET6_IFADDR_STATE_PREDAD) {
4006 action = DAD_BEGIN;
4007 ifp->state = INET6_IFADDR_STATE_DAD;
4008 } else if (ifp->state == INET6_IFADDR_STATE_ERRDAD) {
4009 action = DAD_ABORT;
4010 ifp->state = INET6_IFADDR_STATE_POSTDAD;
Mike Manning85b51b12016-08-18 14:39:40 +01004011
Matteo Croce35e015e2017-09-12 17:46:37 +02004012 if ((dev_net(idev->dev)->ipv6.devconf_all->accept_dad > 1 ||
4013 idev->cnf.accept_dad > 1) &&
4014 !idev->cnf.disable_ipv6 &&
Mike Manning85b51b12016-08-18 14:39:40 +01004015 !(ifp->flags & IFA_F_STABLE_PRIVACY)) {
4016 struct in6_addr addr;
4017
4018 addr.s6_addr32[0] = htonl(0xfe800000);
4019 addr.s6_addr32[1] = 0;
4020
4021 if (!ipv6_generate_eui64(addr.s6_addr + 8, idev->dev) &&
4022 ipv6_addr_equal(&ifp->addr, &addr)) {
4023 /* DAD failed for link-local based on MAC */
4024 idev->cnf.disable_ipv6 = 1;
4025
4026 pr_info("%s: IPv6 being disabled!\n",
4027 ifp->idev->dev->name);
4028 disable_ipv6 = true;
4029 }
4030 }
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004031 }
Hannes Frederic Sowa8e8e6762015-03-23 23:36:03 +01004032 spin_unlock_bh(&ifp->lock);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004033
4034 if (action == DAD_BEGIN) {
4035 addrconf_dad_begin(ifp);
4036 goto out;
4037 } else if (action == DAD_ABORT) {
Wei Yongjun751eb6b2016-09-05 16:06:31 +08004038 in6_ifa_hold(ifp);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004039 addrconf_dad_stop(ifp, 1);
Mike Manning85b51b12016-08-18 14:39:40 +01004040 if (disable_ipv6)
4041 addrconf_ifdown(idev->dev, 0);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004042 goto out;
4043 }
4044
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02004045 if (!ifp->dad_probes && addrconf_dad_end(ifp))
Herbert Xuf2344a12010-05-18 15:55:27 -07004046 goto out;
4047
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004048 write_lock_bh(&idev->lock);
stephen hemminger122e4512010-03-02 13:32:44 +00004049 if (idev->dead || !(idev->if_flags & IF_READY)) {
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004050 write_unlock_bh(&idev->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051 goto out;
4052 }
stephen hemminger21809fa2010-02-08 19:48:52 +00004053
4054 spin_lock(&ifp->lock);
Herbert Xu622ccdf2010-05-18 15:56:06 -07004055 if (ifp->state == INET6_IFADDR_STATE_DEAD) {
4056 spin_unlock(&ifp->lock);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004057 write_unlock_bh(&idev->lock);
Herbert Xu622ccdf2010-05-18 15:56:06 -07004058 goto out;
4059 }
4060
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02004061 if (ifp->dad_probes == 0) {
David Ahernc76fe2d2018-01-25 20:16:29 -08004062 bool send_na = false;
4063
Linus Torvalds1da177e2005-04-16 15:20:36 -07004064 /*
4065 * DAD was successful
4066 */
4067
David Ahernc76fe2d2018-01-25 20:16:29 -08004068 if (ifp->flags & IFA_F_TENTATIVE &&
4069 !(ifp->flags & IFA_F_OPTIMISTIC))
4070 send_na = true;
Paolo Abeni764d3be2016-11-22 16:57:40 +01004071 bump_id = ifp->flags & IFA_F_TENTATIVE;
Brian Haleycc411d02009-09-09 14:41:32 +00004072 ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED);
stephen hemminger21809fa2010-02-08 19:48:52 +00004073 spin_unlock(&ifp->lock);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004074 write_unlock_bh(&idev->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075
David Ahernc76fe2d2018-01-25 20:16:29 -08004076 addrconf_dad_completed(ifp, bump_id, send_na);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004077
4078 goto out;
4079 }
4080
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02004081 ifp->dad_probes--;
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004082 addrconf_mod_dad_work(ifp,
Hangbin Liu19e16d22020-04-01 14:46:20 +08004083 max(NEIGH_VAR(ifp->idev->nd_parms, RETRANS_TIME),
4084 HZ/100));
stephen hemminger21809fa2010-02-08 19:48:52 +00004085 spin_unlock(&ifp->lock);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004086 write_unlock_bh(&idev->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087
4088 /* send a neighbour solicitation for our addr */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004089 addrconf_addr_solict_mult(&ifp->addr, &mcaddr);
Erik Nordmarkadc176c2016-12-02 14:00:08 -08004090 ndisc_send_ns(ifp->idev->dev, &ifp->addr, &mcaddr, &in6addr_any,
4091 ifp->dad_nonce);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004092out:
4093 in6_ifa_put(ifp);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004094 rtnl_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004095}
4096
Hannes Frederic Sowa11ffff72014-01-16 20:13:04 +01004097/* ifp->idev must be at least read locked */
4098static bool ipv6_lonely_lladdr(struct inet6_ifaddr *ifp)
4099{
4100 struct inet6_ifaddr *ifpiter;
4101 struct inet6_dev *idev = ifp->idev;
4102
Hannes Frederic Sowa602582c2014-01-19 21:58:19 +01004103 list_for_each_entry_reverse(ifpiter, &idev->addr_list, if_list) {
4104 if (ifpiter->scope > IFA_LINK)
4105 break;
Hannes Frederic Sowa11ffff72014-01-16 20:13:04 +01004106 if (ifp != ifpiter && ifpiter->scope == IFA_LINK &&
4107 (ifpiter->flags & (IFA_F_PERMANENT|IFA_F_TENTATIVE|
4108 IFA_F_OPTIMISTIC|IFA_F_DADFAILED)) ==
4109 IFA_F_PERMANENT)
4110 return false;
4111 }
4112 return true;
4113}
4114
David Ahernc76fe2d2018-01-25 20:16:29 -08004115static void addrconf_dad_completed(struct inet6_ifaddr *ifp, bool bump_id,
4116 bool send_na)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004117{
Stephen Hemmingere21e8462010-03-20 16:09:01 -07004118 struct net_device *dev = ifp->idev->dev;
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02004119 struct in6_addr lladdr;
Hannes Frederic Sowab173ee42013-06-27 00:07:01 +02004120 bool send_rs, send_mld;
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02004121
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004122 addrconf_del_dad_work(ifp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123
4124 /*
4125 * Configure the address for reception. Now it is valid.
4126 */
4127
4128 ipv6_ifa_notify(RTM_NEWADDR, ifp);
4129
Tore Anderson026359b2011-08-28 23:47:33 +00004130 /* If added prefix is link local and we are prepared to process
4131 router advertisements, start sending router solicitations.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004132 */
4133
Hannes Frederic Sowa1ec047e2013-06-27 00:06:56 +02004134 read_lock_bh(&ifp->idev->lock);
Hannes Frederic Sowa11ffff72014-01-16 20:13:04 +01004135 send_mld = ifp->scope == IFA_LINK && ipv6_lonely_lladdr(ifp);
Hannes Frederic Sowab173ee42013-06-27 00:07:01 +02004136 send_rs = send_mld &&
4137 ipv6_accept_ra(ifp->idev) &&
Maciej Żenczykowskibd11f072016-09-27 23:57:58 -07004138 ifp->idev->cnf.rtr_solicits != 0 &&
Hannes Frederic Sowab173ee42013-06-27 00:07:01 +02004139 (dev->flags&IFF_LOOPBACK) == 0;
Hannes Frederic Sowa1ec047e2013-06-27 00:06:56 +02004140 read_unlock_bh(&ifp->idev->lock);
4141
Hannes Frederic Sowab173ee42013-06-27 00:07:01 +02004142 /* While dad is in progress mld report's source address is in6_addrany.
4143 * Resend with proper ll now.
4144 */
4145 if (send_mld)
4146 ipv6_mc_dad_complete(ifp->idev);
4147
David Ahernc76fe2d2018-01-25 20:16:29 -08004148 /* send unsolicited NA if enabled */
4149 if (send_na &&
4150 (ifp->idev->cnf.ndisc_notify ||
4151 dev_net(dev)->ipv6.devconf_all->ndisc_notify)) {
4152 ndisc_send_na(dev, &in6addr_linklocal_allnodes, &ifp->addr,
4153 /*router=*/ !!ifp->idev->cnf.forwarding,
4154 /*solicited=*/ false, /*override=*/ true,
4155 /*inc_opt=*/ true);
4156 }
4157
Hannes Frederic Sowa1ec047e2013-06-27 00:06:56 +02004158 if (send_rs) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004159 /*
4160 * If a host as already performed a random delay
4161 * [...] as part of DAD [...] there is no need
4162 * to delay again before sending the first RS
4163 */
Hannes Frederic Sowa1ec047e2013-06-27 00:06:56 +02004164 if (ipv6_get_lladdr(dev, &lladdr, IFA_F_TENTATIVE))
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02004165 return;
Hannes Frederic Sowa1ec047e2013-06-27 00:06:56 +02004166 ndisc_send_rs(dev, &lladdr, &in6addr_linklocal_allrouters);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004167
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02004168 write_lock_bh(&ifp->idev->lock);
4169 spin_lock(&ifp->lock);
Maciej Żenczykowskibd11f072016-09-27 23:57:58 -07004170 ifp->idev->rs_interval = rfc3315_s14_backoff_init(
4171 ifp->idev->cnf.rtr_solicit_interval);
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02004172 ifp->idev->rs_probes = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173 ifp->idev->if_flags |= IF_RS_SENT;
Maciej Żenczykowskibd11f072016-09-27 23:57:58 -07004174 addrconf_mod_rs_timer(ifp->idev, ifp->idev->rs_interval);
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02004175 spin_unlock(&ifp->lock);
4176 write_unlock_bh(&ifp->idev->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004177 }
Paolo Abeni764d3be2016-11-22 16:57:40 +01004178
4179 if (bump_id)
4180 rt_genid_bump_ipv6(dev_net(dev));
Marcus Huewea11a7f72017-02-06 18:34:56 +01004181
4182 /* Make sure that a new temporary address will be created
4183 * before this temporary address becomes deprecated.
4184 */
4185 if (ifp->flags & IFA_F_TEMPORARY)
4186 addrconf_verify_rtnl();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004187}
4188
Hangbin Liu896585d2018-11-21 21:52:33 +08004189static void addrconf_dad_run(struct inet6_dev *idev, bool restart)
Stephen Hemmingere21e8462010-03-20 16:09:01 -07004190{
YOSHIFUJI Hideakic5e33bd2005-12-21 22:57:44 +09004191 struct inet6_ifaddr *ifp;
4192
4193 read_lock_bh(&idev->lock);
stephen hemminger502a2ff2010-03-17 20:31:13 +00004194 list_for_each_entry(ifp, &idev->addr_list, if_list) {
stephen hemminger21809fa2010-02-08 19:48:52 +00004195 spin_lock(&ifp->lock);
Hangbin Liu896585d2018-11-21 21:52:33 +08004196 if ((ifp->flags & IFA_F_TENTATIVE &&
4197 ifp->state == INET6_IFADDR_STATE_DAD) || restart) {
4198 if (restart)
4199 ifp->state = INET6_IFADDR_STATE_PREDAD;
Herbert Xuf2344a12010-05-18 15:55:27 -07004200 addrconf_dad_kick(ifp);
Hangbin Liu896585d2018-11-21 21:52:33 +08004201 }
stephen hemminger21809fa2010-02-08 19:48:52 +00004202 spin_unlock(&ifp->lock);
YOSHIFUJI Hideakic5e33bd2005-12-21 22:57:44 +09004203 }
4204 read_unlock_bh(&idev->lock);
4205}
4206
Linus Torvalds1da177e2005-04-16 15:20:36 -07004207#ifdef CONFIG_PROC_FS
4208struct if6_iter_state {
Daniel Lezcano3c400902008-01-10 22:42:49 -08004209 struct seq_net_private p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004210 int bucket;
Mihai Maruseac1d578302012-01-03 23:31:35 +00004211 int offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004212};
4213
Mihai Maruseac1d578302012-01-03 23:31:35 +00004214static struct inet6_ifaddr *if6_get_first(struct seq_file *seq, loff_t pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004215{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004216 struct if6_iter_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09004217 struct net *net = seq_file_net(seq);
Eric Dumazeta5c1d982017-10-23 16:17:50 -07004218 struct inet6_ifaddr *ifa = NULL;
Mihai Maruseac1d578302012-01-03 23:31:35 +00004219 int p = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004220
Mihai Maruseac1d578302012-01-03 23:31:35 +00004221 /* initial bucket if pos is 0 */
4222 if (pos == 0) {
4223 state->bucket = 0;
4224 state->offset = 0;
4225 }
4226
4227 for (; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) {
Eric Dumazeta5c1d982017-10-23 16:17:50 -07004228 hlist_for_each_entry_rcu(ifa, &inet6_addr_lst[state->bucket],
Mihai Maruseac1d578302012-01-03 23:31:35 +00004229 addr_lst) {
Eric Dumazet9f0d3c22012-10-16 07:37:27 +00004230 if (!net_eq(dev_net(ifa->idev->dev), net))
4231 continue;
Mihai Maruseac1d578302012-01-03 23:31:35 +00004232 /* sync with offset */
4233 if (p < state->offset) {
4234 p++;
4235 continue;
4236 }
Eric Dumazet9f0d3c22012-10-16 07:37:27 +00004237 return ifa;
Mihai Maruseac1d578302012-01-03 23:31:35 +00004238 }
4239
4240 /* prepare for next bucket */
4241 state->offset = 0;
4242 p = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004243 }
stephen hemmingerc2e21292010-03-17 20:31:10 +00004244 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004245}
4246
stephen hemmingerc2e21292010-03-17 20:31:10 +00004247static struct inet6_ifaddr *if6_get_next(struct seq_file *seq,
4248 struct inet6_ifaddr *ifa)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004249{
4250 struct if6_iter_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09004251 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004252
Eric Dumazeta5c1d982017-10-23 16:17:50 -07004253 hlist_for_each_entry_continue_rcu(ifa, addr_lst) {
Eric Dumazet9f0d3c22012-10-16 07:37:27 +00004254 if (!net_eq(dev_net(ifa->idev->dev), net))
4255 continue;
Mihai Maruseac1d578302012-01-03 23:31:35 +00004256 state->offset++;
Eric Dumazet9f0d3c22012-10-16 07:37:27 +00004257 return ifa;
Mihai Maruseac1d578302012-01-03 23:31:35 +00004258 }
stephen hemmingerc2e21292010-03-17 20:31:10 +00004259
Jeff Barnhill86f9bd12018-09-21 00:45:27 +00004260 state->offset = 0;
stephen hemmingerc2e21292010-03-17 20:31:10 +00004261 while (++state->bucket < IN6_ADDR_HSIZE) {
Eric Dumazeta5c1d982017-10-23 16:17:50 -07004262 hlist_for_each_entry_rcu(ifa,
stephen hemmingerc2e21292010-03-17 20:31:10 +00004263 &inet6_addr_lst[state->bucket], addr_lst) {
Eric Dumazet9f0d3c22012-10-16 07:37:27 +00004264 if (!net_eq(dev_net(ifa->idev->dev), net))
4265 continue;
Eric Dumazet9f0d3c22012-10-16 07:37:27 +00004266 return ifa;
Daniel Lezcano3c400902008-01-10 22:42:49 -08004267 }
4268 }
4269
stephen hemmingerc2e21292010-03-17 20:31:10 +00004270 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004271}
4272
Linus Torvalds1da177e2005-04-16 15:20:36 -07004273static void *if6_seq_start(struct seq_file *seq, loff_t *pos)
Eric Dumazeta5c1d982017-10-23 16:17:50 -07004274 __acquires(rcu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004275{
Eric Dumazeta5c1d982017-10-23 16:17:50 -07004276 rcu_read_lock();
Mihai Maruseac1d578302012-01-03 23:31:35 +00004277 return if6_get_first(seq, *pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004278}
4279
4280static void *if6_seq_next(struct seq_file *seq, void *v, loff_t *pos)
4281{
4282 struct inet6_ifaddr *ifa;
4283
4284 ifa = if6_get_next(seq, v);
4285 ++*pos;
4286 return ifa;
4287}
4288
4289static void if6_seq_stop(struct seq_file *seq, void *v)
Eric Dumazeta5c1d982017-10-23 16:17:50 -07004290 __releases(rcu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004291{
Eric Dumazeta5c1d982017-10-23 16:17:50 -07004292 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004293}
4294
4295static int if6_seq_show(struct seq_file *seq, void *v)
4296{
4297 struct inet6_ifaddr *ifp = (struct inet6_ifaddr *)v;
Jiri Pirko971a3512013-12-10 13:56:29 +01004298 seq_printf(seq, "%pi6 %02x %02x %02x %02x %8s\n",
Harvey Harrisonb0711952008-10-28 16:05:40 -07004299 &ifp->addr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004300 ifp->idev->dev->ifindex,
4301 ifp->prefix_len,
4302 ifp->scope,
Jiri Pirko971a3512013-12-10 13:56:29 +01004303 (u8) ifp->flags,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004304 ifp->idev->dev->name);
4305 return 0;
4306}
4307
Philippe De Muyter56b3d972007-07-10 23:07:31 -07004308static const struct seq_operations if6_seq_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004309 .start = if6_seq_start,
4310 .next = if6_seq_next,
4311 .show = if6_seq_show,
4312 .stop = if6_seq_stop,
4313};
4314
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00004315static int __net_init if6_proc_net_init(struct net *net)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004316{
Christoph Hellwigc3506372018-04-10 19:42:55 +02004317 if (!proc_create_net("if_inet6", 0444, net->proc_net, &if6_seq_ops,
4318 sizeof(struct if6_iter_state)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004319 return -ENOMEM;
4320 return 0;
4321}
4322
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00004323static void __net_exit if6_proc_net_exit(struct net *net)
Daniel Lezcano3c400902008-01-10 22:42:49 -08004324{
Gao fengece31ff2013-02-18 01:34:56 +00004325 remove_proc_entry("if_inet6", net->proc_net);
Daniel Lezcano3c400902008-01-10 22:42:49 -08004326}
4327
4328static struct pernet_operations if6_proc_net_ops = {
Ian Morris67ba4152014-08-24 21:53:10 +01004329 .init = if6_proc_net_init,
4330 .exit = if6_proc_net_exit,
Daniel Lezcano3c400902008-01-10 22:42:49 -08004331};
4332
4333int __init if6_proc_init(void)
4334{
4335 return register_pernet_subsys(&if6_proc_net_ops);
4336}
4337
Linus Torvalds1da177e2005-04-16 15:20:36 -07004338void if6_proc_exit(void)
4339{
Daniel Lezcano3c400902008-01-10 22:42:49 -08004340 unregister_pernet_subsys(&if6_proc_net_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004341}
4342#endif /* CONFIG_PROC_FS */
4343
Amerigo Wang07a93622012-10-29 16:23:10 +00004344#if IS_ENABLED(CONFIG_IPV6_MIP6)
Noriaki TAKAMIYA3b9f9a12006-09-22 14:45:56 -07004345/* Check if address is a home address configured on any interface. */
Eric Dumazetb71d1d42011-04-22 04:53:02 +00004346int ipv6_chk_home_addr(struct net *net, const struct in6_addr *addr)
Noriaki TAKAMIYA3b9f9a12006-09-22 14:45:56 -07004347{
Eric Dumazet3f27fb22017-10-23 16:17:47 -07004348 unsigned int hash = inet6_addr_hash(net, addr);
stephen hemmingerc2e21292010-03-17 20:31:10 +00004349 struct inet6_ifaddr *ifp = NULL;
Eric Dumazet3f27fb22017-10-23 16:17:47 -07004350 int ret = 0;
stephen hemmingerc2e21292010-03-17 20:31:10 +00004351
Eric Dumazet4e5f47a2017-10-23 16:17:51 -07004352 rcu_read_lock();
4353 hlist_for_each_entry_rcu(ifp, &inet6_addr_lst[hash], addr_lst) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09004354 if (!net_eq(dev_net(ifp->idev->dev), net))
Daniel Lezcano389f6612008-01-10 22:44:40 -08004355 continue;
YOSHIFUJI Hideakicaad2952008-04-10 15:42:07 +09004356 if (ipv6_addr_equal(&ifp->addr, addr) &&
Noriaki TAKAMIYA3b9f9a12006-09-22 14:45:56 -07004357 (ifp->flags & IFA_F_HOMEADDRESS)) {
4358 ret = 1;
4359 break;
4360 }
4361 }
Eric Dumazet4e5f47a2017-10-23 16:17:51 -07004362 rcu_read_unlock();
Noriaki TAKAMIYA3b9f9a12006-09-22 14:45:56 -07004363 return ret;
4364}
4365#endif
4366
Alexander Aringf37c6052020-03-27 18:00:19 -04004367/* RFC6554 has some algorithm to avoid loops in segment routing by
4368 * checking if the segments contains any of a local interface address.
4369 *
4370 * Quote:
4371 *
4372 * To detect loops in the SRH, a router MUST determine if the SRH
4373 * includes multiple addresses assigned to any interface on that router.
4374 * If such addresses appear more than once and are separated by at least
4375 * one address not assigned to that router.
4376 */
4377int ipv6_chk_rpl_srh_loop(struct net *net, const struct in6_addr *segs,
4378 unsigned char nsegs)
4379{
4380 const struct in6_addr *addr;
4381 int i, ret = 0, found = 0;
4382 struct inet6_ifaddr *ifp;
4383 bool separated = false;
4384 unsigned int hash;
4385 bool hash_found;
4386
4387 rcu_read_lock();
4388 for (i = 0; i < nsegs; i++) {
4389 addr = &segs[i];
4390 hash = inet6_addr_hash(net, addr);
4391
4392 hash_found = false;
4393 hlist_for_each_entry_rcu(ifp, &inet6_addr_lst[hash], addr_lst) {
4394 if (!net_eq(dev_net(ifp->idev->dev), net))
4395 continue;
4396
4397 if (ipv6_addr_equal(&ifp->addr, addr)) {
4398 hash_found = true;
4399 break;
4400 }
4401 }
4402
4403 if (hash_found) {
4404 if (found > 1 && separated) {
4405 ret = 1;
4406 break;
4407 }
4408
4409 separated = false;
4410 found++;
4411 } else {
4412 separated = true;
4413 }
4414 }
4415 rcu_read_unlock();
4416
4417 return ret;
4418}
4419
Linus Torvalds1da177e2005-04-16 15:20:36 -07004420/*
4421 * Periodic address status verification
4422 */
4423
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004424static void addrconf_verify_rtnl(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004425{
YOSHIFUJI Hideakib2db7562010-03-20 16:11:12 -07004426 unsigned long now, next, next_sec, next_sched;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004427 struct inet6_ifaddr *ifp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004428 int i;
4429
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004430 ASSERT_RTNL();
4431
stephen hemminger5c578aed2010-03-17 20:31:11 +00004432 rcu_read_lock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004433 now = jiffies;
YOSHIFUJI Hideakib2db7562010-03-20 16:11:12 -07004434 next = round_jiffies_up(now + ADDR_CHECK_FREQUENCY);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004435
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004436 cancel_delayed_work(&addr_chk_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004437
Stephen Hemmingerbcdd5532010-03-20 16:08:18 -07004438 for (i = 0; i < IN6_ADDR_HSIZE; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004439restart:
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004440 hlist_for_each_entry_rcu_bh(ifp, &inet6_addr_lst[i], addr_lst) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004441 unsigned long age;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004442
Yasushi Asanofad8da32013-12-31 12:04:19 +09004443 /* When setting preferred_lft to a value not zero or
4444 * infinity, while valid_lft is infinity
4445 * IFA_F_PERMANENT has a non-infinity life time.
4446 */
4447 if ((ifp->flags & IFA_F_PERMANENT) &&
4448 (ifp->prefered_lft == INFINITY_LIFE_TIME))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004449 continue;
4450
4451 spin_lock(&ifp->lock);
YOSHIFUJI Hideakib2db7562010-03-20 16:11:12 -07004452 /* We try to batch several events at once. */
4453 age = (now - ifp->tstamp + ADDRCONF_TIMER_FUZZ_MINUS) / HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004454
YOSHIFUJI Hideaki8f27ebb2006-07-28 18:12:11 +09004455 if (ifp->valid_lft != INFINITY_LIFE_TIME &&
4456 age >= ifp->valid_lft) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004457 spin_unlock(&ifp->lock);
4458 in6_ifa_hold(ifp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004459 ipv6_del_addr(ifp);
4460 goto restart;
YOSHIFUJI Hideaki8f27ebb2006-07-28 18:12:11 +09004461 } else if (ifp->prefered_lft == INFINITY_LIFE_TIME) {
4462 spin_unlock(&ifp->lock);
4463 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004464 } else if (age >= ifp->prefered_lft) {
Brian Haleya1ed0522009-07-02 07:10:52 +00004465 /* jiffies - ifp->tstamp > age >= ifp->prefered_lft */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004466 int deprecate = 0;
4467
4468 if (!(ifp->flags&IFA_F_DEPRECATED)) {
4469 deprecate = 1;
4470 ifp->flags |= IFA_F_DEPRECATED;
4471 }
4472
Yasushi Asanofad8da32013-12-31 12:04:19 +09004473 if ((ifp->valid_lft != INFINITY_LIFE_TIME) &&
4474 (time_before(ifp->tstamp + ifp->valid_lft * HZ, next)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004475 next = ifp->tstamp + ifp->valid_lft * HZ;
4476
4477 spin_unlock(&ifp->lock);
4478
4479 if (deprecate) {
4480 in6_ifa_hold(ifp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004481
4482 ipv6_ifa_notify(0, ifp);
4483 in6_ifa_put(ifp);
4484 goto restart;
4485 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004486 } else if ((ifp->flags&IFA_F_TEMPORARY) &&
4487 !(ifp->flags&IFA_F_TENTATIVE)) {
stephen hemminger88949cf2010-03-17 20:31:17 +00004488 unsigned long regen_advance = ifp->idev->cnf.regen_max_retry *
4489 ifp->idev->cnf.dad_transmits *
Hangbin Liu19e16d22020-04-01 14:46:20 +08004490 max(NEIGH_VAR(ifp->idev->nd_parms, RETRANS_TIME), HZ/100) / HZ;
stephen hemminger88949cf2010-03-17 20:31:17 +00004491
Linus Torvalds1da177e2005-04-16 15:20:36 -07004492 if (age >= ifp->prefered_lft - regen_advance) {
4493 struct inet6_ifaddr *ifpub = ifp->ifpub;
4494 if (time_before(ifp->tstamp + ifp->prefered_lft * HZ, next))
4495 next = ifp->tstamp + ifp->prefered_lft * HZ;
4496 if (!ifp->regen_count && ifpub) {
4497 ifp->regen_count++;
4498 in6_ifa_hold(ifp);
4499 in6_ifa_hold(ifpub);
4500 spin_unlock(&ifp->lock);
stephen hemminger5c578aed2010-03-17 20:31:11 +00004501
Hiroyuki YAMAMORI291d8092005-12-23 11:24:05 -08004502 spin_lock(&ifpub->lock);
4503 ifpub->regen_count = 0;
4504 spin_unlock(&ifpub->lock);
Eric Dumazete64e4692018-01-26 16:10:43 -08004505 rcu_read_unlock_bh();
Fernando Gont969c5462020-05-01 00:51:47 -03004506 ipv6_create_tempaddr(ifpub, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004507 in6_ifa_put(ifpub);
4508 in6_ifa_put(ifp);
Eric Dumazete64e4692018-01-26 16:10:43 -08004509 rcu_read_lock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004510 goto restart;
4511 }
4512 } else if (time_before(ifp->tstamp + ifp->prefered_lft * HZ - regen_advance * HZ, next))
4513 next = ifp->tstamp + ifp->prefered_lft * HZ - regen_advance * HZ;
4514 spin_unlock(&ifp->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004515 } else {
4516 /* ifp->prefered_lft <= ifp->valid_lft */
4517 if (time_before(ifp->tstamp + ifp->prefered_lft * HZ, next))
4518 next = ifp->tstamp + ifp->prefered_lft * HZ;
4519 spin_unlock(&ifp->lock);
4520 }
4521 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004522 }
4523
YOSHIFUJI Hideakib2db7562010-03-20 16:11:12 -07004524 next_sec = round_jiffies_up(next);
4525 next_sched = next;
4526
4527 /* If rounded timeout is accurate enough, accept it. */
4528 if (time_before(next_sec, next + ADDRCONF_TIMER_FUZZ))
4529 next_sched = next_sec;
4530
4531 /* And minimum interval is ADDRCONF_TIMER_FUZZ_MAX. */
4532 if (time_before(next_sched, jiffies + ADDRCONF_TIMER_FUZZ_MAX))
4533 next_sched = jiffies + ADDRCONF_TIMER_FUZZ_MAX;
4534
Joe Perchese32ac252018-03-26 08:35:01 -07004535 pr_debug("now = %lu, schedule = %lu, rounded schedule = %lu => %lu\n",
4536 now, next, next_sec, next_sched);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004537 mod_delayed_work(addrconf_wq, &addr_chk_work, next_sched - now);
stephen hemminger5c578aed2010-03-17 20:31:11 +00004538 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004539}
4540
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004541static void addrconf_verify_work(struct work_struct *w)
4542{
4543 rtnl_lock();
4544 addrconf_verify_rtnl();
4545 rtnl_unlock();
4546}
4547
4548static void addrconf_verify(void)
4549{
4550 mod_delayed_work(addrconf_wq, &addr_chk_work, 0);
4551}
4552
Nicolas Dichtelcaeaba72013-05-16 22:32:00 +00004553static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local,
4554 struct in6_addr **peer_pfx)
Thomas Graf461d8832006-09-18 00:09:49 -07004555{
4556 struct in6_addr *pfx = NULL;
4557
Nicolas Dichtelcaeaba72013-05-16 22:32:00 +00004558 *peer_pfx = NULL;
4559
Thomas Graf461d8832006-09-18 00:09:49 -07004560 if (addr)
4561 pfx = nla_data(addr);
4562
4563 if (local) {
4564 if (pfx && nla_memcmp(local, pfx, sizeof(*pfx)))
Nicolas Dichtelcaeaba72013-05-16 22:32:00 +00004565 *peer_pfx = pfx;
4566 pfx = nla_data(local);
Thomas Graf461d8832006-09-18 00:09:49 -07004567 }
4568
4569 return pfx;
4570}
4571
Patrick McHardyef7c79e2007-06-05 12:38:30 -07004572static const struct nla_policy ifa_ipv6_policy[IFA_MAX+1] = {
Thomas Graf461d8832006-09-18 00:09:49 -07004573 [IFA_ADDRESS] = { .len = sizeof(struct in6_addr) },
4574 [IFA_LOCAL] = { .len = sizeof(struct in6_addr) },
4575 [IFA_CACHEINFO] = { .len = sizeof(struct ifa_cacheinfo) },
Jiri Pirko479840f2013-12-06 09:45:21 +01004576 [IFA_FLAGS] = { .len = sizeof(u32) },
David Ahern8308f3f2018-05-27 08:09:58 -07004577 [IFA_RT_PRIORITY] = { .len = sizeof(u32) },
Christian Brauner6ecf4c32018-09-04 21:53:50 +02004578 [IFA_TARGET_NETNSID] = { .type = NLA_S32 },
Thomas Graf461d8832006-09-18 00:09:49 -07004579};
4580
Linus Torvalds1da177e2005-04-16 15:20:36 -07004581static int
David Ahernc21ef3e2017-04-16 09:48:24 -07004582inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh,
4583 struct netlink_ext_ack *extack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004584{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09004585 struct net *net = sock_net(skb->sk);
Thomas Grafb933f712006-09-18 00:10:19 -07004586 struct ifaddrmsg *ifm;
4587 struct nlattr *tb[IFA_MAX+1];
Nicolas Dichtelcaeaba72013-05-16 22:32:00 +00004588 struct in6_addr *pfx, *peer_pfx;
Heiner Kallweit6046d5b2014-04-20 21:29:36 +02004589 u32 ifa_flags;
Thomas Grafb933f712006-09-18 00:10:19 -07004590 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004591
Johannes Berg8cb08172019-04-26 14:07:28 +02004592 err = nlmsg_parse_deprecated(nlh, sizeof(*ifm), tb, IFA_MAX,
4593 ifa_ipv6_policy, extack);
Thomas Grafb933f712006-09-18 00:10:19 -07004594 if (err < 0)
4595 return err;
4596
4597 ifm = nlmsg_data(nlh);
Nicolas Dichtelcaeaba72013-05-16 22:32:00 +00004598 pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL], &peer_pfx);
Ian Morris63159f22015-03-29 14:00:04 +01004599 if (!pfx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004600 return -EINVAL;
4601
Heiner Kallweit6046d5b2014-04-20 21:29:36 +02004602 ifa_flags = tb[IFA_FLAGS] ? nla_get_u32(tb[IFA_FLAGS]) : ifm->ifa_flags;
4603
4604 /* We ignore other flags so far. */
4605 ifa_flags &= IFA_F_MANAGETEMPADDR;
4606
4607 return inet6_addr_del(net, ifm->ifa_index, ifa_flags, pfx,
4608 ifm->ifa_prefixlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004609}
4610
David Ahern8308f3f2018-05-27 08:09:58 -07004611static int modify_prefix_route(struct inet6_ifaddr *ifp,
Hangbin Liu61794012020-03-03 14:37:34 +08004612 unsigned long expires, u32 flags,
4613 bool modify_peer)
David Ahern8308f3f2018-05-27 08:09:58 -07004614{
4615 struct fib6_info *f6i;
David Aherne7c7faa2018-06-28 13:36:55 -07004616 u32 prio;
David Ahern8308f3f2018-05-27 08:09:58 -07004617
Hangbin Liu61794012020-03-03 14:37:34 +08004618 f6i = addrconf_get_prefix_route(modify_peer ? &ifp->peer_addr : &ifp->addr,
4619 ifp->prefix_len,
David Ahern2b2450c2019-03-27 20:53:52 -07004620 ifp->idev->dev, 0, RTF_DEFAULT, true);
David Ahern8308f3f2018-05-27 08:09:58 -07004621 if (!f6i)
4622 return -ENOENT;
4623
David Aherne7c7faa2018-06-28 13:36:55 -07004624 prio = ifp->rt_priority ? : IP6_RT_PRIO_ADDRCONF;
4625 if (f6i->fib6_metric != prio) {
4626 /* delete old one */
Roopa Prabhu11dd74b2020-04-27 13:56:45 -07004627 ip6_del_rt(dev_net(ifp->idev->dev), f6i, false);
David Aherne7c7faa2018-06-28 13:36:55 -07004628
David Ahern8308f3f2018-05-27 08:09:58 -07004629 /* add new one */
Hangbin Liu61794012020-03-03 14:37:34 +08004630 addrconf_prefix_route(modify_peer ? &ifp->peer_addr : &ifp->addr,
4631 ifp->prefix_len,
David Ahern8308f3f2018-05-27 08:09:58 -07004632 ifp->rt_priority, ifp->idev->dev,
4633 expires, flags, GFP_KERNEL);
David Ahern8308f3f2018-05-27 08:09:58 -07004634 } else {
4635 if (!expires)
4636 fib6_clean_expires(f6i);
4637 else
4638 fib6_set_expires(f6i, expires);
4639
4640 fib6_info_release(f6i);
4641 }
4642
4643 return 0;
4644}
4645
David Ahernd169a1f2018-05-27 08:09:55 -07004646static int inet6_addr_modify(struct inet6_ifaddr *ifp, struct ifa6_config *cfg)
Noriaki TAKAMIYA081bba52006-07-28 18:12:13 +09004647{
YOSHIFUJI Hideaki6f704992008-05-19 16:56:11 -07004648 u32 flags;
4649 clock_t expires;
YOSHIFUJI Hideaki4bed72e2008-05-27 17:37:49 +09004650 unsigned long timeout;
Jiri Pirko53bd6742013-12-06 09:45:22 +01004651 bool was_managetempaddr;
Thomas Haller5b84efe2014-01-15 15:36:59 +01004652 bool had_prefixroute;
Hangbin Liud0098e42020-03-03 14:37:35 +08004653 bool new_peer = false;
YOSHIFUJI Hideaki46d48042007-02-07 20:36:26 +09004654
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004655 ASSERT_RTNL();
4656
David Ahernd169a1f2018-05-27 08:09:55 -07004657 if (!cfg->valid_lft || cfg->preferred_lft > cfg->valid_lft)
Noriaki TAKAMIYA081bba52006-07-28 18:12:13 +09004658 return -EINVAL;
4659
David Ahernd169a1f2018-05-27 08:09:55 -07004660 if (cfg->ifa_flags & IFA_F_MANAGETEMPADDR &&
Jiri Pirko53bd6742013-12-06 09:45:22 +01004661 (ifp->flags & IFA_F_TEMPORARY || ifp->prefix_len != 64))
4662 return -EINVAL;
4663
Sabrina Dubrocaf1c02cf2018-02-28 16:40:08 +01004664 if (!(ifp->flags & IFA_F_TENTATIVE) || ifp->flags & IFA_F_DADFAILED)
David Ahernd169a1f2018-05-27 08:09:55 -07004665 cfg->ifa_flags &= ~IFA_F_OPTIMISTIC;
Sabrina Dubrocaf1c02cf2018-02-28 16:40:08 +01004666
David Ahernd169a1f2018-05-27 08:09:55 -07004667 timeout = addrconf_timeout_fixup(cfg->valid_lft, HZ);
YOSHIFUJI Hideaki4bed72e2008-05-27 17:37:49 +09004668 if (addrconf_finite_timeout(timeout)) {
4669 expires = jiffies_to_clock_t(timeout * HZ);
David Ahernd169a1f2018-05-27 08:09:55 -07004670 cfg->valid_lft = timeout;
YOSHIFUJI Hideaki6f704992008-05-19 16:56:11 -07004671 flags = RTF_EXPIRES;
YOSHIFUJI Hideaki4bed72e2008-05-27 17:37:49 +09004672 } else {
4673 expires = 0;
4674 flags = 0;
David Ahernd169a1f2018-05-27 08:09:55 -07004675 cfg->ifa_flags |= IFA_F_PERMANENT;
YOSHIFUJI Hideaki6f704992008-05-19 16:56:11 -07004676 }
Noriaki TAKAMIYA081bba52006-07-28 18:12:13 +09004677
David Ahernd169a1f2018-05-27 08:09:55 -07004678 timeout = addrconf_timeout_fixup(cfg->preferred_lft, HZ);
YOSHIFUJI Hideaki4bed72e2008-05-27 17:37:49 +09004679 if (addrconf_finite_timeout(timeout)) {
4680 if (timeout == 0)
David Ahernd169a1f2018-05-27 08:09:55 -07004681 cfg->ifa_flags |= IFA_F_DEPRECATED;
4682 cfg->preferred_lft = timeout;
YOSHIFUJI Hideaki4bed72e2008-05-27 17:37:49 +09004683 }
Noriaki TAKAMIYA081bba52006-07-28 18:12:13 +09004684
Hangbin Liud0098e42020-03-03 14:37:35 +08004685 if (cfg->peer_pfx &&
4686 memcmp(&ifp->peer_addr, cfg->peer_pfx, sizeof(struct in6_addr))) {
4687 if (!ipv6_addr_any(&ifp->peer_addr))
4688 cleanup_prefix_route(ifp, expires, true, true);
4689 new_peer = true;
4690 }
4691
Noriaki TAKAMIYA081bba52006-07-28 18:12:13 +09004692 spin_lock_bh(&ifp->lock);
Jiri Pirko53bd6742013-12-06 09:45:22 +01004693 was_managetempaddr = ifp->flags & IFA_F_MANAGETEMPADDR;
Thomas Haller5b84efe2014-01-15 15:36:59 +01004694 had_prefixroute = ifp->flags & IFA_F_PERMANENT &&
4695 !(ifp->flags & IFA_F_NOPREFIXROUTE);
Jiri Pirko53bd6742013-12-06 09:45:22 +01004696 ifp->flags &= ~(IFA_F_DEPRECATED | IFA_F_PERMANENT | IFA_F_NODAD |
Thomas Haller761aac72014-01-15 15:36:58 +01004697 IFA_F_HOMEADDRESS | IFA_F_MANAGETEMPADDR |
4698 IFA_F_NOPREFIXROUTE);
David Ahernd169a1f2018-05-27 08:09:55 -07004699 ifp->flags |= cfg->ifa_flags;
Noriaki TAKAMIYA081bba52006-07-28 18:12:13 +09004700 ifp->tstamp = jiffies;
David Ahernd169a1f2018-05-27 08:09:55 -07004701 ifp->valid_lft = cfg->valid_lft;
4702 ifp->prefered_lft = cfg->preferred_lft;
Noriaki TAKAMIYA081bba52006-07-28 18:12:13 +09004703
David Ahern8308f3f2018-05-27 08:09:58 -07004704 if (cfg->rt_priority && cfg->rt_priority != ifp->rt_priority)
4705 ifp->rt_priority = cfg->rt_priority;
Noriaki TAKAMIYA081bba52006-07-28 18:12:13 +09004706
Hangbin Liud0098e42020-03-03 14:37:35 +08004707 if (new_peer)
4708 ifp->peer_addr = *cfg->peer_pfx;
4709
Noriaki TAKAMIYA081bba52006-07-28 18:12:13 +09004710 spin_unlock_bh(&ifp->lock);
4711 if (!(ifp->flags&IFA_F_TENTATIVE))
4712 ipv6_ifa_notify(0, ifp);
Noriaki TAKAMIYA081bba52006-07-28 18:12:13 +09004713
David Ahernd169a1f2018-05-27 08:09:55 -07004714 if (!(cfg->ifa_flags & IFA_F_NOPREFIXROUTE)) {
David Ahern8308f3f2018-05-27 08:09:58 -07004715 int rc = -ENOENT;
4716
4717 if (had_prefixroute)
Hangbin Liu61794012020-03-03 14:37:34 +08004718 rc = modify_prefix_route(ifp, expires, flags, false);
David Ahern8308f3f2018-05-27 08:09:58 -07004719
4720 /* prefix route could have been deleted; if so restore it */
4721 if (rc == -ENOENT) {
4722 addrconf_prefix_route(&ifp->addr, ifp->prefix_len,
4723 ifp->rt_priority, ifp->idev->dev,
4724 expires, flags, GFP_KERNEL);
4725 }
Hangbin Liu61794012020-03-03 14:37:34 +08004726
4727 if (had_prefixroute && !ipv6_addr_any(&ifp->peer_addr))
4728 rc = modify_prefix_route(ifp, expires, flags, true);
4729
4730 if (rc == -ENOENT && !ipv6_addr_any(&ifp->peer_addr)) {
4731 addrconf_prefix_route(&ifp->peer_addr, ifp->prefix_len,
4732 ifp->rt_priority, ifp->idev->dev,
4733 expires, flags, GFP_KERNEL);
4734 }
Thomas Haller5b84efe2014-01-15 15:36:59 +01004735 } else if (had_prefixroute) {
4736 enum cleanup_prefix_rt_t action;
4737 unsigned long rt_expires;
4738
4739 write_lock_bh(&ifp->idev->lock);
4740 action = check_cleanup_prefix_route(ifp, &rt_expires);
4741 write_unlock_bh(&ifp->idev->lock);
4742
4743 if (action != CLEANUP_PREFIX_RT_NOP) {
4744 cleanup_prefix_route(ifp, rt_expires,
Hangbin Liud0098e42020-03-03 14:37:35 +08004745 action == CLEANUP_PREFIX_RT_DEL, false);
Thomas Haller5b84efe2014-01-15 15:36:59 +01004746 }
Thomas Haller761aac72014-01-15 15:36:58 +01004747 }
Jiri Pirko53bd6742013-12-06 09:45:22 +01004748
4749 if (was_managetempaddr || ifp->flags & IFA_F_MANAGETEMPADDR) {
David Ahernd169a1f2018-05-27 08:09:55 -07004750 if (was_managetempaddr &&
4751 !(ifp->flags & IFA_F_MANAGETEMPADDR)) {
4752 cfg->valid_lft = 0;
4753 cfg->preferred_lft = 0;
4754 }
4755 manage_tempaddrs(ifp->idev, ifp, cfg->valid_lft,
4756 cfg->preferred_lft, !was_managetempaddr,
4757 jiffies);
Jiri Pirko53bd6742013-12-06 09:45:22 +01004758 }
4759
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004760 addrconf_verify_rtnl();
Noriaki TAKAMIYA081bba52006-07-28 18:12:13 +09004761
4762 return 0;
4763}
4764
4765static int
David Ahernc21ef3e2017-04-16 09:48:24 -07004766inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
4767 struct netlink_ext_ack *extack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004768{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09004769 struct net *net = sock_net(skb->sk);
Thomas Graf461d8832006-09-18 00:09:49 -07004770 struct ifaddrmsg *ifm;
4771 struct nlattr *tb[IFA_MAX+1];
David Ahern19b15182018-05-27 08:09:54 -07004772 struct in6_addr *peer_pfx;
Thomas Graf7198f8c2006-09-18 00:13:46 -07004773 struct inet6_ifaddr *ifa;
4774 struct net_device *dev;
Sabrina Dubrocaf1c02cf2018-02-28 16:40:08 +01004775 struct inet6_dev *idev;
David Ahern19b15182018-05-27 08:09:54 -07004776 struct ifa6_config cfg;
Thomas Graf461d8832006-09-18 00:09:49 -07004777 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004778
Johannes Berg8cb08172019-04-26 14:07:28 +02004779 err = nlmsg_parse_deprecated(nlh, sizeof(*ifm), tb, IFA_MAX,
4780 ifa_ipv6_policy, extack);
Thomas Graf461d8832006-09-18 00:09:49 -07004781 if (err < 0)
4782 return err;
4783
David Ahern19b15182018-05-27 08:09:54 -07004784 memset(&cfg, 0, sizeof(cfg));
4785
Thomas Graf461d8832006-09-18 00:09:49 -07004786 ifm = nlmsg_data(nlh);
David Ahern19b15182018-05-27 08:09:54 -07004787 cfg.pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL], &peer_pfx);
4788 if (!cfg.pfx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004789 return -EINVAL;
4790
David Ahern19b15182018-05-27 08:09:54 -07004791 cfg.peer_pfx = peer_pfx;
4792 cfg.plen = ifm->ifa_prefixlen;
David Ahern8308f3f2018-05-27 08:09:58 -07004793 if (tb[IFA_RT_PRIORITY])
4794 cfg.rt_priority = nla_get_u32(tb[IFA_RT_PRIORITY]);
4795
David Ahern19b15182018-05-27 08:09:54 -07004796 cfg.valid_lft = INFINITY_LIFE_TIME;
4797 cfg.preferred_lft = INFINITY_LIFE_TIME;
4798
Thomas Graf461d8832006-09-18 00:09:49 -07004799 if (tb[IFA_CACHEINFO]) {
Noriaki TAKAMIYA0778769d2006-07-28 18:12:10 +09004800 struct ifa_cacheinfo *ci;
Thomas Graf461d8832006-09-18 00:09:49 -07004801
4802 ci = nla_data(tb[IFA_CACHEINFO]);
David Ahern19b15182018-05-27 08:09:54 -07004803 cfg.valid_lft = ci->ifa_valid;
4804 cfg.preferred_lft = ci->ifa_prefered;
Noriaki TAKAMIYA0778769d2006-07-28 18:12:10 +09004805 }
4806
Daniel Lezcanoaf284932008-03-05 10:46:57 -08004807 dev = __dev_get_by_index(net, ifm->ifa_index);
Ian Morris63159f22015-03-29 14:00:04 +01004808 if (!dev)
Thomas Graf7198f8c2006-09-18 00:13:46 -07004809 return -ENODEV;
4810
David Ahern19b15182018-05-27 08:09:54 -07004811 if (tb[IFA_FLAGS])
4812 cfg.ifa_flags = nla_get_u32(tb[IFA_FLAGS]);
4813 else
4814 cfg.ifa_flags = ifm->ifa_flags;
Jiri Pirko479840f2013-12-06 09:45:21 +01004815
Noriaki TAKAMIYA55ebaef2006-09-22 14:45:27 -07004816 /* We ignore other flags so far. */
David Ahern19b15182018-05-27 08:09:54 -07004817 cfg.ifa_flags &= IFA_F_NODAD | IFA_F_HOMEADDRESS |
4818 IFA_F_MANAGETEMPADDR | IFA_F_NOPREFIXROUTE |
4819 IFA_F_MCAUTOJOIN | IFA_F_OPTIMISTIC;
Sabrina Dubrocaf1c02cf2018-02-28 16:40:08 +01004820
4821 idev = ipv6_find_idev(dev);
Sabrina Dubrocadb0b99f2019-08-23 15:44:36 +02004822 if (IS_ERR(idev))
4823 return PTR_ERR(idev);
Sabrina Dubrocaf1c02cf2018-02-28 16:40:08 +01004824
4825 if (!ipv6_allow_optimistic_dad(net, idev))
David Ahern19b15182018-05-27 08:09:54 -07004826 cfg.ifa_flags &= ~IFA_F_OPTIMISTIC;
Sabrina Dubrocaf1c02cf2018-02-28 16:40:08 +01004827
David Ahern19b15182018-05-27 08:09:54 -07004828 if (cfg.ifa_flags & IFA_F_NODAD &&
4829 cfg.ifa_flags & IFA_F_OPTIMISTIC) {
Sabrina Dubrocaf1c02cf2018-02-28 16:40:08 +01004830 NL_SET_ERR_MSG(extack, "IFA_F_NODAD and IFA_F_OPTIMISTIC are mutually exclusive");
4831 return -EINVAL;
4832 }
Noriaki TAKAMIYA55ebaef2006-09-22 14:45:27 -07004833
David Ahern19b15182018-05-27 08:09:54 -07004834 ifa = ipv6_get_ifaddr(net, cfg.pfx, dev, 1);
Ian Morris63159f22015-03-29 14:00:04 +01004835 if (!ifa) {
Thomas Graf7198f8c2006-09-18 00:13:46 -07004836 /*
4837 * It would be best to check for !NLM_F_CREATE here but
stephen hemmingerdb9c7c32014-01-12 11:26:32 -08004838 * userspace already relies on not having to provide this.
Thomas Graf7198f8c2006-09-18 00:13:46 -07004839 */
David Ahern19b15182018-05-27 08:09:54 -07004840 return inet6_addr_add(net, ifm->ifa_index, &cfg, extack);
Noriaki TAKAMIYA081bba52006-07-28 18:12:13 +09004841 }
4842
Thomas Graf7198f8c2006-09-18 00:13:46 -07004843 if (nlh->nlmsg_flags & NLM_F_EXCL ||
4844 !(nlh->nlmsg_flags & NLM_F_REPLACE))
4845 err = -EEXIST;
4846 else
David Ahernd169a1f2018-05-27 08:09:55 -07004847 err = inet6_addr_modify(ifa, &cfg);
Thomas Graf7198f8c2006-09-18 00:13:46 -07004848
4849 in6_ifa_put(ifa);
4850
4851 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004852}
4853
Jiri Pirko479840f2013-12-06 09:45:21 +01004854static void put_ifaddrmsg(struct nlmsghdr *nlh, u8 prefixlen, u32 flags,
Thomas Graf101bb222006-09-18 00:11:52 -07004855 u8 scope, int ifindex)
4856{
4857 struct ifaddrmsg *ifm;
4858
4859 ifm = nlmsg_data(nlh);
4860 ifm->ifa_family = AF_INET6;
4861 ifm->ifa_prefixlen = prefixlen;
4862 ifm->ifa_flags = flags;
4863 ifm->ifa_scope = scope;
4864 ifm->ifa_index = ifindex;
4865}
4866
Thomas Graf85486af2006-09-18 00:11:24 -07004867static int put_cacheinfo(struct sk_buff *skb, unsigned long cstamp,
4868 unsigned long tstamp, u32 preferred, u32 valid)
4869{
4870 struct ifa_cacheinfo ci;
4871
Thomas Graf18a31e12010-11-17 04:12:02 +00004872 ci.cstamp = cstamp_delta(cstamp);
4873 ci.tstamp = cstamp_delta(tstamp);
Thomas Graf85486af2006-09-18 00:11:24 -07004874 ci.ifa_prefered = preferred;
4875 ci.ifa_valid = valid;
4876
4877 return nla_put(skb, IFA_CACHEINFO, sizeof(ci), &ci);
4878}
4879
Thomas Graf101bb222006-09-18 00:11:52 -07004880static inline int rt_scope(int ifa_scope)
4881{
4882 if (ifa_scope & IFA_HOST)
4883 return RT_SCOPE_HOST;
4884 else if (ifa_scope & IFA_LINK)
4885 return RT_SCOPE_LINK;
4886 else if (ifa_scope & IFA_SITE)
4887 return RT_SCOPE_SITE;
4888 else
4889 return RT_SCOPE_UNIVERSE;
4890}
4891
Thomas Graf0ab68032006-09-18 00:12:35 -07004892static inline int inet6_ifaddr_msgsize(void)
4893{
Thomas Graf339bf982006-11-10 14:10:15 -08004894 return NLMSG_ALIGN(sizeof(struct ifaddrmsg))
Nicolas Dichtelcaeaba72013-05-16 22:32:00 +00004895 + nla_total_size(16) /* IFA_LOCAL */
Thomas Graf339bf982006-11-10 14:10:15 -08004896 + nla_total_size(16) /* IFA_ADDRESS */
Jiri Pirko479840f2013-12-06 09:45:21 +01004897 + nla_total_size(sizeof(struct ifa_cacheinfo))
David Ahern8308f3f2018-05-27 08:09:58 -07004898 + nla_total_size(4) /* IFA_FLAGS */
4899 + nla_total_size(4) /* IFA_RT_PRIORITY */;
Thomas Graf0ab68032006-09-18 00:12:35 -07004900}
YOSHIFUJI Hideakic5396a32006-06-17 22:48:48 -07004901
David Ahern6ba1e6e2018-10-07 20:16:26 -07004902enum addr_type_t {
4903 UNICAST_ADDR,
4904 MULTICAST_ADDR,
4905 ANYCAST_ADDR,
4906};
4907
Christian Brauner203651b2018-09-04 21:53:55 +02004908struct inet6_fill_args {
4909 u32 portid;
4910 u32 seq;
4911 int event;
4912 unsigned int flags;
4913 int netnsid;
David Ahern6371a712018-10-19 12:45:30 -07004914 int ifindex;
David Ahern6ba1e6e2018-10-07 20:16:26 -07004915 enum addr_type_t type;
Christian Brauner203651b2018-09-04 21:53:55 +02004916};
4917
Linus Torvalds1da177e2005-04-16 15:20:36 -07004918static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
Christian Brauner203651b2018-09-04 21:53:55 +02004919 struct inet6_fill_args *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004920{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004921 struct nlmsghdr *nlh;
Thomas Graf85486af2006-09-18 00:11:24 -07004922 u32 preferred, valid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004923
Christian Brauner203651b2018-09-04 21:53:55 +02004924 nlh = nlmsg_put(skb, args->portid, args->seq, args->event,
4925 sizeof(struct ifaddrmsg), args->flags);
Ian Morris63159f22015-03-29 14:00:04 +01004926 if (!nlh)
Patrick McHardy26932562007-01-31 23:16:40 -08004927 return -EMSGSIZE;
Thomas Graf0ab68032006-09-18 00:12:35 -07004928
Thomas Graf101bb222006-09-18 00:11:52 -07004929 put_ifaddrmsg(nlh, ifa->prefix_len, ifa->flags, rt_scope(ifa->scope),
4930 ifa->idev->dev->ifindex);
4931
Christian Brauner203651b2018-09-04 21:53:55 +02004932 if (args->netnsid >= 0 &&
4933 nla_put_s32(skb, IFA_TARGET_NETNSID, args->netnsid))
Christian Brauner6ecf4c32018-09-04 21:53:50 +02004934 goto error;
4935
Yasushi Asanofad8da32013-12-31 12:04:19 +09004936 if (!((ifa->flags&IFA_F_PERMANENT) &&
4937 (ifa->prefered_lft == INFINITY_LIFE_TIME))) {
Thomas Graf85486af2006-09-18 00:11:24 -07004938 preferred = ifa->prefered_lft;
4939 valid = ifa->valid_lft;
4940 if (preferred != INFINITY_LIFE_TIME) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004941 long tval = (jiffies - ifa->tstamp)/HZ;
Jens Rosenbooma1faa692009-06-25 04:55:50 +00004942 if (preferred > tval)
4943 preferred -= tval;
4944 else
4945 preferred = 0;
Ben Hutchingsf56619f2010-06-26 11:37:47 +00004946 if (valid != INFINITY_LIFE_TIME) {
4947 if (valid > tval)
4948 valid -= tval;
4949 else
4950 valid = 0;
4951 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004952 }
4953 } else {
Thomas Graf85486af2006-09-18 00:11:24 -07004954 preferred = INFINITY_LIFE_TIME;
4955 valid = INFINITY_LIFE_TIME;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004956 }
Thomas Graf85486af2006-09-18 00:11:24 -07004957
Cong Wang7996c792013-05-22 05:41:06 +00004958 if (!ipv6_addr_any(&ifa->peer_addr)) {
Jiri Benc930345e2015-03-29 16:59:25 +02004959 if (nla_put_in6_addr(skb, IFA_LOCAL, &ifa->addr) < 0 ||
4960 nla_put_in6_addr(skb, IFA_ADDRESS, &ifa->peer_addr) < 0)
Nicolas Dichtelcaeaba72013-05-16 22:32:00 +00004961 goto error;
4962 } else
Jiri Benc930345e2015-03-29 16:59:25 +02004963 if (nla_put_in6_addr(skb, IFA_ADDRESS, &ifa->addr) < 0)
Nicolas Dichtelcaeaba72013-05-16 22:32:00 +00004964 goto error;
4965
David Ahern8308f3f2018-05-27 08:09:58 -07004966 if (ifa->rt_priority &&
4967 nla_put_u32(skb, IFA_RT_PRIORITY, ifa->rt_priority))
4968 goto error;
4969
Nicolas Dichtelcaeaba72013-05-16 22:32:00 +00004970 if (put_cacheinfo(skb, ifa->cstamp, ifa->tstamp, preferred, valid) < 0)
4971 goto error;
Thomas Graf85486af2006-09-18 00:11:24 -07004972
Jiri Pirko479840f2013-12-06 09:45:21 +01004973 if (nla_put_u32(skb, IFA_FLAGS, ifa->flags) < 0)
4974 goto error;
4975
Johannes Berg053c0952015-01-16 22:09:00 +01004976 nlmsg_end(skb, nlh);
4977 return 0;
Nicolas Dichtelcaeaba72013-05-16 22:32:00 +00004978
4979error:
4980 nlmsg_cancel(skb, nlh);
4981 return -EMSGSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004982}
4983
4984static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca,
Christian Brauner203651b2018-09-04 21:53:55 +02004985 struct inet6_fill_args *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004986{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004987 struct nlmsghdr *nlh;
Thomas Graf101bb222006-09-18 00:11:52 -07004988 u8 scope = RT_SCOPE_UNIVERSE;
4989 int ifindex = ifmca->idev->dev->ifindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004990
Thomas Graf101bb222006-09-18 00:11:52 -07004991 if (ipv6_addr_scope(&ifmca->mca_addr) & IFA_SITE)
4992 scope = RT_SCOPE_SITE;
4993
Christian Brauner203651b2018-09-04 21:53:55 +02004994 nlh = nlmsg_put(skb, args->portid, args->seq, args->event,
4995 sizeof(struct ifaddrmsg), args->flags);
Ian Morris63159f22015-03-29 14:00:04 +01004996 if (!nlh)
Patrick McHardy26932562007-01-31 23:16:40 -08004997 return -EMSGSIZE;
Thomas Graf0ab68032006-09-18 00:12:35 -07004998
Christian Brauner203651b2018-09-04 21:53:55 +02004999 if (args->netnsid >= 0 &&
5000 nla_put_s32(skb, IFA_TARGET_NETNSID, args->netnsid))
Christian Brauner6ecf4c32018-09-04 21:53:50 +02005001 return -EMSGSIZE;
5002
Thomas Graf101bb222006-09-18 00:11:52 -07005003 put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex);
Jiri Benc930345e2015-03-29 16:59:25 +02005004 if (nla_put_in6_addr(skb, IFA_MULTICAST, &ifmca->mca_addr) < 0 ||
Thomas Graf0ab68032006-09-18 00:12:35 -07005005 put_cacheinfo(skb, ifmca->mca_cstamp, ifmca->mca_tstamp,
Patrick McHardy26932562007-01-31 23:16:40 -08005006 INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0) {
5007 nlmsg_cancel(skb, nlh);
5008 return -EMSGSIZE;
5009 }
Thomas Graf85486af2006-09-18 00:11:24 -07005010
Johannes Berg053c0952015-01-16 22:09:00 +01005011 nlmsg_end(skb, nlh);
5012 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005013}
5014
5015static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca,
Christian Brauner203651b2018-09-04 21:53:55 +02005016 struct inet6_fill_args *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005017{
David Ahern9ee8cbb2018-04-18 15:39:01 -07005018 struct net_device *dev = fib6_info_nh_dev(ifaca->aca_rt);
5019 int ifindex = dev ? dev->ifindex : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005020 struct nlmsghdr *nlh;
Thomas Graf101bb222006-09-18 00:11:52 -07005021 u8 scope = RT_SCOPE_UNIVERSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005022
Thomas Graf101bb222006-09-18 00:11:52 -07005023 if (ipv6_addr_scope(&ifaca->aca_addr) & IFA_SITE)
5024 scope = RT_SCOPE_SITE;
5025
Christian Brauner203651b2018-09-04 21:53:55 +02005026 nlh = nlmsg_put(skb, args->portid, args->seq, args->event,
5027 sizeof(struct ifaddrmsg), args->flags);
Ian Morris63159f22015-03-29 14:00:04 +01005028 if (!nlh)
Patrick McHardy26932562007-01-31 23:16:40 -08005029 return -EMSGSIZE;
Thomas Graf0ab68032006-09-18 00:12:35 -07005030
Christian Brauner203651b2018-09-04 21:53:55 +02005031 if (args->netnsid >= 0 &&
5032 nla_put_s32(skb, IFA_TARGET_NETNSID, args->netnsid))
Christian Brauner6ecf4c32018-09-04 21:53:50 +02005033 return -EMSGSIZE;
5034
Thomas Graf101bb222006-09-18 00:11:52 -07005035 put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex);
Jiri Benc930345e2015-03-29 16:59:25 +02005036 if (nla_put_in6_addr(skb, IFA_ANYCAST, &ifaca->aca_addr) < 0 ||
Thomas Graf0ab68032006-09-18 00:12:35 -07005037 put_cacheinfo(skb, ifaca->aca_cstamp, ifaca->aca_tstamp,
Patrick McHardy26932562007-01-31 23:16:40 -08005038 INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0) {
5039 nlmsg_cancel(skb, nlh);
5040 return -EMSGSIZE;
5041 }
Thomas Graf85486af2006-09-18 00:11:24 -07005042
Johannes Berg053c0952015-01-16 22:09:00 +01005043 nlmsg_end(skb, nlh);
5044 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005045}
5046
Eric Dumazet234b27c2009-11-12 04:11:50 +00005047/* called with rcu_read_lock() */
5048static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb,
David Ahernfe884c22018-10-19 12:45:28 -07005049 struct netlink_callback *cb, int s_ip_idx,
David Ahern6ba1e6e2018-10-07 20:16:26 -07005050 struct inet6_fill_args *fillargs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005051{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005052 struct ifmcaddr6 *ifmca;
5053 struct ifacaddr6 *ifaca;
David Ahernfe884c22018-10-19 12:45:28 -07005054 int ip_idx = 0;
Eric Dumazet234b27c2009-11-12 04:11:50 +00005055 int err = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005056
Eric Dumazet234b27c2009-11-12 04:11:50 +00005057 read_lock_bh(&idev->lock);
David Ahern6ba1e6e2018-10-07 20:16:26 -07005058 switch (fillargs->type) {
stephen hemminger502a2ff2010-03-17 20:31:13 +00005059 case UNICAST_ADDR: {
5060 struct inet6_ifaddr *ifa;
David Ahern6ba1e6e2018-10-07 20:16:26 -07005061 fillargs->event = RTM_NEWADDR;
stephen hemminger502a2ff2010-03-17 20:31:13 +00005062
Eric Dumazet234b27c2009-11-12 04:11:50 +00005063 /* unicast address incl. temp addr */
stephen hemminger502a2ff2010-03-17 20:31:13 +00005064 list_for_each_entry(ifa, &idev->addr_list, if_list) {
David Ahern4ba4c562018-10-19 10:00:19 -07005065 if (ip_idx < s_ip_idx)
5066 goto next;
David Ahern6ba1e6e2018-10-07 20:16:26 -07005067 err = inet6_fill_ifaddr(skb, ifa, fillargs);
Johannes Berg053c0952015-01-16 22:09:00 +01005068 if (err < 0)
Eric Dumazet234b27c2009-11-12 04:11:50 +00005069 break;
Nicolas Dichtel63998ac2013-03-22 06:28:43 +00005070 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
David Ahern4ba4c562018-10-19 10:00:19 -07005071next:
5072 ip_idx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005073 }
Eric Dumazet234b27c2009-11-12 04:11:50 +00005074 break;
stephen hemminger502a2ff2010-03-17 20:31:13 +00005075 }
Eric Dumazet234b27c2009-11-12 04:11:50 +00005076 case MULTICAST_ADDR:
David Ahern6ba1e6e2018-10-07 20:16:26 -07005077 fillargs->event = RTM_GETMULTICAST;
Christian Brauner203651b2018-09-04 21:53:55 +02005078
Eric Dumazet234b27c2009-11-12 04:11:50 +00005079 /* multicast address */
5080 for (ifmca = idev->mc_list; ifmca;
5081 ifmca = ifmca->next, ip_idx++) {
5082 if (ip_idx < s_ip_idx)
5083 continue;
David Ahern6ba1e6e2018-10-07 20:16:26 -07005084 err = inet6_fill_ifmcaddr(skb, ifmca, fillargs);
Johannes Berg053c0952015-01-16 22:09:00 +01005085 if (err < 0)
Eric Dumazet234b27c2009-11-12 04:11:50 +00005086 break;
5087 }
5088 break;
5089 case ANYCAST_ADDR:
David Ahern6ba1e6e2018-10-07 20:16:26 -07005090 fillargs->event = RTM_GETANYCAST;
Eric Dumazet234b27c2009-11-12 04:11:50 +00005091 /* anycast address */
5092 for (ifaca = idev->ac_list; ifaca;
5093 ifaca = ifaca->aca_next, ip_idx++) {
5094 if (ip_idx < s_ip_idx)
5095 continue;
David Ahern6ba1e6e2018-10-07 20:16:26 -07005096 err = inet6_fill_ifacaddr(skb, ifaca, fillargs);
Johannes Berg053c0952015-01-16 22:09:00 +01005097 if (err < 0)
Eric Dumazet234b27c2009-11-12 04:11:50 +00005098 break;
5099 }
5100 break;
5101 default:
5102 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005103 }
Eric Dumazet234b27c2009-11-12 04:11:50 +00005104 read_unlock_bh(&idev->lock);
David Ahernfe884c22018-10-19 12:45:28 -07005105 cb->args[2] = ip_idx;
Eric Dumazet234b27c2009-11-12 04:11:50 +00005106 return err;
5107}
5108
David Aherned6eff12018-10-07 20:16:29 -07005109static int inet6_valid_dump_ifaddr_req(const struct nlmsghdr *nlh,
5110 struct inet6_fill_args *fillargs,
5111 struct net **tgt_net, struct sock *sk,
David Ahern6371a712018-10-19 12:45:30 -07005112 struct netlink_callback *cb)
David Aherned6eff12018-10-07 20:16:29 -07005113{
David Ahern6371a712018-10-19 12:45:30 -07005114 struct netlink_ext_ack *extack = cb->extack;
David Aherned6eff12018-10-07 20:16:29 -07005115 struct nlattr *tb[IFA_MAX+1];
5116 struct ifaddrmsg *ifm;
5117 int err, i;
5118
5119 if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ifm))) {
5120 NL_SET_ERR_MSG_MOD(extack, "Invalid header for address dump request");
5121 return -EINVAL;
5122 }
5123
5124 ifm = nlmsg_data(nlh);
5125 if (ifm->ifa_prefixlen || ifm->ifa_flags || ifm->ifa_scope) {
5126 NL_SET_ERR_MSG_MOD(extack, "Invalid values in header for address dump request");
5127 return -EINVAL;
5128 }
David Ahern6371a712018-10-19 12:45:30 -07005129
5130 fillargs->ifindex = ifm->ifa_index;
5131 if (fillargs->ifindex) {
5132 cb->answer_flags |= NLM_F_DUMP_FILTERED;
5133 fillargs->flags |= NLM_F_DUMP_FILTERED;
David Aherned6eff12018-10-07 20:16:29 -07005134 }
5135
Johannes Berg8cb08172019-04-26 14:07:28 +02005136 err = nlmsg_parse_deprecated_strict(nlh, sizeof(*ifm), tb, IFA_MAX,
5137 ifa_ipv6_policy, extack);
David Aherned6eff12018-10-07 20:16:29 -07005138 if (err < 0)
5139 return err;
5140
5141 for (i = 0; i <= IFA_MAX; ++i) {
5142 if (!tb[i])
5143 continue;
5144
5145 if (i == IFA_TARGET_NETNSID) {
5146 struct net *net;
5147
5148 fillargs->netnsid = nla_get_s32(tb[i]);
5149 net = rtnl_get_net_ns_capable(sk, fillargs->netnsid);
5150 if (IS_ERR(net)) {
Bjørn Morkbf4cc402018-10-25 21:18:25 +02005151 fillargs->netnsid = -1;
David Aherned6eff12018-10-07 20:16:29 -07005152 NL_SET_ERR_MSG_MOD(extack, "Invalid target network namespace id");
5153 return PTR_ERR(net);
5154 }
5155 *tgt_net = net;
5156 } else {
5157 NL_SET_ERR_MSG_MOD(extack, "Unsupported attribute in dump request");
5158 return -EINVAL;
5159 }
5160 }
5161
5162 return 0;
5163}
5164
Eric Dumazet234b27c2009-11-12 04:11:50 +00005165static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
5166 enum addr_type_t type)
5167{
David Aherned6eff12018-10-07 20:16:29 -07005168 const struct nlmsghdr *nlh = cb->nlh;
David Ahern6ba1e6e2018-10-07 20:16:26 -07005169 struct inet6_fill_args fillargs = {
5170 .portid = NETLINK_CB(cb->skb).portid,
5171 .seq = cb->nlh->nlmsg_seq,
5172 .flags = NLM_F_MULTI,
5173 .netnsid = -1,
5174 .type = type,
5175 };
Eric Dumazet234b27c2009-11-12 04:11:50 +00005176 struct net *net = sock_net(skb->sk);
Christian Brauner6ecf4c32018-09-04 21:53:50 +02005177 struct net *tgt_net = net;
David Ahernfe884c22018-10-19 12:45:28 -07005178 int idx, s_idx, s_ip_idx;
Eric Dumazet234b27c2009-11-12 04:11:50 +00005179 int h, s_h;
Eric Dumazet234b27c2009-11-12 04:11:50 +00005180 struct net_device *dev;
5181 struct inet6_dev *idev;
5182 struct hlist_head *head;
David Ahern242afaa2018-10-24 12:59:00 -07005183 int err = 0;
Eric Dumazet234b27c2009-11-12 04:11:50 +00005184
5185 s_h = cb->args[0];
5186 s_idx = idx = cb->args[1];
David Ahernfe884c22018-10-19 12:45:28 -07005187 s_ip_idx = cb->args[2];
Eric Dumazet234b27c2009-11-12 04:11:50 +00005188
David Aherned6eff12018-10-07 20:16:29 -07005189 if (cb->strict_check) {
David Aherned6eff12018-10-07 20:16:29 -07005190 err = inet6_valid_dump_ifaddr_req(nlh, &fillargs, &tgt_net,
David Ahern6371a712018-10-19 12:45:30 -07005191 skb->sk, cb);
David Aherned6eff12018-10-07 20:16:29 -07005192 if (err < 0)
David Ahern242afaa2018-10-24 12:59:00 -07005193 goto put_tgt_net;
David Ahern6371a712018-10-19 12:45:30 -07005194
David Ahern242afaa2018-10-24 12:59:00 -07005195 err = 0;
David Ahern6371a712018-10-19 12:45:30 -07005196 if (fillargs.ifindex) {
5197 dev = __dev_get_by_index(tgt_net, fillargs.ifindex);
David Ahern242afaa2018-10-24 12:59:00 -07005198 if (!dev) {
5199 err = -ENODEV;
5200 goto put_tgt_net;
5201 }
David Ahern6371a712018-10-19 12:45:30 -07005202 idev = __in6_dev_get(dev);
5203 if (idev) {
5204 err = in6_dump_addrs(idev, skb, cb, s_ip_idx,
5205 &fillargs);
Jakub Kicinski15180392019-01-22 14:47:19 -08005206 if (err > 0)
5207 err = 0;
David Ahern6371a712018-10-19 12:45:30 -07005208 }
5209 goto put_tgt_net;
5210 }
Christian Brauner6ecf4c32018-09-04 21:53:50 +02005211 }
5212
Eric Dumazet234b27c2009-11-12 04:11:50 +00005213 rcu_read_lock();
Christian Brauner6ecf4c32018-09-04 21:53:50 +02005214 cb->seq = atomic_read(&tgt_net->ipv6.dev_addr_genid) ^ tgt_net->dev_base_seq;
Eric Dumazet234b27c2009-11-12 04:11:50 +00005215 for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
5216 idx = 0;
Christian Brauner6ecf4c32018-09-04 21:53:50 +02005217 head = &tgt_net->dev_index_head[h];
Sasha Levinb67bfe02013-02-27 17:06:00 -08005218 hlist_for_each_entry_rcu(dev, head, index_hlist) {
Eric Dumazet234b27c2009-11-12 04:11:50 +00005219 if (idx < s_idx)
5220 goto cont;
Patrick McHardy4b97efd2010-03-26 20:27:49 -07005221 if (h > s_h || idx > s_idx)
Eric Dumazet234b27c2009-11-12 04:11:50 +00005222 s_ip_idx = 0;
Stephen Hemmingere21e8462010-03-20 16:09:01 -07005223 idev = __in6_dev_get(dev);
5224 if (!idev)
Eric Dumazet234b27c2009-11-12 04:11:50 +00005225 goto cont;
5226
David Ahernfe884c22018-10-19 12:45:28 -07005227 if (in6_dump_addrs(idev, skb, cb, s_ip_idx,
David Ahern6ba1e6e2018-10-07 20:16:26 -07005228 &fillargs) < 0)
Eric Dumazet234b27c2009-11-12 04:11:50 +00005229 goto done;
5230cont:
5231 idx++;
5232 }
5233 }
5234done:
5235 rcu_read_unlock();
5236 cb->args[0] = h;
5237 cb->args[1] = idx;
David Ahern6371a712018-10-19 12:45:30 -07005238put_tgt_net:
David Ahern6ba1e6e2018-10-07 20:16:26 -07005239 if (fillargs.netnsid >= 0)
Christian Brauner6ecf4c32018-09-04 21:53:50 +02005240 put_net(tgt_net);
Eric Dumazet234b27c2009-11-12 04:11:50 +00005241
Arthur Gautier7c1e8a32018-12-31 02:10:58 +00005242 return skb->len ? : err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005243}
5244
5245static int inet6_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
5246{
5247 enum addr_type_t type = UNICAST_ADDR;
Denis V. Lunevb8542722007-12-01 00:21:31 +11005248
Linus Torvalds1da177e2005-04-16 15:20:36 -07005249 return inet6_dump_addr(skb, cb, type);
5250}
5251
5252static int inet6_dump_ifmcaddr(struct sk_buff *skb, struct netlink_callback *cb)
5253{
5254 enum addr_type_t type = MULTICAST_ADDR;
Denis V. Lunevb8542722007-12-01 00:21:31 +11005255
Linus Torvalds1da177e2005-04-16 15:20:36 -07005256 return inet6_dump_addr(skb, cb, type);
5257}
5258
5259
5260static int inet6_dump_ifacaddr(struct sk_buff *skb, struct netlink_callback *cb)
5261{
5262 enum addr_type_t type = ANYCAST_ADDR;
Denis V. Lunevb8542722007-12-01 00:21:31 +11005263
Linus Torvalds1da177e2005-04-16 15:20:36 -07005264 return inet6_dump_addr(skb, cb, type);
5265}
5266
Jakub Kicinski4b1373d2019-01-18 10:46:21 -08005267static int inet6_rtm_valid_getaddr_req(struct sk_buff *skb,
5268 const struct nlmsghdr *nlh,
5269 struct nlattr **tb,
5270 struct netlink_ext_ack *extack)
5271{
5272 struct ifaddrmsg *ifm;
5273 int i, err;
5274
5275 if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ifm))) {
5276 NL_SET_ERR_MSG_MOD(extack, "Invalid header for get address request");
5277 return -EINVAL;
5278 }
5279
Hangbin Liu2beb6d22019-12-11 22:20:16 +08005280 if (!netlink_strict_get_check(skb))
5281 return nlmsg_parse_deprecated(nlh, sizeof(*ifm), tb, IFA_MAX,
5282 ifa_ipv6_policy, extack);
5283
Jakub Kicinski4b1373d2019-01-18 10:46:21 -08005284 ifm = nlmsg_data(nlh);
5285 if (ifm->ifa_prefixlen || ifm->ifa_flags || ifm->ifa_scope) {
5286 NL_SET_ERR_MSG_MOD(extack, "Invalid values in header for get address request");
5287 return -EINVAL;
5288 }
5289
Johannes Berg8cb08172019-04-26 14:07:28 +02005290 err = nlmsg_parse_deprecated_strict(nlh, sizeof(*ifm), tb, IFA_MAX,
5291 ifa_ipv6_policy, extack);
Jakub Kicinski4b1373d2019-01-18 10:46:21 -08005292 if (err)
5293 return err;
5294
5295 for (i = 0; i <= IFA_MAX; i++) {
5296 if (!tb[i])
5297 continue;
5298
5299 switch (i) {
5300 case IFA_TARGET_NETNSID:
5301 case IFA_ADDRESS:
5302 case IFA_LOCAL:
5303 break;
5304 default:
5305 NL_SET_ERR_MSG_MOD(extack, "Unsupported attribute in get address request");
5306 return -EINVAL;
5307 }
5308 }
5309
5310 return 0;
5311}
5312
David Ahernc21ef3e2017-04-16 09:48:24 -07005313static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh,
5314 struct netlink_ext_ack *extack)
Noriaki TAKAMIYA6c223822006-07-28 18:12:12 +09005315{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09005316 struct net *net = sock_net(in_skb->sk);
Christian Brauner203651b2018-09-04 21:53:55 +02005317 struct inet6_fill_args fillargs = {
5318 .portid = NETLINK_CB(in_skb).portid,
5319 .seq = nlh->nlmsg_seq,
5320 .event = RTM_NEWADDR,
5321 .flags = 0,
5322 .netnsid = -1,
5323 };
Christian Brauner6ecf4c32018-09-04 21:53:50 +02005324 struct net *tgt_net = net;
Thomas Graf1b29fc22006-09-18 00:10:50 -07005325 struct ifaddrmsg *ifm;
5326 struct nlattr *tb[IFA_MAX+1];
Nicolas Dichtelcaeaba72013-05-16 22:32:00 +00005327 struct in6_addr *addr = NULL, *peer;
Noriaki TAKAMIYA6c223822006-07-28 18:12:12 +09005328 struct net_device *dev = NULL;
5329 struct inet6_ifaddr *ifa;
5330 struct sk_buff *skb;
Noriaki TAKAMIYA6c223822006-07-28 18:12:12 +09005331 int err;
5332
Jakub Kicinski4b1373d2019-01-18 10:46:21 -08005333 err = inet6_rtm_valid_getaddr_req(in_skb, nlh, tb, extack);
Thomas Graf1b29fc22006-09-18 00:10:50 -07005334 if (err < 0)
Florian Westphalc24675f2017-10-11 10:28:01 +02005335 return err;
Noriaki TAKAMIYA6c223822006-07-28 18:12:12 +09005336
Christian Brauner6ecf4c32018-09-04 21:53:50 +02005337 if (tb[IFA_TARGET_NETNSID]) {
Christian Brauner203651b2018-09-04 21:53:55 +02005338 fillargs.netnsid = nla_get_s32(tb[IFA_TARGET_NETNSID]);
Christian Brauner6ecf4c32018-09-04 21:53:50 +02005339
5340 tgt_net = rtnl_get_net_ns_capable(NETLINK_CB(in_skb).sk,
Christian Brauner203651b2018-09-04 21:53:55 +02005341 fillargs.netnsid);
Christian Brauner6ecf4c32018-09-04 21:53:50 +02005342 if (IS_ERR(tgt_net))
5343 return PTR_ERR(tgt_net);
5344 }
5345
Nicolas Dichtelcaeaba72013-05-16 22:32:00 +00005346 addr = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL], &peer);
Florian Westphalc24675f2017-10-11 10:28:01 +02005347 if (!addr)
5348 return -EINVAL;
Thomas Graf1b29fc22006-09-18 00:10:50 -07005349
5350 ifm = nlmsg_data(nlh);
Noriaki TAKAMIYA6c223822006-07-28 18:12:12 +09005351 if (ifm->ifa_index)
Christian Brauner6ecf4c32018-09-04 21:53:50 +02005352 dev = dev_get_by_index(tgt_net, ifm->ifa_index);
Noriaki TAKAMIYA6c223822006-07-28 18:12:12 +09005353
Christian Brauner6ecf4c32018-09-04 21:53:50 +02005354 ifa = ipv6_get_ifaddr(tgt_net, addr, dev, 1);
Stephen Hemmingere21e8462010-03-20 16:09:01 -07005355 if (!ifa) {
Thomas Graf1b29fc22006-09-18 00:10:50 -07005356 err = -EADDRNOTAVAIL;
5357 goto errout;
Noriaki TAKAMIYA6c223822006-07-28 18:12:12 +09005358 }
5359
Stephen Hemmingere21e8462010-03-20 16:09:01 -07005360 skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_KERNEL);
5361 if (!skb) {
Thomas Graf1b29fc22006-09-18 00:10:50 -07005362 err = -ENOBUFS;
5363 goto errout_ifa;
5364 }
5365
Christian Brauner203651b2018-09-04 21:53:55 +02005366 err = inet6_fill_ifaddr(skb, ifa, &fillargs);
Patrick McHardy26932562007-01-31 23:16:40 -08005367 if (err < 0) {
5368 /* -EMSGSIZE implies BUG in inet6_ifaddr_msgsize() */
5369 WARN_ON(err == -EMSGSIZE);
5370 kfree_skb(skb);
5371 goto errout_ifa;
5372 }
Christian Brauner6ecf4c32018-09-04 21:53:50 +02005373 err = rtnl_unicast(skb, tgt_net, NETLINK_CB(in_skb).portid);
Thomas Graf1b29fc22006-09-18 00:10:50 -07005374errout_ifa:
Noriaki TAKAMIYA6c223822006-07-28 18:12:12 +09005375 in6_ifa_put(ifa);
Thomas Graf1b29fc22006-09-18 00:10:50 -07005376errout:
Florian Westphalc24675f2017-10-11 10:28:01 +02005377 if (dev)
5378 dev_put(dev);
Christian Brauner203651b2018-09-04 21:53:55 +02005379 if (fillargs.netnsid >= 0)
Christian Brauner6ecf4c32018-09-04 21:53:50 +02005380 put_net(tgt_net);
5381
Noriaki TAKAMIYA6c223822006-07-28 18:12:12 +09005382 return err;
Noriaki TAKAMIYA6c223822006-07-28 18:12:12 +09005383}
5384
Linus Torvalds1da177e2005-04-16 15:20:36 -07005385static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
5386{
5387 struct sk_buff *skb;
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09005388 struct net *net = dev_net(ifa->idev->dev);
Christian Brauner203651b2018-09-04 21:53:55 +02005389 struct inet6_fill_args fillargs = {
5390 .portid = 0,
5391 .seq = 0,
5392 .event = event,
5393 .flags = 0,
5394 .netnsid = -1,
5395 };
Thomas Graf5d620262006-08-15 00:35:02 -07005396 int err = -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005397
Thomas Graf0ab68032006-09-18 00:12:35 -07005398 skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_ATOMIC);
Ian Morris63159f22015-03-29 14:00:04 +01005399 if (!skb)
Thomas Graf5d620262006-08-15 00:35:02 -07005400 goto errout;
5401
Christian Brauner203651b2018-09-04 21:53:55 +02005402 err = inet6_fill_ifaddr(skb, ifa, &fillargs);
Patrick McHardy26932562007-01-31 23:16:40 -08005403 if (err < 0) {
5404 /* -EMSGSIZE implies BUG in inet6_ifaddr_msgsize() */
5405 WARN_ON(err == -EMSGSIZE);
5406 kfree_skb(skb);
5407 goto errout;
5408 }
Pablo Neira Ayuso1ce85fe2009-02-24 23:18:28 -08005409 rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
5410 return;
Thomas Graf5d620262006-08-15 00:35:02 -07005411errout:
5412 if (err < 0)
Benjamin Thery6fda7352008-03-05 10:47:47 -08005413 rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005414}
5415
Dave Jonesb6f99a22007-03-22 12:27:49 -07005416static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005417 __s32 *array, int bytes)
5418{
Thomas Graf04561c12006-11-14 19:53:58 -08005419 BUG_ON(bytes < (DEVCONF_MAX * 4));
5420
Linus Torvalds1da177e2005-04-16 15:20:36 -07005421 memset(array, 0, bytes);
5422 array[DEVCONF_FORWARDING] = cnf->forwarding;
5423 array[DEVCONF_HOPLIMIT] = cnf->hop_limit;
5424 array[DEVCONF_MTU6] = cnf->mtu6;
5425 array[DEVCONF_ACCEPT_RA] = cnf->accept_ra;
5426 array[DEVCONF_ACCEPT_REDIRECTS] = cnf->accept_redirects;
5427 array[DEVCONF_AUTOCONF] = cnf->autoconf;
5428 array[DEVCONF_DAD_TRANSMITS] = cnf->dad_transmits;
5429 array[DEVCONF_RTR_SOLICITS] = cnf->rtr_solicits;
Thomas Graf93908d12010-11-17 01:44:24 +00005430 array[DEVCONF_RTR_SOLICIT_INTERVAL] =
5431 jiffies_to_msecs(cnf->rtr_solicit_interval);
Maciej Żenczykowskibd11f072016-09-27 23:57:58 -07005432 array[DEVCONF_RTR_SOLICIT_MAX_INTERVAL] =
5433 jiffies_to_msecs(cnf->rtr_solicit_max_interval);
Thomas Graf93908d12010-11-17 01:44:24 +00005434 array[DEVCONF_RTR_SOLICIT_DELAY] =
5435 jiffies_to_msecs(cnf->rtr_solicit_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005436 array[DEVCONF_FORCE_MLD_VERSION] = cnf->force_mld_version;
Hannes Frederic Sowafc4eba52013-08-14 01:03:46 +02005437 array[DEVCONF_MLDV1_UNSOLICITED_REPORT_INTERVAL] =
5438 jiffies_to_msecs(cnf->mldv1_unsolicited_report_interval);
5439 array[DEVCONF_MLDV2_UNSOLICITED_REPORT_INTERVAL] =
5440 jiffies_to_msecs(cnf->mldv2_unsolicited_report_interval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005441 array[DEVCONF_USE_TEMPADDR] = cnf->use_tempaddr;
5442 array[DEVCONF_TEMP_VALID_LFT] = cnf->temp_valid_lft;
5443 array[DEVCONF_TEMP_PREFERED_LFT] = cnf->temp_prefered_lft;
5444 array[DEVCONF_REGEN_MAX_RETRY] = cnf->regen_max_retry;
5445 array[DEVCONF_MAX_DESYNC_FACTOR] = cnf->max_desync_factor;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005446 array[DEVCONF_MAX_ADDRESSES] = cnf->max_addresses;
YOSHIFUJI Hideaki65f5c7c2006-03-20 16:55:08 -08005447 array[DEVCONF_ACCEPT_RA_DEFRTR] = cnf->accept_ra_defrtr;
Hangbin Liu8013d1d2015-07-30 14:28:42 +08005448 array[DEVCONF_ACCEPT_RA_MIN_HOP_LIMIT] = cnf->accept_ra_min_hop_limit;
YOSHIFUJI Hideakic4fd30e2006-03-20 16:55:26 -08005449 array[DEVCONF_ACCEPT_RA_PINFO] = cnf->accept_ra_pinfo;
YOSHIFUJI Hideaki930d6ff2006-03-20 17:05:30 -08005450#ifdef CONFIG_IPV6_ROUTER_PREF
5451 array[DEVCONF_ACCEPT_RA_RTR_PREF] = cnf->accept_ra_rtr_pref;
Thomas Graf93908d12010-11-17 01:44:24 +00005452 array[DEVCONF_RTR_PROBE_INTERVAL] =
5453 jiffies_to_msecs(cnf->rtr_probe_interval);
Neil Hormanfa03ef32007-01-30 14:30:10 -08005454#ifdef CONFIG_IPV6_ROUTE_INFO
Joel Scherpelzbbea1242017-03-22 18:19:04 +09005455 array[DEVCONF_ACCEPT_RA_RT_INFO_MIN_PLEN] = cnf->accept_ra_rt_info_min_plen;
YOSHIFUJI Hideaki09c884d2006-03-20 17:07:03 -08005456 array[DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN] = cnf->accept_ra_rt_info_max_plen;
5457#endif
YOSHIFUJI Hideaki930d6ff2006-03-20 17:05:30 -08005458#endif
YOSHIFUJI Hideakifbea49e2006-09-22 14:43:49 -07005459 array[DEVCONF_PROXY_NDP] = cnf->proxy_ndp;
YOSHIFUJI Hideaki0bcbc922007-04-24 14:58:30 -07005460 array[DEVCONF_ACCEPT_SOURCE_ROUTE] = cnf->accept_source_route;
Neil Horman95c385b2007-04-25 17:08:10 -07005461#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
5462 array[DEVCONF_OPTIMISTIC_DAD] = cnf->optimistic_dad;
Erik Kline7fd25612014-10-28 18:11:14 +09005463 array[DEVCONF_USE_OPTIMISTIC] = cnf->use_optimistic;
Neil Horman95c385b2007-04-25 17:08:10 -07005464#endif
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09005465#ifdef CONFIG_IPV6_MROUTE
5466 array[DEVCONF_MC_FORWARDING] = cnf->mc_forwarding;
5467#endif
YOSHIFUJI Hideaki778d80b2008-06-28 14:17:11 +09005468 array[DEVCONF_DISABLE_IPV6] = cnf->disable_ipv6;
YOSHIFUJI Hideaki1b34be72008-06-28 14:18:38 +09005469 array[DEVCONF_ACCEPT_DAD] = cnf->accept_dad;
Cosmin Ratiuc3faca02009-10-09 03:11:14 +00005470 array[DEVCONF_FORCE_TLLAO] = cnf->force_tllao;
Hannes Frederic Sowa5cb04432012-11-06 16:46:20 +00005471 array[DEVCONF_NDISC_NOTIFY] = cnf->ndisc_notify;
Hannes Frederic Sowab800c3b2013-08-27 01:36:51 +02005472 array[DEVCONF_SUPPRESS_FRAG_NDISC] = cnf->suppress_frag_ndisc;
Ben Greeard9333192014-06-25 14:44:53 -07005473 array[DEVCONF_ACCEPT_RA_FROM_LOCAL] = cnf->accept_ra_from_local;
Harout Hedeshianc2943f12015-01-20 10:06:05 -07005474 array[DEVCONF_ACCEPT_RA_MTU] = cnf->accept_ra_mtu;
Andy Gospodarek35103d12015-08-13 10:39:01 -04005475 array[DEVCONF_IGNORE_ROUTES_WITH_LINKDOWN] = cnf->ignore_routes_with_linkdown;
Hannes Frederic Sowa3d1bec92015-03-23 23:36:00 +01005476 /* we omit DEVCONF_STABLE_SECRET for now */
Erik Kline3985e8a2015-07-22 16:38:25 +09005477 array[DEVCONF_USE_OIF_ADDRS_ONLY] = cnf->use_oif_addrs_only;
Johannes Bergabbc3042016-02-04 13:31:19 +01005478 array[DEVCONF_DROP_UNICAST_IN_L2_MULTICAST] = cnf->drop_unicast_in_l2_multicast;
Johannes Berg7a02bf82016-02-04 13:31:20 +01005479 array[DEVCONF_DROP_UNSOLICITED_NA] = cnf->drop_unsolicited_na;
David Ahernf1705ec2016-02-24 09:25:37 -08005480 array[DEVCONF_KEEP_ADDR_ON_DOWN] = cnf->keep_addr_on_down;
David Lebrun1ababeb2016-11-08 14:57:39 +01005481 array[DEVCONF_SEG6_ENABLED] = cnf->seg6_enabled;
David Lebrunbf355b82016-11-08 14:57:42 +01005482#ifdef CONFIG_IPV6_SEG6_HMAC
5483 array[DEVCONF_SEG6_REQUIRE_HMAC] = cnf->seg6_require_hmac;
5484#endif
Erik Nordmarkadc176c2016-12-02 14:00:08 -08005485 array[DEVCONF_ENHANCED_DAD] = cnf->enhanced_dad;
Felix Jiad35a00b2017-01-26 16:59:17 +13005486 array[DEVCONF_ADDR_GEN_MODE] = cnf->addr_gen_mode;
David Forsterdf789fe2017-02-23 16:27:18 +00005487 array[DEVCONF_DISABLE_POLICY] = cnf->disable_policy;
Maciej Żenczykowski2210d6b2017-11-07 21:52:09 -08005488 array[DEVCONF_NDISC_TCLASS] = cnf->ndisc_tclass;
Alexander Aring8610c7c2020-03-27 18:00:20 -04005489 array[DEVCONF_RPL_SEG_ENABLED] = cnf->rpl_seg_enabled;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005490}
5491
Thomas Grafb382b192010-11-16 04:33:57 +00005492static inline size_t inet6_ifla6_size(void)
5493{
5494 return nla_total_size(4) /* IFLA_INET6_FLAGS */
5495 + nla_total_size(sizeof(struct ifla_cacheinfo))
5496 + nla_total_size(DEVCONF_MAX * 4) /* IFLA_INET6_CONF */
5497 + nla_total_size(IPSTATS_MIB_MAX * 8) /* IFLA_INET6_STATS */
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005498 + nla_total_size(ICMP6_MIB_MAX * 8) /* IFLA_INET6_ICMP6STATS */
Sabrina Dubrocabdd72f42018-07-09 12:25:16 +02005499 + nla_total_size(sizeof(struct in6_addr)) /* IFLA_INET6_TOKEN */
5500 + nla_total_size(1) /* IFLA_INET6_ADDR_GEN_MODE */
5501 + 0;
Thomas Grafb382b192010-11-16 04:33:57 +00005502}
5503
Thomas Graf339bf982006-11-10 14:10:15 -08005504static inline size_t inet6_if_nlmsg_size(void)
5505{
5506 return NLMSG_ALIGN(sizeof(struct ifinfomsg))
5507 + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
5508 + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */
5509 + nla_total_size(4) /* IFLA_MTU */
5510 + nla_total_size(4) /* IFLA_LINK */
Andy Gospodarek03443382015-08-13 15:26:35 -04005511 + nla_total_size(1) /* IFLA_OPERSTATE */
Thomas Grafb382b192010-11-16 04:33:57 +00005512 + nla_total_size(inet6_ifla6_size()); /* IFLA_PROTINFO */
Thomas Graf339bf982006-11-10 14:10:15 -08005513}
YOSHIFUJI Hideakic5396a32006-06-17 22:48:48 -07005514
Eric Dumazetbe281e52011-05-19 01:14:23 +00005515static inline void __snmp6_fill_statsdev(u64 *stats, atomic_long_t *mib,
Jia Heaca05672016-09-30 11:29:03 +08005516 int bytes)
Herbert Xu7f7d9a62007-04-24 21:54:09 -07005517{
5518 int i;
Jia Heaca05672016-09-30 11:29:03 +08005519 int pad = bytes - sizeof(u64) * ICMP6_MIB_MAX;
Herbert Xu7f7d9a62007-04-24 21:54:09 -07005520 BUG_ON(pad < 0);
5521
5522 /* Use put_unaligned() because stats may not be aligned for u64. */
Jia Heaca05672016-09-30 11:29:03 +08005523 put_unaligned(ICMP6_MIB_MAX, &stats[0]);
5524 for (i = 1; i < ICMP6_MIB_MAX; i++)
Eric Dumazetbe281e52011-05-19 01:14:23 +00005525 put_unaligned(atomic_long_read(&mib[i]), &stats[i]);
Herbert Xu7f7d9a62007-04-24 21:54:09 -07005526
Jia Heaca05672016-09-30 11:29:03 +08005527 memset(&stats[ICMP6_MIB_MAX], 0, pad);
Herbert Xu7f7d9a62007-04-24 21:54:09 -07005528}
5529
WANG Cong698365f2014-05-05 15:55:55 -07005530static inline void __snmp6_fill_stats64(u64 *stats, void __percpu *mib,
Raghavendra K Ta3a77372015-08-30 11:29:42 +05305531 int bytes, size_t syncpoff)
Eric Dumazet4ce3c182010-06-30 13:31:19 -07005532{
Raghavendra K Ta3a77372015-08-30 11:29:42 +05305533 int i, c;
5534 u64 buff[IPSTATS_MIB_MAX];
5535 int pad = bytes - sizeof(u64) * IPSTATS_MIB_MAX;
5536
Eric Dumazet4ce3c182010-06-30 13:31:19 -07005537 BUG_ON(pad < 0);
5538
Raghavendra K Ta3a77372015-08-30 11:29:42 +05305539 memset(buff, 0, sizeof(buff));
5540 buff[0] = IPSTATS_MIB_MAX;
Eric Dumazet4ce3c182010-06-30 13:31:19 -07005541
Raghavendra K Ta3a77372015-08-30 11:29:42 +05305542 for_each_possible_cpu(c) {
5543 for (i = 1; i < IPSTATS_MIB_MAX; i++)
5544 buff[i] += snmp_get_cpu_field64(mib, c, i, syncpoff);
5545 }
5546
5547 memcpy(stats, buff, IPSTATS_MIB_MAX * sizeof(u64));
5548 memset(&stats[IPSTATS_MIB_MAX], 0, pad);
Eric Dumazet4ce3c182010-06-30 13:31:19 -07005549}
5550
Herbert Xu7f7d9a62007-04-24 21:54:09 -07005551static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype,
5552 int bytes)
5553{
Stephen Hemmingere21e8462010-03-20 16:09:01 -07005554 switch (attrtype) {
Herbert Xu7f7d9a62007-04-24 21:54:09 -07005555 case IFLA_INET6_STATS:
Raghavendra K Ta3a77372015-08-30 11:29:42 +05305556 __snmp6_fill_stats64(stats, idev->stats.ipv6, bytes,
5557 offsetof(struct ipstats_mib, syncp));
Herbert Xu7f7d9a62007-04-24 21:54:09 -07005558 break;
5559 case IFLA_INET6_ICMP6STATS:
Jia Heaca05672016-09-30 11:29:03 +08005560 __snmp6_fill_statsdev(stats, idev->stats.icmpv6dev->mibs, bytes);
Herbert Xu7f7d9a62007-04-24 21:54:09 -07005561 break;
5562 }
5563}
5564
Sowmini Varadhand5566fd2015-09-11 16:48:48 -04005565static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev,
5566 u32 ext_filter_mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005567{
YOSHIFUJI Hideakibf99f1b2007-04-20 15:56:20 -07005568 struct nlattr *nla;
Thomas Graf04561c12006-11-14 19:53:58 -08005569 struct ifla_cacheinfo ci;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005570
David S. Millerc78679e2012-04-01 20:27:33 -04005571 if (nla_put_u32(skb, IFLA_INET6_FLAGS, idev->if_flags))
5572 goto nla_put_failure;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005573 ci.max_reasm_len = IPV6_MAXPLEN;
David S. Miller24912422010-11-19 13:13:47 -08005574 ci.tstamp = cstamp_delta(idev->tstamp);
5575 ci.reachable_time = jiffies_to_msecs(idev->nd_parms->reachable_time);
Jiri Pirko1f9248e2013-12-07 19:26:53 +01005576 ci.retrans_time = jiffies_to_msecs(NEIGH_VAR(idev->nd_parms, RETRANS_TIME));
David S. Millerc78679e2012-04-01 20:27:33 -04005577 if (nla_put(skb, IFLA_INET6_CACHEINFO, sizeof(ci), &ci))
5578 goto nla_put_failure;
YOSHIFUJI Hideakibf99f1b2007-04-20 15:56:20 -07005579 nla = nla_reserve(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(s32));
Ian Morris63159f22015-03-29 14:00:04 +01005580 if (!nla)
Thomas Graf04561c12006-11-14 19:53:58 -08005581 goto nla_put_failure;
YOSHIFUJI Hideakibf99f1b2007-04-20 15:56:20 -07005582 ipv6_store_devconf(&idev->cnf, nla_data(nla), nla_len(nla));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005583
YOSHIFUJI Hideakibf99f1b2007-04-20 15:56:20 -07005584 /* XXX - MC not implemented */
5585
Sowmini Varadhand5566fd2015-09-11 16:48:48 -04005586 if (ext_filter_mask & RTEXT_FILTER_SKIP_STATS)
5587 return 0;
5588
YOSHIFUJI Hideakibf99f1b2007-04-20 15:56:20 -07005589 nla = nla_reserve(skb, IFLA_INET6_STATS, IPSTATS_MIB_MAX * sizeof(u64));
Ian Morris63159f22015-03-29 14:00:04 +01005590 if (!nla)
YOSHIFUJI Hideakibf99f1b2007-04-20 15:56:20 -07005591 goto nla_put_failure;
5592 snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_STATS, nla_len(nla));
5593
5594 nla = nla_reserve(skb, IFLA_INET6_ICMP6STATS, ICMP6_MIB_MAX * sizeof(u64));
Ian Morris63159f22015-03-29 14:00:04 +01005595 if (!nla)
YOSHIFUJI Hideakibf99f1b2007-04-20 15:56:20 -07005596 goto nla_put_failure;
5597 snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_ICMP6STATS, nla_len(nla));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005598
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005599 nla = nla_reserve(skb, IFLA_INET6_TOKEN, sizeof(struct in6_addr));
Ian Morris63159f22015-03-29 14:00:04 +01005600 if (!nla)
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005601 goto nla_put_failure;
5602 read_lock_bh(&idev->lock);
5603 memcpy(nla_data(nla), idev->token.s6_addr, nla_len(nla));
5604 read_unlock_bh(&idev->lock);
5605
Nicolas Dichtel0d7982c2019-09-30 14:02:16 +02005606 if (nla_put_u8(skb, IFLA_INET6_ADDR_GEN_MODE, idev->cnf.addr_gen_mode))
5607 goto nla_put_failure;
5608
Thomas Grafb382b192010-11-16 04:33:57 +00005609 return 0;
5610
5611nla_put_failure:
5612 return -EMSGSIZE;
5613}
5614
Arad, Ronenb1974ed2015-10-19 09:23:28 -07005615static size_t inet6_get_link_af_size(const struct net_device *dev,
5616 u32 ext_filter_mask)
Thomas Grafb382b192010-11-16 04:33:57 +00005617{
5618 if (!__in6_dev_get(dev))
5619 return 0;
5620
5621 return inet6_ifla6_size();
5622}
5623
Sowmini Varadhand5566fd2015-09-11 16:48:48 -04005624static int inet6_fill_link_af(struct sk_buff *skb, const struct net_device *dev,
5625 u32 ext_filter_mask)
Thomas Grafb382b192010-11-16 04:33:57 +00005626{
5627 struct inet6_dev *idev = __in6_dev_get(dev);
5628
5629 if (!idev)
5630 return -ENODATA;
5631
Sowmini Varadhand5566fd2015-09-11 16:48:48 -04005632 if (inet6_fill_ifla6_attrs(skb, idev, ext_filter_mask) < 0)
Thomas Grafb382b192010-11-16 04:33:57 +00005633 return -EMSGSIZE;
5634
5635 return 0;
5636}
5637
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005638static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token)
5639{
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005640 struct inet6_ifaddr *ifp;
5641 struct net_device *dev = idev->dev;
Daniel Borkmann47e27d52016-04-08 15:55:00 +02005642 bool clear_token, update_rs = false;
Hannes Frederic Sowadc848292013-06-24 21:42:40 +02005643 struct in6_addr ll_addr;
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005644
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01005645 ASSERT_RTNL();
5646
Ian Morris63159f22015-03-29 14:00:04 +01005647 if (!token)
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005648 return -EINVAL;
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005649 if (dev->flags & (IFF_LOOPBACK | IFF_NOARP))
5650 return -EINVAL;
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005651 if (!ipv6_accept_ra(idev))
5652 return -EINVAL;
Maciej Żenczykowskibd11f072016-09-27 23:57:58 -07005653 if (idev->cnf.rtr_solicits == 0)
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005654 return -EINVAL;
5655
5656 write_lock_bh(&idev->lock);
5657
5658 BUILD_BUG_ON(sizeof(token->s6_addr) != 16);
5659 memcpy(idev->token.s6_addr + 8, token->s6_addr + 8, 8);
5660
5661 write_unlock_bh(&idev->lock);
5662
Daniel Borkmann47e27d52016-04-08 15:55:00 +02005663 clear_token = ipv6_addr_any(token);
5664 if (clear_token)
5665 goto update_lft;
5666
Hannes Frederic Sowadc848292013-06-24 21:42:40 +02005667 if (!idev->dead && (idev->if_flags & IF_READY) &&
5668 !ipv6_get_lladdr(dev, &ll_addr, IFA_F_TENTATIVE |
5669 IFA_F_OPTIMISTIC)) {
Daniel Borkmannfc403832013-04-09 03:47:15 +00005670 /* If we're not ready, then normal ifup will take care
5671 * of this. Otherwise, we need to request our rs here.
5672 */
5673 ndisc_send_rs(dev, &ll_addr, &in6addr_linklocal_allrouters);
5674 update_rs = true;
5675 }
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005676
Daniel Borkmann47e27d52016-04-08 15:55:00 +02005677update_lft:
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005678 write_lock_bh(&idev->lock);
Daniel Borkmannfc403832013-04-09 03:47:15 +00005679
Hannes Frederic Sowa77ecaac2013-06-26 03:41:49 +02005680 if (update_rs) {
Daniel Borkmannfc403832013-04-09 03:47:15 +00005681 idev->if_flags |= IF_RS_SENT;
Maciej Żenczykowskibd11f072016-09-27 23:57:58 -07005682 idev->rs_interval = rfc3315_s14_backoff_init(
5683 idev->cnf.rtr_solicit_interval);
Hannes Frederic Sowa77ecaac2013-06-26 03:41:49 +02005684 idev->rs_probes = 1;
Maciej Żenczykowskibd11f072016-09-27 23:57:58 -07005685 addrconf_mod_rs_timer(idev, idev->rs_interval);
Hannes Frederic Sowa77ecaac2013-06-26 03:41:49 +02005686 }
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005687
5688 /* Well, that's kinda nasty ... */
5689 list_for_each_entry(ifp, &idev->addr_list, if_list) {
5690 spin_lock(&ifp->lock);
Daniel Borkmann617fe292013-04-09 03:47:16 +00005691 if (ifp->tokenized) {
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005692 ifp->valid_lft = 0;
5693 ifp->prefered_lft = 0;
5694 }
5695 spin_unlock(&ifp->lock);
5696 }
5697
5698 write_unlock_bh(&idev->lock);
Lubomir Rintelb2ed64a2014-10-27 17:39:16 +01005699 inet6_ifinfo_notify(RTM_NEWLINK, idev);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01005700 addrconf_verify_rtnl();
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005701 return 0;
5702}
5703
Daniel Borkmann11b1f822015-02-05 14:39:11 +01005704static const struct nla_policy inet6_af_policy[IFLA_INET6_MAX + 1] = {
5705 [IFLA_INET6_ADDR_GEN_MODE] = { .type = NLA_U8 },
5706 [IFLA_INET6_TOKEN] = { .len = sizeof(struct in6_addr) },
5707};
5708
Felix Jiad35a00b2017-01-26 16:59:17 +13005709static int check_addr_gen_mode(int mode)
5710{
5711 if (mode != IN6_ADDR_GEN_MODE_EUI64 &&
5712 mode != IN6_ADDR_GEN_MODE_NONE &&
5713 mode != IN6_ADDR_GEN_MODE_STABLE_PRIVACY &&
5714 mode != IN6_ADDR_GEN_MODE_RANDOM)
5715 return -EINVAL;
5716 return 1;
5717}
5718
5719static int check_stable_privacy(struct inet6_dev *idev, struct net *net,
5720 int mode)
5721{
5722 if (mode == IN6_ADDR_GEN_MODE_STABLE_PRIVACY &&
5723 !idev->cnf.stable_secret.initialized &&
5724 !net->ipv6.devconf_dflt->stable_secret.initialized)
5725 return -EINVAL;
5726 return 1;
5727}
5728
Maxim Mikityanskiy7dc2bcc2019-05-21 06:40:04 +00005729static int inet6_validate_link_af(const struct net_device *dev,
5730 const struct nlattr *nla)
5731{
5732 struct nlattr *tb[IFLA_INET6_MAX + 1];
5733 struct inet6_dev *idev = NULL;
5734 int err;
5735
5736 if (dev) {
5737 idev = __in6_dev_get(dev);
5738 if (!idev)
5739 return -EAFNOSUPPORT;
5740 }
5741
5742 err = nla_parse_nested_deprecated(tb, IFLA_INET6_MAX, nla,
5743 inet6_af_policy, NULL);
5744 if (err)
5745 return err;
5746
5747 if (!tb[IFLA_INET6_TOKEN] && !tb[IFLA_INET6_ADDR_GEN_MODE])
5748 return -EINVAL;
5749
5750 if (tb[IFLA_INET6_ADDR_GEN_MODE]) {
5751 u8 mode = nla_get_u8(tb[IFLA_INET6_ADDR_GEN_MODE]);
5752
5753 if (check_addr_gen_mode(mode) < 0)
5754 return -EINVAL;
5755 if (dev && check_stable_privacy(idev, dev_net(dev), mode) < 0)
5756 return -EINVAL;
5757 }
5758
5759 return 0;
5760}
5761
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005762static int inet6_set_link_af(struct net_device *dev, const struct nlattr *nla)
5763{
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005764 struct inet6_dev *idev = __in6_dev_get(dev);
5765 struct nlattr *tb[IFLA_INET6_MAX + 1];
Maxim Mikityanskiy7dc2bcc2019-05-21 06:40:04 +00005766 int err;
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005767
Eric Dumazetdb3fa272020-02-07 07:16:37 -08005768 if (!idev)
5769 return -EAFNOSUPPORT;
5770
Johannes Berg8cb08172019-04-26 14:07:28 +02005771 if (nla_parse_nested_deprecated(tb, IFLA_INET6_MAX, nla, NULL, NULL) < 0)
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005772 BUG();
5773
Jiri Pirkobc91b0f2014-07-11 21:10:18 +02005774 if (tb[IFLA_INET6_TOKEN]) {
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005775 err = inet6_set_iftoken(idev, nla_data(tb[IFLA_INET6_TOKEN]));
Jiri Pirkobc91b0f2014-07-11 21:10:18 +02005776 if (err)
5777 return err;
5778 }
5779
5780 if (tb[IFLA_INET6_ADDR_GEN_MODE]) {
5781 u8 mode = nla_get_u8(tb[IFLA_INET6_ADDR_GEN_MODE]);
5782
Felix Jiad35a00b2017-01-26 16:59:17 +13005783 idev->cnf.addr_gen_mode = mode;
Jiri Pirkobc91b0f2014-07-11 21:10:18 +02005784 }
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005785
Maxim Mikityanskiy7dc2bcc2019-05-21 06:40:04 +00005786 return 0;
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005787}
5788
Thomas Grafb382b192010-11-16 04:33:57 +00005789static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
Eric W. Biederman15e47302012-09-07 20:12:54 +00005790 u32 portid, u32 seq, int event, unsigned int flags)
Thomas Grafb382b192010-11-16 04:33:57 +00005791{
5792 struct net_device *dev = idev->dev;
5793 struct ifinfomsg *hdr;
5794 struct nlmsghdr *nlh;
5795 void *protoinfo;
5796
Eric W. Biederman15e47302012-09-07 20:12:54 +00005797 nlh = nlmsg_put(skb, portid, seq, event, sizeof(*hdr), flags);
Ian Morris63159f22015-03-29 14:00:04 +01005798 if (!nlh)
Thomas Grafb382b192010-11-16 04:33:57 +00005799 return -EMSGSIZE;
5800
5801 hdr = nlmsg_data(nlh);
5802 hdr->ifi_family = AF_INET6;
5803 hdr->__ifi_pad = 0;
5804 hdr->ifi_type = dev->type;
5805 hdr->ifi_index = dev->ifindex;
5806 hdr->ifi_flags = dev_get_flags(dev);
5807 hdr->ifi_change = 0;
5808
David S. Millerc78679e2012-04-01 20:27:33 -04005809 if (nla_put_string(skb, IFLA_IFNAME, dev->name) ||
5810 (dev->addr_len &&
5811 nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr)) ||
5812 nla_put_u32(skb, IFLA_MTU, dev->mtu) ||
Nicolas Dichtela54acb32015-04-02 17:07:00 +02005813 (dev->ifindex != dev_get_iflink(dev) &&
Andy Gospodarek03443382015-08-13 15:26:35 -04005814 nla_put_u32(skb, IFLA_LINK, dev_get_iflink(dev))) ||
5815 nla_put_u8(skb, IFLA_OPERSTATE,
5816 netif_running(dev) ? dev->operstate : IF_OPER_DOWN))
David S. Millerc78679e2012-04-01 20:27:33 -04005817 goto nla_put_failure;
Michal Kubecekae0be8d2019-04-26 11:13:06 +02005818 protoinfo = nla_nest_start_noflag(skb, IFLA_PROTINFO);
Ian Morris63159f22015-03-29 14:00:04 +01005819 if (!protoinfo)
Thomas Grafb382b192010-11-16 04:33:57 +00005820 goto nla_put_failure;
5821
Sowmini Varadhand5566fd2015-09-11 16:48:48 -04005822 if (inet6_fill_ifla6_attrs(skb, idev, 0) < 0)
Thomas Grafb382b192010-11-16 04:33:57 +00005823 goto nla_put_failure;
5824
Thomas Graf04561c12006-11-14 19:53:58 -08005825 nla_nest_end(skb, protoinfo);
Johannes Berg053c0952015-01-16 22:09:00 +01005826 nlmsg_end(skb, nlh);
5827 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005828
Thomas Graf04561c12006-11-14 19:53:58 -08005829nla_put_failure:
Patrick McHardy26932562007-01-31 23:16:40 -08005830 nlmsg_cancel(skb, nlh);
5831 return -EMSGSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005832}
5833
David Ahern786e0002018-10-07 20:16:33 -07005834static int inet6_valid_dump_ifinfo(const struct nlmsghdr *nlh,
5835 struct netlink_ext_ack *extack)
5836{
5837 struct ifinfomsg *ifm;
5838
5839 if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ifm))) {
5840 NL_SET_ERR_MSG_MOD(extack, "Invalid header for link dump request");
5841 return -EINVAL;
5842 }
5843
5844 if (nlmsg_attrlen(nlh, sizeof(*ifm))) {
5845 NL_SET_ERR_MSG_MOD(extack, "Invalid data after header");
5846 return -EINVAL;
5847 }
5848
5849 ifm = nlmsg_data(nlh);
5850 if (ifm->__ifi_pad || ifm->ifi_type || ifm->ifi_flags ||
5851 ifm->ifi_change || ifm->ifi_index) {
5852 NL_SET_ERR_MSG_MOD(extack, "Invalid values in header for dump request");
5853 return -EINVAL;
5854 }
5855
5856 return 0;
5857}
5858
Linus Torvalds1da177e2005-04-16 15:20:36 -07005859static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
5860{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09005861 struct net *net = sock_net(skb->sk);
Eric Dumazet84d26972009-11-09 12:11:28 +00005862 int h, s_h;
David S. Miller434a8a52009-11-11 18:53:00 -08005863 int idx = 0, s_idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005864 struct net_device *dev;
5865 struct inet6_dev *idev;
Eric Dumazet84d26972009-11-09 12:11:28 +00005866 struct hlist_head *head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005867
David Ahern786e0002018-10-07 20:16:33 -07005868 /* only requests using strict checking can pass data to
5869 * influence the dump
5870 */
5871 if (cb->strict_check) {
5872 int err = inet6_valid_dump_ifinfo(cb->nlh, cb->extack);
5873
5874 if (err < 0)
5875 return err;
5876 }
5877
Eric Dumazet84d26972009-11-09 12:11:28 +00005878 s_h = cb->args[0];
5879 s_idx = cb->args[1];
5880
5881 rcu_read_lock();
5882 for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
5883 idx = 0;
5884 head = &net->dev_index_head[h];
Sasha Levinb67bfe02013-02-27 17:06:00 -08005885 hlist_for_each_entry_rcu(dev, head, index_hlist) {
Eric Dumazet84d26972009-11-09 12:11:28 +00005886 if (idx < s_idx)
5887 goto cont;
5888 idev = __in6_dev_get(dev);
5889 if (!idev)
5890 goto cont;
5891 if (inet6_fill_ifinfo(skb, idev,
Eric W. Biederman15e47302012-09-07 20:12:54 +00005892 NETLINK_CB(cb->skb).portid,
Eric Dumazet84d26972009-11-09 12:11:28 +00005893 cb->nlh->nlmsg_seq,
Johannes Berg053c0952015-01-16 22:09:00 +01005894 RTM_NEWLINK, NLM_F_MULTI) < 0)
Eric Dumazet84d26972009-11-09 12:11:28 +00005895 goto out;
Pavel Emelianov7562f872007-05-03 15:13:45 -07005896cont:
Eric Dumazet84d26972009-11-09 12:11:28 +00005897 idx++;
5898 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005899 }
Eric Dumazet84d26972009-11-09 12:11:28 +00005900out:
5901 rcu_read_unlock();
5902 cb->args[1] = idx;
5903 cb->args[0] = h;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005904
5905 return skb->len;
5906}
5907
5908void inet6_ifinfo_notify(int event, struct inet6_dev *idev)
5909{
5910 struct sk_buff *skb;
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09005911 struct net *net = dev_net(idev->dev);
Thomas Graf8d7a76c2006-08-15 00:35:47 -07005912 int err = -ENOBUFS;
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09005913
Thomas Graf339bf982006-11-10 14:10:15 -08005914 skb = nlmsg_new(inet6_if_nlmsg_size(), GFP_ATOMIC);
Ian Morris63159f22015-03-29 14:00:04 +01005915 if (!skb)
Thomas Graf8d7a76c2006-08-15 00:35:47 -07005916 goto errout;
5917
5918 err = inet6_fill_ifinfo(skb, idev, 0, 0, event, 0);
Patrick McHardy26932562007-01-31 23:16:40 -08005919 if (err < 0) {
5920 /* -EMSGSIZE implies BUG in inet6_if_nlmsg_size() */
5921 WARN_ON(err == -EMSGSIZE);
5922 kfree_skb(skb);
5923 goto errout;
5924 }
Nicolas Dichtel5f75a102010-12-07 23:38:31 +00005925 rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFINFO, NULL, GFP_ATOMIC);
Pablo Neira Ayuso1ce85fe2009-02-24 23:18:28 -08005926 return;
Thomas Graf8d7a76c2006-08-15 00:35:47 -07005927errout:
5928 if (err < 0)
Nicolas Dichtel5f75a102010-12-07 23:38:31 +00005929 rtnl_set_sk_err(net, RTNLGRP_IPV6_IFINFO, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005930}
5931
Thomas Graf339bf982006-11-10 14:10:15 -08005932static inline size_t inet6_prefix_nlmsg_size(void)
5933{
5934 return NLMSG_ALIGN(sizeof(struct prefixmsg))
5935 + nla_total_size(sizeof(struct in6_addr))
5936 + nla_total_size(sizeof(struct prefix_cacheinfo));
5937}
YOSHIFUJI Hideakic5396a32006-06-17 22:48:48 -07005938
Linus Torvalds1da177e2005-04-16 15:20:36 -07005939static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev,
Eric W. Biederman15e47302012-09-07 20:12:54 +00005940 struct prefix_info *pinfo, u32 portid, u32 seq,
Thomas Graf6051e2f2006-11-14 19:54:19 -08005941 int event, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005942{
Thomas Graf6051e2f2006-11-14 19:54:19 -08005943 struct prefixmsg *pmsg;
5944 struct nlmsghdr *nlh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005945 struct prefix_cacheinfo ci;
5946
Eric W. Biederman15e47302012-09-07 20:12:54 +00005947 nlh = nlmsg_put(skb, portid, seq, event, sizeof(*pmsg), flags);
Ian Morris63159f22015-03-29 14:00:04 +01005948 if (!nlh)
Patrick McHardy26932562007-01-31 23:16:40 -08005949 return -EMSGSIZE;
Thomas Graf6051e2f2006-11-14 19:54:19 -08005950
5951 pmsg = nlmsg_data(nlh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005952 pmsg->prefix_family = AF_INET6;
Patrick McHardy8a470772005-06-28 12:56:45 -07005953 pmsg->prefix_pad1 = 0;
5954 pmsg->prefix_pad2 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005955 pmsg->prefix_ifindex = idev->dev->ifindex;
5956 pmsg->prefix_len = pinfo->prefix_len;
5957 pmsg->prefix_type = pinfo->type;
Patrick McHardy8a470772005-06-28 12:56:45 -07005958 pmsg->prefix_pad3 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005959 pmsg->prefix_flags = 0;
5960 if (pinfo->onlink)
5961 pmsg->prefix_flags |= IF_PREFIX_ONLINK;
5962 if (pinfo->autoconf)
5963 pmsg->prefix_flags |= IF_PREFIX_AUTOCONF;
5964
David S. Millerc78679e2012-04-01 20:27:33 -04005965 if (nla_put(skb, PREFIX_ADDRESS, sizeof(pinfo->prefix), &pinfo->prefix))
5966 goto nla_put_failure;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005967 ci.preferred_time = ntohl(pinfo->prefered);
5968 ci.valid_time = ntohl(pinfo->valid);
David S. Millerc78679e2012-04-01 20:27:33 -04005969 if (nla_put(skb, PREFIX_CACHEINFO, sizeof(ci), &ci))
5970 goto nla_put_failure;
Johannes Berg053c0952015-01-16 22:09:00 +01005971 nlmsg_end(skb, nlh);
5972 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005973
Thomas Graf6051e2f2006-11-14 19:54:19 -08005974nla_put_failure:
Patrick McHardy26932562007-01-31 23:16:40 -08005975 nlmsg_cancel(skb, nlh);
5976 return -EMSGSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005977}
5978
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09005979static void inet6_prefix_notify(int event, struct inet6_dev *idev,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005980 struct prefix_info *pinfo)
5981{
5982 struct sk_buff *skb;
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09005983 struct net *net = dev_net(idev->dev);
Thomas Graf8c384bfa2006-08-15 00:36:07 -07005984 int err = -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005985
Thomas Graf339bf982006-11-10 14:10:15 -08005986 skb = nlmsg_new(inet6_prefix_nlmsg_size(), GFP_ATOMIC);
Ian Morris63159f22015-03-29 14:00:04 +01005987 if (!skb)
Thomas Graf8c384bfa2006-08-15 00:36:07 -07005988 goto errout;
5989
5990 err = inet6_fill_prefix(skb, idev, pinfo, 0, 0, event, 0);
Patrick McHardy26932562007-01-31 23:16:40 -08005991 if (err < 0) {
5992 /* -EMSGSIZE implies BUG in inet6_prefix_nlmsg_size() */
5993 WARN_ON(err == -EMSGSIZE);
5994 kfree_skb(skb);
5995 goto errout;
5996 }
Pablo Neira Ayuso1ce85fe2009-02-24 23:18:28 -08005997 rtnl_notify(skb, net, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC);
5998 return;
Thomas Graf8c384bfa2006-08-15 00:36:07 -07005999errout:
6000 if (err < 0)
Benjamin Thery6fda7352008-03-05 10:47:47 -08006001 rtnl_set_sk_err(net, RTNLGRP_IPV6_PREFIX, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006002}
6003
Linus Torvalds1da177e2005-04-16 15:20:36 -07006004static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
6005{
Nicolas Dichtel63998ac2013-03-22 06:28:43 +00006006 struct net *net = dev_net(ifp->idev->dev);
6007
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01006008 if (event)
6009 ASSERT_RTNL();
6010
Linus Torvalds1da177e2005-04-16 15:20:36 -07006011 inet6_ifa_notify(event ? : RTM_NEWADDR, ifp);
6012
6013 switch (event) {
6014 case RTM_NEWADDR:
Neil Horman95c385b2007-04-25 17:08:10 -07006015 /*
David Ahern2d819d252019-10-04 08:03:09 -07006016 * If the address was optimistic we inserted the route at the
6017 * start of our DAD process, so we don't need to do it again.
6018 * If the device was taken down in the middle of the DAD
6019 * cycle there is a race where we could get here without a
6020 * host route, so nothing to insert. That will be fixed when
6021 * the device is brought up.
Neil Horman95c385b2007-04-25 17:08:10 -07006022 */
David Ahern2d819d252019-10-04 08:03:09 -07006023 if (ifp->rt && !rcu_access_pointer(ifp->rt->fib6_node)) {
David Ahernafb1d4b52018-04-17 17:33:11 -07006024 ip6_ins_rt(net, ifp->rt);
David Ahern2d819d252019-10-04 08:03:09 -07006025 } else if (!ifp->rt && (ifp->idev->dev->flags & IFF_UP)) {
6026 pr_warn("BUG: Address %pI6c on device %s is missing its host route.\n",
6027 &ifp->addr, ifp->idev->dev->name);
6028 }
6029
Linus Torvalds1da177e2005-04-16 15:20:36 -07006030 if (ifp->idev->cnf.forwarding)
6031 addrconf_join_anycast(ifp);
Cong Wang7996c792013-05-22 05:41:06 +00006032 if (!ipv6_addr_any(&ifp->peer_addr))
Hangbin Liu07758eb2020-02-29 17:27:13 +08006033 addrconf_prefix_route(&ifp->peer_addr, 128,
6034 ifp->rt_priority, ifp->idev->dev,
6035 0, 0, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006036 break;
6037 case RTM_DELADDR:
6038 if (ifp->idev->cnf.forwarding)
6039 addrconf_leave_anycast(ifp);
6040 addrconf_leave_solict(ifp->idev, &ifp->addr);
Cong Wang7996c792013-05-22 05:41:06 +00006041 if (!ipv6_addr_any(&ifp->peer_addr)) {
David Ahern8d1c8022018-04-17 17:33:26 -07006042 struct fib6_info *rt;
Nicolas Dichtelcaeaba72013-05-16 22:32:00 +00006043
Nicolas Dichtele7478df2014-09-03 23:59:22 +02006044 rt = addrconf_get_prefix_route(&ifp->peer_addr, 128,
David Ahern2b2450c2019-03-27 20:53:52 -07006045 ifp->idev->dev, 0, 0,
6046 false);
Martin KaFai Lau8e3d5be2015-09-15 14:30:08 -07006047 if (rt)
Roopa Prabhu11dd74b2020-04-27 13:56:45 -07006048 ip6_del_rt(net, rt, false);
Nicolas Dichtelcaeaba72013-05-16 22:32:00 +00006049 }
David Ahern38bd10c2016-04-21 20:56:12 -07006050 if (ifp->rt) {
Roopa Prabhu11dd74b2020-04-27 13:56:45 -07006051 ip6_del_rt(net, ifp->rt, false);
David Ahern93531c62018-04-17 17:33:25 -07006052 ifp->rt = NULL;
David Ahern38bd10c2016-04-21 20:56:12 -07006053 }
Hannes Frederic Sowa705f1c82014-09-28 00:46:06 +02006054 rt_genid_bump_ipv6(net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006055 break;
6056 }
Nicolas Dichtel63998ac2013-03-22 06:28:43 +00006057 atomic_inc(&net->ipv6.dev_addr_genid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006058}
6059
6060static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
6061{
YOSHIFUJI Hideaki8814c4b2006-09-22 14:44:24 -07006062 rcu_read_lock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006063 if (likely(ifp->idev->dead == 0))
6064 __ipv6_ifa_notify(event, ifp);
YOSHIFUJI Hideaki8814c4b2006-09-22 14:44:24 -07006065 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006066}
6067
6068#ifdef CONFIG_SYSCTL
6069
Christoph Hellwig32927392020-04-24 08:43:38 +02006070static int addrconf_sysctl_forward(struct ctl_table *ctl, int write,
6071 void *buffer, size_t *lenp, loff_t *ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006072{
6073 int *valp = ctl->data;
6074 int val = *valp;
Eric W. Biederman88af1822010-02-19 13:22:59 +00006075 loff_t pos = *ppos;
Joe Perchesfe2c6332013-06-11 23:04:25 -07006076 struct ctl_table lctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006077 int ret;
6078
Francesco Ruggeri013d97e2012-01-16 10:40:10 +00006079 /*
6080 * ctl->data points to idev->cnf.forwarding, we should
6081 * not modify it until we get the rtnl lock.
6082 */
6083 lctl = *ctl;
6084 lctl.data = &val;
6085
6086 ret = proc_dointvec(&lctl, write, buffer, lenp, ppos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006087
Pavel Emelyanovc8fecf22007-12-05 01:50:24 -08006088 if (write)
Stephen Hemmingerb325fdd2009-02-26 06:55:31 +00006089 ret = addrconf_fixup_forwarding(ctl, valp, val);
Eric W. Biederman88af1822010-02-19 13:22:59 +00006090 if (ret)
6091 *ppos = pos;
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09006092 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006093}
6094
Christoph Hellwig32927392020-04-24 08:43:38 +02006095static int addrconf_sysctl_mtu(struct ctl_table *ctl, int write,
6096 void *buffer, size_t *lenp, loff_t *ppos)
Marcelo Leitner77751422015-02-23 11:17:13 -03006097{
6098 struct inet6_dev *idev = ctl->extra1;
6099 int min_mtu = IPV6_MIN_MTU;
6100 struct ctl_table lctl;
6101
6102 lctl = *ctl;
6103 lctl.extra1 = &min_mtu;
6104 lctl.extra2 = idev ? &idev->dev->mtu : NULL;
6105
6106 return proc_dointvec_minmax(&lctl, write, buffer, lenp, ppos);
6107}
6108
Brian Haley56d417b2009-06-01 03:07:33 -07006109static void dev_disable_change(struct inet6_dev *idev)
6110{
Cong Wang75538c22013-05-29 11:30:50 +08006111 struct netdev_notifier_info info;
6112
Brian Haley56d417b2009-06-01 03:07:33 -07006113 if (!idev || !idev->dev)
6114 return;
6115
Cong Wang75538c22013-05-29 11:30:50 +08006116 netdev_notifier_info_init(&info, idev->dev);
Brian Haley56d417b2009-06-01 03:07:33 -07006117 if (idev->cnf.disable_ipv6)
Cong Wang75538c22013-05-29 11:30:50 +08006118 addrconf_notify(NULL, NETDEV_DOWN, &info);
Brian Haley56d417b2009-06-01 03:07:33 -07006119 else
Cong Wang75538c22013-05-29 11:30:50 +08006120 addrconf_notify(NULL, NETDEV_UP, &info);
Brian Haley56d417b2009-06-01 03:07:33 -07006121}
6122
6123static void addrconf_disable_change(struct net *net, __s32 newf)
6124{
6125 struct net_device *dev;
6126 struct inet6_dev *idev;
6127
Kefeng Wang03e4def2017-01-19 16:26:21 +08006128 for_each_netdev(net, dev) {
Brian Haley56d417b2009-06-01 03:07:33 -07006129 idev = __in6_dev_get(dev);
6130 if (idev) {
6131 int changed = (!idev->cnf.disable_ipv6) ^ (!newf);
6132 idev->cnf.disable_ipv6 = newf;
6133 if (changed)
6134 dev_disable_change(idev);
6135 }
Brian Haley56d417b2009-06-01 03:07:33 -07006136 }
Brian Haley56d417b2009-06-01 03:07:33 -07006137}
6138
Francesco Ruggeri013d97e2012-01-16 10:40:10 +00006139static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int newf)
Brian Haley56d417b2009-06-01 03:07:33 -07006140{
6141 struct net *net;
Francesco Ruggeri013d97e2012-01-16 10:40:10 +00006142 int old;
6143
6144 if (!rtnl_trylock())
6145 return restart_syscall();
Brian Haley56d417b2009-06-01 03:07:33 -07006146
6147 net = (struct net *)table->extra2;
Francesco Ruggeri013d97e2012-01-16 10:40:10 +00006148 old = *p;
6149 *p = newf;
Brian Haley56d417b2009-06-01 03:07:33 -07006150
Francesco Ruggeri013d97e2012-01-16 10:40:10 +00006151 if (p == &net->ipv6.devconf_dflt->disable_ipv6) {
6152 rtnl_unlock();
Brian Haley56d417b2009-06-01 03:07:33 -07006153 return 0;
Eric W. Biederman88af1822010-02-19 13:22:59 +00006154 }
Brian Haley56d417b2009-06-01 03:07:33 -07006155
6156 if (p == &net->ipv6.devconf_all->disable_ipv6) {
Brian Haley56d417b2009-06-01 03:07:33 -07006157 net->ipv6.devconf_dflt->disable_ipv6 = newf;
6158 addrconf_disable_change(net, newf);
Francesco Ruggeri013d97e2012-01-16 10:40:10 +00006159 } else if ((!newf) ^ (!old))
Brian Haley56d417b2009-06-01 03:07:33 -07006160 dev_disable_change((struct inet6_dev *)table->extra1);
6161
6162 rtnl_unlock();
6163 return 0;
6164}
6165
Christoph Hellwig32927392020-04-24 08:43:38 +02006166static int addrconf_sysctl_disable(struct ctl_table *ctl, int write,
6167 void *buffer, size_t *lenp, loff_t *ppos)
Brian Haley56d417b2009-06-01 03:07:33 -07006168{
6169 int *valp = ctl->data;
6170 int val = *valp;
Eric W. Biederman88af1822010-02-19 13:22:59 +00006171 loff_t pos = *ppos;
Joe Perchesfe2c6332013-06-11 23:04:25 -07006172 struct ctl_table lctl;
Brian Haley56d417b2009-06-01 03:07:33 -07006173 int ret;
6174
Francesco Ruggeri013d97e2012-01-16 10:40:10 +00006175 /*
6176 * ctl->data points to idev->cnf.disable_ipv6, we should
6177 * not modify it until we get the rtnl lock.
6178 */
6179 lctl = *ctl;
6180 lctl.data = &val;
6181
6182 ret = proc_dointvec(&lctl, write, buffer, lenp, ppos);
Brian Haley56d417b2009-06-01 03:07:33 -07006183
6184 if (write)
6185 ret = addrconf_disable_ipv6(ctl, valp, val);
Eric W. Biederman88af1822010-02-19 13:22:59 +00006186 if (ret)
6187 *ppos = pos;
Brian Haley56d417b2009-06-01 03:07:33 -07006188 return ret;
6189}
6190
Christoph Hellwig32927392020-04-24 08:43:38 +02006191static int addrconf_sysctl_proxy_ndp(struct ctl_table *ctl, int write,
6192 void *buffer, size_t *lenp, loff_t *ppos)
stephen hemmingerc92d5492013-12-17 22:37:14 -08006193{
6194 int *valp = ctl->data;
6195 int ret;
6196 int old, new;
6197
6198 old = *valp;
6199 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
6200 new = *valp;
6201
6202 if (write && old != new) {
6203 struct net *net = ctl->extra2;
6204
6205 if (!rtnl_trylock())
6206 return restart_syscall();
6207
6208 if (valp == &net->ipv6.devconf_dflt->proxy_ndp)
David Ahern85b3daa2017-03-28 14:28:04 -07006209 inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
6210 NETCONFA_PROXY_NEIGH,
stephen hemmingerc92d5492013-12-17 22:37:14 -08006211 NETCONFA_IFINDEX_DEFAULT,
6212 net->ipv6.devconf_dflt);
6213 else if (valp == &net->ipv6.devconf_all->proxy_ndp)
David Ahern85b3daa2017-03-28 14:28:04 -07006214 inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
6215 NETCONFA_PROXY_NEIGH,
stephen hemmingerc92d5492013-12-17 22:37:14 -08006216 NETCONFA_IFINDEX_ALL,
6217 net->ipv6.devconf_all);
6218 else {
6219 struct inet6_dev *idev = ctl->extra1;
6220
David Ahern85b3daa2017-03-28 14:28:04 -07006221 inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
6222 NETCONFA_PROXY_NEIGH,
stephen hemmingerc92d5492013-12-17 22:37:14 -08006223 idev->dev->ifindex,
6224 &idev->cnf);
6225 }
6226 rtnl_unlock();
6227 }
6228
6229 return ret;
6230}
6231
Felix Jiad35a00b2017-01-26 16:59:17 +13006232static int addrconf_sysctl_addr_gen_mode(struct ctl_table *ctl, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +02006233 void *buffer, size_t *lenp,
Felix Jiad35a00b2017-01-26 16:59:17 +13006234 loff_t *ppos)
6235{
6236 int ret = 0;
Sabrina Dubrocac6dbf7a2018-07-09 12:25:14 +02006237 u32 new_val;
Felix Jiad35a00b2017-01-26 16:59:17 +13006238 struct inet6_dev *idev = (struct inet6_dev *)ctl->extra1;
6239 struct net *net = (struct net *)ctl->extra2;
Sabrina Dubrocac6dbf7a2018-07-09 12:25:14 +02006240 struct ctl_table tmp = {
6241 .data = &new_val,
6242 .maxlen = sizeof(new_val),
6243 .mode = ctl->mode,
6244 };
Felix Jiad35a00b2017-01-26 16:59:17 +13006245
Felix Jia8c171d62017-02-27 12:41:23 +13006246 if (!rtnl_trylock())
6247 return restart_syscall();
6248
Sabrina Dubrocac6dbf7a2018-07-09 12:25:14 +02006249 new_val = *((u32 *)ctl->data);
6250
6251 ret = proc_douintvec(&tmp, write, buffer, lenp, ppos);
6252 if (ret != 0)
6253 goto out;
Felix Jiad35a00b2017-01-26 16:59:17 +13006254
6255 if (write) {
Felix Jia8c171d62017-02-27 12:41:23 +13006256 if (check_addr_gen_mode(new_val) < 0) {
6257 ret = -EINVAL;
6258 goto out;
6259 }
Felix Jiad35a00b2017-01-26 16:59:17 +13006260
Sabrina Dubrocac6dbf7a2018-07-09 12:25:14 +02006261 if (idev) {
Felix Jia8c171d62017-02-27 12:41:23 +13006262 if (check_stable_privacy(idev, net, new_val) < 0) {
6263 ret = -EINVAL;
6264 goto out;
6265 }
Felix Jiad35a00b2017-01-26 16:59:17 +13006266
6267 if (idev->cnf.addr_gen_mode != new_val) {
6268 idev->cnf.addr_gen_mode = new_val;
Felix Jiad35a00b2017-01-26 16:59:17 +13006269 addrconf_dev_config(idev->dev);
Felix Jiad35a00b2017-01-26 16:59:17 +13006270 }
Sabrina Dubrocaf24c5982018-07-09 12:25:17 +02006271 } else if (&net->ipv6.devconf_all->addr_gen_mode == ctl->data) {
6272 struct net_device *dev;
6273
6274 net->ipv6.devconf_dflt->addr_gen_mode = new_val;
6275 for_each_netdev(net, dev) {
6276 idev = __in6_dev_get(dev);
6277 if (idev &&
6278 idev->cnf.addr_gen_mode != new_val) {
6279 idev->cnf.addr_gen_mode = new_val;
6280 addrconf_dev_config(idev->dev);
6281 }
6282 }
Felix Jiad35a00b2017-01-26 16:59:17 +13006283 }
Sabrina Dubrocac6dbf7a2018-07-09 12:25:14 +02006284
6285 *((u32 *)ctl->data) = new_val;
Felix Jiad35a00b2017-01-26 16:59:17 +13006286 }
6287
Felix Jia8c171d62017-02-27 12:41:23 +13006288out:
6289 rtnl_unlock();
6290
Felix Jiad35a00b2017-01-26 16:59:17 +13006291 return ret;
6292}
6293
Hannes Frederic Sowa3d1bec92015-03-23 23:36:00 +01006294static int addrconf_sysctl_stable_secret(struct ctl_table *ctl, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +02006295 void *buffer, size_t *lenp,
Hannes Frederic Sowa3d1bec92015-03-23 23:36:00 +01006296 loff_t *ppos)
6297{
6298 int err;
6299 struct in6_addr addr;
6300 char str[IPV6_MAX_STRLEN];
6301 struct ctl_table lctl = *ctl;
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01006302 struct net *net = ctl->extra2;
Hannes Frederic Sowa3d1bec92015-03-23 23:36:00 +01006303 struct ipv6_stable_secret *secret = ctl->data;
6304
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01006305 if (&net->ipv6.devconf_all->stable_secret == ctl->data)
6306 return -EIO;
6307
Hannes Frederic Sowa3d1bec92015-03-23 23:36:00 +01006308 lctl.maxlen = IPV6_MAX_STRLEN;
6309 lctl.data = str;
6310
6311 if (!rtnl_trylock())
6312 return restart_syscall();
6313
6314 if (!write && !secret->initialized) {
6315 err = -EIO;
6316 goto out;
6317 }
6318
WANG Cong5449a5c2015-12-21 10:55:45 -08006319 err = snprintf(str, sizeof(str), "%pI6", &secret->secret);
6320 if (err >= sizeof(str)) {
6321 err = -EIO;
6322 goto out;
Hannes Frederic Sowa3d1bec92015-03-23 23:36:00 +01006323 }
6324
6325 err = proc_dostring(&lctl, write, buffer, lenp, ppos);
6326 if (err || !write)
6327 goto out;
6328
6329 if (in6_pton(str, -1, addr.in6_u.u6_addr8, -1, NULL) != 1) {
6330 err = -EIO;
6331 goto out;
6332 }
6333
6334 secret->initialized = true;
6335 secret->secret = addr;
6336
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01006337 if (&net->ipv6.devconf_dflt->stable_secret == ctl->data) {
6338 struct net_device *dev;
6339
6340 for_each_netdev(net, dev) {
6341 struct inet6_dev *idev = __in6_dev_get(dev);
6342
6343 if (idev) {
Felix Jiad35a00b2017-01-26 16:59:17 +13006344 idev->cnf.addr_gen_mode =
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01006345 IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
6346 }
6347 }
6348 } else {
6349 struct inet6_dev *idev = ctl->extra1;
6350
Felix Jiad35a00b2017-01-26 16:59:17 +13006351 idev->cnf.addr_gen_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01006352 }
6353
Hannes Frederic Sowa3d1bec92015-03-23 23:36:00 +01006354out:
6355 rtnl_unlock();
6356
6357 return err;
6358}
stephen hemmingerc92d5492013-12-17 22:37:14 -08006359
Andy Gospodarek35103d12015-08-13 10:39:01 -04006360static
6361int addrconf_sysctl_ignore_routes_with_linkdown(struct ctl_table *ctl,
Christoph Hellwig32927392020-04-24 08:43:38 +02006362 int write, void *buffer,
Andy Gospodarek35103d12015-08-13 10:39:01 -04006363 size_t *lenp,
6364 loff_t *ppos)
6365{
6366 int *valp = ctl->data;
6367 int val = *valp;
6368 loff_t pos = *ppos;
6369 struct ctl_table lctl;
6370 int ret;
6371
6372 /* ctl->data points to idev->cnf.ignore_routes_when_linkdown
6373 * we should not modify it until we get the rtnl lock.
6374 */
6375 lctl = *ctl;
6376 lctl.data = &val;
6377
6378 ret = proc_dointvec(&lctl, write, buffer, lenp, ppos);
6379
6380 if (write)
6381 ret = addrconf_fixup_linkdown(ctl, valp, val);
6382 if (ret)
6383 *ppos = pos;
6384 return ret;
6385}
6386
David Forsterdf789fe2017-02-23 16:27:18 +00006387static
6388void addrconf_set_nopolicy(struct rt6_info *rt, int action)
6389{
6390 if (rt) {
6391 if (action)
6392 rt->dst.flags |= DST_NOPOLICY;
6393 else
6394 rt->dst.flags &= ~DST_NOPOLICY;
6395 }
6396}
6397
6398static
6399void addrconf_disable_policy_idev(struct inet6_dev *idev, int val)
6400{
6401 struct inet6_ifaddr *ifa;
6402
6403 read_lock_bh(&idev->lock);
6404 list_for_each_entry(ifa, &idev->addr_list, if_list) {
6405 spin_lock(&ifa->lock);
6406 if (ifa->rt) {
David Ahernf88d8ea2019-06-03 20:19:52 -07006407 /* host routes only use builtin fib6_nh */
David Ahern1cf844c2019-05-22 20:27:59 -07006408 struct fib6_nh *nh = ifa->rt->fib6_nh;
David Forsterdf789fe2017-02-23 16:27:18 +00006409 int cpu;
6410
Wei Wang66f5d6c2017-10-06 12:06:10 -07006411 rcu_read_lock();
David Ahern3b6761d2018-04-17 17:33:20 -07006412 ifa->rt->dst_nopolicy = val ? true : false;
David Ahernf40b6ae2019-05-22 20:27:55 -07006413 if (nh->rt6i_pcpu) {
David Forsterdf789fe2017-02-23 16:27:18 +00006414 for_each_possible_cpu(cpu) {
6415 struct rt6_info **rtp;
6416
David Ahernf40b6ae2019-05-22 20:27:55 -07006417 rtp = per_cpu_ptr(nh->rt6i_pcpu, cpu);
David Forsterdf789fe2017-02-23 16:27:18 +00006418 addrconf_set_nopolicy(*rtp, val);
6419 }
6420 }
Wei Wang66f5d6c2017-10-06 12:06:10 -07006421 rcu_read_unlock();
David Forsterdf789fe2017-02-23 16:27:18 +00006422 }
6423 spin_unlock(&ifa->lock);
6424 }
6425 read_unlock_bh(&idev->lock);
6426}
6427
6428static
6429int addrconf_disable_policy(struct ctl_table *ctl, int *valp, int val)
6430{
6431 struct inet6_dev *idev;
6432 struct net *net;
6433
6434 if (!rtnl_trylock())
6435 return restart_syscall();
6436
6437 *valp = val;
6438
6439 net = (struct net *)ctl->extra2;
6440 if (valp == &net->ipv6.devconf_dflt->disable_policy) {
6441 rtnl_unlock();
6442 return 0;
6443 }
6444
6445 if (valp == &net->ipv6.devconf_all->disable_policy) {
6446 struct net_device *dev;
6447
6448 for_each_netdev(net, dev) {
6449 idev = __in6_dev_get(dev);
6450 if (idev)
6451 addrconf_disable_policy_idev(idev, val);
6452 }
6453 } else {
6454 idev = (struct inet6_dev *)ctl->extra1;
6455 addrconf_disable_policy_idev(idev, val);
6456 }
6457
6458 rtnl_unlock();
6459 return 0;
6460}
6461
Christoph Hellwig32927392020-04-24 08:43:38 +02006462static int addrconf_sysctl_disable_policy(struct ctl_table *ctl, int write,
6463 void *buffer, size_t *lenp, loff_t *ppos)
David Forsterdf789fe2017-02-23 16:27:18 +00006464{
6465 int *valp = ctl->data;
6466 int val = *valp;
6467 loff_t pos = *ppos;
6468 struct ctl_table lctl;
6469 int ret;
6470
6471 lctl = *ctl;
6472 lctl.data = &val;
6473 ret = proc_dointvec(&lctl, write, buffer, lenp, ppos);
6474
6475 if (write && (*valp != val))
6476 ret = addrconf_disable_policy(ctl, valp, val);
6477
6478 if (ret)
6479 *ppos = pos;
6480
6481 return ret;
6482}
6483
Maciej Żenczykowskicb4a4c62016-10-07 01:00:49 -07006484static int minus_one = -1;
Maciej Żenczykowskicb9e6842016-09-29 00:33:43 -07006485static const int two_five_five = 255;
6486
Konstantin Khlebnikov607ea7c2016-04-18 14:41:10 +03006487static const struct ctl_table addrconf_sysctl[] = {
Konstantin Khlebnikov5df1f772016-04-18 14:41:17 +03006488 {
6489 .procname = "forwarding",
6490 .data = &ipv6_devconf.forwarding,
6491 .maxlen = sizeof(int),
6492 .mode = 0644,
6493 .proc_handler = addrconf_sysctl_forward,
6494 },
6495 {
6496 .procname = "hop_limit",
6497 .data = &ipv6_devconf.hop_limit,
6498 .maxlen = sizeof(int),
6499 .mode = 0644,
Maciej Żenczykowskicb9e6842016-09-29 00:33:43 -07006500 .proc_handler = proc_dointvec_minmax,
Matteo Croceeec48442019-07-18 15:58:50 -07006501 .extra1 = (void *)SYSCTL_ONE,
Maciej Żenczykowskicb9e6842016-09-29 00:33:43 -07006502 .extra2 = (void *)&two_five_five,
Konstantin Khlebnikov5df1f772016-04-18 14:41:17 +03006503 },
6504 {
6505 .procname = "mtu",
6506 .data = &ipv6_devconf.mtu6,
6507 .maxlen = sizeof(int),
6508 .mode = 0644,
6509 .proc_handler = addrconf_sysctl_mtu,
6510 },
6511 {
6512 .procname = "accept_ra",
6513 .data = &ipv6_devconf.accept_ra,
6514 .maxlen = sizeof(int),
6515 .mode = 0644,
6516 .proc_handler = proc_dointvec,
6517 },
6518 {
6519 .procname = "accept_redirects",
6520 .data = &ipv6_devconf.accept_redirects,
6521 .maxlen = sizeof(int),
6522 .mode = 0644,
6523 .proc_handler = proc_dointvec,
6524 },
6525 {
6526 .procname = "autoconf",
6527 .data = &ipv6_devconf.autoconf,
6528 .maxlen = sizeof(int),
6529 .mode = 0644,
6530 .proc_handler = proc_dointvec,
6531 },
6532 {
6533 .procname = "dad_transmits",
6534 .data = &ipv6_devconf.dad_transmits,
6535 .maxlen = sizeof(int),
6536 .mode = 0644,
6537 .proc_handler = proc_dointvec,
6538 },
6539 {
6540 .procname = "router_solicitations",
6541 .data = &ipv6_devconf.rtr_solicits,
6542 .maxlen = sizeof(int),
6543 .mode = 0644,
Maciej Żenczykowskicb4a4c62016-10-07 01:00:49 -07006544 .proc_handler = proc_dointvec_minmax,
6545 .extra1 = &minus_one,
Konstantin Khlebnikov5df1f772016-04-18 14:41:17 +03006546 },
6547 {
6548 .procname = "router_solicitation_interval",
6549 .data = &ipv6_devconf.rtr_solicit_interval,
6550 .maxlen = sizeof(int),
6551 .mode = 0644,
6552 .proc_handler = proc_dointvec_jiffies,
6553 },
6554 {
Maciej Żenczykowskibd11f072016-09-27 23:57:58 -07006555 .procname = "router_solicitation_max_interval",
6556 .data = &ipv6_devconf.rtr_solicit_max_interval,
6557 .maxlen = sizeof(int),
6558 .mode = 0644,
6559 .proc_handler = proc_dointvec_jiffies,
6560 },
6561 {
Konstantin Khlebnikov5df1f772016-04-18 14:41:17 +03006562 .procname = "router_solicitation_delay",
6563 .data = &ipv6_devconf.rtr_solicit_delay,
6564 .maxlen = sizeof(int),
6565 .mode = 0644,
6566 .proc_handler = proc_dointvec_jiffies,
6567 },
6568 {
6569 .procname = "force_mld_version",
6570 .data = &ipv6_devconf.force_mld_version,
6571 .maxlen = sizeof(int),
6572 .mode = 0644,
6573 .proc_handler = proc_dointvec,
6574 },
6575 {
6576 .procname = "mldv1_unsolicited_report_interval",
6577 .data =
6578 &ipv6_devconf.mldv1_unsolicited_report_interval,
6579 .maxlen = sizeof(int),
6580 .mode = 0644,
6581 .proc_handler = proc_dointvec_ms_jiffies,
6582 },
6583 {
6584 .procname = "mldv2_unsolicited_report_interval",
6585 .data =
6586 &ipv6_devconf.mldv2_unsolicited_report_interval,
6587 .maxlen = sizeof(int),
6588 .mode = 0644,
6589 .proc_handler = proc_dointvec_ms_jiffies,
6590 },
6591 {
6592 .procname = "use_tempaddr",
6593 .data = &ipv6_devconf.use_tempaddr,
6594 .maxlen = sizeof(int),
6595 .mode = 0644,
6596 .proc_handler = proc_dointvec,
6597 },
6598 {
6599 .procname = "temp_valid_lft",
6600 .data = &ipv6_devconf.temp_valid_lft,
6601 .maxlen = sizeof(int),
6602 .mode = 0644,
6603 .proc_handler = proc_dointvec,
6604 },
6605 {
6606 .procname = "temp_prefered_lft",
6607 .data = &ipv6_devconf.temp_prefered_lft,
6608 .maxlen = sizeof(int),
6609 .mode = 0644,
6610 .proc_handler = proc_dointvec,
6611 },
6612 {
6613 .procname = "regen_max_retry",
6614 .data = &ipv6_devconf.regen_max_retry,
6615 .maxlen = sizeof(int),
6616 .mode = 0644,
6617 .proc_handler = proc_dointvec,
6618 },
6619 {
6620 .procname = "max_desync_factor",
6621 .data = &ipv6_devconf.max_desync_factor,
6622 .maxlen = sizeof(int),
6623 .mode = 0644,
6624 .proc_handler = proc_dointvec,
6625 },
6626 {
6627 .procname = "max_addresses",
6628 .data = &ipv6_devconf.max_addresses,
6629 .maxlen = sizeof(int),
6630 .mode = 0644,
6631 .proc_handler = proc_dointvec,
6632 },
6633 {
6634 .procname = "accept_ra_defrtr",
6635 .data = &ipv6_devconf.accept_ra_defrtr,
6636 .maxlen = sizeof(int),
6637 .mode = 0644,
6638 .proc_handler = proc_dointvec,
6639 },
6640 {
6641 .procname = "accept_ra_min_hop_limit",
6642 .data = &ipv6_devconf.accept_ra_min_hop_limit,
6643 .maxlen = sizeof(int),
6644 .mode = 0644,
6645 .proc_handler = proc_dointvec,
6646 },
6647 {
6648 .procname = "accept_ra_pinfo",
6649 .data = &ipv6_devconf.accept_ra_pinfo,
6650 .maxlen = sizeof(int),
6651 .mode = 0644,
6652 .proc_handler = proc_dointvec,
6653 },
YOSHIFUJI Hideaki930d6ff2006-03-20 17:05:30 -08006654#ifdef CONFIG_IPV6_ROUTER_PREF
Konstantin Khlebnikov5df1f772016-04-18 14:41:17 +03006655 {
6656 .procname = "accept_ra_rtr_pref",
6657 .data = &ipv6_devconf.accept_ra_rtr_pref,
6658 .maxlen = sizeof(int),
6659 .mode = 0644,
6660 .proc_handler = proc_dointvec,
6661 },
6662 {
6663 .procname = "router_probe_interval",
6664 .data = &ipv6_devconf.rtr_probe_interval,
6665 .maxlen = sizeof(int),
6666 .mode = 0644,
6667 .proc_handler = proc_dointvec_jiffies,
6668 },
Neil Hormanfa03ef32007-01-30 14:30:10 -08006669#ifdef CONFIG_IPV6_ROUTE_INFO
Konstantin Khlebnikov5df1f772016-04-18 14:41:17 +03006670 {
Joel Scherpelzbbea1242017-03-22 18:19:04 +09006671 .procname = "accept_ra_rt_info_min_plen",
6672 .data = &ipv6_devconf.accept_ra_rt_info_min_plen,
6673 .maxlen = sizeof(int),
6674 .mode = 0644,
6675 .proc_handler = proc_dointvec,
6676 },
6677 {
Konstantin Khlebnikov5df1f772016-04-18 14:41:17 +03006678 .procname = "accept_ra_rt_info_max_plen",
6679 .data = &ipv6_devconf.accept_ra_rt_info_max_plen,
6680 .maxlen = sizeof(int),
6681 .mode = 0644,
6682 .proc_handler = proc_dointvec,
6683 },
YOSHIFUJI Hideaki09c884d2006-03-20 17:07:03 -08006684#endif
YOSHIFUJI Hideaki930d6ff2006-03-20 17:05:30 -08006685#endif
Konstantin Khlebnikov5df1f772016-04-18 14:41:17 +03006686 {
6687 .procname = "proxy_ndp",
6688 .data = &ipv6_devconf.proxy_ndp,
6689 .maxlen = sizeof(int),
6690 .mode = 0644,
6691 .proc_handler = addrconf_sysctl_proxy_ndp,
6692 },
6693 {
6694 .procname = "accept_source_route",
6695 .data = &ipv6_devconf.accept_source_route,
6696 .maxlen = sizeof(int),
6697 .mode = 0644,
6698 .proc_handler = proc_dointvec,
6699 },
Neil Horman95c385b2007-04-25 17:08:10 -07006700#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
Konstantin Khlebnikov5df1f772016-04-18 14:41:17 +03006701 {
6702 .procname = "optimistic_dad",
6703 .data = &ipv6_devconf.optimistic_dad,
6704 .maxlen = sizeof(int),
6705 .mode = 0644,
6706 .proc_handler = proc_dointvec,
6707 },
6708 {
6709 .procname = "use_optimistic",
6710 .data = &ipv6_devconf.use_optimistic,
6711 .maxlen = sizeof(int),
6712 .mode = 0644,
6713 .proc_handler = proc_dointvec,
6714 },
Neil Horman95c385b2007-04-25 17:08:10 -07006715#endif
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09006716#ifdef CONFIG_IPV6_MROUTE
Konstantin Khlebnikov5df1f772016-04-18 14:41:17 +03006717 {
6718 .procname = "mc_forwarding",
6719 .data = &ipv6_devconf.mc_forwarding,
6720 .maxlen = sizeof(int),
6721 .mode = 0444,
6722 .proc_handler = proc_dointvec,
6723 },
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09006724#endif
Konstantin Khlebnikov5df1f772016-04-18 14:41:17 +03006725 {
6726 .procname = "disable_ipv6",
6727 .data = &ipv6_devconf.disable_ipv6,
6728 .maxlen = sizeof(int),
6729 .mode = 0644,
6730 .proc_handler = addrconf_sysctl_disable,
6731 },
6732 {
6733 .procname = "accept_dad",
6734 .data = &ipv6_devconf.accept_dad,
6735 .maxlen = sizeof(int),
6736 .mode = 0644,
6737 .proc_handler = proc_dointvec,
6738 },
6739 {
6740 .procname = "force_tllao",
6741 .data = &ipv6_devconf.force_tllao,
6742 .maxlen = sizeof(int),
6743 .mode = 0644,
6744 .proc_handler = proc_dointvec
6745 },
6746 {
6747 .procname = "ndisc_notify",
6748 .data = &ipv6_devconf.ndisc_notify,
6749 .maxlen = sizeof(int),
6750 .mode = 0644,
6751 .proc_handler = proc_dointvec
6752 },
6753 {
6754 .procname = "suppress_frag_ndisc",
6755 .data = &ipv6_devconf.suppress_frag_ndisc,
6756 .maxlen = sizeof(int),
6757 .mode = 0644,
6758 .proc_handler = proc_dointvec
6759 },
6760 {
6761 .procname = "accept_ra_from_local",
6762 .data = &ipv6_devconf.accept_ra_from_local,
6763 .maxlen = sizeof(int),
6764 .mode = 0644,
6765 .proc_handler = proc_dointvec,
6766 },
6767 {
6768 .procname = "accept_ra_mtu",
6769 .data = &ipv6_devconf.accept_ra_mtu,
6770 .maxlen = sizeof(int),
6771 .mode = 0644,
6772 .proc_handler = proc_dointvec,
6773 },
6774 {
6775 .procname = "stable_secret",
6776 .data = &ipv6_devconf.stable_secret,
6777 .maxlen = IPV6_MAX_STRLEN,
6778 .mode = 0600,
6779 .proc_handler = addrconf_sysctl_stable_secret,
6780 },
6781 {
6782 .procname = "use_oif_addrs_only",
6783 .data = &ipv6_devconf.use_oif_addrs_only,
6784 .maxlen = sizeof(int),
6785 .mode = 0644,
6786 .proc_handler = proc_dointvec,
6787 },
6788 {
6789 .procname = "ignore_routes_with_linkdown",
6790 .data = &ipv6_devconf.ignore_routes_with_linkdown,
6791 .maxlen = sizeof(int),
6792 .mode = 0644,
6793 .proc_handler = addrconf_sysctl_ignore_routes_with_linkdown,
6794 },
6795 {
6796 .procname = "drop_unicast_in_l2_multicast",
6797 .data = &ipv6_devconf.drop_unicast_in_l2_multicast,
6798 .maxlen = sizeof(int),
6799 .mode = 0644,
6800 .proc_handler = proc_dointvec,
6801 },
6802 {
6803 .procname = "drop_unsolicited_na",
6804 .data = &ipv6_devconf.drop_unsolicited_na,
6805 .maxlen = sizeof(int),
6806 .mode = 0644,
6807 .proc_handler = proc_dointvec,
6808 },
6809 {
6810 .procname = "keep_addr_on_down",
6811 .data = &ipv6_devconf.keep_addr_on_down,
6812 .maxlen = sizeof(int),
6813 .mode = 0644,
6814 .proc_handler = proc_dointvec,
David Ahernf1705ec2016-02-24 09:25:37 -08006815
Konstantin Khlebnikov5df1f772016-04-18 14:41:17 +03006816 },
6817 {
David Lebrun1ababeb2016-11-08 14:57:39 +01006818 .procname = "seg6_enabled",
6819 .data = &ipv6_devconf.seg6_enabled,
6820 .maxlen = sizeof(int),
6821 .mode = 0644,
6822 .proc_handler = proc_dointvec,
6823 },
David Lebrunbf355b82016-11-08 14:57:42 +01006824#ifdef CONFIG_IPV6_SEG6_HMAC
6825 {
6826 .procname = "seg6_require_hmac",
6827 .data = &ipv6_devconf.seg6_require_hmac,
6828 .maxlen = sizeof(int),
6829 .mode = 0644,
6830 .proc_handler = proc_dointvec,
6831 },
6832#endif
David Lebrun1ababeb2016-11-08 14:57:39 +01006833 {
Erik Nordmarkadc176c2016-12-02 14:00:08 -08006834 .procname = "enhanced_dad",
6835 .data = &ipv6_devconf.enhanced_dad,
6836 .maxlen = sizeof(int),
6837 .mode = 0644,
6838 .proc_handler = proc_dointvec,
6839 },
6840 {
Felix Jiad35a00b2017-01-26 16:59:17 +13006841 .procname = "addr_gen_mode",
6842 .data = &ipv6_devconf.addr_gen_mode,
6843 .maxlen = sizeof(int),
6844 .mode = 0644,
6845 .proc_handler = addrconf_sysctl_addr_gen_mode,
6846 },
6847 {
David Forsterdf789fe2017-02-23 16:27:18 +00006848 .procname = "disable_policy",
6849 .data = &ipv6_devconf.disable_policy,
6850 .maxlen = sizeof(int),
6851 .mode = 0644,
6852 .proc_handler = addrconf_sysctl_disable_policy,
6853 },
6854 {
Maciej Żenczykowski2210d6b2017-11-07 21:52:09 -08006855 .procname = "ndisc_tclass",
6856 .data = &ipv6_devconf.ndisc_tclass,
6857 .maxlen = sizeof(int),
6858 .mode = 0644,
6859 .proc_handler = proc_dointvec_minmax,
Matteo Croceeec48442019-07-18 15:58:50 -07006860 .extra1 = (void *)SYSCTL_ZERO,
Maciej Żenczykowski2210d6b2017-11-07 21:52:09 -08006861 .extra2 = (void *)&two_five_five,
6862 },
6863 {
Alexander Aring8610c7c2020-03-27 18:00:20 -04006864 .procname = "rpl_seg_enabled",
6865 .data = &ipv6_devconf.rpl_seg_enabled,
6866 .maxlen = sizeof(int),
6867 .mode = 0644,
6868 .proc_handler = proc_dointvec,
6869 },
6870 {
Konstantin Khlebnikov5df1f772016-04-18 14:41:17 +03006871 /* sentinel */
6872 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006873};
6874
Pavel Emelyanovbff16c22008-01-10 17:42:13 -08006875static int __addrconf_sysctl_register(struct net *net, char *dev_name,
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08006876 struct inet6_dev *idev, struct ipv6_devconf *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006877{
Nicolas Dichtel29c994e2016-08-30 10:09:22 +02006878 int i, ifindex;
Konstantin Khlebnikov607ea7c2016-04-18 14:41:10 +03006879 struct ctl_table *table;
Eric W. Biederman6105e292012-04-19 13:41:24 +00006880 char path[sizeof("net/ipv6/conf/") + IFNAMSIZ];
Pavel Emelyanov1dab6222007-12-02 00:59:38 +11006881
Konstantin Khlebnikov607ea7c2016-04-18 14:41:10 +03006882 table = kmemdup(addrconf_sysctl, sizeof(addrconf_sysctl), GFP_KERNEL);
6883 if (!table)
Pavel Emelyanovf68635e2007-12-02 00:21:52 +11006884 goto out;
6885
Konstantin Khlebnikov607ea7c2016-04-18 14:41:10 +03006886 for (i = 0; table[i].data; i++) {
6887 table[i].data += (char *)p - (char *)&ipv6_devconf;
Maciej Żenczykowskicb9e6842016-09-29 00:33:43 -07006888 /* If one of these is already set, then it is not safe to
6889 * overwrite either of them: this makes proc_dointvec_minmax
6890 * usable.
6891 */
6892 if (!table[i].extra1 && !table[i].extra2) {
6893 table[i].extra1 = idev; /* embedded; no ref */
6894 table[i].extra2 = net;
6895 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006896 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006897
Eric W. Biederman6105e292012-04-19 13:41:24 +00006898 snprintf(path, sizeof(path), "net/ipv6/conf/%s", dev_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006899
Konstantin Khlebnikov607ea7c2016-04-18 14:41:10 +03006900 p->sysctl_header = register_net_sysctl(net, path, table);
6901 if (!p->sysctl_header)
Eric W. Biederman6105e292012-04-19 13:41:24 +00006902 goto free;
Pavel Emelyanovf68635e2007-12-02 00:21:52 +11006903
Nicolas Dichtel29c994e2016-08-30 10:09:22 +02006904 if (!strcmp(dev_name, "all"))
6905 ifindex = NETCONFA_IFINDEX_ALL;
6906 else if (!strcmp(dev_name, "default"))
6907 ifindex = NETCONFA_IFINDEX_DEFAULT;
6908 else
6909 ifindex = idev->dev->ifindex;
David Ahern85b3daa2017-03-28 14:28:04 -07006910 inet6_netconf_notify_devconf(net, RTM_NEWNETCONF, NETCONFA_ALL,
6911 ifindex, p);
Pavel Emelyanov95897312008-01-10 17:41:45 -08006912 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006913
Pavel Emelyanovf68635e2007-12-02 00:21:52 +11006914free:
Konstantin Khlebnikov607ea7c2016-04-18 14:41:10 +03006915 kfree(table);
Pavel Emelyanovf68635e2007-12-02 00:21:52 +11006916out:
Pavel Emelyanov95897312008-01-10 17:41:45 -08006917 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006918}
6919
David Ahern23452172017-03-28 14:28:05 -07006920static void __addrconf_sysctl_unregister(struct net *net,
6921 struct ipv6_devconf *p, int ifindex)
Pavel Emelyanov408c4762008-01-10 17:41:21 -08006922{
Konstantin Khlebnikov607ea7c2016-04-18 14:41:10 +03006923 struct ctl_table *table;
Pavel Emelyanov408c4762008-01-10 17:41:21 -08006924
Konstantin Khlebnikov607ea7c2016-04-18 14:41:10 +03006925 if (!p->sysctl_header)
Pavel Emelyanov408c4762008-01-10 17:41:21 -08006926 return;
6927
Konstantin Khlebnikov607ea7c2016-04-18 14:41:10 +03006928 table = p->sysctl_header->ctl_table_arg;
6929 unregister_net_sysctl_table(p->sysctl_header);
6930 p->sysctl_header = NULL;
6931 kfree(table);
David Ahern23452172017-03-28 14:28:05 -07006932
6933 inet6_netconf_notify_devconf(net, RTM_DELNETCONF, 0, ifindex, NULL);
Pavel Emelyanov408c4762008-01-10 17:41:21 -08006934}
6935
WANG Conga317a2f2014-07-25 15:25:09 -07006936static int addrconf_sysctl_register(struct inet6_dev *idev)
Pavel Emelyanovf52295a2007-12-02 00:58:37 +11006937{
WANG Conga317a2f2014-07-25 15:25:09 -07006938 int err;
6939
6940 if (!sysctl_dev_name_is_allowed(idev->dev->name))
6941 return -EINVAL;
6942
6943 err = neigh_sysctl_register(idev->dev, idev->nd_parms,
6944 &ndisc_ifinfo_sysctl_change);
6945 if (err)
6946 return err;
6947 err = __addrconf_sysctl_register(dev_net(idev->dev), idev->dev->name,
6948 idev, &idev->cnf);
6949 if (err)
6950 neigh_sysctl_unregister(idev->nd_parms);
6951
6952 return err;
Pavel Emelyanovf52295a2007-12-02 00:58:37 +11006953}
6954
Pavel Emelyanov408c4762008-01-10 17:41:21 -08006955static void addrconf_sysctl_unregister(struct inet6_dev *idev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006956{
David Ahern23452172017-03-28 14:28:05 -07006957 __addrconf_sysctl_unregister(dev_net(idev->dev), &idev->cnf,
6958 idev->dev->ifindex);
Pavel Emelyanov408c4762008-01-10 17:41:21 -08006959 neigh_sysctl_unregister(idev->nd_parms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006960}
6961
6962
6963#endif
6964
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00006965static int __net_init addrconf_init_net(struct net *net)
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08006966{
Hong Zhiguoa79ca222013-03-26 01:52:45 +08006967 int err = -ENOMEM;
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08006968 struct ipv6_devconf *all, *dflt;
6969
Hong Zhiguoa79ca222013-03-26 01:52:45 +08006970 all = kmemdup(&ipv6_devconf, sizeof(ipv6_devconf), GFP_KERNEL);
Ian Morris63159f22015-03-29 14:00:04 +01006971 if (!all)
Hong Zhiguoa79ca222013-03-26 01:52:45 +08006972 goto err_alloc_all;
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08006973
Hong Zhiguoa79ca222013-03-26 01:52:45 +08006974 dflt = kmemdup(&ipv6_devconf_dflt, sizeof(ipv6_devconf_dflt), GFP_KERNEL);
Ian Morris63159f22015-03-29 14:00:04 +01006975 if (!dflt)
Hong Zhiguoa79ca222013-03-26 01:52:45 +08006976 goto err_alloc_dflt;
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08006977
Arnd Bergmanna154d5d2019-03-04 21:38:03 +01006978 if (IS_ENABLED(CONFIG_SYSCTL) &&
Nicolas Dichtel9efd6a32020-05-13 15:58:43 +02006979 !net_eq(net, &init_net)) {
6980 switch (sysctl_devconf_inherit_init_net) {
6981 case 1: /* copy from init_net */
6982 memcpy(all, init_net.ipv6.devconf_all,
6983 sizeof(ipv6_devconf));
6984 memcpy(dflt, init_net.ipv6.devconf_dflt,
6985 sizeof(ipv6_devconf_dflt));
6986 break;
6987 case 3: /* copy from the current netns */
6988 memcpy(all, current->nsproxy->net_ns->ipv6.devconf_all,
6989 sizeof(ipv6_devconf));
6990 memcpy(dflt,
6991 current->nsproxy->net_ns->ipv6.devconf_dflt,
6992 sizeof(ipv6_devconf_dflt));
6993 break;
6994 case 0:
6995 case 2:
6996 /* use compiled values */
6997 break;
6998 }
Cong Wang856c3952019-01-17 23:27:11 -08006999 }
7000
Hong Zhiguoa79ca222013-03-26 01:52:45 +08007001 /* these will be inherited by all namespaces */
7002 dflt->autoconf = ipv6_defaults.autoconf;
7003 dflt->disable_ipv6 = ipv6_defaults.disable_ipv6;
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08007004
Hannes Frederic Sowa3d1bec92015-03-23 23:36:00 +01007005 dflt->stable_secret.initialized = false;
7006 all->stable_secret.initialized = false;
7007
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08007008 net->ipv6.devconf_all = all;
7009 net->ipv6.devconf_dflt = dflt;
7010
7011#ifdef CONFIG_SYSCTL
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08007012 err = __addrconf_sysctl_register(net, "all", NULL, all);
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08007013 if (err < 0)
7014 goto err_reg_all;
7015
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08007016 err = __addrconf_sysctl_register(net, "default", NULL, dflt);
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08007017 if (err < 0)
7018 goto err_reg_dflt;
7019#endif
7020 return 0;
7021
7022#ifdef CONFIG_SYSCTL
7023err_reg_dflt:
David Ahern23452172017-03-28 14:28:05 -07007024 __addrconf_sysctl_unregister(net, all, NETCONFA_IFINDEX_ALL);
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08007025err_reg_all:
7026 kfree(dflt);
7027#endif
7028err_alloc_dflt:
7029 kfree(all);
7030err_alloc_all:
7031 return err;
7032}
7033
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00007034static void __net_exit addrconf_exit_net(struct net *net)
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08007035{
7036#ifdef CONFIG_SYSCTL
David Ahern23452172017-03-28 14:28:05 -07007037 __addrconf_sysctl_unregister(net, net->ipv6.devconf_dflt,
7038 NETCONFA_IFINDEX_DEFAULT);
7039 __addrconf_sysctl_unregister(net, net->ipv6.devconf_all,
7040 NETCONFA_IFINDEX_ALL);
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08007041#endif
zhuyj73cf0e922014-11-26 10:25:58 +08007042 kfree(net->ipv6.devconf_dflt);
7043 kfree(net->ipv6.devconf_all);
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08007044}
7045
7046static struct pernet_operations addrconf_ops = {
7047 .init = addrconf_init_net,
7048 .exit = addrconf_exit_net,
7049};
7050
Daniel Borkmann207895fd32015-01-29 12:15:03 +01007051static struct rtnl_af_ops inet6_ops __read_mostly = {
Thomas Grafb382b192010-11-16 04:33:57 +00007052 .family = AF_INET6,
7053 .fill_link_af = inet6_fill_link_af,
7054 .get_link_af_size = inet6_get_link_af_size,
Daniel Borkmann11b1f822015-02-05 14:39:11 +01007055 .validate_link_af = inet6_validate_link_af,
Daniel Borkmannf53adae2013-04-08 04:01:30 +00007056 .set_link_af = inet6_set_link_af,
Thomas Grafb382b192010-11-16 04:33:57 +00007057};
7058
Linus Torvalds1da177e2005-04-16 15:20:36 -07007059/*
7060 * Init / cleanup code
7061 */
7062
7063int __init addrconf_init(void)
7064{
WANG Conga317a2f2014-07-25 15:25:09 -07007065 struct inet6_dev *idev;
stephen hemmingerc2e21292010-03-17 20:31:10 +00007066 int i, err;
YOSHIFUJI Hideaki2a8cc6c2007-11-14 15:56:23 +09007067
Stephen Hemmingere21e8462010-03-20 16:09:01 -07007068 err = ipv6_addr_label_init();
7069 if (err < 0) {
Joe Perchesf3213832012-05-15 14:11:53 +00007070 pr_crit("%s: cannot initialize default policy table: %d\n",
7071 __func__, err);
Neil Horman2cc6d2b2010-09-24 09:55:52 +00007072 goto out;
YOSHIFUJI Hideaki2a8cc6c2007-11-14 15:56:23 +09007073 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007074
Neil Horman2cc6d2b2010-09-24 09:55:52 +00007075 err = register_pernet_subsys(&addrconf_ops);
7076 if (err < 0)
7077 goto out_addrlabel;
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08007078
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01007079 addrconf_wq = create_workqueue("ipv6_addrconf");
7080 if (!addrconf_wq) {
7081 err = -ENOMEM;
7082 goto out_nowq;
7083 }
7084
Linus Torvalds1da177e2005-04-16 15:20:36 -07007085 /* The addrconf netdev notifier requires that loopback_dev
7086 * has it's ipv6 private information allocated and setup
7087 * before it can bring up and give link-local addresses
7088 * to other devices which are up.
7089 *
7090 * Unfortunately, loopback_dev is not necessarily the first
7091 * entry in the global dev_base list of net devices. In fact,
7092 * it is likely to be the very last entry on that list.
7093 * So this causes the notifier registry below to try and
7094 * give link-local addresses to all devices besides loopback_dev
7095 * first, then loopback_dev, which cases all the non-loopback_dev
7096 * devices to fail to get a link-local address.
7097 *
7098 * So, as a temporary fix, allocate the ipv6 structure for
7099 * loopback_dev first by hand.
7100 * Longer term, all of the dependencies ipv6 has upon the loopback
7101 * device and it being up should be removed.
7102 */
7103 rtnl_lock();
WANG Conga317a2f2014-07-25 15:25:09 -07007104 idev = ipv6_add_dev(init_net.loopback_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007105 rtnl_unlock();
WANG Conga317a2f2014-07-25 15:25:09 -07007106 if (IS_ERR(idev)) {
7107 err = PTR_ERR(idev);
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08007108 goto errlo;
WANG Conga317a2f2014-07-25 15:25:09 -07007109 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007110
WANG Cong2f460932017-05-03 22:07:31 -07007111 ip6_route_init_special_entries();
7112
stephen hemmingerc2e21292010-03-17 20:31:10 +00007113 for (i = 0; i < IN6_ADDR_HSIZE; i++)
7114 INIT_HLIST_HEAD(&inet6_addr_lst[i]);
7115
Linus Torvalds1da177e2005-04-16 15:20:36 -07007116 register_netdevice_notifier(&ipv6_dev_notf);
7117
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01007118 addrconf_verify();
Thomas Grafc127ea22007-03-22 11:58:32 -07007119
stephen hemminger3678a9d2013-12-30 10:41:32 -08007120 rtnl_af_register(&inet6_ops);
Thomas Grafb382b192010-11-16 04:33:57 +00007121
Florian Westphal16feebc2017-12-02 21:44:08 +01007122 err = rtnl_register_module(THIS_MODULE, PF_INET6, RTM_GETLINK,
7123 NULL, inet6_dump_ifinfo, 0);
Thomas Grafc127ea22007-03-22 11:58:32 -07007124 if (err < 0)
7125 goto errout;
7126
Florian Westphal16feebc2017-12-02 21:44:08 +01007127 err = rtnl_register_module(THIS_MODULE, PF_INET6, RTM_NEWADDR,
7128 inet6_rtm_newaddr, NULL, 0);
7129 if (err < 0)
7130 goto errout;
7131 err = rtnl_register_module(THIS_MODULE, PF_INET6, RTM_DELADDR,
7132 inet6_rtm_deladdr, NULL, 0);
7133 if (err < 0)
7134 goto errout;
7135 err = rtnl_register_module(THIS_MODULE, PF_INET6, RTM_GETADDR,
7136 inet6_rtm_getaddr, inet6_dump_ifaddr,
7137 RTNL_FLAG_DOIT_UNLOCKED);
7138 if (err < 0)
7139 goto errout;
7140 err = rtnl_register_module(THIS_MODULE, PF_INET6, RTM_GETMULTICAST,
7141 NULL, inet6_dump_ifmcaddr, 0);
7142 if (err < 0)
7143 goto errout;
7144 err = rtnl_register_module(THIS_MODULE, PF_INET6, RTM_GETANYCAST,
7145 NULL, inet6_dump_ifacaddr, 0);
7146 if (err < 0)
7147 goto errout;
7148 err = rtnl_register_module(THIS_MODULE, PF_INET6, RTM_GETNETCONF,
7149 inet6_netconf_get_devconf,
7150 inet6_netconf_dump_devconf,
7151 RTNL_FLAG_DOIT_UNLOCKED);
7152 if (err < 0)
7153 goto errout;
Florian Westphala3fde2a2017-12-04 19:19:18 +01007154 err = ipv6_addr_label_rtnl_register();
7155 if (err < 0)
7156 goto errout;
YOSHIFUJI Hideaki2a8cc6c2007-11-14 15:56:23 +09007157
Linus Torvalds1da177e2005-04-16 15:20:36 -07007158 return 0;
Thomas Grafc127ea22007-03-22 11:58:32 -07007159errout:
Florian Westphal16feebc2017-12-02 21:44:08 +01007160 rtnl_unregister_all(PF_INET6);
Thomas Grafb382b192010-11-16 04:33:57 +00007161 rtnl_af_unregister(&inet6_ops);
Thomas Grafc127ea22007-03-22 11:58:32 -07007162 unregister_netdevice_notifier(&ipv6_dev_notf);
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08007163errlo:
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01007164 destroy_workqueue(addrconf_wq);
7165out_nowq:
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08007166 unregister_pernet_subsys(&addrconf_ops);
Neil Horman2cc6d2b2010-09-24 09:55:52 +00007167out_addrlabel:
7168 ipv6_addr_label_cleanup();
7169out:
Thomas Grafc127ea22007-03-22 11:58:32 -07007170 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007171}
7172
Daniel Lezcano09f77092007-12-13 05:34:58 -08007173void addrconf_cleanup(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007174{
Daniel Lezcano176c39a2009-03-03 01:06:45 -08007175 struct net_device *dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007176 int i;
7177
7178 unregister_netdevice_notifier(&ipv6_dev_notf);
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08007179 unregister_pernet_subsys(&addrconf_ops);
Neil Horman2cc6d2b2010-09-24 09:55:52 +00007180 ipv6_addr_label_cleanup();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007181
Florian Westphal5c451212017-10-04 15:58:49 +02007182 rtnl_af_unregister(&inet6_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007183
Florian Westphal5c451212017-10-04 15:58:49 +02007184 rtnl_lock();
Thomas Grafb382b192010-11-16 04:33:57 +00007185
Daniel Lezcano176c39a2009-03-03 01:06:45 -08007186 /* clean dev list */
7187 for_each_netdev(&init_net, dev) {
7188 if (__in6_dev_get(dev) == NULL)
7189 continue;
7190 addrconf_ifdown(dev, 1);
7191 }
7192 addrconf_ifdown(init_net.loopback_dev, 2);
7193
Linus Torvalds1da177e2005-04-16 15:20:36 -07007194 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07007195 * Check hash table.
7196 */
stephen hemminger5c578aed2010-03-17 20:31:11 +00007197 spin_lock_bh(&addrconf_hash_lock);
stephen hemmingerc2e21292010-03-17 20:31:10 +00007198 for (i = 0; i < IN6_ADDR_HSIZE; i++)
7199 WARN_ON(!hlist_empty(&inet6_addr_lst[i]));
stephen hemminger5c578aed2010-03-17 20:31:11 +00007200 spin_unlock_bh(&addrconf_hash_lock);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01007201 cancel_delayed_work(&addr_chk_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007202 rtnl_unlock();
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01007203
7204 destroy_workqueue(addrconf_wq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007205}