Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * IPv6 Address [auto]configuration | |
3 | * Linux INET6 implementation | |
4 | * | |
5 | * Authors: | |
6 | * Pedro Roque <roque@di.fc.ul.pt> | |
7 | * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> | |
8 | * | |
9 | * $Id: addrconf.c,v 1.69 2001/10/31 21:55:54 davem Exp $ | |
10 | * | |
11 | * This program is free software; you can redistribute it and/or | |
12 | * modify it under the terms of the GNU General Public License | |
13 | * as published by the Free Software Foundation; either version | |
14 | * 2 of the License, or (at your option) any later version. | |
15 | */ | |
16 | ||
17 | /* | |
18 | * Changes: | |
19 | * | |
20 | * Janos Farkas : delete timer on ifdown | |
21 | * <chexum@bankinf.banki.hu> | |
22 | * Andi Kleen : kill double kfree on module | |
23 | * unload. | |
24 | * Maciej W. Rozycki : FDDI support | |
25 | * sekiya@USAGI : Don't send too many RS | |
26 | * packets. | |
27 | * yoshfuji@USAGI : Fixed interval between DAD | |
28 | * packets. | |
29 | * YOSHIFUJI Hideaki @USAGI : improved accuracy of | |
30 | * address validation timer. | |
31 | * YOSHIFUJI Hideaki @USAGI : Privacy Extensions (RFC3041) | |
32 | * support. | |
33 | * Yuji SEKIYA @USAGI : Don't assign a same IPv6 | |
34 | * address on a same interface. | |
35 | * YOSHIFUJI Hideaki @USAGI : ARCnet support | |
36 | * YOSHIFUJI Hideaki @USAGI : convert /proc/net/if_inet6 to | |
37 | * seq_file. | |
b1cacb68 YH |
38 | * YOSHIFUJI Hideaki @USAGI : improved source address |
39 | * selection; consider scope, | |
40 | * status etc. | |
1da177e4 LT |
41 | */ |
42 | ||
43 | #include <linux/config.h> | |
44 | #include <linux/errno.h> | |
45 | #include <linux/types.h> | |
46 | #include <linux/socket.h> | |
47 | #include <linux/sockios.h> | |
48 | #include <linux/sched.h> | |
49 | #include <linux/net.h> | |
50 | #include <linux/in6.h> | |
51 | #include <linux/netdevice.h> | |
52 | #include <linux/if_arp.h> | |
53 | #include <linux/if_arcnet.h> | |
54 | #include <linux/if_infiniband.h> | |
55 | #include <linux/route.h> | |
56 | #include <linux/inetdevice.h> | |
57 | #include <linux/init.h> | |
58 | #ifdef CONFIG_SYSCTL | |
59 | #include <linux/sysctl.h> | |
60 | #endif | |
4fc268d2 | 61 | #include <linux/capability.h> |
1da177e4 LT |
62 | #include <linux/delay.h> |
63 | #include <linux/notifier.h> | |
543537bd | 64 | #include <linux/string.h> |
1da177e4 LT |
65 | |
66 | #include <net/sock.h> | |
67 | #include <net/snmp.h> | |
68 | ||
69 | #include <net/ipv6.h> | |
70 | #include <net/protocol.h> | |
71 | #include <net/ndisc.h> | |
72 | #include <net/ip6_route.h> | |
73 | #include <net/addrconf.h> | |
74 | #include <net/tcp.h> | |
75 | #include <net/ip.h> | |
76 | #include <linux/if_tunnel.h> | |
77 | #include <linux/rtnetlink.h> | |
78 | ||
79 | #ifdef CONFIG_IPV6_PRIVACY | |
80 | #include <linux/random.h> | |
81 | #include <linux/crypto.h> | |
378f058c | 82 | #include <linux/scatterlist.h> |
1da177e4 LT |
83 | #endif |
84 | ||
85 | #include <asm/uaccess.h> | |
86 | ||
87 | #include <linux/proc_fs.h> | |
88 | #include <linux/seq_file.h> | |
89 | ||
90 | /* Set to 3 to get tracing... */ | |
91 | #define ACONF_DEBUG 2 | |
92 | ||
93 | #if ACONF_DEBUG >= 3 | |
94 | #define ADBG(x) printk x | |
95 | #else | |
96 | #define ADBG(x) | |
97 | #endif | |
98 | ||
99 | #define INFINITY_LIFE_TIME 0xFFFFFFFF | |
100 | #define TIME_DELTA(a,b) ((unsigned long)((long)(a) - (long)(b))) | |
101 | ||
102 | #ifdef CONFIG_SYSCTL | |
103 | static void addrconf_sysctl_register(struct inet6_dev *idev, struct ipv6_devconf *p); | |
104 | static void addrconf_sysctl_unregister(struct ipv6_devconf *p); | |
105 | #endif | |
106 | ||
107 | #ifdef CONFIG_IPV6_PRIVACY | |
108 | static int __ipv6_regen_rndid(struct inet6_dev *idev); | |
109 | static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr); | |
110 | static void ipv6_regen_rndid(unsigned long data); | |
111 | ||
112 | static int desync_factor = MAX_DESYNC_FACTOR * HZ; | |
113 | static struct crypto_tfm *md5_tfm; | |
114 | static DEFINE_SPINLOCK(md5_tfm_lock); | |
115 | #endif | |
116 | ||
117 | static int ipv6_count_addresses(struct inet6_dev *idev); | |
118 | ||
119 | /* | |
120 | * Configured unicast address hash table | |
121 | */ | |
122 | static struct inet6_ifaddr *inet6_addr_lst[IN6_ADDR_HSIZE]; | |
123 | static DEFINE_RWLOCK(addrconf_hash_lock); | |
124 | ||
125 | /* Protects inet6 devices */ | |
126 | DEFINE_RWLOCK(addrconf_lock); | |
127 | ||
128 | static void addrconf_verify(unsigned long); | |
129 | ||
8d06afab | 130 | static DEFINE_TIMER(addr_chk_timer, addrconf_verify, 0, 0); |
1da177e4 LT |
131 | static DEFINE_SPINLOCK(addrconf_verify_lock); |
132 | ||
133 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp); | |
134 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp); | |
135 | ||
136 | static int addrconf_ifdown(struct net_device *dev, int how); | |
137 | ||
e431b8c0 | 138 | static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags); |
1da177e4 LT |
139 | static void addrconf_dad_timer(unsigned long data); |
140 | static void addrconf_dad_completed(struct inet6_ifaddr *ifp); | |
c5e33bdd | 141 | static void addrconf_dad_run(struct inet6_dev *idev); |
1da177e4 LT |
142 | static void addrconf_rs_timer(unsigned long data); |
143 | static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); | |
144 | static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); | |
145 | ||
146 | static void inet6_prefix_notify(int event, struct inet6_dev *idev, | |
147 | struct prefix_info *pinfo); | |
148 | static int ipv6_chk_same_addr(const struct in6_addr *addr, struct net_device *dev); | |
149 | ||
150 | static struct notifier_block *inet6addr_chain; | |
151 | ||
152 | struct ipv6_devconf ipv6_devconf = { | |
153 | .forwarding = 0, | |
154 | .hop_limit = IPV6_DEFAULT_HOPLIMIT, | |
155 | .mtu6 = IPV6_MIN_MTU, | |
156 | .accept_ra = 1, | |
157 | .accept_redirects = 1, | |
158 | .autoconf = 1, | |
159 | .force_mld_version = 0, | |
160 | .dad_transmits = 1, | |
161 | .rtr_solicits = MAX_RTR_SOLICITATIONS, | |
162 | .rtr_solicit_interval = RTR_SOLICITATION_INTERVAL, | |
163 | .rtr_solicit_delay = MAX_RTR_SOLICITATION_DELAY, | |
164 | #ifdef CONFIG_IPV6_PRIVACY | |
165 | .use_tempaddr = 0, | |
166 | .temp_valid_lft = TEMP_VALID_LIFETIME, | |
167 | .temp_prefered_lft = TEMP_PREFERRED_LIFETIME, | |
168 | .regen_max_retry = REGEN_MAX_RETRY, | |
169 | .max_desync_factor = MAX_DESYNC_FACTOR, | |
170 | #endif | |
171 | .max_addresses = IPV6_MAX_ADDRESSES, | |
172 | }; | |
173 | ||
174 | static struct ipv6_devconf ipv6_devconf_dflt = { | |
175 | .forwarding = 0, | |
176 | .hop_limit = IPV6_DEFAULT_HOPLIMIT, | |
177 | .mtu6 = IPV6_MIN_MTU, | |
178 | .accept_ra = 1, | |
179 | .accept_redirects = 1, | |
180 | .autoconf = 1, | |
181 | .dad_transmits = 1, | |
182 | .rtr_solicits = MAX_RTR_SOLICITATIONS, | |
183 | .rtr_solicit_interval = RTR_SOLICITATION_INTERVAL, | |
184 | .rtr_solicit_delay = MAX_RTR_SOLICITATION_DELAY, | |
185 | #ifdef CONFIG_IPV6_PRIVACY | |
186 | .use_tempaddr = 0, | |
187 | .temp_valid_lft = TEMP_VALID_LIFETIME, | |
188 | .temp_prefered_lft = TEMP_PREFERRED_LIFETIME, | |
189 | .regen_max_retry = REGEN_MAX_RETRY, | |
190 | .max_desync_factor = MAX_DESYNC_FACTOR, | |
191 | #endif | |
192 | .max_addresses = IPV6_MAX_ADDRESSES, | |
193 | }; | |
194 | ||
195 | /* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */ | |
196 | #if 0 | |
197 | const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; | |
198 | #endif | |
199 | const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; | |
200 | ||
b1cacb68 YH |
201 | #define IPV6_ADDR_SCOPE_TYPE(scope) ((scope) << 16) |
202 | ||
203 | static inline unsigned ipv6_addr_scope2type(unsigned scope) | |
204 | { | |
205 | switch(scope) { | |
206 | case IPV6_ADDR_SCOPE_NODELOCAL: | |
207 | return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_NODELOCAL) | | |
208 | IPV6_ADDR_LOOPBACK); | |
209 | case IPV6_ADDR_SCOPE_LINKLOCAL: | |
210 | return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL) | | |
211 | IPV6_ADDR_LINKLOCAL); | |
212 | case IPV6_ADDR_SCOPE_SITELOCAL: | |
213 | return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL) | | |
214 | IPV6_ADDR_SITELOCAL); | |
215 | } | |
216 | return IPV6_ADDR_SCOPE_TYPE(scope); | |
217 | } | |
218 | ||
219 | int __ipv6_addr_type(const struct in6_addr *addr) | |
1da177e4 | 220 | { |
1da177e4 LT |
221 | u32 st; |
222 | ||
223 | st = addr->s6_addr32[0]; | |
224 | ||
1da177e4 | 225 | /* Consider all addresses with the first three bits different of |
b1cacb68 | 226 | 000 and 111 as unicasts. |
1da177e4 LT |
227 | */ |
228 | if ((st & htonl(0xE0000000)) != htonl(0x00000000) && | |
229 | (st & htonl(0xE0000000)) != htonl(0xE0000000)) | |
b1cacb68 YH |
230 | return (IPV6_ADDR_UNICAST | |
231 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); | |
1da177e4 | 232 | |
b1cacb68 YH |
233 | if ((st & htonl(0xFF000000)) == htonl(0xFF000000)) { |
234 | /* multicast */ | |
235 | /* addr-select 3.1 */ | |
236 | return (IPV6_ADDR_MULTICAST | | |
237 | ipv6_addr_scope2type(IPV6_ADDR_MC_SCOPE(addr))); | |
238 | } | |
239 | ||
240 | if ((st & htonl(0xFFC00000)) == htonl(0xFE800000)) | |
241 | return (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_UNICAST | | |
242 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL)); /* addr-select 3.1 */ | |
1da177e4 | 243 | if ((st & htonl(0xFFC00000)) == htonl(0xFEC00000)) |
b1cacb68 YH |
244 | return (IPV6_ADDR_SITELOCAL | IPV6_ADDR_UNICAST | |
245 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL)); /* addr-select 3.1 */ | |
1da177e4 LT |
246 | |
247 | if ((addr->s6_addr32[0] | addr->s6_addr32[1]) == 0) { | |
248 | if (addr->s6_addr32[2] == 0) { | |
249 | if (addr->s6_addr32[3] == 0) | |
250 | return IPV6_ADDR_ANY; | |
251 | ||
252 | if (addr->s6_addr32[3] == htonl(0x00000001)) | |
b1cacb68 YH |
253 | return (IPV6_ADDR_LOOPBACK | IPV6_ADDR_UNICAST | |
254 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL)); /* addr-select 3.4 */ | |
1da177e4 | 255 | |
b1cacb68 YH |
256 | return (IPV6_ADDR_COMPATv4 | IPV6_ADDR_UNICAST | |
257 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.3 */ | |
1da177e4 LT |
258 | } |
259 | ||
260 | if (addr->s6_addr32[2] == htonl(0x0000ffff)) | |
b1cacb68 YH |
261 | return (IPV6_ADDR_MAPPED | |
262 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.3 */ | |
1da177e4 LT |
263 | } |
264 | ||
b1cacb68 YH |
265 | return (IPV6_ADDR_RESERVED | |
266 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.4 */ | |
1da177e4 LT |
267 | } |
268 | ||
269 | static void addrconf_del_timer(struct inet6_ifaddr *ifp) | |
270 | { | |
271 | if (del_timer(&ifp->timer)) | |
272 | __in6_ifa_put(ifp); | |
273 | } | |
274 | ||
275 | enum addrconf_timer_t | |
276 | { | |
277 | AC_NONE, | |
278 | AC_DAD, | |
279 | AC_RS, | |
280 | }; | |
281 | ||
282 | static void addrconf_mod_timer(struct inet6_ifaddr *ifp, | |
283 | enum addrconf_timer_t what, | |
284 | unsigned long when) | |
285 | { | |
286 | if (!del_timer(&ifp->timer)) | |
287 | in6_ifa_hold(ifp); | |
288 | ||
289 | switch (what) { | |
290 | case AC_DAD: | |
291 | ifp->timer.function = addrconf_dad_timer; | |
292 | break; | |
293 | case AC_RS: | |
294 | ifp->timer.function = addrconf_rs_timer; | |
295 | break; | |
296 | default:; | |
297 | } | |
298 | ifp->timer.expires = jiffies + when; | |
299 | add_timer(&ifp->timer); | |
300 | } | |
301 | ||
302 | /* Nobody refers to this device, we may destroy it. */ | |
303 | ||
304 | void in6_dev_finish_destroy(struct inet6_dev *idev) | |
305 | { | |
306 | struct net_device *dev = idev->dev; | |
307 | BUG_TRAP(idev->addr_list==NULL); | |
308 | BUG_TRAP(idev->mc_list==NULL); | |
309 | #ifdef NET_REFCNT_DEBUG | |
310 | printk(KERN_DEBUG "in6_dev_finish_destroy: %s\n", dev ? dev->name : "NIL"); | |
311 | #endif | |
312 | dev_put(dev); | |
313 | if (!idev->dead) { | |
314 | printk("Freeing alive inet6 device %p\n", idev); | |
315 | return; | |
316 | } | |
317 | snmp6_free_dev(idev); | |
318 | kfree(idev); | |
319 | } | |
320 | ||
321 | static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |
322 | { | |
323 | struct inet6_dev *ndev; | |
324 | ||
325 | ASSERT_RTNL(); | |
326 | ||
327 | if (dev->mtu < IPV6_MIN_MTU) | |
328 | return NULL; | |
329 | ||
330 | ndev = kmalloc(sizeof(struct inet6_dev), GFP_KERNEL); | |
331 | ||
332 | if (ndev) { | |
333 | memset(ndev, 0, sizeof(struct inet6_dev)); | |
334 | ||
335 | rwlock_init(&ndev->lock); | |
336 | ndev->dev = dev; | |
337 | memcpy(&ndev->cnf, &ipv6_devconf_dflt, sizeof(ndev->cnf)); | |
338 | ndev->cnf.mtu6 = dev->mtu; | |
339 | ndev->cnf.sysctl = NULL; | |
340 | ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl); | |
341 | if (ndev->nd_parms == NULL) { | |
342 | kfree(ndev); | |
343 | return NULL; | |
344 | } | |
345 | /* We refer to the device */ | |
346 | dev_hold(dev); | |
347 | ||
348 | if (snmp6_alloc_dev(ndev) < 0) { | |
349 | ADBG((KERN_WARNING | |
350 | "%s(): cannot allocate memory for statistics; dev=%s.\n", | |
351 | __FUNCTION__, dev->name)); | |
352 | neigh_parms_release(&nd_tbl, ndev->nd_parms); | |
353 | ndev->dead = 1; | |
354 | in6_dev_finish_destroy(ndev); | |
355 | return NULL; | |
356 | } | |
357 | ||
358 | if (snmp6_register_dev(ndev) < 0) { | |
359 | ADBG((KERN_WARNING | |
360 | "%s(): cannot create /proc/net/dev_snmp6/%s\n", | |
361 | __FUNCTION__, dev->name)); | |
362 | neigh_parms_release(&nd_tbl, ndev->nd_parms); | |
363 | ndev->dead = 1; | |
364 | in6_dev_finish_destroy(ndev); | |
365 | return NULL; | |
366 | } | |
367 | ||
368 | /* One reference from device. We must do this before | |
369 | * we invoke __ipv6_regen_rndid(). | |
370 | */ | |
371 | in6_dev_hold(ndev); | |
372 | ||
373 | #ifdef CONFIG_IPV6_PRIVACY | |
374 | get_random_bytes(ndev->rndid, sizeof(ndev->rndid)); | |
375 | get_random_bytes(ndev->entropy, sizeof(ndev->entropy)); | |
376 | init_timer(&ndev->regen_timer); | |
377 | ndev->regen_timer.function = ipv6_regen_rndid; | |
378 | ndev->regen_timer.data = (unsigned long) ndev; | |
379 | if ((dev->flags&IFF_LOOPBACK) || | |
380 | dev->type == ARPHRD_TUNNEL || |