Blame view

net/ipv6/addrconf.c 130 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
  /*
   *	IPv6 Address [auto]configuration
   *	Linux INET6 implementation
   *
   *	Authors:
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
6
   *	Pedro Roque		<roque@di.fc.ul.pt>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
8
   *	Alexey Kuznetsov	<kuznet@ms2.inr.ac.ru>
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
   *	This program is free software; you can redistribute it and/or
   *      modify it under the terms of the GNU General Public License
   *      as published by the Free Software Foundation; either version
   *      2 of the License, or (at your option) any later version.
   */
  
  /*
   *	Changes:
   *
   *	Janos Farkas			:	delete timer on ifdown
   *	<chexum@bankinf.banki.hu>
   *	Andi Kleen			:	kill double kfree on module
   *						unload.
   *	Maciej W. Rozycki		:	FDDI support
   *	sekiya@USAGI			:	Don't send too many RS
   *						packets.
   *	yoshfuji@USAGI			:       Fixed interval between DAD
   *						packets.
   *	YOSHIFUJI Hideaki @USAGI	:	improved accuracy of
   *						address validation timer.
   *	YOSHIFUJI Hideaki @USAGI	:	Privacy Extensions (RFC3041)
   *						support.
   *	Yuji SEKIYA @USAGI		:	Don't assign a same IPv6
   *						address on a same interface.
   *	YOSHIFUJI Hideaki @USAGI	:	ARCnet support
   *	YOSHIFUJI Hideaki @USAGI	:	convert /proc/net/if_inet6 to
   *						seq_file.
b1cacb682   YOSHIFUJI Hideaki   [IPV6]: Make ipv6...
36
37
38
   *	YOSHIFUJI Hideaki @USAGI	:	improved source address
   *						selection; consider scope,
   *						status etc.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
   */
f32138319   Joe Perches   net: ipv6: Standa...
40
  #define pr_fmt(fmt) "IPv6: " fmt
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
  #include <linux/errno.h>
  #include <linux/types.h>
a0bffffc1   Ilpo Järvinen   net/*: use linux/...
43
  #include <linux/kernel.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
45
  #include <linux/socket.h>
  #include <linux/sockios.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
47
48
  #include <linux/net.h>
  #include <linux/in6.h>
  #include <linux/netdevice.h>
1823730fb   Thomas Graf   [IPv4]: Move inte...
49
  #include <linux/if_addr.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
51
52
53
54
55
  #include <linux/if_arp.h>
  #include <linux/if_arcnet.h>
  #include <linux/if_infiniband.h>
  #include <linux/route.h>
  #include <linux/inetdevice.h>
  #include <linux/init.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
56
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
58
59
  #ifdef CONFIG_SYSCTL
  #include <linux/sysctl.h>
  #endif
4fc268d24   Randy Dunlap   [PATCH] capable/c...
60
  #include <linux/capability.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
61
62
  #include <linux/delay.h>
  #include <linux/notifier.h>
543537bd9   Paulo Marques   [PATCH] create a ...
63
  #include <linux/string.h>
ddbe50320   Eric Dumazet   ipv6: add ipv6_ad...
64
  #include <linux/hash.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65

457c4cbc5   Eric W. Biederman   [NET]: Make /proc...
66
  #include <net/net_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
68
  #include <net/sock.h>
  #include <net/snmp.h>
06a4c1c55   alex.bluesman.smirnov@gmail.com   6lowpan: IPv6 lin...
69
  #include <net/af_ieee802154.h>
cb6bf3550   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
70
  #include <net/firewire.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
72
73
74
75
76
77
  #include <net/ipv6.h>
  #include <net/protocol.h>
  #include <net/ndisc.h>
  #include <net/ip6_route.h>
  #include <net/addrconf.h>
  #include <net/tcp.h>
  #include <net/ip.h>
5d6202664   Thomas Graf   [IPv6] address: C...
78
  #include <net/netlink.h>
f24e3d658   Mitsuru Chinen   [IPV6]: Defer IPv...
79
  #include <net/pkt_sched.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80
81
  #include <linux/if_tunnel.h>
  #include <linux/rtnetlink.h>
f3a1bfb11   Nicolas Dichtel   rtnl/ipv6: use ne...
82
  #include <linux/netconf.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
  #include <linux/random.h>
e21e8467d   Stephen Hemminger   addrconf: checkpa...
84
  #include <linux/uaccess.h>
7f7d9a6b9   Herbert Xu   [IPV6]: Consolida...
85
  #include <asm/unaligned.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
87
88
  
  #include <linux/proc_fs.h>
  #include <linux/seq_file.h>
bc3b2d7fb   Paul Gortmaker   net: Add export.h...
89
  #include <linux/export.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
91
92
93
94
  
  /* Set to 3 to get tracing... */
  #define ACONF_DEBUG 2
  
  #if ACONF_DEBUG >= 3
ba3542e15   dingtianhong   ipv6: convert the...
95
  #define ADBG(fmt, ...) printk(fmt, ##__VA_ARGS__)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
  #else
ba3542e15   dingtianhong   ipv6: convert the...
97
  #define ADBG(fmt, ...) do { if (0) printk(fmt, ##__VA_ARGS__); } while (0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
99
100
  #endif
  
  #define	INFINITY_LIFE_TIME	0xFFFFFFFF
18a31e1e2   Thomas Graf   ipv6: Expose reac...
101
102
103
104
105
  
  static inline u32 cstamp_delta(unsigned long cstamp)
  {
  	return (cstamp - INITIAL_JIFFIES) * 100UL / HZ;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
106
107
  
  #ifdef CONFIG_SYSCTL
f52295a9c   Pavel Emelyanov   [IPV6]: Unify and...
108
  static void addrconf_sysctl_register(struct inet6_dev *idev);
408c4768c   Pavel Emelyanov   [NETNS]: Clean ou...
109
110
111
112
113
114
115
116
117
  static void addrconf_sysctl_unregister(struct inet6_dev *idev);
  #else
  static inline void addrconf_sysctl_register(struct inet6_dev *idev)
  {
  }
  
  static inline void addrconf_sysctl_unregister(struct inet6_dev *idev)
  {
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118
  #endif
eb7e05759   Sorin Dumitru   ipv6: remove some...
119
120
  static void __ipv6_regen_rndid(struct inet6_dev *idev);
  static void __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
  static void ipv6_regen_rndid(unsigned long data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122

1b34be74c   YOSHIFUJI Hideaki   ipv6 addrconf: ad...
123
  static int ipv6_generate_eui64(u8 *eui, struct net_device *dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124
125
126
127
128
  static int ipv6_count_addresses(struct inet6_dev *idev);
  
  /*
   *	Configured unicast address hash table
   */
c2e21293c   stephen hemminger   ipv6: convert add...
129
  static struct hlist_head inet6_addr_lst[IN6_ADDR_HSIZE];
5c578aedc   stephen hemminger   IPv6: convert add...
130
  static DEFINE_SPINLOCK(addrconf_hash_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131

c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
132
133
134
  static void addrconf_verify(void);
  static void addrconf_verify_rtnl(void);
  static void addrconf_verify_work(struct work_struct *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
135

c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
136
137
  static struct workqueue_struct *addrconf_wq;
  static DECLARE_DELAYED_WORK(addr_chk_work, addrconf_verify_work);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
138
139
140
  
  static void addrconf_join_anycast(struct inet6_ifaddr *ifp);
  static void addrconf_leave_anycast(struct inet6_ifaddr *ifp);
93d9b7d7a   Jiri Pirko   net: rename notif...
141
142
  static void addrconf_type_change(struct net_device *dev,
  				 unsigned long event);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
  static int addrconf_ifdown(struct net_device *dev, int how);
21caa6622   Romain Kuntz   ipv6: use addrcon...
144
145
146
147
  static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx,
  						  int plen,
  						  const struct net_device *dev,
  						  u32 flags, u32 noflags);
cf22f9a2b   David S. Miller   ipv6: Remove unus...
148
  static void addrconf_dad_start(struct inet6_ifaddr *ifp);
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
149
  static void addrconf_dad_work(struct work_struct *w);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150
  static void addrconf_dad_completed(struct inet6_ifaddr *ifp);
c5e33bddd   YOSHIFUJI Hideaki   [IPV6]: Run DAD w...
151
  static void addrconf_dad_run(struct inet6_dev *idev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152
153
154
  static void addrconf_rs_timer(unsigned long data);
  static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa);
  static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa);
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
155
  static void inet6_prefix_notify(int event, struct inet6_dev *idev,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156
  				struct prefix_info *pinfo);
3e81c6da3   David S. Miller   ipv6: Fix bug in ...
157
158
  static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr,
  			       struct net_device *dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159

888c848ed   Adrian Bunk   ipv6: make struct...
160
  static struct ipv6_devconf ipv6_devconf __read_mostly = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
162
163
164
165
166
167
  	.forwarding		= 0,
  	.hop_limit		= IPV6_DEFAULT_HOPLIMIT,
  	.mtu6			= IPV6_MIN_MTU,
  	.accept_ra		= 1,
  	.accept_redirects	= 1,
  	.autoconf		= 1,
  	.force_mld_version	= 0,
fc4eba58b   Hannes Frederic Sowa   ipv6: make unsoli...
168
169
  	.mldv1_unsolicited_report_interval = 10 * HZ,
  	.mldv2_unsolicited_report_interval = HZ,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
171
172
173
  	.dad_transmits		= 1,
  	.rtr_solicits		= MAX_RTR_SOLICITATIONS,
  	.rtr_solicit_interval	= RTR_SOLICITATION_INTERVAL,
  	.rtr_solicit_delay	= MAX_RTR_SOLICITATION_DELAY,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174
175
176
177
178
  	.use_tempaddr 		= 0,
  	.temp_valid_lft		= TEMP_VALID_LIFETIME,
  	.temp_prefered_lft	= TEMP_PREFERRED_LIFETIME,
  	.regen_max_retry	= REGEN_MAX_RETRY,
  	.max_desync_factor	= MAX_DESYNC_FACTOR,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
  	.max_addresses		= IPV6_MAX_ADDRESSES,
65f5c7c11   YOSHIFUJI Hideaki   [IPV6]: ROUTE: Ad...
180
  	.accept_ra_defrtr	= 1,
c4fd30eb1   YOSHIFUJI Hideaki   [IPV6]: ADDRCONF:...
181
  	.accept_ra_pinfo	= 1,
930d6ff2e   YOSHIFUJI Hideaki   [IPV6]: ROUTE: Ad...
182
183
  #ifdef CONFIG_IPV6_ROUTER_PREF
  	.accept_ra_rtr_pref	= 1,
52e163563   YOSHIFUJI Hideaki   [IPV6]: ROUTE: Ad...
184
  	.rtr_probe_interval	= 60 * HZ,
09c884d4c   YOSHIFUJI Hideaki   [IPV6]: ROUTE: Ad...
185
186
187
  #ifdef CONFIG_IPV6_ROUTE_INFO
  	.accept_ra_rt_info_max_plen = 0,
  #endif
930d6ff2e   YOSHIFUJI Hideaki   [IPV6]: ROUTE: Ad...
188
  #endif
fbea49e1e   YOSHIFUJI Hideaki   [IPV6] NDISC: Add...
189
  	.proxy_ndp		= 0,
0bcbc9262   YOSHIFUJI Hideaki   [IPV6]: Disallow ...
190
  	.accept_source_route	= 0,	/* we do not accept RH0 by default. */
778d80be5   YOSHIFUJI Hideaki   ipv6: Add disable...
191
  	.disable_ipv6		= 0,
1b34be74c   YOSHIFUJI Hideaki   ipv6 addrconf: ad...
192
  	.accept_dad		= 1,
b800c3b96   Hannes Frederic Sowa   ipv6: drop fragme...
193
  	.suppress_frag_ndisc	= 1,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
  };
ab32ea5d8   Brian Haley   [NET/IPV4/IPV6]: ...
195
  static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
196
197
198
199
200
201
  	.forwarding		= 0,
  	.hop_limit		= IPV6_DEFAULT_HOPLIMIT,
  	.mtu6			= IPV6_MIN_MTU,
  	.accept_ra		= 1,
  	.accept_redirects	= 1,
  	.autoconf		= 1,
fc4eba58b   Hannes Frederic Sowa   ipv6: make unsoli...
202
203
204
  	.force_mld_version	= 0,
  	.mldv1_unsolicited_report_interval = 10 * HZ,
  	.mldv2_unsolicited_report_interval = HZ,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
205
206
207
208
  	.dad_transmits		= 1,
  	.rtr_solicits		= MAX_RTR_SOLICITATIONS,
  	.rtr_solicit_interval	= RTR_SOLICITATION_INTERVAL,
  	.rtr_solicit_delay	= MAX_RTR_SOLICITATION_DELAY,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209
210
211
212
213
  	.use_tempaddr		= 0,
  	.temp_valid_lft		= TEMP_VALID_LIFETIME,
  	.temp_prefered_lft	= TEMP_PREFERRED_LIFETIME,
  	.regen_max_retry	= REGEN_MAX_RETRY,
  	.max_desync_factor	= MAX_DESYNC_FACTOR,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
  	.max_addresses		= IPV6_MAX_ADDRESSES,
65f5c7c11   YOSHIFUJI Hideaki   [IPV6]: ROUTE: Ad...
215
  	.accept_ra_defrtr	= 1,
c4fd30eb1   YOSHIFUJI Hideaki   [IPV6]: ADDRCONF:...
216
  	.accept_ra_pinfo	= 1,
930d6ff2e   YOSHIFUJI Hideaki   [IPV6]: ROUTE: Ad...
217
218
  #ifdef CONFIG_IPV6_ROUTER_PREF
  	.accept_ra_rtr_pref	= 1,
52e163563   YOSHIFUJI Hideaki   [IPV6]: ROUTE: Ad...
219
  	.rtr_probe_interval	= 60 * HZ,
09c884d4c   YOSHIFUJI Hideaki   [IPV6]: ROUTE: Ad...
220
221
222
  #ifdef CONFIG_IPV6_ROUTE_INFO
  	.accept_ra_rt_info_max_plen = 0,
  #endif
930d6ff2e   YOSHIFUJI Hideaki   [IPV6]: ROUTE: Ad...
223
  #endif
fbea49e1e   YOSHIFUJI Hideaki   [IPV6] NDISC: Add...
224
  	.proxy_ndp		= 0,
0bcbc9262   YOSHIFUJI Hideaki   [IPV6]: Disallow ...
225
  	.accept_source_route	= 0,	/* we do not accept RH0 by default. */
778d80be5   YOSHIFUJI Hideaki   ipv6: Add disable...
226
  	.disable_ipv6		= 0,
1b34be74c   YOSHIFUJI Hideaki   ipv6 addrconf: ad...
227
  	.accept_dad		= 1,
b800c3b96   Hannes Frederic Sowa   ipv6: drop fragme...
228
  	.suppress_frag_ndisc	= 1,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
229
  };
f24e3d658   Mitsuru Chinen   [IPV6]: Defer IPv...
230
  /* Check if a valid qdisc is available */
052979499   David S. Miller   pkt_sched: Add qd...
231
  static inline bool addrconf_qdisc_ok(const struct net_device *dev)
f24e3d658   Mitsuru Chinen   [IPV6]: Defer IPv...
232
  {
052979499   David S. Miller   pkt_sched: Add qd...
233
  	return !qdisc_tx_is_noop(dev);
f24e3d658   Mitsuru Chinen   [IPV6]: Defer IPv...
234
  }
b7b1bfce0   Hannes Frederic Sowa   ipv6: split dupli...
235
  static void addrconf_del_rs_timer(struct inet6_dev *idev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236
  {
b7b1bfce0   Hannes Frederic Sowa   ipv6: split dupli...
237
238
239
  	if (del_timer(&idev->rs_timer))
  		__in6_dev_put(idev);
  }
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
240
  static void addrconf_del_dad_work(struct inet6_ifaddr *ifp)
b7b1bfce0   Hannes Frederic Sowa   ipv6: split dupli...
241
  {
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
242
  	if (cancel_delayed_work(&ifp->dad_work))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
244
  		__in6_ifa_put(ifp);
  }
b7b1bfce0   Hannes Frederic Sowa   ipv6: split dupli...
245
246
247
248
249
250
251
  static void addrconf_mod_rs_timer(struct inet6_dev *idev,
  				  unsigned long when)
  {
  	if (!timer_pending(&idev->rs_timer))
  		in6_dev_hold(idev);
  	mod_timer(&idev->rs_timer, jiffies + when);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
252

c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
253
254
  static void addrconf_mod_dad_work(struct inet6_ifaddr *ifp,
  				   unsigned long delay)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
  {
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
256
  	if (!delayed_work_pending(&ifp->dad_work))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257
  		in6_ifa_hold(ifp);
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
258
  	mod_delayed_work(addrconf_wq, &ifp->dad_work, delay);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259
  }
7f7d9a6b9   Herbert Xu   [IPV6]: Consolida...
260
261
  static int snmp6_alloc_dev(struct inet6_dev *idev)
  {
827da44c6   John Stultz   net: Explicitly i...
262
  	int i;
7d720c3e4   Tejun Heo   percpu: add __per...
263
  	if (snmp_mib_init((void __percpu **)idev->stats.ipv6,
1823e4c80   Eric Dumazet   snmp: add align p...
264
265
  			  sizeof(struct ipstats_mib),
  			  __alignof__(struct ipstats_mib)) < 0)
7f7d9a6b9   Herbert Xu   [IPV6]: Consolida...
266
  		goto err_ip;
827da44c6   John Stultz   net: Explicitly i...
267
268
269
270
271
272
273
274
275
276
  
  	for_each_possible_cpu(i) {
  		struct ipstats_mib *addrconf_stats;
  		addrconf_stats = per_cpu_ptr(idev->stats.ipv6[0], i);
  		u64_stats_init(&addrconf_stats->syncp);
  #if SNMP_ARRAY_SZ == 2
  		addrconf_stats = per_cpu_ptr(idev->stats.ipv6[1], i);
  		u64_stats_init(&addrconf_stats->syncp);
  #endif
  	}
be281e554   Eric Dumazet   ipv6: reduce per ...
277
278
279
  	idev->stats.icmpv6dev = kzalloc(sizeof(struct icmpv6_mib_device),
  					GFP_KERNEL);
  	if (!idev->stats.icmpv6dev)
7f7d9a6b9   Herbert Xu   [IPV6]: Consolida...
280
  		goto err_icmp;
be281e554   Eric Dumazet   ipv6: reduce per ...
281
282
283
  	idev->stats.icmpv6msgdev = kzalloc(sizeof(struct icmpv6msg_mib_device),
  					   GFP_KERNEL);
  	if (!idev->stats.icmpv6msgdev)
14878f75a   David L Stevens   [IPV6]: Add ICMPM...
284
  		goto err_icmpmsg;
7f7d9a6b9   Herbert Xu   [IPV6]: Consolida...
285
286
  
  	return 0;
14878f75a   David L Stevens   [IPV6]: Add ICMPM...
287
  err_icmpmsg:
be281e554   Eric Dumazet   ipv6: reduce per ...
288
  	kfree(idev->stats.icmpv6dev);
7f7d9a6b9   Herbert Xu   [IPV6]: Consolida...
289
  err_icmp:
7d720c3e4   Tejun Heo   percpu: add __per...
290
  	snmp_mib_free((void __percpu **)idev->stats.ipv6);
7f7d9a6b9   Herbert Xu   [IPV6]: Consolida...
291
  err_ip:
aaf70ec7f   Pavel Emelyanov   [IPV6]: Cleanup s...
292
  	return -ENOMEM;
7f7d9a6b9   Herbert Xu   [IPV6]: Consolida...
293
  }
8e5e8f30d   Eldad Zack   net/ipv6/addrconf...
294
  static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295
296
297
298
299
300
301
  {
  	struct inet6_dev *ndev;
  
  	ASSERT_RTNL();
  
  	if (dev->mtu < IPV6_MIN_MTU)
  		return NULL;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
302
  	ndev = kzalloc(sizeof(struct inet6_dev), GFP_KERNEL);
322f74a43   Ingo Oeser   [IPV6]: Cleanups ...
303

1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
304
305
  	if (ndev == NULL)
  		return NULL;
322f74a43   Ingo Oeser   [IPV6]: Cleanups ...
306
307
308
  
  	rwlock_init(&ndev->lock);
  	ndev->dev = dev;
502a2ffd7   stephen hemminger   ipv6: convert ide...
309
  	INIT_LIST_HEAD(&ndev->addr_list);
b7b1bfce0   Hannes Frederic Sowa   ipv6: split dupli...
310
311
  	setup_timer(&ndev->rs_timer, addrconf_rs_timer,
  		    (unsigned long)ndev);
c346dca10   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
312
  	memcpy(&ndev->cnf, dev_net(dev)->ipv6.devconf_dflt, sizeof(ndev->cnf));
322f74a43   Ingo Oeser   [IPV6]: Cleanups ...
313
314
315
316
317
318
319
  	ndev->cnf.mtu6 = dev->mtu;
  	ndev->cnf.sysctl = NULL;
  	ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl);
  	if (ndev->nd_parms == NULL) {
  		kfree(ndev);
  		return NULL;
  	}
0187bdfb0   Ben Hutchings   net: Disable LRO ...
320
321
  	if (ndev->cnf.forwarding)
  		dev_disable_lro(dev);
322f74a43   Ingo Oeser   [IPV6]: Cleanups ...
322
323
  	/* We refer to the device */
  	dev_hold(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
324

322f74a43   Ingo Oeser   [IPV6]: Cleanups ...
325
  	if (snmp6_alloc_dev(ndev) < 0) {
ba3542e15   dingtianhong   ipv6: convert the...
326
  		ADBG(KERN_WARNING
f32138319   Joe Perches   net: ipv6: Standa...
327
328
  			"%s: cannot allocate memory for statistics; dev=%s.
  ",
ba3542e15   dingtianhong   ipv6: convert the...
329
  			__func__, dev->name);
322f74a43   Ingo Oeser   [IPV6]: Cleanups ...
330
  		neigh_parms_release(&nd_tbl, ndev->nd_parms);
8603e33d0   Roy Li   ipv6: fix a possi...
331
332
  		dev_put(dev);
  		kfree(ndev);
322f74a43   Ingo Oeser   [IPV6]: Cleanups ...
333
334
  		return NULL;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335

322f74a43   Ingo Oeser   [IPV6]: Cleanups ...
336
  	if (snmp6_register_dev(ndev) < 0) {
ba3542e15   dingtianhong   ipv6: convert the...
337
  		ADBG(KERN_WARNING
f32138319   Joe Perches   net: ipv6: Standa...
338
339
  			"%s: cannot create /proc/net/dev_snmp6/%s
  ",
ba3542e15   dingtianhong   ipv6: convert the...
340
  			__func__, dev->name);
322f74a43   Ingo Oeser   [IPV6]: Cleanups ...
341
342
343
344
345
346
347
348
349
350
  		neigh_parms_release(&nd_tbl, ndev->nd_parms);
  		ndev->dead = 1;
  		in6_dev_finish_destroy(ndev);
  		return NULL;
  	}
  
  	/* One reference from device.  We must do this before
  	 * we invoke __ipv6_regen_rndid().
  	 */
  	in6_dev_hold(ndev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351

1b34be74c   YOSHIFUJI Hideaki   ipv6 addrconf: ad...
352
353
  	if (dev->flags & (IFF_NOARP | IFF_LOOPBACK))
  		ndev->cnf.accept_dad = -1;
07a936260   Amerigo Wang   ipv6: use IS_ENAB...
354
  #if IS_ENABLED(CONFIG_IPV6_SIT)
b077d7aba   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
355
  	if (dev->type == ARPHRD_SIT && (dev->priv_flags & IFF_ISATAP)) {
f32138319   Joe Perches   net: ipv6: Standa...
356
357
  		pr_info("%s: Disabled Multicast RS
  ", dev->name);
b077d7aba   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
358
359
360
  		ndev->cnf.rtr_solicits = 0;
  	}
  #endif
372e6c8f1   stephen hemminger   ipv6: convert tem...
361
  	INIT_LIST_HEAD(&ndev->tempaddr_list);
b24b8a247   Pavel Emelyanov   [NET]: Convert in...
362
  	setup_timer(&ndev->regen_timer, ipv6_regen_rndid, (unsigned long)ndev);
322f74a43   Ingo Oeser   [IPV6]: Cleanups ...
363
364
  	if ((dev->flags&IFF_LOOPBACK) ||
  	    dev->type == ARPHRD_TUNNEL ||
9625ed72e   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
365
  	    dev->type == ARPHRD_TUNNEL6 ||
0be669bb3   Joerg Roedel   [IPV6]: Seperate ...
366
  	    dev->type == ARPHRD_SIT ||
0be669bb3   Joerg Roedel   [IPV6]: Seperate ...
367
  	    dev->type == ARPHRD_NONE) {
322f74a43   Ingo Oeser   [IPV6]: Cleanups ...
368
369
370
371
372
  		ndev->cnf.use_tempaddr = -1;
  	} else {
  		in6_dev_hold(ndev);
  		ipv6_regen_rndid((unsigned long) ndev);
  	}
5d9efa7ee   David S. Miller   ipv6: Remove priv...
373

914faa147   Daniel Borkmann   net: ipv6: minor:...
374
  	ndev->token = in6addr_any;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
375

f24e3d658   Mitsuru Chinen   [IPV6]: Defer IPv...
376
  	if (netif_running(dev) && addrconf_qdisc_ok(dev))
53aadcc90   Herbert Xu   [IPV6]: Set IF_RE...
377
  		ndev->if_flags |= IF_READY;
322f74a43   Ingo Oeser   [IPV6]: Cleanups ...
378
379
  	ipv6_mc_init_dev(ndev);
  	ndev->tstamp = jiffies;
f52295a9c   Pavel Emelyanov   [IPV6]: Unify and...
380
  	addrconf_sysctl_register(ndev);
30c4cf577   David L Stevens   [IPV4/IPV6]: Fix ...
381
  	/* protected by rtnl_lock */
cf778b00e   Eric Dumazet   net: reintroduce ...
382
  	rcu_assign_pointer(dev->ip6_ptr, ndev);
d88ae4cc9   YOSHIFUJI Hideaki   [IPV6] MCAST: Fix...
383

2c5e89338   Hannes Frederic Sowa   ipv6: by default ...
384
385
  	/* Join interface-local all-node multicast group */
  	ipv6_dev_mc_inc(dev, &in6addr_interfacelocal_allnodes);
d88ae4cc9   YOSHIFUJI Hideaki   [IPV6] MCAST: Fix...
386
  	/* Join all-node multicast group */
f3ee4010e   YOSHIFUJI Hideaki   [IPV6]: Define co...
387
  	ipv6_dev_mc_inc(dev, &in6addr_linklocal_allnodes);
d88ae4cc9   YOSHIFUJI Hideaki   [IPV6] MCAST: Fix...
388

d6ddef9e6   Li Wei   IPv6: Fix not joi...
389
  	/* Join all-router multicast group if forwarding is set */
8b2aaedee   Li Wei   ipv6: Fix Smatch ...
390
  	if (ndev->cnf.forwarding && (dev->flags & IFF_MULTICAST))
d6ddef9e6   Li Wei   IPv6: Fix not joi...
391
  		ipv6_dev_mc_inc(dev, &in6addr_linklocal_allrouters);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
392
393
  	return ndev;
  }
8e5e8f30d   Eldad Zack   net/ipv6/addrconf...
394
  static struct inet6_dev *ipv6_find_idev(struct net_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
396
397
398
  {
  	struct inet6_dev *idev;
  
  	ASSERT_RTNL();
e21e8467d   Stephen Hemminger   addrconf: checkpa...
399
400
401
402
  	idev = __in6_dev_get(dev);
  	if (!idev) {
  		idev = ipv6_add_dev(dev);
  		if (!idev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
404
  			return NULL;
  	}
c5e33bddd   YOSHIFUJI Hideaki   [IPV6]: Run DAD w...
405

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
406
407
408
409
  	if (dev->flags&IFF_UP)
  		ipv6_mc_up(idev);
  	return idev;
  }
f3a1bfb11   Nicolas Dichtel   rtnl/ipv6: use ne...
410
411
412
413
  static int inet6_netconf_msgsize_devconf(int type)
  {
  	int size =  NLMSG_ALIGN(sizeof(struct netconfmsg))
  		    + nla_total_size(4);	/* NETCONFA_IFINDEX */
76f8f6cb7   Nicolas Dichtel   rtnl/ipv6: add su...
414
415
  	/* type -1 is used for ALL */
  	if (type == -1 || type == NETCONFA_FORWARDING)
f3a1bfb11   Nicolas Dichtel   rtnl/ipv6: use ne...
416
  		size += nla_total_size(4);
b1afce953   David S. Miller   ipv6: Protect ->m...
417
  #ifdef CONFIG_IPV6_MROUTE
d67b8c616   Nicolas Dichtel   netconf: advertis...
418
419
  	if (type == -1 || type == NETCONFA_MC_FORWARDING)
  		size += nla_total_size(4);
b1afce953   David S. Miller   ipv6: Protect ->m...
420
  #endif
c92d5491a   stephen hemminger   netconf: add supp...
421
422
  	if (type == -1 || type == NETCONFA_PROXY_NEIGH)
  		size += nla_total_size(4);
f3a1bfb11   Nicolas Dichtel   rtnl/ipv6: use ne...
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
  
  	return size;
  }
  
  static int inet6_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
  				      struct ipv6_devconf *devconf, u32 portid,
  				      u32 seq, int event, unsigned int flags,
  				      int type)
  {
  	struct nlmsghdr  *nlh;
  	struct netconfmsg *ncm;
  
  	nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct netconfmsg),
  			flags);
  	if (nlh == NULL)
  		return -EMSGSIZE;
  
  	ncm = nlmsg_data(nlh);
  	ncm->ncm_family = AF_INET6;
  
  	if (nla_put_s32(skb, NETCONFA_IFINDEX, ifindex) < 0)
  		goto nla_put_failure;
76f8f6cb7   Nicolas Dichtel   rtnl/ipv6: add su...
445
446
  	/* type -1 is used for ALL */
  	if ((type == -1 || type == NETCONFA_FORWARDING) &&
f3a1bfb11   Nicolas Dichtel   rtnl/ipv6: use ne...
447
448
  	    nla_put_s32(skb, NETCONFA_FORWARDING, devconf->forwarding) < 0)
  		goto nla_put_failure;
b1afce953   David S. Miller   ipv6: Protect ->m...
449
  #ifdef CONFIG_IPV6_MROUTE
d67b8c616   Nicolas Dichtel   netconf: advertis...
450
451
452
453
  	if ((type == -1 || type == NETCONFA_MC_FORWARDING) &&
  	    nla_put_s32(skb, NETCONFA_MC_FORWARDING,
  			devconf->mc_forwarding) < 0)
  		goto nla_put_failure;
b1afce953   David S. Miller   ipv6: Protect ->m...
454
  #endif
c92d5491a   stephen hemminger   netconf: add supp...
455
456
457
  	if ((type == -1 || type == NETCONFA_PROXY_NEIGH) &&
  	    nla_put_s32(skb, NETCONFA_PROXY_NEIGH, devconf->proxy_ndp) < 0)
  		goto nla_put_failure;
f3a1bfb11   Nicolas Dichtel   rtnl/ipv6: use ne...
458
459
460
461
462
463
  	return nlmsg_end(skb, nlh);
  
  nla_put_failure:
  	nlmsg_cancel(skb, nlh);
  	return -EMSGSIZE;
  }
d67b8c616   Nicolas Dichtel   netconf: advertis...
464
465
  void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex,
  				  struct ipv6_devconf *devconf)
f3a1bfb11   Nicolas Dichtel   rtnl/ipv6: use ne...
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
  {
  	struct sk_buff *skb;
  	int err = -ENOBUFS;
  
  	skb = nlmsg_new(inet6_netconf_msgsize_devconf(type), GFP_ATOMIC);
  	if (skb == NULL)
  		goto errout;
  
  	err = inet6_netconf_fill_devconf(skb, ifindex, devconf, 0, 0,
  					 RTM_NEWNETCONF, 0, type);
  	if (err < 0) {
  		/* -EMSGSIZE implies BUG in inet6_netconf_msgsize_devconf() */
  		WARN_ON(err == -EMSGSIZE);
  		kfree_skb(skb);
  		goto errout;
  	}
  	rtnl_notify(skb, net, 0, RTNLGRP_IPV6_NETCONF, NULL, GFP_ATOMIC);
  	return;
  errout:
bd7790286   Cong Ding   ipv6: addrconf.c:...
485
  	rtnl_set_sk_err(net, RTNLGRP_IPV6_NETCONF, err);
f3a1bfb11   Nicolas Dichtel   rtnl/ipv6: use ne...
486
  }
76f8f6cb7   Nicolas Dichtel   rtnl/ipv6: add su...
487
488
489
  static const struct nla_policy devconf_ipv6_policy[NETCONFA_MAX+1] = {
  	[NETCONFA_IFINDEX]	= { .len = sizeof(int) },
  	[NETCONFA_FORWARDING]	= { .len = sizeof(int) },
c92d5491a   stephen hemminger   netconf: add supp...
490
  	[NETCONFA_PROXY_NEIGH]	= { .len = sizeof(int) },
76f8f6cb7   Nicolas Dichtel   rtnl/ipv6: add su...
491
492
493
  };
  
  static int inet6_netconf_get_devconf(struct sk_buff *in_skb,
661d2967b   Thomas Graf   rtnetlink: Remove...
494
  				     struct nlmsghdr *nlh)
76f8f6cb7   Nicolas Dichtel   rtnl/ipv6: add su...
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
  {
  	struct net *net = sock_net(in_skb->sk);
  	struct nlattr *tb[NETCONFA_MAX+1];
  	struct netconfmsg *ncm;
  	struct sk_buff *skb;
  	struct ipv6_devconf *devconf;
  	struct inet6_dev *in6_dev;
  	struct net_device *dev;
  	int ifindex;
  	int err;
  
  	err = nlmsg_parse(nlh, sizeof(*ncm), tb, NETCONFA_MAX,
  			  devconf_ipv6_policy);
  	if (err < 0)
  		goto errout;
  
  	err = EINVAL;
  	if (!tb[NETCONFA_IFINDEX])
  		goto errout;
  
  	ifindex = nla_get_s32(tb[NETCONFA_IFINDEX]);
  	switch (ifindex) {
  	case NETCONFA_IFINDEX_ALL:
  		devconf = net->ipv6.devconf_all;
  		break;
  	case NETCONFA_IFINDEX_DEFAULT:
  		devconf = net->ipv6.devconf_dflt;
  		break;
  	default:
  		dev = __dev_get_by_index(net, ifindex);
  		if (dev == NULL)
  			goto errout;
  		in6_dev = __in6_dev_get(dev);
  		if (in6_dev == NULL)
  			goto errout;
  		devconf = &in6_dev->cnf;
  		break;
  	}
  
  	err = -ENOBUFS;
  	skb = nlmsg_new(inet6_netconf_msgsize_devconf(-1), GFP_ATOMIC);
  	if (skb == NULL)
  		goto errout;
  
  	err = inet6_netconf_fill_devconf(skb, ifindex, devconf,
  					 NETLINK_CB(in_skb).portid,
  					 nlh->nlmsg_seq, RTM_NEWNETCONF, 0,
  					 -1);
  	if (err < 0) {
  		/* -EMSGSIZE implies BUG in inet6_netconf_msgsize_devconf() */
  		WARN_ON(err == -EMSGSIZE);
  		kfree_skb(skb);
  		goto errout;
  	}
  	err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
  errout:
  	return err;
  }
7a6742003   Nicolas Dichtel   netconf: add the ...
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
  static int inet6_netconf_dump_devconf(struct sk_buff *skb,
  				      struct netlink_callback *cb)
  {
  	struct net *net = sock_net(skb->sk);
  	int h, s_h;
  	int idx, s_idx;
  	struct net_device *dev;
  	struct inet6_dev *idev;
  	struct hlist_head *head;
  
  	s_h = cb->args[0];
  	s_idx = idx = cb->args[1];
  
  	for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
  		idx = 0;
  		head = &net->dev_index_head[h];
  		rcu_read_lock();
63998ac24   Nicolas Dichtel   ipv6: provide add...
570
571
  		cb->seq = atomic_read(&net->ipv6.dev_addr_genid) ^
  			  net->dev_base_seq;
7a6742003   Nicolas Dichtel   netconf: add the ...
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
  		hlist_for_each_entry_rcu(dev, head, index_hlist) {
  			if (idx < s_idx)
  				goto cont;
  			idev = __in6_dev_get(dev);
  			if (!idev)
  				goto cont;
  
  			if (inet6_netconf_fill_devconf(skb, dev->ifindex,
  						       &idev->cnf,
  						       NETLINK_CB(cb->skb).portid,
  						       cb->nlh->nlmsg_seq,
  						       RTM_NEWNETCONF,
  						       NLM_F_MULTI,
  						       -1) <= 0) {
  				rcu_read_unlock();
  				goto done;
  			}
63998ac24   Nicolas Dichtel   ipv6: provide add...
589
  			nl_dump_check_consistent(cb, nlmsg_hdr(skb));
7a6742003   Nicolas Dichtel   netconf: add the ...
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
  cont:
  			idx++;
  		}
  		rcu_read_unlock();
  	}
  	if (h == NETDEV_HASHENTRIES) {
  		if (inet6_netconf_fill_devconf(skb, NETCONFA_IFINDEX_ALL,
  					       net->ipv6.devconf_all,
  					       NETLINK_CB(cb->skb).portid,
  					       cb->nlh->nlmsg_seq,
  					       RTM_NEWNETCONF, NLM_F_MULTI,
  					       -1) <= 0)
  			goto done;
  		else
  			h++;
  	}
  	if (h == NETDEV_HASHENTRIES + 1) {
  		if (inet6_netconf_fill_devconf(skb, NETCONFA_IFINDEX_DEFAULT,
  					       net->ipv6.devconf_dflt,
  					       NETLINK_CB(cb->skb).portid,
  					       cb->nlh->nlmsg_seq,
  					       RTM_NEWNETCONF, NLM_F_MULTI,
  					       -1) <= 0)
  			goto done;
  		else
  			h++;
  	}
  done:
  	cb->args[0] = h;
  	cb->args[1] = idx;
  
  	return skb->len;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
623
624
625
626
627
  #ifdef CONFIG_SYSCTL
  static void dev_forward_change(struct inet6_dev *idev)
  {
  	struct net_device *dev;
  	struct inet6_ifaddr *ifa;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
628
629
630
631
  
  	if (!idev)
  		return;
  	dev = idev->dev;
0187bdfb0   Ben Hutchings   net: Disable LRO ...
632
633
  	if (idev->cnf.forwarding)
  		dev_disable_lro(dev);
1a9408355   Amerigo Wang   ipv6: remove a us...
634
  	if (dev->flags & IFF_MULTICAST) {
2c5e89338   Hannes Frederic Sowa   ipv6: by default ...
635
  		if (idev->cnf.forwarding) {
f3ee4010e   YOSHIFUJI Hideaki   [IPV6]: Define co...
636
  			ipv6_dev_mc_inc(dev, &in6addr_linklocal_allrouters);
2c5e89338   Hannes Frederic Sowa   ipv6: by default ...
637
638
639
  			ipv6_dev_mc_inc(dev, &in6addr_interfacelocal_allrouters);
  			ipv6_dev_mc_inc(dev, &in6addr_sitelocal_allrouters);
  		} else {
f3ee4010e   YOSHIFUJI Hideaki   [IPV6]: Define co...
640
  			ipv6_dev_mc_dec(dev, &in6addr_linklocal_allrouters);
2c5e89338   Hannes Frederic Sowa   ipv6: by default ...
641
642
643
  			ipv6_dev_mc_dec(dev, &in6addr_interfacelocal_allrouters);
  			ipv6_dev_mc_dec(dev, &in6addr_sitelocal_allrouters);
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
644
  	}
502a2ffd7   stephen hemminger   ipv6: convert ide...
645
646
  
  	list_for_each_entry(ifa, &idev->addr_list, if_list) {
2c12a74cc   Michal Wrobel   [IPV6]: anycast r...
647
648
  		if (ifa->flags&IFA_F_TENTATIVE)
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
649
650
651
652
653
  		if (idev->cnf.forwarding)
  			addrconf_join_anycast(ifa);
  		else
  			addrconf_leave_anycast(ifa);
  	}
f3a1bfb11   Nicolas Dichtel   rtnl/ipv6: use ne...
654
655
  	inet6_netconf_notify_devconf(dev_net(dev), NETCONFA_FORWARDING,
  				     dev->ifindex, &idev->cnf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
656
  }
e186932b3   Pavel Emelyanov   [NETNS]: Use the ...
657
  static void addrconf_forward_change(struct net *net, __s32 newf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
658
659
660
  {
  	struct net_device *dev;
  	struct inet6_dev *idev;
4acd4945c   Ben Hutchings   ipv6: addrconf: A...
661
  	for_each_netdev(net, dev) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
662
663
  		idev = __in6_dev_get(dev);
  		if (idev) {
e186932b3   Pavel Emelyanov   [NETNS]: Use the ...
664
665
  			int changed = (!idev->cnf.forwarding) ^ (!newf);
  			idev->cnf.forwarding = newf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666
667
668
  			if (changed)
  				dev_forward_change(idev);
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
669
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
670
  }
c8fecf224   Pavel Emelyanov   [IPV6]: Eliminate...
671

013d97e9d   Francesco Ruggeri   net: race conditi...
672
  static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf)
c8fecf224   Pavel Emelyanov   [IPV6]: Eliminate...
673
  {
bff16c2f9   Pavel Emelyanov   [NETNS]: Make the...
674
  	struct net *net;
013d97e9d   Francesco Ruggeri   net: race conditi...
675
676
677
678
  	int old;
  
  	if (!rtnl_trylock())
  		return restart_syscall();
bff16c2f9   Pavel Emelyanov   [NETNS]: Make the...
679
680
  
  	net = (struct net *)table->extra2;
013d97e9d   Francesco Ruggeri   net: race conditi...
681
682
  	old = *p;
  	*p = newf;
b325fddb7   Stephen Hemminger   ipv6: Fix sysctl ...
683

013d97e9d   Francesco Ruggeri   net: race conditi...
684
  	if (p == &net->ipv6.devconf_dflt->forwarding) {
f3a1bfb11   Nicolas Dichtel   rtnl/ipv6: use ne...
685
686
687
688
  		if ((!newf) ^ (!old))
  			inet6_netconf_notify_devconf(net, NETCONFA_FORWARDING,
  						     NETCONFA_IFINDEX_DEFAULT,
  						     net->ipv6.devconf_dflt);
013d97e9d   Francesco Ruggeri   net: race conditi...
689
690
  		rtnl_unlock();
  		return 0;
88af182e3   Eric W. Biederman   net: Fix sysctl r...
691
  	}
c8fecf224   Pavel Emelyanov   [IPV6]: Eliminate...
692

e186932b3   Pavel Emelyanov   [NETNS]: Use the ...
693
  	if (p == &net->ipv6.devconf_all->forwarding) {
e186932b3   Pavel Emelyanov   [NETNS]: Use the ...
694
695
  		net->ipv6.devconf_dflt->forwarding = newf;
  		addrconf_forward_change(net, newf);
f3a1bfb11   Nicolas Dichtel   rtnl/ipv6: use ne...
696
697
698
699
  		if ((!newf) ^ (!old))
  			inet6_netconf_notify_devconf(net, NETCONFA_FORWARDING,
  						     NETCONFA_IFINDEX_ALL,
  						     net->ipv6.devconf_all);
013d97e9d   Francesco Ruggeri   net: race conditi...
700
  	} else if ((!newf) ^ (!old))
c8fecf224   Pavel Emelyanov   [IPV6]: Eliminate...
701
  		dev_forward_change((struct inet6_dev *)table->extra1);
0187bdfb0   Ben Hutchings   net: Disable LRO ...
702
  	rtnl_unlock();
c8fecf224   Pavel Emelyanov   [IPV6]: Eliminate...
703

013d97e9d   Francesco Ruggeri   net: race conditi...
704
  	if (newf)
7b4da5322   Daniel Lezcano   [NETNS][IPV6] rou...
705
  		rt6_purge_dflt_routers(net);
b325fddb7   Stephen Hemminger   ipv6: Fix sysctl ...
706
  	return 1;
c8fecf224   Pavel Emelyanov   [IPV6]: Eliminate...
707
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
708
  #endif
5c578aedc   stephen hemminger   IPv6: convert add...
709
  /* Nobody refers to this ifaddr, destroy it */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
710
711
  void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp)
  {
c2e21293c   stephen hemminger   ipv6: convert add...
712
  	WARN_ON(!hlist_unhashed(&ifp->addr_lst));
547b792ca   Ilpo Järvinen   net: convert BUG_...
713

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
714
  #ifdef NET_REFCNT_DEBUG
91df42bed   Joe Perches   net: ipv4 and ipv...
715
716
  	pr_debug("%s
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
717
718
719
  #endif
  
  	in6_dev_put(ifp->idev);
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
720
721
722
723
  	if (cancel_delayed_work(&ifp->dad_work))
  		pr_notice("delayed DAD work was pending while freeing ifa=%p
  ",
  			  ifp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
724

e9d3e0849   Herbert Xu   ipv6: Replace ine...
725
  	if (ifp->state != INET6_IFADDR_STATE_DEAD) {
f32138319   Joe Perches   net: ipv6: Standa...
726
727
  		pr_warn("Freeing alive inet6 address %p
  ", ifp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
728
729
  		return;
  	}
94e187c01   Amerigo Wang   ipv6: introduce i...
730
  	ip6_rt_put(ifp->rt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
731

e57859854   Lai Jiangshan   net,rcu: convert ...
732
  	kfree_rcu(ifp, rcu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
733
  }
e55ffac60   Brian Haley   [IPV6]: order add...
734
735
736
  static void
  ipv6_link_dev_addr(struct inet6_dev *idev, struct inet6_ifaddr *ifp)
  {
502a2ffd7   stephen hemminger   ipv6: convert ide...
737
  	struct list_head *p;
8a6ce0c08   YOSHIFUJI Hideaki   [IPV6]: Use ipv6_...
738
  	int ifp_scope = ipv6_addr_src_scope(&ifp->addr);
e55ffac60   Brian Haley   [IPV6]: order add...
739
740
741
742
743
  
  	/*
  	 * Each device address list is sorted in order of scope -
  	 * global before linklocal.
  	 */
502a2ffd7   stephen hemminger   ipv6: convert ide...
744
745
746
  	list_for_each(p, &idev->addr_list) {
  		struct inet6_ifaddr *ifa
  			= list_entry(p, struct inet6_ifaddr, if_list);
8a6ce0c08   YOSHIFUJI Hideaki   [IPV6]: Use ipv6_...
747
  		if (ifp_scope >= ipv6_addr_src_scope(&ifa->addr))
e55ffac60   Brian Haley   [IPV6]: order add...
748
749
  			break;
  	}
b54c9b98b   David S. Miller   ipv6: Preserve pe...
750
  	list_add_tail(&ifp->if_list, p);
e55ffac60   Brian Haley   [IPV6]: order add...
751
  }
ddbe50320   Eric Dumazet   ipv6: add ipv6_ad...
752
  static u32 inet6_addr_hash(const struct in6_addr *addr)
3eb84f492   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
753
  {
ddbe50320   Eric Dumazet   ipv6: add ipv6_ad...
754
  	return hash_32(ipv6_addr_hash(addr), IN6_ADDR_HSIZE_SHIFT);
3eb84f492   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
755
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
756
757
758
  /* On success it returns ifp with increased reference count */
  
  static struct inet6_ifaddr *
3f8f52982   Jiri Pirko   ipv6: move peer_a...
759
760
  ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
  	      const struct in6_addr *peer_addr, int pfxlen,
8a226b2cf   Jiri Benc   ipv6: prevent rac...
761
  	      int scope, u32 flags, u32 valid_lft, u32 prefered_lft)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
762
763
764
  {
  	struct inet6_ifaddr *ifa = NULL;
  	struct rt6_info *rt;
3a88a81d8   stephen hemminger   ipv6: user better...
765
  	unsigned int hash;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
766
  	int err = 0;
d68b82705   YOSHIFUJI Hideaki   ipv6: Do not assi...
767
768
769
770
771
772
773
  	int addr_type = ipv6_addr_type(addr);
  
  	if (addr_type == IPV6_ADDR_ANY ||
  	    addr_type & IPV6_ADDR_MULTICAST ||
  	    (!(idev->dev->flags & IFF_LOOPBACK) &&
  	     addr_type & IPV6_ADDR_LOOPBACK))
  		return ERR_PTR(-EADDRNOTAVAIL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
774

8814c4b53   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
775
  	rcu_read_lock_bh();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
776
777
778
779
  	if (idev->dead) {
  		err = -ENODEV;			/*XXX*/
  		goto out2;
  	}
56d417b12   Brian Haley   IPv6: Add 'autoco...
780
  	if (idev->cnf.disable_ipv6) {
9bdd8d40c   Brian Haley   ipv6: Fix incorre...
781
782
783
  		err = -EACCES;
  		goto out2;
  	}
5c578aedc   stephen hemminger   IPv6: convert add...
784
  	spin_lock(&addrconf_hash_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
785
786
  
  	/* Ignore adding duplicate addresses on an interface */
c346dca10   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
787
  	if (ipv6_chk_same_addr(dev_net(idev->dev), addr, idev->dev)) {
ba3542e15   dingtianhong   ipv6: convert the...
788
789
  		ADBG("ipv6_add_addr: already assigned
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
790
791
792
  		err = -EEXIST;
  		goto out;
  	}
322f74a43   Ingo Oeser   [IPV6]: Cleanups ...
793
  	ifa = kzalloc(sizeof(struct inet6_ifaddr), GFP_ATOMIC);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
794
795
  
  	if (ifa == NULL) {
ba3542e15   dingtianhong   ipv6: convert the...
796
797
  		ADBG("ipv6_add_addr: malloc failed
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
798
799
800
  		err = -ENOBUFS;
  		goto out;
  	}
8f0315190   David S. Miller   ipv6: Make third ...
801
  	rt = addrconf_dst_alloc(idev, addr, false);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
802
803
804
805
  	if (IS_ERR(rt)) {
  		err = PTR_ERR(rt);
  		goto out;
  	}
bba24896f   Jiri Pirko   neigh: ipv6: resp...
806
  	neigh_parms_data_state_setall(idev->nd_parms);
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
807
  	ifa->addr = *addr;
3f8f52982   Jiri Pirko   ipv6: move peer_a...
808
809
  	if (peer_addr)
  		ifa->peer_addr = *peer_addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
810
811
  
  	spin_lock_init(&ifa->lock);
e9d3e0849   Herbert Xu   ipv6: Replace ine...
812
  	spin_lock_init(&ifa->state_lock);
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
813
  	INIT_DELAYED_WORK(&ifa->dad_work, addrconf_dad_work);
c2e21293c   stephen hemminger   ipv6: convert add...
814
  	INIT_HLIST_NODE(&ifa->addr_lst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
815
816
817
  	ifa->scope = scope;
  	ifa->prefix_len = pfxlen;
  	ifa->flags = flags | IFA_F_TENTATIVE;
8a226b2cf   Jiri Benc   ipv6: prevent rac...
818
819
  	ifa->valid_lft = valid_lft;
  	ifa->prefered_lft = prefered_lft;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
820
  	ifa->cstamp = ifa->tstamp = jiffies;
617fe29d4   Daniel Borkmann   net: ipv6: only i...
821
  	ifa->tokenized = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
822

57f5f544f   Keir Fraser   [IPV6]: ipv6_add_...
823
  	ifa->rt = rt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
824
825
826
827
828
829
  	ifa->idev = idev;
  	in6_dev_hold(idev);
  	/* For caller */
  	in6_ifa_hold(ifa);
  
  	/* Add to big hash table */
ddbe50320   Eric Dumazet   ipv6: add ipv6_ad...
830
  	hash = inet6_addr_hash(addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
831

5c578aedc   stephen hemminger   IPv6: convert add...
832
  	hlist_add_head_rcu(&ifa->addr_lst, &inet6_addr_lst[hash]);
5c578aedc   stephen hemminger   IPv6: convert add...
833
  	spin_unlock(&addrconf_hash_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
834
835
836
  
  	write_lock(&idev->lock);
  	/* Add to inet6_dev unicast addr list. */
e55ffac60   Brian Haley   [IPV6]: order add...
837
  	ipv6_link_dev_addr(idev, ifa);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
838

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
839
  	if (ifa->flags&IFA_F_TEMPORARY) {
372e6c8f1   stephen hemminger   ipv6: convert tem...
840
  		list_add(&ifa->tmp_list, &idev->tempaddr_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
841
842
  		in6_ifa_hold(ifa);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
843

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
844
845
846
  	in6_ifa_hold(ifa);
  	write_unlock(&idev->lock);
  out2:
8814c4b53   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
847
  	rcu_read_unlock_bh();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
848

fd92833a5   YOSHIFUJI Hideaki   [IPV6]: Fix a bra...
849
  	if (likely(err == 0))
f88c91ddb   Cong Wang   ipv6: statically ...
850
  		inet6addr_notifier_call_chain(NETDEV_UP, ifa);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
851
852
853
854
855
856
857
  	else {
  		kfree(ifa);
  		ifa = ERR_PTR(err);
  	}
  
  	return ifa;
  out:
5c578aedc   stephen hemminger   IPv6: convert add...
858
  	spin_unlock(&addrconf_hash_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
859
860
  	goto out2;
  }
5b84efecb   Thomas Haller   ipv6 addrconf: do...
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
  enum cleanup_prefix_rt_t {
  	CLEANUP_PREFIX_RT_NOP,    /* no cleanup action for prefix route */
  	CLEANUP_PREFIX_RT_DEL,    /* delete the prefix route */
  	CLEANUP_PREFIX_RT_EXPIRE, /* update the lifetime of the prefix route */
  };
  
  /*
   * Check, whether the prefix for ifp would still need a prefix route
   * after deleting ifp. The function returns one of the CLEANUP_PREFIX_RT_*
   * constants.
   *
   * 1) we don't purge prefix if address was not permanent.
   *    prefix is managed by its own lifetime.
   * 2) we also don't purge, if the address was IFA_F_NOPREFIXROUTE.
   * 3) if there are no addresses, delete prefix.
   * 4) if there are still other permanent address(es),
   *    corresponding prefix is still permanent.
   * 5) if there are still other addresses with IFA_F_NOPREFIXROUTE,
   *    don't purge the prefix, assume user space is managing it.
   * 6) otherwise, update prefix lifetime to the
   *    longest valid lifetime among the corresponding
   *    addresses on the device.
   *    Note: subsequent RA will update lifetime.
   **/
  static enum cleanup_prefix_rt_t
  check_cleanup_prefix_route(struct inet6_ifaddr *ifp, unsigned long *expires)
  {
  	struct inet6_ifaddr *ifa;
  	struct inet6_dev *idev = ifp->idev;
  	unsigned long lifetime;
  	enum cleanup_prefix_rt_t action = CLEANUP_PREFIX_RT_DEL;
  
  	*expires = jiffies;
  
  	list_for_each_entry(ifa, &idev->addr_list, if_list) {
  		if (ifa == ifp)
  			continue;
  		if (!ipv6_prefix_equal(&ifa->addr, &ifp->addr,
  				       ifp->prefix_len))
  			continue;
  		if (ifa->flags & (IFA_F_PERMANENT | IFA_F_NOPREFIXROUTE))
  			return CLEANUP_PREFIX_RT_NOP;
  
  		action = CLEANUP_PREFIX_RT_EXPIRE;
  
  		spin_lock(&ifa->lock);
  
  		lifetime = addrconf_timeout_fixup(ifa->valid_lft, HZ);
  		/*
  		 * Note: Because this address is
  		 * not permanent, lifetime <
  		 * LONG_MAX / HZ here.
  		 */
  		if (time_before(*expires, ifa->tstamp + lifetime * HZ))
  			*expires = ifa->tstamp + lifetime * HZ;
  		spin_unlock(&ifa->lock);
  	}
  
  	return action;
  }
  
  static void
  cleanup_prefix_route(struct inet6_ifaddr *ifp, unsigned long expires, bool del_rt)
  {
  	struct rt6_info *rt;
  
  	rt = addrconf_get_prefix_route(&ifp->addr,
  				       ifp->prefix_len,
  				       ifp->idev->dev,
  				       0, RTF_GATEWAY | RTF_DEFAULT);
  	if (rt) {
  		if (del_rt)
  			ip6_del_rt(rt);
  		else {
  			if (!(rt->rt6i_flags & RTF_EXPIRES))
  				rt6_set_expires(rt, expires);
  			ip6_rt_put(rt);
  		}
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
941
942
943
944
  /* This function wants to get referenced ifp and releases it before return */
  
  static void ipv6_del_addr(struct inet6_ifaddr *ifp)
  {
4c5ff6a6f   Herbert Xu   ipv6: Use state_l...
945
  	int state;
5b84efecb   Thomas Haller   ipv6 addrconf: do...
946
947
  	enum cleanup_prefix_rt_t action = CLEANUP_PREFIX_RT_NOP;
  	unsigned long expires;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
948

c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
949
  	ASSERT_RTNL();
4c5ff6a6f   Herbert Xu   ipv6: Use state_l...
950
951
  	spin_lock_bh(&ifp->state_lock);
  	state = ifp->state;
e9d3e0849   Herbert Xu   ipv6: Replace ine...
952
  	ifp->state = INET6_IFADDR_STATE_DEAD;
4c5ff6a6f   Herbert Xu   ipv6: Use state_l...
953
954
955
956
  	spin_unlock_bh(&ifp->state_lock);
  
  	if (state == INET6_IFADDR_STATE_DEAD)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
957

5c578aedc   stephen hemminger   IPv6: convert add...
958
959
  	spin_lock_bh(&addrconf_hash_lock);
  	hlist_del_init_rcu(&ifp->addr_lst);
5c578aedc   stephen hemminger   IPv6: convert add...
960
  	spin_unlock_bh(&addrconf_hash_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
961

5b84efecb   Thomas Haller   ipv6 addrconf: do...
962
  	write_lock_bh(&ifp->idev->lock);
5d9efa7ee   David S. Miller   ipv6: Remove priv...
963

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
964
  	if (ifp->flags&IFA_F_TEMPORARY) {
372e6c8f1   stephen hemminger   ipv6: convert tem...
965
966
967
968
  		list_del(&ifp->tmp_list);
  		if (ifp->ifpub) {
  			in6_ifa_put(ifp->ifpub);
  			ifp->ifpub = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
969
  		}
372e6c8f1   stephen hemminger   ipv6: convert tem...
970
  		__in6_ifa_put(ifp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
971
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
972

5b84efecb   Thomas Haller   ipv6 addrconf: do...
973
974
  	if (ifp->flags & IFA_F_PERMANENT && !(ifp->flags & IFA_F_NOPREFIXROUTE))
  		action = check_cleanup_prefix_route(ifp, &expires);
502a2ffd7   stephen hemminger   ipv6: convert ide...
975

5b84efecb   Thomas Haller   ipv6 addrconf: do...
976
977
978
979
  	list_del_init(&ifp->if_list);
  	__in6_ifa_put(ifp);
  
  	write_unlock_bh(&ifp->idev->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
980

c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
981
  	addrconf_del_dad_work(ifp);
b22385664   Andrey Vagin   ipv6: fix race be...
982

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
983
  	ipv6_ifa_notify(RTM_DELADDR, ifp);
f88c91ddb   Cong Wang   ipv6: statically ...
984
  	inet6addr_notifier_call_chain(NETDEV_DOWN, ifp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
985

5b84efecb   Thomas Haller   ipv6 addrconf: do...
986
987
988
  	if (action != CLEANUP_PREFIX_RT_NOP) {
  		cleanup_prefix_route(ifp, expires,
  			action == CLEANUP_PREFIX_RT_DEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
989
  	}
c3968a857   Daniel Walter   ipv6: RTA_PREFSRC...
990
991
  	/* clean up prefsrc entries */
  	rt6_remove_prefsrc(ifp);
4c5ff6a6f   Herbert Xu   ipv6: Use state_l...
992
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
993
994
  	in6_ifa_put(ifp);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
995
996
997
998
  static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *ift)
  {
  	struct inet6_dev *idev = ifp->idev;
  	struct in6_addr addr, *tmpaddr;
76f793e3a   Lorenzo Colitti   ipv6: updates to ...
999
  	unsigned long tmp_prefered_lft, tmp_valid_lft, tmp_tstamp, age;
eac55bf97   Benoit Boissinot   IPv6: do not crea...
1000
  	unsigned long regen_advance;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1001
1002
  	int tmp_plen;
  	int ret = 0;
95c385b4d   Neil Horman   [IPV6] ADDRCONF: ...
1003
  	u32 addr_flags;
76f793e3a   Lorenzo Colitti   ipv6: updates to ...
1004
  	unsigned long now = jiffies;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1005

53bd67491   Jiri Pirko   ipv6 addrconf: in...
1006
  	write_lock_bh(&idev->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
  	if (ift) {
  		spin_lock_bh(&ift->lock);
  		memcpy(&addr.s6_addr[8], &ift->addr.s6_addr[8], 8);
  		spin_unlock_bh(&ift->lock);
  		tmpaddr = &addr;
  	} else {
  		tmpaddr = NULL;
  	}
  retry:
  	in6_dev_hold(idev);
  	if (idev->cnf.use_tempaddr <= 0) {
53bd67491   Jiri Pirko   ipv6 addrconf: in...
1018
  		write_unlock_bh(&idev->lock);
f32138319   Joe Perches   net: ipv6: Standa...
1019
1020
  		pr_info("%s: use_tempaddr is disabled
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1021
1022
1023
1024
1025
1026
1027
1028
  		in6_dev_put(idev);
  		ret = -1;
  		goto out;
  	}
  	spin_lock_bh(&ifp->lock);
  	if (ifp->regen_count++ >= idev->cnf.regen_max_retry) {
  		idev->cnf.use_tempaddr = -1;	/*XXX*/
  		spin_unlock_bh(&ifp->lock);
53bd67491   Jiri Pirko   ipv6 addrconf: in...
1029
  		write_unlock_bh(&idev->lock);
f32138319   Joe Perches   net: ipv6: Standa...
1030
1031
1032
  		pr_warn("%s: regeneration time exceeded - disabled temporary address support
  ",
  			__func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1033
1034
1035
1036
1037
1038
  		in6_dev_put(idev);
  		ret = -1;
  		goto out;
  	}
  	in6_ifa_hold(ifp);
  	memcpy(addr.s6_addr, ifp->addr.s6_addr, 8);
eb7e05759   Sorin Dumitru   ipv6: remove some...
1039
  	__ipv6_try_regen_rndid(idev, tmpaddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1040
  	memcpy(&addr.s6_addr[8], idev->rndid, 8);
76f793e3a   Lorenzo Colitti   ipv6: updates to ...
1041
  	age = (now - ifp->tstamp) / HZ;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1042
1043
  	tmp_valid_lft = min_t(__u32,
  			      ifp->valid_lft,
7a876b0ef   Glenn Wurster   IPv6: Temp addres...
1044
  			      idev->cnf.temp_valid_lft + age);
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
1045
1046
  	tmp_prefered_lft = min_t(__u32,
  				 ifp->prefered_lft,
7a876b0ef   Glenn Wurster   IPv6: Temp addres...
1047
  				 idev->cnf.temp_prefered_lft + age -
784e2710c   Ben Hutchings   ipv6: Use interfa...
1048
  				 idev->cnf.max_desync_factor);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1049
  	tmp_plen = ifp->prefix_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1050
1051
  	tmp_tstamp = ifp->tstamp;
  	spin_unlock_bh(&ifp->lock);
eac55bf97   Benoit Boissinot   IPv6: do not crea...
1052
  	regen_advance = idev->cnf.regen_max_retry *
7eaa48a45   David S. Miller   Revert "ipv6: fix...
1053
  	                idev->cnf.dad_transmits *
1f9248e56   Jiri Pirko   neigh: convert pa...
1054
  	                NEIGH_VAR(idev->nd_parms, RETRANS_TIME) / HZ;
53bd67491   Jiri Pirko   ipv6 addrconf: in...
1055
  	write_unlock_bh(&idev->lock);
95c385b4d   Neil Horman   [IPV6] ADDRCONF: ...
1056

eac55bf97   Benoit Boissinot   IPv6: do not crea...
1057
1058
1059
1060
  	/* A temporary address is created only if this calculated Preferred
  	 * Lifetime is greater than REGEN_ADVANCE time units.  In particular,
  	 * an implementation must not create a temporary address with a zero
  	 * Preferred Lifetime.
ecab67015   Heiner Kallweit   ipv6: Avoid unnec...
1061
1062
  	 * Use age calculation as in addrconf_verify to avoid unnecessary
  	 * temporary addresses being generated.
eac55bf97   Benoit Boissinot   IPv6: do not crea...
1063
  	 */
ecab67015   Heiner Kallweit   ipv6: Avoid unnec...
1064
1065
  	age = (now - tmp_tstamp + ADDRCONF_TIMER_FUZZ_MINUS) / HZ;
  	if (tmp_prefered_lft <= regen_advance + age) {
eac55bf97   Benoit Boissinot   IPv6: do not crea...
1066
1067
1068
1069
1070
  		in6_ifa_put(ifp);
  		in6_dev_put(idev);
  		ret = -1;
  		goto out;
  	}
95c385b4d   Neil Horman   [IPV6] ADDRCONF: ...
1071
1072
1073
1074
  	addr_flags = IFA_F_TEMPORARY;
  	/* set in addrconf_prefix_rcv() */
  	if (ifp->flags & IFA_F_OPTIMISTIC)
  		addr_flags |= IFA_F_OPTIMISTIC;
4b08a8f1b   Hannes Frederic Sowa   ipv6: remove max_...
1075
1076
1077
1078
  	ift = ipv6_add_addr(idev, &addr, NULL, tmp_plen,
  			    ipv6_addr_scope(&addr), addr_flags,
  			    tmp_valid_lft, tmp_prefered_lft);
  	if (IS_ERR(ift)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1079
1080
  		in6_ifa_put(ifp);
  		in6_dev_put(idev);
f32138319   Joe Perches   net: ipv6: Standa...
1081
1082
  		pr_info("%s: retry temporary address regeneration
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1083
  		tmpaddr = &addr;
53bd67491   Jiri Pirko   ipv6 addrconf: in...
1084
  		write_lock_bh(&idev->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1085
1086
1087
1088
1089
  		goto retry;
  	}
  
  	spin_lock_bh(&ift->lock);
  	ift->ifpub = ifp;
76f793e3a   Lorenzo Colitti   ipv6: updates to ...
1090
  	ift->cstamp = now;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1091
1092
  	ift->tstamp = tmp_tstamp;
  	spin_unlock_bh(&ift->lock);
cf22f9a2b   David S. Miller   ipv6: Remove unus...
1093
  	addrconf_dad_start(ift);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1094
1095
1096
1097
1098
  	in6_ifa_put(ift);
  	in6_dev_put(idev);
  out:
  	return ret;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1099
1100
  
  /*
072047e4d   YOSHIFUJI Hideaki   [IPV6]: RFC3484 c...
1101
   *	Choose an appropriate source address (RFC3484)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1102
   */
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
  enum {
  	IPV6_SADDR_RULE_INIT = 0,
  	IPV6_SADDR_RULE_LOCAL,
  	IPV6_SADDR_RULE_SCOPE,
  	IPV6_SADDR_RULE_PREFERRED,
  #ifdef CONFIG_IPV6_MIP6
  	IPV6_SADDR_RULE_HOA,
  #endif
  	IPV6_SADDR_RULE_OIF,
  	IPV6_SADDR_RULE_LABEL,
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1113
  	IPV6_SADDR_RULE_PRIVACY,
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1114
1115
1116
1117
  	IPV6_SADDR_RULE_ORCHID,
  	IPV6_SADDR_RULE_PREFIX,
  	IPV6_SADDR_RULE_MAX
  };
072047e4d   YOSHIFUJI Hideaki   [IPV6]: RFC3484 c...
1118
  struct ipv6_saddr_score {
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1119
1120
1121
1122
1123
1124
  	int			rule;
  	int			addr_type;
  	struct inet6_ifaddr	*ifa;
  	DECLARE_BITMAP(scorebits, IPV6_SADDR_RULE_MAX);
  	int			scopedist;
  	int			matchlen;
072047e4d   YOSHIFUJI Hideaki   [IPV6]: RFC3484 c...
1125
  };
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1126
  struct ipv6_saddr_dst {
9acd9f3ae   YOSHIFUJI Hideaki   [IPV6]: Make addr...
1127
  	const struct in6_addr *addr;
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1128
1129
1130
  	int ifindex;
  	int scope;
  	int label;
7cbca67c0   YOSHIFUJI Hideaki   [IPV6]: Support S...
1131
  	unsigned int prefs;
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1132
  };
072047e4d   YOSHIFUJI Hideaki   [IPV6]: RFC3484 c...
1133

b6f99a211   Dave Jones   [NET]: fix up mis...
1134
  static inline int ipv6_saddr_preferred(int type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1135
  {
45bb00609   Ulrich Weber   ipv6: Remove IPV6...
1136
  	if (type & (IPV6_ADDR_MAPPED|IPV6_ADDR_COMPATv4|IPV6_ADDR_LOOPBACK))
072047e4d   YOSHIFUJI Hideaki   [IPV6]: RFC3484 c...
1137
1138
  		return 1;
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1139
  }
3de232554   Benjamin Thery   ipv6 netns: Addre...
1140
1141
  static int ipv6_get_saddr_eval(struct net *net,
  			       struct ipv6_saddr_score *score,
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
  			       struct ipv6_saddr_dst *dst,
  			       int i)
  {
  	int ret;
  
  	if (i <= score->rule) {
  		switch (i) {
  		case IPV6_SADDR_RULE_SCOPE:
  			ret = score->scopedist;
  			break;
  		case IPV6_SADDR_RULE_PREFIX:
  			ret = score->matchlen;
  			break;
  		default:
  			ret = !!test_bit(i, score->scorebits);
  		}
  		goto out;
  	}
  
  	switch (i) {
  	case IPV6_SADDR_RULE_INIT:
  		/* Rule 0: remember if hiscore is not ready yet */
  		ret = !!score->ifa;
  		break;
  	case IPV6_SADDR_RULE_LOCAL:
  		/* Rule 1: Prefer same address */
  		ret = ipv6_addr_equal(&score->ifa->addr, dst->addr);
  		break;
  	case IPV6_SADDR_RULE_SCOPE:
  		/* Rule 2: Prefer appropriate scope
  		 *
  		 *      ret
  		 *       ^
  		 *    -1 |  d 15
  		 *    ---+--+-+---> scope
  		 *       |
  		 *       |             d is scope of the destination.
  		 *  B-d  |  \
  		 *       |   \      <- smaller scope is better if
db9c7c394   stephen hemminger   ipv6: addrconf sp...
1181
  		 *  B-15 |    \        if scope is enough for destination.
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
  		 *       |             ret = B - scope (-1 <= scope >= d <= 15).
  		 * d-C-1 | /
  		 *       |/         <- greater is better
  		 *   -C  /             if scope is not enough for destination.
  		 *      /|             ret = scope - C (-1 <= d < scope <= 15).
  		 *
  		 * d - C - 1 < B -15 (for all -1 <= d <= 15).
  		 * C > d + 14 - B >= 15 + 14 - B = 29 - B.
  		 * Assume B = 0 and we get C > 29.
  		 */
  		ret = __ipv6_addr_src_scope(score->addr_type);
  		if (ret >= dst->scope)
  			ret = -ret;
  		else
  			ret -= 128;	/* 30 is enough */
  		score->scopedist = ret;
  		break;
  	case IPV6_SADDR_RULE_PREFERRED:
  		/* Rule 3: Avoid deprecated and optimistic addresses */
  		ret = ipv6_saddr_preferred(score->addr_type) ||
  		      !(score->ifa->flags & (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC));
  		break;
  #ifdef CONFIG_IPV6_MIP6
  	case IPV6_SADDR_RULE_HOA:
7cbca67c0   YOSHIFUJI Hideaki   [IPV6]: Support S...
1206
  	    {
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1207
  		/* Rule 4: Prefer home address */
7cbca67c0   YOSHIFUJI Hideaki   [IPV6]: Support S...
1208
1209
  		int prefhome = !(dst->prefs & IPV6_PREFER_SRC_COA);
  		ret = !(score->ifa->flags & IFA_F_HOMEADDRESS) ^ prefhome;
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1210
  		break;
7cbca67c0   YOSHIFUJI Hideaki   [IPV6]: Support S...
1211
  	    }
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1212
1213
1214
1215
1216
1217
1218
1219
  #endif
  	case IPV6_SADDR_RULE_OIF:
  		/* Rule 5: Prefer outgoing interface */
  		ret = (!dst->ifindex ||
  		       dst->ifindex == score->ifa->idev->dev->ifindex);
  		break;
  	case IPV6_SADDR_RULE_LABEL:
  		/* Rule 6: Prefer matching label */
3de232554   Benjamin Thery   ipv6 netns: Addre...
1220
1221
  		ret = ipv6_addr_label(net,
  				      &score->ifa->addr, score->addr_type,
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1222
1223
  				      score->ifa->idev->dev->ifindex) == dst->label;
  		break;
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1224
  	case IPV6_SADDR_RULE_PRIVACY:
7cbca67c0   YOSHIFUJI Hideaki   [IPV6]: Support S...
1225
  	    {
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1226
  		/* Rule 7: Prefer public address
25985edce   Lucas De Marchi   Fix common misspe...
1227
  		 * Note: prefer temporary address if use_tempaddr >= 2
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1228
  		 */
7cbca67c0   YOSHIFUJI Hideaki   [IPV6]: Support S...
1229
1230
1231
1232
  		int preftmp = dst->prefs & (IPV6_PREFER_SRC_PUBLIC|IPV6_PREFER_SRC_TMP) ?
  				!!(dst->prefs & IPV6_PREFER_SRC_TMP) :
  				score->ifa->idev->cnf.use_tempaddr >= 2;
  		ret = (!(score->ifa->flags & IFA_F_TEMPORARY)) ^ preftmp;
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1233
  		break;
7cbca67c0   YOSHIFUJI Hideaki   [IPV6]: Support S...
1234
  	    }
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1235
1236
1237
1238
1239
1240
1241
1242
1243
  	case IPV6_SADDR_RULE_ORCHID:
  		/* Rule 8-: Prefer ORCHID vs ORCHID or
  		 *	    non-ORCHID vs non-ORCHID
  		 */
  		ret = !(ipv6_addr_orchid(&score->ifa->addr) ^
  			ipv6_addr_orchid(dst->addr));
  		break;
  	case IPV6_SADDR_RULE_PREFIX:
  		/* Rule 8: Use longest matching prefix */
91b4b04ff   YOSHIFUJI Hideaki / 吉藤英明   ipv6: Compare add...
1244
1245
1246
1247
  		ret = ipv6_addr_diff(&score->ifa->addr, dst->addr);
  		if (ret > score->ifa->prefix_len)
  			ret = score->ifa->prefix_len;
  		score->matchlen = ret;
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
  		break;
  	default:
  		ret = 0;
  	}
  
  	if (ret)
  		__set_bit(i, score->scorebits);
  	score->rule = i;
  out:
  	return ret;
  }
b3f644fc8   Patrick McHardy   netfilter: ip6tab...
1259
  int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev,
9acd9f3ae   YOSHIFUJI Hideaki   [IPV6]: Make addr...
1260
  		       const struct in6_addr *daddr, unsigned int prefs,
7cbca67c0   YOSHIFUJI Hideaki   [IPV6]: Support S...
1261
  		       struct in6_addr *saddr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1262
  {
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1263
1264
  	struct ipv6_saddr_score scores[2],
  				*score = &scores[0], *hiscore = &scores[1];
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1265
  	struct ipv6_saddr_dst dst;
072047e4d   YOSHIFUJI Hideaki   [IPV6]: RFC3484 c...
1266
  	struct net_device *dev;
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1267
  	int dst_type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1268

a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1269
1270
1271
1272
  	dst_type = __ipv6_addr_type(daddr);
  	dst.addr = daddr;
  	dst.ifindex = dst_dev ? dst_dev->ifindex : 0;
  	dst.scope = __ipv6_addr_src_scope(dst_type);
3de232554   Benjamin Thery   ipv6 netns: Addre...
1273
  	dst.label = ipv6_addr_label(net, daddr, dst_type, dst.ifindex);
7cbca67c0   YOSHIFUJI Hideaki   [IPV6]: Support S...
1274
  	dst.prefs = prefs;
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1275
1276
1277
  
  	hiscore->rule = -1;
  	hiscore->ifa = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1278

8814c4b53   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1279
  	rcu_read_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1280

c6d14c845   Eric Dumazet   net: Introduce fo...
1281
  	for_each_netdev_rcu(net, dev) {
072047e4d   YOSHIFUJI Hideaki   [IPV6]: RFC3484 c...
1282
  		struct inet6_dev *idev;
072047e4d   YOSHIFUJI Hideaki   [IPV6]: RFC3484 c...
1283

a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1284
  		/* Candidate Source Address (section 4)
072047e4d   YOSHIFUJI Hideaki   [IPV6]: RFC3484 c...
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
  		 *  - multicast and link-local destination address,
  		 *    the set of candidate source address MUST only
  		 *    include addresses assigned to interfaces
  		 *    belonging to the same link as the outgoing
  		 *    interface.
  		 * (- For site-local destination addresses, the
  		 *    set of candidate source addresses MUST only
  		 *    include addresses assigned to interfaces
  		 *    belonging to the same site as the outgoing
  		 *    interface.)
  		 */
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1296
1297
1298
  		if (((dst_type & IPV6_ADDR_MULTICAST) ||
  		     dst.scope <= IPV6_ADDR_SCOPE_LINKLOCAL) &&
  		    dst.ifindex && dev->ifindex != dst.ifindex)
072047e4d   YOSHIFUJI Hideaki   [IPV6]: RFC3484 c...
1299
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1300

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1301
  		idev = __in6_dev_get(dev);
072047e4d   YOSHIFUJI Hideaki   [IPV6]: RFC3484 c...
1302
1303
1304
1305
  		if (!idev)
  			continue;
  
  		read_lock_bh(&idev->lock);
502a2ffd7   stephen hemminger   ipv6: convert ide...
1306
  		list_for_each_entry(score->ifa, &idev->addr_list, if_list) {
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1307
  			int i;
072047e4d   YOSHIFUJI Hideaki   [IPV6]: RFC3484 c...
1308

a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1309
  			/*
6b3ae80a6   YOSHIFUJI Hideaki   [IPV6]: Don't sel...
1310
1311
1312
  			 * - Tentative Address (RFC2462 section 5.4)
  			 *  - A tentative address is not considered
  			 *    "assigned to an interface" in the traditional
95c385b4d   Neil Horman   [IPV6] ADDRCONF: ...
1313
  			 *    sense, unless it is also flagged as optimistic.
6b3ae80a6   YOSHIFUJI Hideaki   [IPV6]: Don't sel...
1314
  			 * - Candidate Source Address (section 4)
072047e4d   YOSHIFUJI Hideaki   [IPV6]: RFC3484 c...
1315
1316
1317
1318
  			 *  - In any case, anycast addresses, multicast
  			 *    addresses, and the unspecified address MUST
  			 *    NOT be included in a candidate set.
  			 */
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1319
1320
  			if ((score->ifa->flags & IFA_F_TENTATIVE) &&
  			    (!(score->ifa->flags & IFA_F_OPTIMISTIC)))
6b3ae80a6   YOSHIFUJI Hideaki   [IPV6]: Don't sel...
1321
  				continue;
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1322
1323
1324
1325
1326
  
  			score->addr_type = __ipv6_addr_type(&score->ifa->addr);
  
  			if (unlikely(score->addr_type == IPV6_ADDR_ANY ||
  				     score->addr_type & IPV6_ADDR_MULTICAST)) {
072047e4d   YOSHIFUJI Hideaki   [IPV6]: RFC3484 c...
1327
  				LIMIT_NETDEBUG(KERN_DEBUG
3b6d821c4   Joe Perches   [IPV6]: Add missi...
1328
  					       "ADDRCONF: unspecified / multicast address "
072047e4d   YOSHIFUJI Hideaki   [IPV6]: RFC3484 c...
1329
1330
1331
1332
  					       "assigned as unicast address on %s",
  					       dev->name);
  				continue;
  			}
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1333
1334
1335
1336
1337
  			score->rule = -1;
  			bitmap_zero(score->scorebits, IPV6_SADDR_RULE_MAX);
  
  			for (i = 0; i < IPV6_SADDR_RULE_MAX; i++) {
  				int minihiscore, miniscore;
3de232554   Benjamin Thery   ipv6 netns: Addre...
1338
1339
  				minihiscore = ipv6_get_saddr_eval(net, hiscore, &dst, i);
  				miniscore = ipv6_get_saddr_eval(net, score, &dst, i);
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
  
  				if (minihiscore > miniscore) {
  					if (i == IPV6_SADDR_RULE_SCOPE &&
  					    score->scopedist > 0) {
  						/*
  						 * special case:
  						 * each remaining entry
  						 * has too small (not enough)
  						 * scope, because ifa entries
  						 * are sorted by their scope
  						 * values.
  						 */
  						goto try_nextdev;
  					}
  					break;
  				} else if (minihiscore < miniscore) {
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1356
1357
1358
1359
  					if (hiscore->ifa)
  						in6_ifa_put(hiscore->ifa);
  
  					in6_ifa_hold(score->ifa);
a0bffffc1   Ilpo Järvinen   net/*: use linux/...
1360
  					swap(hiscore, score);
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1361
1362
1363
1364
1365
  
  					/* restore our iterator */
  					score->ifa = hiscore->ifa;
  
  					break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1366
  				}
072047e4d   YOSHIFUJI Hideaki   [IPV6]: RFC3484 c...
1367
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1368
  		}
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1369
  try_nextdev:
072047e4d   YOSHIFUJI Hideaki   [IPV6]: RFC3484 c...
1370
  		read_unlock_bh(&idev->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1371
  	}
8814c4b53   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1372
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1373

a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1374
  	if (!hiscore->ifa)
072047e4d   YOSHIFUJI Hideaki   [IPV6]: RFC3484 c...
1375
  		return -EADDRNOTAVAIL;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
1376

4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
1377
  	*saddr = hiscore->ifa->addr;
a9b05723f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1378
  	in6_ifa_put(hiscore->ifa);
072047e4d   YOSHIFUJI Hideaki   [IPV6]: RFC3484 c...
1379
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1380
  }
5e5f3f0f8   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1381
  EXPORT_SYMBOL(ipv6_dev_get_saddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1382

8965779d2   Amerigo Wang   ipv6,mcast: alway...
1383
  int __ipv6_get_lladdr(struct inet6_dev *idev, struct in6_addr *addr,
479840ffd   Jiri Pirko   ipv6 addrconf: ex...
1384
  		      u32 banned_flags)
b7b1bfce0   Hannes Frederic Sowa   ipv6: split dupli...
1385
1386
1387
  {
  	struct inet6_ifaddr *ifp;
  	int err = -EADDRNOTAVAIL;
602582ca7   Hannes Frederic Sowa   ipv6: optimize li...
1388
1389
1390
  	list_for_each_entry_reverse(ifp, &idev->addr_list, if_list) {
  		if (ifp->scope > IFA_LINK)
  			break;
b7b1bfce0   Hannes Frederic Sowa   ipv6: split dupli...
1391
1392
1393
1394
1395
1396
1397
1398
1399
  		if (ifp->scope == IFA_LINK &&
  		    !(ifp->flags & banned_flags)) {
  			*addr = ifp->addr;
  			err = 0;
  			break;
  		}
  	}
  	return err;
  }
95c385b4d   Neil Horman   [IPV6] ADDRCONF: ...
1400
  int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr,
479840ffd   Jiri Pirko   ipv6 addrconf: ex...
1401
  		    u32 banned_flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1402
1403
1404
  {
  	struct inet6_dev *idev;
  	int err = -EADDRNOTAVAIL;
8814c4b53   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1405
  	rcu_read_lock();
e21e8467d   Stephen Hemminger   addrconf: checkpa...
1406
1407
  	idev = __in6_dev_get(dev);
  	if (idev) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1408
  		read_lock_bh(&idev->lock);
b7b1bfce0   Hannes Frederic Sowa   ipv6: split dupli...
1409
  		err = __ipv6_get_lladdr(idev, addr, banned_flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1410
1411
  		read_unlock_bh(&idev->lock);
  	}
8814c4b53   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1412
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1413
1414
1415
1416
1417
1418
1419
1420
1421
  	return err;
  }
  
  static int ipv6_count_addresses(struct inet6_dev *idev)
  {
  	int cnt = 0;
  	struct inet6_ifaddr *ifp;
  
  	read_lock_bh(&idev->lock);
502a2ffd7   stephen hemminger   ipv6: convert ide...
1422
  	list_for_each_entry(ifp, &idev->addr_list, if_list)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1423
1424
1425
1426
  		cnt++;
  	read_unlock_bh(&idev->lock);
  	return cnt;
  }
b71d1d426   Eric Dumazet   inet: constify ip...
1427
  int ipv6_chk_addr(struct net *net, const struct in6_addr *addr,
2a7851bff   Florian Westphal   netfilter: add nf...
1428
  		  const struct net_device *dev, int strict)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1429
  {
eedf042a6   Stephen Hemminger   ipv6: fix the bug...
1430
  	struct inet6_ifaddr *ifp;
ddbe50320   Eric Dumazet   ipv6: add ipv6_ad...
1431
  	unsigned int hash = inet6_addr_hash(addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1432

5c578aedc   stephen hemminger   IPv6: convert add...
1433
  	rcu_read_lock_bh();
b67bfe0d4   Sasha Levin   hlist: drop the n...
1434
  	hlist_for_each_entry_rcu(ifp, &inet6_addr_lst[hash], addr_lst) {
878628fbf   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
1435
  		if (!net_eq(dev_net(ifp->idev->dev), net))
bfeade087   Daniel Lezcano   [NETNS][IPV6]: in...
1436
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1437
  		if (ipv6_addr_equal(&ifp->addr, addr) &&
eedf042a6   Stephen Hemminger   ipv6: fix the bug...
1438
1439
1440
1441
1442
  		    !(ifp->flags&IFA_F_TENTATIVE) &&
  		    (dev == NULL || ifp->idev->dev == dev ||
  		     !(ifp->scope&(IFA_LINK|IFA_HOST) || strict))) {
  			rcu_read_unlock_bh();
  			return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1443
1444
  		}
  	}
5c578aedc   stephen hemminger   IPv6: convert add...
1445

eedf042a6   Stephen Hemminger   ipv6: fix the bug...
1446
1447
  	rcu_read_unlock_bh();
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1448
  }
7159039a1   YOSHIFUJI Hideaki   [IPV6]: Decentral...
1449
  EXPORT_SYMBOL(ipv6_chk_addr);
3e81c6da3   David S. Miller   ipv6: Fix bug in ...
1450
1451
  static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr,
  			       struct net_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1452
  {
ddbe50320   Eric Dumazet   ipv6: add ipv6_ad...
1453
  	unsigned int hash = inet6_addr_hash(addr);
c2e21293c   stephen hemminger   ipv6: convert add...
1454
  	struct inet6_ifaddr *ifp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1455

b67bfe0d4   Sasha Levin   hlist: drop the n...
1456
  	hlist_for_each_entry(ifp, &inet6_addr_lst[hash], addr_lst) {
878628fbf   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
1457
  		if (!net_eq(dev_net(ifp->idev->dev), net))
06bfe655e   Daniel Lezcano   [NETNS][IPV6]: in...
1458
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1459
1460
  		if (ipv6_addr_equal(&ifp->addr, addr)) {
  			if (dev == NULL || ifp->idev->dev == dev)
3e81c6da3   David S. Miller   ipv6: Fix bug in ...
1461
  				return true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1462
1463
  		}
  	}
3e81c6da3   David S. Miller   ipv6: Fix bug in ...
1464
  	return false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1465
  }
7df37ff33   Catalin\(ux\) M. BOIE   IPv6 NAT: Do not ...
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
  /* Compares an address/prefix_len with addresses on device @dev.
   * If one is found it returns true.
   */
  bool ipv6_chk_custom_prefix(const struct in6_addr *addr,
  	const unsigned int prefix_len, struct net_device *dev)
  {
  	struct inet6_dev *idev;
  	struct inet6_ifaddr *ifa;
  	bool ret = false;
  
  	rcu_read_lock();
  	idev = __in6_dev_get(dev);
  	if (idev) {
  		read_lock_bh(&idev->lock);
  		list_for_each_entry(ifa, &idev->addr_list, if_list) {
  			ret = ipv6_prefix_equal(addr, &ifa->addr, prefix_len);
  			if (ret)
  				break;
  		}
  		read_unlock_bh(&idev->lock);
  	}
  	rcu_read_unlock();
  
  	return ret;
  }
  EXPORT_SYMBOL(ipv6_chk_custom_prefix);
b71d1d426   Eric Dumazet   inet: constify ip...
1492
  int ipv6_chk_prefix(const struct in6_addr *addr, struct net_device *dev)
52eeeb848   YOSHIFUJI Hideaki   [IPV6]: Unify ip6...
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
  {
  	struct inet6_dev *idev;
  	struct inet6_ifaddr *ifa;
  	int	onlink;
  
  	onlink = 0;
  	rcu_read_lock();
  	idev = __in6_dev_get(dev);
  	if (idev) {
  		read_lock_bh(&idev->lock);
502a2ffd7   stephen hemminger   ipv6: convert ide...
1503
  		list_for_each_entry(ifa, &idev->addr_list, if_list) {
52eeeb848   YOSHIFUJI Hideaki   [IPV6]: Unify ip6...
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
  			onlink = ipv6_prefix_equal(addr, &ifa->addr,
  						   ifa->prefix_len);
  			if (onlink)
  				break;
  		}
  		read_unlock_bh(&idev->lock);
  	}
  	rcu_read_unlock();
  	return onlink;
  }
52eeeb848   YOSHIFUJI Hideaki   [IPV6]: Unify ip6...
1514
  EXPORT_SYMBOL(ipv6_chk_prefix);
9acd9f3ae   YOSHIFUJI Hideaki   [IPV6]: Make addr...
1515
  struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *addr,
1cab3da6b   Daniel Lezcano   [NETNS][IPV6]: in...
1516
  				     struct net_device *dev, int strict)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1517
  {
b79d1d54c   David S. Miller   ipv6: Fix result ...
1518
  	struct inet6_ifaddr *ifp, *result = NULL;
ddbe50320   Eric Dumazet   ipv6: add ipv6_ad...
1519
  	unsigned int hash = inet6_addr_hash(addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1520

5c578aedc   stephen hemminger   IPv6: convert add...
1521
  	rcu_read_lock_bh();
b67bfe0d4   Sasha Levin   hlist: drop the n...
1522
  	hlist_for_each_entry_rcu_bh(ifp, &inet6_addr_lst[hash], addr_lst) {
878628fbf   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
1523
  		if (!net_eq(dev_net(ifp->idev->dev), net))
1cab3da6b   Daniel Lezcano   [NETNS][IPV6]: in...
1524
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1525
1526
1527
  		if (ipv6_addr_equal(&ifp->addr, addr)) {
  			if (dev == NULL || ifp->idev->dev == dev ||
  			    !(ifp->scope&(IFA_LINK|IFA_HOST) || strict)) {
b79d1d54c   David S. Miller   ipv6: Fix result ...
1528
  				result = ifp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1529
1530
1531
1532
1533
  				in6_ifa_hold(ifp);
  				break;
  			}
  		}
  	}
5c578aedc   stephen hemminger   IPv6: convert add...
1534
  	rcu_read_unlock_bh();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1535

b79d1d54c   David S. Miller   ipv6: Fix result ...
1536
  	return result;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1537
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1538
  /* Gets referenced address, destroys ifaddr */
cc411d0ba   Brian Haley   ipv6: Add IFA_F_D...
1539
  static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1540
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1541
1542
  	if (ifp->flags&IFA_F_PERMANENT) {
  		spin_lock_bh(&ifp->lock);
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
1543
  		addrconf_del_dad_work(ifp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1544
  		ifp->flags |= IFA_F_TENTATIVE;
cc411d0ba   Brian Haley   ipv6: Add IFA_F_D...
1545
1546
  		if (dad_failed)
  			ifp->flags |= IFA_F_DADFAILED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1547
  		spin_unlock_bh(&ifp->lock);
e2577a065   Herbert Xu   ipv6: Send netlin...
1548
1549
  		if (dad_failed)
  			ipv6_ifa_notify(0, ifp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1550
  		in6_ifa_put(ifp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
  	} else if (ifp->flags&IFA_F_TEMPORARY) {
  		struct inet6_ifaddr *ifpub;
  		spin_lock_bh(&ifp->lock);
  		ifpub = ifp->ifpub;
  		if (ifpub) {
  			in6_ifa_hold(ifpub);
  			spin_unlock_bh(&ifp->lock);
  			ipv6_create_tempaddr(ifpub, ifp);
  			in6_ifa_put(ifpub);
  		} else {
  			spin_unlock_bh(&ifp->lock);
  		}
  		ipv6_del_addr(ifp);
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
1564
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1565
  		ipv6_del_addr(ifp);
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
1566
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1567
  }
f2344a131   Herbert Xu   ipv6: Use POSTDAD...
1568
1569
1570
  static int addrconf_dad_end(struct inet6_ifaddr *ifp)
  {
  	int err = -ENOENT;
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
1571
  	spin_lock_bh(&ifp->state_lock);
f2344a131   Herbert Xu   ipv6: Use POSTDAD...
1572
1573
1574
1575
  	if (ifp->state == INET6_IFADDR_STATE_DAD) {
  		ifp->state = INET6_IFADDR_STATE_POSTDAD;
  		err = 0;
  	}
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
1576
  	spin_unlock_bh(&ifp->state_lock);
f2344a131   Herbert Xu   ipv6: Use POSTDAD...
1577
1578
1579
  
  	return err;
  }
3c21edbd1   YOSHIFUJI Hideaki   [IPV6]: Defer IPv...
1580
1581
  void addrconf_dad_failure(struct inet6_ifaddr *ifp)
  {
1b34be74c   YOSHIFUJI Hideaki   ipv6 addrconf: ad...
1582
  	struct inet6_dev *idev = ifp->idev;
9bdd8d40c   Brian Haley   ipv6: Fix incorre...
1583

853dc2e03   Ursula Braun   ipv6: fix refcnt ...
1584
1585
  	if (addrconf_dad_end(ifp)) {
  		in6_ifa_put(ifp);
f2344a131   Herbert Xu   ipv6: Use POSTDAD...
1586
  		return;
853dc2e03   Ursula Braun   ipv6: fix refcnt ...
1587
  	}
f2344a131   Herbert Xu   ipv6: Use POSTDAD...
1588

e87cc4728   Joe Perches   net: Convert net_...
1589
1590
1591
  	net_info_ratelimited("%s: IPv6 duplicate address %pI6c detected!
  ",
  			     ifp->idev->dev->name, &ifp->addr);
9bdd8d40c   Brian Haley   ipv6: Fix incorre...
1592

1b34be74c   YOSHIFUJI Hideaki   ipv6 addrconf: ad...
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
  	if (idev->cnf.accept_dad > 1 && !idev->cnf.disable_ipv6) {
  		struct in6_addr addr;
  
  		addr.s6_addr32[0] = htonl(0xfe800000);
  		addr.s6_addr32[1] = 0;
  
  		if (!ipv6_generate_eui64(addr.s6_addr + 8, idev->dev) &&
  		    ipv6_addr_equal(&ifp->addr, &addr)) {
  			/* DAD failed for link-local based on MAC address */
  			idev->cnf.disable_ipv6 = 1;
9bdd8d40c   Brian Haley   ipv6: Fix incorre...
1603

f32138319   Joe Perches   net: ipv6: Standa...
1604
1605
  			pr_info("%s: IPv6 being disabled!
  ",
9bdd8d40c   Brian Haley   ipv6: Fix incorre...
1606
  				ifp->idev->dev->name);
1b34be74c   YOSHIFUJI Hideaki   ipv6 addrconf: ad...
1607
1608
  		}
  	}
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
1609
1610
1611
1612
1613
1614
  	spin_lock_bh(&ifp->state_lock);
  	/* transition from _POSTDAD to _ERRDAD */
  	ifp->state = INET6_IFADDR_STATE_ERRDAD;
  	spin_unlock_bh(&ifp->state_lock);
  
  	addrconf_mod_dad_work(ifp, 0);
3c21edbd1   YOSHIFUJI Hideaki   [IPV6]: Defer IPv...
1615
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1616
1617
  
  /* Join to solicited addr multicast group. */
b71d1d426   Eric Dumazet   inet: constify ip...
1618
  void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1619
1620
  {
  	struct in6_addr maddr;
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
1621
  	ASSERT_RTNL();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1622
1623
1624
1625
1626
1627
  	if (dev->flags&(IFF_LOOPBACK|IFF_NOARP))
  		return;
  
  	addrconf_addr_solict_mult(addr, &maddr);
  	ipv6_dev_mc_inc(dev, &maddr);
  }
b71d1d426   Eric Dumazet   inet: constify ip...
1628
  void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1629
1630
  {
  	struct in6_addr maddr;
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
1631
  	ASSERT_RTNL();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1632
1633
1634
1635
1636
1637
  	if (idev->dev->flags&(IFF_LOOPBACK|IFF_NOARP))
  		return;
  
  	addrconf_addr_solict_mult(addr, &maddr);
  	__ipv6_dev_mc_dec(idev, &maddr);
  }
20380731b   Arnaldo Carvalho de Melo   [NET]: Fix sparse...
1638
  static void addrconf_join_anycast(struct inet6_ifaddr *ifp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1639
1640
  {
  	struct in6_addr addr;
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
1641
1642
  
  	ASSERT_RTNL();
88ad31491   Hannes Frederic Sowa   ipv6: don't insta...
1643
  	if (ifp->prefix_len >= 127) /* RFC 6164 */
2bda8a0c8   Bjørn Mork   Disable router an...
1644
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1645
1646
1647
1648
1649
  	ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
  	if (ipv6_addr_any(&addr))
  		return;
  	ipv6_dev_ac_inc(ifp->idev->dev, &addr);
  }
20380731b   Arnaldo Carvalho de Melo   [NET]: Fix sparse...
1650
  static void addrconf_leave_anycast(struct inet6_ifaddr *ifp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1651
1652
  {
  	struct in6_addr addr;
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
1653
1654
  
  	ASSERT_RTNL();
88ad31491   Hannes Frederic Sowa   ipv6: don't insta...
1655
  	if (ifp->prefix_len >= 127) /* RFC 6164 */
32019e651   YOSHIFUJI Hideaki   ipv6: Do not leav...
1656
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1657
1658
1659
1660
1661
  	ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
  	if (ipv6_addr_any(&addr))
  		return;
  	__ipv6_dev_ac_dec(ifp->idev, &addr);
  }
073a8e0e1   YOSHIFUJI Hideaki   [IPV6]: ADDRCONF:...
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
  static int addrconf_ifid_eui48(u8 *eui, struct net_device *dev)
  {
  	if (dev->addr_len != ETH_ALEN)
  		return -1;
  	memcpy(eui, dev->dev_addr, 3);
  	memcpy(eui + 5, dev->dev_addr + 3, 3);
  
  	/*
  	 * The zSeries OSA network cards can be shared among various
  	 * OS instances, but the OSA cards have only one MAC address.
  	 * This leads to duplicate address conflicts in conjunction
  	 * with IPv6 if more than one instance uses the same card.
  	 *
  	 * The driver for these cards can deliver a unique 16-bit
  	 * identifier for each instance sharing the same card.  It is
  	 * placed instead of 0xFFFE in the interface identifier.  The
  	 * "u" bit of the interface identifier is not inverted in this
  	 * case.  Hence the resulting interface identifier has local
  	 * scope according to RFC2373.
  	 */
  	if (dev->dev_id) {
  		eui[3] = (dev->dev_id >> 8) & 0xFF;
  		eui[4] = dev->dev_id & 0xFF;
  	} else {
  		eui[3] = 0xFF;
  		eui[4] = 0xFE;
  		eui[0] ^= 2;
  	}
  	return 0;
  }
06a4c1c55   alex.bluesman.smirnov@gmail.com   6lowpan: IPv6 lin...
1692
1693
1694
1695
1696
  static int addrconf_ifid_eui64(u8 *eui, struct net_device *dev)
  {
  	if (dev->addr_len != IEEE802154_ADDR_LEN)
  		return -1;
  	memcpy(eui, dev->dev_addr, 8);
5e98a36ed   YOSHIFUJI Hideaki / 吉藤英明   ipv6 addrconf: Fi...
1697
  	eui[0] ^= 2;
06a4c1c55   alex.bluesman.smirnov@gmail.com   6lowpan: IPv6 lin...
1698
1699
  	return 0;
  }
cb6bf3550   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
  static int addrconf_ifid_ieee1394(u8 *eui, struct net_device *dev)
  {
  	union fwnet_hwaddr *ha;
  
  	if (dev->addr_len != FWNET_ALEN)
  		return -1;
  
  	ha = (union fwnet_hwaddr *)dev->dev_addr;
  
  	memcpy(eui, &ha->uc.uniq_id, sizeof(ha->uc.uniq_id));
  	eui[0] ^= 2;
  	return 0;
  }
073a8e0e1   YOSHIFUJI Hideaki   [IPV6]: ADDRCONF:...
1713
1714
1715
1716
1717
1718
  static int addrconf_ifid_arcnet(u8 *eui, struct net_device *dev)
  {
  	/* XXX: inherit EUI-64 from other interface -- yoshfuji */
  	if (dev->addr_len != ARCNET_ALEN)
  		return -1;
  	memset(eui, 0, 7);
8e5e8f30d   Eldad Zack   net/ipv6/addrconf...
1719
  	eui[7] = *(u8 *)dev->dev_addr;
073a8e0e1   YOSHIFUJI Hideaki   [IPV6]: ADDRCONF:...
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
  	return 0;
  }
  
  static int addrconf_ifid_infiniband(u8 *eui, struct net_device *dev)
  {
  	if (dev->addr_len != INFINIBAND_ALEN)
  		return -1;
  	memcpy(eui, dev->dev_addr + 12, 8);
  	eui[0] |= 2;
  	return 0;
  }
c61393ea8   stephen hemminger   ipv6: make __ipv6...
1731
  static int __ipv6_isatap_ifid(u8 *eui, __be32 addr)
dfd982baf   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1732
  {
9af28511b   Sascha Hlusiak   addrconf: refuse ...
1733
1734
  	if (addr == 0)
  		return -1;
dfd982baf   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
  	eui[0] = (ipv4_is_zeronet(addr) || ipv4_is_private_10(addr) ||
  		  ipv4_is_loopback(addr) || ipv4_is_linklocal_169(addr) ||
  		  ipv4_is_private_172(addr) || ipv4_is_test_192(addr) ||
  		  ipv4_is_anycast_6to4(addr) || ipv4_is_private_192(addr) ||
  		  ipv4_is_test_198(addr) || ipv4_is_multicast(addr) ||
  		  ipv4_is_lbcast(addr)) ? 0x00 : 0x02;
  	eui[1] = 0;
  	eui[2] = 0x5E;
  	eui[3] = 0xFE;
  	memcpy(eui + 4, &addr, 4);
  	return 0;
  }
dfd982baf   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1747
1748
1749
1750
1751
1752
1753
  
  static int addrconf_ifid_sit(u8 *eui, struct net_device *dev)
  {
  	if (dev->priv_flags & IFF_ISATAP)
  		return __ipv6_isatap_ifid(eui, *(__be32 *)dev->dev_addr);
  	return -1;
  }
aee80b54b   stephen hemminger   ipv6: generate li...
1754
1755
1756
1757
  static int addrconf_ifid_gre(u8 *eui, struct net_device *dev)
  {
  	return __ipv6_isatap_ifid(eui, *(__be32 *)dev->dev_addr);
  }
e837735ec   Nicolas Dichtel   ip6_tunnel: ensur...
1758
1759
1760
1761
1762
1763
1764
1765
1766
  static int addrconf_ifid_ip6tnl(u8 *eui, struct net_device *dev)
  {
  	memcpy(eui, dev->perm_addr, 3);
  	memcpy(eui + 5, dev->perm_addr + 3, 3);
  	eui[3] = 0xFF;
  	eui[4] = 0xFE;
  	eui[0] ^= 2;
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1767
1768
1769
1770
1771
  static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
  {
  	switch (dev->type) {
  	case ARPHRD_ETHER:
  	case ARPHRD_FDDI:
073a8e0e1   YOSHIFUJI Hideaki   [IPV6]: ADDRCONF:...
1772
  		return addrconf_ifid_eui48(eui, dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1773
  	case ARPHRD_ARCNET:
073a8e0e1   YOSHIFUJI Hideaki   [IPV6]: ADDRCONF:...
1774
  		return addrconf_ifid_arcnet(eui, dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1775
  	case ARPHRD_INFINIBAND:
073a8e0e1   YOSHIFUJI Hideaki   [IPV6]: ADDRCONF:...
1776
  		return addrconf_ifid_infiniband(eui, dev);
c7dc89c0a   Fred L. Templin   [IPV6]: Add RFC42...
1777
  	case ARPHRD_SIT:
dfd982baf   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1778
  		return addrconf_ifid_sit(eui, dev);
aee80b54b   stephen hemminger   ipv6: generate li...
1779
1780
  	case ARPHRD_IPGRE:
  		return addrconf_ifid_gre(eui, dev);
e74bccb8a   Jukka Rissanen   ipv6: Add checks ...
1781
  	case ARPHRD_6LOWPAN:
06a4c1c55   alex.bluesman.smirnov@gmail.com   6lowpan: IPv6 lin...
1782
1783
  	case ARPHRD_IEEE802154:
  		return addrconf_ifid_eui64(eui, dev);
cb6bf3550   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
1784
1785
  	case ARPHRD_IEEE1394:
  		return addrconf_ifid_ieee1394(eui, dev);
e837735ec   Nicolas Dichtel   ip6_tunnel: ensur...
1786
1787
  	case ARPHRD_TUNNEL6:
  		return addrconf_ifid_ip6tnl(eui, dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
  	}
  	return -1;
  }
  
  static int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev)
  {
  	int err = -1;
  	struct inet6_ifaddr *ifp;
  
  	read_lock_bh(&idev->lock);
602582ca7   Hannes Frederic Sowa   ipv6: optimize li...
1798
1799
1800
  	list_for_each_entry_reverse(ifp, &idev->addr_list, if_list) {
  		if (ifp->scope > IFA_LINK)
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1801
1802
1803
1804
1805
1806
1807
1808
1809
  		if (ifp->scope == IFA_LINK && !(ifp->flags&IFA_F_TENTATIVE)) {
  			memcpy(eui, ifp->addr.s6_addr+8, 8);
  			err = 0;
  			break;
  		}
  	}
  	read_unlock_bh(&idev->lock);
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1810
  /* (re)generation of randomized interface identifier (RFC 3041 3.2, 3.5) */
eb7e05759   Sorin Dumitru   ipv6: remove some...
1811
  static void __ipv6_regen_rndid(struct inet6_dev *idev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1812
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1813
  regen:
955189efb   YOSHIFUJI Hideaki   [IPV6]: ADDRCONF:...
1814
  	get_random_bytes(idev->rndid, sizeof(idev->rndid));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1815
  	idev->rndid[0] &= ~0x02;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1816
1817
1818
1819
1820
1821
1822
  
  	/*
  	 * <draft-ietf-ipngwg-temp-addresses-v2-00.txt>:
  	 * check if generated address is not inappropriate
  	 *
  	 *  - Reserved subnet anycast (RFC 2526)
  	 *	11111101 11....11 1xxxxxxx
c7dc89c0a   Fred L. Templin   [IPV6]: Add RFC42...
1823
  	 *  - ISATAP (RFC4214) 6.1
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1824
1825
1826
1827
  	 *	00-00-5E-FE-xx-xx-xx-xx
  	 *  - value 0
  	 *  - XXX: already assigned to an address on the device
  	 */
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
1828
  	if (idev->rndid[0] == 0xfd &&
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1829
1830
1831
1832
1833
1834
1835
1836
1837
  	    (idev->rndid[1]&idev->rndid[2]&idev->rndid[3]&idev->rndid[4]&idev->rndid[5]&idev->rndid[6]) == 0xff &&
  	    (idev->rndid[7]&0x80))
  		goto regen;
  	if ((idev->rndid[0]|idev->rndid[1]) == 0) {
  		if (idev->rndid[2] == 0x5e && idev->rndid[3] == 0xfe)
  			goto regen;
  		if ((idev->rndid[2]|idev->rndid[3]|idev->rndid[4]|idev->rndid[5]|idev->rndid[6]|idev->rndid[7]) == 0x00)
  			goto regen;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1838
1839
1840
1841
1842
1843
  }
  
  static void ipv6_regen_rndid(unsigned long data)
  {
  	struct inet6_dev *idev = (struct inet6_dev *) data;
  	unsigned long expires;
8814c4b53   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1844
  	rcu_read_lock_bh();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1845
1846
1847
1848
  	write_lock_bh(&idev->lock);
  
  	if (idev->dead)
  		goto out;
eb7e05759   Sorin Dumitru   ipv6: remove some...
1849
  	__ipv6_regen_rndid(idev);
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
1850

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1851
  	expires = jiffies +
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
1852
  		idev->cnf.temp_prefered_lft * HZ -
1f9248e56   Jiri Pirko   neigh: convert pa...
1853
1854
  		idev->cnf.regen_max_retry * idev->cnf.dad_transmits *
  		NEIGH_VAR(idev->nd_parms, RETRANS_TIME) -
784e2710c   Ben Hutchings   ipv6: Use interfa...
1855
  		idev->cnf.max_desync_factor * HZ;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1856
  	if (time_before(expires, jiffies)) {
f32138319   Joe Perches   net: ipv6: Standa...
1857
1858
1859
  		pr_warn("%s: too short regeneration interval; timer disabled for %s
  ",
  			__func__, idev->dev->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1860
1861
1862
1863
1864
1865
1866
1867
  		goto out;
  	}
  
  	if (!mod_timer(&idev->regen_timer, expires))
  		in6_dev_hold(idev);
  
  out:
  	write_unlock_bh(&idev->lock);
8814c4b53   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
1868
  	rcu_read_unlock_bh();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1869
1870
  	in6_dev_put(idev);
  }
eb7e05759   Sorin Dumitru   ipv6: remove some...
1871
  static void  __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr)
8e5e8f30d   Eldad Zack   net/ipv6/addrconf...
1872
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1873
  	if (tmpaddr && memcmp(idev->rndid, &tmpaddr->s6_addr[8], 8) == 0)
eb7e05759   Sorin Dumitru   ipv6: remove some...
1874
  		__ipv6_regen_rndid(idev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1875
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1876
1877
1878
1879
1880
1881
1882
  
  /*
   *	Add prefix route.
   */
  
  static void
  addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev,
e431b8c00   Jamal Hadi Salim   [NETLINK]: Explic...
1883
  		      unsigned long expires, u32 flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1884
  {
86872cb57   Thomas Graf   [IPv6] route: FIB...
1885
1886
1887
1888
1889
1890
1891
  	struct fib6_config cfg = {
  		.fc_table = RT6_TABLE_PREFIX,
  		.fc_metric = IP6_RT_PRIO_ADDRCONF,
  		.fc_ifindex = dev->ifindex,
  		.fc_expires = expires,
  		.fc_dst_len = plen,
  		.fc_flags = RTF_UP | flags,
c346dca10   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
1892
  		.fc_nlinfo.nl_net = dev_net(dev),
f410a1fba   Stephen Hemminger   ipv6: protocol fo...
1893
  		.fc_protocol = RTPROT_KERNEL,
86872cb57   Thomas Graf   [IPv6] route: FIB...
1894
  	};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1895

4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
1896
  	cfg.fc_dst = *pfx;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1897
1898
1899
1900
1901
  
  	/* Prevent useless cloning on PtP SIT.
  	   This thing is done here expecting that the whole
  	   class of non-broadcast devices need not cloning.
  	 */
07a936260   Amerigo Wang   ipv6: use IS_ENAB...
1902
  #if IS_ENABLED(CONFIG_IPV6_SIT)
86872cb57   Thomas Graf   [IPv6] route: FIB...
1903
1904
  	if (dev->type == ARPHRD_SIT && (dev->flags & IFF_POINTOPOINT))
  		cfg.fc_flags |= RTF_NONEXTHOP;
0be669bb3   Joerg Roedel   [IPV6]: Seperate ...
1905
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1906

86872cb57   Thomas Graf   [IPv6] route: FIB...
1907
  	ip6_route_add(&cfg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1908
  }
14ef37b6d   Andreas Hofmeister   ipv6: fix route l...
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
  
  static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx,
  						  int plen,
  						  const struct net_device *dev,
  						  u32 flags, u32 noflags)
  {
  	struct fib6_node *fn;
  	struct rt6_info *rt = NULL;
  	struct fib6_table *table;
  
  	table = fib6_get_table(dev_net(dev), RT6_TABLE_PREFIX);
  	if (table == NULL)
  		return NULL;
5744dd9b7   Li RongQing   ipv6: replace wri...
1922
  	read_lock_bh(&table->tb6_lock);
14ef37b6d   Andreas Hofmeister   ipv6: fix route l...
1923
1924
1925
1926
  	fn = fib6_locate(&table->tb6_root, pfx, plen, NULL, 0);
  	if (!fn)
  		goto out;
  	for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) {
d19185428   David S. Miller   ipv6: Kill rt6i_d...
1927
  		if (rt->dst.dev->ifindex != dev->ifindex)
14ef37b6d   Andreas Hofmeister   ipv6: fix route l...
1928
1929
1930
  			continue;
  		if ((rt->rt6i_flags & flags) != flags)
  			continue;
85da53bf1   Romain Kuntz   ipv6: fix the nof...
1931
  		if ((rt->rt6i_flags & noflags) != 0)
14ef37b6d   Andreas Hofmeister   ipv6: fix route l...
1932
1933
1934
1935
1936
  			continue;
  		dst_hold(&rt->dst);
  		break;
  	}
  out:
5744dd9b7   Li RongQing   ipv6: replace wri...
1937
  	read_unlock_bh(&table->tb6_lock);
14ef37b6d   Andreas Hofmeister   ipv6: fix route l...
1938
1939
  	return rt;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1940
1941
1942
1943
  /* Create "default" multicast route to the interface */
  
  static void addrconf_add_mroute(struct net_device *dev)
  {
86872cb57   Thomas Graf   [IPv6] route: FIB...
1944
1945
1946
1947
1948
1949
  	struct fib6_config cfg = {
  		.fc_table = RT6_TABLE_LOCAL,
  		.fc_metric = IP6_RT_PRIO_ADDRCONF,
  		.fc_ifindex = dev->ifindex,
  		.fc_dst_len = 8,
  		.fc_flags = RTF_UP,
c346dca10   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
1950
  		.fc_nlinfo.nl_net = dev_net(dev),
86872cb57   Thomas Graf   [IPv6] route: FIB...
1951
1952
1953
1954
1955
  	};
  
  	ipv6_addr_set(&cfg.fc_dst, htonl(0xFF000000), 0, 0, 0);
  
  	ip6_route_add(&cfg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1956
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1957
1958
1959
1960
1961
  static struct inet6_dev *addrconf_add_dev(struct net_device *dev)
  {
  	struct inet6_dev *idev;
  
  	ASSERT_RTNL();
e21e8467d   Stephen Hemminger   addrconf: checkpa...
1962
1963
  	idev = ipv6_find_idev(dev);
  	if (!idev)
64e724f62   Brian Haley   ipv6: Don't add r...
1964
1965
1966
1967
  		return ERR_PTR(-ENOBUFS);
  
  	if (idev->cnf.disable_ipv6)
  		return ERR_PTR(-EACCES);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1968
1969
  
  	/* Add default multicast route */
4af04aba9   Li Wei   ipv6: Fix for add...
1970
1971
  	if (!(dev->flags & IFF_LOOPBACK))
  		addrconf_add_mroute(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1972

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1973
1974
  	return idev;
  }
53bd67491   Jiri Pirko   ipv6 addrconf: in...
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
  static void manage_tempaddrs(struct inet6_dev *idev,
  			     struct inet6_ifaddr *ifp,
  			     __u32 valid_lft, __u32 prefered_lft,
  			     bool create, unsigned long now)
  {
  	u32 flags;
  	struct inet6_ifaddr *ift;
  
  	read_lock_bh(&idev->lock);
  	/* update all temporary addresses in the list */
  	list_for_each_entry(ift, &idev->tempaddr_list, tmp_list) {
  		int age, max_valid, max_prefered;
  
  		if (ifp != ift->ifpub)
  			continue;
  
  		/* RFC 4941 section 3.3:
  		 * If a received option will extend the lifetime of a public
  		 * address, the lifetimes of temporary addresses should
  		 * be extended, subject to the overall constraint that no
  		 * temporary addresses should ever remain "valid" or "preferred"
  		 * for a time longer than (TEMP_VALID_LIFETIME) or
  		 * (TEMP_PREFERRED_LIFETIME - DESYNC_FACTOR), respectively.
  		 */
  		age = (now - ift->cstamp) / HZ;
  		max_valid = idev->cnf.temp_valid_lft - age;
  		if (max_valid < 0)
  			max_valid = 0;
  
  		max_prefered = idev->cnf.temp_prefered_lft -
  			       idev->cnf.max_desync_factor - age;
  		if (max_prefered < 0)
  			max_prefered = 0;
  
  		if (valid_lft > max_valid)
  			valid_lft = max_valid;
  
  		if (prefered_lft > max_prefered)
  			prefered_lft = max_prefered;
  
  		spin_lock(&ift->lock);
  		flags = ift->flags;
  		ift->valid_lft = valid_lft;
  		ift->prefered_lft = prefered_lft;
  		ift->tstamp = now;
  		if (prefered_lft > 0)
  			ift->flags &= ~IFA_F_DEPRECATED;
  
  		spin_unlock(&ift->lock);
  		if (!(flags&IFA_F_TENTATIVE))
  			ipv6_ifa_notify(0, ift);
  	}
  
  	if ((create || list_empty(&idev->tempaddr_list)) &&
  	    idev->cnf.use_tempaddr > 0) {
  		/* When a new public address is created as described
  		 * in [ADDRCONF], also create a new temporary address.
  		 * Also create a temporary address if it's enabled but
  		 * no temporary address currently exists.
  		 */
  		read_unlock_bh(&idev->lock);
  		ipv6_create_tempaddr(ifp, NULL);
  	} else {
  		read_unlock_bh(&idev->lock);
  	}
  }
e6bff995f   Neil Horman   ipv6: Check RA fo...
2041
  void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2042
2043
2044
2045
2046
  {
  	struct prefix_info *pinfo;
  	__u32 valid_lft;
  	__u32 prefered_lft;
  	int addr_type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2047
  	struct inet6_dev *in6_dev;
56d417b12   Brian Haley   IPv6: Add 'autoco...
2048
  	struct net *net = dev_net(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2049
2050
  
  	pinfo = (struct prefix_info *) opt;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
2051

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2052
  	if (len < sizeof(struct prefix_info)) {
ba3542e15   dingtianhong   ipv6: convert the...
2053
2054
  		ADBG("addrconf: prefix option too short
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2055
2056
  		return;
  	}
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
2057

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
  	/*
  	 *	Validation checks ([ADDRCONF], page 19)
  	 */
  
  	addr_type = ipv6_addr_type(&pinfo->prefix);
  
  	if (addr_type & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL))
  		return;
  
  	valid_lft = ntohl(pinfo->valid);
  	prefered_lft = ntohl(pinfo->prefered);
  
  	if (prefered_lft > valid_lft) {
e87cc4728   Joe Perches   net: Convert net_...
2071
2072
  		net_warn_ratelimited("addrconf: prefix option has invalid lifetime
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2073
2074
2075
2076
2077
2078
  		return;
  	}
  
  	in6_dev = in6_dev_get(dev);
  
  	if (in6_dev == NULL) {
e87cc4728   Joe Perches   net: Convert net_...
2079
2080
2081
  		net_dbg_ratelimited("addrconf: device %s not configured
  ",
  				    dev->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2082
2083
2084
2085
2086
2087
2088
2089
  		return;
  	}
  
  	/*
  	 *	Two things going on here:
  	 *	1) Add routes for on-link prefixes
  	 *	2) Configure prefixes with the auto flag set
  	 */
4bed72e4f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
2090
2091
2092
  	if (pinfo->onlink) {
  		struct rt6_info *rt;
  		unsigned long rt_expires;
6f704992d   YOSHIFUJI Hideaki   ipv6 addrconf: Al...
2093
2094
2095
2096
2097
  		/* Avoid arithmetic overflow. Really, we could
  		 * save rt_expires in seconds, likely valid_lft,
  		 * but it would require division in fib gc, that it
  		 * not good.
  		 */
4bed72e4f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
2098
2099
2100
2101
  		if (HZ > USER_HZ)
  			rt_expires = addrconf_timeout_fixup(valid_lft, HZ);
  		else
  			rt_expires = addrconf_timeout_fixup(valid_lft, USER_HZ);
3dd4bc68f   YOSHIFUJI Hideaki   [IPV6]: Fix route...
2102

4bed72e4f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
2103
2104
  		if (addrconf_finite_timeout(rt_expires))
  			rt_expires *= HZ;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2105

14ef37b6d   Andreas Hofmeister   ipv6: fix route l...
2106
2107
2108
2109
2110
  		rt = addrconf_get_prefix_route(&pinfo->prefix,
  					       pinfo->prefix_len,
  					       dev,
  					       RTF_ADDRCONF | RTF_PREFIX_RT,
  					       RTF_GATEWAY | RTF_DEFAULT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2111

14ef37b6d   Andreas Hofmeister   ipv6: fix route l...
2112
  		if (rt) {
6f704992d   YOSHIFUJI Hideaki   ipv6 addrconf: Al...
2113
2114
2115
2116
  			/* Autoconf prefix route */
  			if (valid_lft == 0) {
  				ip6_del_rt(rt);
  				rt = NULL;
4bed72e4f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
2117
  			} else if (addrconf_finite_timeout(rt_expires)) {
6f704992d   YOSHIFUJI Hideaki   ipv6 addrconf: Al...
2118
  				/* not infinity */
1716a9610   Gao feng   ipv6: fix problem...
2119
  				rt6_set_expires(rt, jiffies + rt_expires);
6f704992d   YOSHIFUJI Hideaki   ipv6 addrconf: Al...
2120
  			} else {
1716a9610   Gao feng   ipv6: fix problem...
2121
  				rt6_clean_expires(rt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2122
2123
  			}
  		} else if (valid_lft) {
6f704992d   YOSHIFUJI Hideaki   ipv6 addrconf: Al...
2124
  			clock_t expires = 0;
4bed72e4f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
2125
2126
  			int flags = RTF_ADDRCONF | RTF_PREFIX_RT;
  			if (addrconf_finite_timeout(rt_expires)) {
6f704992d   YOSHIFUJI Hideaki   ipv6 addrconf: Al...
2127
2128
2129
2130
  				/* not infinity */
  				flags |= RTF_EXPIRES;
  				expires = jiffies_to_clock_t(rt_expires);
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2131
  			addrconf_prefix_route(&pinfo->prefix, pinfo->prefix_len,
6f704992d   YOSHIFUJI Hideaki   ipv6 addrconf: Al...
2132
  					      dev, expires, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2133
  		}
94e187c01   Amerigo Wang   ipv6: introduce i...
2134
  		ip6_rt_put(rt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2135
2136
2137
2138
2139
  	}
  
  	/* Try to figure out our local address for this prefix */
  
  	if (pinfo->autoconf && in6_dev->cnf.autoconf) {
8e5e8f30d   Eldad Zack   net/ipv6/addrconf...
2140
  		struct inet6_ifaddr *ifp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2141
2142
  		struct in6_addr addr;
  		int create = 0, update_lft = 0;
617fe29d4   Daniel Borkmann   net: ipv6: only i...
2143
  		bool tokenized = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2144
2145
2146
  
  		if (pinfo->prefix_len == 64) {
  			memcpy(&addr, &pinfo->prefix, 8);
f53adae4e   Daniel Borkmann   net: ipv6: add to...
2147
2148
2149
2150
2151
2152
  
  			if (!ipv6_addr_any(&in6_dev->token)) {
  				read_lock_bh(&in6_dev->lock);
  				memcpy(addr.s6_addr + 8,
  				       in6_dev->token.s6_addr + 8, 8);
  				read_unlock_bh(&in6_dev->lock);
617fe29d4   Daniel Borkmann   net: ipv6: only i...
2153
  				tokenized = true;
f53adae4e   Daniel Borkmann   net: ipv6: add to...
2154
2155
  			} else if (ipv6_generate_eui64(addr.s6_addr + 8, dev) &&
  				   ipv6_inherit_eui64(addr.s6_addr + 8, in6_dev)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2156
2157
2158
2159
2160
  				in6_dev_put(in6_dev);
  				return;
  			}
  			goto ok;
  		}
e87cc4728   Joe Perches   net: Convert net_...
2161
2162
2163
  		net_dbg_ratelimited("IPv6 addrconf: prefix with wrong length %d
  ",
  				    pinfo->prefix_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2164
2165
2166
2167
  		in6_dev_put(in6_dev);
  		return;
  
  ok:
53b7997fd   YOSHIFUJI Hideaki   ipv6 netns: Make ...
2168
  		ifp = ipv6_get_ifaddr(net, &addr, dev, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2169
2170
2171
  
  		if (ifp == NULL && valid_lft) {
  			int max_addresses = in6_dev->cnf.max_addresses;
95c385b4d   Neil Horman   [IPV6] ADDRCONF: ...
2172
2173
2174
2175
  			u32 addr_flags = 0;
  
  #ifdef CONFIG_IPV6_OPTIMISTIC_DAD
  			if (in6_dev->cnf.optimistic_dad &&
e6bff995f   Neil Horman   ipv6: Check RA fo...
2176
  			    !net->ipv6.devconf_all->forwarding && sllao)
95c385b4d   Neil Horman   [IPV6] ADDRCONF: ...
2177
2178
  				addr_flags = IFA_F_OPTIMISTIC;
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2179
2180
2181
2182
2183
2184
  
  			/* Do not allow to create too much of autoconfigured
  			 * addresses; this would be too easy way to crash kernel.
  			 */
  			if (!max_addresses ||
  			    ipv6_count_addresses(in6_dev) < max_addresses)
3f8f52982   Jiri Pirko   ipv6: move peer_a...
2185
2186
  				ifp = ipv6_add_addr(in6_dev, &addr, NULL,
  						    pinfo->prefix_len,
95c385b4d   Neil Horman   [IPV6] ADDRCONF: ...
2187
  						    addr_type&IPV6_ADDR_SCOPE_MASK,
8a226b2cf   Jiri Benc   ipv6: prevent rac...
2188
2189
  						    addr_flags, valid_lft,
  						    prefered_lft);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2190

3f0d2ba0b   YOSHIFUJI Hideaki / 吉藤英明   ipv6: Use IS_ERR_...
2191
  			if (IS_ERR_OR_NULL(ifp)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2192
2193
2194
  				in6_dev_put(in6_dev);
  				return;
  			}
8a226b2cf   Jiri Benc   ipv6: prevent rac...
2195
2196
  			update_lft = 0;
  			create = 1;
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
2197
2198
  			spin_lock_bh(&ifp->lock);
  			ifp->flags |= IFA_F_MANAGETEMPADDR;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2199
  			ifp->cstamp = jiffies;
617fe29d4   Daniel Borkmann   net: ipv6: only i...
2200
  			ifp->tokenized = tokenized;
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
2201
  			spin_unlock_bh(&ifp->lock);
cf22f9a2b   David S. Miller   ipv6: Remove unus...
2202
  			addrconf_dad_start(ifp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2203
2204
2205
  		}
  
  		if (ifp) {
479840ffd   Jiri Pirko   ipv6 addrconf: ex...
2206
  			u32 flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2207
  			unsigned long now;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2208
2209
2210
2211
2212
2213
2214
2215
2216
  			u32 stored_lft;
  
  			/* update lifetime (RFC2462 5.5.3 e) */
  			spin_lock(&ifp->lock);
  			now = jiffies;
  			if (ifp->valid_lft > (now - ifp->tstamp) / HZ)
  				stored_lft = ifp->valid_lft - (now - ifp->tstamp) / HZ;
  			else
  				stored_lft = 0;
8a226b2cf   Jiri Benc   ipv6: prevent rac...
2217
  			if (!update_lft && !create && stored_lft) {
c9d55d5bf   Paul Marks   ipv6: Fix preferr...
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
  				const u32 minimum_lft = min(
  					stored_lft, (u32)MIN_VALID_LIFETIME);
  				valid_lft = max(valid_lft, minimum_lft);
  
  				/* RFC4862 Section 5.5.3e:
  				 * "Note that the preferred lifetime of the
  				 *  corresponding address is always reset to
  				 *  the Preferred Lifetime in the received
  				 *  Prefix Information option, regardless of
  				 *  whether the valid lifetime is also reset or
  				 *  ignored."
  				 *
  				 * So we should always update prefered_lft here.
  				 */
  				update_lft = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
  			}
  
  			if (update_lft) {
  				ifp->valid_lft = valid_lft;
  				ifp->prefered_lft = prefered_lft;
  				ifp->tstamp = now;
  				flags = ifp->flags;
  				ifp->flags &= ~IFA_F_DEPRECATED;
  				spin_unlock(&ifp->lock);
  
  				if (!(flags&IFA_F_TENTATIVE))
  					ipv6_ifa_notify(0, ifp);
  			} else
  				spin_unlock(&ifp->lock);
53bd67491   Jiri Pirko   ipv6 addrconf: in...
2247
2248
  			manage_tempaddrs(in6_dev, ifp, valid_lft, prefered_lft,
  					 create, now);
5d9efa7ee   David S. Miller   ipv6: Remove priv...
2249

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2250
  			in6_ifa_put(ifp);
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
2251
  			addrconf_verify();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
  		}
  	}
  	inet6_prefix_notify(RTM_NEWPREFIX, in6_dev, pinfo);
  	in6_dev_put(in6_dev);
  }
  
  /*
   *	Set destination address.
   *	Special case for SIT interfaces where we create a new "virtual"
   *	device.
   */
af2849377   Daniel Lezcano   [NETNS][IPV6] add...
2263
  int addrconf_set_dstaddr(struct net *net, void __user *arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
  {
  	struct in6_ifreq ireq;
  	struct net_device *dev;
  	int err = -EINVAL;
  
  	rtnl_lock();
  
  	err = -EFAULT;
  	if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
  		goto err_exit;
af2849377   Daniel Lezcano   [NETNS][IPV6] add...
2274
  	dev = __dev_get_by_index(net, ireq.ifr6_ifindex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2275
2276
2277
2278
  
  	err = -ENODEV;
  	if (dev == NULL)
  		goto err_exit;
07a936260   Amerigo Wang   ipv6: use IS_ENAB...
2279
  #if IS_ENABLED(CONFIG_IPV6_SIT)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2280
  	if (dev->type == ARPHRD_SIT) {
5bc3eb7e2   Stephen Hemminger   ip: convert to ne...
2281
  		const struct net_device_ops *ops = dev->netdev_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2282
  		struct ifreq ifr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
  		struct ip_tunnel_parm p;
  
  		err = -EADDRNOTAVAIL;
  		if (!(ipv6_addr_type(&ireq.ifr6_addr) & IPV6_ADDR_COMPATv4))
  			goto err_exit;
  
  		memset(&p, 0, sizeof(p));
  		p.iph.daddr = ireq.ifr6_addr.s6_addr32[3];
  		p.iph.saddr = 0;
  		p.iph.version = 4;
  		p.iph.ihl = 5;
  		p.iph.protocol = IPPROTO_IPV6;
  		p.iph.ttl = 64;
d20b3109e   Stephen Hemminger   [IPV6]: addrconf ...
2296
  		ifr.ifr_ifru.ifru_data = (__force void __user *)&p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2297

5bc3eb7e2   Stephen Hemminger   ip: convert to ne...
2298
2299
2300
2301
2302
2303
2304
2305
  		if (ops->ndo_do_ioctl) {
  			mm_segment_t oldfs = get_fs();
  
  			set_fs(KERNEL_DS);
  			err = ops->ndo_do_ioctl(dev, &ifr, SIOCADDTUNNEL);
  			set_fs(oldfs);
  		} else
  			err = -EOPNOTSUPP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2306
2307
2308
  
  		if (err == 0) {
  			err = -ENOBUFS;
af2849377   Daniel Lezcano   [NETNS][IPV6] add...
2309
2310
  			dev = __dev_get_by_name(net, p.name);
  			if (!dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2311
2312
2313
2314
  				goto err_exit;
  			err = dev_open(dev);
  		}
  	}
0be669bb3   Joerg Roedel   [IPV6]: Seperate ...
2315
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2316
2317
2318
2319
2320
2321
2322
2323
2324
  
  err_exit:
  	rtnl_unlock();
  	return err;
  }
  
  /*
   *	Manual configuration of address on an interface
   */
479840ffd   Jiri Pirko   ipv6 addrconf: ex...
2325
2326
  static int inet6_addr_add(struct net *net, int ifindex,
  			  const struct in6_addr *pfx,
caeaba790   Nicolas Dichtel   ipv6: add support...
2327
  			  const struct in6_addr *peer_pfx,
479840ffd   Jiri Pirko   ipv6 addrconf: ex...
2328
2329
  			  unsigned int plen, __u32 ifa_flags,
  			  __u32 prefered_lft, __u32 valid_lft)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2330
2331
2332
2333
2334
  {
  	struct inet6_ifaddr *ifp;
  	struct inet6_dev *idev;
  	struct net_device *dev;
  	int scope;
6f704992d   YOSHIFUJI Hideaki   ipv6 addrconf: Al...
2335
2336
  	u32 flags;
  	clock_t expires;
4bed72e4f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
2337
  	unsigned long timeout;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2338
2339
  
  	ASSERT_RTNL();
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
2340

24ef0da7b   Thomas Graf   [IPV6] ADDRCONF: ...
2341
2342
  	if (plen > 128)
  		return -EINVAL;
0778769d3   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
2343
2344
2345
  	/* check the lifetime */
  	if (!valid_lft || prefered_lft > valid_lft)
  		return -EINVAL;
53bd67491   Jiri Pirko   ipv6 addrconf: in...
2346
2347
  	if (ifa_flags & IFA_F_MANAGETEMPADDR && plen != 64)
  		return -EINVAL;
af2849377   Daniel Lezcano   [NETNS][IPV6] add...
2348
2349
  	dev = __dev_get_by_index(net, ifindex);
  	if (!dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2350
  		return -ENODEV;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
2351

64e724f62   Brian Haley   ipv6: Don't add r...
2352
2353
2354
  	idev = addrconf_add_dev(dev);
  	if (IS_ERR(idev))
  		return PTR_ERR(idev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2355
2356
  
  	scope = ipv6_addr_scope(pfx);
4bed72e4f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
2357
2358
2359
2360
  	timeout = addrconf_timeout_fixup(valid_lft, HZ);
  	if (addrconf_finite_timeout(timeout)) {
  		expires = jiffies_to_clock_t(timeout * HZ);
  		valid_lft = timeout;
6f704992d   YOSHIFUJI Hideaki   ipv6 addrconf: Al...
2361
  		flags = RTF_EXPIRES;
4bed72e4f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
2362
2363
2364
2365
  	} else {
  		expires = 0;
  		flags = 0;
  		ifa_flags |= IFA_F_PERMANENT;
6f704992d   YOSHIFUJI Hideaki   ipv6 addrconf: Al...
2366
  	}
0778769d3   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
2367

4bed72e4f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
2368
2369
2370
2371
2372
2373
  	timeout = addrconf_timeout_fixup(prefered_lft, HZ);
  	if (addrconf_finite_timeout(timeout)) {
  		if (timeout == 0)
  			ifa_flags |= IFA_F_DEPRECATED;
  		prefered_lft = timeout;
  	}
0778769d3   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
2374

8a226b2cf   Jiri Benc   ipv6: prevent rac...
2375
2376
  	ifp = ipv6_add_addr(idev, pfx, peer_pfx, plen, scope, ifa_flags,
  			    valid_lft, prefered_lft);
0778769d3   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
2377

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2378
  	if (!IS_ERR(ifp)) {
761aac737   Thomas Haller   ipv6 addrconf: ad...
2379
2380
2381
2382
  		if (!(ifa_flags & IFA_F_NOPREFIXROUTE)) {
  			addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev,
  					      expires, flags);
  		}
95c385b4d   Neil Horman   [IPV6] ADDRCONF: ...
2383
2384
2385
2386
2387
  		/*
  		 * Note that section 3.1 of RFC 4429 indicates
  		 * that the Optimistic flag should not be set for
  		 * manually configured addresses
  		 */
cf22f9a2b   David S. Miller   ipv6: Remove unus...
2388
  		addrconf_dad_start(ifp);
53bd67491   Jiri Pirko   ipv6 addrconf: in...
2389
2390
2391
  		if (ifa_flags & IFA_F_MANAGETEMPADDR)
  			manage_tempaddrs(idev, ifp, valid_lft, prefered_lft,
  					 true, jiffies);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2392
  		in6_ifa_put(ifp);
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
2393
  		addrconf_verify_rtnl();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2394
2395
2396
2397
2398
  		return 0;
  	}
  
  	return PTR_ERR(ifp);
  }
b71d1d426   Eric Dumazet   inet: constify ip...
2399
  static int inet6_addr_del(struct net *net, int ifindex, const struct in6_addr *pfx,
24ef0da7b   Thomas Graf   [IPV6] ADDRCONF: ...
2400
  			  unsigned int plen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2401
2402
2403
2404
  {
  	struct inet6_ifaddr *ifp;
  	struct inet6_dev *idev;
  	struct net_device *dev;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
2405

24ef0da7b   Thomas Graf   [IPV6] ADDRCONF: ...
2406
2407
  	if (plen > 128)
  		return -EINVAL;
af2849377   Daniel Lezcano   [NETNS][IPV6] add...
2408
2409
  	dev = __dev_get_by_index(net, ifindex);
  	if (!dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2410
  		return -ENODEV;
7eaa48a45   David S. Miller   Revert "ipv6: fix...
2411
  	if ((idev = __in6_dev_get(dev)) == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2412
2413
2414
  		return -ENXIO;
  
  	read_lock_bh(&idev->lock);
502a2ffd7   stephen hemminger   ipv6: convert ide...
2415
  	list_for_each_entry(ifp, &idev->addr_list, if_list) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2416
2417
2418
2419
  		if (ifp->prefix_len == plen &&
  		    ipv6_addr_equal(pfx, &ifp->addr)) {
  			in6_ifa_hold(ifp);
  			read_unlock_bh(&idev->lock);
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
2420

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2421
  			ipv6_del_addr(ifp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2422
2423
2424
2425
2426
2427
  			return 0;
  		}
  	}
  	read_unlock_bh(&idev->lock);
  	return -EADDRNOTAVAIL;
  }
af2849377   Daniel Lezcano   [NETNS][IPV6] add...
2428
  int addrconf_add_ifaddr(struct net *net, void __user *arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2429
2430
2431
  {
  	struct in6_ifreq ireq;
  	int err;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
2432

af31f412c   Eric W. Biederman   net: Allow userns...
2433
  	if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2434
  		return -EPERM;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
2435

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2436
2437
2438
2439
  	if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
  		return -EFAULT;
  
  	rtnl_lock();
caeaba790   Nicolas Dichtel   ipv6: add support...
2440
  	err = inet6_addr_add(net, ireq.ifr6_ifindex, &ireq.ifr6_addr, NULL,
af2849377   Daniel Lezcano   [NETNS][IPV6] add...
2441
2442
  			     ireq.ifr6_prefixlen, IFA_F_PERMANENT,
  			     INFINITY_LIFE_TIME, INFINITY_LIFE_TIME);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2443
2444
2445
  	rtnl_unlock();
  	return err;
  }
af2849377   Daniel Lezcano   [NETNS][IPV6] add...
2446
  int addrconf_del_ifaddr(struct net *net, void __user *arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2447
2448
2449
  {
  	struct in6_ifreq ireq;
  	int err;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
2450

af31f412c   Eric W. Biederman   net: Allow userns...
2451
  	if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2452
2453
2454
2455
2456
2457
  		return -EPERM;
  
  	if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
  		return -EFAULT;
  
  	rtnl_lock();
af2849377   Daniel Lezcano   [NETNS][IPV6] add...
2458
2459
  	err = inet6_addr_del(net, ireq.ifr6_ifindex, &ireq.ifr6_addr,
  			     ireq.ifr6_prefixlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2460
2461
2462
  	rtnl_unlock();
  	return err;
  }
b5f348e5a   Ilpo Järvinen   ipv6/addrconf: co...
2463
2464
2465
2466
  static void add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
  		     int plen, int scope)
  {
  	struct inet6_ifaddr *ifp;
8a226b2cf   Jiri Benc   ipv6: prevent rac...
2467
  	ifp = ipv6_add_addr(idev, addr, NULL, plen,
07edd741c   Hannes Frederic Sowa   ipv6: add link-lo...
2468
2469
  			    scope, IFA_F_PERMANENT,
  			    INFINITY_LIFE_TIME, INFINITY_LIFE_TIME);
b5f348e5a   Ilpo Järvinen   ipv6/addrconf: co...
2470
2471
2472
2473
2474
2475
2476
2477
  	if (!IS_ERR(ifp)) {
  		spin_lock_bh(&ifp->lock);
  		ifp->flags &= ~IFA_F_TENTATIVE;
  		spin_unlock_bh(&ifp->lock);
  		ipv6_ifa_notify(RTM_NEWADDR, ifp);
  		in6_ifa_put(ifp);
  	}
  }
07a936260   Amerigo Wang   ipv6: use IS_ENAB...
2478
  #if IS_ENABLED(CONFIG_IPV6_SIT)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2479
2480
  static void sit_add_v4_addrs(struct inet6_dev *idev)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2481
2482
  	struct in6_addr addr;
  	struct net_device *dev;
c346dca10   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
2483
  	struct net *net = dev_net(idev->dev);
929c9cf31   Nicolas Dichtel   sit: fix prefix l...
2484
  	int scope, plen;
f0e2acfa3   Nicolas Dichtel   sit: link local r...
2485
  	u32 pflags = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2486
2487
2488
2489
2490
2491
2492
2493
2494
  
  	ASSERT_RTNL();
  
  	memset(&addr, 0, sizeof(struct in6_addr));
  	memcpy(&addr.s6_addr32[3], idev->dev->dev_addr, 4);
  
  	if (idev->dev->flags&IFF_POINTOPOINT) {
  		addr.s6_addr32[0] = htonl(0xfe800000);
  		scope = IFA_LINK;
929c9cf31   Nicolas Dichtel   sit: fix prefix l...
2495
  		plen = 64;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2496
2497
  	} else {
  		scope = IPV6_ADDR_COMPATv4;
929c9cf31   Nicolas Dichtel   sit: fix prefix l...
2498
  		plen = 96;
f0e2acfa3   Nicolas Dichtel   sit: link local r...
2499
  		pflags |= RTF_NONEXTHOP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2500
2501
2502
  	}
  
  	if (addr.s6_addr32[3]) {
929c9cf31   Nicolas Dichtel   sit: fix prefix l...
2503
  		add_addr(idev, &addr, plen, scope);
f0e2acfa3   Nicolas Dichtel   sit: link local r...
2504
  		addrconf_prefix_route(&addr, plen, idev->dev, 0, pflags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2505
2506
  		return;
  	}
6fda73500   Benjamin Thery   [NETNS][IPV6] add...
2507
  	for_each_netdev(net, dev) {
8e5e8f30d   Eldad Zack   net/ipv6/addrconf...
2508
  		struct in_device *in_dev = __in_dev_get_rtnl(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2509
  		if (in_dev && (dev->flags & IFF_UP)) {
8e5e8f30d   Eldad Zack   net/ipv6/addrconf...
2510
  			struct in_ifaddr *ifa;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2511
2512
2513
2514
  
  			int flag = scope;
  
  			for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
  
  				addr.s6_addr32[3] = ifa->ifa_local;
  
  				if (ifa->ifa_scope == RT_SCOPE_LINK)
  					continue;
  				if (ifa->ifa_scope >= RT_SCOPE_HOST) {
  					if (idev->dev->flags&IFF_POINTOPOINT)
  						continue;
  					flag |= IFA_HOST;
  				}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2525

b5f348e5a   Ilpo Järvinen   ipv6/addrconf: co...
2526
  				add_addr(idev, &addr, plen, flag);
f0e2acfa3   Nicolas Dichtel   sit: link local r...
2527
2528
  				addrconf_prefix_route(&addr, plen, idev->dev, 0,
  						      pflags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2529
2530
  			}
  		}
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
2531
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2532
  }
0be669bb3   Joerg Roedel   [IPV6]: Seperate ...
2533
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2534
2535
2536
2537
  
  static void init_loopback(struct net_device *dev)
  {
  	struct inet6_dev  *idev;
25fb6ca4e   Balakumaran Kannan   net IPv6 : Fix br...
2538
2539
2540
  	struct net_device *sp_dev;
  	struct inet6_ifaddr *sp_ifa;
  	struct rt6_info *sp_rt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2541
2542
2543
2544
  
  	/* ::1 */
  
  	ASSERT_RTNL();
7eaa48a45   David S. Miller   Revert "ipv6: fix...
2545
  	if ((idev = ipv6_find_idev(dev)) == NULL) {
91df42bed   Joe Perches   net: ipv4 and ipv...
2546
2547
  		pr_debug("%s: add_dev failed
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2548
2549
  		return;
  	}
b5f348e5a   Ilpo Järvinen   ipv6/addrconf: co...
2550
  	add_addr(idev, &in6addr_loopback, 128, IFA_HOST);
25fb6ca4e   Balakumaran Kannan   net IPv6 : Fix br...
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
  
  	/* Add routes to other interface's IPv6 addresses */
  	for_each_netdev(dev_net(dev), sp_dev) {
  		if (!strcmp(sp_dev->name, dev->name))
  			continue;
  
  		idev = __in6_dev_get(sp_dev);
  		if (!idev)
  			continue;
  
  		read_lock_bh(&idev->lock);
  		list_for_each_entry(sp_ifa, &idev->addr_list, if_list) {
  
  			if (sp_ifa->flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE))
  				continue;
33d99113b   Gao feng   ipv6: reallocate ...
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
  			if (sp_ifa->rt) {
  				/* This dst has been added to garbage list when
  				 * lo device down, release this obsolete dst and
  				 * reallocate a new router for ifa.
  				 */
  				if (sp_ifa->rt->dst.obsolete > 0) {
  					ip6_rt_put(sp_ifa->rt);
  					sp_ifa->rt = NULL;
  				} else {
  					continue;
  				}
  			}
a881ae1f6   Gao feng   ipv6: don't call ...
2578

57ec0afe2   François-Xavier Le Bail   ipv6: fix third a...
2579
  			sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, false);
25fb6ca4e   Balakumaran Kannan   net IPv6 : Fix br...
2580
2581
  
  			/* Failure cases are ignored */
534c87792   Gao feng   ipv6: assign rt6_...
2582
2583
  			if (!IS_ERR(sp_rt)) {
  				sp_ifa->rt = sp_rt;
25fb6ca4e   Balakumaran Kannan   net IPv6 : Fix br...
2584
  				ip6_ins_rt(sp_rt);
534c87792   Gao feng   ipv6: assign rt6_...
2585
  			}
25fb6ca4e   Balakumaran Kannan   net IPv6 : Fix br...
2586
2587
2588
  		}
  		read_unlock_bh(&idev->lock);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2589
  }
b71d1d426   Eric Dumazet   inet: constify ip...
2590
  static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr *addr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2591
  {
8e5e8f30d   Eldad Zack   net/ipv6/addrconf...
2592
  	struct inet6_ifaddr *ifp;
95c385b4d   Neil Horman   [IPV6] ADDRCONF: ...
2593
2594
2595
2596
  	u32 addr_flags = IFA_F_PERMANENT;
  
  #ifdef CONFIG_IPV6_OPTIMISTIC_DAD
  	if (idev->cnf.optimistic_dad &&
702beb87d   David Miller   ipv6: Fix warning...
2597
  	    !dev_net(idev->dev)->ipv6.devconf_all->forwarding)
95c385b4d   Neil Horman   [IPV6] ADDRCONF: ...
2598
2599
  		addr_flags |= IFA_F_OPTIMISTIC;
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2600

95c385b4d   Neil Horman   [IPV6] ADDRCONF: ...
2601

07edd741c   Hannes Frederic Sowa   ipv6: add link-lo...
2602
2603
  	ifp = ipv6_add_addr(idev, addr, NULL, 64, IFA_LINK, addr_flags,
  			    INFINITY_LIFE_TIME, INFINITY_LIFE_TIME);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2604
  	if (!IS_ERR(ifp)) {
46d480468   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
2605
  		addrconf_prefix_route(&ifp->addr, ifp->prefix_len, idev->dev, 0, 0);
cf22f9a2b   David S. Miller   ipv6: Remove unus...
2606
  		addrconf_dad_start(ifp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2607
2608
2609
2610
2611
2612
2613
  		in6_ifa_put(ifp);
  	}
  }
  
  static void addrconf_dev_config(struct net_device *dev)
  {
  	struct in6_addr addr;
8e5e8f30d   Eldad Zack   net/ipv6/addrconf...
2614
  	struct inet6_dev *idev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2615
2616
  
  	ASSERT_RTNL();
74235a25c   Herbert Xu   [IPV6] addrconf: ...
2617
2618
  	if ((dev->type != ARPHRD_ETHER) &&
  	    (dev->type != ARPHRD_FDDI) &&
74235a25c   Herbert Xu   [IPV6] addrconf: ...
2619
  	    (dev->type != ARPHRD_ARCNET) &&
06a4c1c55   alex.bluesman.smirnov@gmail.com   6lowpan: IPv6 lin...
2620
  	    (dev->type != ARPHRD_INFINIBAND) &&
cb6bf3550   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
2621
  	    (dev->type != ARPHRD_IEEE802154) &&
e837735ec   Nicolas Dichtel   ip6_tunnel: ensur...
2622
  	    (dev->type != ARPHRD_IEEE1394) &&
e74bccb8a   Jukka Rissanen   ipv6: Add checks ...
2623
2624
  	    (dev->type != ARPHRD_TUNNEL6) &&
  	    (dev->type != ARPHRD_6LOWPAN)) {
74235a25c   Herbert Xu   [IPV6] addrconf: ...
2625
2626
2627
  		/* Alas, we support only Ethernet autoconfiguration. */
  		return;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2628
  	idev = addrconf_add_dev(dev);
64e724f62   Brian Haley   ipv6: Don't add r...
2629
  	if (IS_ERR(idev))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2630
2631
2632
2633
2634
2635
2636
2637
  		return;
  
  	memset(&addr, 0, sizeof(struct in6_addr));
  	addr.s6_addr32[0] = htonl(0xFE800000);
  
  	if (ipv6_generate_eui64(addr.s6_addr + 8, dev) == 0)
  		addrconf_add_linklocal(idev, &addr);
  }
07a936260   Amerigo Wang   ipv6: use IS_ENAB...
2638
  #if IS_ENABLED(CONFIG_IPV6_SIT)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2639
2640
2641
2642
2643
  static void addrconf_sit_config(struct net_device *dev)
  {
  	struct inet6_dev *idev;
  
  	ASSERT_RTNL();
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
2644
2645
2646
  	/*
  	 * Configure the tunnel with one of our IPv4
  	 * addresses... we should configure all of
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2647
2648
  	 * our v4 addrs in the tunnel
  	 */
7eaa48a45   David S. Miller   Revert "ipv6: fix...
2649
  	if ((idev = ipv6_find_idev(dev)) == NULL) {
91df42bed   Joe Perches   net: ipv4 and ipv...
2650
2651
  		pr_debug("%s: add_dev failed
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2652
2653
  		return;
  	}
c7dc89c0a   Fred L. Templin   [IPV6]: Add RFC42...
2654
2655
2656
2657
  	if (dev->priv_flags & IFF_ISATAP) {
  		struct in6_addr addr;
  
  		ipv6_addr_set(&addr,  htonl(0xFE800000), 0, 0, 0);
c7dc89c0a   Fred L. Templin   [IPV6]: Add RFC42...
2658
2659
2660
2661
  		if (!ipv6_generate_eui64(addr.s6_addr + 8, dev))
  			addrconf_add_linklocal(idev, &addr);
  		return;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2662
  	sit_add_v4_addrs(idev);
62b54dd91   Nicolas Dichtel   ipv6: don't add l...
2663
  	if (dev->flags&IFF_POINTOPOINT)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2664
  		addrconf_add_mroute(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2665
  }
0be669bb3   Joerg Roedel   [IPV6]: Seperate ...
2666
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2667

07a936260   Amerigo Wang   ipv6: use IS_ENAB...
2668
  #if IS_ENABLED(CONFIG_NET_IPGRE)
aee80b54b   stephen hemminger   ipv6: generate li...
2669
2670
2671
2672
  static void addrconf_gre_config(struct net_device *dev)
  {
  	struct inet6_dev *idev;
  	struct in6_addr addr;
aee80b54b   stephen hemminger   ipv6: generate li...
2673
  	ASSERT_RTNL();
7eaa48a45   David S. Miller   Revert "ipv6: fix...
2674
  	if ((idev = ipv6_find_idev(dev)) == NULL) {
91df42bed   Joe Perches   net: ipv4 and ipv...
2675
2676
  		pr_debug("%s: add_dev failed
  ", __func__);
aee80b54b   stephen hemminger   ipv6: generate li...
2677
2678
2679
2680
  		return;
  	}
  
  	ipv6_addr_set(&addr,  htonl(0xFE800000), 0, 0, 0);
aee80b54b   stephen hemminger   ipv6: generate li...
2681
2682
  	if (!ipv6_generate_eui64(addr.s6_addr + 8, dev))
  		addrconf_add_linklocal(idev, &addr);
08b44656c   Nicolas Dichtel   gre: add link loc...
2683
2684
  	else
  		addrconf_prefix_route(&addr, 64, dev, 0, 0);
aee80b54b   stephen hemminger   ipv6: generate li...
2685
2686
  }
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2687
2688
2689
2690
  static inline int
  ipv6_inherit_linklocal(struct inet6_dev *idev, struct net_device *link_dev)
  {
  	struct in6_addr lladdr;
95c385b4d   Neil Horman   [IPV6] ADDRCONF: ...
2691
  	if (!ipv6_get_lladdr(link_dev, &lladdr, IFA_F_TENTATIVE)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2692
2693
2694
2695
2696
  		addrconf_add_linklocal(idev, &lladdr);
  		return 0;
  	}
  	return -1;
  }
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
2697
  static int addrconf_notify(struct notifier_block *this, unsigned long event,
351638e7d   Jiri Pirko   net: pass info st...
2698
  			   void *ptr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2699
  {
351638e7d   Jiri Pirko   net: pass info st...
2700
  	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
748e2d939   Eric Dumazet   net: reinstate rt...
2701
  	struct inet6_dev *idev = __in6_dev_get(dev);
c5e33bddd   YOSHIFUJI Hideaki   [IPV6]: Run DAD w...
2702
  	int run_pending = 0;
b217d616a   Herbert Xu   [IPV4/IPV6]: Fail...
2703
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2704

e21e8467d   Stephen Hemminger   addrconf: checkpa...
2705
  	switch (event) {
45ba9dd20   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
2706
  	case NETDEV_REGISTER:
74235a25c   Herbert Xu   [IPV6] addrconf: ...
2707
  		if (!idev && dev->mtu >= IPV6_MIN_MTU) {
45ba9dd20   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
2708
2709
  			idev = ipv6_add_dev(dev);
  			if (!idev)
b217d616a   Herbert Xu   [IPV4/IPV6]: Fail...
2710
  				return notifier_from_errno(-ENOMEM);
45ba9dd20   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
2711
2712
  		}
  		break;
bcdd553fd   Stephen Hemminger   IPv6: addrconf cl...
2713

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2714
  	case NETDEV_UP:
3c21edbd1   YOSHIFUJI Hideaki   [IPV6]: Defer IPv...
2715
  	case NETDEV_CHANGE:
c2edacf80   Jay Vosburgh   bonding / ipv6: n...
2716
2717
  		if (dev->flags & IFF_SLAVE)
  			break;
3c21edbd1   YOSHIFUJI Hideaki   [IPV6]: Defer IPv...
2718
  		if (event == NETDEV_UP) {
f24e3d658   Mitsuru Chinen   [IPV6]: Defer IPv...
2719
  			if (!addrconf_qdisc_ok(dev)) {
3c21edbd1   YOSHIFUJI Hideaki   [IPV6]: Defer IPv...
2720
  				/* device is not ready yet. */
f32138319   Joe Perches   net: ipv6: Standa...
2721
2722
  				pr_info("ADDRCONF(NETDEV_UP): %s: link is not ready
  ",
3c21edbd1   YOSHIFUJI Hideaki   [IPV6]: Defer IPv...
2723
2724
2725
  					dev->name);
  				break;
  			}
990810493   Kristian Slavov   [IPV6]: Address a...
2726

d31c7b8fa   Evgeniy Polyakov   [IPV6]: Restore I...
2727
2728
  			if (!idev && dev->mtu >= IPV6_MIN_MTU)
  				idev = ipv6_add_dev(dev);
e3ec6cfc2   Benjamin Thery   ipv6: fix run pen...
2729
  			if (idev) {
990810493   Kristian Slavov   [IPV6]: Address a...
2730
  				idev->if_flags |= IF_READY;
e3ec6cfc2   Benjamin Thery   ipv6: fix run pen...
2731
2732
  				run_pending = 1;
  			}
3c21edbd1   YOSHIFUJI Hideaki   [IPV6]: Defer IPv...
2733
  		} else {
f24e3d658   Mitsuru Chinen   [IPV6]: Defer IPv...
2734
  			if (!addrconf_qdisc_ok(dev)) {
3c21edbd1   YOSHIFUJI Hideaki   [IPV6]: Defer IPv...
2735
2736
2737
2738
2739
  				/* device is still not ready. */
  				break;
  			}
  
  			if (idev) {
bcdd553fd   Stephen Hemminger   IPv6: addrconf cl...
2740
  				if (idev->if_flags & IF_READY)
3c21edbd1   YOSHIFUJI Hideaki   [IPV6]: Defer IPv...
2741
2742
  					/* device is already configured. */
  					break;
3c21edbd1   YOSHIFUJI Hideaki   [IPV6]: Defer IPv...
2743
2744
  				idev->if_flags |= IF_READY;
  			}
f32138319   Joe Perches   net: ipv6: Standa...
2745
2746
2747
  			pr_info("ADDRCONF(NETDEV_CHANGE): %s: link becomes ready
  ",
  				dev->name);
3c21edbd1   YOSHIFUJI Hideaki   [IPV6]: Defer IPv...
2748

c5e33bddd   YOSHIFUJI Hideaki   [IPV6]: Run DAD w...
2749
  			run_pending = 1;
3c21edbd1   YOSHIFUJI Hideaki   [IPV6]: Defer IPv...
2750
  		}
e21e8467d   Stephen Hemminger   addrconf: checkpa...
2751
  		switch (dev->type) {
07a936260   Amerigo Wang   ipv6: use IS_ENAB...
2752
  #if IS_ENABLED(CONFIG_IPV6_SIT)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2753
2754
2755
  		case ARPHRD_SIT:
  			addrconf_sit_config(dev);
  			break;
0be669bb3   Joerg Roedel   [IPV6]: Seperate ...
2756
  #endif
07a936260   Amerigo Wang   ipv6: use IS_ENAB...
2757
  #if IS_ENABLED(CONFIG_NET_IPGRE)
aee80b54b   stephen hemminger   ipv6: generate li...
2758
2759
2760
2761
  		case ARPHRD_IPGRE:
  			addrconf_gre_config(dev);
  			break;
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2762
2763
2764
2765
2766
2767
2768
  		case ARPHRD_LOOPBACK:
  			init_loopback(dev);
  			break;
  
  		default:
  			addrconf_dev_config(dev);
  			break;
3ff50b799   Stephen Hemminger   [NET]: cleanup ex...
2769
  		}
bcdd553fd   Stephen Hemminger   IPv6: addrconf cl...
2770

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2771
  		if (idev) {
c5e33bddd   YOSHIFUJI Hideaki   [IPV6]: Run DAD w...
2772
2773
  			if (run_pending)
  				addrconf_dad_run(idev);
bcdd553fd   Stephen Hemminger   IPv6: addrconf cl...
2774
2775
2776
2777
  			/*
  			 * If the MTU changed during the interface down,
  			 * when the interface up, the changed MTU must be
  			 * reflected in the idev as well as routers.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2778
  			 */
bcdd553fd   Stephen Hemminger   IPv6: addrconf cl...
2779
2780
  			if (idev->cnf.mtu6 != dev->mtu &&
  			    dev->mtu >= IPV6_MIN_MTU) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2781
2782
2783
2784
2785
  				rt6_mtu_change(dev, dev->mtu);
  				idev->cnf.mtu6 = dev->mtu;
  			}
  			idev->tstamp = jiffies;
  			inet6_ifinfo_notify(RTM_NEWLINK, idev);
bcdd553fd   Stephen Hemminger   IPv6: addrconf cl...
2786
2787
2788
2789
  
  			/*
  			 * If the changed mtu during down is lower than
  			 * IPV6_MIN_MTU stop IPv6 on this interface.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2790
2791
  			 */
  			if (dev->mtu < IPV6_MIN_MTU)
bcdd553fd   Stephen Hemminger   IPv6: addrconf cl...
2792
  				addrconf_ifdown(dev, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2793
2794
2795
2796
  		}
  		break;
  
  	case NETDEV_CHANGEMTU:
d31c7b8fa   Evgeniy Polyakov   [IPV6]: Restore I...
2797
  		if (idev && dev->mtu >= IPV6_MIN_MTU) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2798
2799
2800
2801
  			rt6_mtu_change(dev, dev->mtu);
  			idev->cnf.mtu6 = dev->mtu;
  			break;
  		}
d31c7b8fa   Evgeniy Polyakov   [IPV6]: Restore I...
2802
2803
2804
2805
2806
  		if (!idev && dev->mtu >= IPV6_MIN_MTU) {
  			idev = ipv6_add_dev(dev);
  			if (idev)
  				break;
  		}
bcdd553fd   Stephen Hemminger   IPv6: addrconf cl...
2807
  		/*
db9c7c394   stephen hemminger   ipv6: addrconf sp...
2808
  		 * if MTU under IPV6_MIN_MTU.
bcdd553fd   Stephen Hemminger   IPv6: addrconf cl...
2809
2810
  		 * Stop IPv6 on this interface.
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2811
2812
2813
2814
2815
2816
2817
2818
  
  	case NETDEV_DOWN:
  	case NETDEV_UNREGISTER:
  		/*
  		 *	Remove all addresses from this interface.
  		 */
  		addrconf_ifdown(dev, event != NETDEV_DOWN);
  		break;
3c21edbd1   YOSHIFUJI Hideaki   [IPV6]: Defer IPv...
2819

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2820
  	case NETDEV_CHANGENAME:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2821
  		if (idev) {
5632c5152   Stephen Hemminger   [IPV6]: Track dev...
2822
  			snmp6_unregister_dev(idev);
408c4768c   Pavel Emelyanov   [NETNS]: Clean ou...
2823
  			addrconf_sysctl_unregister(idev);
f52295a9c   Pavel Emelyanov   [IPV6]: Unify and...
2824
  			addrconf_sysctl_register(idev);
b217d616a   Herbert Xu   [IPV4/IPV6]: Fail...
2825
2826
2827
  			err = snmp6_register_dev(idev);
  			if (err)
  				return notifier_from_errno(err);
5632c5152   Stephen Hemminger   [IPV6]: Track dev...
2828
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2829
  		break;
bcdd553fd   Stephen Hemminger   IPv6: addrconf cl...
2830

93d9b7d7a   Jiri Pirko   net: rename notif...
2831
2832
2833
  	case NETDEV_PRE_TYPE_CHANGE:
  	case NETDEV_POST_TYPE_CHANGE:
  		addrconf_type_change(dev, event);
75c78500d   Moni Shoua   bonding: remap mu...
2834
  		break;
3ff50b799   Stephen Hemminger   [NET]: cleanup ex...
2835
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2836
2837
2838
2839
2840
2841
2842
2843
2844
  
  	return NOTIFY_OK;
  }
  
  /*
   *	addrconf module should be notified of a device going up
   */
  static struct notifier_block ipv6_dev_notf = {
  	.notifier_call = addrconf_notify,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2845
  };
93d9b7d7a   Jiri Pirko   net: rename notif...
2846
  static void addrconf_type_change(struct net_device *dev, unsigned long event)
75c78500d   Moni Shoua   bonding: remap mu...
2847
2848
2849
2850
2851
  {
  	struct inet6_dev *idev;
  	ASSERT_RTNL();
  
  	idev = __in6_dev_get(dev);
93d9b7d7a   Jiri Pirko   net: rename notif...
2852
  	if (event == NETDEV_POST_TYPE_CHANGE)
75c78500d   Moni Shoua   bonding: remap mu...
2853
  		ipv6_mc_remap(idev);
93d9b7d7a   Jiri Pirko   net: rename notif...
2854
  	else if (event == NETDEV_PRE_TYPE_CHANGE)
75c78500d   Moni Shoua   bonding: remap mu...
2855
2856
  		ipv6_mc_unmap(idev);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2857
2858
  static int addrconf_ifdown(struct net_device *dev, int how)
  {
c346dca10   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
2859
  	struct net *net = dev_net(dev);
502a2ffd7   stephen hemminger   ipv6: convert ide...
2860
2861
  	struct inet6_dev *idev;
  	struct inet6_ifaddr *ifa;
73a8bd74e   David S. Miller   ipv6: Revert 'adm...
2862
  	int state, i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2863
2864
  
  	ASSERT_RTNL();
73a8bd74e   David S. Miller   ipv6: Revert 'adm...
2865
2866
  	rt6_ifdown(net, dev);
  	neigh_ifdown(&nd_tbl, dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2867
2868
2869
2870
  
  	idev = __in6_dev_get(dev);
  	if (idev == NULL)
  		return -ENODEV;
bcdd553fd   Stephen Hemminger   IPv6: addrconf cl...
2871
2872
2873
  	/*
  	 * Step 1: remove reference to ipv6 device from parent device.
  	 *	   Do not dev_put!
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2874
  	 */
439e23857   Denis V. Lunev   [IPV6]: Event typ...
2875
  	if (how) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2876
  		idev->dead = 1;
8814c4b53   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
2877
2878
  
  		/* protected by rtnl_lock */
a9b3cd7f3   Stephen Hemminger   rcu: convert uses...
2879
  		RCU_INIT_POINTER(dev->ip6_ptr, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2880
2881
2882
2883
2884
  
  		/* Step 1.5: remove snmp6 entry */
  		snmp6_unregister_dev(idev);
  
  	}
73a8bd74e   David S. Miller   ipv6: Revert 'adm...
2885
2886
2887
  	/* Step 2: clear hash table */
  	for (i = 0; i < IN6_ADDR_HSIZE; i++) {
  		struct hlist_head *h = &inet6_addr_lst[i];
73a8bd74e   David S. Miller   ipv6: Revert 'adm...
2888
2889
2890
  
  		spin_lock_bh(&addrconf_hash_lock);
  	restart:
b67bfe0d4   Sasha Levin   hlist: drop the n...
2891
  		hlist_for_each_entry_rcu(ifa, h, addr_lst) {
73a8bd74e   David S. Miller   ipv6: Revert 'adm...
2892
2893
  			if (ifa->idev == idev) {
  				hlist_del_init_rcu(&ifa->addr_lst);
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
2894
  				addrconf_del_dad_work(ifa);
73a8bd74e   David S. Miller   ipv6: Revert 'adm...
2895
2896
2897
2898
2899
  				goto restart;
  			}
  		}
  		spin_unlock_bh(&addrconf_hash_lock);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2900
  	write_lock_bh(&idev->lock);
b7b1bfce0   Hannes Frederic Sowa   ipv6: split dupli...
2901
  	addrconf_del_rs_timer(idev);
bcdd553fd   Stephen Hemminger   IPv6: addrconf cl...
2902
  	/* Step 2: clear flags for stateless addrconf */
439e23857   Denis V. Lunev   [IPV6]: Event typ...
2903
  	if (!how)
3c21edbd1   YOSHIFUJI Hideaki   [IPV6]: Defer IPv...
2904
  		idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2905

439e23857   Denis V. Lunev   [IPV6]: Event typ...
2906
  	if (how && del_timer(&idev->regen_timer))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2907
  		in6_dev_put(idev);
bcdd553fd   Stephen Hemminger   IPv6: addrconf cl...
2908
  	/* Step 3: clear tempaddr list */
372e6c8f1   stephen hemminger   ipv6: convert tem...
2909
2910
2911
2912
  	while (!list_empty(&idev->tempaddr_list)) {
  		ifa = list_first_entry(&idev->tempaddr_list,
  				       struct inet6_ifaddr, tmp_list);
  		list_del(&ifa->tmp_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
  		write_unlock_bh(&idev->lock);
  		spin_lock_bh(&ifa->lock);
  
  		if (ifa->ifpub) {
  			in6_ifa_put(ifa->ifpub);
  			ifa->ifpub = NULL;
  		}
  		spin_unlock_bh(&ifa->lock);
  		in6_ifa_put(ifa);
  		write_lock_bh(&idev->lock);
  	}
8f37ada5b   stephen hemminger   IPv6: fix race be...
2924

502a2ffd7   stephen hemminger   ipv6: convert ide...
2925
2926
2927
  	while (!list_empty(&idev->addr_list)) {
  		ifa = list_first_entry(&idev->addr_list,
  				       struct inet6_ifaddr, if_list);
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
2928
  		addrconf_del_dad_work(ifa);
84e8b803f   stephen hemminger   IPv6: addrconf no...
2929

73a8bd74e   David S. Miller   ipv6: Revert 'adm...
2930
  		list_del(&ifa->if_list);
84e8b803f   stephen hemminger   IPv6: addrconf no...
2931

73a8bd74e   David S. Miller   ipv6: Revert 'adm...
2932
  		write_unlock_bh(&idev->lock);
84e8b803f   stephen hemminger   IPv6: addrconf no...
2933

73a8bd74e   David S. Miller   ipv6: Revert 'adm...
2934
2935
2936
2937
  		spin_lock_bh(&ifa->state_lock);
  		state = ifa->state;
  		ifa->state = INET6_IFADDR_STATE_DEAD;
  		spin_unlock_bh(&ifa->state_lock);
9d82ca98f   John Fastabend   ipv6: fix missing...
2938

73a8bd74e   David S. Miller   ipv6: Revert 'adm...
2939
2940
  		if (state != INET6_IFADDR_STATE_DEAD) {
  			__ipv6_ifa_notify(RTM_DELADDR, ifa);
f88c91ddb   Cong Wang   ipv6: statically ...
2941
  			inet6addr_notifier_call_chain(NETDEV_DOWN, ifa);
27bdb2abc   stephen hemminger   IPv6: keep tentat...
2942
  		}
73a8bd74e   David S. Miller   ipv6: Revert 'adm...
2943
  		in6_ifa_put(ifa);
8f37ada5b   stephen hemminger   IPv6: fix race be...
2944

73a8bd74e   David S. Miller   ipv6: Revert 'adm...
2945
2946
  		write_lock_bh(&idev->lock);
  	}
8f37ada5b   stephen hemminger   IPv6: fix race be...
2947

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2948
2949
2950
  	write_unlock_bh(&idev->lock);
  
  	/* Step 5: Discard multicast list */
439e23857   Denis V. Lunev   [IPV6]: Event typ...
2951
  	if (how)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2952
2953
2954
  		ipv6_mc_destroy_dev(idev);
  	else
  		ipv6_mc_down(idev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2955
  	idev->tstamp = jiffies;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
2956

bcdd553fd   Stephen Hemminger   IPv6: addrconf cl...
2957
  	/* Last: Shot the device (if unregistered) */
439e23857   Denis V. Lunev   [IPV6]: Event typ...
2958
  	if (how) {
408c4768c   Pavel Emelyanov   [NETNS]: Clean ou...
2959
  		addrconf_sysctl_unregister(idev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2960
2961
2962
2963
2964
2965
2966
2967
2968
  		neigh_parms_release(&nd_tbl, idev->nd_parms);
  		neigh_ifdown(&nd_tbl, dev);
  		in6_dev_put(idev);
  	}
  	return 0;
  }
  
  static void addrconf_rs_timer(unsigned long data)
  {
b7b1bfce0   Hannes Frederic Sowa   ipv6: split dupli...
2969
  	struct inet6_dev *idev = (struct inet6_dev *)data;
caf92bc40   Cong Wang   ipv6: do not call...
2970
  	struct net_device *dev = idev->dev;
b7b1bfce0   Hannes Frederic Sowa   ipv6: split dupli...
2971
  	struct in6_addr lladdr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2972

b7b1bfce0   Hannes Frederic Sowa   ipv6: split dupli...
2973
  	write_lock(&idev->lock);
5b2a19539   stephen hemminger   IPv6: addrconf ti...
2974
  	if (idev->dead || !(idev->if_flags & IF_READY))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2975
  		goto out;
9ba2add3c   Shmulik Ladkani   ipv6: Make 'addrc...
2976
  	if (!ipv6_accept_ra(idev))
5b2a19539   stephen hemminger   IPv6: addrconf ti...
2977
2978
2979
2980
  		goto out;
  
  	/* Announcement received after solicitation was sent */
  	if (idev->if_flags & IF_RA_RCVD)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2981
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2982

b7b1bfce0   Hannes Frederic Sowa   ipv6: split dupli...
2983
  	if (idev->rs_probes++ < idev->cnf.rtr_solicits) {
caf92bc40   Cong Wang   ipv6: do not call...
2984
2985
2986
  		write_unlock(&idev->lock);
  		if (!ipv6_get_lladdr(dev, &lladdr, IFA_F_TENTATIVE))
  			ndisc_send_rs(dev, &lladdr,
b7b1bfce0   Hannes Frederic Sowa   ipv6: split dupli...
2987
2988
  				      &in6addr_linklocal_allrouters);
  		else
caf92bc40   Cong Wang   ipv6: do not call...
2989
  			goto put;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2990

caf92bc40   Cong Wang   ipv6: do not call...
2991
  		write_lock(&idev->lock);
b7b1bfce0   Hannes Frederic Sowa   ipv6: split dupli...
2992
2993
2994
2995
2996
  		/* The wait after the last probe can be shorter */
  		addrconf_mod_rs_timer(idev, (idev->rs_probes ==
  					     idev->cnf.rtr_solicits) ?
  				      idev->cnf.rtr_solicit_delay :
  				      idev->cnf.rtr_solicit_interval);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2997
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2998
2999
3000
3001
  		/*
  		 * Note: we do not support deprecated "all on-link"
  		 * assumption any longer.
  		 */
91df42bed   Joe Perches   net: ipv4 and ipv...
3002
3003
  		pr_debug("%s: no IPv6 routers present
  ", idev->dev->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3004
3005
3006
  	}
  
  out:
b7b1bfce0   Hannes Frederic Sowa   ipv6: split dupli...
3007
  	write_unlock(&idev->lock);
caf92bc40   Cong Wang   ipv6: do not call...
3008
  put:
b7b1bfce0   Hannes Frederic Sowa   ipv6: split dupli...
3009
  	in6_dev_put(idev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3010
3011
3012
3013
3014
  }
  
  /*
   *	Duplicate Address Detection
   */
3c21edbd1   YOSHIFUJI Hideaki   [IPV6]: Defer IPv...
3015
3016
3017
3018
  static void addrconf_dad_kick(struct inet6_ifaddr *ifp)
  {
  	unsigned long rand_num;
  	struct inet6_dev *idev = ifp->idev;
95c385b4d   Neil Horman   [IPV6] ADDRCONF: ...
3019
3020
3021
  	if (ifp->flags & IFA_F_OPTIMISTIC)
  		rand_num = 0;
  	else
63862b5be   Aruna-Hewapathirane   net: replace macr...
3022
  		rand_num = prandom_u32() % (idev->cnf.rtr_solicit_delay ? : 1);
95c385b4d   Neil Horman   [IPV6] ADDRCONF: ...
3023

b7b1bfce0   Hannes Frederic Sowa   ipv6: split dupli...
3024
  	ifp->dad_probes = idev->cnf.dad_transmits;
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
3025
  	addrconf_mod_dad_work(ifp, rand_num);
3c21edbd1   YOSHIFUJI Hideaki   [IPV6]: Defer IPv...
3026
  }
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
3027
  static void addrconf_dad_begin(struct inet6_ifaddr *ifp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3028
3029
3030
  {
  	struct inet6_dev *idev = ifp->idev;
  	struct net_device *dev = idev->dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3031
3032
  
  	addrconf_join_solict(dev, &ifp->addr);
63862b5be   Aruna-Hewapathirane   net: replace macr...
3033
  	prandom_seed((__force u32) ifp->addr.s6_addr32[3]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3034
3035
  
  	read_lock_bh(&idev->lock);
622ccdf10   Herbert Xu   ipv6: Never sched...
3036
  	spin_lock(&ifp->lock);
e9d3e0849   Herbert Xu   ipv6: Replace ine...
3037
  	if (ifp->state == INET6_IFADDR_STATE_DEAD)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3038
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3039
3040
  
  	if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) ||
1b34be74c   YOSHIFUJI Hideaki   ipv6 addrconf: ad...
3041
  	    idev->cnf.accept_dad < 1 ||
55ebaef1d   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
3042
3043
  	    !(ifp->flags&IFA_F_TENTATIVE) ||
  	    ifp->flags & IFA_F_NODAD) {
cc411d0ba   Brian Haley   ipv6: Add IFA_F_D...
3044
  		ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED);
21809fafa   stephen hemminger   IPv6: remove triv...
3045
  		spin_unlock(&ifp->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3046
3047
3048
3049
3050
  		read_unlock_bh(&idev->lock);
  
  		addrconf_dad_completed(ifp);
  		return;
  	}
6732badee   YOSHIFUJI Hideaki   [IPV6]: Fix addrc...
3051
  	if (!(idev->if_flags & IF_READY)) {
21809fafa   stephen hemminger   IPv6: remove triv...
3052
  		spin_unlock(&ifp->lock);
6732badee   YOSHIFUJI Hideaki   [IPV6]: Fix addrc...
3053
  		read_unlock_bh(&idev->lock);
3c21edbd1   YOSHIFUJI Hideaki   [IPV6]: Defer IPv...
3054
  		/*
590a9887a   Masatake YAMATO   trivial: Fix a ty...
3055
  		 * If the device is not ready:
3c21edbd1   YOSHIFUJI Hideaki   [IPV6]: Defer IPv...
3056
3057
3058
3059
  		 * - keep it tentative if it is a permanent address.
  		 * - otherwise, kill it.
  		 */
  		in6_ifa_hold(ifp);
cc411d0ba   Brian Haley   ipv6: Add IFA_F_D...
3060
  		addrconf_dad_stop(ifp, 0);
6732badee   YOSHIFUJI Hideaki   [IPV6]: Fix addrc...
3061
  		return;
3c21edbd1   YOSHIFUJI Hideaki   [IPV6]: Defer IPv...
3062
  	}
95c385b4d   Neil Horman   [IPV6] ADDRCONF: ...
3063
3064
3065
3066
3067
  
  	/*
  	 * Optimistic nodes can start receiving
  	 * Frames right away
  	 */
e21e8467d   Stephen Hemminger   addrconf: checkpa...
3068
  	if (ifp->flags & IFA_F_OPTIMISTIC)
95c385b4d   Neil Horman   [IPV6] ADDRCONF: ...
3069
  		ip6_ins_rt(ifp->rt);
6732badee   YOSHIFUJI Hideaki   [IPV6]: Fix addrc...
3070
  	addrconf_dad_kick(ifp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3071
  out:
622ccdf10   Herbert Xu   ipv6: Never sched...
3072
  	spin_unlock(&ifp->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3073
3074
  	read_unlock_bh(&idev->lock);
  }
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
3075
  static void addrconf_dad_start(struct inet6_ifaddr *ifp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3076
  {
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
  	bool begin_dad = false;
  
  	spin_lock_bh(&ifp->state_lock);
  	if (ifp->state != INET6_IFADDR_STATE_DEAD) {
  		ifp->state = INET6_IFADDR_STATE_PREDAD;
  		begin_dad = true;
  	}
  	spin_unlock_bh(&ifp->state_lock);
  
  	if (begin_dad)
  		addrconf_mod_dad_work(ifp, 0);
  }
  
  static void addrconf_dad_work(struct work_struct *w)
  {
  	struct inet6_ifaddr *ifp = container_of(to_delayed_work(w),
  						struct inet6_ifaddr,
  						dad_work);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3095
  	struct inet6_dev *idev = ifp->idev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3096
  	struct in6_addr mcaddr;
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
  	enum {
  		DAD_PROCESS,
  		DAD_BEGIN,
  		DAD_ABORT,
  	} action = DAD_PROCESS;
  
  	rtnl_lock();
  
  	spin_lock_bh(&ifp->state_lock);
  	if (ifp->state == INET6_IFADDR_STATE_PREDAD) {
  		action = DAD_BEGIN;
  		ifp->state = INET6_IFADDR_STATE_DAD;
  	} else if (ifp->state == INET6_IFADDR_STATE_ERRDAD) {
  		action = DAD_ABORT;
  		ifp->state = INET6_IFADDR_STATE_POSTDAD;
  	}
  	spin_unlock_bh(&ifp->state_lock);
  
  	if (action == DAD_BEGIN) {
  		addrconf_dad_begin(ifp);
  		goto out;
  	} else if (action == DAD_ABORT) {
  		addrconf_dad_stop(ifp, 1);
  		goto out;
  	}
b7b1bfce0   Hannes Frederic Sowa   ipv6: split dupli...
3122
  	if (!ifp->dad_probes && addrconf_dad_end(ifp))
f2344a131   Herbert Xu   ipv6: Use POSTDAD...
3123
  		goto out;
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
3124
  	write_lock_bh(&idev->lock);
122e4519c   stephen hemminger   IPv6: addrconf da...
3125
  	if (idev->dead || !(idev->if_flags & IF_READY)) {
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
3126
  		write_unlock_bh(&idev->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3127
3128
  		goto out;
  	}
21809fafa   stephen hemminger   IPv6: remove triv...
3129
3130
  
  	spin_lock(&ifp->lock);
622ccdf10   Herbert Xu   ipv6: Never sched...
3131
3132
  	if (ifp->state == INET6_IFADDR_STATE_DEAD) {
  		spin_unlock(&ifp->lock);
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
3133
  		write_unlock_bh(&idev->lock);
622ccdf10   Herbert Xu   ipv6: Never sched...
3134
3135
  		goto out;
  	}
b7b1bfce0   Hannes Frederic Sowa   ipv6: split dupli...
3136
  	if (ifp->dad_probes == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3137
3138
3139
  		/*
  		 * DAD was successful
  		 */
cc411d0ba   Brian Haley   ipv6: Add IFA_F_D...
3140
  		ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED);
21809fafa   stephen hemminger   IPv6: remove triv...
3141
  		spin_unlock(&ifp->lock);
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
3142
  		write_unlock_bh(&idev->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3143
3144
3145
3146
3147
  
  		addrconf_dad_completed(ifp);
  
  		goto out;
  	}
b7b1bfce0   Hannes Frederic Sowa   ipv6: split dupli...
3148
  	ifp->dad_probes--;
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
3149
3150
  	addrconf_mod_dad_work(ifp,
  			      NEIGH_VAR(ifp->idev->nd_parms, RETRANS_TIME));
21809fafa   stephen hemminger   IPv6: remove triv...
3151
  	spin_unlock(&ifp->lock);
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
3152
  	write_unlock_bh(&idev->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3153
3154
  
  	/* send a neighbour solicitation for our addr */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3155
  	addrconf_addr_solict_mult(&ifp->addr, &mcaddr);
d7aabf22e   YOSHIFUJI Hideaki   [IPV6]: Use in6ad...
3156
  	ndisc_send_ns(ifp->idev->dev, NULL, &ifp->addr, &mcaddr, &in6addr_any);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3157
3158
  out:
  	in6_ifa_put(ifp);
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
3159
  	rtnl_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3160
  }
11ffff752   Hannes Frederic Sowa   ipv6: simplify de...
3161
3162
3163
3164
3165
  /* ifp->idev must be at least read locked */
  static bool ipv6_lonely_lladdr(struct inet6_ifaddr *ifp)
  {
  	struct inet6_ifaddr *ifpiter;
  	struct inet6_dev *idev = ifp->idev;
602582ca7   Hannes Frederic Sowa   ipv6: optimize li...
3166
3167
3168
  	list_for_each_entry_reverse(ifpiter, &idev->addr_list, if_list) {
  		if (ifpiter->scope > IFA_LINK)
  			break;
11ffff752   Hannes Frederic Sowa   ipv6: simplify de...
3169
3170
3171
3172
3173
3174
3175
3176
  		if (ifp != ifpiter && ifpiter->scope == IFA_LINK &&
  		    (ifpiter->flags & (IFA_F_PERMANENT|IFA_F_TENTATIVE|
  				       IFA_F_OPTIMISTIC|IFA_F_DADFAILED)) ==
  		    IFA_F_PERMANENT)
  			return false;
  	}
  	return true;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3177
3178
  static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
  {
e21e8467d   Stephen Hemminger   addrconf: checkpa...
3179
  	struct net_device *dev = ifp->idev->dev;
b7b1bfce0   Hannes Frederic Sowa   ipv6: split dupli...
3180
  	struct in6_addr lladdr;
b173ee488   Hannes Frederic Sowa   ipv6: resend MLD ...
3181
  	bool send_rs, send_mld;
b7b1bfce0   Hannes Frederic Sowa   ipv6: split dupli...
3182

c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
3183
  	addrconf_del_dad_work(ifp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3184
3185
3186
3187
3188
3189
  
  	/*
  	 *	Configure the address for reception. Now it is valid.
  	 */
  
  	ipv6_ifa_notify(RTM_NEWADDR, ifp);
026359bc6   Tore Anderson   ipv6: Send ICMPv6...
3190
3191
  	/* If added prefix is link local and we are prepared to process
  	   router advertisements, start sending router solicitations.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3192
  	 */
1ec047eb4   Hannes Frederic Sowa   ipv6: introduce p...
3193
  	read_lock_bh(&ifp->idev->lock);
11ffff752   Hannes Frederic Sowa   ipv6: simplify de...
3194
  	send_mld = ifp->scope == IFA_LINK && ipv6_lonely_lladdr(ifp);
b173ee488   Hannes Frederic Sowa   ipv6: resend MLD ...
3195
3196
  	send_rs = send_mld &&
  		  ipv6_accept_ra(ifp->idev) &&
1ec047eb4   Hannes Frederic Sowa   ipv6: introduce p...
3197
  		  ifp->idev->cnf.rtr_solicits > 0 &&
b173ee488   Hannes Frederic Sowa   ipv6: resend MLD ...
3198
  		  (dev->flags&IFF_LOOPBACK) == 0;
1ec047eb4   Hannes Frederic Sowa   ipv6: introduce p...
3199
  	read_unlock_bh(&ifp->idev->lock);
b173ee488   Hannes Frederic Sowa   ipv6: resend MLD ...
3200
3201
3202
3203
3204
  	/* While dad is in progress mld report's source address is in6_addrany.
  	 * Resend with proper ll now.
  	 */
  	if (send_mld)
  		ipv6_mc_dad_complete(ifp->idev);
1ec047eb4   Hannes Frederic Sowa   ipv6: introduce p...
3205
  	if (send_rs) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3206
3207
3208
3209
3210
  		/*
  		 *	If a host as already performed a random delay
  		 *	[...] as part of DAD [...] there is no need
  		 *	to delay again before sending the first RS
  		 */
1ec047eb4   Hannes Frederic Sowa   ipv6: introduce p...
3211
  		if (ipv6_get_lladdr(dev, &lladdr, IFA_F_TENTATIVE))
b7b1bfce0   Hannes Frederic Sowa   ipv6: split dupli...
3212
  			return;
1ec047eb4   Hannes Frederic Sowa   ipv6: introduce p...
3213
  		ndisc_send_rs(dev, &lladdr, &in6addr_linklocal_allrouters);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3214

b7b1bfce0   Hannes Frederic Sowa   ipv6: split dupli...
3215
3216
3217
  		write_lock_bh(&ifp->idev->lock);
  		spin_lock(&ifp->lock);
  		ifp->idev->rs_probes = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3218
  		ifp->idev->if_flags |= IF_RS_SENT;
b7b1bfce0   Hannes Frederic Sowa   ipv6: split dupli...
3219
3220
3221
3222
  		addrconf_mod_rs_timer(ifp->idev,
  				      ifp->idev->cnf.rtr_solicit_interval);
  		spin_unlock(&ifp->lock);
  		write_unlock_bh(&ifp->idev->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3223
3224
  	}
  }
e21e8467d   Stephen Hemminger   addrconf: checkpa...
3225
3226
  static void addrconf_dad_run(struct inet6_dev *idev)
  {
c5e33bddd   YOSHIFUJI Hideaki   [IPV6]: Run DAD w...
3227
3228
3229
  	struct inet6_ifaddr *ifp;
  
  	read_lock_bh(&idev->lock);
502a2ffd7   stephen hemminger   ipv6: convert ide...
3230
  	list_for_each_entry(ifp, &idev->addr_list, if_list) {
21809fafa   stephen hemminger   IPv6: remove triv...
3231
  		spin_lock(&ifp->lock);
f2344a131   Herbert Xu   ipv6: Use POSTDAD...
3232
3233
3234
  		if (ifp->flags & IFA_F_TENTATIVE &&
  		    ifp->state == INET6_IFADDR_STATE_DAD)
  			addrconf_dad_kick(ifp);
21809fafa   stephen hemminger   IPv6: remove triv...
3235
  		spin_unlock(&ifp->lock);
c5e33bddd   YOSHIFUJI Hideaki   [IPV6]: Run DAD w...
3236
3237
3238
  	}
  	read_unlock_bh(&idev->lock);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3239
3240
  #ifdef CONFIG_PROC_FS
  struct if6_iter_state {
3c40090a0   Daniel Lezcano   [NETNS][IPV6]: in...
3241
  	struct seq_net_private p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3242
  	int bucket;
1d5783030   Mihai Maruseac   ipv6/addrconf: sp...
3243
  	int offset;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3244
  };
1d5783030   Mihai Maruseac   ipv6/addrconf: sp...
3245
  static struct inet6_ifaddr *if6_get_first(struct seq_file *seq, loff_t pos)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3246
3247
3248
  {
  	struct inet6_ifaddr *ifa = NULL;
  	struct if6_iter_state *state = seq->private;
1218854af   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
3249
  	struct net *net = seq_file_net(seq);
1d5783030   Mihai Maruseac   ipv6/addrconf: sp...
3250
  	int p = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3251

1d5783030   Mihai Maruseac   ipv6/addrconf: sp...
3252
3253
3254
3255
3256
3257
3258
  	/* initial bucket if pos is 0 */
  	if (pos == 0) {
  		state->bucket = 0;
  		state->offset = 0;
  	}
  
  	for (; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) {
b67bfe0d4   Sasha Levin   hlist: drop the n...
3259
  		hlist_for_each_entry_rcu_bh(ifa, &inet6_addr_lst[state->bucket],
1d5783030   Mihai Maruseac   ipv6/addrconf: sp...
3260
  					 addr_lst) {
9f0d3c278   Eric Dumazet   ipv6: addrconf: f...
3261
3262
  			if (!net_eq(dev_net(ifa->idev->dev), net))
  				continue;
1d5783030   Mihai Maruseac   ipv6/addrconf: sp...
3263
3264
3265
3266
3267
3268
  			/* sync with offset */
  			if (p < state->offset) {
  				p++;
  				continue;
  			}
  			state->offset++;
9f0d3c278   Eric Dumazet   ipv6: addrconf: f...
3269
  			return ifa;
1d5783030   Mihai Maruseac   ipv6/addrconf: sp...
3270
3271
3272
3273
3274
  		}
  
  		/* prepare for next bucket */
  		state->offset = 0;
  		p = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3275
  	}
c2e21293c   stephen hemminger   ipv6: convert add...
3276
  	return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3277
  }
c2e21293c   stephen hemminger   ipv6: convert add...
3278
3279
  static struct inet6_ifaddr *if6_get_next(struct seq_file *seq,
  					 struct inet6_ifaddr *ifa)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3280
3281
  {
  	struct if6_iter_state *state = seq->private;
1218854af   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
3282
  	struct net *net = seq_file_net(seq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3283

b67bfe0d4   Sasha Levin   hlist: drop the n...
3284
  	hlist_for_each_entry_continue_rcu_bh(ifa, addr_lst) {
9f0d3c278   Eric Dumazet   ipv6: addrconf: f...
3285
3286
  		if (!net_eq(dev_net(ifa->idev->dev), net))
  			continue;
1d5783030   Mihai Maruseac   ipv6/addrconf: sp...
3287
  		state->offset++;
9f0d3c278   Eric Dumazet   ipv6: addrconf: f...
3288
  		return ifa;
1d5783030   Mihai Maruseac   ipv6/addrconf: sp...
3289
  	}
3c40090a0   Daniel Lezcano   [NETNS][IPV6]: in...
3290

c2e21293c   stephen hemminger   ipv6: convert add...
3291
  	while (++state->bucket < IN6_ADDR_HSIZE) {
1d5783030   Mihai Maruseac   ipv6/addrconf: sp...
3292
  		state->offset = 0;
b67bfe0d4   Sasha Levin   hlist: drop the n...
3293
  		hlist_for_each_entry_rcu_bh(ifa,
c2e21293c   stephen hemminger   ipv6: convert add...
3294
  				     &inet6_addr_lst[state->bucket], addr_lst) {
9f0d3c278   Eric Dumazet   ipv6: addrconf: f...
3295
3296
  			if (!net_eq(dev_net(ifa->idev->dev), net))
  				continue;
1d5783030   Mihai Maruseac   ipv6/addrconf: sp...
3297
  			state->offset++;
9f0d3c278   Eric Dumazet   ipv6: addrconf: f...
3298
  			return ifa;
c2e21293c   stephen hemminger   ipv6: convert add...
3299
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3300
  	}
3c40090a0   Daniel Lezcano   [NETNS][IPV6]: in...
3301

c2e21293c   stephen hemminger   ipv6: convert add...
3302
  	return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3303
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3304
  static void *if6_seq_start(struct seq_file *seq, loff_t *pos)
4f70ecca9   Eric Dumazet   net: rcu fixes
3305
  	__acquires(rcu_bh)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3306
  {
5c578aedc   stephen hemminger   IPv6: convert add...
3307
  	rcu_read_lock_bh();
1d5783030   Mihai Maruseac   ipv6/addrconf: sp...
3308
  	return if6_get_first(seq, *pos);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
  }
  
  static void *if6_seq_next(struct seq_file *seq, void *v, loff_t *pos)
  {
  	struct inet6_ifaddr *ifa;
  
  	ifa = if6_get_next(seq, v);
  	++*pos;
  	return ifa;
  }
  
  static void if6_seq_stop(struct seq_file *seq, void *v)
4f70ecca9   Eric Dumazet   net: rcu fixes
3321
  	__releases(rcu_bh)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3322
  {
5c578aedc   stephen hemminger   IPv6: convert add...
3323
  	rcu_read_unlock_bh();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3324
3325
3326
3327
3328
  }
  
  static int if6_seq_show(struct seq_file *seq, void *v)
  {
  	struct inet6_ifaddr *ifp = (struct inet6_ifaddr *)v;
971a351cc   Jiri Pirko   ipv6 addrconf: re...
3329
3330
  	seq_printf(seq, "%pi6 %02x %02x %02x %02x %8s
  ",
b071195de   Harvey Harrison   net: replace all ...
3331
  		   &ifp->addr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3332
3333
3334
  		   ifp->idev->dev->ifindex,
  		   ifp->prefix_len,
  		   ifp->scope,
971a351cc   Jiri Pirko   ipv6 addrconf: re...
3335
  		   (u8) ifp->flags,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3336
3337
3338
  		   ifp->idev->dev->name);
  	return 0;
  }
56b3d975b   Philippe De Muyter   [NET]: Make all i...
3339
  static const struct seq_operations if6_seq_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3340
3341
3342
3343
3344
3345
3346
3347
  	.start	= if6_seq_start,
  	.next	= if6_seq_next,
  	.show	= if6_seq_show,
  	.stop	= if6_seq_stop,
  };
  
  static int if6_seq_open(struct inode *inode, struct file *file)
  {
3c40090a0   Daniel Lezcano   [NETNS][IPV6]: in...
3348
3349
  	return seq_open_net(inode, file, &if6_seq_ops,
  			    sizeof(struct if6_iter_state));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3350
  }
9a32144e9   Arjan van de Ven   [PATCH] mark stru...
3351
  static const struct file_operations if6_fops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3352
3353
3354
3355
  	.owner		= THIS_MODULE,
  	.open		= if6_seq_open,
  	.read		= seq_read,
  	.llseek		= seq_lseek,
3c40090a0   Daniel Lezcano   [NETNS][IPV6]: in...
3356
  	.release	= seq_release_net,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3357
  };
2c8c1e729   Alexey Dobriyan   net: spread __net...
3358
  static int __net_init if6_proc_net_init(struct net *net)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3359
  {
d4beaa66a   Gao feng   net: proc: change...
3360
  	if (!proc_create("if_inet6", S_IRUGO, net->proc_net, &if6_fops))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3361
3362
3363
  		return -ENOMEM;
  	return 0;
  }
2c8c1e729   Alexey Dobriyan   net: spread __net...
3364
  static void __net_exit if6_proc_net_exit(struct net *net)
3c40090a0   Daniel Lezcano   [NETNS][IPV6]: in...
3365
  {
ece31ffd5   Gao feng   net: proc: change...
3366
  	remove_proc_entry("if_inet6", net->proc_net);
3c40090a0   Daniel Lezcano   [NETNS][IPV6]: in...
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
  }
  
  static struct pernet_operations if6_proc_net_ops = {
         .init = if6_proc_net_init,
         .exit = if6_proc_net_exit,
  };
  
  int __init if6_proc_init(void)
  {
  	return register_pernet_subsys(&if6_proc_net_ops);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3378
3379
  void if6_proc_exit(void)
  {
3c40090a0   Daniel Lezcano   [NETNS][IPV6]: in...
3380
  	unregister_pernet_subsys(&if6_proc_net_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3381
3382
  }
  #endif	/* CONFIG_PROC_FS */
07a936260   Amerigo Wang   ipv6: use IS_ENAB...
3383
  #if IS_ENABLED(CONFIG_IPV6_MIP6)
3b9f9a1c3   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
3384
  /* Check if address is a home address configured on any interface. */
b71d1d426   Eric Dumazet   inet: constify ip...
3385
  int ipv6_chk_home_addr(struct net *net, const struct in6_addr *addr)
3b9f9a1c3   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
3386
3387
  {
  	int ret = 0;
c2e21293c   stephen hemminger   ipv6: convert add...
3388
  	struct inet6_ifaddr *ifp = NULL;
ddbe50320   Eric Dumazet   ipv6: add ipv6_ad...
3389
  	unsigned int hash = inet6_addr_hash(addr);
c2e21293c   stephen hemminger   ipv6: convert add...
3390

5c578aedc   stephen hemminger   IPv6: convert add...
3391
  	rcu_read_lock_bh();
b67bfe0d4   Sasha Levin   hlist: drop the n...
3392
  	hlist_for_each_entry_rcu_bh(ifp, &inet6_addr_lst[hash], addr_lst) {
878628fbf   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
3393
  		if (!net_eq(dev_net(ifp->idev->dev), net))
389f66122   Daniel Lezcano   [NETNS][IPV6]: in...
3394
  			continue;
caad295fe   YOSHIFUJI Hideaki   [IPV6]: Use ipv6_...
3395
  		if (ipv6_addr_equal(&ifp->addr, addr) &&
3b9f9a1c3   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
3396
3397
3398
3399
3400
  		    (ifp->flags & IFA_F_HOMEADDRESS)) {
  			ret = 1;
  			break;
  		}
  	}
5c578aedc   stephen hemminger   IPv6: convert add...
3401
  	rcu_read_unlock_bh();
3b9f9a1c3   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
3402
3403
3404
  	return ret;
  }
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3405
3406
3407
  /*
   *	Periodic address status verification
   */
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
3408
  static void addrconf_verify_rtnl(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3409
  {
b2db75644   YOSHIFUJI Hideaki   ipv6: Reduce time...
3410
  	unsigned long now, next, next_sec, next_sched;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3411
  	struct inet6_ifaddr *ifp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3412
  	int i;
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
3413
  	ASSERT_RTNL();
5c578aedc   stephen hemminger   IPv6: convert add...
3414
  	rcu_read_lock_bh();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3415
  	now = jiffies;
b2db75644   YOSHIFUJI Hideaki   ipv6: Reduce time...
3416
  	next = round_jiffies_up(now + ADDR_CHECK_FREQUENCY);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3417

c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
3418
  	cancel_delayed_work(&addr_chk_work);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3419

bcdd553fd   Stephen Hemminger   IPv6: addrconf cl...
3420
  	for (i = 0; i < IN6_ADDR_HSIZE; i++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3421
  restart:
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
3422
  		hlist_for_each_entry_rcu_bh(ifp, &inet6_addr_lst[i], addr_lst) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3423
  			unsigned long age;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3424

fad8da3e0   Yasushi Asano   ipv6 addrconf: fi...
3425
3426
3427
3428
3429
3430
  			/* When setting preferred_lft to a value not zero or
  			 * infinity, while valid_lft is infinity
  			 * IFA_F_PERMANENT has a non-infinity life time.
  			 */
  			if ((ifp->flags & IFA_F_PERMANENT) &&
  			    (ifp->prefered_lft == INFINITY_LIFE_TIME))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3431
3432
3433
  				continue;
  
  			spin_lock(&ifp->lock);
b2db75644   YOSHIFUJI Hideaki   ipv6: Reduce time...
3434
3435
  			/* We try to batch several events at once. */
  			age = (now - ifp->tstamp + ADDRCONF_TIMER_FUZZ_MINUS) / HZ;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3436

8f27ebb98   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
3437
3438
  			if (ifp->valid_lft != INFINITY_LIFE_TIME &&
  			    age >= ifp->valid_lft) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3439
3440
  				spin_unlock(&ifp->lock);
  				in6_ifa_hold(ifp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3441
3442
  				ipv6_del_addr(ifp);
  				goto restart;
8f27ebb98   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
3443
3444
3445
  			} else if (ifp->prefered_lft == INFINITY_LIFE_TIME) {
  				spin_unlock(&ifp->lock);
  				continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3446
  			} else if (age >= ifp->prefered_lft) {
a1ed05263   Brian Haley   IPv6: preferred l...
3447
  				/* jiffies - ifp->tstamp > age >= ifp->prefered_lft */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3448
3449
3450
3451
3452
3453
  				int deprecate = 0;
  
  				if (!(ifp->flags&IFA_F_DEPRECATED)) {
  					deprecate = 1;
  					ifp->flags |= IFA_F_DEPRECATED;
  				}
fad8da3e0   Yasushi Asano   ipv6 addrconf: fi...
3454
3455
  				if ((ifp->valid_lft != INFINITY_LIFE_TIME) &&
  				    (time_before(ifp->tstamp + ifp->valid_lft * HZ, next)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3456
3457
3458
3459
3460
3461
  					next = ifp->tstamp + ifp->valid_lft * HZ;
  
  				spin_unlock(&ifp->lock);
  
  				if (deprecate) {
  					in6_ifa_hold(ifp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3462
3463
3464
3465
3466
  
  					ipv6_ifa_notify(0, ifp);
  					in6_ifa_put(ifp);
  					goto restart;
  				}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3467
3468
  			} else if ((ifp->flags&IFA_F_TEMPORARY) &&
  				   !(ifp->flags&IFA_F_TENTATIVE)) {
88949cf48   stephen hemminger   IPv6: addrconf cl...
3469
3470
  				unsigned long regen_advance = ifp->idev->cnf.regen_max_retry *
  					ifp->idev->cnf.dad_transmits *
1f9248e56   Jiri Pirko   neigh: convert pa...
3471
  					NEIGH_VAR(ifp->idev->nd_parms, RETRANS_TIME) / HZ;
88949cf48   stephen hemminger   IPv6: addrconf cl...
3472

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3473
3474
3475
3476
3477
3478
3479
3480
3481
  				if (age >= ifp->prefered_lft - regen_advance) {
  					struct inet6_ifaddr *ifpub = ifp->ifpub;
  					if (time_before(ifp->tstamp + ifp->prefered_lft * HZ, next))
  						next = ifp->tstamp + ifp->prefered_lft * HZ;
  					if (!ifp->regen_count && ifpub) {
  						ifp->regen_count++;
  						in6_ifa_hold(ifp);
  						in6_ifa_hold(ifpub);
  						spin_unlock(&ifp->lock);
5c578aedc   stephen hemminger   IPv6: convert add...
3482

291d809ba   Hiroyuki YAMAMORI   [IPV6]: Fix Tempo...
3483
3484
3485
  						spin_lock(&ifpub->lock);
  						ifpub->regen_count = 0;
  						spin_unlock(&ifpub->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3486
3487
3488
3489
3490
3491
3492
3493
  						ipv6_create_tempaddr(ifpub, ifp);
  						in6_ifa_put(ifpub);
  						in6_ifa_put(ifp);
  						goto restart;
  					}
  				} else if (time_before(ifp->tstamp + ifp->prefered_lft * HZ - regen_advance * HZ, next))
  					next = ifp->tstamp + ifp->prefered_lft * HZ - regen_advance * HZ;
  				spin_unlock(&ifp->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3494
3495
3496
3497
3498
3499
3500
  			} else {
  				/* ifp->prefered_lft <= ifp->valid_lft */
  				if (time_before(ifp->tstamp + ifp->prefered_lft * HZ, next))
  					next = ifp->tstamp + ifp->prefered_lft * HZ;
  				spin_unlock(&ifp->lock);
  			}
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3501
  	}
b2db75644   YOSHIFUJI Hideaki   ipv6: Reduce time...
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
  	next_sec = round_jiffies_up(next);
  	next_sched = next;
  
  	/* If rounded timeout is accurate enough, accept it. */
  	if (time_before(next_sec, next + ADDRCONF_TIMER_FUZZ))
  		next_sched = next_sec;
  
  	/* And minimum interval is ADDRCONF_TIMER_FUZZ_MAX. */
  	if (time_before(next_sched, jiffies + ADDRCONF_TIMER_FUZZ_MAX))
  		next_sched = jiffies + ADDRCONF_TIMER_FUZZ_MAX;
ba3542e15   dingtianhong   ipv6: convert the...
3512
3513
3514
  	ADBG(KERN_DEBUG "now = %lu, schedule = %lu, rounded schedule = %lu => %lu
  ",
  	      now, next, next_sec, next_sched);
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
3515
  	mod_delayed_work(addrconf_wq, &addr_chk_work, next_sched - now);
5c578aedc   stephen hemminger   IPv6: convert add...
3516
  	rcu_read_unlock_bh();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3517
  }
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
  static void addrconf_verify_work(struct work_struct *w)
  {
  	rtnl_lock();
  	addrconf_verify_rtnl();
  	rtnl_unlock();
  }
  
  static void addrconf_verify(void)
  {
  	mod_delayed_work(addrconf_wq, &addr_chk_work, 0);
  }
caeaba790   Nicolas Dichtel   ipv6: add support...
3529
3530
  static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local,
  				     struct in6_addr **peer_pfx)
461d8837f   Thomas Graf   [IPV6] address: C...
3531
3532
  {
  	struct in6_addr *pfx = NULL;
caeaba790   Nicolas Dichtel   ipv6: add support...
3533
  	*peer_pfx = NULL;
461d8837f   Thomas Graf   [IPV6] address: C...
3534
3535
3536
3537
3538
  	if (addr)
  		pfx = nla_data(addr);
  
  	if (local) {
  		if (pfx && nla_memcmp(local, pfx, sizeof(*pfx)))
caeaba790   Nicolas Dichtel   ipv6: add support...
3539
3540
  			*peer_pfx = pfx;
  		pfx = nla_data(local);
461d8837f   Thomas Graf   [IPV6] address: C...
3541
3542
3543
3544
  	}
  
  	return pfx;
  }
ef7c79ed6   Patrick McHardy   [NETLINK]: Mark n...
3545
  static const struct nla_policy ifa_ipv6_policy[IFA_MAX+1] = {
461d8837f   Thomas Graf   [IPV6] address: C...
3546
3547
3548
  	[IFA_ADDRESS]		= { .len = sizeof(struct in6_addr) },
  	[IFA_LOCAL]		= { .len = sizeof(struct in6_addr) },
  	[IFA_CACHEINFO]		= { .len = sizeof(struct ifa_cacheinfo) },
479840ffd   Jiri Pirko   ipv6 addrconf: ex...
3549
  	[IFA_FLAGS]		= { .len = sizeof(u32) },
461d8837f   Thomas Graf   [IPV6] address: C...
3550
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3551
  static int
661d2967b   Thomas Graf   rtnetlink: Remove...
3552
  inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3553
  {
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
3554
  	struct net *net = sock_net(skb->sk);
b933f7166   Thomas Graf   [IPV6] address: C...
3555
3556
  	struct ifaddrmsg *ifm;
  	struct nlattr *tb[IFA_MAX+1];
caeaba790   Nicolas Dichtel   ipv6: add support...
3557
  	struct in6_addr *pfx, *peer_pfx;
b933f7166   Thomas Graf   [IPV6] address: C...
3558
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3559

b933f7166   Thomas Graf   [IPV6] address: C...
3560
3561
3562
3563
3564
  	err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
  	if (err < 0)
  		return err;
  
  	ifm = nlmsg_data(nlh);
caeaba790   Nicolas Dichtel   ipv6: add support...
3565
  	pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL], &peer_pfx);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3566
3567
  	if (pfx == NULL)
  		return -EINVAL;
af2849377   Daniel Lezcano   [NETNS][IPV6] add...
3568
  	return inet6_addr_del(net, ifm->ifa_index, pfx, ifm->ifa_prefixlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3569
  }
479840ffd   Jiri Pirko   ipv6 addrconf: ex...
3570
  static int inet6_addr_modify(struct inet6_ifaddr *ifp, u32 ifa_flags,
55ebaef1d   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
3571
  			     u32 prefered_lft, u32 valid_lft)
081bba5b3   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
3572
  {
6f704992d   YOSHIFUJI Hideaki   ipv6 addrconf: Al...
3573
3574
  	u32 flags;
  	clock_t expires;
4bed72e4f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
3575
  	unsigned long timeout;
53bd67491   Jiri Pirko   ipv6 addrconf: in...
3576
  	bool was_managetempaddr;
5b84efecb   Thomas Haller   ipv6 addrconf: do...
3577
  	bool had_prefixroute;
46d480468   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
3578

c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
3579
  	ASSERT_RTNL();
081bba5b3   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
3580
3581
  	if (!valid_lft || (prefered_lft > valid_lft))
  		return -EINVAL;
53bd67491   Jiri Pirko   ipv6 addrconf: in...
3582
3583
3584
  	if (ifa_flags & IFA_F_MANAGETEMPADDR &&
  	    (ifp->flags & IFA_F_TEMPORARY || ifp->prefix_len != 64))
  		return -EINVAL;
4bed72e4f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
3585
3586
3587
3588
  	timeout = addrconf_timeout_fixup(valid_lft, HZ);
  	if (addrconf_finite_timeout(timeout)) {
  		expires = jiffies_to_clock_t(timeout * HZ);
  		valid_lft = timeout;
6f704992d   YOSHIFUJI Hideaki   ipv6 addrconf: Al...
3589
  		flags = RTF_EXPIRES;
4bed72e4f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
3590
3591
3592
3593
  	} else {
  		expires = 0;
  		flags = 0;
  		ifa_flags |= IFA_F_PERMANENT;
6f704992d   YOSHIFUJI Hideaki   ipv6 addrconf: Al...
3594
  	}
081bba5b3   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
3595

4bed72e4f   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
3596
3597
3598
3599
3600
3601
  	timeout = addrconf_timeout_fixup(prefered_lft, HZ);
  	if (addrconf_finite_timeout(timeout)) {
  		if (timeout == 0)
  			ifa_flags |= IFA_F_DEPRECATED;
  		prefered_lft = timeout;
  	}
081bba5b3   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
3602
3603
  
  	spin_lock_bh(&ifp->lock);
53bd67491   Jiri Pirko   ipv6 addrconf: in...
3604
  	was_managetempaddr = ifp->flags & IFA_F_MANAGETEMPADDR;
5b84efecb   Thomas Haller   ipv6 addrconf: do...
3605
3606
  	had_prefixroute = ifp->flags & IFA_F_PERMANENT &&
  			  !(ifp->flags & IFA_F_NOPREFIXROUTE);
53bd67491   Jiri Pirko   ipv6 addrconf: in...
3607
  	ifp->flags &= ~(IFA_F_DEPRECATED | IFA_F_PERMANENT | IFA_F_NODAD |
761aac737   Thomas Haller   ipv6 addrconf: ad...
3608
3609
  			IFA_F_HOMEADDRESS | IFA_F_MANAGETEMPADDR |
  			IFA_F_NOPREFIXROUTE);
53bd67491   Jiri Pirko   ipv6 addrconf: in...
3610
  	ifp->flags |= ifa_flags;
081bba5b3   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
3611
3612
3613
3614
3615
3616
3617
  	ifp->tstamp = jiffies;
  	ifp->valid_lft = valid_lft;
  	ifp->prefered_lft = prefered_lft;
  
  	spin_unlock_bh(&ifp->lock);
  	if (!(ifp->flags&IFA_F_TENTATIVE))
  		ipv6_ifa_notify(0, ifp);
081bba5b3   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
3618

761aac737   Thomas Haller   ipv6 addrconf: ad...
3619
3620
3621
  	if (!(ifa_flags & IFA_F_NOPREFIXROUTE)) {
  		addrconf_prefix_route(&ifp->addr, ifp->prefix_len, ifp->idev->dev,
  				      expires, flags);
5b84efecb   Thomas Haller   ipv6 addrconf: do...
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
  	} else if (had_prefixroute) {
  		enum cleanup_prefix_rt_t action;
  		unsigned long rt_expires;
  
  		write_lock_bh(&ifp->idev->lock);
  		action = check_cleanup_prefix_route(ifp, &rt_expires);
  		write_unlock_bh(&ifp->idev->lock);
  
  		if (action != CLEANUP_PREFIX_RT_NOP) {
  			cleanup_prefix_route(ifp, rt_expires,
  				action == CLEANUP_PREFIX_RT_DEL);
  		}
761aac737   Thomas Haller   ipv6 addrconf: ad...
3634
  	}
53bd67491   Jiri Pirko   ipv6 addrconf: in...
3635
3636
3637
3638
3639
3640
3641
  
  	if (was_managetempaddr || ifp->flags & IFA_F_MANAGETEMPADDR) {
  		if (was_managetempaddr && !(ifp->flags & IFA_F_MANAGETEMPADDR))
  			valid_lft = prefered_lft = 0;
  		manage_tempaddrs(ifp->idev, ifp, valid_lft, prefered_lft,
  				 !was_managetempaddr, jiffies);
  	}
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
3642
  	addrconf_verify_rtnl();
081bba5b3   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
3643
3644
3645
3646
3647
  
  	return 0;
  }
  
  static int
661d2967b   Thomas Graf   rtnetlink: Remove...
3648
  inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3649
  {
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
3650
  	struct net *net = sock_net(skb->sk);
461d8837f   Thomas Graf   [IPV6] address: C...
3651
3652
  	struct ifaddrmsg *ifm;
  	struct nlattr *tb[IFA_MAX+1];
caeaba790   Nicolas Dichtel   ipv6: add support...
3653
  	struct in6_addr *pfx, *peer_pfx;
7198f8cec   Thomas Graf   [IPV6] address: S...
3654
3655
  	struct inet6_ifaddr *ifa;
  	struct net_device *dev;
55ebaef1d   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
3656
  	u32 valid_lft = INFINITY_LIFE_TIME, preferred_lft = INFINITY_LIFE_TIME;
479840ffd   Jiri Pirko   ipv6 addrconf: ex...
3657
  	u32 ifa_flags;
461d8837f   Thomas Graf   [IPV6] address: C...
3658
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3659

461d8837f   Thomas Graf   [IPV6] address: C...
3660
3661
3662
3663
3664
  	err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
  	if (err < 0)
  		return err;
  
  	ifm = nlmsg_data(nlh);
caeaba790   Nicolas Dichtel   ipv6: add support...
3665
  	pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL], &peer_pfx);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3666
3667
  	if (pfx == NULL)
  		return -EINVAL;
461d8837f   Thomas Graf   [IPV6] address: C...
3668
  	if (tb[IFA_CACHEINFO]) {
0778769d3   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
3669
  		struct ifa_cacheinfo *ci;
461d8837f   Thomas Graf   [IPV6] address: C...
3670
3671
  
  		ci = nla_data(tb[IFA_CACHEINFO]);
0778769d3   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
3672
  		valid_lft = ci->ifa_valid;
461d8837f   Thomas Graf   [IPV6] address: C...
3673
3674
3675
3676
  		preferred_lft = ci->ifa_prefered;
  	} else {
  		preferred_lft = INFINITY_LIFE_TIME;
  		valid_lft = INFINITY_LIFE_TIME;
0778769d3   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
3677
  	}
af2849377   Daniel Lezcano   [NETNS][IPV6] add...
3678
  	dev =  __dev_get_by_index(net, ifm->ifa_index);
7198f8cec   Thomas Graf   [IPV6] address: S...
3679
3680
  	if (dev == NULL)
  		return -ENODEV;
479840ffd   Jiri Pirko   ipv6 addrconf: ex...
3681
  	ifa_flags = tb[IFA_FLAGS] ? nla_get_u32(tb[IFA_FLAGS]) : ifm->ifa_flags;
55ebaef1d   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
3682
  	/* We ignore other flags so far. */
761aac737   Thomas Haller   ipv6 addrconf: ad...
3683
3684
  	ifa_flags &= IFA_F_NODAD | IFA_F_HOMEADDRESS | IFA_F_MANAGETEMPADDR |
  		     IFA_F_NOPREFIXROUTE;
55ebaef1d   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
3685

1cab3da6b   Daniel Lezcano   [NETNS][IPV6]: in...
3686
  	ifa = ipv6_get_ifaddr(net, pfx, dev, 1);
7198f8cec   Thomas Graf   [IPV6] address: S...
3687
3688
3689
  	if (ifa == NULL) {
  		/*
  		 * It would be best to check for !NLM_F_CREATE here but
db9c7c394   stephen hemminger   ipv6: addrconf sp...
3690
  		 * userspace already relies on not having to provide this.
7198f8cec   Thomas Graf   [IPV6] address: S...
3691
  		 */
caeaba790   Nicolas Dichtel   ipv6: add support...
3692
  		return inet6_addr_add(net, ifm->ifa_index, pfx, peer_pfx,
af2849377   Daniel Lezcano   [NETNS][IPV6] add...
3693
3694
  				      ifm->ifa_prefixlen, ifa_flags,
  				      preferred_lft, valid_lft);
081bba5b3   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
3695
  	}
7198f8cec   Thomas Graf   [IPV6] address: S...
3696
3697
3698
3699
  	if (nlh->nlmsg_flags & NLM_F_EXCL ||
  	    !(nlh->nlmsg_flags & NLM_F_REPLACE))
  		err = -EEXIST;
  	else
55ebaef1d   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
3700
  		err = inet6_addr_modify(ifa, ifa_flags, preferred_lft, valid_lft);
7198f8cec   Thomas Graf   [IPV6] address: S...
3701
3702
3703
3704
  
  	in6_ifa_put(ifa);
  
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3705
  }
479840ffd   Jiri Pirko   ipv6 addrconf: ex...
3706
  static void put_ifaddrmsg(struct nlmsghdr *nlh, u8 prefixlen, u32 flags,
101bb2296   Thomas Graf   [IPV6] address: A...
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
  			  u8 scope, int ifindex)
  {
  	struct ifaddrmsg *ifm;
  
  	ifm = nlmsg_data(nlh);
  	ifm->ifa_family = AF_INET6;
  	ifm->ifa_prefixlen = prefixlen;
  	ifm->ifa_flags = flags;
  	ifm->ifa_scope = scope;
  	ifm->ifa_index = ifindex;
  }
85486af00   Thomas Graf   [IPV6] address: A...
3718
3719
3720
3721
  static int put_cacheinfo(struct sk_buff *skb, unsigned long cstamp,
  			 unsigned long tstamp, u32 preferred, u32 valid)
  {
  	struct ifa_cacheinfo ci;
18a31e1e2   Thomas Graf   ipv6: Expose reac...
3722
3723
  	ci.cstamp = cstamp_delta(cstamp);
  	ci.tstamp = cstamp_delta(tstamp);
85486af00   Thomas Graf   [IPV6] address: A...
3724
3725
3726
3727
3728
  	ci.ifa_prefered = preferred;
  	ci.ifa_valid = valid;
  
  	return nla_put(skb, IFA_CACHEINFO, sizeof(ci), &ci);
  }
101bb2296   Thomas Graf   [IPV6] address: A...
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
  static inline int rt_scope(int ifa_scope)
  {
  	if (ifa_scope & IFA_HOST)
  		return RT_SCOPE_HOST;
  	else if (ifa_scope & IFA_LINK)
  		return RT_SCOPE_LINK;
  	else if (ifa_scope & IFA_SITE)
  		return RT_SCOPE_SITE;
  	else
  		return RT_SCOPE_UNIVERSE;
  }
0ab6803bc   Thomas Graf   [IPV6] address: C...
3740
3741
  static inline int inet6_ifaddr_msgsize(void)
  {
339bf98ff   Thomas Graf   [NETLINK]: Do pre...
3742
  	return NLMSG_ALIGN(sizeof(struct ifaddrmsg))
caeaba790   Nicolas Dichtel   ipv6: add support...
3743
  	       + nla_total_size(16) /* IFA_LOCAL */
339bf98ff   Thomas Graf   [NETLINK]: Do pre...
3744
  	       + nla_total_size(16) /* IFA_ADDRESS */
479840ffd   Jiri Pirko   ipv6 addrconf: ex...
3745
3746
  	       + nla_total_size(sizeof(struct ifa_cacheinfo))
  	       + nla_total_size(4)  /* IFA_FLAGS */;
0ab6803bc   Thomas Graf   [IPV6] address: C...
3747
  }
c5396a31b   YOSHIFUJI Hideaki   [IPV6]: Sum real ...
3748

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3749
  static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
15e473046   Eric W. Biederman   netlink: Rename p...
3750
  			     u32 portid, u32 seq, int event, unsigned int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3751
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3752
  	struct nlmsghdr  *nlh;
85486af00   Thomas Graf   [IPV6] address: A...
3753
  	u32 preferred, valid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3754

15e473046   Eric W. Biederman   netlink: Rename p...
3755
  	nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct ifaddrmsg), flags);
0ab6803bc   Thomas Graf   [IPV6] address: C...
3756
  	if (nlh == NULL)
26932566a   Patrick McHardy   [NETLINK]: Don't ...
3757
  		return -EMSGSIZE;
0ab6803bc   Thomas Graf   [IPV6] address: C...
3758

101bb2296   Thomas Graf   [IPV6] address: A...
3759
3760
  	put_ifaddrmsg(nlh, ifa->prefix_len, ifa->flags, rt_scope(ifa->scope),
  		      ifa->idev->dev->ifindex);
fad8da3e0   Yasushi Asano   ipv6 addrconf: fi...
3761
3762
  	if (!((ifa->flags&IFA_F_PERMANENT) &&
  	      (ifa->prefered_lft == INFINITY_LIFE_TIME))) {
85486af00   Thomas Graf   [IPV6] address: A...
3763
3764
3765
  		preferred = ifa->prefered_lft;
  		valid = ifa->valid_lft;
  		if (preferred != INFINITY_LIFE_TIME) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3766
  			long tval = (jiffies - ifa->tstamp)/HZ;
a1faa6981   Jens Rosenboom   ipv6: avoid wrapa...
3767
3768
3769
3770
  			if (preferred > tval)
  				preferred -= tval;
  			else
  				preferred = 0;
f56619fc7   Ben Hutchings   ipv6: Clamp repor...
3771
3772
3773
3774
3775
3776
  			if (valid != INFINITY_LIFE_TIME) {
  				if (valid > tval)
  					valid -= tval;
  				else
  					valid = 0;
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3777
3778
  		}
  	} else {
85486af00   Thomas Graf   [IPV6] address: A...
3779
3780
3781
  		preferred = INFINITY_LIFE_TIME;
  		valid = INFINITY_LIFE_TIME;
  	}
7996c799a   Cong Wang   ipv6: use ipv6_ad...
3782
  	if (!ipv6_addr_any(&ifa->peer_addr)) {
caeaba790   Nicolas Dichtel   ipv6: add support...
3783
3784
3785
3786
3787
3788
3789
3790
3791
  		if (nla_put(skb, IFA_LOCAL, 16, &ifa->addr) < 0 ||
  		    nla_put(skb, IFA_ADDRESS, 16, &ifa->peer_addr) < 0)
  			goto error;
  	} else
  		if (nla_put(skb, IFA_ADDRESS, 16, &ifa->addr) < 0)
  			goto error;
  
  	if (put_cacheinfo(skb, ifa->cstamp, ifa->tstamp, preferred, valid) < 0)
  		goto error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3792

479840ffd   Jiri Pirko   ipv6 addrconf: ex...
3793
3794
  	if (nla_put_u32(skb, IFA_FLAGS, ifa->flags) < 0)
  		goto error;
0ab6803bc   Thomas Graf   [IPV6] address: C...
3795
  	return nlmsg_end(skb, nlh);
caeaba790   Nicolas Dichtel   ipv6: add support...
3796
3797
3798
3799
  
  error:
  	nlmsg_cancel(skb, nlh);
  	return -EMSGSIZE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3800
3801
3802
  }
  
  static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca,
15e473046   Eric W. Biederman   netlink: Rename p...
3803
  				u32 portid, u32 seq, int event, u16 flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3804
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3805
  	struct nlmsghdr  *nlh;
101bb2296   Thomas Graf   [IPV6] address: A...
3806
3807
3808
3809
3810
  	u8 scope = RT_SCOPE_UNIVERSE;
  	int ifindex = ifmca->idev->dev->ifindex;
  
  	if (ipv6_addr_scope(&ifmca->mca_addr) & IFA_SITE)
  		scope = RT_SCOPE_SITE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3811

15e473046   Eric W. Biederman   netlink: Rename p...
3812
  	nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct ifaddrmsg), flags);
0ab6803bc   Thomas Graf   [IPV6] address: C...
3813
  	if (nlh == NULL)
26932566a   Patrick McHardy   [NETLINK]: Don't ...
3814
  		return -EMSGSIZE;
85486af00   Thomas Graf   [IPV6] address: A...
3815

0ab6803bc   Thomas Graf   [IPV6] address: C...
3816
3817
3818
  	put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex);
  	if (nla_put(skb, IFA_MULTICAST, 16, &ifmca->mca_addr) < 0 ||
  	    put_cacheinfo(skb, ifmca->mca_cstamp, ifmca->mca_tstamp,
26932566a   Patrick McHardy   [NETLINK]: Don't ...
3819
3820
3821
3822
  			  INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0) {
  		nlmsg_cancel(skb, nlh);
  		return -EMSGSIZE;
  	}
85486af00   Thomas Graf   [IPV6] address: A...
3823

0ab6803bc   Thomas Graf   [IPV6] address: C...
3824
  	return nlmsg_end(skb, nlh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3825
3826
3827
  }
  
  static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca,
15e473046   Eric W. Biederman   netlink: Rename p...
3828
  				u32 portid, u32 seq, int event, unsigned int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3829
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3830
  	struct nlmsghdr  *nlh;
101bb2296   Thomas Graf   [IPV6] address: A...
3831
3832
3833
3834
3835
  	u8 scope = RT_SCOPE_UNIVERSE;
  	int ifindex = ifaca->aca_idev->dev->ifindex;
  
  	if (ipv6_addr_scope(&ifaca->aca_addr) & IFA_SITE)
  		scope = RT_SCOPE_SITE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3836

15e473046   Eric W. Biederman   netlink: Rename p...
3837
  	nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct ifaddrmsg), flags);
0ab6803bc   Thomas Graf   [IPV6] address: C...
3838
  	if (nlh == NULL)
26932566a   Patrick McHardy   [NETLINK]: Don't ...
3839
  		return -EMSGSIZE;
85486af00   Thomas Graf   [IPV6] address: A...
3840

0ab6803bc   Thomas Graf   [IPV6] address: C...
3841
3842
3843
  	put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex);
  	if (nla_put(skb, IFA_ANYCAST, 16, &ifaca->aca_addr) < 0 ||
  	    put_cacheinfo(skb, ifaca->aca_cstamp, ifaca->aca_tstamp,
26932566a   Patrick McHardy   [NETLINK]: Don't ...
3844
3845
3846
3847
  			  INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0) {
  		nlmsg_cancel(skb, nlh);
  		return -EMSGSIZE;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3848

0ab6803bc   Thomas Graf   [IPV6] address: C...
3849
  	return nlmsg_end(skb, nlh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3850
  }
e21e8467d   Stephen Hemminger   addrconf: checkpa...
3851
  enum addr_type_t {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3852
3853
3854
3855
  	UNICAST_ADDR,
  	MULTICAST_ADDR,
  	ANYCAST_ADDR,
  };
234b27c3f   Eric Dumazet   ipv6: speedup ine...
3856
3857
3858
3859
3860
  /* called with rcu_read_lock() */
  static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb,
  			  struct netlink_callback *cb, enum addr_type_t type,
  			  int s_ip_idx, int *p_ip_idx)
  {
234b27c3f   Eric Dumazet   ipv6: speedup ine...
3861
3862
3863
3864
3865
3866
3867
  	struct ifmcaddr6 *ifmca;
  	struct ifacaddr6 *ifaca;
  	int err = 1;
  	int ip_idx = *p_ip_idx;
  
  	read_lock_bh(&idev->lock);
  	switch (type) {
502a2ffd7   stephen hemminger   ipv6: convert ide...
3868
3869
  	case UNICAST_ADDR: {
  		struct inet6_ifaddr *ifa;
234b27c3f   Eric Dumazet   ipv6: speedup ine...
3870
  		/* unicast address incl. temp addr */
502a2ffd7   stephen hemminger   ipv6: convert ide...
3871
3872
  		list_for_each_entry(ifa, &idev->addr_list, if_list) {
  			if (++ip_idx < s_ip_idx)
234b27c3f   Eric Dumazet   ipv6: speedup ine...
3873
3874
  				continue;
  			err = inet6_fill_ifaddr(skb, ifa,
15e473046   Eric W. Biederman   netlink: Rename p...
3875
  						NETLINK_CB(cb->skb).portid,
234b27c3f   Eric Dumazet   ipv6: speedup ine...
3876
3877
3878
3879
3880
  						cb->nlh->nlmsg_seq,
  						RTM_NEWADDR,
  						NLM_F_MULTI);
  			if (err <= 0)
  				break;
63998ac24   Nicolas Dichtel   ipv6: provide add...
3881
  			nl_dump_check_consistent(cb, nlmsg_hdr(skb));
234b27c3f   Eric Dumazet   ipv6: speedup ine...
3882
3883
  		}
  		break;
502a2ffd7   stephen hemminger   ipv6: convert ide...
3884
  	}
234b27c3f   Eric Dumazet   ipv6: speedup ine...
3885
3886
3887
3888
3889
3890
3891
  	case MULTICAST_ADDR:
  		/* multicast address */
  		for (ifmca = idev->mc_list; ifmca;
  		     ifmca = ifmca->next, ip_idx++) {
  			if (ip_idx < s_ip_idx)
  				continue;
  			err = inet6_fill_ifmcaddr(skb, ifmca,
15e473046   Eric W. Biederman   netlink: Rename p...
3892
  						  NETLINK_CB(cb->skb).portid,
234b27c3f   Eric Dumazet   ipv6: speedup ine...
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
  						  cb->nlh->nlmsg_seq,
  						  RTM_GETMULTICAST,
  						  NLM_F_MULTI);
  			if (err <= 0)
  				break;
  		}
  		break;
  	case ANYCAST_ADDR:
  		/* anycast address */
  		for (ifaca = idev->ac_list; ifaca;
  		     ifaca = ifaca->aca_next, ip_idx++) {
  			if (ip_idx < s_ip_idx)
  				continue;
  			err = inet6_fill_ifacaddr(skb, ifaca,
15e473046   Eric W. Biederman   netlink: Rename p...
3907
  						  NETLINK_CB(cb->skb).portid,
234b27c3f   Eric Dumazet   ipv6: speedup ine...
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
  						  cb->nlh->nlmsg_seq,
  						  RTM_GETANYCAST,
  						  NLM_F_MULTI);
  			if (err <= 0)
  				break;
  		}
  		break;
  	default:
  		break;
  	}
  	read_unlock_bh(&idev->lock);
  	*p_ip_idx = ip_idx;
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3922
3923
3924
  static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
  			   enum addr_type_t type)
  {
234b27c3f   Eric Dumazet   ipv6: speedup ine...
3925
3926
  	struct net *net = sock_net(skb->sk);
  	int h, s_h;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3927
3928
  	int idx, ip_idx;
  	int s_idx, s_ip_idx;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3929
  	struct net_device *dev;
234b27c3f   Eric Dumazet   ipv6: speedup ine...
3930
3931
  	struct inet6_dev *idev;
  	struct hlist_head *head;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
3932

234b27c3f   Eric Dumazet   ipv6: speedup ine...
3933
3934
3935
  	s_h = cb->args[0];
  	s_idx = idx = cb->args[1];
  	s_ip_idx = ip_idx = cb->args[2];
5d5619b40   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
3936

234b27c3f   Eric Dumazet   ipv6: speedup ine...
3937
  	rcu_read_lock();
63998ac24   Nicolas Dichtel   ipv6: provide add...
3938
  	cb->seq = atomic_read(&net->ipv6.dev_addr_genid) ^ net->dev_base_seq;
234b27c3f   Eric Dumazet   ipv6: speedup ine...
3939
3940
3941
  	for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
  		idx = 0;
  		head = &net->dev_index_head[h];
b67bfe0d4   Sasha Levin   hlist: drop the n...
3942
  		hlist_for_each_entry_rcu(dev, head, index_hlist) {
234b27c3f   Eric Dumazet   ipv6: speedup ine...
3943
3944
  			if (idx < s_idx)
  				goto cont;
4b97efdf3   Patrick McHardy   net: fix netlink ...
3945
  			if (h > s_h || idx > s_idx)
234b27c3f   Eric Dumazet   ipv6: speedup ine...
3946
3947
  				s_ip_idx = 0;
  			ip_idx = 0;
e21e8467d   Stephen Hemminger   addrconf: checkpa...
3948
3949
  			idev = __in6_dev_get(dev);
  			if (!idev)
234b27c3f   Eric Dumazet   ipv6: speedup ine...
3950
3951
3952
3953
3954
  				goto cont;
  
  			if (in6_dump_addrs(idev, skb, cb, type,
  					   s_ip_idx, &ip_idx) <= 0)
  				goto done;
7562f876c   Pavel Emelianov   [NET]: Rework dev...
3955
  cont:
234b27c3f   Eric Dumazet   ipv6: speedup ine...
3956
3957
  			idx++;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3958
  	}
234b27c3f   Eric Dumazet   ipv6: speedup ine...
3959
3960
3961
3962
3963
  done:
  	rcu_read_unlock();
  	cb->args[0] = h;
  	cb->args[1] = idx;
  	cb->args[2] = ip_idx;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3964
3965
3966
3967
3968
3969
  	return skb->len;
  }
  
  static int inet6_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
  {
  	enum addr_type_t type = UNICAST_ADDR;
b854272b3   Denis V. Lunev   [NET]: Modify all...
3970

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3971
3972
3973
3974
3975
3976
  	return inet6_dump_addr(skb, cb, type);
  }
  
  static int inet6_dump_ifmcaddr(struct sk_buff *skb, struct netlink_callback *cb)
  {
  	enum addr_type_t type = MULTICAST_ADDR;
b854272b3   Denis V. Lunev   [NET]: Modify all...
3977

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3978
3979
3980
3981
3982
3983
3984
  	return inet6_dump_addr(skb, cb, type);
  }
  
  
  static int inet6_dump_ifacaddr(struct sk_buff *skb, struct netlink_callback *cb)
  {
  	enum addr_type_t type = ANYCAST_ADDR;
b854272b3   Denis V. Lunev   [NET]: Modify all...
3985

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3986
3987
  	return inet6_dump_addr(skb, cb, type);
  }
661d2967b   Thomas Graf   rtnetlink: Remove...
3988
  static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh)
6c2238280   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
3989
  {
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
3990
  	struct net *net = sock_net(in_skb->sk);
1b29fc2c8   Thomas Graf   [IPV6] address: C...
3991
3992
  	struct ifaddrmsg *ifm;
  	struct nlattr *tb[IFA_MAX+1];
caeaba790   Nicolas Dichtel   ipv6: add support...
3993
  	struct in6_addr *addr = NULL, *peer;
6c2238280   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
3994
3995
3996
  	struct net_device *dev = NULL;
  	struct inet6_ifaddr *ifa;
  	struct sk_buff *skb;
6c2238280   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
3997
  	int err;
1b29fc2c8   Thomas Graf   [IPV6] address: C...
3998
3999
4000
  	err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
  	if (err < 0)
  		goto errout;
caeaba790   Nicolas Dichtel   ipv6: add support...
4001
  	addr = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL], &peer);
1b29fc2c8   Thomas Graf   [IPV6] address: C...
4002
4003
4004
  	if (addr == NULL) {
  		err = -EINVAL;
  		goto errout;
6c2238280   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
4005
  	}
6c2238280   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
4006

1b29fc2c8   Thomas Graf   [IPV6] address: C...
4007
  	ifm = nlmsg_data(nlh);
6c2238280   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
4008
  	if (ifm->ifa_index)
6fda73500   Benjamin Thery   [NETNS][IPV6] add...
4009
  		dev = __dev_get_by_index(net, ifm->ifa_index);
6c2238280   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
4010

e21e8467d   Stephen Hemminger   addrconf: checkpa...
4011
4012
  	ifa = ipv6_get_ifaddr(net, addr, dev, 1);
  	if (!ifa) {
1b29fc2c8   Thomas Graf   [IPV6] address: C...
4013
4014
4015
  		err = -EADDRNOTAVAIL;
  		goto errout;
  	}
6c2238280   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
4016

e21e8467d   Stephen Hemminger   addrconf: checkpa...
4017
4018
  	skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_KERNEL);
  	if (!skb) {
6c2238280   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
4019
  		err = -ENOBUFS;
1b29fc2c8   Thomas Graf   [IPV6] address: C...
4020
  		goto errout_ifa;
6c2238280   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
4021
  	}
15e473046   Eric W. Biederman   netlink: Rename p...
4022
  	err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).portid,
6c2238280   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
4023
  				nlh->nlmsg_seq, RTM_NEWADDR, 0);
26932566a   Patrick McHardy   [NETLINK]: Don't ...
4024
4025
4026
4027
4028
4029
  	if (err < 0) {
  		/* -EMSGSIZE implies BUG in inet6_ifaddr_msgsize() */
  		WARN_ON(err == -EMSGSIZE);
  		kfree_skb(skb);
  		goto errout_ifa;
  	}
15e473046   Eric W. Biederman   netlink: Rename p...
4030
  	err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
1b29fc2c8   Thomas Graf   [IPV6] address: C...
4031
  errout_ifa:
6c2238280   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
4032
  	in6_ifa_put(ifa);
1b29fc2c8   Thomas Graf   [IPV6] address: C...
4033
  errout:
6c2238280   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
4034
  	return err;
6c2238280   Noriaki TAKAMIYA   [IPV6] ADDRCONF: ...
4035
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4036
4037
4038
  static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
  {
  	struct sk_buff *skb;
c346dca10   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
4039
  	struct net *net = dev_net(ifa->idev->dev);
5d6202664   Thomas Graf   [IPv6] address: C...
4040
  	int err = -ENOBUFS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4041

0ab6803bc   Thomas Graf   [IPV6] address: C...
4042
  	skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_ATOMIC);
5d6202664   Thomas Graf   [IPv6] address: C...
4043
4044
4045
4046
  	if (skb == NULL)
  		goto errout;
  
  	err = inet6_fill_ifaddr(skb, ifa, 0, 0, event, 0);
26932566a   Patrick McHardy   [NETLINK]: Don't ...
4047
4048
4049
4050
4051
4052
  	if (err < 0) {
  		/* -EMSGSIZE implies BUG in inet6_ifaddr_msgsize() */
  		WARN_ON(err == -EMSGSIZE);
  		kfree_skb(skb);
  		goto errout;
  	}
1ce85fe40   Pablo Neira Ayuso   netlink: change n...
4053
4054
  	rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
  	return;
5d6202664   Thomas Graf   [IPv6] address: C...
4055
4056
  errout:
  	if (err < 0)
6fda73500   Benjamin Thery   [NETNS][IPV6] add...
4057
  		rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4058
  }
b6f99a211   Dave Jones   [NET]: fix up mis...
4059
  static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4060
4061
  				__s32 *array, int bytes)
  {
04561c1fe   Thomas Graf   [IPv6] iflink: Co...
4062
  	BUG_ON(bytes < (DEVCONF_MAX * 4));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4063
4064
4065
4066
4067
4068
4069
4070
4071
  	memset(array, 0, bytes);
  	array[DEVCONF_FORWARDING] = cnf->forwarding;
  	array[DEVCONF_HOPLIMIT] = cnf->hop_limit;
  	array[DEVCONF_MTU6] = cnf->mtu6;
  	array[DEVCONF_ACCEPT_RA] = cnf->accept_ra;
  	array[DEVCONF_ACCEPT_REDIRECTS] = cnf->accept_redirects;
  	array[DEVCONF_AUTOCONF] = cnf->autoconf;
  	array[DEVCONF_DAD_TRANSMITS] = cnf->dad_transmits;
  	array[DEVCONF_RTR_SOLICITS] = cnf->rtr_solicits;
93908d192   Thomas Graf   ipv6: Expose IFLA...
4072
4073
4074
4075
  	array[DEVCONF_RTR_SOLICIT_INTERVAL] =
  		jiffies_to_msecs(cnf->rtr_solicit_interval);
  	array[DEVCONF_RTR_SOLICIT_DELAY] =
  		jiffies_to_msecs(cnf->rtr_solicit_delay);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4076
  	array[DEVCONF_FORCE_MLD_VERSION] = cnf->force_mld_version;
fc4eba58b   Hannes Frederic Sowa   ipv6: make unsoli...
4077
4078
4079
4080
  	array[DEVCONF_MLDV1_UNSOLICITED_REPORT_INTERVAL] =
  		jiffies_to_msecs(cnf->mldv1_unsolicited_report_interval);
  	array[DEVCONF_MLDV2_UNSOLICITED_REPORT_INTERVAL] =
  		jiffies_to_msecs(cnf->mldv2_unsolicited_report_interval);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4081
4082
4083
4084
4085
  	array[DEVCONF_USE_TEMPADDR] = cnf->use_tempaddr;
  	array[DEVCONF_TEMP_VALID_LFT] = cnf->temp_valid_lft;
  	array[DEVCONF_TEMP_PREFERED_LFT] = cnf->temp_prefered_lft;
  	array[DEVCONF_REGEN_MAX_RETRY] = cnf->regen_max_retry;
  	array[DEVCONF_MAX_DESYNC_FACTOR] = cnf->max_desync_factor;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4086
  	array[DEVCONF_MAX_ADDRESSES] = cnf->max_addresses;
65f5c7c11   YOSHIFUJI Hideaki   [IPV6]: ROUTE: Ad...
4087
  	array[DEVCONF_ACCEPT_RA_DEFRTR] = cnf->accept_ra_defrtr;
c4fd30eb1   YOSHIFUJI Hideaki   [IPV6]: ADDRCONF:...
4088
  	array[DEVCONF_ACCEPT_RA_PINFO] = cnf->accept_ra_pinfo;
930d6ff2e   YOSHIFUJI Hideaki   [IPV6]: ROUTE: Ad...
4089
4090
  #ifdef CONFIG_IPV6_ROUTER_PREF
  	array[DEVCONF_ACCEPT_RA_RTR_PREF] = cnf->accept_ra_rtr_pref;
93908d192   Thomas Graf   ipv6: Expose IFLA...
4091
4092
  	array[DEVCONF_RTR_PROBE_INTERVAL] =
  		jiffies_to_msecs(cnf->rtr_probe_interval);
fa03ef38e   Neil Horman   [IPV6]: Fix up so...
4093
  #ifdef CONFIG_IPV6_ROUTE_INFO
09c884d4c   YOSHIFUJI Hideaki   [IPV6]: ROUTE: Ad...
4094
4095
  	array[DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN] = cnf->accept_ra_rt_info_max_plen;
  #endif
930d6ff2e   YOSHIFUJI Hideaki   [IPV6]: ROUTE: Ad...
4096
  #endif
fbea49e1e   YOSHIFUJI Hideaki   [IPV6] NDISC: Add...
4097
  	array[DEVCONF_PROXY_NDP] = cnf->proxy_ndp;
0bcbc9262   YOSHIFUJI Hideaki   [IPV6]: Disallow ...
4098
  	array[DEVCONF_ACCEPT_SOURCE_ROUTE] = cnf->accept_source_route;
95c385b4d   Neil Horman   [IPV6] ADDRCONF: ...
4099
4100
4101
  #ifdef CONFIG_IPV6_OPTIMISTIC_DAD
  	array[DEVCONF_OPTIMISTIC_DAD] = cnf->optimistic_dad;
  #endif
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
4102
4103
4104
  #ifdef CONFIG_IPV6_MROUTE
  	array[DEVCONF_MC_FORWARDING] = cnf->mc_forwarding;
  #endif
778d80be5   YOSHIFUJI Hideaki   ipv6: Add disable...
4105
  	array[DEVCONF_DISABLE_IPV6] = cnf->disable_ipv6;
1b34be74c   YOSHIFUJI Hideaki   ipv6 addrconf: ad...
4106
  	array[DEVCONF_ACCEPT_DAD] = cnf->accept_dad;
c3faca053   Cosmin Ratiu   ipv6: fix devconf...
4107
  	array[DEVCONF_FORCE_TLLAO] = cnf->force_tllao;
5cb04436e   Hannes Frederic Sowa   ipv6: add knob to...
4108
  	array[DEVCONF_NDISC_NOTIFY] = cnf->ndisc_notify;
b800c3b96   Hannes Frederic Sowa   ipv6: drop fragme...
4109
  	array[DEVCONF_SUPPRESS_FRAG_NDISC] = cnf->suppress_frag_ndisc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4110
  }
b382b191e   Thomas Graf   ipv6: AF_INET6 li...
4111
4112
4113
4114
4115
4116
  static inline size_t inet6_ifla6_size(void)
  {
  	return nla_total_size(4) /* IFLA_INET6_FLAGS */
  	     + nla_total_size(sizeof(struct ifla_cacheinfo))
  	     + nla_total_size(DEVCONF_MAX * 4) /* IFLA_INET6_CONF */
  	     + nla_total_size(IPSTATS_MIB_MAX * 8) /* IFLA_INET6_STATS */
f53adae4e   Daniel Borkmann   net: ipv6: add to...
4117
4118
  	     + nla_total_size(ICMP6_MIB_MAX * 8) /* IFLA_INET6_ICMP6STATS */
  	     + nla_total_size(sizeof(struct in6_addr)); /* IFLA_INET6_TOKEN */
b382b191e   Thomas Graf   ipv6: AF_INET6 li...
4119
  }
339bf98ff   Thomas Graf   [NETLINK]: Do pre...
4120
4121
4122
4123
4124
4125
4126
  static inline size_t inet6_if_nlmsg_size(void)
  {
  	return NLMSG_ALIGN(sizeof(struct ifinfomsg))
  	       + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
  	       + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */
  	       + nla_total_size(4) /* IFLA_MTU */
  	       + nla_total_size(4) /* IFLA_LINK */
b382b191e   Thomas Graf   ipv6: AF_INET6 li...
4127
  	       + nla_total_size(inet6_ifla6_size()); /* IFLA_PROTINFO */
339bf98ff   Thomas Graf   [NETLINK]: Do pre...
4128
  }
c5396a31b   YOSHIFUJI Hideaki   [IPV6]: Sum real ...
4129

be281e554   Eric Dumazet   ipv6: reduce per ...
4130
  static inline void __snmp6_fill_statsdev(u64 *stats, atomic_long_t *mib,
7d720c3e4   Tejun Heo   percpu: add __per...
4131
  				      int items, int bytes)
7f7d9a6b9   Herbert Xu   [IPV6]: Consolida...
4132
4133
4134
4135
4136
4137
4138
4139
  {
  	int i;
  	int pad = bytes - sizeof(u64) * items;
  	BUG_ON(pad < 0);
  
  	/* Use put_unaligned() because stats may not be aligned for u64. */
  	put_unaligned(items, &stats[0]);
  	for (i = 1; i < items; i++)
be281e554   Eric Dumazet   ipv6: reduce per ...
4140
  		put_unaligned(atomic_long_read(&mib[i]), &stats[i]);
7f7d9a6b9   Herbert Xu   [IPV6]: Consolida...
4141
4142
4143
  
  	memset(&stats[items], 0, pad);
  }
4ce3c183f   Eric Dumazet   snmp: 64bit ipsta...
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
  static inline void __snmp6_fill_stats64(u64 *stats, void __percpu **mib,
  				      int items, int bytes, size_t syncpoff)
  {
  	int i;
  	int pad = bytes - sizeof(u64) * items;
  	BUG_ON(pad < 0);
  
  	/* Use put_unaligned() because stats may not be aligned for u64. */
  	put_unaligned(items, &stats[0]);
  	for (i = 1; i < items; i++)
  		put_unaligned(snmp_fold_field64(mib, i, syncpoff), &stats[i]);
  
  	memset(&stats[items], 0, pad);
  }
7f7d9a6b9   Herbert Xu   [IPV6]: Consolida...
4158
4159
4160
  static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype,
  			     int bytes)
  {
e21e8467d   Stephen Hemminger   addrconf: checkpa...
4161
  	switch (attrtype) {
7f7d9a6b9   Herbert Xu   [IPV6]: Consolida...
4162
  	case IFLA_INET6_STATS:
4ce3c183f   Eric Dumazet   snmp: 64bit ipsta...
4163
4164
  		__snmp6_fill_stats64(stats, (void __percpu **)idev->stats.ipv6,
  				     IPSTATS_MIB_MAX, bytes, offsetof(struct ipstats_mib, syncp));
7f7d9a6b9   Herbert Xu   [IPV6]: Consolida...
4165
4166
  		break;
  	case IFLA_INET6_ICMP6STATS:
be281e554   Eric Dumazet   ipv6: reduce per ...
4167
  		__snmp6_fill_statsdev(stats, idev->stats.icmpv6dev->mibs, ICMP6_MIB_MAX, bytes);
7f7d9a6b9   Herbert Xu   [IPV6]: Consolida...
4168
4169
4170
  		break;
  	}
  }
b382b191e   Thomas Graf   ipv6: AF_INET6 li...
4171
4172
4173
4174
  static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev)
  {
  	struct nlattr *nla;
  	struct ifla_cacheinfo ci;
c78679e8f   David S. Miller   ipv6: Stop using ...
4175
4176
  	if (nla_put_u32(skb, IFLA_INET6_FLAGS, idev->if_flags))
  		goto nla_put_failure;
b382b191e   Thomas Graf   ipv6: AF_INET6 li...
4177
  	ci.max_reasm_len = IPV6_MAXPLEN;
24912420e   David S. Miller   Merge branch 'mas...
4178
4179
  	ci.tstamp = cstamp_delta(idev->tstamp);
  	ci.reachable_time = jiffies_to_msecs(idev->nd_parms->reachable_time);
1f9248e56   Jiri Pirko   neigh: convert pa...
4180
  	ci.retrans_time = jiffies_to_msecs(NEIGH_VAR(idev->nd_parms, RETRANS_TIME));
c78679e8f   David S. Miller   ipv6: Stop using ...
4181
4182
  	if (nla_put(skb, IFLA_INET6_CACHEINFO, sizeof(ci), &ci))
  		goto nla_put_failure;
b382b191e   Thomas Graf   ipv6: AF_INET6 li...
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
  	nla = nla_reserve(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(s32));
  	if (nla == NULL)
  		goto nla_put_failure;
  	ipv6_store_devconf(&idev->cnf, nla_data(nla), nla_len(nla));
  
  	/* XXX - MC not implemented */
  
  	nla = nla_reserve(skb, IFLA_INET6_STATS, IPSTATS_MIB_MAX * sizeof(u64));
  	if (nla == NULL)
  		goto nla_put_failure;
  	snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_STATS, nla_len(nla));
  
  	nla = nla_reserve(skb, IFLA_INET6_ICMP6STATS, ICMP6_MIB_MAX * sizeof(u64));
  	if (nla == NULL)
  		goto nla_put_failure;
  	snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_ICMP6STATS, nla_len(nla));
f53adae4e   Daniel Borkmann   net: ipv6: add to...
4199
4200
4201
4202
4203
4204
  	nla = nla_reserve(skb, IFLA_INET6_TOKEN, sizeof(struct in6_addr));
  	if (nla == NULL)
  		goto nla_put_failure;
  	read_lock_bh(&idev->lock);
  	memcpy(nla_data(nla), idev->token.s6_addr, nla_len(nla));
  	read_unlock_bh(&idev->lock);
b382b191e   Thomas Graf   ipv6: AF_INET6 li...
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
  	return 0;
  
  nla_put_failure:
  	return -EMSGSIZE;
  }
  
  static size_t inet6_get_link_af_size(const struct net_device *dev)
  {
  	if (!__in6_dev_get(dev))
  		return 0;
  
  	return inet6_ifla6_size();
  }
  
  static int inet6_fill_link_af(struct sk_buff *skb, const struct net_device *dev)
  {
  	struct inet6_dev *idev = __in6_dev_get(dev);
  
  	if (!idev)
  		return -ENODATA;
  
  	if (inet6_fill_ifla6_attrs(skb, idev) < 0)
  		return -EMSGSIZE;
  
  	return 0;
  }
f53adae4e   Daniel Borkmann   net: ipv6: add to...
4231
4232
  static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token)
  {
f53adae4e   Daniel Borkmann   net: ipv6: add to...
4233
4234
  	struct inet6_ifaddr *ifp;
  	struct net_device *dev = idev->dev;
fc403832f   Daniel Borkmann   net: ipv6: also a...
4235
  	bool update_rs = false;
dc8482926   Hannes Frederic Sowa   ipv6: check retur...
4236
  	struct in6_addr ll_addr;
f53adae4e   Daniel Borkmann   net: ipv6: add to...
4237

c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
4238
  	ASSERT_RTNL();
f53adae4e   Daniel Borkmann   net: ipv6: add to...
4239
4240
4241
4242
4243
4244
  	if (token == NULL)
  		return -EINVAL;
  	if (ipv6_addr_any(token))
  		return -EINVAL;
  	if (dev->flags & (IFF_LOOPBACK | IFF_NOARP))
  		return -EINVAL;
f53adae4e   Daniel Borkmann   net: ipv6: add to...
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
  	if (!ipv6_accept_ra(idev))
  		return -EINVAL;
  	if (idev->cnf.rtr_solicits <= 0)
  		return -EINVAL;
  
  	write_lock_bh(&idev->lock);
  
  	BUILD_BUG_ON(sizeof(token->s6_addr) != 16);
  	memcpy(idev->token.s6_addr + 8, token->s6_addr + 8, 8);
  
  	write_unlock_bh(&idev->lock);
dc8482926   Hannes Frederic Sowa   ipv6: check retur...
4256
4257
4258
  	if (!idev->dead && (idev->if_flags & IF_READY) &&
  	    !ipv6_get_lladdr(dev, &ll_addr, IFA_F_TENTATIVE |
  			     IFA_F_OPTIMISTIC)) {
fc403832f   Daniel Borkmann   net: ipv6: also a...
4259
4260
4261
4262
4263
4264
4265
  
  		/* If we're not ready, then normal ifup will take care
  		 * of this. Otherwise, we need to request our rs here.
  		 */
  		ndisc_send_rs(dev, &ll_addr, &in6addr_linklocal_allrouters);
  		update_rs = true;
  	}
f53adae4e   Daniel Borkmann   net: ipv6: add to...
4266
4267
  
  	write_lock_bh(&idev->lock);
fc403832f   Daniel Borkmann   net: ipv6: also a...
4268

77ecaace6   Hannes Frederic Sowa   ipv6: rearm route...
4269
  	if (update_rs) {
fc403832f   Daniel Borkmann   net: ipv6: also a...
4270
  		idev->if_flags |= IF_RS_SENT;
77ecaace6   Hannes Frederic Sowa   ipv6: rearm route...
4271
4272
4273
  		idev->rs_probes = 1;
  		addrconf_mod_rs_timer(idev, idev->cnf.rtr_solicit_interval);
  	}
f53adae4e   Daniel Borkmann   net: ipv6: add to...
4274
4275
4276
4277
  
  	/* Well, that's kinda nasty ... */
  	list_for_each_entry(ifp, &idev->addr_list, if_list) {
  		spin_lock(&ifp->lock);
617fe29d4   Daniel Borkmann   net: ipv6: only i...
4278
  		if (ifp->tokenized) {
f53adae4e   Daniel Borkmann   net: ipv6: add to...
4279
4280
4281
4282
4283
4284
4285
  			ifp->valid_lft = 0;
  			ifp->prefered_lft = 0;
  		}
  		spin_unlock(&ifp->lock);
  	}
  
  	write_unlock_bh(&idev->lock);
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
4286
  	addrconf_verify_rtnl();
f53adae4e   Daniel Borkmann   net: ipv6: add to...
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
  	return 0;
  }
  
  static int inet6_set_link_af(struct net_device *dev, const struct nlattr *nla)
  {
  	int err = -EINVAL;
  	struct inet6_dev *idev = __in6_dev_get(dev);
  	struct nlattr *tb[IFLA_INET6_MAX + 1];
  
  	if (!idev)
  		return -EAFNOSUPPORT;
  
  	if (nla_parse_nested(tb, IFLA_INET6_MAX, nla, NULL) < 0)
  		BUG();
  
  	if (tb[IFLA_INET6_TOKEN])
  		err = inet6_set_iftoken(idev, nla_data(tb[IFLA_INET6_TOKEN]));
  
  	return err;
  }
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
4307
  static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
15e473046   Eric W. Biederman   netlink: Rename p...
4308
  			     u32 portid, u32 seq, int event, unsigned int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4309
  {
04561c1fe   Thomas Graf   [IPv6] iflink: Co...
4310
  	struct net_device *dev = idev->dev;
04561c1fe   Thomas Graf   [IPv6] iflink: Co...
4311
4312
4313
  	struct ifinfomsg *hdr;
  	struct nlmsghdr *nlh;
  	void *protoinfo;
04561c1fe   Thomas Graf   [IPv6] iflink: Co...
4314

15e473046   Eric W. Biederman   netlink: Rename p...
4315
  	nlh = nlmsg_put(skb, portid, seq, event, sizeof(*hdr), flags);
04561c1fe   Thomas Graf   [IPv6] iflink: Co...
4316
  	if (nlh == NULL)
26932566a   Patrick McHardy   [NETLINK]: Don't ...
4317
  		return -EMSGSIZE;
04561c1fe   Thomas Graf   [IPv6] iflink: Co...
4318
4319
4320
4321
4322
4323
4324
4325
  
  	hdr = nlmsg_data(nlh);
  	hdr->ifi_family = AF_INET6;
  	hdr->__ifi_pad = 0;
  	hdr->ifi_type = dev->type;
  	hdr->ifi_index = dev->ifindex;
  	hdr->ifi_flags = dev_get_flags(dev);
  	hdr->ifi_change = 0;
c78679e8f   David S. Miller   ipv6: Stop using ...
4326
4327
4328
4329
4330
4331
4332
  	if (nla_put_string(skb, IFLA_IFNAME, dev->name) ||
  	    (dev->addr_len &&
  	     nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr)) ||
  	    nla_put_u32(skb, IFLA_MTU, dev->mtu) ||
  	    (dev->ifindex != dev->iflink &&
  	     nla_put_u32(skb, IFLA_LINK, dev->iflink)))
  		goto nla_put_failure;
04561c1fe   Thomas Graf   [IPv6] iflink: Co...
4333
4334
4335
  	protoinfo = nla_nest_start(skb, IFLA_PROTINFO);
  	if (protoinfo == NULL)
  		goto nla_put_failure;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4336

b382b191e   Thomas Graf   ipv6: AF_INET6 li...
4337
  	if (inet6_fill_ifla6_attrs(skb, idev) < 0)
bf99f1bde   YOSHIFUJI Hideaki   [IPV6] SNMP: Netl...
4338
  		goto nla_put_failure;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4339

04561c1fe   Thomas Graf   [IPv6] iflink: Co...
4340
4341
  	nla_nest_end(skb, protoinfo);
  	return nlmsg_end(skb, nlh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4342

04561c1fe   Thomas Graf   [IPv6] iflink: Co...
4343
  nla_put_failure:
26932566a   Patrick McHardy   [NETLINK]: Don't ...
4344
4345
  	nlmsg_cancel(skb, nlh);
  	return -EMSGSIZE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4346
4347
4348
4349
  }
  
  static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
  {
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
4350
  	struct net *net = sock_net(skb->sk);
84d2697d9   Eric Dumazet   ipv6: speedup ine...
4351
  	int h, s_h;
434a8a58d   David S. Miller   ipv6: Remove unus...
4352
  	int idx = 0, s_idx;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4353
4354
  	struct net_device *dev;
  	struct inet6_dev *idev;
84d2697d9   Eric Dumazet   ipv6: speedup ine...
4355
  	struct hlist_head *head;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4356

84d2697d9   Eric Dumazet   ipv6: speedup ine...
4357
4358
4359
4360
4361
4362
4363
  	s_h = cb->args[0];
  	s_idx = cb->args[1];
  
  	rcu_read_lock();
  	for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
  		idx = 0;
  		head = &net->dev_index_head[h];
b67bfe0d4   Sasha Levin   hlist: drop the n...
4364
  		hlist_for_each_entry_rcu(dev, head, index_hlist) {
84d2697d9   Eric Dumazet   ipv6: speedup ine...
4365
4366
4367
4368
4369
4370
  			if (idx < s_idx)
  				goto cont;
  			idev = __in6_dev_get(dev);
  			if (!idev)
  				goto cont;
  			if (inet6_fill_ifinfo(skb, idev,
15e473046   Eric W. Biederman   netlink: Rename p...
4371
  					      NETLINK_CB(cb->skb).portid,
84d2697d9   Eric Dumazet   ipv6: speedup ine...
4372
4373
4374
  					      cb->nlh->nlmsg_seq,
  					      RTM_NEWLINK, NLM_F_MULTI) <= 0)
  				goto out;
7562f876c   Pavel Emelianov   [NET]: Rework dev...
4375
  cont:
84d2697d9   Eric Dumazet   ipv6: speedup ine...
4376
4377
  			idx++;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4378
  	}
84d2697d9   Eric Dumazet   ipv6: speedup ine...
4379
4380
4381
4382
  out:
  	rcu_read_unlock();
  	cb->args[1] = idx;
  	cb->args[0] = h;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4383
4384
4385
4386
4387
4388
4389
  
  	return skb->len;
  }
  
  void inet6_ifinfo_notify(int event, struct inet6_dev *idev)
  {
  	struct sk_buff *skb;
c346dca10   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
4390
  	struct net *net = dev_net(idev->dev);
8d7a76c9b   Thomas Graf   [IPv6] link: Conv...
4391
  	int err = -ENOBUFS;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
4392

339bf98ff   Thomas Graf   [NETLINK]: Do pre...
4393
  	skb = nlmsg_new(inet6_if_nlmsg_size(), GFP_ATOMIC);
8d7a76c9b   Thomas Graf   [IPv6] link: Conv...
4394
4395
4396
4397
  	if (skb == NULL)
  		goto errout;
  
  	err = inet6_fill_ifinfo(skb, idev, 0, 0, event, 0);
26932566a   Patrick McHardy   [NETLINK]: Don't ...
4398
4399
4400
4401
4402
4403
  	if (err < 0) {
  		/* -EMSGSIZE implies BUG in inet6_if_nlmsg_size() */
  		WARN_ON(err == -EMSGSIZE);
  		kfree_skb(skb);
  		goto errout;
  	}
5f75a1042   Nicolas Dichtel   ipv6: fix nl grou...
4404
  	rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFINFO, NULL, GFP_ATOMIC);
1ce85fe40   Pablo Neira Ayuso   netlink: change n...
4405
  	return;
8d7a76c9b   Thomas Graf   [IPv6] link: Conv...
4406
4407
  errout:
  	if (err < 0)
5f75a1042   Nicolas Dichtel   ipv6: fix nl grou...
4408
  		rtnl_set_sk_err(net, RTNLGRP_IPV6_IFINFO, err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4409
  }
339bf98ff   Thomas Graf   [NETLINK]: Do pre...
4410
4411
4412
4413
4414
4415
  static inline size_t inet6_prefix_nlmsg_size(void)
  {
  	return NLMSG_ALIGN(sizeof(struct prefixmsg))
  	       + nla_total_size(sizeof(struct in6_addr))
  	       + nla_total_size(sizeof(struct prefix_cacheinfo));
  }
c5396a31b   YOSHIFUJI Hideaki   [IPV6]: Sum real ...
4416

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4417
  static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev,
15e473046   Eric W. Biederman   netlink: Rename p...
4418
  			     struct prefix_info *pinfo, u32 portid, u32 seq,
6051e2f4f   Thomas Graf   [IPv6] prefix: Co...
4419
  			     int event, unsigned int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4420
  {
6051e2f4f   Thomas Graf   [IPv6] prefix: Co...
4421
4422
  	struct prefixmsg *pmsg;
  	struct nlmsghdr *nlh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4423
  	struct prefix_cacheinfo	ci;
15e473046   Eric W. Biederman   netlink: Rename p...
4424
  	nlh = nlmsg_put(skb, portid, seq, event, sizeof(*pmsg), flags);
6051e2f4f   Thomas Graf   [IPv6] prefix: Co...
4425
  	if (nlh == NULL)
26932566a   Patrick McHardy   [NETLINK]: Don't ...
4426
  		return -EMSGSIZE;
6051e2f4f   Thomas Graf   [IPv6] prefix: Co...
4427
4428
  
  	pmsg = nlmsg_data(nlh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4429
  	pmsg->prefix_family = AF_INET6;
8a47077a0   Patrick McHardy   [NETLINK]: Missin...
4430
4431
  	pmsg->prefix_pad1 = 0;
  	pmsg->prefix_pad2 = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4432
4433
4434
  	pmsg->prefix_ifindex = idev->dev->ifindex;
  	pmsg->prefix_len = pinfo->prefix_len;
  	pmsg->prefix_type = pinfo->type;
8a47077a0   Patrick McHardy   [NETLINK]: Missin...
4435
  	pmsg->prefix_pad3 = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4436
4437
4438
4439
4440
  	pmsg->prefix_flags = 0;
  	if (pinfo->onlink)
  		pmsg->prefix_flags |= IF_PREFIX_ONLINK;
  	if (pinfo->autoconf)
  		pmsg->prefix_flags |= IF_PREFIX_AUTOCONF;
c78679e8f   David S. Miller   ipv6: Stop using ...
4441
4442
  	if (nla_put(skb, PREFIX_ADDRESS, sizeof(pinfo->prefix), &pinfo->prefix))
  		goto nla_put_failure;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4443
4444
  	ci.preferred_time = ntohl(pinfo->prefered);
  	ci.valid_time = ntohl(pinfo->valid);
c78679e8f   David S. Miller   ipv6: Stop using ...
4445
4446
  	if (nla_put(skb, PREFIX_CACHEINFO, sizeof(ci), &ci))
  		goto nla_put_failure;
6051e2f4f   Thomas Graf   [IPv6] prefix: Co...
4447
  	return nlmsg_end(skb, nlh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4448

6051e2f4f   Thomas Graf   [IPv6] prefix: Co...
4449
  nla_put_failure:
26932566a   Patrick McHardy   [NETLINK]: Don't ...
4450
4451
  	nlmsg_cancel(skb, nlh);
  	return -EMSGSIZE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4452
  }
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
4453
  static void inet6_prefix_notify(int event, struct inet6_dev *idev,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4454
4455
4456
  			 struct prefix_info *pinfo)
  {
  	struct sk_buff *skb;
c346dca10   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
4457
  	struct net *net = dev_net(idev->dev);
8c384bfa3   Thomas Graf   [IPv6] prefix: Co...
4458
  	int err = -ENOBUFS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4459

339bf98ff   Thomas Graf   [NETLINK]: Do pre...
4460
  	skb = nlmsg_new(inet6_prefix_nlmsg_size(), GFP_ATOMIC);
8c384bfa3   Thomas Graf   [IPv6] prefix: Co...
4461
4462
4463
4464
  	if (skb == NULL)
  		goto errout;
  
  	err = inet6_fill_prefix(skb, idev, pinfo, 0, 0, event, 0);
26932566a   Patrick McHardy   [NETLINK]: Don't ...
4465
4466
4467
4468
4469
4470
  	if (err < 0) {
  		/* -EMSGSIZE implies BUG in inet6_prefix_nlmsg_size() */
  		WARN_ON(err == -EMSGSIZE);
  		kfree_skb(skb);
  		goto errout;
  	}
1ce85fe40   Pablo Neira Ayuso   netlink: change n...
4471
4472
  	rtnl_notify(skb, net, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC);
  	return;
8c384bfa3   Thomas Graf   [IPv6] prefix: Co...
4473
4474
  errout:
  	if (err < 0)
6fda73500   Benjamin Thery   [NETNS][IPV6] add...
4475
  		rtnl_set_sk_err(net, RTNLGRP_IPV6_PREFIX, err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4476
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4477
4478
  static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
  {
63998ac24   Nicolas Dichtel   ipv6: provide add...
4479
  	struct net *net = dev_net(ifp->idev->dev);
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
4480
4481
  	if (event)
  		ASSERT_RTNL();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4482
4483
4484
4485
  	inet6_ifa_notify(event ? : RTM_NEWADDR, ifp);
  
  	switch (event) {
  	case RTM_NEWADDR:
95c385b4d   Neil Horman   [IPV6] ADDRCONF: ...
4486
4487
4488
4489
4490
4491
4492
4493
  		/*
  		 * If the address was optimistic
  		 * we inserted the route at the start of
  		 * our DAD process, so we don't need
  		 * to do it again
  		 */
  		if (!(ifp->rt->rt6i_node))
  			ip6_ins_rt(ifp->rt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4494
4495
  		if (ifp->idev->cnf.forwarding)
  			addrconf_join_anycast(ifp);
7996c799a   Cong Wang   ipv6: use ipv6_ad...
4496
  		if (!ipv6_addr_any(&ifp->peer_addr))
caeaba790   Nicolas Dichtel   ipv6: add support...
4497
4498
  			addrconf_prefix_route(&ifp->peer_addr, 128,
  					      ifp->idev->dev, 0, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4499
4500
4501
4502
4503
  		break;
  	case RTM_DELADDR:
  		if (ifp->idev->cnf.forwarding)
  			addrconf_leave_anycast(ifp);
  		addrconf_leave_solict(ifp->idev, &ifp->addr);
7996c799a   Cong Wang   ipv6: use ipv6_ad...
4504
  		if (!ipv6_addr_any(&ifp->peer_addr)) {
caeaba790   Nicolas Dichtel   ipv6: add support...
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
  			struct rt6_info *rt;
  			struct net_device *dev = ifp->idev->dev;
  
  			rt = rt6_lookup(dev_net(dev), &ifp->peer_addr, NULL,
  					dev->ifindex, 1);
  			if (rt) {
  				dst_hold(&rt->dst);
  				if (ip6_del_rt(rt))
  					dst_free(&rt->dst);
  			}
  		}
d8d1f30b9   Changli Gao   net-next: remove ...
4516
  		dst_hold(&ifp->rt->dst);
93fa159ab   stephen hemminger   IPv6: keep route ...
4517

73a8bd74e   David S. Miller   ipv6: Revert 'adm...
4518
  		if (ip6_del_rt(ifp->rt))
d8d1f30b9   Changli Gao   net-next: remove ...
4519
  			dst_free(&ifp->rt->dst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4520
4521
  		break;
  	}
63998ac24   Nicolas Dichtel   ipv6: provide add...
4522
  	atomic_inc(&net->ipv6.dev_addr_genid);
439677d76   fan.du   ipv6: bump genid ...
4523
  	rt_genid_bump_ipv6(net);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4524
4525
4526
4527
  }
  
  static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
  {
8814c4b53   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
4528
  	rcu_read_lock_bh();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4529
4530
  	if (likely(ifp->idev->dead == 0))
  		__ipv6_ifa_notify(event, ifp);
8814c4b53   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
4531
  	rcu_read_unlock_bh();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4532
4533
4534
4535
4536
  }
  
  #ifdef CONFIG_SYSCTL
  
  static
fe2c6338f   Joe Perches   net: Convert uses...
4537
  int addrconf_sysctl_forward(struct ctl_table *ctl, int write,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4538
4539
4540
4541
  			   void __user *buffer, size_t *lenp, loff_t *ppos)
  {
  	int *valp = ctl->data;
  	int val = *valp;
88af182e3   Eric W. Biederman   net: Fix sysctl r...
4542
  	loff_t pos = *ppos;
fe2c6338f   Joe Perches   net: Convert uses...
4543
  	struct ctl_table lctl;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4544
  	int ret;
013d97e9d   Francesco Ruggeri   net: race conditi...
4545
4546
4547
4548
4549
4550
4551
4552
  	/*
  	 * ctl->data points to idev->cnf.forwarding, we should
  	 * not modify it until we get the rtnl lock.
  	 */
  	lctl = *ctl;
  	lctl.data = &val;
  
  	ret = proc_dointvec(&lctl, write, buffer, lenp, ppos);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4553

c8fecf224   Pavel Emelyanov   [IPV6]: Eliminate...
4554
  	if (write)
b325fddb7   Stephen Hemminger   ipv6: Fix sysctl ...
4555
  		ret = addrconf_fixup_forwarding(ctl, valp, val);
88af182e3   Eric W. Biederman   net: Fix sysctl r...
4556
4557
  	if (ret)
  		*ppos = pos;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
4558
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4559
  }
56d417b12   Brian Haley   IPv6: Add 'autoco...
4560
4561
  static void dev_disable_change(struct inet6_dev *idev)
  {
75538c2b8   Cong Wang   net: always pass ...
4562
  	struct netdev_notifier_info info;
56d417b12   Brian Haley   IPv6: Add 'autoco...
4563
4564
  	if (!idev || !idev->dev)
  		return;
75538c2b8   Cong Wang   net: always pass ...
4565
  	netdev_notifier_info_init(&info, idev->dev);
56d417b12   Brian Haley   IPv6: Add 'autoco...
4566
  	if (idev->cnf.disable_ipv6)
75538c2b8   Cong Wang   net: always pass ...
4567
  		addrconf_notify(NULL, NETDEV_DOWN, &info);
56d417b12   Brian Haley   IPv6: Add 'autoco...
4568
  	else
75538c2b8   Cong Wang   net: always pass ...
4569
  		addrconf_notify(NULL, NETDEV_UP, &info);
56d417b12   Brian Haley   IPv6: Add 'autoco...
4570
4571
4572
4573
4574
4575
  }
  
  static void addrconf_disable_change(struct net *net, __s32 newf)
  {
  	struct net_device *dev;
  	struct inet6_dev *idev;
c6d14c845   Eric Dumazet   net: Introduce fo...
4576
4577
  	rcu_read_lock();
  	for_each_netdev_rcu(net, dev) {
56d417b12   Brian Haley   IPv6: Add 'autoco...
4578
4579
4580
4581
4582
4583
4584
  		idev = __in6_dev_get(dev);
  		if (idev) {
  			int changed = (!idev->cnf.disable_ipv6) ^ (!newf);
  			idev->cnf.disable_ipv6 = newf;
  			if (changed)
  				dev_disable_change(idev);
  		}
56d417b12   Brian Haley   IPv6: Add 'autoco...
4585
  	}
c6d14c845   Eric Dumazet   net: Introduce fo...
4586
  	rcu_read_unlock();
56d417b12   Brian Haley   IPv6: Add 'autoco...
4587
  }
013d97e9d   Francesco Ruggeri   net: race conditi...
4588
  static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int newf)
56d417b12   Brian Haley   IPv6: Add 'autoco...
4589
4590
  {
  	struct net *net;
013d97e9d   Francesco Ruggeri   net: race conditi...
4591
4592
4593
4594
  	int old;
  
  	if (!rtnl_trylock())
  		return restart_syscall();
56d417b12   Brian Haley   IPv6: Add 'autoco...
4595
4596
  
  	net = (struct net *)table->extra2;
013d97e9d   Francesco Ruggeri   net: race conditi...
4597
4598
  	old = *p;
  	*p = newf;
56d417b12   Brian Haley   IPv6: Add 'autoco...
4599

013d97e9d   Francesco Ruggeri   net: race conditi...
4600
4601
  	if (p == &net->ipv6.devconf_dflt->disable_ipv6) {
  		rtnl_unlock();
56d417b12   Brian Haley   IPv6: Add 'autoco...
4602
  		return 0;
88af182e3   Eric W. Biederman   net: Fix sysctl r...
4603
  	}
56d417b12   Brian Haley   IPv6: Add 'autoco...
4604
4605
  
  	if (p == &net->ipv6.devconf_all->disable_ipv6) {
56d417b12   Brian Haley   IPv6: Add 'autoco...
4606
4607
  		net->ipv6.devconf_dflt->disable_ipv6 = newf;
  		addrconf_disable_change(net, newf);
013d97e9d   Francesco Ruggeri   net: race conditi...
4608
  	} else if ((!newf) ^ (!old))
56d417b12   Brian Haley   IPv6: Add 'autoco...
4609
4610
4611
4612
4613
4614
4615
  		dev_disable_change((struct inet6_dev *)table->extra1);
  
  	rtnl_unlock();
  	return 0;
  }
  
  static
fe2c6338f   Joe Perches   net: Convert uses...
4616
  int addrconf_sysctl_disable(struct ctl_table *ctl, int write,
56d417b12   Brian Haley   IPv6: Add 'autoco...
4617
4618
4619
4620
  			    void __user *buffer, size_t *lenp, loff_t *ppos)
  {
  	int *valp = ctl->data;
  	int val = *valp;
88af182e3   Eric W. Biederman   net: Fix sysctl r...
4621
  	loff_t pos = *ppos;
fe2c6338f   Joe Perches   net: Convert uses...
4622
  	struct ctl_table lctl;
56d417b12   Brian Haley   IPv6: Add 'autoco...
4623
  	int ret;
013d97e9d   Francesco Ruggeri   net: race conditi...
4624
4625
4626
4627
4628
4629
4630
4631
  	/*
  	 * ctl->data points to idev->cnf.disable_ipv6, we should
  	 * not modify it until we get the rtnl lock.
  	 */
  	lctl = *ctl;
  	lctl.data = &val;
  
  	ret = proc_dointvec(&lctl, write, buffer, lenp, ppos);
56d417b12   Brian Haley   IPv6: Add 'autoco...
4632
4633
4634
  
  	if (write)
  		ret = addrconf_disable_ipv6(ctl, valp, val);
88af182e3   Eric W. Biederman   net: Fix sysctl r...
4635
4636
  	if (ret)
  		*ppos = pos;
56d417b12   Brian Haley   IPv6: Add 'autoco...
4637
4638
  	return ret;
  }
c92d5491a   stephen hemminger   netconf: add supp...
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
  static
  int addrconf_sysctl_proxy_ndp(struct ctl_table *ctl, int write,
  			      void __user *buffer, size_t *lenp, loff_t *ppos)
  {
  	int *valp = ctl->data;
  	int ret;
  	int old, new;
  
  	old = *valp;
  	ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
  	new = *valp;
  
  	if (write && old != new) {
  		struct net *net = ctl->extra2;
  
  		if (!rtnl_trylock())
  			return restart_syscall();
  
  		if (valp == &net->ipv6.devconf_dflt->proxy_ndp)
  			inet6_netconf_notify_devconf(net, NETCONFA_PROXY_NEIGH,
  						     NETCONFA_IFINDEX_DEFAULT,
  						     net->ipv6.devconf_dflt);
  		else if (valp == &net->ipv6.devconf_all->proxy_ndp)
  			inet6_netconf_notify_devconf(net, NETCONFA_PROXY_NEIGH,
  						     NETCONFA_IFINDEX_ALL,
  						     net->ipv6.devconf_all);
  		else {
  			struct inet6_dev *idev = ctl->extra1;
  
  			inet6_netconf_notify_devconf(net, NETCONFA_PROXY_NEIGH,
  						     idev->dev->ifindex,
  						     &idev->cnf);
  		}
  		rtnl_unlock();
  	}
  
  	return ret;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4677
4678
4679
  static struct addrconf_sysctl_table
  {
  	struct ctl_table_header *sysctl_header;
fe2c6338f   Joe Perches   net: Convert uses...
4680
  	struct ctl_table addrconf_vars[DEVCONF_MAX+1];
ab32ea5d8   Brian Haley   [NET/IPV4/IPV6]: ...
4681
  } addrconf_sysctl __read_mostly = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4682
4683
  	.sysctl_header = NULL,
  	.addrconf_vars = {
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
4684
  		{
e21e8467d   Stephen Hemminger   addrconf: checkpa...
4685
4686
4687
4688
4689
  			.procname	= "forwarding",
  			.data		= &ipv6_devconf.forwarding,
  			.maxlen		= sizeof(int),
  			.mode		= 0644,
  			.proc_handler	= addrconf_sysctl_forward,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4690
4691
  		},
  		{
e21e8467d   Stephen Hemminger   addrconf: checkpa...
4692
4693
4694
4695
4696
  			.procname	= "hop_limit",
  			.data		= &ipv6_devconf.hop_limit,
  			.maxlen		= sizeof(int),
  			.mode		= 0644,
  			.proc_handler	= proc_dointvec,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4697
4698
  		},
  		{
e21e8467d   Stephen Hemminger   addrconf: checkpa...
4699
4700
4701
4702
4703
  			.procname	= "mtu",
  			.data		= &ipv6_devconf.mtu6,
  			.maxlen		= sizeof(int),
  			.mode		= 0644,
  			.proc_handler	= proc_dointvec,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4704
4705
  		},
  		{
e21e8467d   Stephen Hemminger   addrconf: checkpa...
4706
4707
4708
4709
4710
  			.procname	= "accept_ra",
  			.data		= &ipv6_devconf.accept_ra,
  			.maxlen		= sizeof(int),
  			.mode		= 0644,
  			.proc_handler	= proc_dointvec,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4711
4712
  		},
  		{
e21e8467d   Stephen Hemminger   addrconf: checkpa...
4713
4714
4715
4716
4717
  			.procname	= "accept_redirects",
  			.data		= &ipv6_devconf.accept_redirects,
  			.maxlen		= sizeof(int),
  			.mode		= 0644,
  			.proc_handler	= proc_dointvec,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4718
4719
  		},
  		{
e21e8467d   Stephen Hemminger   addrconf: checkpa...
4720
4721
4722
4723
4724
  			.procname	= "autoconf",
  			.data		= &ipv6_devconf.autoconf,
  			.maxlen		= sizeof(int),
  			.mode		= 0644,
  			.proc_handler	= proc_dointvec,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4725
4726
  		},
  		{
e21e8467d   Stephen Hemminger   addrconf: checkpa...
4727
4728
4729
4730
4731
  			.procname	= "dad_transmits",
  			.data		= &ipv6_devconf.dad_transmits,
  			.maxlen		= sizeof(int),
  			.mode		= 0644,
  			.proc_handler	= proc_dointvec,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4732
4733
  		},
  		{
e21e8467d   Stephen Hemminger   addrconf: checkpa...
4734
4735
4736
4737
4738
  			.procname	= "router_solicitations",
  			.data		= &ipv6_devconf.rtr_solicits,
  			.maxlen		= sizeof(int),
  			.mode		= 0644,
  			.proc_handler	= proc_dointvec,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4739
4740
  		},
  		{
e21e8467d   Stephen Hemminger   addrconf: checkpa...
4741
4742
4743
4744
4745
  			.procname	= "router_solicitation_interval",
  			.data		= &ipv6_devconf.rtr_solicit_interval,
  			.maxlen		= sizeof(int),
  			.mode		= 0644,
  			.proc_handler	= proc_dointvec_jiffies,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4746
4747
  		},
  		{
e21e8467d   Stephen Hemminger   addrconf: checkpa...
4748
4749
4750
4751
4752
  			.procname	= "router_solicitation_delay",
  			.data		= &ipv6_devconf.rtr_solicit_delay,
  			.maxlen		= sizeof(int),
  			.mode		= 0644,
  			.proc_handler	= proc_dointvec_jiffies,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4753
4754
  		},
  		{
e21e8467d   Stephen Hemminger   addrconf: checkpa...
4755
4756
4757
4758
4759
  			.procname	= "force_mld_version",
  			.data		= &ipv6_devconf.force_mld_version,
  			.maxlen		= sizeof(int),
  			.mode		= 0644,
  			.proc_handler	= proc_dointvec,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4760
  		},
fc4eba58b   Hannes Frederic Sowa   ipv6: make unsoli...
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
  		{
  			.procname	= "mldv1_unsolicited_report_interval",
  			.data		=
  				&ipv6_devconf.mldv1_unsolicited_report_interval,
  			.maxlen		= sizeof(int),
  			.mode		= 0644,
  			.proc_handler	= proc_dointvec_ms_jiffies,
  		},
  		{
  			.procname	= "mldv2_unsolicited_report_interval",
  			.data		=
  				&ipv6_devconf.mldv2_unsolicited_report_interval,
  			.maxlen		= sizeof(int),
  			.mode		= 0644,
  			.proc_handler	= proc_dointvec_ms_jiffies,
  		},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4777
  		{
e21e8467d   Stephen Hemminger   addrconf: checkpa...
4778
4779
4780
4781
4782
  			.procname	= "use_tempaddr",
  			.data		= &ipv6_devconf.use_tempaddr,
  			.maxlen		= sizeof(int),
  			.mode		= 0644,
  			.proc_handler	= proc_dointvec,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4783
4784
  		},
  		{
e21e8467d   Stephen Hemminger   addrconf: checkpa...
4785
4786
4787
4788
4789
  			.procname	= "temp_valid_lft",
  			.data		= &ipv6_devconf.temp_valid_lft,
  			.maxlen		= sizeof(int),
  			.mode		= 0644,
  			.proc_handler	= proc_dointvec,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4790
4791
  		},
  		{
e21e8467d   Stephen Hemminger   addrconf: checkpa...
4792
4793
4794
4795
4796
  			.procname	= "temp_prefered_lft",
  			.data		= &ipv6_devconf.temp_prefered_lft,
  			.maxlen		= sizeof(int),
  			.mode		= 0644,
  			.proc_handler	= proc_dointvec,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4797
4798
  		},
  		{
e21e8467d   Stephen Hemminger   addrconf: checkpa...
4799
4800
4801
4802
4803
  			.procname	= "regen_max_retry",
  			.data		= &ipv6_devconf.regen_max_retry,
  			.maxlen		= sizeof(int),
  			.mode		= 0644,
  			.proc_handler	= proc_dointvec,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4804
4805
  		},
  		{
e21e8467d   Stephen Hemminger   addrconf: checkpa...
4806
4807
4808
4809
4810
  			.procname	= "max_desync_factor",
  			.data		= &ipv6_devconf.max_desync_factor,
  			.maxlen		= sizeof(int),
  			.mode		= 0644,
  			.proc_handler	= proc_dointvec,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4811
  		},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4812
  		{
e21e8467d   Stephen Hemminger   addrconf: checkpa...
4813
4814
4815
4816
4817
  			.procname	= "max_addresses",
  			.data		= &ipv6_devconf.max_addresses,
  			.maxlen		= sizeof(int),
  			.mode		= 0644,
  			.proc_handler	= proc_dointvec,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4818
4819
  		},
  		{
e21e8467d   Stephen Hemminger   addrconf: checkpa...
4820
4821
4822
4823
4824
  			.procname	= "accept_ra_defrtr",
  			.data		= &ipv6_devconf.accept_ra_defrtr,
  			.maxlen		= sizeof(int),
  			.mode		= 0644,
  			.proc_handler	= proc_dointvec,
65f5c7c11   YOSHIFUJI Hideaki   [IPV6]: ROUTE: Ad...
4825
4826
  		},
  		{
e21e8467d   Stephen Hemminger   addrconf: checkpa...
4827
4828
4829
4830
4831
  			.procname	= "accept_ra_pinfo",
  			.data		= &ipv6_devconf.accept_ra_pinfo,
  			.maxlen		= sizeof(int),
  			.mode		= 0644,
  			.proc_handler	= proc_dointvec,
c4fd30eb1   YOSHIFUJI Hideaki   [IPV6]: ADDRCONF:...
4832
  		},
930d6ff2e   YOSHIFUJI Hideaki   [IPV6]: ROUTE: Ad...
4833
4834
  #ifdef CONFIG_IPV6_ROUTER_PREF
  		{
e21e8467d   Stephen Hemminger   addrconf: checkpa...
4835
4836
4837
4838
4839
  			.procname	= "accept_ra_rtr_pref",
  			.data		= &ipv6_devconf.accept_ra_rtr_pref,
  			.maxlen		= sizeof(int),
  			.mode		= 0644,
  			.proc_handler	= proc_dointvec,
930d6ff2e   YOSHIFUJI Hideaki   [IPV6]: ROUTE: Ad...
4840
  		},
52e163563   YOSHIFUJI Hideaki   [IPV6]: ROUTE: Ad...
4841
  		{
e21e8467d   Stephen Hemminger   addrconf: checkpa...
4842
4843
4844
4845
4846
  			.procname	= "router_probe_interval",
  			.data		= &ipv6_devconf.rtr_probe_interval,
  			.maxlen		= sizeof(int),
  			.mode		= 0644,
  			.proc_handler	= proc_dointvec_jiffies,
52e163563   YOSHIFUJI Hideaki   [IPV6]: ROUTE: Ad...
4847
  		},
fa03ef38e   Neil Horman   [IPV6]: Fix up so...
4848
  #ifdef CONFIG_IPV6_ROUTE_INFO
09c884d4c   YOSHIFUJI Hideaki   [IPV6]: ROUTE: Ad...
4849
  		{
e21e8467d   Stephen Hemminger   addrconf: checkpa...
4850
4851
4852
4853
4854
  			.procname	= "accept_ra_rt_info_max_plen",
  			.data		= &ipv6_devconf.accept_ra_rt_info_max_plen,
  			.maxlen		= sizeof(int),
  			.mode		= 0644,
  			.proc_handler	= proc_dointvec,
09c884d4c   YOSHIFUJI Hideaki   [IPV6]: ROUTE: Ad...
4855
4856
  		},
  #endif
930d6ff2e   YOSHIFUJI Hideaki   [IPV6]: ROUTE: Ad...
4857
  #endif
c4fd30eb1   YOSHIFUJI Hideaki   [IPV6]: ADDRCONF:...
4858
  		{
e21e8467d   Stephen Hemminger   addrconf: checkpa...
4859
4860
4861
4862
  			.procname	= "proxy_ndp",
  			.data		= &ipv6_devconf.proxy_ndp,
  			.maxlen		= sizeof(int),
  			.mode		= 0644,
c92d5491a   stephen hemminger   netconf: add supp...
4863
  			.proc_handler	= addrconf_sysctl_proxy_ndp,
fbea49e1e   YOSHIFUJI Hideaki   [IPV6] NDISC: Add...
4864
4865
  		},
  		{
e21e8467d   Stephen Hemminger   addrconf: checkpa...
4866
4867
4868
4869
4870
  			.procname	= "accept_source_route",
  			.data		= &ipv6_devconf.accept_source_route,
  			.maxlen		= sizeof(int),
  			.mode		= 0644,
  			.proc_handler	= proc_dointvec,
0bcbc9262   YOSHIFUJI Hideaki   [IPV6]: Disallow ...
4871
  		},
95c385b4d   Neil Horman   [IPV6] ADDRCONF: ...
4872
4873
  #ifdef CONFIG_IPV6_OPTIMISTIC_DAD
  		{
e21e8467d   Stephen Hemminger   addrconf: checkpa...
4874
4875
4876
4877
4878
  			.procname       = "optimistic_dad",
  			.data           = &ipv6_devconf.optimistic_dad,
  			.maxlen         = sizeof(int),
  			.mode           = 0644,
  			.proc_handler   = proc_dointvec,
95c385b4d   Neil Horman   [IPV6] ADDRCONF: ...
4879
4880
4881
  
  		},
  #endif
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
4882
4883
  #ifdef CONFIG_IPV6_MROUTE
  		{
e21e8467d   Stephen Hemminger   addrconf: checkpa...
4884
4885
4886
4887
4888
  			.procname	= "mc_forwarding",
  			.data		= &ipv6_devconf.mc_forwarding,
  			.maxlen		= sizeof(int),
  			.mode		= 0444,
  			.proc_handler	= proc_dointvec,
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
4889
4890
  		},
  #endif
0bcbc9262   YOSHIFUJI Hideaki   [IPV6]: Disallow ...
4891
  		{
e21e8467d   Stephen Hemminger   addrconf: checkpa...
4892
4893
4894
4895
4896
  			.procname	= "disable_ipv6",
  			.data		= &ipv6_devconf.disable_ipv6,
  			.maxlen		= sizeof(int),
  			.mode		= 0644,
  			.proc_handler	= addrconf_sysctl_disable,
778d80be5   YOSHIFUJI Hideaki   ipv6: Add disable...
4897
4898
  		},
  		{
e21e8467d   Stephen Hemminger   addrconf: checkpa...
4899
4900
4901
4902
4903
  			.procname	= "accept_dad",
  			.data		= &ipv6_devconf.accept_dad,
  			.maxlen		= sizeof(int),
  			.mode		= 0644,
  			.proc_handler	= proc_dointvec,
1b34be74c   YOSHIFUJI Hideaki   ipv6 addrconf: ad...
4904
4905
  		},
  		{
f7734fdf6   Octavian Purdila   make TLLAO option...
4906
4907
4908
4909
4910
4911
4912
  			.procname       = "force_tllao",
  			.data           = &ipv6_devconf.force_tllao,
  			.maxlen         = sizeof(int),
  			.mode           = 0644,
  			.proc_handler   = proc_dointvec
  		},
  		{
5cb04436e   Hannes Frederic Sowa   ipv6: add knob to...
4913
4914
4915
4916
4917
4918
4919
  			.procname       = "ndisc_notify",
  			.data           = &ipv6_devconf.ndisc_notify,
  			.maxlen         = sizeof(int),
  			.mode           = 0644,
  			.proc_handler   = proc_dointvec
  		},
  		{
b800c3b96   Hannes Frederic Sowa   ipv6: drop fragme...
4920
4921
4922
4923
4924
4925
4926
  			.procname	= "suppress_frag_ndisc",
  			.data		= &ipv6_devconf.suppress_frag_ndisc,
  			.maxlen		= sizeof(int),
  			.mode		= 0644,
  			.proc_handler	= proc_dointvec
  		},
  		{
f8572d8f2   Eric W. Biederman   sysctl net: Remov...
4927
  			/* sentinel */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4928
4929
  		}
  	},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4930
  };
bff16c2f9   Pavel Emelyanov   [NETNS]: Make the...
4931
  static int __addrconf_sysctl_register(struct net *net, char *dev_name,
f8572d8f2   Eric W. Biederman   sysctl net: Remov...
4932
  		struct inet6_dev *idev, struct ipv6_devconf *p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4933
4934
  {
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4935
  	struct addrconf_sysctl_table *t;
6105e2932   Eric W. Biederman   net ipv6: Convert...
4936
  	char path[sizeof("net/ipv6/conf/") + IFNAMSIZ];
1dab62226   Pavel Emelyanov   [IPV6]: Use ctl p...
4937

af879cc70   Arnaldo Carvalho de Melo   [IPV6]: Use kmemdup
4938
  	t = kmemdup(&addrconf_sysctl, sizeof(*t), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4939
  	if (t == NULL)
f68635e62   Pavel Emelyanov   [IPV6]: Cleanup t...
4940
  		goto out;
bcdd553fd   Stephen Hemminger   IPv6: addrconf cl...
4941
  	for (i = 0; t->addrconf_vars[i].data; i++) {
e21e8467d   Stephen Hemminger   addrconf: checkpa...
4942
  		t->addrconf_vars[i].data += (char *)p - (char *)&ipv6_devconf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4943
  		t->addrconf_vars[i].extra1 = idev; /* embedded; no ref */
bff16c2f9   Pavel Emelyanov   [NETNS]: Make the...
4944
  		t->addrconf_vars[i].extra2 = net;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4945
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4946

6105e2932   Eric W. Biederman   net ipv6: Convert...
4947
  	snprintf(path, sizeof(path), "net/ipv6/conf/%s", dev_name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4948

6105e2932   Eric W. Biederman   net ipv6: Convert...
4949
  	t->sysctl_header = register_net_sysctl(net, path, t->addrconf_vars);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4950
  	if (t->sysctl_header == NULL)
6105e2932   Eric W. Biederman   net ipv6: Convert...
4951
  		goto free;
f68635e62   Pavel Emelyanov   [IPV6]: Cleanup t...
4952
4953
  
  	p->sysctl = t;
958973122   Pavel Emelyanov   [NETNS]: Make the...
4954
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4955

f68635e62   Pavel Emelyanov   [IPV6]: Cleanup t...
4956
  free:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4957
  	kfree(t);
f68635e62   Pavel Emelyanov   [IPV6]: Cleanup t...
4958
  out:
958973122   Pavel Emelyanov   [NETNS]: Make the...
4959
  	return -ENOBUFS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4960
  }
408c4768c   Pavel Emelyanov   [NETNS]: Clean ou...
4961
4962
4963
4964
4965
4966
4967
4968
4969
  static void __addrconf_sysctl_unregister(struct ipv6_devconf *p)
  {
  	struct addrconf_sysctl_table *t;
  
  	if (p->sysctl == NULL)
  		return;
  
  	t = p->sysctl;
  	p->sysctl = NULL;
ff538818f   Lucian Adrian Grijincu   sysctl: net: call...
4970
  	unregister_net_sysctl_table(t->sysctl_header);
408c4768c   Pavel Emelyanov   [NETNS]: Clean ou...
4971
4972
  	kfree(t);
  }
f52295a9c   Pavel Emelyanov   [IPV6]: Unify and...
4973
4974
  static void addrconf_sysctl_register(struct inet6_dev *idev)
  {
73af614ae   Jiri Pirko   neigh: use tbl->f...
4975
  	neigh_sysctl_register(idev->dev, idev->nd_parms,
f8572d8f2   Eric W. Biederman   sysctl net: Remov...
4976
  			      &ndisc_ifinfo_sysctl_change);
c346dca10   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
4977
  	__addrconf_sysctl_register(dev_net(idev->dev), idev->dev->name,
f8572d8f2   Eric W. Biederman   sysctl net: Remov...
4978
  					idev, &idev->cnf);
f52295a9c   Pavel Emelyanov   [IPV6]: Unify and...
4979
  }
408c4768c   Pavel Emelyanov   [NETNS]: Clean ou...
4980
  static void addrconf_sysctl_unregister(struct inet6_dev *idev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4981
  {
408c4768c   Pavel Emelyanov   [NETNS]: Clean ou...
4982
4983
  	__addrconf_sysctl_unregister(&idev->cnf);
  	neigh_sysctl_unregister(idev->nd_parms);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4984
4985
4986
4987
  }
  
  
  #endif
2c8c1e729   Alexey Dobriyan   net: spread __net...
4988
  static int __net_init addrconf_init_net(struct net *net)
e0da5a480   Pavel Emelyanov   [NETNS]: Create i...
4989
  {
a79ca223e   Hong Zhiguo   ipv6: fix bad fre...
4990
  	int err = -ENOMEM;
e0da5a480   Pavel Emelyanov   [NETNS]: Create i...
4991
  	struct ipv6_devconf *all, *dflt;
a79ca223e   Hong Zhiguo   ipv6: fix bad fre...
4992
4993
4994
  	all = kmemdup(&ipv6_devconf, sizeof(ipv6_devconf), GFP_KERNEL);
  	if (all == NULL)
  		goto err_alloc_all;
e0da5a480   Pavel Emelyanov   [NETNS]: Create i...
4995

a79ca223e   Hong Zhiguo   ipv6: fix bad fre...
4996
4997
4998
  	dflt = kmemdup(&ipv6_devconf_dflt, sizeof(ipv6_devconf_dflt), GFP_KERNEL);
  	if (dflt == NULL)
  		goto err_alloc_dflt;
e0da5a480   Pavel Emelyanov   [NETNS]: Create i...
4999

a79ca223e   Hong Zhiguo   ipv6: fix bad fre...
5000
5001
5002
  	/* these will be inherited by all namespaces */
  	dflt->autoconf = ipv6_defaults.autoconf;
  	dflt->disable_ipv6 = ipv6_defaults.disable_ipv6;
e0da5a480   Pavel Emelyanov   [NETNS]: Create i...
5003
5004
5005
5006
5007
  
  	net->ipv6.devconf_all = all;
  	net->ipv6.devconf_dflt = dflt;
  
  #ifdef CONFIG_SYSCTL
f8572d8f2   Eric W. Biederman   sysctl net: Remov...
5008
  	err = __addrconf_sysctl_register(net, "all", NULL, all);
e0da5a480   Pavel Emelyanov   [NETNS]: Create i...
5009
5010
  	if (err < 0)
  		goto err_reg_all;
f8572d8f2   Eric W. Biederman   sysctl net: Remov...
5011
  	err = __addrconf_sysctl_register(net, "default", NULL, dflt);
e0da5a480   Pavel Emelyanov   [NETNS]: Create i...
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
  	if (err < 0)
  		goto err_reg_dflt;
  #endif
  	return 0;
  
  #ifdef CONFIG_SYSCTL
  err_reg_dflt:
  	__addrconf_sysctl_unregister(all);
  err_reg_all:
  	kfree(dflt);
  #endif
  err_alloc_dflt:
  	kfree(all);
  err_alloc_all:
  	return err;
  }
2c8c1e729   Alexey Dobriyan   net: spread __net...
5028
  static void __net_exit addrconf_exit_net(struct net *net)
e0da5a480   Pavel Emelyanov   [NETNS]: Create i...
5029
5030
5031
5032
5033
  {
  #ifdef CONFIG_SYSCTL
  	__addrconf_sysctl_unregister(net->ipv6.devconf_dflt);
  	__addrconf_sysctl_unregister(net->ipv6.devconf_all);
  #endif
09ad9bc75   Octavian Purdila   net: use net_eq t...
5034
  	if (!net_eq(net, &init_net)) {
e0da5a480   Pavel Emelyanov   [NETNS]: Create i...
5035
5036
5037
5038
5039
5040
5041
5042
5043
  		kfree(net->ipv6.devconf_dflt);
  		kfree(net->ipv6.devconf_all);
  	}
  }
  
  static struct pernet_operations addrconf_ops = {
  	.init = addrconf_init_net,
  	.exit = addrconf_exit_net,
  };
b382b191e   Thomas Graf   ipv6: AF_INET6 li...
5044
5045
5046
5047
  static struct rtnl_af_ops inet6_ops = {
  	.family		  = AF_INET6,
  	.fill_link_af	  = inet6_fill_link_af,
  	.get_link_af_size = inet6_get_link_af_size,
f53adae4e   Daniel Borkmann   net: ipv6: add to...
5048
  	.set_link_af	  = inet6_set_link_af,
b382b191e   Thomas Graf   ipv6: AF_INET6 li...
5049
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5050
5051
5052
5053
5054
5055
  /*
   *	Init / cleanup code
   */
  
  int __init addrconf_init(void)
  {
c2e21293c   stephen hemminger   ipv6: convert add...
5056
  	int i, err;
2a8cc6c89   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
5057

e21e8467d   Stephen Hemminger   addrconf: checkpa...
5058
5059
  	err = ipv6_addr_label_init();
  	if (err < 0) {
f32138319   Joe Perches   net: ipv6: Standa...
5060
5061
5062
  		pr_crit("%s: cannot initialize default policy table: %d
  ",
  			__func__, err);
2cc6d2bf3   Neil Horman   ipv6: add a missi...
5063
  		goto out;
2a8cc6c89   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
5064
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5065

2cc6d2bf3   Neil Horman   ipv6: add a missi...
5066
5067
5068
  	err = register_pernet_subsys(&addrconf_ops);
  	if (err < 0)
  		goto out_addrlabel;
e0da5a480   Pavel Emelyanov   [NETNS]: Create i...
5069

c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
5070
5071
5072
5073
5074
  	addrconf_wq = create_workqueue("ipv6_addrconf");
  	if (!addrconf_wq) {
  		err = -ENOMEM;
  		goto out_nowq;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
  	/* The addrconf netdev notifier requires that loopback_dev
  	 * has it's ipv6 private information allocated and setup
  	 * before it can bring up and give link-local addresses
  	 * to other devices which are up.
  	 *
  	 * Unfortunately, loopback_dev is not necessarily the first
  	 * entry in the global dev_base list of net devices.  In fact,
  	 * it is likely to be the very last entry on that list.
  	 * So this causes the notifier registry below to try and
  	 * give link-local addresses to all devices besides loopback_dev
  	 * first, then loopback_dev, which cases all the non-loopback_dev
  	 * devices to fail to get a link-local address.
  	 *
  	 * So, as a temporary fix, allocate the ipv6 structure for
  	 * loopback_dev first by hand.
  	 * Longer term, all of the dependencies ipv6 has upon the loopback
  	 * device and it being up should be removed.
  	 */
  	rtnl_lock();
2774c7aba   Eric W. Biederman   [NET]: Make the l...
5094
  	if (!ipv6_add_dev(init_net.loopback_dev))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5095
5096
5097
  		err = -ENOMEM;
  	rtnl_unlock();
  	if (err)
e0da5a480   Pavel Emelyanov   [NETNS]: Create i...
5098
  		goto errlo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5099

c2e21293c   stephen hemminger   ipv6: convert add...
5100
5101
  	for (i = 0; i < IN6_ADDR_HSIZE; i++)
  		INIT_HLIST_HEAD(&inet6_addr_lst[i]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5102
  	register_netdevice_notifier(&ipv6_dev_notf);
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
5103
  	addrconf_verify();
c127ea2c4   Thomas Graf   [IPv6]: Use rtnl ...
5104

3678a9d86   stephen hemminger   netlink: cleanup ...
5105
  	rtnl_af_register(&inet6_ops);
b382b191e   Thomas Graf   ipv6: AF_INET6 li...
5106

c7ac8679b   Greg Rose   rtnetlink: Comput...
5107
5108
  	err = __rtnl_register(PF_INET6, RTM_GETLINK, NULL, inet6_dump_ifinfo,
  			      NULL);
c127ea2c4   Thomas Graf   [IPv6]: Use rtnl ...
5109
5110
5111
5112
  	if (err < 0)
  		goto errout;
  
  	/* Only the first call to __rtnl_register can fail */
c7ac8679b   Greg Rose   rtnetlink: Comput...
5113
5114
5115
5116
5117
5118
5119
5120
  	__rtnl_register(PF_INET6, RTM_NEWADDR, inet6_rtm_newaddr, NULL, NULL);
  	__rtnl_register(PF_INET6, RTM_DELADDR, inet6_rtm_deladdr, NULL, NULL);
  	__rtnl_register(PF_INET6, RTM_GETADDR, inet6_rtm_getaddr,
  			inet6_dump_ifaddr, NULL);
  	__rtnl_register(PF_INET6, RTM_GETMULTICAST, NULL,
  			inet6_dump_ifmcaddr, NULL);
  	__rtnl_register(PF_INET6, RTM_GETANYCAST, NULL,
  			inet6_dump_ifacaddr, NULL);
76f8f6cb7   Nicolas Dichtel   rtnl/ipv6: add su...
5121
  	__rtnl_register(PF_INET6, RTM_GETNETCONF, inet6_netconf_get_devconf,
7a6742003   Nicolas Dichtel   netconf: add the ...
5122
  			inet6_netconf_dump_devconf, NULL);
c127ea2c4   Thomas Graf   [IPv6]: Use rtnl ...
5123

2a8cc6c89   YOSHIFUJI Hideaki   [IPV6] ADDRCONF: ...
5124
  	ipv6_addr_label_rtnl_register();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5125
  	return 0;
c127ea2c4   Thomas Graf   [IPv6]: Use rtnl ...
5126
  errout:
b382b191e   Thomas Graf   ipv6: AF_INET6 li...
5127
  	rtnl_af_unregister(&inet6_ops);
c127ea2c4   Thomas Graf   [IPv6]: Use rtnl ...
5128
  	unregister_netdevice_notifier(&ipv6_dev_notf);
e0da5a480   Pavel Emelyanov   [NETNS]: Create i...
5129
  errlo:
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
5130
5131
  	destroy_workqueue(addrconf_wq);
  out_nowq:
e0da5a480   Pavel Emelyanov   [NETNS]: Create i...
5132
  	unregister_pernet_subsys(&addrconf_ops);
2cc6d2bf3   Neil Horman   ipv6: add a missi...
5133
5134
5135
  out_addrlabel:
  	ipv6_addr_label_cleanup();
  out:
c127ea2c4   Thomas Graf   [IPv6]: Use rtnl ...
5136
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5137
  }
09f7709f4   Daniel Lezcano   [IPV6]: fix secti...
5138
  void addrconf_cleanup(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5139
  {
176c39af2   Daniel Lezcano   netns: fix addrco...
5140
  	struct net_device *dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5141
5142
5143
  	int i;
  
  	unregister_netdevice_notifier(&ipv6_dev_notf);
e0da5a480   Pavel Emelyanov   [NETNS]: Create i...
5144
  	unregister_pernet_subsys(&addrconf_ops);
2cc6d2bf3   Neil Horman   ipv6: add a missi...
5145
  	ipv6_addr_label_cleanup();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5146
5147
  
  	rtnl_lock();
b382b191e   Thomas Graf   ipv6: AF_INET6 li...
5148
  	__rtnl_af_unregister(&inet6_ops);
176c39af2   Daniel Lezcano   netns: fix addrco...
5149
5150
5151
5152
5153
5154
5155
  	/* clean dev list */
  	for_each_netdev(&init_net, dev) {
  		if (__in6_dev_get(dev) == NULL)
  			continue;
  		addrconf_ifdown(dev, 1);
  	}
  	addrconf_ifdown(init_net.loopback_dev, 2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5156
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5157
5158
  	 *	Check hash table.
  	 */
5c578aedc   stephen hemminger   IPv6: convert add...
5159
  	spin_lock_bh(&addrconf_hash_lock);
c2e21293c   stephen hemminger   ipv6: convert add...
5160
5161
  	for (i = 0; i < IN6_ADDR_HSIZE; i++)
  		WARN_ON(!hlist_empty(&inet6_addr_lst[i]));
5c578aedc   stephen hemminger   IPv6: convert add...
5162
  	spin_unlock_bh(&addrconf_hash_lock);
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
5163
  	cancel_delayed_work(&addr_chk_work);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5164
  	rtnl_unlock();
c15b1ccad   Hannes Frederic Sowa   ipv6: move DAD an...
5165
5166
  
  	destroy_workqueue(addrconf_wq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5167
  }