blob: fd885f06c4ed61423c576b98ad12789986cf7f7e [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 Hideaki072047e42005-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 Hideaki072047e42005-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 Hideaki072047e42005-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 Hideaki072047e42005-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 Hideaki072047e42005-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 Hideaki072047e42005-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 Hideaki072047e42005-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 Hideaki072047e42005-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
2786/*
2787 * Set destination address.
2788 * Special case for SIT interfaces where we create a new "virtual"
2789 * device.
2790 */
Daniel Lezcanoaf284932008-03-05 10:46:57 -08002791int addrconf_set_dstaddr(struct net *net, void __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002792{
2793 struct in6_ifreq ireq;
2794 struct net_device *dev;
2795 int err = -EINVAL;
2796
2797 rtnl_lock();
2798
2799 err = -EFAULT;
2800 if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
2801 goto err_exit;
2802
Daniel Lezcanoaf284932008-03-05 10:46:57 -08002803 dev = __dev_get_by_index(net, ireq.ifr6_ifindex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804
2805 err = -ENODEV;
Ian Morris63159f22015-03-29 14:00:04 +01002806 if (!dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807 goto err_exit;
2808
Amerigo Wang07a93622012-10-29 16:23:10 +00002809#if IS_ENABLED(CONFIG_IPV6_SIT)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002810 if (dev->type == ARPHRD_SIT) {
Stephen Hemminger5bc3eb72008-11-19 21:52:05 -08002811 const struct net_device_ops *ops = dev->netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812 struct ifreq ifr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813 struct ip_tunnel_parm p;
2814
2815 err = -EADDRNOTAVAIL;
2816 if (!(ipv6_addr_type(&ireq.ifr6_addr) & IPV6_ADDR_COMPATv4))
2817 goto err_exit;
2818
2819 memset(&p, 0, sizeof(p));
2820 p.iph.daddr = ireq.ifr6_addr.s6_addr32[3];
2821 p.iph.saddr = 0;
2822 p.iph.version = 4;
2823 p.iph.ihl = 5;
2824 p.iph.protocol = IPPROTO_IPV6;
2825 p.iph.ttl = 64;
Stephen Hemmingerd20b3102008-01-21 00:48:43 -08002826 ifr.ifr_ifru.ifru_data = (__force void __user *)&p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002827
Stephen Hemminger5bc3eb72008-11-19 21:52:05 -08002828 if (ops->ndo_do_ioctl) {
2829 mm_segment_t oldfs = get_fs();
2830
2831 set_fs(KERNEL_DS);
2832 err = ops->ndo_do_ioctl(dev, &ifr, SIOCADDTUNNEL);
2833 set_fs(oldfs);
2834 } else
2835 err = -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002836
2837 if (err == 0) {
2838 err = -ENOBUFS;
Daniel Lezcanoaf284932008-03-05 10:46:57 -08002839 dev = __dev_get_by_name(net, p.name);
2840 if (!dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002841 goto err_exit;
Petr Machata00f54e62018-12-06 17:05:36 +00002842 err = dev_open(dev, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002843 }
2844 }
Joerg Roedel0be669b2006-10-10 14:49:53 -07002845#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002846
2847err_exit:
2848 rtnl_unlock();
2849 return err;
2850}
2851
Madhu Challa93a714d2015-02-25 09:58:35 -08002852static int ipv6_mc_config(struct sock *sk, bool join,
2853 const struct in6_addr *addr, int ifindex)
2854{
2855 int ret;
2856
2857 ASSERT_RTNL();
2858
2859 lock_sock(sk);
2860 if (join)
Marcelo Ricardo Leitner54ff9ef2015-03-18 14:50:43 -03002861 ret = ipv6_sock_mc_join(sk, ifindex, addr);
Madhu Challa93a714d2015-02-25 09:58:35 -08002862 else
Marcelo Ricardo Leitner54ff9ef2015-03-18 14:50:43 -03002863 ret = ipv6_sock_mc_drop(sk, ifindex, addr);
Madhu Challa93a714d2015-02-25 09:58:35 -08002864 release_sock(sk);
2865
2866 return ret;
2867}
2868
Linus Torvalds1da177e2005-04-16 15:20:36 -07002869/*
2870 * Manual configuration of address on an interface
2871 */
Jiri Pirko479840f2013-12-06 09:45:21 +01002872static int inet6_addr_add(struct net *net, int ifindex,
David Ahern19b15182018-05-27 08:09:54 -07002873 struct ifa6_config *cfg,
David Ahernde95e042017-10-18 09:56:54 -07002874 struct netlink_ext_ack *extack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002875{
2876 struct inet6_ifaddr *ifp;
2877 struct inet6_dev *idev;
2878 struct net_device *dev;
Madhu Challa93a714d2015-02-25 09:58:35 -08002879 unsigned long timeout;
2880 clock_t expires;
YOSHIFUJI Hideaki6f704992008-05-19 16:56:11 -07002881 u32 flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002882
2883 ASSERT_RTNL();
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09002884
David Ahern19b15182018-05-27 08:09:54 -07002885 if (cfg->plen > 128)
Thomas Graf24ef0da2008-05-28 16:54:22 +02002886 return -EINVAL;
2887
Noriaki TAKAMIYA07787692006-07-28 18:12:10 +09002888 /* check the lifetime */
David Ahern19b15182018-05-27 08:09:54 -07002889 if (!cfg->valid_lft || cfg->preferred_lft > cfg->valid_lft)
Noriaki TAKAMIYA07787692006-07-28 18:12:10 +09002890 return -EINVAL;
2891
David Ahern19b15182018-05-27 08:09:54 -07002892 if (cfg->ifa_flags & IFA_F_MANAGETEMPADDR && cfg->plen != 64)
Jiri Pirko53bd6742013-12-06 09:45:22 +01002893 return -EINVAL;
2894
Daniel Lezcanoaf284932008-03-05 10:46:57 -08002895 dev = __dev_get_by_index(net, ifindex);
2896 if (!dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002897 return -ENODEV;
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09002898
Brian Haley64e724f2010-07-20 10:34:30 +00002899 idev = addrconf_add_dev(dev);
2900 if (IS_ERR(idev))
2901 return PTR_ERR(idev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002902
David Ahern19b15182018-05-27 08:09:54 -07002903 if (cfg->ifa_flags & IFA_F_MCAUTOJOIN) {
Madhu Challa93a714d2015-02-25 09:58:35 -08002904 int ret = ipv6_mc_config(net->ipv6.mc_autojoin_sk,
David Ahern19b15182018-05-27 08:09:54 -07002905 true, cfg->pfx, ifindex);
Madhu Challa93a714d2015-02-25 09:58:35 -08002906
2907 if (ret < 0)
2908 return ret;
2909 }
2910
David Ahern19b15182018-05-27 08:09:54 -07002911 cfg->scope = ipv6_addr_scope(cfg->pfx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002912
David Ahern19b15182018-05-27 08:09:54 -07002913 timeout = addrconf_timeout_fixup(cfg->valid_lft, HZ);
YOSHIFUJI Hideaki4bed72e2008-05-27 17:37:49 +09002914 if (addrconf_finite_timeout(timeout)) {
2915 expires = jiffies_to_clock_t(timeout * HZ);
David Ahern19b15182018-05-27 08:09:54 -07002916 cfg->valid_lft = timeout;
YOSHIFUJI Hideaki6f704992008-05-19 16:56:11 -07002917 flags = RTF_EXPIRES;
YOSHIFUJI Hideaki4bed72e2008-05-27 17:37:49 +09002918 } else {
2919 expires = 0;
2920 flags = 0;
David Ahern19b15182018-05-27 08:09:54 -07002921 cfg->ifa_flags |= IFA_F_PERMANENT;
YOSHIFUJI Hideaki6f704992008-05-19 16:56:11 -07002922 }
Noriaki TAKAMIYA07787692006-07-28 18:12:10 +09002923
David Ahern19b15182018-05-27 08:09:54 -07002924 timeout = addrconf_timeout_fixup(cfg->preferred_lft, HZ);
YOSHIFUJI Hideaki4bed72e2008-05-27 17:37:49 +09002925 if (addrconf_finite_timeout(timeout)) {
2926 if (timeout == 0)
David Ahern19b15182018-05-27 08:09:54 -07002927 cfg->ifa_flags |= IFA_F_DEPRECATED;
2928 cfg->preferred_lft = timeout;
YOSHIFUJI Hideaki4bed72e2008-05-27 17:37:49 +09002929 }
Noriaki TAKAMIYA07787692006-07-28 18:12:10 +09002930
David Ahern19b15182018-05-27 08:09:54 -07002931 ifp = ipv6_add_addr(idev, cfg, true, extack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002932 if (!IS_ERR(ifp)) {
David Ahern19b15182018-05-27 08:09:54 -07002933 if (!(cfg->ifa_flags & IFA_F_NOPREFIXROUTE)) {
David Ahern8308f3f2018-05-27 08:09:58 -07002934 addrconf_prefix_route(&ifp->addr, ifp->prefix_len,
2935 ifp->rt_priority, dev, expires,
2936 flags, GFP_KERNEL);
Thomas Haller761aac72014-01-15 15:36:58 +01002937 }
2938
Lorenzo Bianconia2d481b2018-04-17 11:54:39 +02002939 /* Send a netlink notification if DAD is enabled and
2940 * optimistic flag is not set
2941 */
2942 if (!(ifp->flags & (IFA_F_OPTIMISTIC | IFA_F_NODAD)))
2943 ipv6_ifa_notify(0, ifp);
Neil Horman95c385b2007-04-25 17:08:10 -07002944 /*
2945 * Note that section 3.1 of RFC 4429 indicates
2946 * that the Optimistic flag should not be set for
2947 * manually configured addresses
2948 */
David S. Millercf22f9a2012-04-14 21:37:40 -04002949 addrconf_dad_start(ifp);
David Ahern19b15182018-05-27 08:09:54 -07002950 if (cfg->ifa_flags & IFA_F_MANAGETEMPADDR)
2951 manage_tempaddrs(idev, ifp, cfg->valid_lft,
2952 cfg->preferred_lft, true, jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953 in6_ifa_put(ifp);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01002954 addrconf_verify_rtnl();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002955 return 0;
David Ahern19b15182018-05-27 08:09:54 -07002956 } else if (cfg->ifa_flags & IFA_F_MCAUTOJOIN) {
2957 ipv6_mc_config(net->ipv6.mc_autojoin_sk, false,
2958 cfg->pfx, ifindex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002959 }
2960
2961 return PTR_ERR(ifp);
2962}
2963
Heiner Kallweit6046d5b2014-04-20 21:29:36 +02002964static int inet6_addr_del(struct net *net, int ifindex, u32 ifa_flags,
2965 const struct in6_addr *pfx, unsigned int plen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002966{
2967 struct inet6_ifaddr *ifp;
2968 struct inet6_dev *idev;
2969 struct net_device *dev;
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09002970
Thomas Graf24ef0da2008-05-28 16:54:22 +02002971 if (plen > 128)
2972 return -EINVAL;
2973
Daniel Lezcanoaf284932008-03-05 10:46:57 -08002974 dev = __dev_get_by_index(net, ifindex);
2975 if (!dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002976 return -ENODEV;
2977
Ian Morrise5d08d72014-11-23 21:28:43 +00002978 idev = __in6_dev_get(dev);
Ian Morris63159f22015-03-29 14:00:04 +01002979 if (!idev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002980 return -ENXIO;
2981
2982 read_lock_bh(&idev->lock);
stephen hemminger502a2ff2010-03-17 20:31:13 +00002983 list_for_each_entry(ifp, &idev->addr_list, if_list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002984 if (ifp->prefix_len == plen &&
2985 ipv6_addr_equal(pfx, &ifp->addr)) {
2986 in6_ifa_hold(ifp);
2987 read_unlock_bh(&idev->lock);
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09002988
Heiner Kallweit6046d5b2014-04-20 21:29:36 +02002989 if (!(ifp->flags & IFA_F_TEMPORARY) &&
2990 (ifa_flags & IFA_F_MANAGETEMPADDR))
2991 manage_tempaddrs(idev, ifp, 0, 0, false,
2992 jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002993 ipv6_del_addr(ifp);
Heiner Kallweit6046d5b2014-04-20 21:29:36 +02002994 addrconf_verify_rtnl();
Madhu Challa93a714d2015-02-25 09:58:35 -08002995 if (ipv6_addr_is_multicast(pfx)) {
2996 ipv6_mc_config(net->ipv6.mc_autojoin_sk,
2997 false, pfx, dev->ifindex);
2998 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999 return 0;
3000 }
3001 }
3002 read_unlock_bh(&idev->lock);
3003 return -EADDRNOTAVAIL;
3004}
3005
3006
Daniel Lezcanoaf284932008-03-05 10:46:57 -08003007int addrconf_add_ifaddr(struct net *net, void __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008{
David Ahern19b15182018-05-27 08:09:54 -07003009 struct ifa6_config cfg = {
3010 .ifa_flags = IFA_F_PERMANENT,
3011 .preferred_lft = INFINITY_LIFE_TIME,
3012 .valid_lft = INFINITY_LIFE_TIME,
3013 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07003014 struct in6_ifreq ireq;
3015 int err;
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09003016
Eric W. Biedermanaf31f412012-11-16 03:03:06 +00003017 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003018 return -EPERM;
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09003019
Linus Torvalds1da177e2005-04-16 15:20:36 -07003020 if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
3021 return -EFAULT;
3022
David Ahern19b15182018-05-27 08:09:54 -07003023 cfg.pfx = &ireq.ifr6_addr;
3024 cfg.plen = ireq.ifr6_prefixlen;
3025
Linus Torvalds1da177e2005-04-16 15:20:36 -07003026 rtnl_lock();
David Ahern19b15182018-05-27 08:09:54 -07003027 err = inet6_addr_add(net, ireq.ifr6_ifindex, &cfg, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003028 rtnl_unlock();
3029 return err;
3030}
3031
Daniel Lezcanoaf284932008-03-05 10:46:57 -08003032int addrconf_del_ifaddr(struct net *net, void __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033{
3034 struct in6_ifreq ireq;
3035 int err;
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09003036
Eric W. Biedermanaf31f412012-11-16 03:03:06 +00003037 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003038 return -EPERM;
3039
3040 if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
3041 return -EFAULT;
3042
3043 rtnl_lock();
Heiner Kallweit6046d5b2014-04-20 21:29:36 +02003044 err = inet6_addr_del(net, ireq.ifr6_ifindex, 0, &ireq.ifr6_addr,
Daniel Lezcanoaf284932008-03-05 10:46:57 -08003045 ireq.ifr6_prefixlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003046 rtnl_unlock();
3047 return err;
3048}
3049
Ilpo Järvinenb5f348e2009-02-06 23:48:01 -08003050static void add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
3051 int plen, int scope)
3052{
3053 struct inet6_ifaddr *ifp;
David Aherne6464b82018-05-27 08:09:53 -07003054 struct ifa6_config cfg = {
3055 .pfx = addr,
3056 .plen = plen,
3057 .ifa_flags = IFA_F_PERMANENT,
3058 .valid_lft = INFINITY_LIFE_TIME,
3059 .preferred_lft = INFINITY_LIFE_TIME,
3060 .scope = scope
3061 };
Ilpo Järvinenb5f348e2009-02-06 23:48:01 -08003062
David Aherne6464b82018-05-27 08:09:53 -07003063 ifp = ipv6_add_addr(idev, &cfg, true, NULL);
Ilpo Järvinenb5f348e2009-02-06 23:48:01 -08003064 if (!IS_ERR(ifp)) {
3065 spin_lock_bh(&ifp->lock);
3066 ifp->flags &= ~IFA_F_TENTATIVE;
3067 spin_unlock_bh(&ifp->lock);
Paolo Abeni764d3be2016-11-22 16:57:40 +01003068 rt_genid_bump_ipv6(dev_net(idev->dev));
Ilpo Järvinenb5f348e2009-02-06 23:48:01 -08003069 ipv6_ifa_notify(RTM_NEWADDR, ifp);
3070 in6_ifa_put(ifp);
3071 }
3072}
3073
Amerigo Wang07a93622012-10-29 16:23:10 +00003074#if IS_ENABLED(CONFIG_IPV6_SIT)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003075static void sit_add_v4_addrs(struct inet6_dev *idev)
3076{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003077 struct in6_addr addr;
3078 struct net_device *dev;
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09003079 struct net *net = dev_net(idev->dev);
Nicolas Dichtel929c9cf2013-11-14 13:51:05 +01003080 int scope, plen;
Nicolas Dichtelf0e2acf2013-11-14 13:51:06 +01003081 u32 pflags = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003082
3083 ASSERT_RTNL();
3084
3085 memset(&addr, 0, sizeof(struct in6_addr));
3086 memcpy(&addr.s6_addr32[3], idev->dev->dev_addr, 4);
3087
3088 if (idev->dev->flags&IFF_POINTOPOINT) {
3089 addr.s6_addr32[0] = htonl(0xfe800000);
3090 scope = IFA_LINK;
Nicolas Dichtel929c9cf2013-11-14 13:51:05 +01003091 plen = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003092 } else {
3093 scope = IPV6_ADDR_COMPATv4;
Nicolas Dichtel929c9cf2013-11-14 13:51:05 +01003094 plen = 96;
Nicolas Dichtelf0e2acf2013-11-14 13:51:06 +01003095 pflags |= RTF_NONEXTHOP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003096 }
3097
3098 if (addr.s6_addr32[3]) {
Nicolas Dichtel929c9cf2013-11-14 13:51:05 +01003099 add_addr(idev, &addr, plen, scope);
David Ahern8308f3f2018-05-27 08:09:58 -07003100 addrconf_prefix_route(&addr, plen, 0, idev->dev, 0, pflags,
Cong Wange500c6d2018-08-22 12:58:34 -07003101 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003102 return;
3103 }
3104
Benjamin Thery6fda7352008-03-05 10:47:47 -08003105 for_each_netdev(net, dev) {
Eldad Zack8e5e8f32012-04-01 07:49:08 +00003106 struct in_device *in_dev = __in_dev_get_rtnl(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003107 if (in_dev && (dev->flags & IFF_UP)) {
Eldad Zack8e5e8f32012-04-01 07:49:08 +00003108 struct in_ifaddr *ifa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003109 int flag = scope;
3110
Florian Westphalcd5a4112019-05-31 18:27:07 +02003111 in_dev_for_each_ifa_rtnl(ifa, in_dev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003112 addr.s6_addr32[3] = ifa->ifa_local;
3113
3114 if (ifa->ifa_scope == RT_SCOPE_LINK)
3115 continue;
3116 if (ifa->ifa_scope >= RT_SCOPE_HOST) {
3117 if (idev->dev->flags&IFF_POINTOPOINT)
3118 continue;
3119 flag |= IFA_HOST;
3120 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003121
Ilpo Järvinenb5f348e2009-02-06 23:48:01 -08003122 add_addr(idev, &addr, plen, flag);
David Ahern8308f3f2018-05-27 08:09:58 -07003123 addrconf_prefix_route(&addr, plen, 0, idev->dev,
Cong Wange500c6d2018-08-22 12:58:34 -07003124 0, pflags, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003125 }
3126 }
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09003127 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128}
Joerg Roedel0be669b2006-10-10 14:49:53 -07003129#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003130
3131static void init_loopback(struct net_device *dev)
3132{
3133 struct inet6_dev *idev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003134
3135 /* ::1 */
3136
3137 ASSERT_RTNL();
3138
Ian Morrise5d08d72014-11-23 21:28:43 +00003139 idev = ipv6_find_idev(dev);
Sabrina Dubrocadb0b99f2019-08-23 15:44:36 +02003140 if (IS_ERR(idev)) {
Joe Perches91df42b2012-05-15 14:11:54 +00003141 pr_debug("%s: add_dev failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003142 return;
3143 }
3144
Ilpo Järvinenb5f348e2009-02-06 23:48:01 -08003145 add_addr(idev, &in6addr_loopback, 128, IFA_HOST);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003146}
3147
Alexander Aring2ad3ed52016-06-15 21:20:17 +02003148void addrconf_add_linklocal(struct inet6_dev *idev,
3149 const struct in6_addr *addr, u32 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003150{
David Aherne6464b82018-05-27 08:09:53 -07003151 struct ifa6_config cfg = {
3152 .pfx = addr,
3153 .plen = 64,
3154 .ifa_flags = flags | IFA_F_PERMANENT,
3155 .valid_lft = INFINITY_LIFE_TIME,
3156 .preferred_lft = INFINITY_LIFE_TIME,
3157 .scope = IFA_LINK
3158 };
Eldad Zack8e5e8f32012-04-01 07:49:08 +00003159 struct inet6_ifaddr *ifp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003160
Neil Horman95c385b2007-04-25 17:08:10 -07003161#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
Matteo Croce35e015e2017-09-12 17:46:37 +02003162 if ((dev_net(idev->dev)->ipv6.devconf_all->optimistic_dad ||
3163 idev->cnf.optimistic_dad) &&
David Miller702beb82008-07-20 18:17:02 -07003164 !dev_net(idev->dev)->ipv6.devconf_all->forwarding)
David Aherne6464b82018-05-27 08:09:53 -07003165 cfg.ifa_flags |= IFA_F_OPTIMISTIC;
Neil Horman95c385b2007-04-25 17:08:10 -07003166#endif
3167
David Aherne6464b82018-05-27 08:09:53 -07003168 ifp = ipv6_add_addr(idev, &cfg, true, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003169 if (!IS_ERR(ifp)) {
David Ahern8308f3f2018-05-27 08:09:58 -07003170 addrconf_prefix_route(&ifp->addr, ifp->prefix_len, 0, idev->dev,
David Ahernacb54e32018-04-17 17:33:22 -07003171 0, 0, GFP_ATOMIC);
David S. Millercf22f9a2012-04-14 21:37:40 -04003172 addrconf_dad_start(ifp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003173 in6_ifa_put(ifp);
3174 }
3175}
Alexander Aring2ad3ed52016-06-15 21:20:17 +02003176EXPORT_SYMBOL_GPL(addrconf_add_linklocal);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003177
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01003178static bool ipv6_reserved_interfaceid(struct in6_addr address)
3179{
3180 if ((address.s6_addr32[2] | address.s6_addr32[3]) == 0)
3181 return true;
3182
3183 if (address.s6_addr32[2] == htonl(0x02005eff) &&
3184 ((address.s6_addr32[3] & htonl(0xfe000000)) == htonl(0xfe000000)))
3185 return true;
3186
3187 if (address.s6_addr32[2] == htonl(0xfdffffff) &&
3188 ((address.s6_addr32[3] & htonl(0xffffff80)) == htonl(0xffffff80)))
3189 return true;
3190
3191 return false;
3192}
3193
3194static int ipv6_generate_stable_address(struct in6_addr *address,
3195 u8 dad_count,
3196 const struct inet6_dev *idev)
3197{
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01003198 static DEFINE_SPINLOCK(lock);
3199 static __u32 digest[SHA_DIGEST_WORDS];
3200 static __u32 workspace[SHA_WORKSPACE_WORDS];
3201
3202 static union {
3203 char __data[SHA_MESSAGE_BYTES];
3204 struct {
3205 struct in6_addr secret;
Hannes Frederic Sowaff402172015-03-24 11:05:28 +01003206 __be32 prefix[2];
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01003207 unsigned char hwaddr[MAX_ADDR_LEN];
3208 u8 dad_count;
3209 } __packed;
3210 } data;
3211
3212 struct in6_addr secret;
3213 struct in6_addr temp;
3214 struct net *net = dev_net(idev->dev);
3215
3216 BUILD_BUG_ON(sizeof(data.__data) != sizeof(data));
3217
3218 if (idev->cnf.stable_secret.initialized)
3219 secret = idev->cnf.stable_secret.secret;
3220 else if (net->ipv6.devconf_dflt->stable_secret.initialized)
3221 secret = net->ipv6.devconf_dflt->stable_secret.secret;
3222 else
3223 return -1;
3224
3225retry:
3226 spin_lock_bh(&lock);
3227
3228 sha_init(digest);
3229 memset(&data, 0, sizeof(data));
3230 memset(workspace, 0, sizeof(workspace));
3231 memcpy(data.hwaddr, idev->dev->perm_addr, idev->dev->addr_len);
Hannes Frederic Sowaff402172015-03-24 11:05:28 +01003232 data.prefix[0] = address->s6_addr32[0];
3233 data.prefix[1] = address->s6_addr32[1];
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01003234 data.secret = secret;
3235 data.dad_count = dad_count;
3236
3237 sha_transform(digest, data.__data, workspace);
3238
3239 temp = *address;
Hannes Frederic Sowaff402172015-03-24 11:05:28 +01003240 temp.s6_addr32[2] = (__force __be32)digest[0];
3241 temp.s6_addr32[3] = (__force __be32)digest[1];
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01003242
3243 spin_unlock_bh(&lock);
3244
3245 if (ipv6_reserved_interfaceid(temp)) {
3246 dad_count++;
Hannes Frederic Sowa1855b7c2015-03-23 23:36:05 +01003247 if (dad_count > dev_net(idev->dev)->ipv6.sysctl.idgen_retries)
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01003248 return -1;
3249 goto retry;
3250 }
3251
3252 *address = temp;
3253 return 0;
3254}
3255
Bjørn Morkcc9da6c2015-12-16 16:44:38 +01003256static void ipv6_gen_mode_random_init(struct inet6_dev *idev)
3257{
3258 struct ipv6_stable_secret *s = &idev->cnf.stable_secret;
3259
3260 if (s->initialized)
3261 return;
3262 s = &idev->cnf.stable_secret;
3263 get_random_bytes(&s->secret, sizeof(s->secret));
3264 s->initialized = true;
3265}
3266
Jiri Pirkobc91b0f2014-07-11 21:10:18 +02003267static void addrconf_addr_gen(struct inet6_dev *idev, bool prefix_route)
3268{
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01003269 struct in6_addr addr;
Jiri Pirkobc91b0f2014-07-11 21:10:18 +02003270
David Ahernca254492015-10-12 11:47:10 -07003271 /* no link local addresses on L3 master devices */
3272 if (netif_is_l3_master(idev->dev))
3273 return;
3274
Jarod Wilson744fdc822020-03-30 11:22:19 -04003275 /* no link local addresses on devices flagged as slaves */
3276 if (idev->dev->flags & IFF_SLAVE)
3277 return;
3278
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01003279 ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0);
3280
Felix Jiad35a00b2017-01-26 16:59:17 +13003281 switch (idev->cnf.addr_gen_mode) {
Bjørn Morkcc9da6c2015-12-16 16:44:38 +01003282 case IN6_ADDR_GEN_MODE_RANDOM:
3283 ipv6_gen_mode_random_init(idev);
Joe Perchesa8eceea2020-03-12 15:50:22 -07003284 fallthrough;
Bjørn Morkcc9da6c2015-12-16 16:44:38 +01003285 case IN6_ADDR_GEN_MODE_STABLE_PRIVACY:
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01003286 if (!ipv6_generate_stable_address(&addr, 0, idev))
Hannes Frederic Sowa64236f32015-03-23 23:36:02 +01003287 addrconf_add_linklocal(idev, &addr,
3288 IFA_F_STABLE_PRIVACY);
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01003289 else if (prefix_route)
David Ahern8308f3f2018-05-27 08:09:58 -07003290 addrconf_prefix_route(&addr, 64, 0, idev->dev,
David Ahernacb54e32018-04-17 17:33:22 -07003291 0, 0, GFP_KERNEL);
Bjørn Morkcc9da6c2015-12-16 16:44:38 +01003292 break;
3293 case IN6_ADDR_GEN_MODE_EUI64:
Jiri Pirkobc91b0f2014-07-11 21:10:18 +02003294 /* addrconf_add_linklocal also adds a prefix_route and we
3295 * only need to care about prefix routes if ipv6_generate_eui64
3296 * couldn't generate one.
3297 */
3298 if (ipv6_generate_eui64(addr.s6_addr + 8, idev->dev) == 0)
Hannes Frederic Sowa64236f32015-03-23 23:36:02 +01003299 addrconf_add_linklocal(idev, &addr, 0);
Jiri Pirkobc91b0f2014-07-11 21:10:18 +02003300 else if (prefix_route)
David Ahern8308f3f2018-05-27 08:09:58 -07003301 addrconf_prefix_route(&addr, 64, 0, idev->dev,
David Ahern27b10602018-04-18 15:39:06 -07003302 0, 0, GFP_KERNEL);
Bjørn Morkcc9da6c2015-12-16 16:44:38 +01003303 break;
3304 case IN6_ADDR_GEN_MODE_NONE:
3305 default:
3306 /* will not add any link local address */
3307 break;
Jiri Pirkobc91b0f2014-07-11 21:10:18 +02003308 }
3309}
3310
Linus Torvalds1da177e2005-04-16 15:20:36 -07003311static void addrconf_dev_config(struct net_device *dev)
3312{
Eldad Zack8e5e8f32012-04-01 07:49:08 +00003313 struct inet6_dev *idev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003314
3315 ASSERT_RTNL();
3316
Herbert Xu74235a22007-06-14 13:02:55 -07003317 if ((dev->type != ARPHRD_ETHER) &&
3318 (dev->type != ARPHRD_FDDI) &&
Herbert Xu74235a22007-06-14 13:02:55 -07003319 (dev->type != ARPHRD_ARCNET) &&
alex.bluesman.smirnov@gmail.com06a4c1c2012-05-10 03:25:52 +00003320 (dev->type != ARPHRD_INFINIBAND) &&
Nicolas Dichtele8377352013-08-20 12:16:06 +02003321 (dev->type != ARPHRD_IEEE1394) &&
Jukka Rissanene74bccb82013-12-11 17:05:36 +02003322 (dev->type != ARPHRD_TUNNEL6) &&
Bjørn Morkcc9da6c2015-12-16 16:44:38 +01003323 (dev->type != ARPHRD_6LOWPAN) &&
Felix Jia45ce0fd2017-01-26 16:59:18 +13003324 (dev->type != ARPHRD_IP6GRE) &&
3325 (dev->type != ARPHRD_IPGRE) &&
3326 (dev->type != ARPHRD_TUNNEL) &&
Subash Abhinov Kasiviswanathan9deb4412018-06-04 19:26:07 -06003327 (dev->type != ARPHRD_NONE) &&
3328 (dev->type != ARPHRD_RAWIP)) {
Herbert Xu74235a22007-06-14 13:02:55 -07003329 /* Alas, we support only Ethernet autoconfiguration. */
Hangbin Liu60380482020-03-10 15:27:37 +08003330 idev = __in6_dev_get(dev);
3331 if (!IS_ERR_OR_NULL(idev) && dev->flags & IFF_UP &&
3332 dev->flags & IFF_MULTICAST)
3333 ipv6_mc_up(idev);
Herbert Xu74235a22007-06-14 13:02:55 -07003334 return;
3335 }
3336
Linus Torvalds1da177e2005-04-16 15:20:36 -07003337 idev = addrconf_add_dev(dev);
Brian Haley64e724f2010-07-20 10:34:30 +00003338 if (IS_ERR(idev))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003339 return;
3340
Bjørn Morkcc9da6c2015-12-16 16:44:38 +01003341 /* this device type has no EUI support */
3342 if (dev->type == ARPHRD_NONE &&
Felix Jiad35a00b2017-01-26 16:59:17 +13003343 idev->cnf.addr_gen_mode == IN6_ADDR_GEN_MODE_EUI64)
3344 idev->cnf.addr_gen_mode = IN6_ADDR_GEN_MODE_RANDOM;
Bjørn Morkcc9da6c2015-12-16 16:44:38 +01003345
Jiri Pirkobc91b0f2014-07-11 21:10:18 +02003346 addrconf_addr_gen(idev, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003347}
3348
Amerigo Wang07a93622012-10-29 16:23:10 +00003349#if IS_ENABLED(CONFIG_IPV6_SIT)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003350static void addrconf_sit_config(struct net_device *dev)
3351{
3352 struct inet6_dev *idev;
3353
3354 ASSERT_RTNL();
3355
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09003356 /*
3357 * Configure the tunnel with one of our IPv4
3358 * addresses... we should configure all of
Linus Torvalds1da177e2005-04-16 15:20:36 -07003359 * our v4 addrs in the tunnel
3360 */
3361
Ian Morrise5d08d72014-11-23 21:28:43 +00003362 idev = ipv6_find_idev(dev);
Sabrina Dubrocadb0b99f2019-08-23 15:44:36 +02003363 if (IS_ERR(idev)) {
Joe Perches91df42b2012-05-15 14:11:54 +00003364 pr_debug("%s: add_dev failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003365 return;
3366 }
3367
Fred L. Templinc7dc89c2007-11-29 22:11:40 +11003368 if (dev->priv_flags & IFF_ISATAP) {
Jiri Pirkobc91b0f2014-07-11 21:10:18 +02003369 addrconf_addr_gen(idev, false);
Fred L. Templinc7dc89c2007-11-29 22:11:40 +11003370 return;
3371 }
3372
Linus Torvalds1da177e2005-04-16 15:20:36 -07003373 sit_add_v4_addrs(idev);
3374
Nicolas Dichtel62b54dd2012-10-01 23:19:14 +00003375 if (dev->flags&IFF_POINTOPOINT)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003376 addrconf_add_mroute(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003377}
Joerg Roedel0be669b2006-10-10 14:49:53 -07003378#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003379
Amerigo Wang07a93622012-10-29 16:23:10 +00003380#if IS_ENABLED(CONFIG_NET_IPGRE)
stephen hemmingeraee80b52011-06-08 10:44:30 +00003381static void addrconf_gre_config(struct net_device *dev)
3382{
3383 struct inet6_dev *idev;
stephen hemmingeraee80b52011-06-08 10:44:30 +00003384
stephen hemmingeraee80b52011-06-08 10:44:30 +00003385 ASSERT_RTNL();
3386
Ian Morrise5d08d72014-11-23 21:28:43 +00003387 idev = ipv6_find_idev(dev);
Sabrina Dubrocadb0b99f2019-08-23 15:44:36 +02003388 if (IS_ERR(idev)) {
Joe Perches91df42b2012-05-15 14:11:54 +00003389 pr_debug("%s: add_dev failed\n", __func__);
stephen hemmingeraee80b52011-06-08 10:44:30 +00003390 return;
3391 }
3392
Jiri Pirkobc91b0f2014-07-11 21:10:18 +02003393 addrconf_addr_gen(idev, true);
Hannes Frederic Sowad9e4ce62015-10-08 18:19:39 +02003394 if (dev->flags & IFF_POINTOPOINT)
3395 addrconf_add_mroute(dev);
stephen hemmingeraee80b52011-06-08 10:44:30 +00003396}
3397#endif
3398
David Ahernafb1d4b52018-04-17 17:33:11 -07003399static int fixup_permanent_addr(struct net *net,
3400 struct inet6_dev *idev,
David Ahernf1705ec2016-02-24 09:25:37 -08003401 struct inet6_ifaddr *ifp)
3402{
David Ahern93c2fb22018-04-18 15:38:59 -07003403 /* !fib6_node means the host route was removed from the
David Ahern8048ced2017-04-25 09:17:29 -07003404 * FIB, for example, if 'lo' device is taken down. In that
3405 * case regenerate the host route.
3406 */
David Ahern93c2fb22018-04-18 15:38:59 -07003407 if (!ifp->rt || !ifp->rt->fib6_node) {
David Ahern360a9882018-04-18 15:39:00 -07003408 struct fib6_info *f6i, *prev;
David Ahernf1705ec2016-02-24 09:25:37 -08003409
David Ahern360a9882018-04-18 15:39:00 -07003410 f6i = addrconf_f6i_alloc(net, idev, &ifp->addr, false,
3411 GFP_ATOMIC);
3412 if (IS_ERR(f6i))
3413 return PTR_ERR(f6i);
David Ahernf1705ec2016-02-24 09:25:37 -08003414
David Ahern8048ced2017-04-25 09:17:29 -07003415 /* ifp->rt can be accessed outside of rtnl */
3416 spin_lock(&ifp->lock);
3417 prev = ifp->rt;
David Ahern360a9882018-04-18 15:39:00 -07003418 ifp->rt = f6i;
David Ahern8048ced2017-04-25 09:17:29 -07003419 spin_unlock(&ifp->lock);
3420
David Ahern93531c62018-04-17 17:33:25 -07003421 fib6_info_release(prev);
David Ahernf1705ec2016-02-24 09:25:37 -08003422 }
3423
3424 if (!(ifp->flags & IFA_F_NOPREFIXROUTE)) {
3425 addrconf_prefix_route(&ifp->addr, ifp->prefix_len,
David Ahern8308f3f2018-05-27 08:09:58 -07003426 ifp->rt_priority, idev->dev, 0, 0,
3427 GFP_ATOMIC);
David Ahernf1705ec2016-02-24 09:25:37 -08003428 }
3429
David Ahern6d717132017-05-02 14:43:44 -07003430 if (ifp->state == INET6_IFADDR_STATE_PREDAD)
3431 addrconf_dad_start(ifp);
David Ahernf1705ec2016-02-24 09:25:37 -08003432
3433 return 0;
3434}
3435
David Ahernafb1d4b52018-04-17 17:33:11 -07003436static void addrconf_permanent_addr(struct net *net, struct net_device *dev)
David Ahernf1705ec2016-02-24 09:25:37 -08003437{
3438 struct inet6_ifaddr *ifp, *tmp;
3439 struct inet6_dev *idev;
3440
3441 idev = __in6_dev_get(dev);
3442 if (!idev)
3443 return;
3444
3445 write_lock_bh(&idev->lock);
3446
3447 list_for_each_entry_safe(ifp, tmp, &idev->addr_list, if_list) {
3448 if ((ifp->flags & IFA_F_PERMANENT) &&
David Ahernafb1d4b52018-04-17 17:33:11 -07003449 fixup_permanent_addr(net, idev, ifp) < 0) {
David Ahernf1705ec2016-02-24 09:25:37 -08003450 write_unlock_bh(&idev->lock);
Eric Dumazete669b862017-10-30 22:47:09 -07003451 in6_ifa_hold(ifp);
David Ahernf1705ec2016-02-24 09:25:37 -08003452 ipv6_del_addr(ifp);
3453 write_lock_bh(&idev->lock);
3454
3455 net_info_ratelimited("%s: Failed to add prefix route for address %pI6c; dropping\n",
3456 idev->dev->name, &ifp->addr);
3457 }
3458 }
3459
3460 write_unlock_bh(&idev->lock);
3461}
3462
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09003463static int addrconf_notify(struct notifier_block *this, unsigned long event,
Jiri Pirko351638e2013-05-28 01:30:21 +00003464 void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003465{
Jiri Pirko351638e2013-05-28 01:30:21 +00003466 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
Hangbin Liu896585d2018-11-21 21:52:33 +08003467 struct netdev_notifier_change_info *change_info;
David Ahern4f7f34e2016-04-07 11:10:41 -07003468 struct netdev_notifier_changeupper_info *info;
Eric Dumazet748e2d92012-08-22 21:50:59 +00003469 struct inet6_dev *idev = __in6_dev_get(dev);
WANG Cong60abc0b2017-06-21 14:34:58 -07003470 struct net *net = dev_net(dev);
YOSHIFUJI Hideakic5e33bd2005-12-21 22:57:44 +09003471 int run_pending = 0;
Herbert Xub217d612007-07-30 17:04:52 -07003472 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003473
Stephen Hemmingere21e8462010-03-20 16:09:01 -07003474 switch (event) {
YOSHIFUJI Hideaki45ba9dd2007-02-15 02:07:27 +09003475 case NETDEV_REGISTER:
Herbert Xu74235a22007-06-14 13:02:55 -07003476 if (!idev && dev->mtu >= IPV6_MIN_MTU) {
YOSHIFUJI Hideaki45ba9dd2007-02-15 02:07:27 +09003477 idev = ipv6_add_dev(dev);
WANG Conga317a2f2014-07-25 15:25:09 -07003478 if (IS_ERR(idev))
3479 return notifier_from_errno(PTR_ERR(idev));
YOSHIFUJI Hideaki45ba9dd2007-02-15 02:07:27 +09003480 }
3481 break;
Stephen Hemmingerbcdd5532010-03-20 16:08:18 -07003482
Alexander Duyckb7b0b1d2015-10-26 11:06:33 -07003483 case NETDEV_CHANGEMTU:
3484 /* if MTU under IPV6_MIN_MTU stop IPv6 on this interface. */
3485 if (dev->mtu < IPV6_MIN_MTU) {
WANG Cong60abc0b2017-06-21 14:34:58 -07003486 addrconf_ifdown(dev, dev != net->loopback_dev);
Alexander Duyckb7b0b1d2015-10-26 11:06:33 -07003487 break;
3488 }
3489
3490 if (idev) {
3491 rt6_mtu_change(dev, dev->mtu);
3492 idev->cnf.mtu6 = dev->mtu;
3493 break;
3494 }
3495
3496 /* allocate new idev */
3497 idev = ipv6_add_dev(dev);
3498 if (IS_ERR(idev))
3499 break;
3500
3501 /* device is still not ready */
3502 if (!(idev->if_flags & IF_READY))
3503 break;
3504
3505 run_pending = 1;
Joe Perchesa8eceea2020-03-12 15:50:22 -07003506 fallthrough;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003507 case NETDEV_UP:
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003508 case NETDEV_CHANGE:
Jay Vosburghc2edacf2007-07-09 10:42:47 -07003509 if (dev->flags & IFF_SLAVE)
3510 break;
3511
WANG Cong3ce62a82014-09-11 15:07:16 -07003512 if (idev && idev->cnf.disable_ipv6)
3513 break;
3514
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003515 if (event == NETDEV_UP) {
David Ahern38bd10c2016-04-21 20:56:12 -07003516 /* restore routes for permanent addresses */
David Ahernafb1d4b52018-04-17 17:33:11 -07003517 addrconf_permanent_addr(net, dev);
David Ahern38bd10c2016-04-21 20:56:12 -07003518
Mike Manning1f372c72017-09-25 22:01:36 +01003519 if (!addrconf_link_ready(dev)) {
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003520 /* device is not ready yet. */
Lubomir Rintel7c62b8d2019-01-21 14:54:20 +01003521 pr_debug("ADDRCONF(NETDEV_UP): %s: link is not ready\n",
3522 dev->name);
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003523 break;
3524 }
Kristian Slavov99081042006-02-08 16:10:53 -08003525
Evgeniy Polyakovd31c7b82007-11-30 23:36:08 +11003526 if (!idev && dev->mtu >= IPV6_MIN_MTU)
3527 idev = ipv6_add_dev(dev);
3528
WANG Conga317a2f2014-07-25 15:25:09 -07003529 if (!IS_ERR_OR_NULL(idev)) {
Kristian Slavov99081042006-02-08 16:10:53 -08003530 idev->if_flags |= IF_READY;
Benjamin Therye3ec6cf2008-11-05 01:43:57 -08003531 run_pending = 1;
3532 }
Alexander Duyckb7b0b1d2015-10-26 11:06:33 -07003533 } else if (event == NETDEV_CHANGE) {
Mike Manning1f372c72017-09-25 22:01:36 +01003534 if (!addrconf_link_ready(dev)) {
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003535 /* device is still not ready. */
Ido Schimmel27c6fa72018-01-07 12:45:05 +02003536 rt6_sync_down_dev(dev, event);
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003537 break;
3538 }
3539
Hangbin Liu896585d2018-11-21 21:52:33 +08003540 if (!IS_ERR_OR_NULL(idev)) {
Linus Lüssinga088d1d2017-02-03 08:11:03 +01003541 if (idev->if_flags & IF_READY) {
3542 /* device is already configured -
3543 * but resend MLD reports, we might
3544 * have roamed and need to update
3545 * multicast snooping switches
3546 */
3547 ipv6_mc_up(idev);
Hangbin Liu896585d2018-11-21 21:52:33 +08003548 change_info = ptr;
3549 if (change_info->flags_changed & IFF_NOARP)
3550 addrconf_dad_run(idev, true);
Ido Schimmel27c6fa72018-01-07 12:45:05 +02003551 rt6_sync_up(dev, RTNH_F_LINKDOWN);
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003552 break;
Linus Lüssinga088d1d2017-02-03 08:11:03 +01003553 }
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003554 idev->if_flags |= IF_READY;
3555 }
3556
Joe Perchesf3213832012-05-15 14:11:53 +00003557 pr_info("ADDRCONF(NETDEV_CHANGE): %s: link becomes ready\n",
3558 dev->name);
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003559
YOSHIFUJI Hideakic5e33bd2005-12-21 22:57:44 +09003560 run_pending = 1;
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003561 }
3562
Stephen Hemmingere21e8462010-03-20 16:09:01 -07003563 switch (dev->type) {
Amerigo Wang07a93622012-10-29 16:23:10 +00003564#if IS_ENABLED(CONFIG_IPV6_SIT)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003565 case ARPHRD_SIT:
3566 addrconf_sit_config(dev);
3567 break;
Joerg Roedel0be669b2006-10-10 14:49:53 -07003568#endif
Amerigo Wang07a93622012-10-29 16:23:10 +00003569#if IS_ENABLED(CONFIG_NET_IPGRE)
stephen hemmingeraee80b52011-06-08 10:44:30 +00003570 case ARPHRD_IPGRE:
3571 addrconf_gre_config(dev);
3572 break;
3573#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003574 case ARPHRD_LOOPBACK:
3575 init_loopback(dev);
3576 break;
3577
3578 default:
3579 addrconf_dev_config(dev);
3580 break;
Stephen Hemminger3ff50b72007-04-20 17:09:22 -07003581 }
Stephen Hemmingerbcdd5532010-03-20 16:08:18 -07003582
WANG Conga317a2f2014-07-25 15:25:09 -07003583 if (!IS_ERR_OR_NULL(idev)) {
YOSHIFUJI Hideakic5e33bd2005-12-21 22:57:44 +09003584 if (run_pending)
Hangbin Liu896585d2018-11-21 21:52:33 +08003585 addrconf_dad_run(idev, false);
YOSHIFUJI Hideakic5e33bd2005-12-21 22:57:44 +09003586
Ido Schimmel2127d952018-01-07 12:45:03 +02003587 /* Device has an address by now */
3588 rt6_sync_up(dev, RTNH_F_DEAD);
3589
Stephen Hemmingerbcdd5532010-03-20 16:08:18 -07003590 /*
3591 * If the MTU changed during the interface down,
3592 * when the interface up, the changed MTU must be
3593 * reflected in the idev as well as routers.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003594 */
Stephen Hemmingerbcdd5532010-03-20 16:08:18 -07003595 if (idev->cnf.mtu6 != dev->mtu &&
3596 dev->mtu >= IPV6_MIN_MTU) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003597 rt6_mtu_change(dev, dev->mtu);
3598 idev->cnf.mtu6 = dev->mtu;
3599 }
3600 idev->tstamp = jiffies;
3601 inet6_ifinfo_notify(RTM_NEWLINK, idev);
Stephen Hemmingerbcdd5532010-03-20 16:08:18 -07003602
3603 /*
3604 * If the changed mtu during down is lower than
3605 * IPV6_MIN_MTU stop IPv6 on this interface.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003606 */
3607 if (dev->mtu < IPV6_MIN_MTU)
WANG Cong60abc0b2017-06-21 14:34:58 -07003608 addrconf_ifdown(dev, dev != net->loopback_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003609 }
3610 break;
3611
Linus Torvalds1da177e2005-04-16 15:20:36 -07003612 case NETDEV_DOWN:
3613 case NETDEV_UNREGISTER:
3614 /*
3615 * Remove all addresses from this interface.
3616 */
3617 addrconf_ifdown(dev, event != NETDEV_DOWN);
3618 break;
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003619
Linus Torvalds1da177e2005-04-16 15:20:36 -07003620 case NETDEV_CHANGENAME:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003621 if (idev) {
Stephen Hemminger5632c512007-04-28 21:16:39 -07003622 snmp6_unregister_dev(idev);
Pavel Emelyanov408c4762008-01-10 17:41:21 -08003623 addrconf_sysctl_unregister(idev);
WANG Conga317a2f2014-07-25 15:25:09 -07003624 err = addrconf_sysctl_register(idev);
Herbert Xub217d612007-07-30 17:04:52 -07003625 if (err)
3626 return notifier_from_errno(err);
WANG Conga317a2f2014-07-25 15:25:09 -07003627 err = snmp6_register_dev(idev);
3628 if (err) {
3629 addrconf_sysctl_unregister(idev);
3630 return notifier_from_errno(err);
3631 }
Stephen Hemminger5632c512007-04-28 21:16:39 -07003632 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003633 break;
Stephen Hemmingerbcdd5532010-03-20 16:08:18 -07003634
Jiri Pirko93d9b7d2010-03-10 10:28:56 +00003635 case NETDEV_PRE_TYPE_CHANGE:
3636 case NETDEV_POST_TYPE_CHANGE:
Andrew Lunn3ef09522015-12-03 21:12:32 +01003637 if (idev)
3638 addrconf_type_change(dev, event);
Moni Shoua75c78502009-09-15 02:37:40 -07003639 break;
David Ahern4f7f34e2016-04-07 11:10:41 -07003640
3641 case NETDEV_CHANGEUPPER:
3642 info = ptr;
3643
3644 /* flush all routes if dev is linked to or unlinked from
3645 * an L3 master device (e.g., VRF)
3646 */
3647 if (info->upper_dev && netif_is_l3_master(info->upper_dev))
3648 addrconf_ifdown(dev, 0);
Stephen Hemminger3ff50b72007-04-20 17:09:22 -07003649 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003650
3651 return NOTIFY_OK;
3652}
3653
3654/*
3655 * addrconf module should be notified of a device going up
3656 */
3657static struct notifier_block ipv6_dev_notf = {
3658 .notifier_call = addrconf_notify,
WANG Cong242d3a42017-05-08 10:12:13 -07003659 .priority = ADDRCONF_NOTIFY_PRIORITY,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003660};
3661
Jiri Pirko93d9b7d2010-03-10 10:28:56 +00003662static void addrconf_type_change(struct net_device *dev, unsigned long event)
Moni Shoua75c78502009-09-15 02:37:40 -07003663{
3664 struct inet6_dev *idev;
3665 ASSERT_RTNL();
3666
3667 idev = __in6_dev_get(dev);
3668
Jiri Pirko93d9b7d2010-03-10 10:28:56 +00003669 if (event == NETDEV_POST_TYPE_CHANGE)
Moni Shoua75c78502009-09-15 02:37:40 -07003670 ipv6_mc_remap(idev);
Jiri Pirko93d9b7d2010-03-10 10:28:56 +00003671 else if (event == NETDEV_PRE_TYPE_CHANGE)
Moni Shoua75c78502009-09-15 02:37:40 -07003672 ipv6_mc_unmap(idev);
3673}
3674
David Ahern70af9212016-04-08 12:01:21 -07003675static bool addr_is_local(const struct in6_addr *addr)
3676{
3677 return ipv6_addr_type(addr) &
3678 (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK);
3679}
3680
Linus Torvalds1da177e2005-04-16 15:20:36 -07003681static int addrconf_ifdown(struct net_device *dev, int how)
3682{
Ido Schimmel4c981e22018-01-07 12:45:04 +02003683 unsigned long event = how ? NETDEV_UNREGISTER : NETDEV_DOWN;
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09003684 struct net *net = dev_net(dev);
stephen hemminger502a2ff2010-03-17 20:31:13 +00003685 struct inet6_dev *idev;
David Ahernf1705ec2016-02-24 09:25:37 -08003686 struct inet6_ifaddr *ifa, *tmp;
Ivan Vecera0aef78a2018-04-24 19:51:29 +02003687 bool keep_addr = false;
David S. Miller73a8bd72011-01-23 23:27:15 -08003688 int state, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003689
3690 ASSERT_RTNL();
3691
Ido Schimmel4c981e22018-01-07 12:45:04 +02003692 rt6_disable_ip(dev, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003693
3694 idev = __in6_dev_get(dev);
Ian Morris63159f22015-03-29 14:00:04 +01003695 if (!idev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003696 return -ENODEV;
3697
Stephen Hemmingerbcdd5532010-03-20 16:08:18 -07003698 /*
3699 * Step 1: remove reference to ipv6 device from parent device.
3700 * Do not dev_put!
Linus Torvalds1da177e2005-04-16 15:20:36 -07003701 */
Denis V. Lunev439e2382008-04-03 13:30:17 -07003702 if (how) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003703 idev->dead = 1;
YOSHIFUJI Hideaki8814c4b2006-09-22 14:44:24 -07003704
3705 /* protected by rtnl_lock */
Stephen Hemmingera9b3cd72011-08-01 16:19:00 +00003706 RCU_INIT_POINTER(dev->ip6_ptr, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003707
3708 /* Step 1.5: remove snmp6 entry */
3709 snmp6_unregister_dev(idev);
3710
3711 }
3712
David Ahernf1705ec2016-02-24 09:25:37 -08003713 /* combine the user config with event to determine if permanent
3714 * addresses are to be removed from address hash table
3715 */
Ivan Vecera0aef78a2018-04-24 19:51:29 +02003716 if (!how && !idev->cnf.disable_ipv6) {
3717 /* aggregate the system setting and interface setting */
3718 int _keep_addr = net->ipv6.devconf_all->keep_addr_on_down;
3719
3720 if (!_keep_addr)
3721 _keep_addr = idev->cnf.keep_addr_on_down;
3722
3723 keep_addr = (_keep_addr > 0);
3724 }
David Ahernf1705ec2016-02-24 09:25:37 -08003725
David S. Miller73a8bd72011-01-23 23:27:15 -08003726 /* Step 2: clear hash table */
3727 for (i = 0; i < IN6_ADDR_HSIZE; i++) {
3728 struct hlist_head *h = &inet6_addr_lst[i];
David S. Miller73a8bd72011-01-23 23:27:15 -08003729
3730 spin_lock_bh(&addrconf_hash_lock);
Ian Morris67ba4152014-08-24 21:53:10 +01003731restart:
Sasha Levinb67bfe02013-02-27 17:06:00 -08003732 hlist_for_each_entry_rcu(ifa, h, addr_lst) {
David S. Miller73a8bd72011-01-23 23:27:15 -08003733 if (ifa->idev == idev) {
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01003734 addrconf_del_dad_work(ifa);
David Ahernf1705ec2016-02-24 09:25:37 -08003735 /* combined flag + permanent flag decide if
3736 * address is retained on a down event
3737 */
3738 if (!keep_addr ||
David Ahern70af9212016-04-08 12:01:21 -07003739 !(ifa->flags & IFA_F_PERMANENT) ||
3740 addr_is_local(&ifa->addr)) {
David Ahernf1705ec2016-02-24 09:25:37 -08003741 hlist_del_init_rcu(&ifa->addr_lst);
3742 goto restart;
3743 }
David S. Miller73a8bd72011-01-23 23:27:15 -08003744 }
3745 }
3746 spin_unlock_bh(&addrconf_hash_lock);
3747 }
3748
Linus Torvalds1da177e2005-04-16 15:20:36 -07003749 write_lock_bh(&idev->lock);
3750
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02003751 addrconf_del_rs_timer(idev);
3752
Stephen Hemmingerbcdd5532010-03-20 16:08:18 -07003753 /* Step 2: clear flags for stateless addrconf */
Denis V. Lunev439e2382008-04-03 13:30:17 -07003754 if (!how)
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003755 idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003756
Stephen Hemmingerbcdd5532010-03-20 16:08:18 -07003757 /* Step 3: clear tempaddr list */
stephen hemminger372e6c82010-03-17 20:31:09 +00003758 while (!list_empty(&idev->tempaddr_list)) {
3759 ifa = list_first_entry(&idev->tempaddr_list,
3760 struct inet6_ifaddr, tmp_list);
3761 list_del(&ifa->tmp_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003762 write_unlock_bh(&idev->lock);
3763 spin_lock_bh(&ifa->lock);
3764
3765 if (ifa->ifpub) {
3766 in6_ifa_put(ifa->ifpub);
3767 ifa->ifpub = NULL;
3768 }
3769 spin_unlock_bh(&ifa->lock);
3770 in6_ifa_put(ifa);
3771 write_lock_bh(&idev->lock);
3772 }
stephen hemminger8f37ada2010-03-03 08:19:59 +00003773
David Ahernf1705ec2016-02-24 09:25:37 -08003774 list_for_each_entry_safe(ifa, tmp, &idev->addr_list, if_list) {
David Ahern8d1c8022018-04-17 17:33:26 -07003775 struct fib6_info *rt = NULL;
Rabin Vincenta2d6cbb2017-04-10 08:36:39 +02003776 bool keep;
David Ahern38bd10c2016-04-21 20:56:12 -07003777
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01003778 addrconf_del_dad_work(ifa);
stephen hemminger84e8b802010-03-02 13:32:46 +00003779
Rabin Vincenta2d6cbb2017-04-10 08:36:39 +02003780 keep = keep_addr && (ifa->flags & IFA_F_PERMANENT) &&
3781 !addr_is_local(&ifa->addr);
Rabin Vincenta2d6cbb2017-04-10 08:36:39 +02003782
David S. Miller73a8bd72011-01-23 23:27:15 -08003783 write_unlock_bh(&idev->lock);
Hannes Frederic Sowa8e8e6762015-03-23 23:36:03 +01003784 spin_lock_bh(&ifa->lock);
David Ahernf1705ec2016-02-24 09:25:37 -08003785
Rabin Vincenta2d6cbb2017-04-10 08:36:39 +02003786 if (keep) {
David Ahernf1705ec2016-02-24 09:25:37 -08003787 /* set state to skip the notifier below */
3788 state = INET6_IFADDR_STATE_DEAD;
David Ahern6d717132017-05-02 14:43:44 -07003789 ifa->state = INET6_IFADDR_STATE_PREDAD;
David Ahernf1705ec2016-02-24 09:25:37 -08003790 if (!(ifa->flags & IFA_F_NODAD))
3791 ifa->flags |= IFA_F_TENTATIVE;
David Ahern38bd10c2016-04-21 20:56:12 -07003792
3793 rt = ifa->rt;
3794 ifa->rt = NULL;
David Ahernf1705ec2016-02-24 09:25:37 -08003795 } else {
3796 state = ifa->state;
3797 ifa->state = INET6_IFADDR_STATE_DEAD;
David Ahernf1705ec2016-02-24 09:25:37 -08003798 }
3799
Hannes Frederic Sowa8e8e6762015-03-23 23:36:03 +01003800 spin_unlock_bh(&ifa->lock);
stephen hemminger84e8b802010-03-02 13:32:46 +00003801
David Ahern38bd10c2016-04-21 20:56:12 -07003802 if (rt)
Roopa Prabhu11dd74b2020-04-27 13:56:45 -07003803 ip6_del_rt(net, rt, false);
David Ahern38bd10c2016-04-21 20:56:12 -07003804
David S. Miller73a8bd72011-01-23 23:27:15 -08003805 if (state != INET6_IFADDR_STATE_DEAD) {
3806 __ipv6_ifa_notify(RTM_DELADDR, ifa);
Cong Wangf88c91d2013-04-14 23:18:43 +08003807 inet6addr_notifier_call_chain(NETDEV_DOWN, ifa);
Mike Manningea06f712016-07-22 18:32:11 +01003808 } else {
3809 if (idev->cnf.forwarding)
3810 addrconf_leave_anycast(ifa);
3811 addrconf_leave_solict(ifa->idev, &ifa->addr);
stephen hemminger27bdb2a2010-04-12 05:41:32 +00003812 }
stephen hemminger8f37ada2010-03-03 08:19:59 +00003813
David S. Miller73a8bd72011-01-23 23:27:15 -08003814 write_lock_bh(&idev->lock);
Eric Dumazet8ef802a2017-10-07 19:30:23 -07003815 if (!keep) {
3816 list_del_rcu(&ifa->if_list);
3817 in6_ifa_put(ifa);
3818 }
David S. Miller73a8bd72011-01-23 23:27:15 -08003819 }
stephen hemminger8f37ada2010-03-03 08:19:59 +00003820
Linus Torvalds1da177e2005-04-16 15:20:36 -07003821 write_unlock_bh(&idev->lock);
3822
Sabrina Dubroca381f4dc2014-09-10 23:23:02 +02003823 /* Step 5: Discard anycast and multicast list */
3824 if (how) {
3825 ipv6_ac_destroy_dev(idev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003826 ipv6_mc_destroy_dev(idev);
Sabrina Dubroca381f4dc2014-09-10 23:23:02 +02003827 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003828 ipv6_mc_down(idev);
Sabrina Dubroca381f4dc2014-09-10 23:23:02 +02003829 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003830
Linus Torvalds1da177e2005-04-16 15:20:36 -07003831 idev->tstamp = jiffies;
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09003832
Stephen Hemmingerbcdd5532010-03-20 16:08:18 -07003833 /* Last: Shot the device (if unregistered) */
Denis V. Lunev439e2382008-04-03 13:30:17 -07003834 if (how) {
Pavel Emelyanov408c4762008-01-10 17:41:21 -08003835 addrconf_sysctl_unregister(idev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003836 neigh_parms_release(&nd_tbl, idev->nd_parms);
3837 neigh_ifdown(&nd_tbl, dev);
3838 in6_dev_put(idev);
3839 }
3840 return 0;
3841}
3842
Kees Cooke99e88a2017-10-16 14:43:17 -07003843static void addrconf_rs_timer(struct timer_list *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003844{
Kees Cooke99e88a2017-10-16 14:43:17 -07003845 struct inet6_dev *idev = from_timer(idev, t, rs_timer);
Cong Wangcaf92bc2013-08-31 13:44:32 +08003846 struct net_device *dev = idev->dev;
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02003847 struct in6_addr lladdr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003848
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02003849 write_lock(&idev->lock);
stephen hemminger5b2a1952010-03-02 13:32:45 +00003850 if (idev->dead || !(idev->if_flags & IF_READY))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003851 goto out;
3852
Shmulik Ladkani9ba2add2012-12-02 01:44:53 +00003853 if (!ipv6_accept_ra(idev))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003854 goto out;
stephen hemminger5b2a1952010-03-02 13:32:45 +00003855
3856 /* Announcement received after solicitation was sent */
3857 if (idev->if_flags & IF_RA_RCVD)
3858 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003859
Maciej Żenczykowskibd11f072016-09-27 23:57:58 -07003860 if (idev->rs_probes++ < idev->cnf.rtr_solicits || idev->cnf.rtr_solicits < 0) {
Cong Wangcaf92bc2013-08-31 13:44:32 +08003861 write_unlock(&idev->lock);
3862 if (!ipv6_get_lladdr(dev, &lladdr, IFA_F_TENTATIVE))
3863 ndisc_send_rs(dev, &lladdr,
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02003864 &in6addr_linklocal_allrouters);
3865 else
Cong Wangcaf92bc2013-08-31 13:44:32 +08003866 goto put;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003867
Cong Wangcaf92bc2013-08-31 13:44:32 +08003868 write_lock(&idev->lock);
Maciej Żenczykowskibd11f072016-09-27 23:57:58 -07003869 idev->rs_interval = rfc3315_s14_backoff_update(
3870 idev->rs_interval, idev->cnf.rtr_solicit_max_interval);
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02003871 /* The wait after the last probe can be shorter */
3872 addrconf_mod_rs_timer(idev, (idev->rs_probes ==
3873 idev->cnf.rtr_solicits) ?
3874 idev->cnf.rtr_solicit_delay :
Maciej Żenczykowskibd11f072016-09-27 23:57:58 -07003875 idev->rs_interval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003876 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003877 /*
3878 * Note: we do not support deprecated "all on-link"
3879 * assumption any longer.
3880 */
Joe Perches91df42b2012-05-15 14:11:54 +00003881 pr_debug("%s: no IPv6 routers present\n", idev->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003882 }
3883
3884out:
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02003885 write_unlock(&idev->lock);
Cong Wangcaf92bc2013-08-31 13:44:32 +08003886put:
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02003887 in6_dev_put(idev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003888}
3889
3890/*
3891 * Duplicate Address Detection
3892 */
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003893static void addrconf_dad_kick(struct inet6_ifaddr *ifp)
3894{
3895 unsigned long rand_num;
3896 struct inet6_dev *idev = ifp->idev;
Erik Nordmarkadc176c2016-12-02 14:00:08 -08003897 u64 nonce;
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003898
Neil Horman95c385b2007-04-25 17:08:10 -07003899 if (ifp->flags & IFA_F_OPTIMISTIC)
3900 rand_num = 0;
3901 else
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -05003902 rand_num = prandom_u32() % (idev->cnf.rtr_solicit_delay ? : 1);
Neil Horman95c385b2007-04-25 17:08:10 -07003903
Erik Nordmarkadc176c2016-12-02 14:00:08 -08003904 nonce = 0;
3905 if (idev->cnf.enhanced_dad ||
3906 dev_net(idev->dev)->ipv6.devconf_all->enhanced_dad) {
3907 do
3908 get_random_bytes(&nonce, 6);
3909 while (nonce == 0);
3910 }
3911 ifp->dad_nonce = nonce;
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02003912 ifp->dad_probes = idev->cnf.dad_transmits;
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01003913 addrconf_mod_dad_work(ifp, rand_num);
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003914}
3915
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01003916static void addrconf_dad_begin(struct inet6_ifaddr *ifp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003917{
3918 struct inet6_dev *idev = ifp->idev;
3919 struct net_device *dev = idev->dev;
Paolo Abeni764d3be2016-11-22 16:57:40 +01003920 bool bump_id, notify = false;
David Ahernafb1d4b52018-04-17 17:33:11 -07003921 struct net *net;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003922
3923 addrconf_join_solict(dev, &ifp->addr);
3924
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -05003925 prandom_seed((__force u32) ifp->addr.s6_addr32[3]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003926
3927 read_lock_bh(&idev->lock);
Herbert Xu622ccdf2010-05-18 15:56:06 -07003928 spin_lock(&ifp->lock);
Herbert Xue9d3e082010-05-18 15:36:06 -07003929 if (ifp->state == INET6_IFADDR_STATE_DEAD)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003930 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003931
David Ahernafb1d4b52018-04-17 17:33:11 -07003932 net = dev_net(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003933 if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) ||
David Ahernafb1d4b52018-04-17 17:33:11 -07003934 (net->ipv6.devconf_all->accept_dad < 1 &&
Matteo Crocea2d3f3e2017-10-05 19:03:05 +02003935 idev->cnf.accept_dad < 1) ||
Noriaki TAKAMIYA55ebaef2006-09-22 14:45:27 -07003936 !(ifp->flags&IFA_F_TENTATIVE) ||
3937 ifp->flags & IFA_F_NODAD) {
David Ahernc76fe2d2018-01-25 20:16:29 -08003938 bool send_na = false;
3939
3940 if (ifp->flags & IFA_F_TENTATIVE &&
3941 !(ifp->flags & IFA_F_OPTIMISTIC))
3942 send_na = true;
Paolo Abeni764d3be2016-11-22 16:57:40 +01003943 bump_id = ifp->flags & IFA_F_TENTATIVE;
Brian Haleycc411d02009-09-09 14:41:32 +00003944 ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED);
stephen hemminger21809fa2010-02-08 19:48:52 +00003945 spin_unlock(&ifp->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946 read_unlock_bh(&idev->lock);
3947
David Ahernc76fe2d2018-01-25 20:16:29 -08003948 addrconf_dad_completed(ifp, bump_id, send_na);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949 return;
3950 }
3951
YOSHIFUJI Hideaki6732bad2005-12-27 13:35:15 -08003952 if (!(idev->if_flags & IF_READY)) {
stephen hemminger21809fa2010-02-08 19:48:52 +00003953 spin_unlock(&ifp->lock);
YOSHIFUJI Hideaki6732bad2005-12-27 13:35:15 -08003954 read_unlock_bh(&idev->lock);
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003955 /*
Masatake YAMATO590a9882009-06-09 10:41:12 +09003956 * If the device is not ready:
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003957 * - keep it tentative if it is a permanent address.
3958 * - otherwise, kill it.
3959 */
3960 in6_ifa_hold(ifp);
Brian Haleycc411d02009-09-09 14:41:32 +00003961 addrconf_dad_stop(ifp, 0);
YOSHIFUJI Hideaki6732bad2005-12-27 13:35:15 -08003962 return;
YOSHIFUJI Hideaki3c21edb2005-12-21 22:57:24 +09003963 }
Neil Horman95c385b2007-04-25 17:08:10 -07003964
3965 /*
3966 * Optimistic nodes can start receiving
3967 * Frames right away
3968 */
Erik Kline7fd25612014-10-28 18:11:14 +09003969 if (ifp->flags & IFA_F_OPTIMISTIC) {
David Ahernafb1d4b52018-04-17 17:33:11 -07003970 ip6_ins_rt(net, ifp->rt);
3971 if (ipv6_use_optimistic_addr(net, idev)) {
Erik Kline7fd25612014-10-28 18:11:14 +09003972 /* Because optimistic nodes can use this address,
3973 * notify listeners. If DAD fails, RTM_DELADDR is sent.
3974 */
subashab@codeaurora.org16186a82016-02-02 02:11:10 +00003975 notify = true;
Erik Kline7fd25612014-10-28 18:11:14 +09003976 }
3977 }
Neil Horman95c385b2007-04-25 17:08:10 -07003978
YOSHIFUJI Hideaki6732bad2005-12-27 13:35:15 -08003979 addrconf_dad_kick(ifp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003980out:
Herbert Xu622ccdf2010-05-18 15:56:06 -07003981 spin_unlock(&ifp->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003982 read_unlock_bh(&idev->lock);
subashab@codeaurora.org16186a82016-02-02 02:11:10 +00003983 if (notify)
3984 ipv6_ifa_notify(RTM_NEWADDR, ifp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003985}
3986
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01003987static void addrconf_dad_start(struct inet6_ifaddr *ifp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003988{
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01003989 bool begin_dad = false;
3990
Hannes Frederic Sowa8e8e6762015-03-23 23:36:03 +01003991 spin_lock_bh(&ifp->lock);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01003992 if (ifp->state != INET6_IFADDR_STATE_DEAD) {
3993 ifp->state = INET6_IFADDR_STATE_PREDAD;
3994 begin_dad = true;
3995 }
Hannes Frederic Sowa8e8e6762015-03-23 23:36:03 +01003996 spin_unlock_bh(&ifp->lock);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01003997
3998 if (begin_dad)
3999 addrconf_mod_dad_work(ifp, 0);
4000}
4001
4002static void addrconf_dad_work(struct work_struct *w)
4003{
4004 struct inet6_ifaddr *ifp = container_of(to_delayed_work(w),
4005 struct inet6_ifaddr,
4006 dad_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004007 struct inet6_dev *idev = ifp->idev;
Paolo Abeni764d3be2016-11-22 16:57:40 +01004008 bool bump_id, disable_ipv6 = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004009 struct in6_addr mcaddr;
4010
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004011 enum {
4012 DAD_PROCESS,
4013 DAD_BEGIN,
4014 DAD_ABORT,
4015 } action = DAD_PROCESS;
4016
4017 rtnl_lock();
4018
Hannes Frederic Sowa8e8e6762015-03-23 23:36:03 +01004019 spin_lock_bh(&ifp->lock);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004020 if (ifp->state == INET6_IFADDR_STATE_PREDAD) {
4021 action = DAD_BEGIN;
4022 ifp->state = INET6_IFADDR_STATE_DAD;
4023 } else if (ifp->state == INET6_IFADDR_STATE_ERRDAD) {
4024 action = DAD_ABORT;
4025 ifp->state = INET6_IFADDR_STATE_POSTDAD;
Mike Manning85b51b12016-08-18 14:39:40 +01004026
Matteo Croce35e015e2017-09-12 17:46:37 +02004027 if ((dev_net(idev->dev)->ipv6.devconf_all->accept_dad > 1 ||
4028 idev->cnf.accept_dad > 1) &&
4029 !idev->cnf.disable_ipv6 &&
Mike Manning85b51b12016-08-18 14:39:40 +01004030 !(ifp->flags & IFA_F_STABLE_PRIVACY)) {
4031 struct in6_addr addr;
4032
4033 addr.s6_addr32[0] = htonl(0xfe800000);
4034 addr.s6_addr32[1] = 0;
4035
4036 if (!ipv6_generate_eui64(addr.s6_addr + 8, idev->dev) &&
4037 ipv6_addr_equal(&ifp->addr, &addr)) {
4038 /* DAD failed for link-local based on MAC */
4039 idev->cnf.disable_ipv6 = 1;
4040
4041 pr_info("%s: IPv6 being disabled!\n",
4042 ifp->idev->dev->name);
4043 disable_ipv6 = true;
4044 }
4045 }
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004046 }
Hannes Frederic Sowa8e8e6762015-03-23 23:36:03 +01004047 spin_unlock_bh(&ifp->lock);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004048
4049 if (action == DAD_BEGIN) {
4050 addrconf_dad_begin(ifp);
4051 goto out;
4052 } else if (action == DAD_ABORT) {
Wei Yongjun751eb6b2016-09-05 16:06:31 +08004053 in6_ifa_hold(ifp);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004054 addrconf_dad_stop(ifp, 1);
Mike Manning85b51b12016-08-18 14:39:40 +01004055 if (disable_ipv6)
4056 addrconf_ifdown(idev->dev, 0);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004057 goto out;
4058 }
4059
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02004060 if (!ifp->dad_probes && addrconf_dad_end(ifp))
Herbert Xuf2344a12010-05-18 15:55:27 -07004061 goto out;
4062
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004063 write_lock_bh(&idev->lock);
stephen hemminger122e4512010-03-02 13:32:44 +00004064 if (idev->dead || !(idev->if_flags & IF_READY)) {
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004065 write_unlock_bh(&idev->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004066 goto out;
4067 }
stephen hemminger21809fa2010-02-08 19:48:52 +00004068
4069 spin_lock(&ifp->lock);
Herbert Xu622ccdf2010-05-18 15:56:06 -07004070 if (ifp->state == INET6_IFADDR_STATE_DEAD) {
4071 spin_unlock(&ifp->lock);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004072 write_unlock_bh(&idev->lock);
Herbert Xu622ccdf2010-05-18 15:56:06 -07004073 goto out;
4074 }
4075
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02004076 if (ifp->dad_probes == 0) {
David Ahernc76fe2d2018-01-25 20:16:29 -08004077 bool send_na = false;
4078
Linus Torvalds1da177e2005-04-16 15:20:36 -07004079 /*
4080 * DAD was successful
4081 */
4082
David Ahernc76fe2d2018-01-25 20:16:29 -08004083 if (ifp->flags & IFA_F_TENTATIVE &&
4084 !(ifp->flags & IFA_F_OPTIMISTIC))
4085 send_na = true;
Paolo Abeni764d3be2016-11-22 16:57:40 +01004086 bump_id = ifp->flags & IFA_F_TENTATIVE;
Brian Haleycc411d02009-09-09 14:41:32 +00004087 ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED);
stephen hemminger21809fa2010-02-08 19:48:52 +00004088 spin_unlock(&ifp->lock);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004089 write_unlock_bh(&idev->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004090
David Ahernc76fe2d2018-01-25 20:16:29 -08004091 addrconf_dad_completed(ifp, bump_id, send_na);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004092
4093 goto out;
4094 }
4095
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02004096 ifp->dad_probes--;
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004097 addrconf_mod_dad_work(ifp,
Hangbin Liu19e16d22020-04-01 14:46:20 +08004098 max(NEIGH_VAR(ifp->idev->nd_parms, RETRANS_TIME),
4099 HZ/100));
stephen hemminger21809fa2010-02-08 19:48:52 +00004100 spin_unlock(&ifp->lock);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004101 write_unlock_bh(&idev->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004102
4103 /* send a neighbour solicitation for our addr */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004104 addrconf_addr_solict_mult(&ifp->addr, &mcaddr);
Erik Nordmarkadc176c2016-12-02 14:00:08 -08004105 ndisc_send_ns(ifp->idev->dev, &ifp->addr, &mcaddr, &in6addr_any,
4106 ifp->dad_nonce);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004107out:
4108 in6_ifa_put(ifp);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004109 rtnl_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110}
4111
Hannes Frederic Sowa11ffff72014-01-16 20:13:04 +01004112/* ifp->idev must be at least read locked */
4113static bool ipv6_lonely_lladdr(struct inet6_ifaddr *ifp)
4114{
4115 struct inet6_ifaddr *ifpiter;
4116 struct inet6_dev *idev = ifp->idev;
4117
Hannes Frederic Sowa602582c2014-01-19 21:58:19 +01004118 list_for_each_entry_reverse(ifpiter, &idev->addr_list, if_list) {
4119 if (ifpiter->scope > IFA_LINK)
4120 break;
Hannes Frederic Sowa11ffff72014-01-16 20:13:04 +01004121 if (ifp != ifpiter && ifpiter->scope == IFA_LINK &&
4122 (ifpiter->flags & (IFA_F_PERMANENT|IFA_F_TENTATIVE|
4123 IFA_F_OPTIMISTIC|IFA_F_DADFAILED)) ==
4124 IFA_F_PERMANENT)
4125 return false;
4126 }
4127 return true;
4128}
4129
David Ahernc76fe2d2018-01-25 20:16:29 -08004130static void addrconf_dad_completed(struct inet6_ifaddr *ifp, bool bump_id,
4131 bool send_na)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004132{
Stephen Hemmingere21e8462010-03-20 16:09:01 -07004133 struct net_device *dev = ifp->idev->dev;
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02004134 struct in6_addr lladdr;
Hannes Frederic Sowab173ee42013-06-27 00:07:01 +02004135 bool send_rs, send_mld;
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02004136
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004137 addrconf_del_dad_work(ifp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004138
4139 /*
4140 * Configure the address for reception. Now it is valid.
4141 */
4142
4143 ipv6_ifa_notify(RTM_NEWADDR, ifp);
4144
Tore Anderson026359b2011-08-28 23:47:33 +00004145 /* If added prefix is link local and we are prepared to process
4146 router advertisements, start sending router solicitations.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004147 */
4148
Hannes Frederic Sowa1ec047e2013-06-27 00:06:56 +02004149 read_lock_bh(&ifp->idev->lock);
Hannes Frederic Sowa11ffff72014-01-16 20:13:04 +01004150 send_mld = ifp->scope == IFA_LINK && ipv6_lonely_lladdr(ifp);
Hannes Frederic Sowab173ee42013-06-27 00:07:01 +02004151 send_rs = send_mld &&
4152 ipv6_accept_ra(ifp->idev) &&
Maciej Żenczykowskibd11f072016-09-27 23:57:58 -07004153 ifp->idev->cnf.rtr_solicits != 0 &&
Hannes Frederic Sowab173ee42013-06-27 00:07:01 +02004154 (dev->flags&IFF_LOOPBACK) == 0;
Hannes Frederic Sowa1ec047e2013-06-27 00:06:56 +02004155 read_unlock_bh(&ifp->idev->lock);
4156
Hannes Frederic Sowab173ee42013-06-27 00:07:01 +02004157 /* While dad is in progress mld report's source address is in6_addrany.
4158 * Resend with proper ll now.
4159 */
4160 if (send_mld)
4161 ipv6_mc_dad_complete(ifp->idev);
4162
David Ahernc76fe2d2018-01-25 20:16:29 -08004163 /* send unsolicited NA if enabled */
4164 if (send_na &&
4165 (ifp->idev->cnf.ndisc_notify ||
4166 dev_net(dev)->ipv6.devconf_all->ndisc_notify)) {
4167 ndisc_send_na(dev, &in6addr_linklocal_allnodes, &ifp->addr,
4168 /*router=*/ !!ifp->idev->cnf.forwarding,
4169 /*solicited=*/ false, /*override=*/ true,
4170 /*inc_opt=*/ true);
4171 }
4172
Hannes Frederic Sowa1ec047e2013-06-27 00:06:56 +02004173 if (send_rs) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004174 /*
4175 * If a host as already performed a random delay
4176 * [...] as part of DAD [...] there is no need
4177 * to delay again before sending the first RS
4178 */
Hannes Frederic Sowa1ec047e2013-06-27 00:06:56 +02004179 if (ipv6_get_lladdr(dev, &lladdr, IFA_F_TENTATIVE))
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02004180 return;
Hannes Frederic Sowa1ec047e2013-06-27 00:06:56 +02004181 ndisc_send_rs(dev, &lladdr, &in6addr_linklocal_allrouters);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004182
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02004183 write_lock_bh(&ifp->idev->lock);
4184 spin_lock(&ifp->lock);
Maciej Żenczykowskibd11f072016-09-27 23:57:58 -07004185 ifp->idev->rs_interval = rfc3315_s14_backoff_init(
4186 ifp->idev->cnf.rtr_solicit_interval);
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02004187 ifp->idev->rs_probes = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004188 ifp->idev->if_flags |= IF_RS_SENT;
Maciej Żenczykowskibd11f072016-09-27 23:57:58 -07004189 addrconf_mod_rs_timer(ifp->idev, ifp->idev->rs_interval);
Hannes Frederic Sowab7b1bfc2013-06-23 18:39:01 +02004190 spin_unlock(&ifp->lock);
4191 write_unlock_bh(&ifp->idev->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004192 }
Paolo Abeni764d3be2016-11-22 16:57:40 +01004193
4194 if (bump_id)
4195 rt_genid_bump_ipv6(dev_net(dev));
Marcus Huewea11a7f72017-02-06 18:34:56 +01004196
4197 /* Make sure that a new temporary address will be created
4198 * before this temporary address becomes deprecated.
4199 */
4200 if (ifp->flags & IFA_F_TEMPORARY)
4201 addrconf_verify_rtnl();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004202}
4203
Hangbin Liu896585d2018-11-21 21:52:33 +08004204static void addrconf_dad_run(struct inet6_dev *idev, bool restart)
Stephen Hemmingere21e8462010-03-20 16:09:01 -07004205{
YOSHIFUJI Hideakic5e33bd2005-12-21 22:57:44 +09004206 struct inet6_ifaddr *ifp;
4207
4208 read_lock_bh(&idev->lock);
stephen hemminger502a2ff2010-03-17 20:31:13 +00004209 list_for_each_entry(ifp, &idev->addr_list, if_list) {
stephen hemminger21809fa2010-02-08 19:48:52 +00004210 spin_lock(&ifp->lock);
Hangbin Liu896585d2018-11-21 21:52:33 +08004211 if ((ifp->flags & IFA_F_TENTATIVE &&
4212 ifp->state == INET6_IFADDR_STATE_DAD) || restart) {
4213 if (restart)
4214 ifp->state = INET6_IFADDR_STATE_PREDAD;
Herbert Xuf2344a12010-05-18 15:55:27 -07004215 addrconf_dad_kick(ifp);
Hangbin Liu896585d2018-11-21 21:52:33 +08004216 }
stephen hemminger21809fa2010-02-08 19:48:52 +00004217 spin_unlock(&ifp->lock);
YOSHIFUJI Hideakic5e33bd2005-12-21 22:57:44 +09004218 }
4219 read_unlock_bh(&idev->lock);
4220}
4221
Linus Torvalds1da177e2005-04-16 15:20:36 -07004222#ifdef CONFIG_PROC_FS
4223struct if6_iter_state {
Daniel Lezcano3c400902008-01-10 22:42:49 -08004224 struct seq_net_private p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004225 int bucket;
Mihai Maruseac1d578302012-01-03 23:31:35 +00004226 int offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004227};
4228
Mihai Maruseac1d578302012-01-03 23:31:35 +00004229static struct inet6_ifaddr *if6_get_first(struct seq_file *seq, loff_t pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004230{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004231 struct if6_iter_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09004232 struct net *net = seq_file_net(seq);
Eric Dumazeta5c1d982017-10-23 16:17:50 -07004233 struct inet6_ifaddr *ifa = NULL;
Mihai Maruseac1d578302012-01-03 23:31:35 +00004234 int p = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004235
Mihai Maruseac1d578302012-01-03 23:31:35 +00004236 /* initial bucket if pos is 0 */
4237 if (pos == 0) {
4238 state->bucket = 0;
4239 state->offset = 0;
4240 }
4241
4242 for (; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) {
Eric Dumazeta5c1d982017-10-23 16:17:50 -07004243 hlist_for_each_entry_rcu(ifa, &inet6_addr_lst[state->bucket],
Mihai Maruseac1d578302012-01-03 23:31:35 +00004244 addr_lst) {
Eric Dumazet9f0d3c22012-10-16 07:37:27 +00004245 if (!net_eq(dev_net(ifa->idev->dev), net))
4246 continue;
Mihai Maruseac1d578302012-01-03 23:31:35 +00004247 /* sync with offset */
4248 if (p < state->offset) {
4249 p++;
4250 continue;
4251 }
Eric Dumazet9f0d3c22012-10-16 07:37:27 +00004252 return ifa;
Mihai Maruseac1d578302012-01-03 23:31:35 +00004253 }
4254
4255 /* prepare for next bucket */
4256 state->offset = 0;
4257 p = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004258 }
stephen hemmingerc2e21292010-03-17 20:31:10 +00004259 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004260}
4261
stephen hemmingerc2e21292010-03-17 20:31:10 +00004262static struct inet6_ifaddr *if6_get_next(struct seq_file *seq,
4263 struct inet6_ifaddr *ifa)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004264{
4265 struct if6_iter_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09004266 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004267
Eric Dumazeta5c1d982017-10-23 16:17:50 -07004268 hlist_for_each_entry_continue_rcu(ifa, addr_lst) {
Eric Dumazet9f0d3c22012-10-16 07:37:27 +00004269 if (!net_eq(dev_net(ifa->idev->dev), net))
4270 continue;
Mihai Maruseac1d578302012-01-03 23:31:35 +00004271 state->offset++;
Eric Dumazet9f0d3c22012-10-16 07:37:27 +00004272 return ifa;
Mihai Maruseac1d578302012-01-03 23:31:35 +00004273 }
stephen hemmingerc2e21292010-03-17 20:31:10 +00004274
Jeff Barnhill86f9bd12018-09-21 00:45:27 +00004275 state->offset = 0;
stephen hemmingerc2e21292010-03-17 20:31:10 +00004276 while (++state->bucket < IN6_ADDR_HSIZE) {
Eric Dumazeta5c1d982017-10-23 16:17:50 -07004277 hlist_for_each_entry_rcu(ifa,
stephen hemmingerc2e21292010-03-17 20:31:10 +00004278 &inet6_addr_lst[state->bucket], addr_lst) {
Eric Dumazet9f0d3c22012-10-16 07:37:27 +00004279 if (!net_eq(dev_net(ifa->idev->dev), net))
4280 continue;
Eric Dumazet9f0d3c22012-10-16 07:37:27 +00004281 return ifa;
Daniel Lezcano3c400902008-01-10 22:42:49 -08004282 }
4283 }
4284
stephen hemmingerc2e21292010-03-17 20:31:10 +00004285 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004286}
4287
Linus Torvalds1da177e2005-04-16 15:20:36 -07004288static void *if6_seq_start(struct seq_file *seq, loff_t *pos)
Eric Dumazeta5c1d982017-10-23 16:17:50 -07004289 __acquires(rcu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004290{
Eric Dumazeta5c1d982017-10-23 16:17:50 -07004291 rcu_read_lock();
Mihai Maruseac1d578302012-01-03 23:31:35 +00004292 return if6_get_first(seq, *pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004293}
4294
4295static void *if6_seq_next(struct seq_file *seq, void *v, loff_t *pos)
4296{
4297 struct inet6_ifaddr *ifa;
4298
4299 ifa = if6_get_next(seq, v);
4300 ++*pos;
4301 return ifa;
4302}
4303
4304static void if6_seq_stop(struct seq_file *seq, void *v)
Eric Dumazeta5c1d982017-10-23 16:17:50 -07004305 __releases(rcu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004306{
Eric Dumazeta5c1d982017-10-23 16:17:50 -07004307 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004308}
4309
4310static int if6_seq_show(struct seq_file *seq, void *v)
4311{
4312 struct inet6_ifaddr *ifp = (struct inet6_ifaddr *)v;
Jiri Pirko971a3512013-12-10 13:56:29 +01004313 seq_printf(seq, "%pi6 %02x %02x %02x %02x %8s\n",
Harvey Harrisonb0711952008-10-28 16:05:40 -07004314 &ifp->addr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004315 ifp->idev->dev->ifindex,
4316 ifp->prefix_len,
4317 ifp->scope,
Jiri Pirko971a3512013-12-10 13:56:29 +01004318 (u8) ifp->flags,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004319 ifp->idev->dev->name);
4320 return 0;
4321}
4322
Philippe De Muyter56b3d972007-07-10 23:07:31 -07004323static const struct seq_operations if6_seq_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004324 .start = if6_seq_start,
4325 .next = if6_seq_next,
4326 .show = if6_seq_show,
4327 .stop = if6_seq_stop,
4328};
4329
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00004330static int __net_init if6_proc_net_init(struct net *net)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004331{
Christoph Hellwigc3506372018-04-10 19:42:55 +02004332 if (!proc_create_net("if_inet6", 0444, net->proc_net, &if6_seq_ops,
4333 sizeof(struct if6_iter_state)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004334 return -ENOMEM;
4335 return 0;
4336}
4337
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00004338static void __net_exit if6_proc_net_exit(struct net *net)
Daniel Lezcano3c400902008-01-10 22:42:49 -08004339{
Gao fengece31ff2013-02-18 01:34:56 +00004340 remove_proc_entry("if_inet6", net->proc_net);
Daniel Lezcano3c400902008-01-10 22:42:49 -08004341}
4342
4343static struct pernet_operations if6_proc_net_ops = {
Ian Morris67ba4152014-08-24 21:53:10 +01004344 .init = if6_proc_net_init,
4345 .exit = if6_proc_net_exit,
Daniel Lezcano3c400902008-01-10 22:42:49 -08004346};
4347
4348int __init if6_proc_init(void)
4349{
4350 return register_pernet_subsys(&if6_proc_net_ops);
4351}
4352
Linus Torvalds1da177e2005-04-16 15:20:36 -07004353void if6_proc_exit(void)
4354{
Daniel Lezcano3c400902008-01-10 22:42:49 -08004355 unregister_pernet_subsys(&if6_proc_net_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004356}
4357#endif /* CONFIG_PROC_FS */
4358
Amerigo Wang07a93622012-10-29 16:23:10 +00004359#if IS_ENABLED(CONFIG_IPV6_MIP6)
Noriaki TAKAMIYA3b9f9a12006-09-22 14:45:56 -07004360/* Check if address is a home address configured on any interface. */
Eric Dumazetb71d1d42011-04-22 04:53:02 +00004361int ipv6_chk_home_addr(struct net *net, const struct in6_addr *addr)
Noriaki TAKAMIYA3b9f9a12006-09-22 14:45:56 -07004362{
Eric Dumazet3f27fb22017-10-23 16:17:47 -07004363 unsigned int hash = inet6_addr_hash(net, addr);
stephen hemmingerc2e21292010-03-17 20:31:10 +00004364 struct inet6_ifaddr *ifp = NULL;
Eric Dumazet3f27fb22017-10-23 16:17:47 -07004365 int ret = 0;
stephen hemmingerc2e21292010-03-17 20:31:10 +00004366
Eric Dumazet4e5f47a2017-10-23 16:17:51 -07004367 rcu_read_lock();
4368 hlist_for_each_entry_rcu(ifp, &inet6_addr_lst[hash], addr_lst) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09004369 if (!net_eq(dev_net(ifp->idev->dev), net))
Daniel Lezcano389f6612008-01-10 22:44:40 -08004370 continue;
YOSHIFUJI Hideakicaad2952008-04-10 15:42:07 +09004371 if (ipv6_addr_equal(&ifp->addr, addr) &&
Noriaki TAKAMIYA3b9f9a12006-09-22 14:45:56 -07004372 (ifp->flags & IFA_F_HOMEADDRESS)) {
4373 ret = 1;
4374 break;
4375 }
4376 }
Eric Dumazet4e5f47a2017-10-23 16:17:51 -07004377 rcu_read_unlock();
Noriaki TAKAMIYA3b9f9a12006-09-22 14:45:56 -07004378 return ret;
4379}
4380#endif
4381
Alexander Aringf37c6052020-03-27 18:00:19 -04004382/* RFC6554 has some algorithm to avoid loops in segment routing by
4383 * checking if the segments contains any of a local interface address.
4384 *
4385 * Quote:
4386 *
4387 * To detect loops in the SRH, a router MUST determine if the SRH
4388 * includes multiple addresses assigned to any interface on that router.
4389 * If such addresses appear more than once and are separated by at least
4390 * one address not assigned to that router.
4391 */
4392int ipv6_chk_rpl_srh_loop(struct net *net, const struct in6_addr *segs,
4393 unsigned char nsegs)
4394{
4395 const struct in6_addr *addr;
4396 int i, ret = 0, found = 0;
4397 struct inet6_ifaddr *ifp;
4398 bool separated = false;
4399 unsigned int hash;
4400 bool hash_found;
4401
4402 rcu_read_lock();
4403 for (i = 0; i < nsegs; i++) {
4404 addr = &segs[i];
4405 hash = inet6_addr_hash(net, addr);
4406
4407 hash_found = false;
4408 hlist_for_each_entry_rcu(ifp, &inet6_addr_lst[hash], addr_lst) {
4409 if (!net_eq(dev_net(ifp->idev->dev), net))
4410 continue;
4411
4412 if (ipv6_addr_equal(&ifp->addr, addr)) {
4413 hash_found = true;
4414 break;
4415 }
4416 }
4417
4418 if (hash_found) {
4419 if (found > 1 && separated) {
4420 ret = 1;
4421 break;
4422 }
4423
4424 separated = false;
4425 found++;
4426 } else {
4427 separated = true;
4428 }
4429 }
4430 rcu_read_unlock();
4431
4432 return ret;
4433}
4434
Linus Torvalds1da177e2005-04-16 15:20:36 -07004435/*
4436 * Periodic address status verification
4437 */
4438
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004439static void addrconf_verify_rtnl(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004440{
YOSHIFUJI Hideakib2db7562010-03-20 16:11:12 -07004441 unsigned long now, next, next_sec, next_sched;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004442 struct inet6_ifaddr *ifp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004443 int i;
4444
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004445 ASSERT_RTNL();
4446
stephen hemminger5c578aed2010-03-17 20:31:11 +00004447 rcu_read_lock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004448 now = jiffies;
YOSHIFUJI Hideakib2db7562010-03-20 16:11:12 -07004449 next = round_jiffies_up(now + ADDR_CHECK_FREQUENCY);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004450
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004451 cancel_delayed_work(&addr_chk_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004452
Stephen Hemmingerbcdd5532010-03-20 16:08:18 -07004453 for (i = 0; i < IN6_ADDR_HSIZE; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004454restart:
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004455 hlist_for_each_entry_rcu_bh(ifp, &inet6_addr_lst[i], addr_lst) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004456 unsigned long age;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004457
Yasushi Asanofad8da32013-12-31 12:04:19 +09004458 /* When setting preferred_lft to a value not zero or
4459 * infinity, while valid_lft is infinity
4460 * IFA_F_PERMANENT has a non-infinity life time.
4461 */
4462 if ((ifp->flags & IFA_F_PERMANENT) &&
4463 (ifp->prefered_lft == INFINITY_LIFE_TIME))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004464 continue;
4465
4466 spin_lock(&ifp->lock);
YOSHIFUJI Hideakib2db7562010-03-20 16:11:12 -07004467 /* We try to batch several events at once. */
4468 age = (now - ifp->tstamp + ADDRCONF_TIMER_FUZZ_MINUS) / HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004469
YOSHIFUJI Hideaki8f27ebb2006-07-28 18:12:11 +09004470 if (ifp->valid_lft != INFINITY_LIFE_TIME &&
4471 age >= ifp->valid_lft) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004472 spin_unlock(&ifp->lock);
4473 in6_ifa_hold(ifp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004474 ipv6_del_addr(ifp);
4475 goto restart;
YOSHIFUJI Hideaki8f27ebb2006-07-28 18:12:11 +09004476 } else if (ifp->prefered_lft == INFINITY_LIFE_TIME) {
4477 spin_unlock(&ifp->lock);
4478 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004479 } else if (age >= ifp->prefered_lft) {
Brian Haleya1ed0522009-07-02 07:10:52 +00004480 /* jiffies - ifp->tstamp > age >= ifp->prefered_lft */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004481 int deprecate = 0;
4482
4483 if (!(ifp->flags&IFA_F_DEPRECATED)) {
4484 deprecate = 1;
4485 ifp->flags |= IFA_F_DEPRECATED;
4486 }
4487
Yasushi Asanofad8da32013-12-31 12:04:19 +09004488 if ((ifp->valid_lft != INFINITY_LIFE_TIME) &&
4489 (time_before(ifp->tstamp + ifp->valid_lft * HZ, next)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004490 next = ifp->tstamp + ifp->valid_lft * HZ;
4491
4492 spin_unlock(&ifp->lock);
4493
4494 if (deprecate) {
4495 in6_ifa_hold(ifp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004496
4497 ipv6_ifa_notify(0, ifp);
4498 in6_ifa_put(ifp);
4499 goto restart;
4500 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004501 } else if ((ifp->flags&IFA_F_TEMPORARY) &&
4502 !(ifp->flags&IFA_F_TENTATIVE)) {
stephen hemminger88949cf2010-03-17 20:31:17 +00004503 unsigned long regen_advance = ifp->idev->cnf.regen_max_retry *
4504 ifp->idev->cnf.dad_transmits *
Hangbin Liu19e16d22020-04-01 14:46:20 +08004505 max(NEIGH_VAR(ifp->idev->nd_parms, RETRANS_TIME), HZ/100) / HZ;
stephen hemminger88949cf2010-03-17 20:31:17 +00004506
Linus Torvalds1da177e2005-04-16 15:20:36 -07004507 if (age >= ifp->prefered_lft - regen_advance) {
4508 struct inet6_ifaddr *ifpub = ifp->ifpub;
4509 if (time_before(ifp->tstamp + ifp->prefered_lft * HZ, next))
4510 next = ifp->tstamp + ifp->prefered_lft * HZ;
4511 if (!ifp->regen_count && ifpub) {
4512 ifp->regen_count++;
4513 in6_ifa_hold(ifp);
4514 in6_ifa_hold(ifpub);
4515 spin_unlock(&ifp->lock);
stephen hemminger5c578aed2010-03-17 20:31:11 +00004516
Hiroyuki YAMAMORI291d8092005-12-23 11:24:05 -08004517 spin_lock(&ifpub->lock);
4518 ifpub->regen_count = 0;
4519 spin_unlock(&ifpub->lock);
Eric Dumazete64e4692018-01-26 16:10:43 -08004520 rcu_read_unlock_bh();
Fernando Gont969c5462020-05-01 00:51:47 -03004521 ipv6_create_tempaddr(ifpub, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004522 in6_ifa_put(ifpub);
4523 in6_ifa_put(ifp);
Eric Dumazete64e4692018-01-26 16:10:43 -08004524 rcu_read_lock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004525 goto restart;
4526 }
4527 } else if (time_before(ifp->tstamp + ifp->prefered_lft * HZ - regen_advance * HZ, next))
4528 next = ifp->tstamp + ifp->prefered_lft * HZ - regen_advance * HZ;
4529 spin_unlock(&ifp->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004530 } else {
4531 /* ifp->prefered_lft <= ifp->valid_lft */
4532 if (time_before(ifp->tstamp + ifp->prefered_lft * HZ, next))
4533 next = ifp->tstamp + ifp->prefered_lft * HZ;
4534 spin_unlock(&ifp->lock);
4535 }
4536 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004537 }
4538
YOSHIFUJI Hideakib2db7562010-03-20 16:11:12 -07004539 next_sec = round_jiffies_up(next);
4540 next_sched = next;
4541
4542 /* If rounded timeout is accurate enough, accept it. */
4543 if (time_before(next_sec, next + ADDRCONF_TIMER_FUZZ))
4544 next_sched = next_sec;
4545
4546 /* And minimum interval is ADDRCONF_TIMER_FUZZ_MAX. */
4547 if (time_before(next_sched, jiffies + ADDRCONF_TIMER_FUZZ_MAX))
4548 next_sched = jiffies + ADDRCONF_TIMER_FUZZ_MAX;
4549
Joe Perchese32ac252018-03-26 08:35:01 -07004550 pr_debug("now = %lu, schedule = %lu, rounded schedule = %lu => %lu\n",
4551 now, next, next_sec, next_sched);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004552 mod_delayed_work(addrconf_wq, &addr_chk_work, next_sched - now);
stephen hemminger5c578aed2010-03-17 20:31:11 +00004553 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004554}
4555
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004556static void addrconf_verify_work(struct work_struct *w)
4557{
4558 rtnl_lock();
4559 addrconf_verify_rtnl();
4560 rtnl_unlock();
4561}
4562
4563static void addrconf_verify(void)
4564{
4565 mod_delayed_work(addrconf_wq, &addr_chk_work, 0);
4566}
4567
Nicolas Dichtelcaeaba72013-05-16 22:32:00 +00004568static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local,
4569 struct in6_addr **peer_pfx)
Thomas Graf461d8832006-09-18 00:09:49 -07004570{
4571 struct in6_addr *pfx = NULL;
4572
Nicolas Dichtelcaeaba72013-05-16 22:32:00 +00004573 *peer_pfx = NULL;
4574
Thomas Graf461d8832006-09-18 00:09:49 -07004575 if (addr)
4576 pfx = nla_data(addr);
4577
4578 if (local) {
4579 if (pfx && nla_memcmp(local, pfx, sizeof(*pfx)))
Nicolas Dichtelcaeaba72013-05-16 22:32:00 +00004580 *peer_pfx = pfx;
4581 pfx = nla_data(local);
Thomas Graf461d8832006-09-18 00:09:49 -07004582 }
4583
4584 return pfx;
4585}
4586
Patrick McHardyef7c79e2007-06-05 12:38:30 -07004587static const struct nla_policy ifa_ipv6_policy[IFA_MAX+1] = {
Thomas Graf461d8832006-09-18 00:09:49 -07004588 [IFA_ADDRESS] = { .len = sizeof(struct in6_addr) },
4589 [IFA_LOCAL] = { .len = sizeof(struct in6_addr) },
4590 [IFA_CACHEINFO] = { .len = sizeof(struct ifa_cacheinfo) },
Jiri Pirko479840f2013-12-06 09:45:21 +01004591 [IFA_FLAGS] = { .len = sizeof(u32) },
David Ahern8308f3f2018-05-27 08:09:58 -07004592 [IFA_RT_PRIORITY] = { .len = sizeof(u32) },
Christian Brauner6ecf4c32018-09-04 21:53:50 +02004593 [IFA_TARGET_NETNSID] = { .type = NLA_S32 },
Thomas Graf461d8832006-09-18 00:09:49 -07004594};
4595
Linus Torvalds1da177e2005-04-16 15:20:36 -07004596static int
David Ahernc21ef3e2017-04-16 09:48:24 -07004597inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh,
4598 struct netlink_ext_ack *extack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004599{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09004600 struct net *net = sock_net(skb->sk);
Thomas Grafb933f712006-09-18 00:10:19 -07004601 struct ifaddrmsg *ifm;
4602 struct nlattr *tb[IFA_MAX+1];
Nicolas Dichtelcaeaba72013-05-16 22:32:00 +00004603 struct in6_addr *pfx, *peer_pfx;
Heiner Kallweit6046d5b2014-04-20 21:29:36 +02004604 u32 ifa_flags;
Thomas Grafb933f712006-09-18 00:10:19 -07004605 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004606
Johannes Berg8cb08172019-04-26 14:07:28 +02004607 err = nlmsg_parse_deprecated(nlh, sizeof(*ifm), tb, IFA_MAX,
4608 ifa_ipv6_policy, extack);
Thomas Grafb933f712006-09-18 00:10:19 -07004609 if (err < 0)
4610 return err;
4611
4612 ifm = nlmsg_data(nlh);
Nicolas Dichtelcaeaba72013-05-16 22:32:00 +00004613 pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL], &peer_pfx);
Ian Morris63159f22015-03-29 14:00:04 +01004614 if (!pfx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004615 return -EINVAL;
4616
Heiner Kallweit6046d5b2014-04-20 21:29:36 +02004617 ifa_flags = tb[IFA_FLAGS] ? nla_get_u32(tb[IFA_FLAGS]) : ifm->ifa_flags;
4618
4619 /* We ignore other flags so far. */
4620 ifa_flags &= IFA_F_MANAGETEMPADDR;
4621
4622 return inet6_addr_del(net, ifm->ifa_index, ifa_flags, pfx,
4623 ifm->ifa_prefixlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004624}
4625
David Ahern8308f3f2018-05-27 08:09:58 -07004626static int modify_prefix_route(struct inet6_ifaddr *ifp,
Hangbin Liu61794012020-03-03 14:37:34 +08004627 unsigned long expires, u32 flags,
4628 bool modify_peer)
David Ahern8308f3f2018-05-27 08:09:58 -07004629{
4630 struct fib6_info *f6i;
David Aherne7c7faa2018-06-28 13:36:55 -07004631 u32 prio;
David Ahern8308f3f2018-05-27 08:09:58 -07004632
Hangbin Liu61794012020-03-03 14:37:34 +08004633 f6i = addrconf_get_prefix_route(modify_peer ? &ifp->peer_addr : &ifp->addr,
4634 ifp->prefix_len,
David Ahern2b2450c2019-03-27 20:53:52 -07004635 ifp->idev->dev, 0, RTF_DEFAULT, true);
David Ahern8308f3f2018-05-27 08:09:58 -07004636 if (!f6i)
4637 return -ENOENT;
4638
David Aherne7c7faa2018-06-28 13:36:55 -07004639 prio = ifp->rt_priority ? : IP6_RT_PRIO_ADDRCONF;
4640 if (f6i->fib6_metric != prio) {
4641 /* delete old one */
Roopa Prabhu11dd74b2020-04-27 13:56:45 -07004642 ip6_del_rt(dev_net(ifp->idev->dev), f6i, false);
David Aherne7c7faa2018-06-28 13:36:55 -07004643
David Ahern8308f3f2018-05-27 08:09:58 -07004644 /* add new one */
Hangbin Liu61794012020-03-03 14:37:34 +08004645 addrconf_prefix_route(modify_peer ? &ifp->peer_addr : &ifp->addr,
4646 ifp->prefix_len,
David Ahern8308f3f2018-05-27 08:09:58 -07004647 ifp->rt_priority, ifp->idev->dev,
4648 expires, flags, GFP_KERNEL);
David Ahern8308f3f2018-05-27 08:09:58 -07004649 } else {
4650 if (!expires)
4651 fib6_clean_expires(f6i);
4652 else
4653 fib6_set_expires(f6i, expires);
4654
4655 fib6_info_release(f6i);
4656 }
4657
4658 return 0;
4659}
4660
David Ahernd169a1f2018-05-27 08:09:55 -07004661static int inet6_addr_modify(struct inet6_ifaddr *ifp, struct ifa6_config *cfg)
Noriaki TAKAMIYA081bba52006-07-28 18:12:13 +09004662{
YOSHIFUJI Hideaki6f704992008-05-19 16:56:11 -07004663 u32 flags;
4664 clock_t expires;
YOSHIFUJI Hideaki4bed72e2008-05-27 17:37:49 +09004665 unsigned long timeout;
Jiri Pirko53bd6742013-12-06 09:45:22 +01004666 bool was_managetempaddr;
Thomas Haller5b84efe2014-01-15 15:36:59 +01004667 bool had_prefixroute;
Hangbin Liud0098e42020-03-03 14:37:35 +08004668 bool new_peer = false;
YOSHIFUJI Hideaki46d48042007-02-07 20:36:26 +09004669
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004670 ASSERT_RTNL();
4671
David Ahernd169a1f2018-05-27 08:09:55 -07004672 if (!cfg->valid_lft || cfg->preferred_lft > cfg->valid_lft)
Noriaki TAKAMIYA081bba52006-07-28 18:12:13 +09004673 return -EINVAL;
4674
David Ahernd169a1f2018-05-27 08:09:55 -07004675 if (cfg->ifa_flags & IFA_F_MANAGETEMPADDR &&
Jiri Pirko53bd6742013-12-06 09:45:22 +01004676 (ifp->flags & IFA_F_TEMPORARY || ifp->prefix_len != 64))
4677 return -EINVAL;
4678
Sabrina Dubrocaf1c02cf2018-02-28 16:40:08 +01004679 if (!(ifp->flags & IFA_F_TENTATIVE) || ifp->flags & IFA_F_DADFAILED)
David Ahernd169a1f2018-05-27 08:09:55 -07004680 cfg->ifa_flags &= ~IFA_F_OPTIMISTIC;
Sabrina Dubrocaf1c02cf2018-02-28 16:40:08 +01004681
David Ahernd169a1f2018-05-27 08:09:55 -07004682 timeout = addrconf_timeout_fixup(cfg->valid_lft, HZ);
YOSHIFUJI Hideaki4bed72e2008-05-27 17:37:49 +09004683 if (addrconf_finite_timeout(timeout)) {
4684 expires = jiffies_to_clock_t(timeout * HZ);
David Ahernd169a1f2018-05-27 08:09:55 -07004685 cfg->valid_lft = timeout;
YOSHIFUJI Hideaki6f704992008-05-19 16:56:11 -07004686 flags = RTF_EXPIRES;
YOSHIFUJI Hideaki4bed72e2008-05-27 17:37:49 +09004687 } else {
4688 expires = 0;
4689 flags = 0;
David Ahernd169a1f2018-05-27 08:09:55 -07004690 cfg->ifa_flags |= IFA_F_PERMANENT;
YOSHIFUJI Hideaki6f704992008-05-19 16:56:11 -07004691 }
Noriaki TAKAMIYA081bba52006-07-28 18:12:13 +09004692
David Ahernd169a1f2018-05-27 08:09:55 -07004693 timeout = addrconf_timeout_fixup(cfg->preferred_lft, HZ);
YOSHIFUJI Hideaki4bed72e2008-05-27 17:37:49 +09004694 if (addrconf_finite_timeout(timeout)) {
4695 if (timeout == 0)
David Ahernd169a1f2018-05-27 08:09:55 -07004696 cfg->ifa_flags |= IFA_F_DEPRECATED;
4697 cfg->preferred_lft = timeout;
YOSHIFUJI Hideaki4bed72e2008-05-27 17:37:49 +09004698 }
Noriaki TAKAMIYA081bba52006-07-28 18:12:13 +09004699
Hangbin Liud0098e42020-03-03 14:37:35 +08004700 if (cfg->peer_pfx &&
4701 memcmp(&ifp->peer_addr, cfg->peer_pfx, sizeof(struct in6_addr))) {
4702 if (!ipv6_addr_any(&ifp->peer_addr))
4703 cleanup_prefix_route(ifp, expires, true, true);
4704 new_peer = true;
4705 }
4706
Noriaki TAKAMIYA081bba52006-07-28 18:12:13 +09004707 spin_lock_bh(&ifp->lock);
Jiri Pirko53bd6742013-12-06 09:45:22 +01004708 was_managetempaddr = ifp->flags & IFA_F_MANAGETEMPADDR;
Thomas Haller5b84efe2014-01-15 15:36:59 +01004709 had_prefixroute = ifp->flags & IFA_F_PERMANENT &&
4710 !(ifp->flags & IFA_F_NOPREFIXROUTE);
Jiri Pirko53bd6742013-12-06 09:45:22 +01004711 ifp->flags &= ~(IFA_F_DEPRECATED | IFA_F_PERMANENT | IFA_F_NODAD |
Thomas Haller761aac72014-01-15 15:36:58 +01004712 IFA_F_HOMEADDRESS | IFA_F_MANAGETEMPADDR |
4713 IFA_F_NOPREFIXROUTE);
David Ahernd169a1f2018-05-27 08:09:55 -07004714 ifp->flags |= cfg->ifa_flags;
Noriaki TAKAMIYA081bba52006-07-28 18:12:13 +09004715 ifp->tstamp = jiffies;
David Ahernd169a1f2018-05-27 08:09:55 -07004716 ifp->valid_lft = cfg->valid_lft;
4717 ifp->prefered_lft = cfg->preferred_lft;
Noriaki TAKAMIYA081bba52006-07-28 18:12:13 +09004718
David Ahern8308f3f2018-05-27 08:09:58 -07004719 if (cfg->rt_priority && cfg->rt_priority != ifp->rt_priority)
4720 ifp->rt_priority = cfg->rt_priority;
Noriaki TAKAMIYA081bba52006-07-28 18:12:13 +09004721
Hangbin Liud0098e42020-03-03 14:37:35 +08004722 if (new_peer)
4723 ifp->peer_addr = *cfg->peer_pfx;
4724
Noriaki TAKAMIYA081bba52006-07-28 18:12:13 +09004725 spin_unlock_bh(&ifp->lock);
4726 if (!(ifp->flags&IFA_F_TENTATIVE))
4727 ipv6_ifa_notify(0, ifp);
Noriaki TAKAMIYA081bba52006-07-28 18:12:13 +09004728
David Ahernd169a1f2018-05-27 08:09:55 -07004729 if (!(cfg->ifa_flags & IFA_F_NOPREFIXROUTE)) {
David Ahern8308f3f2018-05-27 08:09:58 -07004730 int rc = -ENOENT;
4731
4732 if (had_prefixroute)
Hangbin Liu61794012020-03-03 14:37:34 +08004733 rc = modify_prefix_route(ifp, expires, flags, false);
David Ahern8308f3f2018-05-27 08:09:58 -07004734
4735 /* prefix route could have been deleted; if so restore it */
4736 if (rc == -ENOENT) {
4737 addrconf_prefix_route(&ifp->addr, ifp->prefix_len,
4738 ifp->rt_priority, ifp->idev->dev,
4739 expires, flags, GFP_KERNEL);
4740 }
Hangbin Liu61794012020-03-03 14:37:34 +08004741
4742 if (had_prefixroute && !ipv6_addr_any(&ifp->peer_addr))
4743 rc = modify_prefix_route(ifp, expires, flags, true);
4744
4745 if (rc == -ENOENT && !ipv6_addr_any(&ifp->peer_addr)) {
4746 addrconf_prefix_route(&ifp->peer_addr, ifp->prefix_len,
4747 ifp->rt_priority, ifp->idev->dev,
4748 expires, flags, GFP_KERNEL);
4749 }
Thomas Haller5b84efe2014-01-15 15:36:59 +01004750 } else if (had_prefixroute) {
4751 enum cleanup_prefix_rt_t action;
4752 unsigned long rt_expires;
4753
4754 write_lock_bh(&ifp->idev->lock);
4755 action = check_cleanup_prefix_route(ifp, &rt_expires);
4756 write_unlock_bh(&ifp->idev->lock);
4757
4758 if (action != CLEANUP_PREFIX_RT_NOP) {
4759 cleanup_prefix_route(ifp, rt_expires,
Hangbin Liud0098e42020-03-03 14:37:35 +08004760 action == CLEANUP_PREFIX_RT_DEL, false);
Thomas Haller5b84efe2014-01-15 15:36:59 +01004761 }
Thomas Haller761aac72014-01-15 15:36:58 +01004762 }
Jiri Pirko53bd6742013-12-06 09:45:22 +01004763
4764 if (was_managetempaddr || ifp->flags & IFA_F_MANAGETEMPADDR) {
David Ahernd169a1f2018-05-27 08:09:55 -07004765 if (was_managetempaddr &&
4766 !(ifp->flags & IFA_F_MANAGETEMPADDR)) {
4767 cfg->valid_lft = 0;
4768 cfg->preferred_lft = 0;
4769 }
4770 manage_tempaddrs(ifp->idev, ifp, cfg->valid_lft,
4771 cfg->preferred_lft, !was_managetempaddr,
4772 jiffies);
Jiri Pirko53bd6742013-12-06 09:45:22 +01004773 }
4774
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01004775 addrconf_verify_rtnl();
Noriaki TAKAMIYA081bba52006-07-28 18:12:13 +09004776
4777 return 0;
4778}
4779
4780static int
David Ahernc21ef3e2017-04-16 09:48:24 -07004781inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
4782 struct netlink_ext_ack *extack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004783{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09004784 struct net *net = sock_net(skb->sk);
Thomas Graf461d8832006-09-18 00:09:49 -07004785 struct ifaddrmsg *ifm;
4786 struct nlattr *tb[IFA_MAX+1];
David Ahern19b15182018-05-27 08:09:54 -07004787 struct in6_addr *peer_pfx;
Thomas Graf7198f8c2006-09-18 00:13:46 -07004788 struct inet6_ifaddr *ifa;
4789 struct net_device *dev;
Sabrina Dubrocaf1c02cf2018-02-28 16:40:08 +01004790 struct inet6_dev *idev;
David Ahern19b15182018-05-27 08:09:54 -07004791 struct ifa6_config cfg;
Thomas Graf461d8832006-09-18 00:09:49 -07004792 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004793
Johannes Berg8cb08172019-04-26 14:07:28 +02004794 err = nlmsg_parse_deprecated(nlh, sizeof(*ifm), tb, IFA_MAX,
4795 ifa_ipv6_policy, extack);
Thomas Graf461d8832006-09-18 00:09:49 -07004796 if (err < 0)
4797 return err;
4798
David Ahern19b15182018-05-27 08:09:54 -07004799 memset(&cfg, 0, sizeof(cfg));
4800
Thomas Graf461d8832006-09-18 00:09:49 -07004801 ifm = nlmsg_data(nlh);
David Ahern19b15182018-05-27 08:09:54 -07004802 cfg.pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL], &peer_pfx);
4803 if (!cfg.pfx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004804 return -EINVAL;
4805
David Ahern19b15182018-05-27 08:09:54 -07004806 cfg.peer_pfx = peer_pfx;
4807 cfg.plen = ifm->ifa_prefixlen;
David Ahern8308f3f2018-05-27 08:09:58 -07004808 if (tb[IFA_RT_PRIORITY])
4809 cfg.rt_priority = nla_get_u32(tb[IFA_RT_PRIORITY]);
4810
David Ahern19b15182018-05-27 08:09:54 -07004811 cfg.valid_lft = INFINITY_LIFE_TIME;
4812 cfg.preferred_lft = INFINITY_LIFE_TIME;
4813
Thomas Graf461d8832006-09-18 00:09:49 -07004814 if (tb[IFA_CACHEINFO]) {
Noriaki TAKAMIYA07787692006-07-28 18:12:10 +09004815 struct ifa_cacheinfo *ci;
Thomas Graf461d8832006-09-18 00:09:49 -07004816
4817 ci = nla_data(tb[IFA_CACHEINFO]);
David Ahern19b15182018-05-27 08:09:54 -07004818 cfg.valid_lft = ci->ifa_valid;
4819 cfg.preferred_lft = ci->ifa_prefered;
Noriaki TAKAMIYA07787692006-07-28 18:12:10 +09004820 }
4821
Daniel Lezcanoaf284932008-03-05 10:46:57 -08004822 dev = __dev_get_by_index(net, ifm->ifa_index);
Ian Morris63159f22015-03-29 14:00:04 +01004823 if (!dev)
Thomas Graf7198f8c2006-09-18 00:13:46 -07004824 return -ENODEV;
4825
David Ahern19b15182018-05-27 08:09:54 -07004826 if (tb[IFA_FLAGS])
4827 cfg.ifa_flags = nla_get_u32(tb[IFA_FLAGS]);
4828 else
4829 cfg.ifa_flags = ifm->ifa_flags;
Jiri Pirko479840f2013-12-06 09:45:21 +01004830
Noriaki TAKAMIYA55ebaef2006-09-22 14:45:27 -07004831 /* We ignore other flags so far. */
David Ahern19b15182018-05-27 08:09:54 -07004832 cfg.ifa_flags &= IFA_F_NODAD | IFA_F_HOMEADDRESS |
4833 IFA_F_MANAGETEMPADDR | IFA_F_NOPREFIXROUTE |
4834 IFA_F_MCAUTOJOIN | IFA_F_OPTIMISTIC;
Sabrina Dubrocaf1c02cf2018-02-28 16:40:08 +01004835
4836 idev = ipv6_find_idev(dev);
Sabrina Dubrocadb0b99f2019-08-23 15:44:36 +02004837 if (IS_ERR(idev))
4838 return PTR_ERR(idev);
Sabrina Dubrocaf1c02cf2018-02-28 16:40:08 +01004839
4840 if (!ipv6_allow_optimistic_dad(net, idev))
David Ahern19b15182018-05-27 08:09:54 -07004841 cfg.ifa_flags &= ~IFA_F_OPTIMISTIC;
Sabrina Dubrocaf1c02cf2018-02-28 16:40:08 +01004842
David Ahern19b15182018-05-27 08:09:54 -07004843 if (cfg.ifa_flags & IFA_F_NODAD &&
4844 cfg.ifa_flags & IFA_F_OPTIMISTIC) {
Sabrina Dubrocaf1c02cf2018-02-28 16:40:08 +01004845 NL_SET_ERR_MSG(extack, "IFA_F_NODAD and IFA_F_OPTIMISTIC are mutually exclusive");
4846 return -EINVAL;
4847 }
Noriaki TAKAMIYA55ebaef2006-09-22 14:45:27 -07004848
David Ahern19b15182018-05-27 08:09:54 -07004849 ifa = ipv6_get_ifaddr(net, cfg.pfx, dev, 1);
Ian Morris63159f22015-03-29 14:00:04 +01004850 if (!ifa) {
Thomas Graf7198f8c2006-09-18 00:13:46 -07004851 /*
4852 * It would be best to check for !NLM_F_CREATE here but
stephen hemmingerdb9c7c32014-01-12 11:26:32 -08004853 * userspace already relies on not having to provide this.
Thomas Graf7198f8c2006-09-18 00:13:46 -07004854 */
David Ahern19b15182018-05-27 08:09:54 -07004855 return inet6_addr_add(net, ifm->ifa_index, &cfg, extack);
Noriaki TAKAMIYA081bba52006-07-28 18:12:13 +09004856 }
4857
Thomas Graf7198f8c2006-09-18 00:13:46 -07004858 if (nlh->nlmsg_flags & NLM_F_EXCL ||
4859 !(nlh->nlmsg_flags & NLM_F_REPLACE))
4860 err = -EEXIST;
4861 else
David Ahernd169a1f2018-05-27 08:09:55 -07004862 err = inet6_addr_modify(ifa, &cfg);
Thomas Graf7198f8c2006-09-18 00:13:46 -07004863
4864 in6_ifa_put(ifa);
4865
4866 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004867}
4868
Jiri Pirko479840f2013-12-06 09:45:21 +01004869static void put_ifaddrmsg(struct nlmsghdr *nlh, u8 prefixlen, u32 flags,
Thomas Graf101bb222006-09-18 00:11:52 -07004870 u8 scope, int ifindex)
4871{
4872 struct ifaddrmsg *ifm;
4873
4874 ifm = nlmsg_data(nlh);
4875 ifm->ifa_family = AF_INET6;
4876 ifm->ifa_prefixlen = prefixlen;
4877 ifm->ifa_flags = flags;
4878 ifm->ifa_scope = scope;
4879 ifm->ifa_index = ifindex;
4880}
4881
Thomas Graf85486af2006-09-18 00:11:24 -07004882static int put_cacheinfo(struct sk_buff *skb, unsigned long cstamp,
4883 unsigned long tstamp, u32 preferred, u32 valid)
4884{
4885 struct ifa_cacheinfo ci;
4886
Thomas Graf18a31e12010-11-17 04:12:02 +00004887 ci.cstamp = cstamp_delta(cstamp);
4888 ci.tstamp = cstamp_delta(tstamp);
Thomas Graf85486af2006-09-18 00:11:24 -07004889 ci.ifa_prefered = preferred;
4890 ci.ifa_valid = valid;
4891
4892 return nla_put(skb, IFA_CACHEINFO, sizeof(ci), &ci);
4893}
4894
Thomas Graf101bb222006-09-18 00:11:52 -07004895static inline int rt_scope(int ifa_scope)
4896{
4897 if (ifa_scope & IFA_HOST)
4898 return RT_SCOPE_HOST;
4899 else if (ifa_scope & IFA_LINK)
4900 return RT_SCOPE_LINK;
4901 else if (ifa_scope & IFA_SITE)
4902 return RT_SCOPE_SITE;
4903 else
4904 return RT_SCOPE_UNIVERSE;
4905}
4906
Thomas Graf0ab68032006-09-18 00:12:35 -07004907static inline int inet6_ifaddr_msgsize(void)
4908{
Thomas Graf339bf982006-11-10 14:10:15 -08004909 return NLMSG_ALIGN(sizeof(struct ifaddrmsg))
Nicolas Dichtelcaeaba72013-05-16 22:32:00 +00004910 + nla_total_size(16) /* IFA_LOCAL */
Thomas Graf339bf982006-11-10 14:10:15 -08004911 + nla_total_size(16) /* IFA_ADDRESS */
Jiri Pirko479840f2013-12-06 09:45:21 +01004912 + nla_total_size(sizeof(struct ifa_cacheinfo))
David Ahern8308f3f2018-05-27 08:09:58 -07004913 + nla_total_size(4) /* IFA_FLAGS */
4914 + nla_total_size(4) /* IFA_RT_PRIORITY */;
Thomas Graf0ab68032006-09-18 00:12:35 -07004915}
YOSHIFUJI Hideakic5396a32006-06-17 22:48:48 -07004916
David Ahern6ba1e6e2018-10-07 20:16:26 -07004917enum addr_type_t {
4918 UNICAST_ADDR,
4919 MULTICAST_ADDR,
4920 ANYCAST_ADDR,
4921};
4922
Christian Brauner203651b2018-09-04 21:53:55 +02004923struct inet6_fill_args {
4924 u32 portid;
4925 u32 seq;
4926 int event;
4927 unsigned int flags;
4928 int netnsid;
David Ahern6371a712018-10-19 12:45:30 -07004929 int ifindex;
David Ahern6ba1e6e2018-10-07 20:16:26 -07004930 enum addr_type_t type;
Christian Brauner203651b2018-09-04 21:53:55 +02004931};
4932
Linus Torvalds1da177e2005-04-16 15:20:36 -07004933static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
Christian Brauner203651b2018-09-04 21:53:55 +02004934 struct inet6_fill_args *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004935{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004936 struct nlmsghdr *nlh;
Thomas Graf85486af2006-09-18 00:11:24 -07004937 u32 preferred, valid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004938
Christian Brauner203651b2018-09-04 21:53:55 +02004939 nlh = nlmsg_put(skb, args->portid, args->seq, args->event,
4940 sizeof(struct ifaddrmsg), args->flags);
Ian Morris63159f22015-03-29 14:00:04 +01004941 if (!nlh)
Patrick McHardy26932562007-01-31 23:16:40 -08004942 return -EMSGSIZE;
Thomas Graf0ab68032006-09-18 00:12:35 -07004943
Thomas Graf101bb222006-09-18 00:11:52 -07004944 put_ifaddrmsg(nlh, ifa->prefix_len, ifa->flags, rt_scope(ifa->scope),
4945 ifa->idev->dev->ifindex);
4946
Christian Brauner203651b2018-09-04 21:53:55 +02004947 if (args->netnsid >= 0 &&
4948 nla_put_s32(skb, IFA_TARGET_NETNSID, args->netnsid))
Christian Brauner6ecf4c32018-09-04 21:53:50 +02004949 goto error;
4950
Yasushi Asanofad8da32013-12-31 12:04:19 +09004951 if (!((ifa->flags&IFA_F_PERMANENT) &&
4952 (ifa->prefered_lft == INFINITY_LIFE_TIME))) {
Thomas Graf85486af2006-09-18 00:11:24 -07004953 preferred = ifa->prefered_lft;
4954 valid = ifa->valid_lft;
4955 if (preferred != INFINITY_LIFE_TIME) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004956 long tval = (jiffies - ifa->tstamp)/HZ;
Jens Rosenbooma1faa692009-06-25 04:55:50 +00004957 if (preferred > tval)
4958 preferred -= tval;
4959 else
4960 preferred = 0;
Ben Hutchingsf56619f2010-06-26 11:37:47 +00004961 if (valid != INFINITY_LIFE_TIME) {
4962 if (valid > tval)
4963 valid -= tval;
4964 else
4965 valid = 0;
4966 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004967 }
4968 } else {
Thomas Graf85486af2006-09-18 00:11:24 -07004969 preferred = INFINITY_LIFE_TIME;
4970 valid = INFINITY_LIFE_TIME;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004971 }
Thomas Graf85486af2006-09-18 00:11:24 -07004972
Cong Wang7996c792013-05-22 05:41:06 +00004973 if (!ipv6_addr_any(&ifa->peer_addr)) {
Jiri Benc930345e2015-03-29 16:59:25 +02004974 if (nla_put_in6_addr(skb, IFA_LOCAL, &ifa->addr) < 0 ||
4975 nla_put_in6_addr(skb, IFA_ADDRESS, &ifa->peer_addr) < 0)
Nicolas Dichtelcaeaba72013-05-16 22:32:00 +00004976 goto error;
4977 } else
Jiri Benc930345e2015-03-29 16:59:25 +02004978 if (nla_put_in6_addr(skb, IFA_ADDRESS, &ifa->addr) < 0)
Nicolas Dichtelcaeaba72013-05-16 22:32:00 +00004979 goto error;
4980
David Ahern8308f3f2018-05-27 08:09:58 -07004981 if (ifa->rt_priority &&
4982 nla_put_u32(skb, IFA_RT_PRIORITY, ifa->rt_priority))
4983 goto error;
4984
Nicolas Dichtelcaeaba72013-05-16 22:32:00 +00004985 if (put_cacheinfo(skb, ifa->cstamp, ifa->tstamp, preferred, valid) < 0)
4986 goto error;
Thomas Graf85486af2006-09-18 00:11:24 -07004987
Jiri Pirko479840f2013-12-06 09:45:21 +01004988 if (nla_put_u32(skb, IFA_FLAGS, ifa->flags) < 0)
4989 goto error;
4990
Johannes Berg053c0952015-01-16 22:09:00 +01004991 nlmsg_end(skb, nlh);
4992 return 0;
Nicolas Dichtelcaeaba72013-05-16 22:32:00 +00004993
4994error:
4995 nlmsg_cancel(skb, nlh);
4996 return -EMSGSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004997}
4998
4999static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca,
Christian Brauner203651b2018-09-04 21:53:55 +02005000 struct inet6_fill_args *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005001{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005002 struct nlmsghdr *nlh;
Thomas Graf101bb222006-09-18 00:11:52 -07005003 u8 scope = RT_SCOPE_UNIVERSE;
5004 int ifindex = ifmca->idev->dev->ifindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005005
Thomas Graf101bb222006-09-18 00:11:52 -07005006 if (ipv6_addr_scope(&ifmca->mca_addr) & IFA_SITE)
5007 scope = RT_SCOPE_SITE;
5008
Christian Brauner203651b2018-09-04 21:53:55 +02005009 nlh = nlmsg_put(skb, args->portid, args->seq, args->event,
5010 sizeof(struct ifaddrmsg), args->flags);
Ian Morris63159f22015-03-29 14:00:04 +01005011 if (!nlh)
Patrick McHardy26932562007-01-31 23:16:40 -08005012 return -EMSGSIZE;
Thomas Graf0ab68032006-09-18 00:12:35 -07005013
Christian Brauner203651b2018-09-04 21:53:55 +02005014 if (args->netnsid >= 0 &&
5015 nla_put_s32(skb, IFA_TARGET_NETNSID, args->netnsid))
Christian Brauner6ecf4c32018-09-04 21:53:50 +02005016 return -EMSGSIZE;
5017
Thomas Graf101bb222006-09-18 00:11:52 -07005018 put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex);
Jiri Benc930345e2015-03-29 16:59:25 +02005019 if (nla_put_in6_addr(skb, IFA_MULTICAST, &ifmca->mca_addr) < 0 ||
Thomas Graf0ab68032006-09-18 00:12:35 -07005020 put_cacheinfo(skb, ifmca->mca_cstamp, ifmca->mca_tstamp,
Patrick McHardy26932562007-01-31 23:16:40 -08005021 INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0) {
5022 nlmsg_cancel(skb, nlh);
5023 return -EMSGSIZE;
5024 }
Thomas Graf85486af2006-09-18 00:11:24 -07005025
Johannes Berg053c0952015-01-16 22:09:00 +01005026 nlmsg_end(skb, nlh);
5027 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005028}
5029
5030static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca,
Christian Brauner203651b2018-09-04 21:53:55 +02005031 struct inet6_fill_args *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005032{
David Ahern9ee8cbb2018-04-18 15:39:01 -07005033 struct net_device *dev = fib6_info_nh_dev(ifaca->aca_rt);
5034 int ifindex = dev ? dev->ifindex : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005035 struct nlmsghdr *nlh;
Thomas Graf101bb222006-09-18 00:11:52 -07005036 u8 scope = RT_SCOPE_UNIVERSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005037
Thomas Graf101bb222006-09-18 00:11:52 -07005038 if (ipv6_addr_scope(&ifaca->aca_addr) & IFA_SITE)
5039 scope = RT_SCOPE_SITE;
5040
Christian Brauner203651b2018-09-04 21:53:55 +02005041 nlh = nlmsg_put(skb, args->portid, args->seq, args->event,
5042 sizeof(struct ifaddrmsg), args->flags);
Ian Morris63159f22015-03-29 14:00:04 +01005043 if (!nlh)
Patrick McHardy26932562007-01-31 23:16:40 -08005044 return -EMSGSIZE;
Thomas Graf0ab68032006-09-18 00:12:35 -07005045
Christian Brauner203651b2018-09-04 21:53:55 +02005046 if (args->netnsid >= 0 &&
5047 nla_put_s32(skb, IFA_TARGET_NETNSID, args->netnsid))
Christian Brauner6ecf4c32018-09-04 21:53:50 +02005048 return -EMSGSIZE;
5049
Thomas Graf101bb222006-09-18 00:11:52 -07005050 put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex);
Jiri Benc930345e2015-03-29 16:59:25 +02005051 if (nla_put_in6_addr(skb, IFA_ANYCAST, &ifaca->aca_addr) < 0 ||
Thomas Graf0ab68032006-09-18 00:12:35 -07005052 put_cacheinfo(skb, ifaca->aca_cstamp, ifaca->aca_tstamp,
Patrick McHardy26932562007-01-31 23:16:40 -08005053 INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0) {
5054 nlmsg_cancel(skb, nlh);
5055 return -EMSGSIZE;
5056 }
Thomas Graf85486af2006-09-18 00:11:24 -07005057
Johannes Berg053c0952015-01-16 22:09:00 +01005058 nlmsg_end(skb, nlh);
5059 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005060}
5061
Eric Dumazet234b27c2009-11-12 04:11:50 +00005062/* called with rcu_read_lock() */
5063static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb,
David Ahernfe884c22018-10-19 12:45:28 -07005064 struct netlink_callback *cb, int s_ip_idx,
David Ahern6ba1e6e2018-10-07 20:16:26 -07005065 struct inet6_fill_args *fillargs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005066{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005067 struct ifmcaddr6 *ifmca;
5068 struct ifacaddr6 *ifaca;
David Ahernfe884c22018-10-19 12:45:28 -07005069 int ip_idx = 0;
Eric Dumazet234b27c2009-11-12 04:11:50 +00005070 int err = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005071
Eric Dumazet234b27c2009-11-12 04:11:50 +00005072 read_lock_bh(&idev->lock);
David Ahern6ba1e6e2018-10-07 20:16:26 -07005073 switch (fillargs->type) {
stephen hemminger502a2ff2010-03-17 20:31:13 +00005074 case UNICAST_ADDR: {
5075 struct inet6_ifaddr *ifa;
David Ahern6ba1e6e2018-10-07 20:16:26 -07005076 fillargs->event = RTM_NEWADDR;
stephen hemminger502a2ff2010-03-17 20:31:13 +00005077
Eric Dumazet234b27c2009-11-12 04:11:50 +00005078 /* unicast address incl. temp addr */
stephen hemminger502a2ff2010-03-17 20:31:13 +00005079 list_for_each_entry(ifa, &idev->addr_list, if_list) {
David Ahern4ba4c562018-10-19 10:00:19 -07005080 if (ip_idx < s_ip_idx)
5081 goto next;
David Ahern6ba1e6e2018-10-07 20:16:26 -07005082 err = inet6_fill_ifaddr(skb, ifa, fillargs);
Johannes Berg053c0952015-01-16 22:09:00 +01005083 if (err < 0)
Eric Dumazet234b27c2009-11-12 04:11:50 +00005084 break;
Nicolas Dichtel63998ac2013-03-22 06:28:43 +00005085 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
David Ahern4ba4c562018-10-19 10:00:19 -07005086next:
5087 ip_idx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005088 }
Eric Dumazet234b27c2009-11-12 04:11:50 +00005089 break;
stephen hemminger502a2ff2010-03-17 20:31:13 +00005090 }
Eric Dumazet234b27c2009-11-12 04:11:50 +00005091 case MULTICAST_ADDR:
David Ahern6ba1e6e2018-10-07 20:16:26 -07005092 fillargs->event = RTM_GETMULTICAST;
Christian Brauner203651b2018-09-04 21:53:55 +02005093
Eric Dumazet234b27c2009-11-12 04:11:50 +00005094 /* multicast address */
5095 for (ifmca = idev->mc_list; ifmca;
5096 ifmca = ifmca->next, ip_idx++) {
5097 if (ip_idx < s_ip_idx)
5098 continue;
David Ahern6ba1e6e2018-10-07 20:16:26 -07005099 err = inet6_fill_ifmcaddr(skb, ifmca, fillargs);
Johannes Berg053c0952015-01-16 22:09:00 +01005100 if (err < 0)
Eric Dumazet234b27c2009-11-12 04:11:50 +00005101 break;
5102 }
5103 break;
5104 case ANYCAST_ADDR:
David Ahern6ba1e6e2018-10-07 20:16:26 -07005105 fillargs->event = RTM_GETANYCAST;
Eric Dumazet234b27c2009-11-12 04:11:50 +00005106 /* anycast address */
5107 for (ifaca = idev->ac_list; ifaca;
5108 ifaca = ifaca->aca_next, ip_idx++) {
5109 if (ip_idx < s_ip_idx)
5110 continue;
David Ahern6ba1e6e2018-10-07 20:16:26 -07005111 err = inet6_fill_ifacaddr(skb, ifaca, fillargs);
Johannes Berg053c0952015-01-16 22:09:00 +01005112 if (err < 0)
Eric Dumazet234b27c2009-11-12 04:11:50 +00005113 break;
5114 }
5115 break;
5116 default:
5117 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005118 }
Eric Dumazet234b27c2009-11-12 04:11:50 +00005119 read_unlock_bh(&idev->lock);
David Ahernfe884c22018-10-19 12:45:28 -07005120 cb->args[2] = ip_idx;
Eric Dumazet234b27c2009-11-12 04:11:50 +00005121 return err;
5122}
5123
David Aherned6eff12018-10-07 20:16:29 -07005124static int inet6_valid_dump_ifaddr_req(const struct nlmsghdr *nlh,
5125 struct inet6_fill_args *fillargs,
5126 struct net **tgt_net, struct sock *sk,
David Ahern6371a712018-10-19 12:45:30 -07005127 struct netlink_callback *cb)
David Aherned6eff12018-10-07 20:16:29 -07005128{
David Ahern6371a712018-10-19 12:45:30 -07005129 struct netlink_ext_ack *extack = cb->extack;
David Aherned6eff12018-10-07 20:16:29 -07005130 struct nlattr *tb[IFA_MAX+1];
5131 struct ifaddrmsg *ifm;
5132 int err, i;
5133
5134 if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ifm))) {
5135 NL_SET_ERR_MSG_MOD(extack, "Invalid header for address dump request");
5136 return -EINVAL;
5137 }
5138
5139 ifm = nlmsg_data(nlh);
5140 if (ifm->ifa_prefixlen || ifm->ifa_flags || ifm->ifa_scope) {
5141 NL_SET_ERR_MSG_MOD(extack, "Invalid values in header for address dump request");
5142 return -EINVAL;
5143 }
David Ahern6371a712018-10-19 12:45:30 -07005144
5145 fillargs->ifindex = ifm->ifa_index;
5146 if (fillargs->ifindex) {
5147 cb->answer_flags |= NLM_F_DUMP_FILTERED;
5148 fillargs->flags |= NLM_F_DUMP_FILTERED;
David Aherned6eff12018-10-07 20:16:29 -07005149 }
5150
Johannes Berg8cb08172019-04-26 14:07:28 +02005151 err = nlmsg_parse_deprecated_strict(nlh, sizeof(*ifm), tb, IFA_MAX,
5152 ifa_ipv6_policy, extack);
David Aherned6eff12018-10-07 20:16:29 -07005153 if (err < 0)
5154 return err;
5155
5156 for (i = 0; i <= IFA_MAX; ++i) {
5157 if (!tb[i])
5158 continue;
5159
5160 if (i == IFA_TARGET_NETNSID) {
5161 struct net *net;
5162
5163 fillargs->netnsid = nla_get_s32(tb[i]);
5164 net = rtnl_get_net_ns_capable(sk, fillargs->netnsid);
5165 if (IS_ERR(net)) {
Bjørn Morkbf4cc402018-10-25 21:18:25 +02005166 fillargs->netnsid = -1;
David Aherned6eff12018-10-07 20:16:29 -07005167 NL_SET_ERR_MSG_MOD(extack, "Invalid target network namespace id");
5168 return PTR_ERR(net);
5169 }
5170 *tgt_net = net;
5171 } else {
5172 NL_SET_ERR_MSG_MOD(extack, "Unsupported attribute in dump request");
5173 return -EINVAL;
5174 }
5175 }
5176
5177 return 0;
5178}
5179
Eric Dumazet234b27c2009-11-12 04:11:50 +00005180static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
5181 enum addr_type_t type)
5182{
David Aherned6eff12018-10-07 20:16:29 -07005183 const struct nlmsghdr *nlh = cb->nlh;
David Ahern6ba1e6e2018-10-07 20:16:26 -07005184 struct inet6_fill_args fillargs = {
5185 .portid = NETLINK_CB(cb->skb).portid,
5186 .seq = cb->nlh->nlmsg_seq,
5187 .flags = NLM_F_MULTI,
5188 .netnsid = -1,
5189 .type = type,
5190 };
Eric Dumazet234b27c2009-11-12 04:11:50 +00005191 struct net *net = sock_net(skb->sk);
Christian Brauner6ecf4c32018-09-04 21:53:50 +02005192 struct net *tgt_net = net;
David Ahernfe884c22018-10-19 12:45:28 -07005193 int idx, s_idx, s_ip_idx;
Eric Dumazet234b27c2009-11-12 04:11:50 +00005194 int h, s_h;
Eric Dumazet234b27c2009-11-12 04:11:50 +00005195 struct net_device *dev;
5196 struct inet6_dev *idev;
5197 struct hlist_head *head;
David Ahern242afaa2018-10-24 12:59:00 -07005198 int err = 0;
Eric Dumazet234b27c2009-11-12 04:11:50 +00005199
5200 s_h = cb->args[0];
5201 s_idx = idx = cb->args[1];
David Ahernfe884c22018-10-19 12:45:28 -07005202 s_ip_idx = cb->args[2];
Eric Dumazet234b27c2009-11-12 04:11:50 +00005203
David Aherned6eff12018-10-07 20:16:29 -07005204 if (cb->strict_check) {
David Aherned6eff12018-10-07 20:16:29 -07005205 err = inet6_valid_dump_ifaddr_req(nlh, &fillargs, &tgt_net,
David Ahern6371a712018-10-19 12:45:30 -07005206 skb->sk, cb);
David Aherned6eff12018-10-07 20:16:29 -07005207 if (err < 0)
David Ahern242afaa2018-10-24 12:59:00 -07005208 goto put_tgt_net;
David Ahern6371a712018-10-19 12:45:30 -07005209
David Ahern242afaa2018-10-24 12:59:00 -07005210 err = 0;
David Ahern6371a712018-10-19 12:45:30 -07005211 if (fillargs.ifindex) {
5212 dev = __dev_get_by_index(tgt_net, fillargs.ifindex);
David Ahern242afaa2018-10-24 12:59:00 -07005213 if (!dev) {
5214 err = -ENODEV;
5215 goto put_tgt_net;
5216 }
David Ahern6371a712018-10-19 12:45:30 -07005217 idev = __in6_dev_get(dev);
5218 if (idev) {
5219 err = in6_dump_addrs(idev, skb, cb, s_ip_idx,
5220 &fillargs);
Jakub Kicinski15180392019-01-22 14:47:19 -08005221 if (err > 0)
5222 err = 0;
David Ahern6371a712018-10-19 12:45:30 -07005223 }
5224 goto put_tgt_net;
5225 }
Christian Brauner6ecf4c32018-09-04 21:53:50 +02005226 }
5227
Eric Dumazet234b27c2009-11-12 04:11:50 +00005228 rcu_read_lock();
Christian Brauner6ecf4c32018-09-04 21:53:50 +02005229 cb->seq = atomic_read(&tgt_net->ipv6.dev_addr_genid) ^ tgt_net->dev_base_seq;
Eric Dumazet234b27c2009-11-12 04:11:50 +00005230 for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
5231 idx = 0;
Christian Brauner6ecf4c32018-09-04 21:53:50 +02005232 head = &tgt_net->dev_index_head[h];
Sasha Levinb67bfe02013-02-27 17:06:00 -08005233 hlist_for_each_entry_rcu(dev, head, index_hlist) {
Eric Dumazet234b27c2009-11-12 04:11:50 +00005234 if (idx < s_idx)
5235 goto cont;
Patrick McHardy4b97efd2010-03-26 20:27:49 -07005236 if (h > s_h || idx > s_idx)
Eric Dumazet234b27c2009-11-12 04:11:50 +00005237 s_ip_idx = 0;
Stephen Hemmingere21e8462010-03-20 16:09:01 -07005238 idev = __in6_dev_get(dev);
5239 if (!idev)
Eric Dumazet234b27c2009-11-12 04:11:50 +00005240 goto cont;
5241
David Ahernfe884c22018-10-19 12:45:28 -07005242 if (in6_dump_addrs(idev, skb, cb, s_ip_idx,
David Ahern6ba1e6e2018-10-07 20:16:26 -07005243 &fillargs) < 0)
Eric Dumazet234b27c2009-11-12 04:11:50 +00005244 goto done;
5245cont:
5246 idx++;
5247 }
5248 }
5249done:
5250 rcu_read_unlock();
5251 cb->args[0] = h;
5252 cb->args[1] = idx;
David Ahern6371a712018-10-19 12:45:30 -07005253put_tgt_net:
David Ahern6ba1e6e2018-10-07 20:16:26 -07005254 if (fillargs.netnsid >= 0)
Christian Brauner6ecf4c32018-09-04 21:53:50 +02005255 put_net(tgt_net);
Eric Dumazet234b27c2009-11-12 04:11:50 +00005256
Arthur Gautier7c1e8a32018-12-31 02:10:58 +00005257 return skb->len ? : err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005258}
5259
5260static int inet6_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
5261{
5262 enum addr_type_t type = UNICAST_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
5267static int inet6_dump_ifmcaddr(struct sk_buff *skb, struct netlink_callback *cb)
5268{
5269 enum addr_type_t type = MULTICAST_ADDR;
Denis V. Lunevb8542722007-12-01 00:21:31 +11005270
Linus Torvalds1da177e2005-04-16 15:20:36 -07005271 return inet6_dump_addr(skb, cb, type);
5272}
5273
5274
5275static int inet6_dump_ifacaddr(struct sk_buff *skb, struct netlink_callback *cb)
5276{
5277 enum addr_type_t type = ANYCAST_ADDR;
Denis V. Lunevb8542722007-12-01 00:21:31 +11005278
Linus Torvalds1da177e2005-04-16 15:20:36 -07005279 return inet6_dump_addr(skb, cb, type);
5280}
5281
Jakub Kicinski4b1373d2019-01-18 10:46:21 -08005282static int inet6_rtm_valid_getaddr_req(struct sk_buff *skb,
5283 const struct nlmsghdr *nlh,
5284 struct nlattr **tb,
5285 struct netlink_ext_ack *extack)
5286{
5287 struct ifaddrmsg *ifm;
5288 int i, err;
5289
5290 if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ifm))) {
5291 NL_SET_ERR_MSG_MOD(extack, "Invalid header for get address request");
5292 return -EINVAL;
5293 }
5294
Hangbin Liu2beb6d22019-12-11 22:20:16 +08005295 if (!netlink_strict_get_check(skb))
5296 return nlmsg_parse_deprecated(nlh, sizeof(*ifm), tb, IFA_MAX,
5297 ifa_ipv6_policy, extack);
5298
Jakub Kicinski4b1373d2019-01-18 10:46:21 -08005299 ifm = nlmsg_data(nlh);
5300 if (ifm->ifa_prefixlen || ifm->ifa_flags || ifm->ifa_scope) {
5301 NL_SET_ERR_MSG_MOD(extack, "Invalid values in header for get address request");
5302 return -EINVAL;
5303 }
5304
Johannes Berg8cb08172019-04-26 14:07:28 +02005305 err = nlmsg_parse_deprecated_strict(nlh, sizeof(*ifm), tb, IFA_MAX,
5306 ifa_ipv6_policy, extack);
Jakub Kicinski4b1373d2019-01-18 10:46:21 -08005307 if (err)
5308 return err;
5309
5310 for (i = 0; i <= IFA_MAX; i++) {
5311 if (!tb[i])
5312 continue;
5313
5314 switch (i) {
5315 case IFA_TARGET_NETNSID:
5316 case IFA_ADDRESS:
5317 case IFA_LOCAL:
5318 break;
5319 default:
5320 NL_SET_ERR_MSG_MOD(extack, "Unsupported attribute in get address request");
5321 return -EINVAL;
5322 }
5323 }
5324
5325 return 0;
5326}
5327
David Ahernc21ef3e2017-04-16 09:48:24 -07005328static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh,
5329 struct netlink_ext_ack *extack)
Noriaki TAKAMIYA6c223822006-07-28 18:12:12 +09005330{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09005331 struct net *net = sock_net(in_skb->sk);
Christian Brauner203651b2018-09-04 21:53:55 +02005332 struct inet6_fill_args fillargs = {
5333 .portid = NETLINK_CB(in_skb).portid,
5334 .seq = nlh->nlmsg_seq,
5335 .event = RTM_NEWADDR,
5336 .flags = 0,
5337 .netnsid = -1,
5338 };
Christian Brauner6ecf4c32018-09-04 21:53:50 +02005339 struct net *tgt_net = net;
Thomas Graf1b29fc22006-09-18 00:10:50 -07005340 struct ifaddrmsg *ifm;
5341 struct nlattr *tb[IFA_MAX+1];
Nicolas Dichtelcaeaba72013-05-16 22:32:00 +00005342 struct in6_addr *addr = NULL, *peer;
Noriaki TAKAMIYA6c223822006-07-28 18:12:12 +09005343 struct net_device *dev = NULL;
5344 struct inet6_ifaddr *ifa;
5345 struct sk_buff *skb;
Noriaki TAKAMIYA6c223822006-07-28 18:12:12 +09005346 int err;
5347
Jakub Kicinski4b1373d2019-01-18 10:46:21 -08005348 err = inet6_rtm_valid_getaddr_req(in_skb, nlh, tb, extack);
Thomas Graf1b29fc22006-09-18 00:10:50 -07005349 if (err < 0)
Florian Westphalc24675f2017-10-11 10:28:01 +02005350 return err;
Noriaki TAKAMIYA6c223822006-07-28 18:12:12 +09005351
Christian Brauner6ecf4c32018-09-04 21:53:50 +02005352 if (tb[IFA_TARGET_NETNSID]) {
Christian Brauner203651b2018-09-04 21:53:55 +02005353 fillargs.netnsid = nla_get_s32(tb[IFA_TARGET_NETNSID]);
Christian Brauner6ecf4c32018-09-04 21:53:50 +02005354
5355 tgt_net = rtnl_get_net_ns_capable(NETLINK_CB(in_skb).sk,
Christian Brauner203651b2018-09-04 21:53:55 +02005356 fillargs.netnsid);
Christian Brauner6ecf4c32018-09-04 21:53:50 +02005357 if (IS_ERR(tgt_net))
5358 return PTR_ERR(tgt_net);
5359 }
5360
Nicolas Dichtelcaeaba72013-05-16 22:32:00 +00005361 addr = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL], &peer);
Florian Westphalc24675f2017-10-11 10:28:01 +02005362 if (!addr)
5363 return -EINVAL;
Thomas Graf1b29fc22006-09-18 00:10:50 -07005364
5365 ifm = nlmsg_data(nlh);
Noriaki TAKAMIYA6c223822006-07-28 18:12:12 +09005366 if (ifm->ifa_index)
Christian Brauner6ecf4c32018-09-04 21:53:50 +02005367 dev = dev_get_by_index(tgt_net, ifm->ifa_index);
Noriaki TAKAMIYA6c223822006-07-28 18:12:12 +09005368
Christian Brauner6ecf4c32018-09-04 21:53:50 +02005369 ifa = ipv6_get_ifaddr(tgt_net, addr, dev, 1);
Stephen Hemmingere21e8462010-03-20 16:09:01 -07005370 if (!ifa) {
Thomas Graf1b29fc22006-09-18 00:10:50 -07005371 err = -EADDRNOTAVAIL;
5372 goto errout;
Noriaki TAKAMIYA6c223822006-07-28 18:12:12 +09005373 }
5374
Stephen Hemmingere21e8462010-03-20 16:09:01 -07005375 skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_KERNEL);
5376 if (!skb) {
Thomas Graf1b29fc22006-09-18 00:10:50 -07005377 err = -ENOBUFS;
5378 goto errout_ifa;
5379 }
5380
Christian Brauner203651b2018-09-04 21:53:55 +02005381 err = inet6_fill_ifaddr(skb, ifa, &fillargs);
Patrick McHardy26932562007-01-31 23:16:40 -08005382 if (err < 0) {
5383 /* -EMSGSIZE implies BUG in inet6_ifaddr_msgsize() */
5384 WARN_ON(err == -EMSGSIZE);
5385 kfree_skb(skb);
5386 goto errout_ifa;
5387 }
Christian Brauner6ecf4c32018-09-04 21:53:50 +02005388 err = rtnl_unicast(skb, tgt_net, NETLINK_CB(in_skb).portid);
Thomas Graf1b29fc22006-09-18 00:10:50 -07005389errout_ifa:
Noriaki TAKAMIYA6c223822006-07-28 18:12:12 +09005390 in6_ifa_put(ifa);
Thomas Graf1b29fc22006-09-18 00:10:50 -07005391errout:
Florian Westphalc24675f2017-10-11 10:28:01 +02005392 if (dev)
5393 dev_put(dev);
Christian Brauner203651b2018-09-04 21:53:55 +02005394 if (fillargs.netnsid >= 0)
Christian Brauner6ecf4c32018-09-04 21:53:50 +02005395 put_net(tgt_net);
5396
Noriaki TAKAMIYA6c223822006-07-28 18:12:12 +09005397 return err;
Noriaki TAKAMIYA6c223822006-07-28 18:12:12 +09005398}
5399
Linus Torvalds1da177e2005-04-16 15:20:36 -07005400static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
5401{
5402 struct sk_buff *skb;
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09005403 struct net *net = dev_net(ifa->idev->dev);
Christian Brauner203651b2018-09-04 21:53:55 +02005404 struct inet6_fill_args fillargs = {
5405 .portid = 0,
5406 .seq = 0,
5407 .event = event,
5408 .flags = 0,
5409 .netnsid = -1,
5410 };
Thomas Graf5d620262006-08-15 00:35:02 -07005411 int err = -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005412
Thomas Graf0ab68032006-09-18 00:12:35 -07005413 skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_ATOMIC);
Ian Morris63159f22015-03-29 14:00:04 +01005414 if (!skb)
Thomas Graf5d620262006-08-15 00:35:02 -07005415 goto errout;
5416
Christian Brauner203651b2018-09-04 21:53:55 +02005417 err = inet6_fill_ifaddr(skb, ifa, &fillargs);
Patrick McHardy26932562007-01-31 23:16:40 -08005418 if (err < 0) {
5419 /* -EMSGSIZE implies BUG in inet6_ifaddr_msgsize() */
5420 WARN_ON(err == -EMSGSIZE);
5421 kfree_skb(skb);
5422 goto errout;
5423 }
Pablo Neira Ayuso1ce85fe2009-02-24 23:18:28 -08005424 rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
5425 return;
Thomas Graf5d620262006-08-15 00:35:02 -07005426errout:
5427 if (err < 0)
Benjamin Thery6fda7352008-03-05 10:47:47 -08005428 rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005429}
5430
Dave Jonesb6f99a22007-03-22 12:27:49 -07005431static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005432 __s32 *array, int bytes)
5433{
Thomas Graf04561c12006-11-14 19:53:58 -08005434 BUG_ON(bytes < (DEVCONF_MAX * 4));
5435
Linus Torvalds1da177e2005-04-16 15:20:36 -07005436 memset(array, 0, bytes);
5437 array[DEVCONF_FORWARDING] = cnf->forwarding;
5438 array[DEVCONF_HOPLIMIT] = cnf->hop_limit;
5439 array[DEVCONF_MTU6] = cnf->mtu6;
5440 array[DEVCONF_ACCEPT_RA] = cnf->accept_ra;
5441 array[DEVCONF_ACCEPT_REDIRECTS] = cnf->accept_redirects;
5442 array[DEVCONF_AUTOCONF] = cnf->autoconf;
5443 array[DEVCONF_DAD_TRANSMITS] = cnf->dad_transmits;
5444 array[DEVCONF_RTR_SOLICITS] = cnf->rtr_solicits;
Thomas Graf93908d12010-11-17 01:44:24 +00005445 array[DEVCONF_RTR_SOLICIT_INTERVAL] =
5446 jiffies_to_msecs(cnf->rtr_solicit_interval);
Maciej Żenczykowskibd11f072016-09-27 23:57:58 -07005447 array[DEVCONF_RTR_SOLICIT_MAX_INTERVAL] =
5448 jiffies_to_msecs(cnf->rtr_solicit_max_interval);
Thomas Graf93908d12010-11-17 01:44:24 +00005449 array[DEVCONF_RTR_SOLICIT_DELAY] =
5450 jiffies_to_msecs(cnf->rtr_solicit_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005451 array[DEVCONF_FORCE_MLD_VERSION] = cnf->force_mld_version;
Hannes Frederic Sowafc4eba52013-08-14 01:03:46 +02005452 array[DEVCONF_MLDV1_UNSOLICITED_REPORT_INTERVAL] =
5453 jiffies_to_msecs(cnf->mldv1_unsolicited_report_interval);
5454 array[DEVCONF_MLDV2_UNSOLICITED_REPORT_INTERVAL] =
5455 jiffies_to_msecs(cnf->mldv2_unsolicited_report_interval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005456 array[DEVCONF_USE_TEMPADDR] = cnf->use_tempaddr;
5457 array[DEVCONF_TEMP_VALID_LFT] = cnf->temp_valid_lft;
5458 array[DEVCONF_TEMP_PREFERED_LFT] = cnf->temp_prefered_lft;
5459 array[DEVCONF_REGEN_MAX_RETRY] = cnf->regen_max_retry;
5460 array[DEVCONF_MAX_DESYNC_FACTOR] = cnf->max_desync_factor;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005461 array[DEVCONF_MAX_ADDRESSES] = cnf->max_addresses;
YOSHIFUJI Hideaki65f5c7c2006-03-20 16:55:08 -08005462 array[DEVCONF_ACCEPT_RA_DEFRTR] = cnf->accept_ra_defrtr;
Hangbin Liu8013d1d2015-07-30 14:28:42 +08005463 array[DEVCONF_ACCEPT_RA_MIN_HOP_LIMIT] = cnf->accept_ra_min_hop_limit;
YOSHIFUJI Hideakic4fd30e2006-03-20 16:55:26 -08005464 array[DEVCONF_ACCEPT_RA_PINFO] = cnf->accept_ra_pinfo;
YOSHIFUJI Hideaki930d6ff2006-03-20 17:05:30 -08005465#ifdef CONFIG_IPV6_ROUTER_PREF
5466 array[DEVCONF_ACCEPT_RA_RTR_PREF] = cnf->accept_ra_rtr_pref;
Thomas Graf93908d12010-11-17 01:44:24 +00005467 array[DEVCONF_RTR_PROBE_INTERVAL] =
5468 jiffies_to_msecs(cnf->rtr_probe_interval);
Neil Hormanfa03ef32007-01-30 14:30:10 -08005469#ifdef CONFIG_IPV6_ROUTE_INFO
Joel Scherpelzbbea1242017-03-22 18:19:04 +09005470 array[DEVCONF_ACCEPT_RA_RT_INFO_MIN_PLEN] = cnf->accept_ra_rt_info_min_plen;
YOSHIFUJI Hideaki09c884d2006-03-20 17:07:03 -08005471 array[DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN] = cnf->accept_ra_rt_info_max_plen;
5472#endif
YOSHIFUJI Hideaki930d6ff2006-03-20 17:05:30 -08005473#endif
YOSHIFUJI Hideakifbea49e2006-09-22 14:43:49 -07005474 array[DEVCONF_PROXY_NDP] = cnf->proxy_ndp;
YOSHIFUJI Hideaki0bcbc922007-04-24 14:58:30 -07005475 array[DEVCONF_ACCEPT_SOURCE_ROUTE] = cnf->accept_source_route;
Neil Horman95c385b2007-04-25 17:08:10 -07005476#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
5477 array[DEVCONF_OPTIMISTIC_DAD] = cnf->optimistic_dad;
Erik Kline7fd25612014-10-28 18:11:14 +09005478 array[DEVCONF_USE_OPTIMISTIC] = cnf->use_optimistic;
Neil Horman95c385b2007-04-25 17:08:10 -07005479#endif
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09005480#ifdef CONFIG_IPV6_MROUTE
5481 array[DEVCONF_MC_FORWARDING] = cnf->mc_forwarding;
5482#endif
YOSHIFUJI Hideaki778d80b2008-06-28 14:17:11 +09005483 array[DEVCONF_DISABLE_IPV6] = cnf->disable_ipv6;
YOSHIFUJI Hideaki1b34be72008-06-28 14:18:38 +09005484 array[DEVCONF_ACCEPT_DAD] = cnf->accept_dad;
Cosmin Ratiuc3faca02009-10-09 03:11:14 +00005485 array[DEVCONF_FORCE_TLLAO] = cnf->force_tllao;
Hannes Frederic Sowa5cb04432012-11-06 16:46:20 +00005486 array[DEVCONF_NDISC_NOTIFY] = cnf->ndisc_notify;
Hannes Frederic Sowab800c3b2013-08-27 01:36:51 +02005487 array[DEVCONF_SUPPRESS_FRAG_NDISC] = cnf->suppress_frag_ndisc;
Ben Greeard9333192014-06-25 14:44:53 -07005488 array[DEVCONF_ACCEPT_RA_FROM_LOCAL] = cnf->accept_ra_from_local;
Harout Hedeshianc2943f12015-01-20 10:06:05 -07005489 array[DEVCONF_ACCEPT_RA_MTU] = cnf->accept_ra_mtu;
Andy Gospodarek35103d12015-08-13 10:39:01 -04005490 array[DEVCONF_IGNORE_ROUTES_WITH_LINKDOWN] = cnf->ignore_routes_with_linkdown;
Hannes Frederic Sowa3d1bec92015-03-23 23:36:00 +01005491 /* we omit DEVCONF_STABLE_SECRET for now */
Erik Kline3985e8a2015-07-22 16:38:25 +09005492 array[DEVCONF_USE_OIF_ADDRS_ONLY] = cnf->use_oif_addrs_only;
Johannes Bergabbc3042016-02-04 13:31:19 +01005493 array[DEVCONF_DROP_UNICAST_IN_L2_MULTICAST] = cnf->drop_unicast_in_l2_multicast;
Johannes Berg7a02bf82016-02-04 13:31:20 +01005494 array[DEVCONF_DROP_UNSOLICITED_NA] = cnf->drop_unsolicited_na;
David Ahernf1705ec2016-02-24 09:25:37 -08005495 array[DEVCONF_KEEP_ADDR_ON_DOWN] = cnf->keep_addr_on_down;
David Lebrun1ababeb2016-11-08 14:57:39 +01005496 array[DEVCONF_SEG6_ENABLED] = cnf->seg6_enabled;
David Lebrunbf355b82016-11-08 14:57:42 +01005497#ifdef CONFIG_IPV6_SEG6_HMAC
5498 array[DEVCONF_SEG6_REQUIRE_HMAC] = cnf->seg6_require_hmac;
5499#endif
Erik Nordmarkadc176c2016-12-02 14:00:08 -08005500 array[DEVCONF_ENHANCED_DAD] = cnf->enhanced_dad;
Felix Jiad35a00b2017-01-26 16:59:17 +13005501 array[DEVCONF_ADDR_GEN_MODE] = cnf->addr_gen_mode;
David Forsterdf789fe2017-02-23 16:27:18 +00005502 array[DEVCONF_DISABLE_POLICY] = cnf->disable_policy;
Maciej Żenczykowski2210d6b2017-11-07 21:52:09 -08005503 array[DEVCONF_NDISC_TCLASS] = cnf->ndisc_tclass;
Alexander Aring8610c7c2020-03-27 18:00:20 -04005504 array[DEVCONF_RPL_SEG_ENABLED] = cnf->rpl_seg_enabled;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005505}
5506
Thomas Grafb382b192010-11-16 04:33:57 +00005507static inline size_t inet6_ifla6_size(void)
5508{
5509 return nla_total_size(4) /* IFLA_INET6_FLAGS */
5510 + nla_total_size(sizeof(struct ifla_cacheinfo))
5511 + nla_total_size(DEVCONF_MAX * 4) /* IFLA_INET6_CONF */
5512 + nla_total_size(IPSTATS_MIB_MAX * 8) /* IFLA_INET6_STATS */
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005513 + nla_total_size(ICMP6_MIB_MAX * 8) /* IFLA_INET6_ICMP6STATS */
Sabrina Dubrocabdd72f42018-07-09 12:25:16 +02005514 + nla_total_size(sizeof(struct in6_addr)) /* IFLA_INET6_TOKEN */
5515 + nla_total_size(1) /* IFLA_INET6_ADDR_GEN_MODE */
5516 + 0;
Thomas Grafb382b192010-11-16 04:33:57 +00005517}
5518
Thomas Graf339bf982006-11-10 14:10:15 -08005519static inline size_t inet6_if_nlmsg_size(void)
5520{
5521 return NLMSG_ALIGN(sizeof(struct ifinfomsg))
5522 + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
5523 + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */
5524 + nla_total_size(4) /* IFLA_MTU */
5525 + nla_total_size(4) /* IFLA_LINK */
Andy Gospodarek03443382015-08-13 15:26:35 -04005526 + nla_total_size(1) /* IFLA_OPERSTATE */
Thomas Grafb382b192010-11-16 04:33:57 +00005527 + nla_total_size(inet6_ifla6_size()); /* IFLA_PROTINFO */
Thomas Graf339bf982006-11-10 14:10:15 -08005528}
YOSHIFUJI Hideakic5396a32006-06-17 22:48:48 -07005529
Eric Dumazetbe281e52011-05-19 01:14:23 +00005530static inline void __snmp6_fill_statsdev(u64 *stats, atomic_long_t *mib,
Jia Heaca05672016-09-30 11:29:03 +08005531 int bytes)
Herbert Xu7f7d9a62007-04-24 21:54:09 -07005532{
5533 int i;
Jia Heaca05672016-09-30 11:29:03 +08005534 int pad = bytes - sizeof(u64) * ICMP6_MIB_MAX;
Herbert Xu7f7d9a62007-04-24 21:54:09 -07005535 BUG_ON(pad < 0);
5536
5537 /* Use put_unaligned() because stats may not be aligned for u64. */
Jia Heaca05672016-09-30 11:29:03 +08005538 put_unaligned(ICMP6_MIB_MAX, &stats[0]);
5539 for (i = 1; i < ICMP6_MIB_MAX; i++)
Eric Dumazetbe281e52011-05-19 01:14:23 +00005540 put_unaligned(atomic_long_read(&mib[i]), &stats[i]);
Herbert Xu7f7d9a62007-04-24 21:54:09 -07005541
Jia Heaca05672016-09-30 11:29:03 +08005542 memset(&stats[ICMP6_MIB_MAX], 0, pad);
Herbert Xu7f7d9a62007-04-24 21:54:09 -07005543}
5544
WANG Cong698365f2014-05-05 15:55:55 -07005545static inline void __snmp6_fill_stats64(u64 *stats, void __percpu *mib,
Raghavendra K Ta3a77372015-08-30 11:29:42 +05305546 int bytes, size_t syncpoff)
Eric Dumazet4ce3c182010-06-30 13:31:19 -07005547{
Raghavendra K Ta3a77372015-08-30 11:29:42 +05305548 int i, c;
5549 u64 buff[IPSTATS_MIB_MAX];
5550 int pad = bytes - sizeof(u64) * IPSTATS_MIB_MAX;
5551
Eric Dumazet4ce3c182010-06-30 13:31:19 -07005552 BUG_ON(pad < 0);
5553
Raghavendra K Ta3a77372015-08-30 11:29:42 +05305554 memset(buff, 0, sizeof(buff));
5555 buff[0] = IPSTATS_MIB_MAX;
Eric Dumazet4ce3c182010-06-30 13:31:19 -07005556
Raghavendra K Ta3a77372015-08-30 11:29:42 +05305557 for_each_possible_cpu(c) {
5558 for (i = 1; i < IPSTATS_MIB_MAX; i++)
5559 buff[i] += snmp_get_cpu_field64(mib, c, i, syncpoff);
5560 }
5561
5562 memcpy(stats, buff, IPSTATS_MIB_MAX * sizeof(u64));
5563 memset(&stats[IPSTATS_MIB_MAX], 0, pad);
Eric Dumazet4ce3c182010-06-30 13:31:19 -07005564}
5565
Herbert Xu7f7d9a62007-04-24 21:54:09 -07005566static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype,
5567 int bytes)
5568{
Stephen Hemmingere21e8462010-03-20 16:09:01 -07005569 switch (attrtype) {
Herbert Xu7f7d9a62007-04-24 21:54:09 -07005570 case IFLA_INET6_STATS:
Raghavendra K Ta3a77372015-08-30 11:29:42 +05305571 __snmp6_fill_stats64(stats, idev->stats.ipv6, bytes,
5572 offsetof(struct ipstats_mib, syncp));
Herbert Xu7f7d9a62007-04-24 21:54:09 -07005573 break;
5574 case IFLA_INET6_ICMP6STATS:
Jia Heaca05672016-09-30 11:29:03 +08005575 __snmp6_fill_statsdev(stats, idev->stats.icmpv6dev->mibs, bytes);
Herbert Xu7f7d9a62007-04-24 21:54:09 -07005576 break;
5577 }
5578}
5579
Sowmini Varadhand5566fd2015-09-11 16:48:48 -04005580static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev,
5581 u32 ext_filter_mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005582{
YOSHIFUJI Hideakibf99f1b2007-04-20 15:56:20 -07005583 struct nlattr *nla;
Thomas Graf04561c12006-11-14 19:53:58 -08005584 struct ifla_cacheinfo ci;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005585
David S. Millerc78679e2012-04-01 20:27:33 -04005586 if (nla_put_u32(skb, IFLA_INET6_FLAGS, idev->if_flags))
5587 goto nla_put_failure;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005588 ci.max_reasm_len = IPV6_MAXPLEN;
David S. Miller24912422010-11-19 13:13:47 -08005589 ci.tstamp = cstamp_delta(idev->tstamp);
5590 ci.reachable_time = jiffies_to_msecs(idev->nd_parms->reachable_time);
Jiri Pirko1f9248e2013-12-07 19:26:53 +01005591 ci.retrans_time = jiffies_to_msecs(NEIGH_VAR(idev->nd_parms, RETRANS_TIME));
David S. Millerc78679e2012-04-01 20:27:33 -04005592 if (nla_put(skb, IFLA_INET6_CACHEINFO, sizeof(ci), &ci))
5593 goto nla_put_failure;
YOSHIFUJI Hideakibf99f1b2007-04-20 15:56:20 -07005594 nla = nla_reserve(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(s32));
Ian Morris63159f22015-03-29 14:00:04 +01005595 if (!nla)
Thomas Graf04561c12006-11-14 19:53:58 -08005596 goto nla_put_failure;
YOSHIFUJI Hideakibf99f1b2007-04-20 15:56:20 -07005597 ipv6_store_devconf(&idev->cnf, nla_data(nla), nla_len(nla));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005598
YOSHIFUJI Hideakibf99f1b2007-04-20 15:56:20 -07005599 /* XXX - MC not implemented */
5600
Sowmini Varadhand5566fd2015-09-11 16:48:48 -04005601 if (ext_filter_mask & RTEXT_FILTER_SKIP_STATS)
5602 return 0;
5603
YOSHIFUJI Hideakibf99f1b2007-04-20 15:56:20 -07005604 nla = nla_reserve(skb, IFLA_INET6_STATS, IPSTATS_MIB_MAX * sizeof(u64));
Ian Morris63159f22015-03-29 14:00:04 +01005605 if (!nla)
YOSHIFUJI Hideakibf99f1b2007-04-20 15:56:20 -07005606 goto nla_put_failure;
5607 snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_STATS, nla_len(nla));
5608
5609 nla = nla_reserve(skb, IFLA_INET6_ICMP6STATS, ICMP6_MIB_MAX * sizeof(u64));
Ian Morris63159f22015-03-29 14:00:04 +01005610 if (!nla)
YOSHIFUJI Hideakibf99f1b2007-04-20 15:56:20 -07005611 goto nla_put_failure;
5612 snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_ICMP6STATS, nla_len(nla));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005613
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005614 nla = nla_reserve(skb, IFLA_INET6_TOKEN, sizeof(struct in6_addr));
Ian Morris63159f22015-03-29 14:00:04 +01005615 if (!nla)
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005616 goto nla_put_failure;
5617 read_lock_bh(&idev->lock);
5618 memcpy(nla_data(nla), idev->token.s6_addr, nla_len(nla));
5619 read_unlock_bh(&idev->lock);
5620
Nicolas Dichtel0d7982c2019-09-30 14:02:16 +02005621 if (nla_put_u8(skb, IFLA_INET6_ADDR_GEN_MODE, idev->cnf.addr_gen_mode))
5622 goto nla_put_failure;
5623
Thomas Grafb382b192010-11-16 04:33:57 +00005624 return 0;
5625
5626nla_put_failure:
5627 return -EMSGSIZE;
5628}
5629
Arad, Ronenb1974ed2015-10-19 09:23:28 -07005630static size_t inet6_get_link_af_size(const struct net_device *dev,
5631 u32 ext_filter_mask)
Thomas Grafb382b192010-11-16 04:33:57 +00005632{
5633 if (!__in6_dev_get(dev))
5634 return 0;
5635
5636 return inet6_ifla6_size();
5637}
5638
Sowmini Varadhand5566fd2015-09-11 16:48:48 -04005639static int inet6_fill_link_af(struct sk_buff *skb, const struct net_device *dev,
5640 u32 ext_filter_mask)
Thomas Grafb382b192010-11-16 04:33:57 +00005641{
5642 struct inet6_dev *idev = __in6_dev_get(dev);
5643
5644 if (!idev)
5645 return -ENODATA;
5646
Sowmini Varadhand5566fd2015-09-11 16:48:48 -04005647 if (inet6_fill_ifla6_attrs(skb, idev, ext_filter_mask) < 0)
Thomas Grafb382b192010-11-16 04:33:57 +00005648 return -EMSGSIZE;
5649
5650 return 0;
5651}
5652
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005653static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token)
5654{
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005655 struct inet6_ifaddr *ifp;
5656 struct net_device *dev = idev->dev;
Daniel Borkmann47e27d52016-04-08 15:55:00 +02005657 bool clear_token, update_rs = false;
Hannes Frederic Sowadc848292013-06-24 21:42:40 +02005658 struct in6_addr ll_addr;
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005659
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01005660 ASSERT_RTNL();
5661
Ian Morris63159f22015-03-29 14:00:04 +01005662 if (!token)
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005663 return -EINVAL;
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005664 if (dev->flags & (IFF_LOOPBACK | IFF_NOARP))
5665 return -EINVAL;
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005666 if (!ipv6_accept_ra(idev))
5667 return -EINVAL;
Maciej Żenczykowskibd11f072016-09-27 23:57:58 -07005668 if (idev->cnf.rtr_solicits == 0)
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005669 return -EINVAL;
5670
5671 write_lock_bh(&idev->lock);
5672
5673 BUILD_BUG_ON(sizeof(token->s6_addr) != 16);
5674 memcpy(idev->token.s6_addr + 8, token->s6_addr + 8, 8);
5675
5676 write_unlock_bh(&idev->lock);
5677
Daniel Borkmann47e27d52016-04-08 15:55:00 +02005678 clear_token = ipv6_addr_any(token);
5679 if (clear_token)
5680 goto update_lft;
5681
Hannes Frederic Sowadc848292013-06-24 21:42:40 +02005682 if (!idev->dead && (idev->if_flags & IF_READY) &&
5683 !ipv6_get_lladdr(dev, &ll_addr, IFA_F_TENTATIVE |
5684 IFA_F_OPTIMISTIC)) {
Daniel Borkmannfc403832013-04-09 03:47:15 +00005685 /* If we're not ready, then normal ifup will take care
5686 * of this. Otherwise, we need to request our rs here.
5687 */
5688 ndisc_send_rs(dev, &ll_addr, &in6addr_linklocal_allrouters);
5689 update_rs = true;
5690 }
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005691
Daniel Borkmann47e27d52016-04-08 15:55:00 +02005692update_lft:
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005693 write_lock_bh(&idev->lock);
Daniel Borkmannfc403832013-04-09 03:47:15 +00005694
Hannes Frederic Sowa77ecaac2013-06-26 03:41:49 +02005695 if (update_rs) {
Daniel Borkmannfc403832013-04-09 03:47:15 +00005696 idev->if_flags |= IF_RS_SENT;
Maciej Żenczykowskibd11f072016-09-27 23:57:58 -07005697 idev->rs_interval = rfc3315_s14_backoff_init(
5698 idev->cnf.rtr_solicit_interval);
Hannes Frederic Sowa77ecaac2013-06-26 03:41:49 +02005699 idev->rs_probes = 1;
Maciej Żenczykowskibd11f072016-09-27 23:57:58 -07005700 addrconf_mod_rs_timer(idev, idev->rs_interval);
Hannes Frederic Sowa77ecaac2013-06-26 03:41:49 +02005701 }
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005702
5703 /* Well, that's kinda nasty ... */
5704 list_for_each_entry(ifp, &idev->addr_list, if_list) {
5705 spin_lock(&ifp->lock);
Daniel Borkmann617fe292013-04-09 03:47:16 +00005706 if (ifp->tokenized) {
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005707 ifp->valid_lft = 0;
5708 ifp->prefered_lft = 0;
5709 }
5710 spin_unlock(&ifp->lock);
5711 }
5712
5713 write_unlock_bh(&idev->lock);
Lubomir Rintelb2ed64a2014-10-27 17:39:16 +01005714 inet6_ifinfo_notify(RTM_NEWLINK, idev);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01005715 addrconf_verify_rtnl();
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005716 return 0;
5717}
5718
Daniel Borkmann11b1f822015-02-05 14:39:11 +01005719static const struct nla_policy inet6_af_policy[IFLA_INET6_MAX + 1] = {
5720 [IFLA_INET6_ADDR_GEN_MODE] = { .type = NLA_U8 },
5721 [IFLA_INET6_TOKEN] = { .len = sizeof(struct in6_addr) },
5722};
5723
Felix Jiad35a00b2017-01-26 16:59:17 +13005724static int check_addr_gen_mode(int mode)
5725{
5726 if (mode != IN6_ADDR_GEN_MODE_EUI64 &&
5727 mode != IN6_ADDR_GEN_MODE_NONE &&
5728 mode != IN6_ADDR_GEN_MODE_STABLE_PRIVACY &&
5729 mode != IN6_ADDR_GEN_MODE_RANDOM)
5730 return -EINVAL;
5731 return 1;
5732}
5733
5734static int check_stable_privacy(struct inet6_dev *idev, struct net *net,
5735 int mode)
5736{
5737 if (mode == IN6_ADDR_GEN_MODE_STABLE_PRIVACY &&
5738 !idev->cnf.stable_secret.initialized &&
5739 !net->ipv6.devconf_dflt->stable_secret.initialized)
5740 return -EINVAL;
5741 return 1;
5742}
5743
Maxim Mikityanskiy7dc2bcc2019-05-21 06:40:04 +00005744static int inet6_validate_link_af(const struct net_device *dev,
5745 const struct nlattr *nla)
5746{
5747 struct nlattr *tb[IFLA_INET6_MAX + 1];
5748 struct inet6_dev *idev = NULL;
5749 int err;
5750
5751 if (dev) {
5752 idev = __in6_dev_get(dev);
5753 if (!idev)
5754 return -EAFNOSUPPORT;
5755 }
5756
5757 err = nla_parse_nested_deprecated(tb, IFLA_INET6_MAX, nla,
5758 inet6_af_policy, NULL);
5759 if (err)
5760 return err;
5761
5762 if (!tb[IFLA_INET6_TOKEN] && !tb[IFLA_INET6_ADDR_GEN_MODE])
5763 return -EINVAL;
5764
5765 if (tb[IFLA_INET6_ADDR_GEN_MODE]) {
5766 u8 mode = nla_get_u8(tb[IFLA_INET6_ADDR_GEN_MODE]);
5767
5768 if (check_addr_gen_mode(mode) < 0)
5769 return -EINVAL;
5770 if (dev && check_stable_privacy(idev, dev_net(dev), mode) < 0)
5771 return -EINVAL;
5772 }
5773
5774 return 0;
5775}
5776
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005777static int inet6_set_link_af(struct net_device *dev, const struct nlattr *nla)
5778{
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005779 struct inet6_dev *idev = __in6_dev_get(dev);
5780 struct nlattr *tb[IFLA_INET6_MAX + 1];
Maxim Mikityanskiy7dc2bcc2019-05-21 06:40:04 +00005781 int err;
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005782
Eric Dumazetdb3fa272020-02-07 07:16:37 -08005783 if (!idev)
5784 return -EAFNOSUPPORT;
5785
Johannes Berg8cb08172019-04-26 14:07:28 +02005786 if (nla_parse_nested_deprecated(tb, IFLA_INET6_MAX, nla, NULL, NULL) < 0)
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005787 BUG();
5788
Jiri Pirkobc91b0f2014-07-11 21:10:18 +02005789 if (tb[IFLA_INET6_TOKEN]) {
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005790 err = inet6_set_iftoken(idev, nla_data(tb[IFLA_INET6_TOKEN]));
Jiri Pirkobc91b0f2014-07-11 21:10:18 +02005791 if (err)
5792 return err;
5793 }
5794
5795 if (tb[IFLA_INET6_ADDR_GEN_MODE]) {
5796 u8 mode = nla_get_u8(tb[IFLA_INET6_ADDR_GEN_MODE]);
5797
Felix Jiad35a00b2017-01-26 16:59:17 +13005798 idev->cnf.addr_gen_mode = mode;
Jiri Pirkobc91b0f2014-07-11 21:10:18 +02005799 }
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005800
Maxim Mikityanskiy7dc2bcc2019-05-21 06:40:04 +00005801 return 0;
Daniel Borkmannf53adae2013-04-08 04:01:30 +00005802}
5803
Thomas Grafb382b192010-11-16 04:33:57 +00005804static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
Eric W. Biederman15e47302012-09-07 20:12:54 +00005805 u32 portid, u32 seq, int event, unsigned int flags)
Thomas Grafb382b192010-11-16 04:33:57 +00005806{
5807 struct net_device *dev = idev->dev;
5808 struct ifinfomsg *hdr;
5809 struct nlmsghdr *nlh;
5810 void *protoinfo;
5811
Eric W. Biederman15e47302012-09-07 20:12:54 +00005812 nlh = nlmsg_put(skb, portid, seq, event, sizeof(*hdr), flags);
Ian Morris63159f22015-03-29 14:00:04 +01005813 if (!nlh)
Thomas Grafb382b192010-11-16 04:33:57 +00005814 return -EMSGSIZE;
5815
5816 hdr = nlmsg_data(nlh);
5817 hdr->ifi_family = AF_INET6;
5818 hdr->__ifi_pad = 0;
5819 hdr->ifi_type = dev->type;
5820 hdr->ifi_index = dev->ifindex;
5821 hdr->ifi_flags = dev_get_flags(dev);
5822 hdr->ifi_change = 0;
5823
David S. Millerc78679e2012-04-01 20:27:33 -04005824 if (nla_put_string(skb, IFLA_IFNAME, dev->name) ||
5825 (dev->addr_len &&
5826 nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr)) ||
5827 nla_put_u32(skb, IFLA_MTU, dev->mtu) ||
Nicolas Dichtela54acb32015-04-02 17:07:00 +02005828 (dev->ifindex != dev_get_iflink(dev) &&
Andy Gospodarek03443382015-08-13 15:26:35 -04005829 nla_put_u32(skb, IFLA_LINK, dev_get_iflink(dev))) ||
5830 nla_put_u8(skb, IFLA_OPERSTATE,
5831 netif_running(dev) ? dev->operstate : IF_OPER_DOWN))
David S. Millerc78679e2012-04-01 20:27:33 -04005832 goto nla_put_failure;
Michal Kubecekae0be8d2019-04-26 11:13:06 +02005833 protoinfo = nla_nest_start_noflag(skb, IFLA_PROTINFO);
Ian Morris63159f22015-03-29 14:00:04 +01005834 if (!protoinfo)
Thomas Grafb382b192010-11-16 04:33:57 +00005835 goto nla_put_failure;
5836
Sowmini Varadhand5566fd2015-09-11 16:48:48 -04005837 if (inet6_fill_ifla6_attrs(skb, idev, 0) < 0)
Thomas Grafb382b192010-11-16 04:33:57 +00005838 goto nla_put_failure;
5839
Thomas Graf04561c12006-11-14 19:53:58 -08005840 nla_nest_end(skb, protoinfo);
Johannes Berg053c0952015-01-16 22:09:00 +01005841 nlmsg_end(skb, nlh);
5842 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005843
Thomas Graf04561c12006-11-14 19:53:58 -08005844nla_put_failure:
Patrick McHardy26932562007-01-31 23:16:40 -08005845 nlmsg_cancel(skb, nlh);
5846 return -EMSGSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005847}
5848
David Ahern786e0002018-10-07 20:16:33 -07005849static int inet6_valid_dump_ifinfo(const struct nlmsghdr *nlh,
5850 struct netlink_ext_ack *extack)
5851{
5852 struct ifinfomsg *ifm;
5853
5854 if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ifm))) {
5855 NL_SET_ERR_MSG_MOD(extack, "Invalid header for link dump request");
5856 return -EINVAL;
5857 }
5858
5859 if (nlmsg_attrlen(nlh, sizeof(*ifm))) {
5860 NL_SET_ERR_MSG_MOD(extack, "Invalid data after header");
5861 return -EINVAL;
5862 }
5863
5864 ifm = nlmsg_data(nlh);
5865 if (ifm->__ifi_pad || ifm->ifi_type || ifm->ifi_flags ||
5866 ifm->ifi_change || ifm->ifi_index) {
5867 NL_SET_ERR_MSG_MOD(extack, "Invalid values in header for dump request");
5868 return -EINVAL;
5869 }
5870
5871 return 0;
5872}
5873
Linus Torvalds1da177e2005-04-16 15:20:36 -07005874static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
5875{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09005876 struct net *net = sock_net(skb->sk);
Eric Dumazet84d26972009-11-09 12:11:28 +00005877 int h, s_h;
David S. Miller434a8a52009-11-11 18:53:00 -08005878 int idx = 0, s_idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005879 struct net_device *dev;
5880 struct inet6_dev *idev;
Eric Dumazet84d26972009-11-09 12:11:28 +00005881 struct hlist_head *head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005882
David Ahern786e0002018-10-07 20:16:33 -07005883 /* only requests using strict checking can pass data to
5884 * influence the dump
5885 */
5886 if (cb->strict_check) {
5887 int err = inet6_valid_dump_ifinfo(cb->nlh, cb->extack);
5888
5889 if (err < 0)
5890 return err;
5891 }
5892
Eric Dumazet84d26972009-11-09 12:11:28 +00005893 s_h = cb->args[0];
5894 s_idx = cb->args[1];
5895
5896 rcu_read_lock();
5897 for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
5898 idx = 0;
5899 head = &net->dev_index_head[h];
Sasha Levinb67bfe02013-02-27 17:06:00 -08005900 hlist_for_each_entry_rcu(dev, head, index_hlist) {
Eric Dumazet84d26972009-11-09 12:11:28 +00005901 if (idx < s_idx)
5902 goto cont;
5903 idev = __in6_dev_get(dev);
5904 if (!idev)
5905 goto cont;
5906 if (inet6_fill_ifinfo(skb, idev,
Eric W. Biederman15e47302012-09-07 20:12:54 +00005907 NETLINK_CB(cb->skb).portid,
Eric Dumazet84d26972009-11-09 12:11:28 +00005908 cb->nlh->nlmsg_seq,
Johannes Berg053c0952015-01-16 22:09:00 +01005909 RTM_NEWLINK, NLM_F_MULTI) < 0)
Eric Dumazet84d26972009-11-09 12:11:28 +00005910 goto out;
Pavel Emelianov7562f872007-05-03 15:13:45 -07005911cont:
Eric Dumazet84d26972009-11-09 12:11:28 +00005912 idx++;
5913 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005914 }
Eric Dumazet84d26972009-11-09 12:11:28 +00005915out:
5916 rcu_read_unlock();
5917 cb->args[1] = idx;
5918 cb->args[0] = h;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005919
5920 return skb->len;
5921}
5922
5923void inet6_ifinfo_notify(int event, struct inet6_dev *idev)
5924{
5925 struct sk_buff *skb;
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09005926 struct net *net = dev_net(idev->dev);
Thomas Graf8d7a76c2006-08-15 00:35:47 -07005927 int err = -ENOBUFS;
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09005928
Thomas Graf339bf982006-11-10 14:10:15 -08005929 skb = nlmsg_new(inet6_if_nlmsg_size(), GFP_ATOMIC);
Ian Morris63159f22015-03-29 14:00:04 +01005930 if (!skb)
Thomas Graf8d7a76c2006-08-15 00:35:47 -07005931 goto errout;
5932
5933 err = inet6_fill_ifinfo(skb, idev, 0, 0, event, 0);
Patrick McHardy26932562007-01-31 23:16:40 -08005934 if (err < 0) {
5935 /* -EMSGSIZE implies BUG in inet6_if_nlmsg_size() */
5936 WARN_ON(err == -EMSGSIZE);
5937 kfree_skb(skb);
5938 goto errout;
5939 }
Nicolas Dichtel5f75a102010-12-07 23:38:31 +00005940 rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFINFO, NULL, GFP_ATOMIC);
Pablo Neira Ayuso1ce85fe2009-02-24 23:18:28 -08005941 return;
Thomas Graf8d7a76c2006-08-15 00:35:47 -07005942errout:
5943 if (err < 0)
Nicolas Dichtel5f75a102010-12-07 23:38:31 +00005944 rtnl_set_sk_err(net, RTNLGRP_IPV6_IFINFO, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005945}
5946
Thomas Graf339bf982006-11-10 14:10:15 -08005947static inline size_t inet6_prefix_nlmsg_size(void)
5948{
5949 return NLMSG_ALIGN(sizeof(struct prefixmsg))
5950 + nla_total_size(sizeof(struct in6_addr))
5951 + nla_total_size(sizeof(struct prefix_cacheinfo));
5952}
YOSHIFUJI Hideakic5396a32006-06-17 22:48:48 -07005953
Linus Torvalds1da177e2005-04-16 15:20:36 -07005954static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev,
Eric W. Biederman15e47302012-09-07 20:12:54 +00005955 struct prefix_info *pinfo, u32 portid, u32 seq,
Thomas Graf6051e2f2006-11-14 19:54:19 -08005956 int event, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005957{
Thomas Graf6051e2f2006-11-14 19:54:19 -08005958 struct prefixmsg *pmsg;
5959 struct nlmsghdr *nlh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005960 struct prefix_cacheinfo ci;
5961
Eric W. Biederman15e47302012-09-07 20:12:54 +00005962 nlh = nlmsg_put(skb, portid, seq, event, sizeof(*pmsg), flags);
Ian Morris63159f22015-03-29 14:00:04 +01005963 if (!nlh)
Patrick McHardy26932562007-01-31 23:16:40 -08005964 return -EMSGSIZE;
Thomas Graf6051e2f2006-11-14 19:54:19 -08005965
5966 pmsg = nlmsg_data(nlh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005967 pmsg->prefix_family = AF_INET6;
Patrick McHardy8a470772005-06-28 12:56:45 -07005968 pmsg->prefix_pad1 = 0;
5969 pmsg->prefix_pad2 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005970 pmsg->prefix_ifindex = idev->dev->ifindex;
5971 pmsg->prefix_len = pinfo->prefix_len;
5972 pmsg->prefix_type = pinfo->type;
Patrick McHardy8a470772005-06-28 12:56:45 -07005973 pmsg->prefix_pad3 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005974 pmsg->prefix_flags = 0;
5975 if (pinfo->onlink)
5976 pmsg->prefix_flags |= IF_PREFIX_ONLINK;
5977 if (pinfo->autoconf)
5978 pmsg->prefix_flags |= IF_PREFIX_AUTOCONF;
5979
David S. Millerc78679e2012-04-01 20:27:33 -04005980 if (nla_put(skb, PREFIX_ADDRESS, sizeof(pinfo->prefix), &pinfo->prefix))
5981 goto nla_put_failure;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005982 ci.preferred_time = ntohl(pinfo->prefered);
5983 ci.valid_time = ntohl(pinfo->valid);
David S. Millerc78679e2012-04-01 20:27:33 -04005984 if (nla_put(skb, PREFIX_CACHEINFO, sizeof(ci), &ci))
5985 goto nla_put_failure;
Johannes Berg053c0952015-01-16 22:09:00 +01005986 nlmsg_end(skb, nlh);
5987 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005988
Thomas Graf6051e2f2006-11-14 19:54:19 -08005989nla_put_failure:
Patrick McHardy26932562007-01-31 23:16:40 -08005990 nlmsg_cancel(skb, nlh);
5991 return -EMSGSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005992}
5993
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09005994static void inet6_prefix_notify(int event, struct inet6_dev *idev,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005995 struct prefix_info *pinfo)
5996{
5997 struct sk_buff *skb;
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09005998 struct net *net = dev_net(idev->dev);
Thomas Graf8c384bfa2006-08-15 00:36:07 -07005999 int err = -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006000
Thomas Graf339bf982006-11-10 14:10:15 -08006001 skb = nlmsg_new(inet6_prefix_nlmsg_size(), GFP_ATOMIC);
Ian Morris63159f22015-03-29 14:00:04 +01006002 if (!skb)
Thomas Graf8c384bfa2006-08-15 00:36:07 -07006003 goto errout;
6004
6005 err = inet6_fill_prefix(skb, idev, pinfo, 0, 0, event, 0);
Patrick McHardy26932562007-01-31 23:16:40 -08006006 if (err < 0) {
6007 /* -EMSGSIZE implies BUG in inet6_prefix_nlmsg_size() */
6008 WARN_ON(err == -EMSGSIZE);
6009 kfree_skb(skb);
6010 goto errout;
6011 }
Pablo Neira Ayuso1ce85fe2009-02-24 23:18:28 -08006012 rtnl_notify(skb, net, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC);
6013 return;
Thomas Graf8c384bfa2006-08-15 00:36:07 -07006014errout:
6015 if (err < 0)
Benjamin Thery6fda7352008-03-05 10:47:47 -08006016 rtnl_set_sk_err(net, RTNLGRP_IPV6_PREFIX, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006017}
6018
Linus Torvalds1da177e2005-04-16 15:20:36 -07006019static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
6020{
Nicolas Dichtel63998ac2013-03-22 06:28:43 +00006021 struct net *net = dev_net(ifp->idev->dev);
6022
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01006023 if (event)
6024 ASSERT_RTNL();
6025
Linus Torvalds1da177e2005-04-16 15:20:36 -07006026 inet6_ifa_notify(event ? : RTM_NEWADDR, ifp);
6027
6028 switch (event) {
6029 case RTM_NEWADDR:
Neil Horman95c385b2007-04-25 17:08:10 -07006030 /*
David Ahern2d819d252019-10-04 08:03:09 -07006031 * If the address was optimistic we inserted the route at the
6032 * start of our DAD process, so we don't need to do it again.
6033 * If the device was taken down in the middle of the DAD
6034 * cycle there is a race where we could get here without a
6035 * host route, so nothing to insert. That will be fixed when
6036 * the device is brought up.
Neil Horman95c385b2007-04-25 17:08:10 -07006037 */
David Ahern2d819d252019-10-04 08:03:09 -07006038 if (ifp->rt && !rcu_access_pointer(ifp->rt->fib6_node)) {
David Ahernafb1d4b52018-04-17 17:33:11 -07006039 ip6_ins_rt(net, ifp->rt);
David Ahern2d819d252019-10-04 08:03:09 -07006040 } else if (!ifp->rt && (ifp->idev->dev->flags & IFF_UP)) {
6041 pr_warn("BUG: Address %pI6c on device %s is missing its host route.\n",
6042 &ifp->addr, ifp->idev->dev->name);
6043 }
6044
Linus Torvalds1da177e2005-04-16 15:20:36 -07006045 if (ifp->idev->cnf.forwarding)
6046 addrconf_join_anycast(ifp);
Cong Wang7996c792013-05-22 05:41:06 +00006047 if (!ipv6_addr_any(&ifp->peer_addr))
Hangbin Liu07758eb2020-02-29 17:27:13 +08006048 addrconf_prefix_route(&ifp->peer_addr, 128,
6049 ifp->rt_priority, ifp->idev->dev,
6050 0, 0, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006051 break;
6052 case RTM_DELADDR:
6053 if (ifp->idev->cnf.forwarding)
6054 addrconf_leave_anycast(ifp);
6055 addrconf_leave_solict(ifp->idev, &ifp->addr);
Cong Wang7996c792013-05-22 05:41:06 +00006056 if (!ipv6_addr_any(&ifp->peer_addr)) {
David Ahern8d1c8022018-04-17 17:33:26 -07006057 struct fib6_info *rt;
Nicolas Dichtelcaeaba72013-05-16 22:32:00 +00006058
Nicolas Dichtele7478df2014-09-03 23:59:22 +02006059 rt = addrconf_get_prefix_route(&ifp->peer_addr, 128,
David Ahern2b2450c2019-03-27 20:53:52 -07006060 ifp->idev->dev, 0, 0,
6061 false);
Martin KaFai Lau8e3d5be2015-09-15 14:30:08 -07006062 if (rt)
Roopa Prabhu11dd74b2020-04-27 13:56:45 -07006063 ip6_del_rt(net, rt, false);
Nicolas Dichtelcaeaba72013-05-16 22:32:00 +00006064 }
David Ahern38bd10c2016-04-21 20:56:12 -07006065 if (ifp->rt) {
Roopa Prabhu11dd74b2020-04-27 13:56:45 -07006066 ip6_del_rt(net, ifp->rt, false);
David Ahern93531c62018-04-17 17:33:25 -07006067 ifp->rt = NULL;
David Ahern38bd10c2016-04-21 20:56:12 -07006068 }
Hannes Frederic Sowa705f1c82014-09-28 00:46:06 +02006069 rt_genid_bump_ipv6(net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006070 break;
6071 }
Nicolas Dichtel63998ac2013-03-22 06:28:43 +00006072 atomic_inc(&net->ipv6.dev_addr_genid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006073}
6074
6075static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
6076{
YOSHIFUJI Hideaki8814c4b2006-09-22 14:44:24 -07006077 rcu_read_lock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006078 if (likely(ifp->idev->dead == 0))
6079 __ipv6_ifa_notify(event, ifp);
YOSHIFUJI Hideaki8814c4b2006-09-22 14:44:24 -07006080 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006081}
6082
6083#ifdef CONFIG_SYSCTL
6084
Christoph Hellwig32927392020-04-24 08:43:38 +02006085static int addrconf_sysctl_forward(struct ctl_table *ctl, int write,
6086 void *buffer, size_t *lenp, loff_t *ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006087{
6088 int *valp = ctl->data;
6089 int val = *valp;
Eric W. Biederman88af1822010-02-19 13:22:59 +00006090 loff_t pos = *ppos;
Joe Perchesfe2c6332013-06-11 23:04:25 -07006091 struct ctl_table lctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006092 int ret;
6093
Francesco Ruggeri013d97e2012-01-16 10:40:10 +00006094 /*
6095 * ctl->data points to idev->cnf.forwarding, we should
6096 * not modify it until we get the rtnl lock.
6097 */
6098 lctl = *ctl;
6099 lctl.data = &val;
6100
6101 ret = proc_dointvec(&lctl, write, buffer, lenp, ppos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006102
Pavel Emelyanovc8fecf22007-12-05 01:50:24 -08006103 if (write)
Stephen Hemmingerb325fdd2009-02-26 06:55:31 +00006104 ret = addrconf_fixup_forwarding(ctl, valp, val);
Eric W. Biederman88af1822010-02-19 13:22:59 +00006105 if (ret)
6106 *ppos = pos;
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09006107 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006108}
6109
Christoph Hellwig32927392020-04-24 08:43:38 +02006110static int addrconf_sysctl_mtu(struct ctl_table *ctl, int write,
6111 void *buffer, size_t *lenp, loff_t *ppos)
Marcelo Leitner77751422015-02-23 11:17:13 -03006112{
6113 struct inet6_dev *idev = ctl->extra1;
6114 int min_mtu = IPV6_MIN_MTU;
6115 struct ctl_table lctl;
6116
6117 lctl = *ctl;
6118 lctl.extra1 = &min_mtu;
6119 lctl.extra2 = idev ? &idev->dev->mtu : NULL;
6120
6121 return proc_dointvec_minmax(&lctl, write, buffer, lenp, ppos);
6122}
6123
Brian Haley56d417b2009-06-01 03:07:33 -07006124static void dev_disable_change(struct inet6_dev *idev)
6125{
Cong Wang75538c22013-05-29 11:30:50 +08006126 struct netdev_notifier_info info;
6127
Brian Haley56d417b2009-06-01 03:07:33 -07006128 if (!idev || !idev->dev)
6129 return;
6130
Cong Wang75538c22013-05-29 11:30:50 +08006131 netdev_notifier_info_init(&info, idev->dev);
Brian Haley56d417b2009-06-01 03:07:33 -07006132 if (idev->cnf.disable_ipv6)
Cong Wang75538c22013-05-29 11:30:50 +08006133 addrconf_notify(NULL, NETDEV_DOWN, &info);
Brian Haley56d417b2009-06-01 03:07:33 -07006134 else
Cong Wang75538c22013-05-29 11:30:50 +08006135 addrconf_notify(NULL, NETDEV_UP, &info);
Brian Haley56d417b2009-06-01 03:07:33 -07006136}
6137
6138static void addrconf_disable_change(struct net *net, __s32 newf)
6139{
6140 struct net_device *dev;
6141 struct inet6_dev *idev;
6142
Kefeng Wang03e4def2017-01-19 16:26:21 +08006143 for_each_netdev(net, dev) {
Brian Haley56d417b2009-06-01 03:07:33 -07006144 idev = __in6_dev_get(dev);
6145 if (idev) {
6146 int changed = (!idev->cnf.disable_ipv6) ^ (!newf);
6147 idev->cnf.disable_ipv6 = newf;
6148 if (changed)
6149 dev_disable_change(idev);
6150 }
Brian Haley56d417b2009-06-01 03:07:33 -07006151 }
Brian Haley56d417b2009-06-01 03:07:33 -07006152}
6153
Francesco Ruggeri013d97e2012-01-16 10:40:10 +00006154static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int newf)
Brian Haley56d417b2009-06-01 03:07:33 -07006155{
6156 struct net *net;
Francesco Ruggeri013d97e2012-01-16 10:40:10 +00006157 int old;
6158
6159 if (!rtnl_trylock())
6160 return restart_syscall();
Brian Haley56d417b2009-06-01 03:07:33 -07006161
6162 net = (struct net *)table->extra2;
Francesco Ruggeri013d97e2012-01-16 10:40:10 +00006163 old = *p;
6164 *p = newf;
Brian Haley56d417b2009-06-01 03:07:33 -07006165
Francesco Ruggeri013d97e2012-01-16 10:40:10 +00006166 if (p == &net->ipv6.devconf_dflt->disable_ipv6) {
6167 rtnl_unlock();
Brian Haley56d417b2009-06-01 03:07:33 -07006168 return 0;
Eric W. Biederman88af1822010-02-19 13:22:59 +00006169 }
Brian Haley56d417b2009-06-01 03:07:33 -07006170
6171 if (p == &net->ipv6.devconf_all->disable_ipv6) {
Brian Haley56d417b2009-06-01 03:07:33 -07006172 net->ipv6.devconf_dflt->disable_ipv6 = newf;
6173 addrconf_disable_change(net, newf);
Francesco Ruggeri013d97e2012-01-16 10:40:10 +00006174 } else if ((!newf) ^ (!old))
Brian Haley56d417b2009-06-01 03:07:33 -07006175 dev_disable_change((struct inet6_dev *)table->extra1);
6176
6177 rtnl_unlock();
6178 return 0;
6179}
6180
Christoph Hellwig32927392020-04-24 08:43:38 +02006181static int addrconf_sysctl_disable(struct ctl_table *ctl, int write,
6182 void *buffer, size_t *lenp, loff_t *ppos)
Brian Haley56d417b2009-06-01 03:07:33 -07006183{
6184 int *valp = ctl->data;
6185 int val = *valp;
Eric W. Biederman88af1822010-02-19 13:22:59 +00006186 loff_t pos = *ppos;
Joe Perchesfe2c6332013-06-11 23:04:25 -07006187 struct ctl_table lctl;
Brian Haley56d417b2009-06-01 03:07:33 -07006188 int ret;
6189
Francesco Ruggeri013d97e2012-01-16 10:40:10 +00006190 /*
6191 * ctl->data points to idev->cnf.disable_ipv6, we should
6192 * not modify it until we get the rtnl lock.
6193 */
6194 lctl = *ctl;
6195 lctl.data = &val;
6196
6197 ret = proc_dointvec(&lctl, write, buffer, lenp, ppos);
Brian Haley56d417b2009-06-01 03:07:33 -07006198
6199 if (write)
6200 ret = addrconf_disable_ipv6(ctl, valp, val);
Eric W. Biederman88af1822010-02-19 13:22:59 +00006201 if (ret)
6202 *ppos = pos;
Brian Haley56d417b2009-06-01 03:07:33 -07006203 return ret;
6204}
6205
Christoph Hellwig32927392020-04-24 08:43:38 +02006206static int addrconf_sysctl_proxy_ndp(struct ctl_table *ctl, int write,
6207 void *buffer, size_t *lenp, loff_t *ppos)
stephen hemmingerc92d5492013-12-17 22:37:14 -08006208{
6209 int *valp = ctl->data;
6210 int ret;
6211 int old, new;
6212
6213 old = *valp;
6214 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
6215 new = *valp;
6216
6217 if (write && old != new) {
6218 struct net *net = ctl->extra2;
6219
6220 if (!rtnl_trylock())
6221 return restart_syscall();
6222
6223 if (valp == &net->ipv6.devconf_dflt->proxy_ndp)
David Ahern85b3daa2017-03-28 14:28:04 -07006224 inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
6225 NETCONFA_PROXY_NEIGH,
stephen hemmingerc92d5492013-12-17 22:37:14 -08006226 NETCONFA_IFINDEX_DEFAULT,
6227 net->ipv6.devconf_dflt);
6228 else if (valp == &net->ipv6.devconf_all->proxy_ndp)
David Ahern85b3daa2017-03-28 14:28:04 -07006229 inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
6230 NETCONFA_PROXY_NEIGH,
stephen hemmingerc92d5492013-12-17 22:37:14 -08006231 NETCONFA_IFINDEX_ALL,
6232 net->ipv6.devconf_all);
6233 else {
6234 struct inet6_dev *idev = ctl->extra1;
6235
David Ahern85b3daa2017-03-28 14:28:04 -07006236 inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
6237 NETCONFA_PROXY_NEIGH,
stephen hemmingerc92d5492013-12-17 22:37:14 -08006238 idev->dev->ifindex,
6239 &idev->cnf);
6240 }
6241 rtnl_unlock();
6242 }
6243
6244 return ret;
6245}
6246
Felix Jiad35a00b2017-01-26 16:59:17 +13006247static int addrconf_sysctl_addr_gen_mode(struct ctl_table *ctl, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +02006248 void *buffer, size_t *lenp,
Felix Jiad35a00b2017-01-26 16:59:17 +13006249 loff_t *ppos)
6250{
6251 int ret = 0;
Sabrina Dubrocac6dbf7a2018-07-09 12:25:14 +02006252 u32 new_val;
Felix Jiad35a00b2017-01-26 16:59:17 +13006253 struct inet6_dev *idev = (struct inet6_dev *)ctl->extra1;
6254 struct net *net = (struct net *)ctl->extra2;
Sabrina Dubrocac6dbf7a2018-07-09 12:25:14 +02006255 struct ctl_table tmp = {
6256 .data = &new_val,
6257 .maxlen = sizeof(new_val),
6258 .mode = ctl->mode,
6259 };
Felix Jiad35a00b2017-01-26 16:59:17 +13006260
Felix Jia8c171d62017-02-27 12:41:23 +13006261 if (!rtnl_trylock())
6262 return restart_syscall();
6263
Sabrina Dubrocac6dbf7a2018-07-09 12:25:14 +02006264 new_val = *((u32 *)ctl->data);
6265
6266 ret = proc_douintvec(&tmp, write, buffer, lenp, ppos);
6267 if (ret != 0)
6268 goto out;
Felix Jiad35a00b2017-01-26 16:59:17 +13006269
6270 if (write) {
Felix Jia8c171d62017-02-27 12:41:23 +13006271 if (check_addr_gen_mode(new_val) < 0) {
6272 ret = -EINVAL;
6273 goto out;
6274 }
Felix Jiad35a00b2017-01-26 16:59:17 +13006275
Sabrina Dubrocac6dbf7a2018-07-09 12:25:14 +02006276 if (idev) {
Felix Jia8c171d62017-02-27 12:41:23 +13006277 if (check_stable_privacy(idev, net, new_val) < 0) {
6278 ret = -EINVAL;
6279 goto out;
6280 }
Felix Jiad35a00b2017-01-26 16:59:17 +13006281
6282 if (idev->cnf.addr_gen_mode != new_val) {
6283 idev->cnf.addr_gen_mode = new_val;
Felix Jiad35a00b2017-01-26 16:59:17 +13006284 addrconf_dev_config(idev->dev);
Felix Jiad35a00b2017-01-26 16:59:17 +13006285 }
Sabrina Dubrocaf24c5982018-07-09 12:25:17 +02006286 } else if (&net->ipv6.devconf_all->addr_gen_mode == ctl->data) {
6287 struct net_device *dev;
6288
6289 net->ipv6.devconf_dflt->addr_gen_mode = new_val;
6290 for_each_netdev(net, dev) {
6291 idev = __in6_dev_get(dev);
6292 if (idev &&
6293 idev->cnf.addr_gen_mode != new_val) {
6294 idev->cnf.addr_gen_mode = new_val;
6295 addrconf_dev_config(idev->dev);
6296 }
6297 }
Felix Jiad35a00b2017-01-26 16:59:17 +13006298 }
Sabrina Dubrocac6dbf7a2018-07-09 12:25:14 +02006299
6300 *((u32 *)ctl->data) = new_val;
Felix Jiad35a00b2017-01-26 16:59:17 +13006301 }
6302
Felix Jia8c171d62017-02-27 12:41:23 +13006303out:
6304 rtnl_unlock();
6305
Felix Jiad35a00b2017-01-26 16:59:17 +13006306 return ret;
6307}
6308
Hannes Frederic Sowa3d1bec92015-03-23 23:36:00 +01006309static int addrconf_sysctl_stable_secret(struct ctl_table *ctl, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +02006310 void *buffer, size_t *lenp,
Hannes Frederic Sowa3d1bec92015-03-23 23:36:00 +01006311 loff_t *ppos)
6312{
6313 int err;
6314 struct in6_addr addr;
6315 char str[IPV6_MAX_STRLEN];
6316 struct ctl_table lctl = *ctl;
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01006317 struct net *net = ctl->extra2;
Hannes Frederic Sowa3d1bec92015-03-23 23:36:00 +01006318 struct ipv6_stable_secret *secret = ctl->data;
6319
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01006320 if (&net->ipv6.devconf_all->stable_secret == ctl->data)
6321 return -EIO;
6322
Hannes Frederic Sowa3d1bec92015-03-23 23:36:00 +01006323 lctl.maxlen = IPV6_MAX_STRLEN;
6324 lctl.data = str;
6325
6326 if (!rtnl_trylock())
6327 return restart_syscall();
6328
6329 if (!write && !secret->initialized) {
6330 err = -EIO;
6331 goto out;
6332 }
6333
WANG Cong5449a5c2015-12-21 10:55:45 -08006334 err = snprintf(str, sizeof(str), "%pI6", &secret->secret);
6335 if (err >= sizeof(str)) {
6336 err = -EIO;
6337 goto out;
Hannes Frederic Sowa3d1bec92015-03-23 23:36:00 +01006338 }
6339
6340 err = proc_dostring(&lctl, write, buffer, lenp, ppos);
6341 if (err || !write)
6342 goto out;
6343
6344 if (in6_pton(str, -1, addr.in6_u.u6_addr8, -1, NULL) != 1) {
6345 err = -EIO;
6346 goto out;
6347 }
6348
6349 secret->initialized = true;
6350 secret->secret = addr;
6351
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01006352 if (&net->ipv6.devconf_dflt->stable_secret == ctl->data) {
6353 struct net_device *dev;
6354
6355 for_each_netdev(net, dev) {
6356 struct inet6_dev *idev = __in6_dev_get(dev);
6357
6358 if (idev) {
Felix Jiad35a00b2017-01-26 16:59:17 +13006359 idev->cnf.addr_gen_mode =
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01006360 IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
6361 }
6362 }
6363 } else {
6364 struct inet6_dev *idev = ctl->extra1;
6365
Felix Jiad35a00b2017-01-26 16:59:17 +13006366 idev->cnf.addr_gen_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
Hannes Frederic Sowa622c81d52015-03-23 23:36:01 +01006367 }
6368
Hannes Frederic Sowa3d1bec92015-03-23 23:36:00 +01006369out:
6370 rtnl_unlock();
6371
6372 return err;
6373}
stephen hemmingerc92d5492013-12-17 22:37:14 -08006374
Andy Gospodarek35103d12015-08-13 10:39:01 -04006375static
6376int addrconf_sysctl_ignore_routes_with_linkdown(struct ctl_table *ctl,
Christoph Hellwig32927392020-04-24 08:43:38 +02006377 int write, void *buffer,
Andy Gospodarek35103d12015-08-13 10:39:01 -04006378 size_t *lenp,
6379 loff_t *ppos)
6380{
6381 int *valp = ctl->data;
6382 int val = *valp;
6383 loff_t pos = *ppos;
6384 struct ctl_table lctl;
6385 int ret;
6386
6387 /* ctl->data points to idev->cnf.ignore_routes_when_linkdown
6388 * we should not modify it until we get the rtnl lock.
6389 */
6390 lctl = *ctl;
6391 lctl.data = &val;
6392
6393 ret = proc_dointvec(&lctl, write, buffer, lenp, ppos);
6394
6395 if (write)
6396 ret = addrconf_fixup_linkdown(ctl, valp, val);
6397 if (ret)
6398 *ppos = pos;
6399 return ret;
6400}
6401
David Forsterdf789fe2017-02-23 16:27:18 +00006402static
6403void addrconf_set_nopolicy(struct rt6_info *rt, int action)
6404{
6405 if (rt) {
6406 if (action)
6407 rt->dst.flags |= DST_NOPOLICY;
6408 else
6409 rt->dst.flags &= ~DST_NOPOLICY;
6410 }
6411}
6412
6413static
6414void addrconf_disable_policy_idev(struct inet6_dev *idev, int val)
6415{
6416 struct inet6_ifaddr *ifa;
6417
6418 read_lock_bh(&idev->lock);
6419 list_for_each_entry(ifa, &idev->addr_list, if_list) {
6420 spin_lock(&ifa->lock);
6421 if (ifa->rt) {
David Ahernf88d8ea2019-06-03 20:19:52 -07006422 /* host routes only use builtin fib6_nh */
David Ahern1cf844c2019-05-22 20:27:59 -07006423 struct fib6_nh *nh = ifa->rt->fib6_nh;
David Forsterdf789fe2017-02-23 16:27:18 +00006424 int cpu;
6425
Wei Wang66f5d6c2017-10-06 12:06:10 -07006426 rcu_read_lock();
David Ahern3b6761d2018-04-17 17:33:20 -07006427 ifa->rt->dst_nopolicy = val ? true : false;
David Ahernf40b6ae2019-05-22 20:27:55 -07006428 if (nh->rt6i_pcpu) {
David Forsterdf789fe2017-02-23 16:27:18 +00006429 for_each_possible_cpu(cpu) {
6430 struct rt6_info **rtp;
6431
David Ahernf40b6ae2019-05-22 20:27:55 -07006432 rtp = per_cpu_ptr(nh->rt6i_pcpu, cpu);
David Forsterdf789fe2017-02-23 16:27:18 +00006433 addrconf_set_nopolicy(*rtp, val);
6434 }
6435 }
Wei Wang66f5d6c2017-10-06 12:06:10 -07006436 rcu_read_unlock();
David Forsterdf789fe2017-02-23 16:27:18 +00006437 }
6438 spin_unlock(&ifa->lock);
6439 }
6440 read_unlock_bh(&idev->lock);
6441}
6442
6443static
6444int addrconf_disable_policy(struct ctl_table *ctl, int *valp, int val)
6445{
6446 struct inet6_dev *idev;
6447 struct net *net;
6448
6449 if (!rtnl_trylock())
6450 return restart_syscall();
6451
6452 *valp = val;
6453
6454 net = (struct net *)ctl->extra2;
6455 if (valp == &net->ipv6.devconf_dflt->disable_policy) {
6456 rtnl_unlock();
6457 return 0;
6458 }
6459
6460 if (valp == &net->ipv6.devconf_all->disable_policy) {
6461 struct net_device *dev;
6462
6463 for_each_netdev(net, dev) {
6464 idev = __in6_dev_get(dev);
6465 if (idev)
6466 addrconf_disable_policy_idev(idev, val);
6467 }
6468 } else {
6469 idev = (struct inet6_dev *)ctl->extra1;
6470 addrconf_disable_policy_idev(idev, val);
6471 }
6472
6473 rtnl_unlock();
6474 return 0;
6475}
6476
Christoph Hellwig32927392020-04-24 08:43:38 +02006477static int addrconf_sysctl_disable_policy(struct ctl_table *ctl, int write,
6478 void *buffer, size_t *lenp, loff_t *ppos)
David Forsterdf789fe2017-02-23 16:27:18 +00006479{
6480 int *valp = ctl->data;
6481 int val = *valp;
6482 loff_t pos = *ppos;
6483 struct ctl_table lctl;
6484 int ret;
6485
6486 lctl = *ctl;
6487 lctl.data = &val;
6488 ret = proc_dointvec(&lctl, write, buffer, lenp, ppos);
6489
6490 if (write && (*valp != val))
6491 ret = addrconf_disable_policy(ctl, valp, val);
6492
6493 if (ret)
6494 *ppos = pos;
6495
6496 return ret;
6497}
6498
Maciej Żenczykowskicb4a4c62016-10-07 01:00:49 -07006499static int minus_one = -1;
Maciej Żenczykowskicb9e6842016-09-29 00:33:43 -07006500static const int two_five_five = 255;
6501
Konstantin Khlebnikov607ea7c2016-04-18 14:41:10 +03006502static const struct ctl_table addrconf_sysctl[] = {
Konstantin Khlebnikov5df1f772016-04-18 14:41:17 +03006503 {
6504 .procname = "forwarding",
6505 .data = &ipv6_devconf.forwarding,
6506 .maxlen = sizeof(int),
6507 .mode = 0644,
6508 .proc_handler = addrconf_sysctl_forward,
6509 },
6510 {
6511 .procname = "hop_limit",
6512 .data = &ipv6_devconf.hop_limit,
6513 .maxlen = sizeof(int),
6514 .mode = 0644,
Maciej Żenczykowskicb9e6842016-09-29 00:33:43 -07006515 .proc_handler = proc_dointvec_minmax,
Matteo Croceeec48442019-07-18 15:58:50 -07006516 .extra1 = (void *)SYSCTL_ONE,
Maciej Żenczykowskicb9e6842016-09-29 00:33:43 -07006517 .extra2 = (void *)&two_five_five,
Konstantin Khlebnikov5df1f772016-04-18 14:41:17 +03006518 },
6519 {
6520 .procname = "mtu",
6521 .data = &ipv6_devconf.mtu6,
6522 .maxlen = sizeof(int),
6523 .mode = 0644,
6524 .proc_handler = addrconf_sysctl_mtu,
6525 },
6526 {
6527 .procname = "accept_ra",
6528 .data = &ipv6_devconf.accept_ra,
6529 .maxlen = sizeof(int),
6530 .mode = 0644,
6531 .proc_handler = proc_dointvec,
6532 },
6533 {
6534 .procname = "accept_redirects",
6535 .data = &ipv6_devconf.accept_redirects,
6536 .maxlen = sizeof(int),
6537 .mode = 0644,
6538 .proc_handler = proc_dointvec,
6539 },
6540 {
6541 .procname = "autoconf",
6542 .data = &ipv6_devconf.autoconf,
6543 .maxlen = sizeof(int),
6544 .mode = 0644,
6545 .proc_handler = proc_dointvec,
6546 },
6547 {
6548 .procname = "dad_transmits",
6549 .data = &ipv6_devconf.dad_transmits,
6550 .maxlen = sizeof(int),
6551 .mode = 0644,
6552 .proc_handler = proc_dointvec,
6553 },
6554 {
6555 .procname = "router_solicitations",
6556 .data = &ipv6_devconf.rtr_solicits,
6557 .maxlen = sizeof(int),
6558 .mode = 0644,
Maciej Żenczykowskicb4a4c62016-10-07 01:00:49 -07006559 .proc_handler = proc_dointvec_minmax,
6560 .extra1 = &minus_one,
Konstantin Khlebnikov5df1f772016-04-18 14:41:17 +03006561 },
6562 {
6563 .procname = "router_solicitation_interval",
6564 .data = &ipv6_devconf.rtr_solicit_interval,
6565 .maxlen = sizeof(int),
6566 .mode = 0644,
6567 .proc_handler = proc_dointvec_jiffies,
6568 },
6569 {
Maciej Żenczykowskibd11f072016-09-27 23:57:58 -07006570 .procname = "router_solicitation_max_interval",
6571 .data = &ipv6_devconf.rtr_solicit_max_interval,
6572 .maxlen = sizeof(int),
6573 .mode = 0644,
6574 .proc_handler = proc_dointvec_jiffies,
6575 },
6576 {
Konstantin Khlebnikov5df1f772016-04-18 14:41:17 +03006577 .procname = "router_solicitation_delay",
6578 .data = &ipv6_devconf.rtr_solicit_delay,
6579 .maxlen = sizeof(int),
6580 .mode = 0644,
6581 .proc_handler = proc_dointvec_jiffies,
6582 },
6583 {
6584 .procname = "force_mld_version",
6585 .data = &ipv6_devconf.force_mld_version,
6586 .maxlen = sizeof(int),
6587 .mode = 0644,
6588 .proc_handler = proc_dointvec,
6589 },
6590 {
6591 .procname = "mldv1_unsolicited_report_interval",
6592 .data =
6593 &ipv6_devconf.mldv1_unsolicited_report_interval,
6594 .maxlen = sizeof(int),
6595 .mode = 0644,
6596 .proc_handler = proc_dointvec_ms_jiffies,
6597 },
6598 {
6599 .procname = "mldv2_unsolicited_report_interval",
6600 .data =
6601 &ipv6_devconf.mldv2_unsolicited_report_interval,
6602 .maxlen = sizeof(int),
6603 .mode = 0644,
6604 .proc_handler = proc_dointvec_ms_jiffies,
6605 },
6606 {
6607 .procname = "use_tempaddr",
6608 .data = &ipv6_devconf.use_tempaddr,
6609 .maxlen = sizeof(int),
6610 .mode = 0644,
6611 .proc_handler = proc_dointvec,
6612 },
6613 {
6614 .procname = "temp_valid_lft",
6615 .data = &ipv6_devconf.temp_valid_lft,
6616 .maxlen = sizeof(int),
6617 .mode = 0644,
6618 .proc_handler = proc_dointvec,
6619 },
6620 {
6621 .procname = "temp_prefered_lft",
6622 .data = &ipv6_devconf.temp_prefered_lft,
6623 .maxlen = sizeof(int),
6624 .mode = 0644,
6625 .proc_handler = proc_dointvec,
6626 },
6627 {
6628 .procname = "regen_max_retry",
6629 .data = &ipv6_devconf.regen_max_retry,
6630 .maxlen = sizeof(int),
6631 .mode = 0644,
6632 .proc_handler = proc_dointvec,
6633 },
6634 {
6635 .procname = "max_desync_factor",
6636 .data = &ipv6_devconf.max_desync_factor,
6637 .maxlen = sizeof(int),
6638 .mode = 0644,
6639 .proc_handler = proc_dointvec,
6640 },
6641 {
6642 .procname = "max_addresses",
6643 .data = &ipv6_devconf.max_addresses,
6644 .maxlen = sizeof(int),
6645 .mode = 0644,
6646 .proc_handler = proc_dointvec,
6647 },
6648 {
6649 .procname = "accept_ra_defrtr",
6650 .data = &ipv6_devconf.accept_ra_defrtr,
6651 .maxlen = sizeof(int),
6652 .mode = 0644,
6653 .proc_handler = proc_dointvec,
6654 },
6655 {
6656 .procname = "accept_ra_min_hop_limit",
6657 .data = &ipv6_devconf.accept_ra_min_hop_limit,
6658 .maxlen = sizeof(int),
6659 .mode = 0644,
6660 .proc_handler = proc_dointvec,
6661 },
6662 {
6663 .procname = "accept_ra_pinfo",
6664 .data = &ipv6_devconf.accept_ra_pinfo,
6665 .maxlen = sizeof(int),
6666 .mode = 0644,
6667 .proc_handler = proc_dointvec,
6668 },
YOSHIFUJI Hideaki930d6ff2006-03-20 17:05:30 -08006669#ifdef CONFIG_IPV6_ROUTER_PREF
Konstantin Khlebnikov5df1f772016-04-18 14:41:17 +03006670 {
6671 .procname = "accept_ra_rtr_pref",
6672 .data = &ipv6_devconf.accept_ra_rtr_pref,
6673 .maxlen = sizeof(int),
6674 .mode = 0644,
6675 .proc_handler = proc_dointvec,
6676 },
6677 {
6678 .procname = "router_probe_interval",
6679 .data = &ipv6_devconf.rtr_probe_interval,
6680 .maxlen = sizeof(int),
6681 .mode = 0644,
6682 .proc_handler = proc_dointvec_jiffies,
6683 },
Neil Hormanfa03ef32007-01-30 14:30:10 -08006684#ifdef CONFIG_IPV6_ROUTE_INFO
Konstantin Khlebnikov5df1f772016-04-18 14:41:17 +03006685 {
Joel Scherpelzbbea1242017-03-22 18:19:04 +09006686 .procname = "accept_ra_rt_info_min_plen",
6687 .data = &ipv6_devconf.accept_ra_rt_info_min_plen,
6688 .maxlen = sizeof(int),
6689 .mode = 0644,
6690 .proc_handler = proc_dointvec,
6691 },
6692 {
Konstantin Khlebnikov5df1f772016-04-18 14:41:17 +03006693 .procname = "accept_ra_rt_info_max_plen",
6694 .data = &ipv6_devconf.accept_ra_rt_info_max_plen,
6695 .maxlen = sizeof(int),
6696 .mode = 0644,
6697 .proc_handler = proc_dointvec,
6698 },
YOSHIFUJI Hideaki09c884d2006-03-20 17:07:03 -08006699#endif
YOSHIFUJI Hideaki930d6ff2006-03-20 17:05:30 -08006700#endif
Konstantin Khlebnikov5df1f772016-04-18 14:41:17 +03006701 {
6702 .procname = "proxy_ndp",
6703 .data = &ipv6_devconf.proxy_ndp,
6704 .maxlen = sizeof(int),
6705 .mode = 0644,
6706 .proc_handler = addrconf_sysctl_proxy_ndp,
6707 },
6708 {
6709 .procname = "accept_source_route",
6710 .data = &ipv6_devconf.accept_source_route,
6711 .maxlen = sizeof(int),
6712 .mode = 0644,
6713 .proc_handler = proc_dointvec,
6714 },
Neil Horman95c385b2007-04-25 17:08:10 -07006715#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
Konstantin Khlebnikov5df1f772016-04-18 14:41:17 +03006716 {
6717 .procname = "optimistic_dad",
6718 .data = &ipv6_devconf.optimistic_dad,
6719 .maxlen = sizeof(int),
6720 .mode = 0644,
6721 .proc_handler = proc_dointvec,
6722 },
6723 {
6724 .procname = "use_optimistic",
6725 .data = &ipv6_devconf.use_optimistic,
6726 .maxlen = sizeof(int),
6727 .mode = 0644,
6728 .proc_handler = proc_dointvec,
6729 },
Neil Horman95c385b2007-04-25 17:08:10 -07006730#endif
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09006731#ifdef CONFIG_IPV6_MROUTE
Konstantin Khlebnikov5df1f772016-04-18 14:41:17 +03006732 {
6733 .procname = "mc_forwarding",
6734 .data = &ipv6_devconf.mc_forwarding,
6735 .maxlen = sizeof(int),
6736 .mode = 0444,
6737 .proc_handler = proc_dointvec,
6738 },
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09006739#endif
Konstantin Khlebnikov5df1f772016-04-18 14:41:17 +03006740 {
6741 .procname = "disable_ipv6",
6742 .data = &ipv6_devconf.disable_ipv6,
6743 .maxlen = sizeof(int),
6744 .mode = 0644,
6745 .proc_handler = addrconf_sysctl_disable,
6746 },
6747 {
6748 .procname = "accept_dad",
6749 .data = &ipv6_devconf.accept_dad,
6750 .maxlen = sizeof(int),
6751 .mode = 0644,
6752 .proc_handler = proc_dointvec,
6753 },
6754 {
6755 .procname = "force_tllao",
6756 .data = &ipv6_devconf.force_tllao,
6757 .maxlen = sizeof(int),
6758 .mode = 0644,
6759 .proc_handler = proc_dointvec
6760 },
6761 {
6762 .procname = "ndisc_notify",
6763 .data = &ipv6_devconf.ndisc_notify,
6764 .maxlen = sizeof(int),
6765 .mode = 0644,
6766 .proc_handler = proc_dointvec
6767 },
6768 {
6769 .procname = "suppress_frag_ndisc",
6770 .data = &ipv6_devconf.suppress_frag_ndisc,
6771 .maxlen = sizeof(int),
6772 .mode = 0644,
6773 .proc_handler = proc_dointvec
6774 },
6775 {
6776 .procname = "accept_ra_from_local",
6777 .data = &ipv6_devconf.accept_ra_from_local,
6778 .maxlen = sizeof(int),
6779 .mode = 0644,
6780 .proc_handler = proc_dointvec,
6781 },
6782 {
6783 .procname = "accept_ra_mtu",
6784 .data = &ipv6_devconf.accept_ra_mtu,
6785 .maxlen = sizeof(int),
6786 .mode = 0644,
6787 .proc_handler = proc_dointvec,
6788 },
6789 {
6790 .procname = "stable_secret",
6791 .data = &ipv6_devconf.stable_secret,
6792 .maxlen = IPV6_MAX_STRLEN,
6793 .mode = 0600,
6794 .proc_handler = addrconf_sysctl_stable_secret,
6795 },
6796 {
6797 .procname = "use_oif_addrs_only",
6798 .data = &ipv6_devconf.use_oif_addrs_only,
6799 .maxlen = sizeof(int),
6800 .mode = 0644,
6801 .proc_handler = proc_dointvec,
6802 },
6803 {
6804 .procname = "ignore_routes_with_linkdown",
6805 .data = &ipv6_devconf.ignore_routes_with_linkdown,
6806 .maxlen = sizeof(int),
6807 .mode = 0644,
6808 .proc_handler = addrconf_sysctl_ignore_routes_with_linkdown,
6809 },
6810 {
6811 .procname = "drop_unicast_in_l2_multicast",
6812 .data = &ipv6_devconf.drop_unicast_in_l2_multicast,
6813 .maxlen = sizeof(int),
6814 .mode = 0644,
6815 .proc_handler = proc_dointvec,
6816 },
6817 {
6818 .procname = "drop_unsolicited_na",
6819 .data = &ipv6_devconf.drop_unsolicited_na,
6820 .maxlen = sizeof(int),
6821 .mode = 0644,
6822 .proc_handler = proc_dointvec,
6823 },
6824 {
6825 .procname = "keep_addr_on_down",
6826 .data = &ipv6_devconf.keep_addr_on_down,
6827 .maxlen = sizeof(int),
6828 .mode = 0644,
6829 .proc_handler = proc_dointvec,
David Ahernf1705ec2016-02-24 09:25:37 -08006830
Konstantin Khlebnikov5df1f772016-04-18 14:41:17 +03006831 },
6832 {
David Lebrun1ababeb2016-11-08 14:57:39 +01006833 .procname = "seg6_enabled",
6834 .data = &ipv6_devconf.seg6_enabled,
6835 .maxlen = sizeof(int),
6836 .mode = 0644,
6837 .proc_handler = proc_dointvec,
6838 },
David Lebrunbf355b82016-11-08 14:57:42 +01006839#ifdef CONFIG_IPV6_SEG6_HMAC
6840 {
6841 .procname = "seg6_require_hmac",
6842 .data = &ipv6_devconf.seg6_require_hmac,
6843 .maxlen = sizeof(int),
6844 .mode = 0644,
6845 .proc_handler = proc_dointvec,
6846 },
6847#endif
David Lebrun1ababeb2016-11-08 14:57:39 +01006848 {
Erik Nordmarkadc176c2016-12-02 14:00:08 -08006849 .procname = "enhanced_dad",
6850 .data = &ipv6_devconf.enhanced_dad,
6851 .maxlen = sizeof(int),
6852 .mode = 0644,
6853 .proc_handler = proc_dointvec,
6854 },
6855 {
Felix Jiad35a00b2017-01-26 16:59:17 +13006856 .procname = "addr_gen_mode",
6857 .data = &ipv6_devconf.addr_gen_mode,
6858 .maxlen = sizeof(int),
6859 .mode = 0644,
6860 .proc_handler = addrconf_sysctl_addr_gen_mode,
6861 },
6862 {
David Forsterdf789fe2017-02-23 16:27:18 +00006863 .procname = "disable_policy",
6864 .data = &ipv6_devconf.disable_policy,
6865 .maxlen = sizeof(int),
6866 .mode = 0644,
6867 .proc_handler = addrconf_sysctl_disable_policy,
6868 },
6869 {
Maciej Żenczykowski2210d6b2017-11-07 21:52:09 -08006870 .procname = "ndisc_tclass",
6871 .data = &ipv6_devconf.ndisc_tclass,
6872 .maxlen = sizeof(int),
6873 .mode = 0644,
6874 .proc_handler = proc_dointvec_minmax,
Matteo Croceeec48442019-07-18 15:58:50 -07006875 .extra1 = (void *)SYSCTL_ZERO,
Maciej Żenczykowski2210d6b2017-11-07 21:52:09 -08006876 .extra2 = (void *)&two_five_five,
6877 },
6878 {
Alexander Aring8610c7c2020-03-27 18:00:20 -04006879 .procname = "rpl_seg_enabled",
6880 .data = &ipv6_devconf.rpl_seg_enabled,
6881 .maxlen = sizeof(int),
6882 .mode = 0644,
6883 .proc_handler = proc_dointvec,
6884 },
6885 {
Konstantin Khlebnikov5df1f772016-04-18 14:41:17 +03006886 /* sentinel */
6887 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006888};
6889
Pavel Emelyanovbff16c22008-01-10 17:42:13 -08006890static int __addrconf_sysctl_register(struct net *net, char *dev_name,
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08006891 struct inet6_dev *idev, struct ipv6_devconf *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006892{
Nicolas Dichtel29c994e2016-08-30 10:09:22 +02006893 int i, ifindex;
Konstantin Khlebnikov607ea7c2016-04-18 14:41:10 +03006894 struct ctl_table *table;
Eric W. Biederman6105e292012-04-19 13:41:24 +00006895 char path[sizeof("net/ipv6/conf/") + IFNAMSIZ];
Pavel Emelyanov1dab6222007-12-02 00:59:38 +11006896
Konstantin Khlebnikov607ea7c2016-04-18 14:41:10 +03006897 table = kmemdup(addrconf_sysctl, sizeof(addrconf_sysctl), GFP_KERNEL);
6898 if (!table)
Pavel Emelyanovf68635e2007-12-02 00:21:52 +11006899 goto out;
6900
Konstantin Khlebnikov607ea7c2016-04-18 14:41:10 +03006901 for (i = 0; table[i].data; i++) {
6902 table[i].data += (char *)p - (char *)&ipv6_devconf;
Maciej Żenczykowskicb9e6842016-09-29 00:33:43 -07006903 /* If one of these is already set, then it is not safe to
6904 * overwrite either of them: this makes proc_dointvec_minmax
6905 * usable.
6906 */
6907 if (!table[i].extra1 && !table[i].extra2) {
6908 table[i].extra1 = idev; /* embedded; no ref */
6909 table[i].extra2 = net;
6910 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006911 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006912
Eric W. Biederman6105e292012-04-19 13:41:24 +00006913 snprintf(path, sizeof(path), "net/ipv6/conf/%s", dev_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006914
Konstantin Khlebnikov607ea7c2016-04-18 14:41:10 +03006915 p->sysctl_header = register_net_sysctl(net, path, table);
6916 if (!p->sysctl_header)
Eric W. Biederman6105e292012-04-19 13:41:24 +00006917 goto free;
Pavel Emelyanovf68635e2007-12-02 00:21:52 +11006918
Nicolas Dichtel29c994e2016-08-30 10:09:22 +02006919 if (!strcmp(dev_name, "all"))
6920 ifindex = NETCONFA_IFINDEX_ALL;
6921 else if (!strcmp(dev_name, "default"))
6922 ifindex = NETCONFA_IFINDEX_DEFAULT;
6923 else
6924 ifindex = idev->dev->ifindex;
David Ahern85b3daa2017-03-28 14:28:04 -07006925 inet6_netconf_notify_devconf(net, RTM_NEWNETCONF, NETCONFA_ALL,
6926 ifindex, p);
Pavel Emelyanov95897312008-01-10 17:41:45 -08006927 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006928
Pavel Emelyanovf68635e2007-12-02 00:21:52 +11006929free:
Konstantin Khlebnikov607ea7c2016-04-18 14:41:10 +03006930 kfree(table);
Pavel Emelyanovf68635e2007-12-02 00:21:52 +11006931out:
Pavel Emelyanov95897312008-01-10 17:41:45 -08006932 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006933}
6934
David Ahern23452172017-03-28 14:28:05 -07006935static void __addrconf_sysctl_unregister(struct net *net,
6936 struct ipv6_devconf *p, int ifindex)
Pavel Emelyanov408c4762008-01-10 17:41:21 -08006937{
Konstantin Khlebnikov607ea7c2016-04-18 14:41:10 +03006938 struct ctl_table *table;
Pavel Emelyanov408c4762008-01-10 17:41:21 -08006939
Konstantin Khlebnikov607ea7c2016-04-18 14:41:10 +03006940 if (!p->sysctl_header)
Pavel Emelyanov408c4762008-01-10 17:41:21 -08006941 return;
6942
Konstantin Khlebnikov607ea7c2016-04-18 14:41:10 +03006943 table = p->sysctl_header->ctl_table_arg;
6944 unregister_net_sysctl_table(p->sysctl_header);
6945 p->sysctl_header = NULL;
6946 kfree(table);
David Ahern23452172017-03-28 14:28:05 -07006947
6948 inet6_netconf_notify_devconf(net, RTM_DELNETCONF, 0, ifindex, NULL);
Pavel Emelyanov408c4762008-01-10 17:41:21 -08006949}
6950
WANG Conga317a2f2014-07-25 15:25:09 -07006951static int addrconf_sysctl_register(struct inet6_dev *idev)
Pavel Emelyanovf52295a2007-12-02 00:58:37 +11006952{
WANG Conga317a2f2014-07-25 15:25:09 -07006953 int err;
6954
6955 if (!sysctl_dev_name_is_allowed(idev->dev->name))
6956 return -EINVAL;
6957
6958 err = neigh_sysctl_register(idev->dev, idev->nd_parms,
6959 &ndisc_ifinfo_sysctl_change);
6960 if (err)
6961 return err;
6962 err = __addrconf_sysctl_register(dev_net(idev->dev), idev->dev->name,
6963 idev, &idev->cnf);
6964 if (err)
6965 neigh_sysctl_unregister(idev->nd_parms);
6966
6967 return err;
Pavel Emelyanovf52295a2007-12-02 00:58:37 +11006968}
6969
Pavel Emelyanov408c4762008-01-10 17:41:21 -08006970static void addrconf_sysctl_unregister(struct inet6_dev *idev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006971{
David Ahern23452172017-03-28 14:28:05 -07006972 __addrconf_sysctl_unregister(dev_net(idev->dev), &idev->cnf,
6973 idev->dev->ifindex);
Pavel Emelyanov408c4762008-01-10 17:41:21 -08006974 neigh_sysctl_unregister(idev->nd_parms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006975}
6976
6977
6978#endif
6979
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00006980static int __net_init addrconf_init_net(struct net *net)
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08006981{
Hong Zhiguoa79ca222013-03-26 01:52:45 +08006982 int err = -ENOMEM;
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08006983 struct ipv6_devconf *all, *dflt;
6984
Hong Zhiguoa79ca222013-03-26 01:52:45 +08006985 all = kmemdup(&ipv6_devconf, sizeof(ipv6_devconf), GFP_KERNEL);
Ian Morris63159f22015-03-29 14:00:04 +01006986 if (!all)
Hong Zhiguoa79ca222013-03-26 01:52:45 +08006987 goto err_alloc_all;
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08006988
Hong Zhiguoa79ca222013-03-26 01:52:45 +08006989 dflt = kmemdup(&ipv6_devconf_dflt, sizeof(ipv6_devconf_dflt), GFP_KERNEL);
Ian Morris63159f22015-03-29 14:00:04 +01006990 if (!dflt)
Hong Zhiguoa79ca222013-03-26 01:52:45 +08006991 goto err_alloc_dflt;
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08006992
Arnd Bergmanna154d5d2019-03-04 21:38:03 +01006993 if (IS_ENABLED(CONFIG_SYSCTL) &&
6994 sysctl_devconf_inherit_init_net == 1 && !net_eq(net, &init_net)) {
Cong Wang856c3952019-01-17 23:27:11 -08006995 memcpy(all, init_net.ipv6.devconf_all, sizeof(ipv6_devconf));
6996 memcpy(dflt, init_net.ipv6.devconf_dflt, sizeof(ipv6_devconf_dflt));
6997 }
6998
Hong Zhiguoa79ca222013-03-26 01:52:45 +08006999 /* these will be inherited by all namespaces */
7000 dflt->autoconf = ipv6_defaults.autoconf;
7001 dflt->disable_ipv6 = ipv6_defaults.disable_ipv6;
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08007002
Hannes Frederic Sowa3d1bec92015-03-23 23:36:00 +01007003 dflt->stable_secret.initialized = false;
7004 all->stable_secret.initialized = false;
7005
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08007006 net->ipv6.devconf_all = all;
7007 net->ipv6.devconf_dflt = dflt;
7008
7009#ifdef CONFIG_SYSCTL
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08007010 err = __addrconf_sysctl_register(net, "all", NULL, all);
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08007011 if (err < 0)
7012 goto err_reg_all;
7013
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08007014 err = __addrconf_sysctl_register(net, "default", NULL, dflt);
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08007015 if (err < 0)
7016 goto err_reg_dflt;
7017#endif
7018 return 0;
7019
7020#ifdef CONFIG_SYSCTL
7021err_reg_dflt:
David Ahern23452172017-03-28 14:28:05 -07007022 __addrconf_sysctl_unregister(net, all, NETCONFA_IFINDEX_ALL);
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08007023err_reg_all:
7024 kfree(dflt);
7025#endif
7026err_alloc_dflt:
7027 kfree(all);
7028err_alloc_all:
7029 return err;
7030}
7031
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00007032static void __net_exit addrconf_exit_net(struct net *net)
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08007033{
7034#ifdef CONFIG_SYSCTL
David Ahern23452172017-03-28 14:28:05 -07007035 __addrconf_sysctl_unregister(net, net->ipv6.devconf_dflt,
7036 NETCONFA_IFINDEX_DEFAULT);
7037 __addrconf_sysctl_unregister(net, net->ipv6.devconf_all,
7038 NETCONFA_IFINDEX_ALL);
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08007039#endif
zhuyj73cf0e922014-11-26 10:25:58 +08007040 kfree(net->ipv6.devconf_dflt);
7041 kfree(net->ipv6.devconf_all);
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08007042}
7043
7044static struct pernet_operations addrconf_ops = {
7045 .init = addrconf_init_net,
7046 .exit = addrconf_exit_net,
7047};
7048
Daniel Borkmann207895fd32015-01-29 12:15:03 +01007049static struct rtnl_af_ops inet6_ops __read_mostly = {
Thomas Grafb382b192010-11-16 04:33:57 +00007050 .family = AF_INET6,
7051 .fill_link_af = inet6_fill_link_af,
7052 .get_link_af_size = inet6_get_link_af_size,
Daniel Borkmann11b1f822015-02-05 14:39:11 +01007053 .validate_link_af = inet6_validate_link_af,
Daniel Borkmannf53adae2013-04-08 04:01:30 +00007054 .set_link_af = inet6_set_link_af,
Thomas Grafb382b192010-11-16 04:33:57 +00007055};
7056
Linus Torvalds1da177e2005-04-16 15:20:36 -07007057/*
7058 * Init / cleanup code
7059 */
7060
7061int __init addrconf_init(void)
7062{
WANG Conga317a2f2014-07-25 15:25:09 -07007063 struct inet6_dev *idev;
stephen hemmingerc2e21292010-03-17 20:31:10 +00007064 int i, err;
YOSHIFUJI Hideaki2a8cc6c2007-11-14 15:56:23 +09007065
Stephen Hemmingere21e8462010-03-20 16:09:01 -07007066 err = ipv6_addr_label_init();
7067 if (err < 0) {
Joe Perchesf3213832012-05-15 14:11:53 +00007068 pr_crit("%s: cannot initialize default policy table: %d\n",
7069 __func__, err);
Neil Horman2cc6d2b2010-09-24 09:55:52 +00007070 goto out;
YOSHIFUJI Hideaki2a8cc6c2007-11-14 15:56:23 +09007071 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007072
Neil Horman2cc6d2b2010-09-24 09:55:52 +00007073 err = register_pernet_subsys(&addrconf_ops);
7074 if (err < 0)
7075 goto out_addrlabel;
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08007076
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01007077 addrconf_wq = create_workqueue("ipv6_addrconf");
7078 if (!addrconf_wq) {
7079 err = -ENOMEM;
7080 goto out_nowq;
7081 }
7082
Linus Torvalds1da177e2005-04-16 15:20:36 -07007083 /* The addrconf netdev notifier requires that loopback_dev
7084 * has it's ipv6 private information allocated and setup
7085 * before it can bring up and give link-local addresses
7086 * to other devices which are up.
7087 *
7088 * Unfortunately, loopback_dev is not necessarily the first
7089 * entry in the global dev_base list of net devices. In fact,
7090 * it is likely to be the very last entry on that list.
7091 * So this causes the notifier registry below to try and
7092 * give link-local addresses to all devices besides loopback_dev
7093 * first, then loopback_dev, which cases all the non-loopback_dev
7094 * devices to fail to get a link-local address.
7095 *
7096 * So, as a temporary fix, allocate the ipv6 structure for
7097 * loopback_dev first by hand.
7098 * Longer term, all of the dependencies ipv6 has upon the loopback
7099 * device and it being up should be removed.
7100 */
7101 rtnl_lock();
WANG Conga317a2f2014-07-25 15:25:09 -07007102 idev = ipv6_add_dev(init_net.loopback_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007103 rtnl_unlock();
WANG Conga317a2f2014-07-25 15:25:09 -07007104 if (IS_ERR(idev)) {
7105 err = PTR_ERR(idev);
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08007106 goto errlo;
WANG Conga317a2f2014-07-25 15:25:09 -07007107 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007108
WANG Cong2f460932017-05-03 22:07:31 -07007109 ip6_route_init_special_entries();
7110
stephen hemmingerc2e21292010-03-17 20:31:10 +00007111 for (i = 0; i < IN6_ADDR_HSIZE; i++)
7112 INIT_HLIST_HEAD(&inet6_addr_lst[i]);
7113
Linus Torvalds1da177e2005-04-16 15:20:36 -07007114 register_netdevice_notifier(&ipv6_dev_notf);
7115
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01007116 addrconf_verify();
Thomas Grafc127ea22007-03-22 11:58:32 -07007117
stephen hemminger3678a9d2013-12-30 10:41:32 -08007118 rtnl_af_register(&inet6_ops);
Thomas Grafb382b192010-11-16 04:33:57 +00007119
Florian Westphal16feebc2017-12-02 21:44:08 +01007120 err = rtnl_register_module(THIS_MODULE, PF_INET6, RTM_GETLINK,
7121 NULL, inet6_dump_ifinfo, 0);
Thomas Grafc127ea22007-03-22 11:58:32 -07007122 if (err < 0)
7123 goto errout;
7124
Florian Westphal16feebc2017-12-02 21:44:08 +01007125 err = rtnl_register_module(THIS_MODULE, PF_INET6, RTM_NEWADDR,
7126 inet6_rtm_newaddr, NULL, 0);
7127 if (err < 0)
7128 goto errout;
7129 err = rtnl_register_module(THIS_MODULE, PF_INET6, RTM_DELADDR,
7130 inet6_rtm_deladdr, NULL, 0);
7131 if (err < 0)
7132 goto errout;
7133 err = rtnl_register_module(THIS_MODULE, PF_INET6, RTM_GETADDR,
7134 inet6_rtm_getaddr, inet6_dump_ifaddr,
7135 RTNL_FLAG_DOIT_UNLOCKED);
7136 if (err < 0)
7137 goto errout;
7138 err = rtnl_register_module(THIS_MODULE, PF_INET6, RTM_GETMULTICAST,
7139 NULL, inet6_dump_ifmcaddr, 0);
7140 if (err < 0)
7141 goto errout;
7142 err = rtnl_register_module(THIS_MODULE, PF_INET6, RTM_GETANYCAST,
7143 NULL, inet6_dump_ifacaddr, 0);
7144 if (err < 0)
7145 goto errout;
7146 err = rtnl_register_module(THIS_MODULE, PF_INET6, RTM_GETNETCONF,
7147 inet6_netconf_get_devconf,
7148 inet6_netconf_dump_devconf,
7149 RTNL_FLAG_DOIT_UNLOCKED);
7150 if (err < 0)
7151 goto errout;
Florian Westphala3fde2a2017-12-04 19:19:18 +01007152 err = ipv6_addr_label_rtnl_register();
7153 if (err < 0)
7154 goto errout;
YOSHIFUJI Hideaki2a8cc6c2007-11-14 15:56:23 +09007155
Linus Torvalds1da177e2005-04-16 15:20:36 -07007156 return 0;
Thomas Grafc127ea22007-03-22 11:58:32 -07007157errout:
Florian Westphal16feebc2017-12-02 21:44:08 +01007158 rtnl_unregister_all(PF_INET6);
Thomas Grafb382b192010-11-16 04:33:57 +00007159 rtnl_af_unregister(&inet6_ops);
Thomas Grafc127ea22007-03-22 11:58:32 -07007160 unregister_netdevice_notifier(&ipv6_dev_notf);
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08007161errlo:
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01007162 destroy_workqueue(addrconf_wq);
7163out_nowq:
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08007164 unregister_pernet_subsys(&addrconf_ops);
Neil Horman2cc6d2b2010-09-24 09:55:52 +00007165out_addrlabel:
7166 ipv6_addr_label_cleanup();
7167out:
Thomas Grafc127ea22007-03-22 11:58:32 -07007168 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007169}
7170
Daniel Lezcano09f77092007-12-13 05:34:58 -08007171void addrconf_cleanup(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007172{
Daniel Lezcano176c39a2009-03-03 01:06:45 -08007173 struct net_device *dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007174 int i;
7175
7176 unregister_netdevice_notifier(&ipv6_dev_notf);
Pavel Emelyanove0da5a42008-01-10 17:42:55 -08007177 unregister_pernet_subsys(&addrconf_ops);
Neil Horman2cc6d2b2010-09-24 09:55:52 +00007178 ipv6_addr_label_cleanup();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007179
Florian Westphal5c451212017-10-04 15:58:49 +02007180 rtnl_af_unregister(&inet6_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007181
Florian Westphal5c451212017-10-04 15:58:49 +02007182 rtnl_lock();
Thomas Grafb382b192010-11-16 04:33:57 +00007183
Daniel Lezcano176c39a2009-03-03 01:06:45 -08007184 /* clean dev list */
7185 for_each_netdev(&init_net, dev) {
7186 if (__in6_dev_get(dev) == NULL)
7187 continue;
7188 addrconf_ifdown(dev, 1);
7189 }
7190 addrconf_ifdown(init_net.loopback_dev, 2);
7191
Linus Torvalds1da177e2005-04-16 15:20:36 -07007192 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07007193 * Check hash table.
7194 */
stephen hemminger5c578aed2010-03-17 20:31:11 +00007195 spin_lock_bh(&addrconf_hash_lock);
stephen hemmingerc2e21292010-03-17 20:31:10 +00007196 for (i = 0; i < IN6_ADDR_HSIZE; i++)
7197 WARN_ON(!hlist_empty(&inet6_addr_lst[i]));
stephen hemminger5c578aed2010-03-17 20:31:11 +00007198 spin_unlock_bh(&addrconf_hash_lock);
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01007199 cancel_delayed_work(&addr_chk_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007200 rtnl_unlock();
Hannes Frederic Sowac15b1cc2014-03-27 18:28:07 +01007201
7202 destroy_workqueue(addrconf_wq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007203}