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 | |
61 | #include <linux/delay.h> | |
62 | #include <linux/notifier.h> | |
543537bd | 63 | #include <linux/string.h> |
1da177e4 LT |
64 | |
65 | #include <net/sock.h> | |
66 | #include <net/snmp.h> | |
67 | ||
68 | #include <net/ipv6.h> | |
69 | #include <net/protocol.h> | |
70 | #include <net/ndisc.h> | |
71 | #include <net/ip6_route.h> | |
72 | #include <net/addrconf.h> | |
73 | #include <net/tcp.h> | |
74 | #include <net/ip.h> | |
75 | #include <linux/if_tunnel.h> | |
76 | #include <linux/rtnetlink.h> | |
77 | ||
78 | #ifdef CONFIG_IPV6_PRIVACY | |
79 | #include <linux/random.h> | |
80 | #include <linux/crypto.h> | |
378f058c | 81 | #include <linux/scatterlist.h> |
1da177e4 LT |
82 | #endif |
83 | ||
84 | #include <asm/uaccess.h> | |
85 | ||
86 | #include <linux/proc_fs.h> | |
87 | #include <linux/seq_file.h> | |
88 | ||
89 | /* Set to 3 to get tracing... */ | |
90 | #define ACONF_DEBUG 2 | |
91 | ||
92 | #if ACONF_DEBUG >= 3 | |
93 | #define ADBG(x) printk x | |
94 | #else | |
95 | #define ADBG(x) | |
96 | #endif | |
97 | ||
98 | #define INFINITY_LIFE_TIME 0xFFFFFFFF | |
99 | #define TIME_DELTA(a,b) ((unsigned long)((long)(a) - (long)(b))) | |
100 | ||
101 | #ifdef CONFIG_SYSCTL | |
102 | static void addrconf_sysctl_register(struct inet6_dev *idev, struct ipv6_devconf *p); | |
103 | static void addrconf_sysctl_unregister(struct ipv6_devconf *p); | |
104 | #endif | |
105 | ||
106 | #ifdef CONFIG_IPV6_PRIVACY | |
107 | static int __ipv6_regen_rndid(struct inet6_dev *idev); | |
108 | static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr); | |
109 | static void ipv6_regen_rndid(unsigned long data); | |
110 | ||
111 | static int desync_factor = MAX_DESYNC_FACTOR * HZ; | |
112 | static struct crypto_tfm *md5_tfm; | |
113 | static DEFINE_SPINLOCK(md5_tfm_lock); | |
114 | #endif | |
115 | ||
116 | static int ipv6_count_addresses(struct inet6_dev *idev); | |
117 | ||
118 | /* | |
119 | * Configured unicast address hash table | |
120 | */ | |
121 | static struct inet6_ifaddr *inet6_addr_lst[IN6_ADDR_HSIZE]; | |
122 | static DEFINE_RWLOCK(addrconf_hash_lock); | |
123 | ||
124 | /* Protects inet6 devices */ | |
125 | DEFINE_RWLOCK(addrconf_lock); | |
126 | ||
127 | static void addrconf_verify(unsigned long); | |
128 | ||
8d06afab | 129 | static DEFINE_TIMER(addr_chk_timer, addrconf_verify, 0, 0); |
1da177e4 LT |
130 | static DEFINE_SPINLOCK(addrconf_verify_lock); |
131 | ||
132 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp); | |
133 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp); | |
134 | ||
135 | static int addrconf_ifdown(struct net_device *dev, int how); | |
136 | ||
e431b8c0 | 137 | static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags); |
1da177e4 LT |
138 | static void addrconf_dad_timer(unsigned long data); |
139 | static void addrconf_dad_completed(struct inet6_ifaddr *ifp); | |
c5e33bdd | 140 | static void addrconf_dad_run(struct inet6_dev *idev); |
1da177e4 LT |
141 | static void addrconf_rs_timer(unsigned long data); |
142 | static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); | |
143 | static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); | |
144 | ||
145 | static void inet6_prefix_notify(int event, struct inet6_dev *idev, | |
146 | struct prefix_info *pinfo); | |
147 | static int ipv6_chk_same_addr(const struct in6_addr *addr, struct net_device *dev); | |
148 | ||
149 | static struct notifier_block *inet6addr_chain; | |
150 | ||
151 | struct ipv6_devconf ipv6_devconf = { | |
152 | .forwarding = 0, | |
153 | .hop_limit = IPV6_DEFAULT_HOPLIMIT, | |
154 | .mtu6 = IPV6_MIN_MTU, | |
155 | .accept_ra = 1, | |
156 | .accept_redirects = 1, | |
157 | .autoconf = 1, | |
158 | .force_mld_version = 0, | |
159 | .dad_transmits = 1, | |
160 | .rtr_solicits = MAX_RTR_SOLICITATIONS, | |
161 | .rtr_solicit_interval = RTR_SOLICITATION_INTERVAL, | |
162 | .rtr_solicit_delay = MAX_RTR_SOLICITATION_DELAY, | |
163 | #ifdef CONFIG_IPV6_PRIVACY | |
164 | .use_tempaddr = 0, | |
165 | .temp_valid_lft = TEMP_VALID_LIFETIME, | |
166 | .temp_prefered_lft = TEMP_PREFERRED_LIFETIME, | |
167 | .regen_max_retry = REGEN_MAX_RETRY, | |
168 | .max_desync_factor = MAX_DESYNC_FACTOR, | |
169 | #endif | |
170 | .max_addresses = IPV6_MAX_ADDRESSES, | |
171 | }; | |
172 | ||
173 | static struct ipv6_devconf ipv6_devconf_dflt = { | |
174 | .forwarding = 0, | |
175 | .hop_limit = IPV6_DEFAULT_HOPLIMIT, | |
176 | .mtu6 = IPV6_MIN_MTU, | |
177 | .accept_ra = 1, | |
178 | .accept_redirects = 1, | |
179 | .autoconf = 1, | |
180 | .dad_transmits = 1, | |
181 | .rtr_solicits = MAX_RTR_SOLICITATIONS, | |
182 | .rtr_solicit_interval = RTR_SOLICITATION_INTERVAL, | |
183 | .rtr_solicit_delay = MAX_RTR_SOLICITATION_DELAY, | |
184 | #ifdef CONFIG_IPV6_PRIVACY | |
185 | .use_tempaddr = 0, | |
186 | .temp_valid_lft = TEMP_VALID_LIFETIME, | |
187 | .temp_prefered_lft = TEMP_PREFERRED_LIFETIME, | |
188 | .regen_max_retry = REGEN_MAX_RETRY, | |
189 | .max_desync_factor = MAX_DESYNC_FACTOR, | |
190 | #endif | |
191 | .max_addresses = IPV6_MAX_ADDRESSES, | |
192 | }; | |
193 | ||
194 | /* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */ | |
195 | #if 0 | |
196 | const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; | |
197 | #endif | |
198 | const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; | |
199 | ||
b1cacb68 YH |
200 | #define IPV6_ADDR_SCOPE_TYPE(scope) ((scope) << 16) |
201 | ||
202 | static inline unsigned ipv6_addr_scope2type(unsigned scope) | |
203 | { | |
204 | switch(scope) { | |
205 | case IPV6_ADDR_SCOPE_NODELOCAL: | |
206 | return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_NODELOCAL) | | |
207 | IPV6_ADDR_LOOPBACK); | |
208 | case IPV6_ADDR_SCOPE_LINKLOCAL: | |
209 | return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL) | | |
210 | IPV6_ADDR_LINKLOCAL); | |
211 | case IPV6_ADDR_SCOPE_SITELOCAL: | |
212 | return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL) | | |
213 | IPV6_ADDR_SITELOCAL); | |
214 | } | |
215 | return IPV6_ADDR_SCOPE_TYPE(scope); | |
216 | } | |
217 | ||
218 | int __ipv6_addr_type(const struct in6_addr *addr) | |
1da177e4 | 219 | { |
1da177e4 LT |
220 | u32 st; |
221 | ||
222 | st = addr->s6_addr32[0]; | |
223 | ||
1da177e4 | 224 | /* Consider all addresses with the first three bits different of |
b1cacb68 | 225 | 000 and 111 as unicasts. |
1da177e4 LT |
226 | */ |
227 | if ((st & htonl(0xE0000000)) != htonl(0x00000000) && | |
228 | (st & htonl(0xE0000000)) != htonl(0xE0000000)) | |
b1cacb68 YH |
229 | return (IPV6_ADDR_UNICAST | |
230 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); | |
1da177e4 | 231 | |
b1cacb68 YH |
232 | if ((st & htonl(0xFF000000)) == htonl(0xFF000000)) { |
233 | /* multicast */ | |
234 | /* addr-select 3.1 */ | |
235 | return (IPV6_ADDR_MULTICAST | | |
236 | ipv6_addr_scope2type(IPV6_ADDR_MC_SCOPE(addr))); | |
237 | } | |
238 | ||
239 | if ((st & htonl(0xFFC00000)) == htonl(0xFE800000)) | |
240 | return (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_UNICAST | | |
241 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL)); /* addr-select 3.1 */ | |
1da177e4 | 242 | if ((st & htonl(0xFFC00000)) == htonl(0xFEC00000)) |
b1cacb68 YH |
243 | return (IPV6_ADDR_SITELOCAL | IPV6_ADDR_UNICAST | |
244 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL)); /* addr-select 3.1 */ | |
1da177e4 LT |
245 | |
246 | if ((addr->s6_addr32[0] | addr->s6_addr32[1]) == 0) { | |
247 | if (addr->s6_addr32[2] == 0) { | |
248 | if (addr->s6_addr32[3] == 0) | |
249 | return IPV6_ADDR_ANY; | |
250 | ||
251 | if (addr->s6_addr32[3] == htonl(0x00000001)) | |
b1cacb68 YH |
252 | return (IPV6_ADDR_LOOPBACK | IPV6_ADDR_UNICAST | |
253 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL)); /* addr-select 3.4 */ | |
1da177e4 | 254 | |
b1cacb68 YH |
255 | return (IPV6_ADDR_COMPATv4 | IPV6_ADDR_UNICAST | |
256 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.3 */ | |
1da177e4 LT |
257 | } |
258 | ||
259 | if (addr->s6_addr32[2] == htonl(0x0000ffff)) | |
b1cacb68 YH |
260 | return (IPV6_ADDR_MAPPED | |
261 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.3 */ | |
1da177e4 LT |
262 | } |
263 | ||
b1cacb68 YH |
264 | return (IPV6_ADDR_RESERVED | |
265 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.4 */ | |
1da177e4 LT |
266 | } |
267 | ||
268 | static void addrconf_del_timer(struct inet6_ifaddr *ifp) | |
269 | { | |
270 | if (del_timer(&ifp->timer)) | |
271 | __in6_ifa_put(ifp); | |
272 | } | |
273 | ||
274 | enum addrconf_timer_t | |
275 | { | |
276 | AC_NONE, | |
277 | AC_DAD, | |
278 | AC_RS, | |
279 | }; | |
280 | ||
281 | static void addrconf_mod_timer(struct inet6_ifaddr *ifp, | |
282 | enum addrconf_timer_t what, | |
283 | unsigned long when) | |
284 | { | |
285 | if (!del_timer(&ifp->timer)) | |
286 | in6_ifa_hold(ifp); | |
287 | ||
288 | switch (what) { | |
289 | case AC_DAD: | |
290 | ifp->timer.function = addrconf_dad_timer; | |
291 | break; | |
292 | case AC_RS: | |
293 | ifp->timer.function = addrconf_rs_timer; | |
294 | break; | |
295 | default:; | |
296 | } | |
297 | ifp->timer.expires = jiffies + when; | |
298 | add_timer(&ifp->timer); | |
299 | } | |
300 | ||
301 | /* Nobody refers to this device, we may destroy it. */ | |
302 | ||
303 | void in6_dev_finish_destroy(struct inet6_dev *idev) | |
304 | { | |
305 | struct net_device *dev = idev->dev; | |
306 | BUG_TRAP(idev->addr_list==NULL); | |
307 | BUG_TRAP(idev->mc_list==NULL); | |
308 | #ifdef NET_REFCNT_DEBUG | |
309 | printk(KERN_DEBUG "in6_dev_finish_destroy: %s\n", dev ? dev->name : "NIL"); | |
310 | #endif | |
311 | dev_put(dev); | |
312 | if (!idev->dead) { | |
313 | printk("Freeing alive inet6 device %p\n", idev); | |
314 | return; | |
315 | } | |
316 | snmp6_free_dev(idev); | |
317 | kfree(idev); | |
318 | } | |
319 | ||
320 | static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |
321 | { | |
322 | struct inet6_dev *ndev; | |
323 | ||
324 | ASSERT_RTNL(); | |
325 | ||
326 | if (dev->mtu < IPV6_MIN_MTU) | |
327 | return NULL; | |
328 | ||
329 | ndev = kmalloc(sizeof(struct inet6_dev), GFP_KERNEL); | |
330 | ||
331 | if (ndev) { | |
332 | memset(ndev, 0, sizeof(struct inet6_dev)); | |
333 | ||
334 | rwlock_init(&ndev->lock); | |
335 | ndev->dev = dev; | |
336 | memcpy(&ndev->cnf, &ipv6_devconf_dflt, sizeof(ndev->cnf)); | |
337 | ndev->cnf.mtu6 = dev->mtu; | |
338 | ndev->cnf.sysctl = NULL; | |
339 | ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl); | |
340 | if (ndev->nd_parms == NULL) { | |
341 | kfree(ndev); | |
342 | return NULL; | |
343 | } | |
344 | /* We refer to the device */ | |
345 | dev_hold(dev); | |
346 | ||
347 | if (snmp6_alloc_dev(ndev) < 0) { | |
348 | ADBG((KERN_WARNING | |
349 | "%s(): cannot allocate memory for statistics; dev=%s.\n", | |
350 | __FUNCTION__, dev->name)); | |
351 | neigh_parms_release(&nd_tbl, ndev->nd_parms); | |
352 | ndev->dead = 1; | |
353 | in6_dev_finish_destroy(ndev); | |
354 | return NULL; | |
355 | } | |
356 | ||
357 | if (snmp6_register_dev(ndev) < 0) { | |
358 | ADBG((KERN_WARNING | |
359 | "%s(): cannot create /proc/net/dev_snmp6/%s\n", | |
360 | __FUNCTION__, dev->name)); | |
361 | neigh_parms_release(&nd_tbl, ndev->nd_parms); | |
362 | ndev->dead = 1; | |
363 | in6_dev_finish_destroy(ndev); | |
364 | return NULL; | |
365 | } | |
366 | ||
367 | /* One reference from device. We must do this before | |
368 | * we invoke __ipv6_regen_rndid(). | |
369 | */ | |
370 | in6_dev_hold(ndev); | |
371 | ||
372 | #ifdef CONFIG_IPV6_PRIVACY | |
373 | get_random_bytes(ndev->rndid, sizeof(ndev->rndid)); | |
374 | get_random_bytes(ndev->entropy, sizeof(ndev->entropy)); | |
375 | init_timer(&ndev->regen_timer); | |
376 | ndev->regen_timer.function = ipv6_regen_rndid; | |
377 | ndev->regen_timer.data = (unsigned long) ndev; | |
378 | if ((dev->flags&IFF_LOOPBACK) || | |
379 | dev->type == ARPHRD_TUNNEL || | |