blob: f4462ee33024f4793b844554e33871883d99f8ed [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Neighbour Discovery for IPv6
3 * Linux INET6 implementation
4 *
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
7 * Mike Shaver <shaver@ingenia.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
13 */
14
15/*
16 * Changes:
17 *
18 * Lars Fenneberg : fixed MTU setting on receipt
19 * of an RA.
20 *
21 * Janos Farkas : kmalloc failure checks
22 * Alexey Kuznetsov : state machine reworked
23 * and moved to net/core.
24 * Pekka Savola : RFC2461 validation
25 * YOSHIFUJI Hideaki @USAGI : Verify ND options properly
26 */
27
28/* Set to 3 to get tracing... */
29#define ND_DEBUG 1
30
31#define ND_PRINTK(fmt, args...) do { if (net_ratelimit()) { printk(fmt, ## args); } } while(0)
32#define ND_NOPRINTK(x...) do { ; } while(0)
33#define ND_PRINTK0 ND_PRINTK
34#define ND_PRINTK1 ND_NOPRINTK
35#define ND_PRINTK2 ND_NOPRINTK
36#define ND_PRINTK3 ND_NOPRINTK
37#if ND_DEBUG >= 1
38#undef ND_PRINTK1
39#define ND_PRINTK1 ND_PRINTK
40#endif
41#if ND_DEBUG >= 2
42#undef ND_PRINTK2
43#define ND_PRINTK2 ND_PRINTK
44#endif
45#if ND_DEBUG >= 3
46#undef ND_PRINTK3
47#define ND_PRINTK3 ND_PRINTK
48#endif
49
50#include <linux/module.h>
51#include <linux/config.h>
52#include <linux/errno.h>
53#include <linux/types.h>
54#include <linux/socket.h>
55#include <linux/sockios.h>
56#include <linux/sched.h>
57#include <linux/net.h>
58#include <linux/in6.h>
59#include <linux/route.h>
60#include <linux/init.h>
61#include <linux/rcupdate.h>
62#ifdef CONFIG_SYSCTL
63#include <linux/sysctl.h>
64#endif
65
66#include <linux/if_arp.h>
67#include <linux/ipv6.h>
68#include <linux/icmpv6.h>
69#include <linux/jhash.h>
70
71#include <net/sock.h>
72#include <net/snmp.h>
73
74#include <net/ipv6.h>
75#include <net/protocol.h>
76#include <net/ndisc.h>
77#include <net/ip6_route.h>
78#include <net/addrconf.h>
79#include <net/icmp.h>
80
81#include <net/flow.h>
82#include <net/ip6_checksum.h>
83#include <linux/proc_fs.h>
84
85#include <linux/netfilter.h>
86#include <linux/netfilter_ipv6.h>
87
88static struct socket *ndisc_socket;
89
90static u32 ndisc_hash(const void *pkey, const struct net_device *dev);
91static int ndisc_constructor(struct neighbour *neigh);
92static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb);
93static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb);
94static int pndisc_constructor(struct pneigh_entry *n);
95static void pndisc_destructor(struct pneigh_entry *n);
96static void pndisc_redo(struct sk_buff *skb);
97
98static struct neigh_ops ndisc_generic_ops = {
99 .family = AF_INET6,
100 .solicit = ndisc_solicit,
101 .error_report = ndisc_error_report,
102 .output = neigh_resolve_output,
103 .connected_output = neigh_connected_output,
104 .hh_output = dev_queue_xmit,
105 .queue_xmit = dev_queue_xmit,
106};
107
108static struct neigh_ops ndisc_hh_ops = {
109 .family = AF_INET6,
110 .solicit = ndisc_solicit,
111 .error_report = ndisc_error_report,
112 .output = neigh_resolve_output,
113 .connected_output = neigh_resolve_output,
114 .hh_output = dev_queue_xmit,
115 .queue_xmit = dev_queue_xmit,
116};
117
118
119static struct neigh_ops ndisc_direct_ops = {
120 .family = AF_INET6,
121 .output = dev_queue_xmit,
122 .connected_output = dev_queue_xmit,
123 .hh_output = dev_queue_xmit,
124 .queue_xmit = dev_queue_xmit,
125};
126
127struct neigh_table nd_tbl = {
128 .family = AF_INET6,
129 .entry_size = sizeof(struct neighbour) + sizeof(struct in6_addr),
130 .key_len = sizeof(struct in6_addr),
131 .hash = ndisc_hash,
132 .constructor = ndisc_constructor,
133 .pconstructor = pndisc_constructor,
134 .pdestructor = pndisc_destructor,
135 .proxy_redo = pndisc_redo,
136 .id = "ndisc_cache",
137 .parms = {
138 .tbl = &nd_tbl,
139 .base_reachable_time = 30 * HZ,
140 .retrans_time = 1 * HZ,
141 .gc_staletime = 60 * HZ,
142 .reachable_time = 30 * HZ,
143 .delay_probe_time = 5 * HZ,
144 .queue_len = 3,
145 .ucast_probes = 3,
146 .mcast_probes = 3,
147 .anycast_delay = 1 * HZ,
148 .proxy_delay = (8 * HZ) / 10,
149 .proxy_qlen = 64,
150 },
151 .gc_interval = 30 * HZ,
152 .gc_thresh1 = 128,
153 .gc_thresh2 = 512,
154 .gc_thresh3 = 1024,
155};
156
157/* ND options */
158struct ndisc_options {
159 struct nd_opt_hdr *nd_opt_array[__ND_OPT_MAX];
160};
161
162#define nd_opts_src_lladdr nd_opt_array[ND_OPT_SOURCE_LL_ADDR]
163#define nd_opts_tgt_lladdr nd_opt_array[ND_OPT_TARGET_LL_ADDR]
164#define nd_opts_pi nd_opt_array[ND_OPT_PREFIX_INFO]
165#define nd_opts_pi_end nd_opt_array[__ND_OPT_PREFIX_INFO_END]
166#define nd_opts_rh nd_opt_array[ND_OPT_REDIRECT_HDR]
167#define nd_opts_mtu nd_opt_array[ND_OPT_MTU]
168
169#define NDISC_OPT_SPACE(len) (((len)+2+7)&~7)
170
171/*
172 * Return the padding between the option length and the start of the
173 * link addr. Currently only IP-over-InfiniBand needs this, although
174 * if RFC 3831 IPv6-over-Fibre Channel is ever implemented it may
175 * also need a pad of 2.
176 */
177static int ndisc_addr_option_pad(unsigned short type)
178{
179 switch (type) {
180 case ARPHRD_INFINIBAND: return 2;
181 default: return 0;
182 }
183}
184
185static inline int ndisc_opt_addr_space(struct net_device *dev)
186{
187 return NDISC_OPT_SPACE(dev->addr_len + ndisc_addr_option_pad(dev->type));
188}
189
190static u8 *ndisc_fill_addr_option(u8 *opt, int type, void *data, int data_len,
191 unsigned short addr_type)
192{
193 int space = NDISC_OPT_SPACE(data_len);
194 int pad = ndisc_addr_option_pad(addr_type);
195
196 opt[0] = type;
197 opt[1] = space>>3;
198
199 memset(opt + 2, 0, pad);
200 opt += pad;
201 space -= pad;
202
203 memcpy(opt+2, data, data_len);
204 data_len += 2;
205 opt += data_len;
206 if ((space -= data_len) > 0)
207 memset(opt, 0, space);
208 return opt + space;
209}
210
211static struct nd_opt_hdr *ndisc_next_option(struct nd_opt_hdr *cur,
212 struct nd_opt_hdr *end)
213{
214 int type;
215 if (!cur || !end || cur >= end)
216 return NULL;
217 type = cur->nd_opt_type;
218 do {
219 cur = ((void *)cur) + (cur->nd_opt_len << 3);
220 } while(cur < end && cur->nd_opt_type != type);
221 return (cur <= end && cur->nd_opt_type == type ? cur : NULL);
222}
223
224static struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len,
225 struct ndisc_options *ndopts)
226{
227 struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)opt;
228
229 if (!nd_opt || opt_len < 0 || !ndopts)
230 return NULL;
231 memset(ndopts, 0, sizeof(*ndopts));
232 while (opt_len) {
233 int l;
234 if (opt_len < sizeof(struct nd_opt_hdr))
235 return NULL;
236 l = nd_opt->nd_opt_len << 3;
237 if (opt_len < l || l == 0)
238 return NULL;
239 switch (nd_opt->nd_opt_type) {
240 case ND_OPT_SOURCE_LL_ADDR:
241 case ND_OPT_TARGET_LL_ADDR:
242 case ND_OPT_MTU:
243 case ND_OPT_REDIRECT_HDR:
244 if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) {
245 ND_PRINTK2(KERN_WARNING
246 "%s(): duplicated ND6 option found: type=%d\n",
247 __FUNCTION__,
248 nd_opt->nd_opt_type);
249 } else {
250 ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt;
251 }
252 break;
253 case ND_OPT_PREFIX_INFO:
254 ndopts->nd_opts_pi_end = nd_opt;
255 if (ndopts->nd_opt_array[nd_opt->nd_opt_type] == 0)
256 ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt;
257 break;
258 default:
259 /*
260 * Unknown options must be silently ignored,
261 * to accommodate future extension to the protocol.
262 */
263 ND_PRINTK2(KERN_NOTICE
264 "%s(): ignored unsupported option; type=%d, len=%d\n",
265 __FUNCTION__,
266 nd_opt->nd_opt_type, nd_opt->nd_opt_len);
267 }
268 opt_len -= l;
269 nd_opt = ((void *)nd_opt) + l;
270 }
271 return ndopts;
272}
273
274static inline u8 *ndisc_opt_addr_data(struct nd_opt_hdr *p,
275 struct net_device *dev)
276{
277 u8 *lladdr = (u8 *)(p + 1);
278 int lladdrlen = p->nd_opt_len << 3;
279 int prepad = ndisc_addr_option_pad(dev->type);
280 if (lladdrlen != NDISC_OPT_SPACE(dev->addr_len + prepad))
281 return NULL;
282 return (lladdr + prepad);
283}
284
285int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int dir)
286{
287 switch (dev->type) {
288 case ARPHRD_ETHER:
289 case ARPHRD_IEEE802: /* Not sure. Check it later. --ANK */
290 case ARPHRD_FDDI:
291 ipv6_eth_mc_map(addr, buf);
292 return 0;
293 case ARPHRD_IEEE802_TR:
294 ipv6_tr_mc_map(addr,buf);
295 return 0;
296 case ARPHRD_ARCNET:
297 ipv6_arcnet_mc_map(addr, buf);
298 return 0;
299 case ARPHRD_INFINIBAND:
300 ipv6_ib_mc_map(addr, buf);
301 return 0;
302 default:
303 if (dir) {
304 memcpy(buf, dev->broadcast, dev->addr_len);
305 return 0;
306 }
307 }
308 return -EINVAL;
309}
310
311static u32 ndisc_hash(const void *pkey, const struct net_device *dev)
312{
313 const u32 *p32 = pkey;
314 u32 addr_hash, i;
315
316 addr_hash = 0;
317 for (i = 0; i < (sizeof(struct in6_addr) / sizeof(u32)); i++)
318 addr_hash ^= *p32++;
319
320 return jhash_2words(addr_hash, dev->ifindex, nd_tbl.hash_rnd);
321}
322
323static int ndisc_constructor(struct neighbour *neigh)
324{
325 struct in6_addr *addr = (struct in6_addr*)&neigh->primary_key;
326 struct net_device *dev = neigh->dev;
327 struct inet6_dev *in6_dev;
328 struct neigh_parms *parms;
329 int is_multicast = ipv6_addr_is_multicast(addr);
330
331 rcu_read_lock();
332 in6_dev = in6_dev_get(dev);
333 if (in6_dev == NULL) {
334 rcu_read_unlock();
335 return -EINVAL;
336 }
337
338 parms = in6_dev->nd_parms;
339 __neigh_parms_put(neigh->parms);
340 neigh->parms = neigh_parms_clone(parms);
341 rcu_read_unlock();
342
343 neigh->type = is_multicast ? RTN_MULTICAST : RTN_UNICAST;
344 if (dev->hard_header == NULL) {
345 neigh->nud_state = NUD_NOARP;
346 neigh->ops = &ndisc_direct_ops;
347 neigh->output = neigh->ops->queue_xmit;
348 } else {
349 if (is_multicast) {
350 neigh->nud_state = NUD_NOARP;
351 ndisc_mc_map(addr, neigh->ha, dev, 1);
352 } else if (dev->flags&(IFF_NOARP|IFF_LOOPBACK)) {
353 neigh->nud_state = NUD_NOARP;
354 memcpy(neigh->ha, dev->dev_addr, dev->addr_len);
355 if (dev->flags&IFF_LOOPBACK)
356 neigh->type = RTN_LOCAL;
357 } else if (dev->flags&IFF_POINTOPOINT) {
358 neigh->nud_state = NUD_NOARP;
359 memcpy(neigh->ha, dev->broadcast, dev->addr_len);
360 }
361 if (dev->hard_header_cache)
362 neigh->ops = &ndisc_hh_ops;
363 else
364 neigh->ops = &ndisc_generic_ops;
365 if (neigh->nud_state&NUD_VALID)
366 neigh->output = neigh->ops->connected_output;
367 else
368 neigh->output = neigh->ops->output;
369 }
370 in6_dev_put(in6_dev);
371 return 0;
372}
373
374static int pndisc_constructor(struct pneigh_entry *n)
375{
376 struct in6_addr *addr = (struct in6_addr*)&n->key;
377 struct in6_addr maddr;
378 struct net_device *dev = n->dev;
379
380 if (dev == NULL || __in6_dev_get(dev) == NULL)
381 return -EINVAL;
382 addrconf_addr_solict_mult(addr, &maddr);
383 ipv6_dev_mc_inc(dev, &maddr);
384 return 0;
385}
386
387static void pndisc_destructor(struct pneigh_entry *n)
388{
389 struct in6_addr *addr = (struct in6_addr*)&n->key;
390 struct in6_addr maddr;
391 struct net_device *dev = n->dev;
392
393 if (dev == NULL || __in6_dev_get(dev) == NULL)
394 return;
395 addrconf_addr_solict_mult(addr, &maddr);
396 ipv6_dev_mc_dec(dev, &maddr);
397}
398
399/*
400 * Send a Neighbour Advertisement
401 */
402
403static inline void ndisc_flow_init(struct flowi *fl, u8 type,
404 struct in6_addr *saddr, struct in6_addr *daddr)
405{
406 memset(fl, 0, sizeof(*fl));
407 ipv6_addr_copy(&fl->fl6_src, saddr);
408 ipv6_addr_copy(&fl->fl6_dst, daddr);
409 fl->proto = IPPROTO_ICMPV6;
410 fl->fl_icmp_type = type;
411 fl->fl_icmp_code = 0;
412}
413
414static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
415 struct in6_addr *daddr, struct in6_addr *solicited_addr,
416 int router, int solicited, int override, int inc_opt)
417{
418 struct in6_addr tmpaddr;
419 struct inet6_ifaddr *ifp;
420 struct inet6_dev *idev;
421 struct flowi fl;
422 struct dst_entry* dst;
423 struct sock *sk = ndisc_socket->sk;
424 struct in6_addr *src_addr;
425 struct nd_msg *msg;
426 int len;
427 struct sk_buff *skb;
428 int err;
429
430 len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
431
432 /* for anycast or proxy, solicited_addr != src_addr */
433 ifp = ipv6_get_ifaddr(solicited_addr, dev, 1);
434 if (ifp) {
435 src_addr = solicited_addr;
436 in6_ifa_put(ifp);
437 } else {
438 if (ipv6_dev_get_saddr(dev, daddr, &tmpaddr))
439 return;
440 src_addr = &tmpaddr;
441 }
442
443 ndisc_flow_init(&fl, NDISC_NEIGHBOUR_ADVERTISEMENT, src_addr, daddr);
444
445 dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output);
446 if (!dst)
447 return;
448
449 err = xfrm_lookup(&dst, &fl, NULL, 0);
Patrick McHardye104411b2005-09-08 15:11:55 -0700450 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452
453 if (inc_opt) {
454 if (dev->addr_len)
455 len += ndisc_opt_addr_space(dev);
456 else
457 inc_opt = 0;
458 }
459
460 skb = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
461 1, &err);
462
463 if (skb == NULL) {
464 ND_PRINTK0(KERN_ERR
465 "ICMPv6 NA: %s() failed to allocate an skb.\n",
466 __FUNCTION__);
467 dst_release(dst);
468 return;
469 }
470
471 skb_reserve(skb, LL_RESERVED_SPACE(dev));
472 ip6_nd_hdr(sk, skb, dev, src_addr, daddr, IPPROTO_ICMPV6, len);
473
474 msg = (struct nd_msg *)skb_put(skb, len);
475 skb->h.raw = (unsigned char*)msg;
476
477 msg->icmph.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT;
478 msg->icmph.icmp6_code = 0;
479 msg->icmph.icmp6_cksum = 0;
480
481 msg->icmph.icmp6_unused = 0;
482 msg->icmph.icmp6_router = router;
483 msg->icmph.icmp6_solicited = solicited;
484 msg->icmph.icmp6_override = !!override;
485
486 /* Set the target address. */
487 ipv6_addr_copy(&msg->target, solicited_addr);
488
489 if (inc_opt)
490 ndisc_fill_addr_option(msg->opt, ND_OPT_TARGET_LL_ADDR, dev->dev_addr,
491 dev->addr_len, dev->type);
492
493 /* checksum */
494 msg->icmph.icmp6_cksum = csum_ipv6_magic(src_addr, daddr, len,
495 IPPROTO_ICMPV6,
496 csum_partial((__u8 *) msg,
497 len, 0));
498
499 skb->dst = dst;
500 idev = in6_dev_get(dst->dev);
501 IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
502 err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
503 if (!err) {
504 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTNEIGHBORADVERTISEMENTS);
505 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
506 }
507
508 if (likely(idev != NULL))
509 in6_dev_put(idev);
510}
511
512void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
513 struct in6_addr *solicit,
514 struct in6_addr *daddr, struct in6_addr *saddr)
515{
516 struct flowi fl;
517 struct dst_entry* dst;
518 struct inet6_dev *idev;
519 struct sock *sk = ndisc_socket->sk;
520 struct sk_buff *skb;
521 struct nd_msg *msg;
522 struct in6_addr addr_buf;
523 int len;
524 int err;
525 int send_llinfo;
526
527 if (saddr == NULL) {
528 if (ipv6_get_lladdr(dev, &addr_buf))
529 return;
530 saddr = &addr_buf;
531 }
532
533 ndisc_flow_init(&fl, NDISC_NEIGHBOUR_SOLICITATION, saddr, daddr);
534
535 dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output);
536 if (!dst)
537 return;
538
539 err = xfrm_lookup(&dst, &fl, NULL, 0);
Patrick McHardye104411b2005-09-08 15:11:55 -0700540 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542
543 len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
544 send_llinfo = dev->addr_len && !ipv6_addr_any(saddr);
545 if (send_llinfo)
546 len += ndisc_opt_addr_space(dev);
547
548 skb = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
549 1, &err);
550 if (skb == NULL) {
551 ND_PRINTK0(KERN_ERR
552 "ICMPv6 NA: %s() failed to allocate an skb.\n",
553 __FUNCTION__);
554 dst_release(dst);
555 return;
556 }
557
558 skb_reserve(skb, LL_RESERVED_SPACE(dev));
559 ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len);
560
561 msg = (struct nd_msg *)skb_put(skb, len);
562 skb->h.raw = (unsigned char*)msg;
563 msg->icmph.icmp6_type = NDISC_NEIGHBOUR_SOLICITATION;
564 msg->icmph.icmp6_code = 0;
565 msg->icmph.icmp6_cksum = 0;
566 msg->icmph.icmp6_unused = 0;
567
568 /* Set the target address. */
569 ipv6_addr_copy(&msg->target, solicit);
570
571 if (send_llinfo)
572 ndisc_fill_addr_option(msg->opt, ND_OPT_SOURCE_LL_ADDR, dev->dev_addr,
573 dev->addr_len, dev->type);
574
575 /* checksum */
576 msg->icmph.icmp6_cksum = csum_ipv6_magic(&skb->nh.ipv6h->saddr,
577 daddr, len,
578 IPPROTO_ICMPV6,
579 csum_partial((__u8 *) msg,
580 len, 0));
581 /* send it! */
582 skb->dst = dst;
583 idev = in6_dev_get(dst->dev);
584 IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
585 err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
586 if (!err) {
587 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTNEIGHBORSOLICITS);
588 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
589 }
590
591 if (likely(idev != NULL))
592 in6_dev_put(idev);
593}
594
595void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
596 struct in6_addr *daddr)
597{
598 struct flowi fl;
599 struct dst_entry* dst;
600 struct inet6_dev *idev;
601 struct sock *sk = ndisc_socket->sk;
602 struct sk_buff *skb;
603 struct icmp6hdr *hdr;
604 __u8 * opt;
605 int len;
606 int err;
607
608 ndisc_flow_init(&fl, NDISC_ROUTER_SOLICITATION, saddr, daddr);
609
610 dst = ndisc_dst_alloc(dev, NULL, daddr, ip6_output);
611 if (!dst)
612 return;
613
614 err = xfrm_lookup(&dst, &fl, NULL, 0);
Patrick McHardye104411b2005-09-08 15:11:55 -0700615 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617
618 len = sizeof(struct icmp6hdr);
619 if (dev->addr_len)
620 len += ndisc_opt_addr_space(dev);
621
622 skb = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
623 1, &err);
624 if (skb == NULL) {
625 ND_PRINTK0(KERN_ERR
626 "ICMPv6 RS: %s() failed to allocate an skb.\n",
627 __FUNCTION__);
628 dst_release(dst);
629 return;
630 }
631
632 skb_reserve(skb, LL_RESERVED_SPACE(dev));
633 ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len);
634
635 hdr = (struct icmp6hdr *)skb_put(skb, len);
636 skb->h.raw = (unsigned char*)hdr;
637 hdr->icmp6_type = NDISC_ROUTER_SOLICITATION;
638 hdr->icmp6_code = 0;
639 hdr->icmp6_cksum = 0;
640 hdr->icmp6_unused = 0;
641
642 opt = (u8*) (hdr + 1);
643
644 if (dev->addr_len)
645 ndisc_fill_addr_option(opt, ND_OPT_SOURCE_LL_ADDR, dev->dev_addr,
646 dev->addr_len, dev->type);
647
648 /* checksum */
649 hdr->icmp6_cksum = csum_ipv6_magic(&skb->nh.ipv6h->saddr, daddr, len,
650 IPPROTO_ICMPV6,
651 csum_partial((__u8 *) hdr, len, 0));
652
653 /* send it! */
654 skb->dst = dst;
655 idev = in6_dev_get(dst->dev);
656 IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
657 err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
658 if (!err) {
659 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTROUTERSOLICITS);
660 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
661 }
662
663 if (likely(idev != NULL))
664 in6_dev_put(idev);
665}
666
667
668static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb)
669{
670 /*
671 * "The sender MUST return an ICMP
672 * destination unreachable"
673 */
674 dst_link_failure(skb);
675 kfree_skb(skb);
676}
677
678/* Called with locked neigh: either read or both */
679
680static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
681{
682 struct in6_addr *saddr = NULL;
683 struct in6_addr mcaddr;
684 struct net_device *dev = neigh->dev;
685 struct in6_addr *target = (struct in6_addr *)&neigh->primary_key;
686 int probes = atomic_read(&neigh->probes);
687
688 if (skb && ipv6_chk_addr(&skb->nh.ipv6h->saddr, dev, 1))
689 saddr = &skb->nh.ipv6h->saddr;
690
691 if ((probes -= neigh->parms->ucast_probes) < 0) {
692 if (!(neigh->nud_state & NUD_VALID)) {
693 ND_PRINTK1(KERN_DEBUG
694 "%s(): trying to ucast probe in NUD_INVALID: "
Joe Perches46b86a22006-01-13 14:29:07 -0800695 NIP6_FMT "\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 __FUNCTION__,
697 NIP6(*target));
698 }
699 ndisc_send_ns(dev, neigh, target, target, saddr);
700 } else if ((probes -= neigh->parms->app_probes) < 0) {
701#ifdef CONFIG_ARPD
702 neigh_app_ns(neigh);
703#endif
704 } else {
705 addrconf_addr_solict_mult(target, &mcaddr);
706 ndisc_send_ns(dev, NULL, target, &mcaddr, saddr);
707 }
708}
709
710static void ndisc_recv_ns(struct sk_buff *skb)
711{
712 struct nd_msg *msg = (struct nd_msg *)skb->h.raw;
713 struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
714 struct in6_addr *daddr = &skb->nh.ipv6h->daddr;
715 u8 *lladdr = NULL;
716 u32 ndoptlen = skb->tail - msg->opt;
717 struct ndisc_options ndopts;
718 struct net_device *dev = skb->dev;
719 struct inet6_ifaddr *ifp;
720 struct inet6_dev *idev = NULL;
721 struct neighbour *neigh;
722 int dad = ipv6_addr_any(saddr);
723 int inc;
724
725 if (ipv6_addr_is_multicast(&msg->target)) {
726 ND_PRINTK2(KERN_WARNING
727 "ICMPv6 NS: multicast target address");
728 return;
729 }
730
731 /*
732 * RFC2461 7.1.1:
733 * DAD has to be destined for solicited node multicast address.
734 */
735 if (dad &&
736 !(daddr->s6_addr32[0] == htonl(0xff020000) &&
737 daddr->s6_addr32[1] == htonl(0x00000000) &&
738 daddr->s6_addr32[2] == htonl(0x00000001) &&
739 daddr->s6_addr [12] == 0xff )) {
740 ND_PRINTK2(KERN_WARNING
741 "ICMPv6 NS: bad DAD packet (wrong destination)\n");
742 return;
743 }
744
745 if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts)) {
746 ND_PRINTK2(KERN_WARNING
747 "ICMPv6 NS: invalid ND options\n");
748 return;
749 }
750
751 if (ndopts.nd_opts_src_lladdr) {
752 lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr, dev);
753 if (!lladdr) {
754 ND_PRINTK2(KERN_WARNING
755 "ICMPv6 NS: invalid link-layer address length\n");
756 return;
757 }
758
759 /* RFC2461 7.1.1:
760 * If the IP source address is the unspecified address,
761 * there MUST NOT be source link-layer address option
762 * in the message.
763 */
764 if (dad) {
765 ND_PRINTK2(KERN_WARNING
766 "ICMPv6 NS: bad DAD packet (link-layer address option)\n");
767 return;
768 }
769 }
770
771 inc = ipv6_addr_is_multicast(daddr);
772
773 if ((ifp = ipv6_get_ifaddr(&msg->target, dev, 1)) != NULL) {
774 if (ifp->flags & IFA_F_TENTATIVE) {
775 /* Address is tentative. If the source
776 is unspecified address, it is someone
777 does DAD, otherwise we ignore solicitations
778 until DAD timer expires.
779 */
780 if (!dad)
781 goto out;
782 if (dev->type == ARPHRD_IEEE802_TR) {
783 unsigned char *sadr = skb->mac.raw;
784 if (((sadr[8] ^ dev->dev_addr[0]) & 0x7f) == 0 &&
785 sadr[9] == dev->dev_addr[1] &&
786 sadr[10] == dev->dev_addr[2] &&
787 sadr[11] == dev->dev_addr[3] &&
788 sadr[12] == dev->dev_addr[4] &&
789 sadr[13] == dev->dev_addr[5]) {
790 /* looped-back to us */
791 goto out;
792 }
793 }
794 addrconf_dad_failure(ifp);
795 return;
796 }
797
798 idev = ifp->idev;
799 } else {
800 idev = in6_dev_get(dev);
801 if (!idev) {
802 /* XXX: count this drop? */
803 return;
804 }
805
806 if (ipv6_chk_acast_addr(dev, &msg->target) ||
807 (idev->cnf.forwarding &&
808 pneigh_lookup(&nd_tbl, &msg->target, dev, 0))) {
Patrick McHardya61bbcf2005-08-14 17:24:31 -0700809 if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 skb->pkt_type != PACKET_HOST &&
811 inc != 0 &&
812 idev->nd_parms->proxy_delay != 0) {
813 /*
814 * for anycast or proxy,
815 * sender should delay its response
816 * by a random time between 0 and
817 * MAX_ANYCAST_DELAY_TIME seconds.
818 * (RFC2461) -- yoshfuji
819 */
820 struct sk_buff *n = skb_clone(skb, GFP_ATOMIC);
821 if (n)
822 pneigh_enqueue(&nd_tbl, idev->nd_parms, n);
823 goto out;
824 }
825 } else
826 goto out;
827 }
828
829 if (dad) {
830 struct in6_addr maddr;
831
832 ipv6_addr_all_nodes(&maddr);
833 ndisc_send_na(dev, NULL, &maddr, &msg->target,
834 idev->cnf.forwarding, 0, (ifp != NULL), 1);
835 goto out;
836 }
837
838 if (inc)
839 NEIGH_CACHE_STAT_INC(&nd_tbl, rcv_probes_mcast);
840 else
841 NEIGH_CACHE_STAT_INC(&nd_tbl, rcv_probes_ucast);
842
843 /*
844 * update / create cache entry
845 * for the source address
846 */
847 neigh = __neigh_lookup(&nd_tbl, saddr, dev,
848 !inc || lladdr || !dev->addr_len);
849 if (neigh)
850 neigh_update(neigh, lladdr, NUD_STALE,
851 NEIGH_UPDATE_F_WEAK_OVERRIDE|
852 NEIGH_UPDATE_F_OVERRIDE);
853 if (neigh || !dev->hard_header) {
854 ndisc_send_na(dev, neigh, saddr, &msg->target,
855 idev->cnf.forwarding,
856 1, (ifp != NULL && inc), inc);
857 if (neigh)
858 neigh_release(neigh);
859 }
860
861out:
862 if (ifp)
863 in6_ifa_put(ifp);
864 else
865 in6_dev_put(idev);
866
867 return;
868}
869
870static void ndisc_recv_na(struct sk_buff *skb)
871{
872 struct nd_msg *msg = (struct nd_msg *)skb->h.raw;
873 struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
874 struct in6_addr *daddr = &skb->nh.ipv6h->daddr;
875 u8 *lladdr = NULL;
876 u32 ndoptlen = skb->tail - msg->opt;
877 struct ndisc_options ndopts;
878 struct net_device *dev = skb->dev;
879 struct inet6_ifaddr *ifp;
880 struct neighbour *neigh;
881
882 if (skb->len < sizeof(struct nd_msg)) {
883 ND_PRINTK2(KERN_WARNING
884 "ICMPv6 NA: packet too short\n");
885 return;
886 }
887
888 if (ipv6_addr_is_multicast(&msg->target)) {
889 ND_PRINTK2(KERN_WARNING
890 "ICMPv6 NA: target address is multicast.\n");
891 return;
892 }
893
894 if (ipv6_addr_is_multicast(daddr) &&
895 msg->icmph.icmp6_solicited) {
896 ND_PRINTK2(KERN_WARNING
897 "ICMPv6 NA: solicited NA is multicasted.\n");
898 return;
899 }
900
901 if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts)) {
902 ND_PRINTK2(KERN_WARNING
903 "ICMPv6 NS: invalid ND option\n");
904 return;
905 }
906 if (ndopts.nd_opts_tgt_lladdr) {
907 lladdr = ndisc_opt_addr_data(ndopts.nd_opts_tgt_lladdr, dev);
908 if (!lladdr) {
909 ND_PRINTK2(KERN_WARNING
910 "ICMPv6 NA: invalid link-layer address length\n");
911 return;
912 }
913 }
914 if ((ifp = ipv6_get_ifaddr(&msg->target, dev, 1))) {
915 if (ifp->flags & IFA_F_TENTATIVE) {
916 addrconf_dad_failure(ifp);
917 return;
918 }
919 /* What should we make now? The advertisement
920 is invalid, but ndisc specs say nothing
921 about it. It could be misconfiguration, or
922 an smart proxy agent tries to help us :-)
923 */
924 ND_PRINTK1(KERN_WARNING
925 "ICMPv6 NA: someone advertises our address on %s!\n",
926 ifp->idev->dev->name);
927 in6_ifa_put(ifp);
928 return;
929 }
930 neigh = neigh_lookup(&nd_tbl, &msg->target, dev);
931
932 if (neigh) {
933 u8 old_flags = neigh->flags;
934
935 if (neigh->nud_state & NUD_FAILED)
936 goto out;
937
938 neigh_update(neigh, lladdr,
939 msg->icmph.icmp6_solicited ? NUD_REACHABLE : NUD_STALE,
940 NEIGH_UPDATE_F_WEAK_OVERRIDE|
941 (msg->icmph.icmp6_override ? NEIGH_UPDATE_F_OVERRIDE : 0)|
942 NEIGH_UPDATE_F_OVERRIDE_ISROUTER|
943 (msg->icmph.icmp6_router ? NEIGH_UPDATE_F_ISROUTER : 0));
944
945 if ((old_flags & ~neigh->flags) & NTF_ROUTER) {
946 /*
947 * Change: router to host
948 */
949 struct rt6_info *rt;
950 rt = rt6_get_dflt_router(saddr, dev);
951 if (rt)
Jamal Hadi Salim0d51aa82005-06-21 13:51:04 -0700952 ip6_del_rt(rt, NULL, NULL, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 }
954
955out:
956 neigh_release(neigh);
957 }
958}
959
960static void ndisc_recv_rs(struct sk_buff *skb)
961{
962 struct rs_msg *rs_msg = (struct rs_msg *) skb->h.raw;
963 unsigned long ndoptlen = skb->len - sizeof(*rs_msg);
964 struct neighbour *neigh;
965 struct inet6_dev *idev;
966 struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
967 struct ndisc_options ndopts;
968 u8 *lladdr = NULL;
969
970 if (skb->len < sizeof(*rs_msg))
971 return;
972
973 idev = in6_dev_get(skb->dev);
974 if (!idev) {
975 if (net_ratelimit())
976 ND_PRINTK1("ICMP6 RS: can't find in6 device\n");
977 return;
978 }
979
980 /* Don't accept RS if we're not in router mode */
981 if (!idev->cnf.forwarding)
982 goto out;
983
984 /*
985 * Don't update NCE if src = ::;
986 * this implies that the source node has no ip address assigned yet.
987 */
988 if (ipv6_addr_any(saddr))
989 goto out;
990
991 /* Parse ND options */
992 if (!ndisc_parse_options(rs_msg->opt, ndoptlen, &ndopts)) {
993 if (net_ratelimit())
994 ND_PRINTK2("ICMP6 NS: invalid ND option, ignored\n");
995 goto out;
996 }
997
998 if (ndopts.nd_opts_src_lladdr) {
999 lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr,
1000 skb->dev);
1001 if (!lladdr)
1002 goto out;
1003 }
1004
1005 neigh = __neigh_lookup(&nd_tbl, saddr, skb->dev, 1);
1006 if (neigh) {
1007 neigh_update(neigh, lladdr, NUD_STALE,
1008 NEIGH_UPDATE_F_WEAK_OVERRIDE|
1009 NEIGH_UPDATE_F_OVERRIDE|
1010 NEIGH_UPDATE_F_OVERRIDE_ISROUTER);
1011 neigh_release(neigh);
1012 }
1013out:
1014 in6_dev_put(idev);
1015}
1016
1017static void ndisc_router_discovery(struct sk_buff *skb)
1018{
1019 struct ra_msg *ra_msg = (struct ra_msg *) skb->h.raw;
1020 struct neighbour *neigh = NULL;
1021 struct inet6_dev *in6_dev;
YOSHIFUJI Hideaki65f5c7c2006-03-20 16:55:08 -08001022 struct rt6_info *rt = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 int lifetime;
1024 struct ndisc_options ndopts;
1025 int optlen;
YOSHIFUJI Hideakiebacaaa2006-03-20 17:04:53 -08001026 unsigned int pref = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027
1028 __u8 * opt = (__u8 *)(ra_msg + 1);
1029
1030 optlen = (skb->tail - skb->h.raw) - sizeof(struct ra_msg);
1031
1032 if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr) & IPV6_ADDR_LINKLOCAL)) {
1033 ND_PRINTK2(KERN_WARNING
1034 "ICMPv6 RA: source address is not link-local.\n");
1035 return;
1036 }
1037 if (optlen < 0) {
1038 ND_PRINTK2(KERN_WARNING
1039 "ICMPv6 RA: packet too short\n");
1040 return;
1041 }
1042
1043 /*
1044 * set the RA_RECV flag in the interface
1045 */
1046
1047 in6_dev = in6_dev_get(skb->dev);
1048 if (in6_dev == NULL) {
1049 ND_PRINTK0(KERN_ERR
1050 "ICMPv6 RA: can't find inet6 device for %s.\n",
1051 skb->dev->name);
1052 return;
1053 }
1054 if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra) {
1055 in6_dev_put(in6_dev);
1056 return;
1057 }
1058
1059 if (!ndisc_parse_options(opt, optlen, &ndopts)) {
1060 in6_dev_put(in6_dev);
1061 ND_PRINTK2(KERN_WARNING
1062 "ICMP6 RA: invalid ND options\n");
1063 return;
1064 }
1065
1066 if (in6_dev->if_flags & IF_RS_SENT) {
1067 /*
1068 * flag that an RA was received after an RS was sent
1069 * out on this interface.
1070 */
1071 in6_dev->if_flags |= IF_RA_RCVD;
1072 }
1073
1074 /*
1075 * Remember the managed/otherconf flags from most recently
1076 * received RA message (RFC 2462) -- yoshfuji
1077 */
1078 in6_dev->if_flags = (in6_dev->if_flags & ~(IF_RA_MANAGED |
1079 IF_RA_OTHERCONF)) |
1080 (ra_msg->icmph.icmp6_addrconf_managed ?
1081 IF_RA_MANAGED : 0) |
1082 (ra_msg->icmph.icmp6_addrconf_other ?
1083 IF_RA_OTHERCONF : 0);
1084
YOSHIFUJI Hideaki65f5c7c2006-03-20 16:55:08 -08001085 if (!in6_dev->cnf.accept_ra_defrtr)
1086 goto skip_defrtr;
1087
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime);
1089
YOSHIFUJI Hideakiebacaaa2006-03-20 17:04:53 -08001090#ifdef CONFIG_IPV6_ROUTER_PREF
1091 pref = ra_msg->icmph.icmp6_router_pref;
1092 /* 10b is handled as if it were 00b (medium) */
YOSHIFUJI Hideaki930d6ff2006-03-20 17:05:30 -08001093 if (pref == ICMPV6_ROUTER_PREF_INVALID ||
1094 in6_dev->cnf.accept_ra_rtr_pref)
YOSHIFUJI Hideakiebacaaa2006-03-20 17:04:53 -08001095 pref = ICMPV6_ROUTER_PREF_MEDIUM;
1096#endif
1097
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 rt = rt6_get_dflt_router(&skb->nh.ipv6h->saddr, skb->dev);
1099
1100 if (rt)
1101 neigh = rt->rt6i_nexthop;
1102
1103 if (rt && lifetime == 0) {
1104 neigh_clone(neigh);
Jamal Hadi Salim0d51aa82005-06-21 13:51:04 -07001105 ip6_del_rt(rt, NULL, NULL, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106 rt = NULL;
1107 }
1108
1109 if (rt == NULL && lifetime) {
1110 ND_PRINTK3(KERN_DEBUG
1111 "ICMPv6 RA: adding default router.\n");
1112
YOSHIFUJI Hideakiebacaaa2006-03-20 17:04:53 -08001113 rt = rt6_add_dflt_router(&skb->nh.ipv6h->saddr, skb->dev, pref);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114 if (rt == NULL) {
1115 ND_PRINTK0(KERN_ERR
1116 "ICMPv6 RA: %s() failed to add default route.\n",
1117 __FUNCTION__);
1118 in6_dev_put(in6_dev);
1119 return;
1120 }
1121
1122 neigh = rt->rt6i_nexthop;
1123 if (neigh == NULL) {
1124 ND_PRINTK0(KERN_ERR
1125 "ICMPv6 RA: %s() got default router without neighbour.\n",
1126 __FUNCTION__);
1127 dst_release(&rt->u.dst);
1128 in6_dev_put(in6_dev);
1129 return;
1130 }
1131 neigh->flags |= NTF_ROUTER;
YOSHIFUJI Hideakiebacaaa2006-03-20 17:04:53 -08001132 } else if (rt) {
1133 rt->rt6i_flags |= (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 }
1135
1136 if (rt)
1137 rt->rt6i_expires = jiffies + (HZ * lifetime);
1138
1139 if (ra_msg->icmph.icmp6_hop_limit) {
1140 in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit;
1141 if (rt)
1142 rt->u.dst.metrics[RTAX_HOPLIMIT-1] = ra_msg->icmph.icmp6_hop_limit;
1143 }
1144
YOSHIFUJI Hideaki65f5c7c2006-03-20 16:55:08 -08001145skip_defrtr:
1146
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 /*
1148 * Update Reachable Time and Retrans Timer
1149 */
1150
1151 if (in6_dev->nd_parms) {
1152 unsigned long rtime = ntohl(ra_msg->retrans_timer);
1153
1154 if (rtime && rtime/1000 < MAX_SCHEDULE_TIMEOUT/HZ) {
1155 rtime = (rtime*HZ)/1000;
1156 if (rtime < HZ/10)
1157 rtime = HZ/10;
1158 in6_dev->nd_parms->retrans_time = rtime;
1159 in6_dev->tstamp = jiffies;
1160 inet6_ifinfo_notify(RTM_NEWLINK, in6_dev);
1161 }
1162
1163 rtime = ntohl(ra_msg->reachable_time);
1164 if (rtime && rtime/1000 < MAX_SCHEDULE_TIMEOUT/(3*HZ)) {
1165 rtime = (rtime*HZ)/1000;
1166
1167 if (rtime < HZ/10)
1168 rtime = HZ/10;
1169
1170 if (rtime != in6_dev->nd_parms->base_reachable_time) {
1171 in6_dev->nd_parms->base_reachable_time = rtime;
1172 in6_dev->nd_parms->gc_staletime = 3 * rtime;
1173 in6_dev->nd_parms->reachable_time = neigh_rand_reach_time(rtime);
1174 in6_dev->tstamp = jiffies;
1175 inet6_ifinfo_notify(RTM_NEWLINK, in6_dev);
1176 }
1177 }
1178 }
1179
1180 /*
1181 * Process options.
1182 */
1183
1184 if (!neigh)
1185 neigh = __neigh_lookup(&nd_tbl, &skb->nh.ipv6h->saddr,
1186 skb->dev, 1);
1187 if (neigh) {
1188 u8 *lladdr = NULL;
1189 if (ndopts.nd_opts_src_lladdr) {
1190 lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr,
1191 skb->dev);
1192 if (!lladdr) {
1193 ND_PRINTK2(KERN_WARNING
1194 "ICMPv6 RA: invalid link-layer address length\n");
1195 goto out;
1196 }
1197 }
1198 neigh_update(neigh, lladdr, NUD_STALE,
1199 NEIGH_UPDATE_F_WEAK_OVERRIDE|
1200 NEIGH_UPDATE_F_OVERRIDE|
1201 NEIGH_UPDATE_F_OVERRIDE_ISROUTER|
1202 NEIGH_UPDATE_F_ISROUTER);
1203 }
1204
YOSHIFUJI Hideakic4fd30e2006-03-20 16:55:26 -08001205 if (in6_dev->cnf.accept_ra_pinfo && ndopts.nd_opts_pi) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 struct nd_opt_hdr *p;
1207 for (p = ndopts.nd_opts_pi;
1208 p;
1209 p = ndisc_next_option(p, ndopts.nd_opts_pi_end)) {
1210 addrconf_prefix_rcv(skb->dev, (u8*)p, (p->nd_opt_len) << 3);
1211 }
1212 }
1213
1214 if (ndopts.nd_opts_mtu) {
1215 u32 mtu;
1216
1217 memcpy(&mtu, ((u8*)(ndopts.nd_opts_mtu+1))+2, sizeof(mtu));
1218 mtu = ntohl(mtu);
1219
1220 if (mtu < IPV6_MIN_MTU || mtu > skb->dev->mtu) {
1221 ND_PRINTK2(KERN_WARNING
1222 "ICMPv6 RA: invalid mtu: %d\n",
1223 mtu);
1224 } else if (in6_dev->cnf.mtu6 != mtu) {
1225 in6_dev->cnf.mtu6 = mtu;
1226
1227 if (rt)
1228 rt->u.dst.metrics[RTAX_MTU-1] = mtu;
1229
1230 rt6_mtu_change(skb->dev, mtu);
1231 }
1232 }
1233
1234 if (ndopts.nd_opts_tgt_lladdr || ndopts.nd_opts_rh) {
1235 ND_PRINTK2(KERN_WARNING
1236 "ICMPv6 RA: invalid RA options");
1237 }
1238out:
1239 if (rt)
1240 dst_release(&rt->u.dst);
1241 else if (neigh)
1242 neigh_release(neigh);
1243 in6_dev_put(in6_dev);
1244}
1245
1246static void ndisc_redirect_rcv(struct sk_buff *skb)
1247{
1248 struct inet6_dev *in6_dev;
1249 struct icmp6hdr *icmph;
1250 struct in6_addr *dest;
1251 struct in6_addr *target; /* new first hop to destination */
1252 struct neighbour *neigh;
1253 int on_link = 0;
1254 struct ndisc_options ndopts;
1255 int optlen;
1256 u8 *lladdr = NULL;
1257
1258 if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr) & IPV6_ADDR_LINKLOCAL)) {
1259 ND_PRINTK2(KERN_WARNING
1260 "ICMPv6 Redirect: source address is not link-local.\n");
1261 return;
1262 }
1263
1264 optlen = skb->tail - skb->h.raw;
1265 optlen -= sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr);
1266
1267 if (optlen < 0) {
1268 ND_PRINTK2(KERN_WARNING
1269 "ICMPv6 Redirect: packet too short\n");
1270 return;
1271 }
1272
1273 icmph = (struct icmp6hdr *) skb->h.raw;
1274 target = (struct in6_addr *) (icmph + 1);
1275 dest = target + 1;
1276
1277 if (ipv6_addr_is_multicast(dest)) {
1278 ND_PRINTK2(KERN_WARNING
1279 "ICMPv6 Redirect: destination address is multicast.\n");
1280 return;
1281 }
1282
1283 if (ipv6_addr_equal(dest, target)) {
1284 on_link = 1;
1285 } else if (!(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) {
1286 ND_PRINTK2(KERN_WARNING
1287 "ICMPv6 Redirect: target address is not link-local.\n");
1288 return;
1289 }
1290
1291 in6_dev = in6_dev_get(skb->dev);
1292 if (!in6_dev)
1293 return;
1294 if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_redirects) {
1295 in6_dev_put(in6_dev);
1296 return;
1297 }
1298
1299 /* RFC2461 8.1:
1300 * The IP source address of the Redirect MUST be the same as the current
1301 * first-hop router for the specified ICMP Destination Address.
1302 */
1303
1304 if (!ndisc_parse_options((u8*)(dest + 1), optlen, &ndopts)) {
1305 ND_PRINTK2(KERN_WARNING
1306 "ICMPv6 Redirect: invalid ND options\n");
1307 in6_dev_put(in6_dev);
1308 return;
1309 }
1310 if (ndopts.nd_opts_tgt_lladdr) {
1311 lladdr = ndisc_opt_addr_data(ndopts.nd_opts_tgt_lladdr,
1312 skb->dev);
1313 if (!lladdr) {
1314 ND_PRINTK2(KERN_WARNING
1315 "ICMPv6 Redirect: invalid link-layer address length\n");
1316 in6_dev_put(in6_dev);
1317 return;
1318 }
1319 }
1320
1321 neigh = __neigh_lookup(&nd_tbl, target, skb->dev, 1);
1322 if (neigh) {
1323 rt6_redirect(dest, &skb->nh.ipv6h->saddr, neigh, lladdr,
1324 on_link);
1325 neigh_release(neigh);
1326 }
1327 in6_dev_put(in6_dev);
1328}
1329
1330void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
1331 struct in6_addr *target)
1332{
1333 struct sock *sk = ndisc_socket->sk;
1334 int len = sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr);
1335 struct sk_buff *buff;
1336 struct icmp6hdr *icmph;
1337 struct in6_addr saddr_buf;
1338 struct in6_addr *addrp;
1339 struct net_device *dev;
1340 struct rt6_info *rt;
1341 struct dst_entry *dst;
1342 struct inet6_dev *idev;
1343 struct flowi fl;
1344 u8 *opt;
1345 int rd_len;
1346 int err;
1347 int hlen;
1348 u8 ha_buf[MAX_ADDR_LEN], *ha = NULL;
1349
1350 dev = skb->dev;
1351
1352 if (ipv6_get_lladdr(dev, &saddr_buf)) {
1353 ND_PRINTK2(KERN_WARNING
1354 "ICMPv6 Redirect: no link-local address on %s\n",
1355 dev->name);
1356 return;
1357 }
1358
1359 ndisc_flow_init(&fl, NDISC_REDIRECT, &saddr_buf, &skb->nh.ipv6h->saddr);
1360
1361 dst = ip6_route_output(NULL, &fl);
1362 if (dst == NULL)
1363 return;
1364
1365 err = xfrm_lookup(&dst, &fl, NULL, 0);
Patrick McHardye104411b2005-09-08 15:11:55 -07001366 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368
1369 rt = (struct rt6_info *) dst;
1370
1371 if (rt->rt6i_flags & RTF_GATEWAY) {
1372 ND_PRINTK2(KERN_WARNING
1373 "ICMPv6 Redirect: destination is not a neighbour.\n");
1374 dst_release(dst);
1375 return;
1376 }
1377 if (!xrlim_allow(dst, 1*HZ)) {
1378 dst_release(dst);
1379 return;
1380 }
1381
1382 if (dev->addr_len) {
1383 read_lock_bh(&neigh->lock);
1384 if (neigh->nud_state & NUD_VALID) {
1385 memcpy(ha_buf, neigh->ha, dev->addr_len);
1386 read_unlock_bh(&neigh->lock);
1387 ha = ha_buf;
1388 len += ndisc_opt_addr_space(dev);
1389 } else
1390 read_unlock_bh(&neigh->lock);
1391 }
1392
1393 rd_len = min_t(unsigned int,
1394 IPV6_MIN_MTU-sizeof(struct ipv6hdr)-len, skb->len + 8);
1395 rd_len &= ~0x7;
1396 len += rd_len;
1397
1398 buff = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
1399 1, &err);
1400 if (buff == NULL) {
1401 ND_PRINTK0(KERN_ERR
1402 "ICMPv6 Redirect: %s() failed to allocate an skb.\n",
1403 __FUNCTION__);
1404 dst_release(dst);
1405 return;
1406 }
1407
1408 hlen = 0;
1409
1410 skb_reserve(buff, LL_RESERVED_SPACE(dev));
1411 ip6_nd_hdr(sk, buff, dev, &saddr_buf, &skb->nh.ipv6h->saddr,
1412 IPPROTO_ICMPV6, len);
1413
1414 icmph = (struct icmp6hdr *)skb_put(buff, len);
1415 buff->h.raw = (unsigned char*)icmph;
1416
1417 memset(icmph, 0, sizeof(struct icmp6hdr));
1418 icmph->icmp6_type = NDISC_REDIRECT;
1419
1420 /*
1421 * copy target and destination addresses
1422 */
1423
1424 addrp = (struct in6_addr *)(icmph + 1);
1425 ipv6_addr_copy(addrp, target);
1426 addrp++;
1427 ipv6_addr_copy(addrp, &skb->nh.ipv6h->daddr);
1428
1429 opt = (u8*) (addrp + 1);
1430
1431 /*
1432 * include target_address option
1433 */
1434
1435 if (ha)
1436 opt = ndisc_fill_addr_option(opt, ND_OPT_TARGET_LL_ADDR, ha,
1437 dev->addr_len, dev->type);
1438
1439 /*
1440 * build redirect option and copy skb over to the new packet.
1441 */
1442
1443 memset(opt, 0, 8);
1444 *(opt++) = ND_OPT_REDIRECT_HDR;
1445 *(opt++) = (rd_len >> 3);
1446 opt += 6;
1447
1448 memcpy(opt, skb->nh.ipv6h, rd_len - 8);
1449
1450 icmph->icmp6_cksum = csum_ipv6_magic(&saddr_buf, &skb->nh.ipv6h->saddr,
1451 len, IPPROTO_ICMPV6,
1452 csum_partial((u8 *) icmph, len, 0));
1453
1454 buff->dst = dst;
1455 idev = in6_dev_get(dst->dev);
1456 IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
1457 err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, buff, NULL, dst->dev, dst_output);
1458 if (!err) {
1459 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTREDIRECTS);
1460 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
1461 }
1462
1463 if (likely(idev != NULL))
1464 in6_dev_put(idev);
1465}
1466
1467static void pndisc_redo(struct sk_buff *skb)
1468{
YOSHIFUJI Hideaki140e26fc2005-10-05 12:11:41 -07001469 ndisc_recv_ns(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 kfree_skb(skb);
1471}
1472
1473int ndisc_rcv(struct sk_buff *skb)
1474{
1475 struct nd_msg *msg;
1476
1477 if (!pskb_may_pull(skb, skb->len))
1478 return 0;
1479
1480 msg = (struct nd_msg *) skb->h.raw;
1481
1482 __skb_push(skb, skb->data-skb->h.raw);
1483
1484 if (skb->nh.ipv6h->hop_limit != 255) {
1485 ND_PRINTK2(KERN_WARNING
1486 "ICMPv6 NDISC: invalid hop-limit: %d\n",
1487 skb->nh.ipv6h->hop_limit);
1488 return 0;
1489 }
1490
1491 if (msg->icmph.icmp6_code != 0) {
1492 ND_PRINTK2(KERN_WARNING
1493 "ICMPv6 NDISC: invalid ICMPv6 code: %d\n",
1494 msg->icmph.icmp6_code);
1495 return 0;
1496 }
1497
Patrick McHardya61bbcf2005-08-14 17:24:31 -07001498 memset(NEIGH_CB(skb), 0, sizeof(struct neighbour_cb));
1499
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 switch (msg->icmph.icmp6_type) {
1501 case NDISC_NEIGHBOUR_SOLICITATION:
1502 ndisc_recv_ns(skb);
1503 break;
1504
1505 case NDISC_NEIGHBOUR_ADVERTISEMENT:
1506 ndisc_recv_na(skb);
1507 break;
1508
1509 case NDISC_ROUTER_SOLICITATION:
1510 ndisc_recv_rs(skb);
1511 break;
1512
1513 case NDISC_ROUTER_ADVERTISEMENT:
1514 ndisc_router_discovery(skb);
1515 break;
1516
1517 case NDISC_REDIRECT:
1518 ndisc_redirect_rcv(skb);
1519 break;
1520 };
1521
1522 return 0;
1523}
1524
1525static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
1526{
1527 struct net_device *dev = ptr;
1528
1529 switch (event) {
1530 case NETDEV_CHANGEADDR:
1531 neigh_changeaddr(&nd_tbl, dev);
1532 fib6_run_gc(~0UL);
1533 break;
1534 case NETDEV_DOWN:
1535 neigh_ifdown(&nd_tbl, dev);
1536 fib6_run_gc(~0UL);
1537 break;
1538 default:
1539 break;
1540 }
1541
1542 return NOTIFY_DONE;
1543}
1544
1545static struct notifier_block ndisc_netdev_notifier = {
1546 .notifier_call = ndisc_netdev_event,
1547};
1548
1549#ifdef CONFIG_SYSCTL
1550static void ndisc_warn_deprecated_sysctl(struct ctl_table *ctl,
1551 const char *func, const char *dev_name)
1552{
1553 static char warncomm[TASK_COMM_LEN];
1554 static int warned;
1555 if (strcmp(warncomm, current->comm) && warned < 5) {
1556 strcpy(warncomm, current->comm);
1557 printk(KERN_WARNING
1558 "process `%s' is using deprecated sysctl (%s) "
1559 "net.ipv6.neigh.%s.%s; "
1560 "Use net.ipv6.neigh.%s.%s_ms "
1561 "instead.\n",
1562 warncomm, func,
1563 dev_name, ctl->procname,
1564 dev_name, ctl->procname);
1565 warned++;
1566 }
1567}
1568
1569int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, struct file * filp, void __user *buffer, size_t *lenp, loff_t *ppos)
1570{
1571 struct net_device *dev = ctl->extra1;
1572 struct inet6_dev *idev;
1573 int ret;
1574
1575 if (ctl->ctl_name == NET_NEIGH_RETRANS_TIME ||
1576 ctl->ctl_name == NET_NEIGH_REACHABLE_TIME)
1577 ndisc_warn_deprecated_sysctl(ctl, "syscall", dev ? dev->name : "default");
1578
1579 switch (ctl->ctl_name) {
1580 case NET_NEIGH_RETRANS_TIME:
1581 ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
1582 break;
1583 case NET_NEIGH_REACHABLE_TIME:
1584 ret = proc_dointvec_jiffies(ctl, write,
1585 filp, buffer, lenp, ppos);
1586 break;
1587 case NET_NEIGH_RETRANS_TIME_MS:
1588 case NET_NEIGH_REACHABLE_TIME_MS:
1589 ret = proc_dointvec_ms_jiffies(ctl, write,
1590 filp, buffer, lenp, ppos);
1591 break;
1592 default:
1593 ret = -1;
1594 }
1595
1596 if (write && ret == 0 && dev && (idev = in6_dev_get(dev)) != NULL) {
1597 if (ctl->ctl_name == NET_NEIGH_REACHABLE_TIME ||
1598 ctl->ctl_name == NET_NEIGH_REACHABLE_TIME_MS)
1599 idev->nd_parms->reachable_time = neigh_rand_reach_time(idev->nd_parms->base_reachable_time);
1600 idev->tstamp = jiffies;
1601 inet6_ifinfo_notify(RTM_NEWLINK, idev);
1602 in6_dev_put(idev);
1603 }
1604 return ret;
1605}
1606
1607static int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl, int __user *name,
1608 int nlen, void __user *oldval,
1609 size_t __user *oldlenp,
1610 void __user *newval, size_t newlen,
1611 void **context)
1612{
1613 struct net_device *dev = ctl->extra1;
1614 struct inet6_dev *idev;
1615 int ret;
1616
1617 if (ctl->ctl_name == NET_NEIGH_RETRANS_TIME ||
1618 ctl->ctl_name == NET_NEIGH_REACHABLE_TIME)
1619 ndisc_warn_deprecated_sysctl(ctl, "procfs", dev ? dev->name : "default");
1620
1621 switch (ctl->ctl_name) {
1622 case NET_NEIGH_REACHABLE_TIME:
1623 ret = sysctl_jiffies(ctl, name, nlen,
1624 oldval, oldlenp, newval, newlen,
1625 context);
1626 break;
1627 case NET_NEIGH_RETRANS_TIME_MS:
1628 case NET_NEIGH_REACHABLE_TIME_MS:
1629 ret = sysctl_ms_jiffies(ctl, name, nlen,
1630 oldval, oldlenp, newval, newlen,
1631 context);
1632 break;
1633 default:
1634 ret = 0;
1635 }
1636
1637 if (newval && newlen && ret > 0 &&
1638 dev && (idev = in6_dev_get(dev)) != NULL) {
1639 if (ctl->ctl_name == NET_NEIGH_REACHABLE_TIME ||
1640 ctl->ctl_name == NET_NEIGH_REACHABLE_TIME_MS)
1641 idev->nd_parms->reachable_time = neigh_rand_reach_time(idev->nd_parms->base_reachable_time);
1642 idev->tstamp = jiffies;
1643 inet6_ifinfo_notify(RTM_NEWLINK, idev);
1644 in6_dev_put(idev);
1645 }
1646
1647 return ret;
1648}
1649
1650#endif
1651
1652int __init ndisc_init(struct net_proto_family *ops)
1653{
1654 struct ipv6_pinfo *np;
1655 struct sock *sk;
1656 int err;
1657
1658 err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &ndisc_socket);
1659 if (err < 0) {
1660 ND_PRINTK0(KERN_ERR
1661 "ICMPv6 NDISC: Failed to initialize the control socket (err %d).\n",
1662 err);
1663 ndisc_socket = NULL; /* For safety. */
1664 return err;
1665 }
1666
1667 sk = ndisc_socket->sk;
1668 np = inet6_sk(sk);
1669 sk->sk_allocation = GFP_ATOMIC;
1670 np->hop_limit = 255;
1671 /* Do not loopback ndisc messages */
1672 np->mc_loop = 0;
1673 sk->sk_prot->unhash(sk);
1674
1675 /*
1676 * Initialize the neighbour table
1677 */
1678
1679 neigh_table_init(&nd_tbl);
1680
1681#ifdef CONFIG_SYSCTL
1682 neigh_sysctl_register(NULL, &nd_tbl.parms, NET_IPV6, NET_IPV6_NEIGH,
1683 "ipv6",
1684 &ndisc_ifinfo_sysctl_change,
1685 &ndisc_ifinfo_sysctl_strategy);
1686#endif
1687
1688 register_netdevice_notifier(&ndisc_netdev_notifier);
1689 return 0;
1690}
1691
1692void ndisc_cleanup(void)
1693{
1694#ifdef CONFIG_SYSCTL
1695 neigh_sysctl_unregister(&nd_tbl.parms);
1696#endif
1697 neigh_table_clear(&nd_tbl);
1698 sock_release(ndisc_socket);
1699 ndisc_socket = NULL; /* For safety. */
1700}