aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ndisc.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /net/ipv6/ndisc.c
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'net/ipv6/ndisc.c')
-rw-r--r--net/ipv6/ndisc.c1690
1 files changed, 1690 insertions, 0 deletions
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
new file mode 100644
index 000000000000..7c291f4e9edc
--- /dev/null
+++ b/net/ipv6/ndisc.c
@@ -0,0 +1,1690 @@
1/*
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);
450 if (err < 0) {
451 dst_release(dst);
452 return;
453 }
454
455 if (inc_opt) {
456 if (dev->addr_len)
457 len += ndisc_opt_addr_space(dev);
458 else
459 inc_opt = 0;
460 }
461
462 skb = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
463 1, &err);
464
465 if (skb == NULL) {
466 ND_PRINTK0(KERN_ERR
467 "ICMPv6 NA: %s() failed to allocate an skb.\n",
468 __FUNCTION__);
469 dst_release(dst);
470 return;
471 }
472
473 skb_reserve(skb, LL_RESERVED_SPACE(dev));
474 ip6_nd_hdr(sk, skb, dev, src_addr, daddr, IPPROTO_ICMPV6, len);
475
476 msg = (struct nd_msg *)skb_put(skb, len);
477 skb->h.raw = (unsigned char*)msg;
478
479 msg->icmph.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT;
480 msg->icmph.icmp6_code = 0;
481 msg->icmph.icmp6_cksum = 0;
482
483 msg->icmph.icmp6_unused = 0;
484 msg->icmph.icmp6_router = router;
485 msg->icmph.icmp6_solicited = solicited;
486 msg->icmph.icmp6_override = !!override;
487
488 /* Set the target address. */
489 ipv6_addr_copy(&msg->target, solicited_addr);
490
491 if (inc_opt)
492 ndisc_fill_addr_option(msg->opt, ND_OPT_TARGET_LL_ADDR, dev->dev_addr,
493 dev->addr_len, dev->type);
494
495 /* checksum */
496 msg->icmph.icmp6_cksum = csum_ipv6_magic(src_addr, daddr, len,
497 IPPROTO_ICMPV6,
498 csum_partial((__u8 *) msg,
499 len, 0));
500
501 skb->dst = dst;
502 idev = in6_dev_get(dst->dev);
503 IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
504 err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
505 if (!err) {
506 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTNEIGHBORADVERTISEMENTS);
507 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
508 }
509
510 if (likely(idev != NULL))
511 in6_dev_put(idev);
512}
513
514void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
515 struct in6_addr *solicit,
516 struct in6_addr *daddr, struct in6_addr *saddr)
517{
518 struct flowi fl;
519 struct dst_entry* dst;
520 struct inet6_dev *idev;
521 struct sock *sk = ndisc_socket->sk;
522 struct sk_buff *skb;
523 struct nd_msg *msg;
524 struct in6_addr addr_buf;
525 int len;
526 int err;
527 int send_llinfo;
528
529 if (saddr == NULL) {
530 if (ipv6_get_lladdr(dev, &addr_buf))
531 return;
532 saddr = &addr_buf;
533 }
534
535 ndisc_flow_init(&fl, NDISC_NEIGHBOUR_SOLICITATION, saddr, daddr);
536
537 dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output);
538 if (!dst)
539 return;
540
541 err = xfrm_lookup(&dst, &fl, NULL, 0);
542 if (err < 0) {
543 dst_release(dst);
544 return;
545 }
546
547 len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
548 send_llinfo = dev->addr_len && !ipv6_addr_any(saddr);
549 if (send_llinfo)
550 len += ndisc_opt_addr_space(dev);
551
552 skb = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
553 1, &err);
554 if (skb == NULL) {
555 ND_PRINTK0(KERN_ERR
556 "ICMPv6 NA: %s() failed to allocate an skb.\n",
557 __FUNCTION__);
558 dst_release(dst);
559 return;
560 }
561
562 skb_reserve(skb, LL_RESERVED_SPACE(dev));
563 ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len);
564
565 msg = (struct nd_msg *)skb_put(skb, len);
566 skb->h.raw = (unsigned char*)msg;
567 msg->icmph.icmp6_type = NDISC_NEIGHBOUR_SOLICITATION;
568 msg->icmph.icmp6_code = 0;
569 msg->icmph.icmp6_cksum = 0;
570 msg->icmph.icmp6_unused = 0;
571
572 /* Set the target address. */
573 ipv6_addr_copy(&msg->target, solicit);
574
575 if (send_llinfo)
576 ndisc_fill_addr_option(msg->opt, ND_OPT_SOURCE_LL_ADDR, dev->dev_addr,
577 dev->addr_len, dev->type);
578
579 /* checksum */
580 msg->icmph.icmp6_cksum = csum_ipv6_magic(&skb->nh.ipv6h->saddr,
581 daddr, len,
582 IPPROTO_ICMPV6,
583 csum_partial((__u8 *) msg,
584 len, 0));
585 /* send it! */
586 skb->dst = dst;
587 idev = in6_dev_get(dst->dev);
588 IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
589 err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
590 if (!err) {
591 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTNEIGHBORSOLICITS);
592 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
593 }
594
595 if (likely(idev != NULL))
596 in6_dev_put(idev);
597}
598
599void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
600 struct in6_addr *daddr)
601{
602 struct flowi fl;
603 struct dst_entry* dst;
604 struct inet6_dev *idev;
605 struct sock *sk = ndisc_socket->sk;
606 struct sk_buff *skb;
607 struct icmp6hdr *hdr;
608 __u8 * opt;
609 int len;
610 int err;
611
612 ndisc_flow_init(&fl, NDISC_ROUTER_SOLICITATION, saddr, daddr);
613
614 dst = ndisc_dst_alloc(dev, NULL, daddr, ip6_output);
615 if (!dst)
616 return;
617
618 err = xfrm_lookup(&dst, &fl, NULL, 0);
619 if (err < 0) {
620 dst_release(dst);
621 return;
622 }
623
624 len = sizeof(struct icmp6hdr);
625 if (dev->addr_len)
626 len += ndisc_opt_addr_space(dev);
627
628 skb = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
629 1, &err);
630 if (skb == NULL) {
631 ND_PRINTK0(KERN_ERR
632 "ICMPv6 RS: %s() failed to allocate an skb.\n",
633 __FUNCTION__);
634 dst_release(dst);
635 return;
636 }
637
638 skb_reserve(skb, LL_RESERVED_SPACE(dev));
639 ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len);
640
641 hdr = (struct icmp6hdr *)skb_put(skb, len);
642 skb->h.raw = (unsigned char*)hdr;
643 hdr->icmp6_type = NDISC_ROUTER_SOLICITATION;
644 hdr->icmp6_code = 0;
645 hdr->icmp6_cksum = 0;
646 hdr->icmp6_unused = 0;
647
648 opt = (u8*) (hdr + 1);
649
650 if (dev->addr_len)
651 ndisc_fill_addr_option(opt, ND_OPT_SOURCE_LL_ADDR, dev->dev_addr,
652 dev->addr_len, dev->type);
653
654 /* checksum */
655 hdr->icmp6_cksum = csum_ipv6_magic(&skb->nh.ipv6h->saddr, daddr, len,
656 IPPROTO_ICMPV6,
657 csum_partial((__u8 *) hdr, len, 0));
658
659 /* send it! */
660 skb->dst = dst;
661 idev = in6_dev_get(dst->dev);
662 IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
663 err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
664 if (!err) {
665 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTROUTERSOLICITS);
666 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
667 }
668
669 if (likely(idev != NULL))
670 in6_dev_put(idev);
671}
672
673
674static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb)
675{
676 /*
677 * "The sender MUST return an ICMP
678 * destination unreachable"
679 */
680 dst_link_failure(skb);
681 kfree_skb(skb);
682}
683
684/* Called with locked neigh: either read or both */
685
686static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
687{
688 struct in6_addr *saddr = NULL;
689 struct in6_addr mcaddr;
690 struct net_device *dev = neigh->dev;
691 struct in6_addr *target = (struct in6_addr *)&neigh->primary_key;
692 int probes = atomic_read(&neigh->probes);
693
694 if (skb && ipv6_chk_addr(&skb->nh.ipv6h->saddr, dev, 1))
695 saddr = &skb->nh.ipv6h->saddr;
696
697 if ((probes -= neigh->parms->ucast_probes) < 0) {
698 if (!(neigh->nud_state & NUD_VALID)) {
699 ND_PRINTK1(KERN_DEBUG
700 "%s(): trying to ucast probe in NUD_INVALID: "
701 "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
702 __FUNCTION__,
703 NIP6(*target));
704 }
705 ndisc_send_ns(dev, neigh, target, target, saddr);
706 } else if ((probes -= neigh->parms->app_probes) < 0) {
707#ifdef CONFIG_ARPD
708 neigh_app_ns(neigh);
709#endif
710 } else {
711 addrconf_addr_solict_mult(target, &mcaddr);
712 ndisc_send_ns(dev, NULL, target, &mcaddr, saddr);
713 }
714}
715
716static void ndisc_recv_ns(struct sk_buff *skb)
717{
718 struct nd_msg *msg = (struct nd_msg *)skb->h.raw;
719 struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
720 struct in6_addr *daddr = &skb->nh.ipv6h->daddr;
721 u8 *lladdr = NULL;
722 u32 ndoptlen = skb->tail - msg->opt;
723 struct ndisc_options ndopts;
724 struct net_device *dev = skb->dev;
725 struct inet6_ifaddr *ifp;
726 struct inet6_dev *idev = NULL;
727 struct neighbour *neigh;
728 int dad = ipv6_addr_any(saddr);
729 int inc;
730
731 if (ipv6_addr_is_multicast(&msg->target)) {
732 ND_PRINTK2(KERN_WARNING
733 "ICMPv6 NS: multicast target address");
734 return;
735 }
736
737 /*
738 * RFC2461 7.1.1:
739 * DAD has to be destined for solicited node multicast address.
740 */
741 if (dad &&
742 !(daddr->s6_addr32[0] == htonl(0xff020000) &&
743 daddr->s6_addr32[1] == htonl(0x00000000) &&
744 daddr->s6_addr32[2] == htonl(0x00000001) &&
745 daddr->s6_addr [12] == 0xff )) {
746 ND_PRINTK2(KERN_WARNING
747 "ICMPv6 NS: bad DAD packet (wrong destination)\n");
748 return;
749 }
750
751 if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts)) {
752 ND_PRINTK2(KERN_WARNING
753 "ICMPv6 NS: invalid ND options\n");
754 return;
755 }
756
757 if (ndopts.nd_opts_src_lladdr) {
758 lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr, dev);
759 if (!lladdr) {
760 ND_PRINTK2(KERN_WARNING
761 "ICMPv6 NS: invalid link-layer address length\n");
762 return;
763 }
764
765 /* RFC2461 7.1.1:
766 * If the IP source address is the unspecified address,
767 * there MUST NOT be source link-layer address option
768 * in the message.
769 */
770 if (dad) {
771 ND_PRINTK2(KERN_WARNING
772 "ICMPv6 NS: bad DAD packet (link-layer address option)\n");
773 return;
774 }
775 }
776
777 inc = ipv6_addr_is_multicast(daddr);
778
779 if ((ifp = ipv6_get_ifaddr(&msg->target, dev, 1)) != NULL) {
780 if (ifp->flags & IFA_F_TENTATIVE) {
781 /* Address is tentative. If the source
782 is unspecified address, it is someone
783 does DAD, otherwise we ignore solicitations
784 until DAD timer expires.
785 */
786 if (!dad)
787 goto out;
788 if (dev->type == ARPHRD_IEEE802_TR) {
789 unsigned char *sadr = skb->mac.raw;
790 if (((sadr[8] ^ dev->dev_addr[0]) & 0x7f) == 0 &&
791 sadr[9] == dev->dev_addr[1] &&
792 sadr[10] == dev->dev_addr[2] &&
793 sadr[11] == dev->dev_addr[3] &&
794 sadr[12] == dev->dev_addr[4] &&
795 sadr[13] == dev->dev_addr[5]) {
796 /* looped-back to us */
797 goto out;
798 }
799 }
800 addrconf_dad_failure(ifp);
801 return;
802 }
803
804 idev = ifp->idev;
805 } else {
806 idev = in6_dev_get(dev);
807 if (!idev) {
808 /* XXX: count this drop? */
809 return;
810 }
811
812 if (ipv6_chk_acast_addr(dev, &msg->target) ||
813 (idev->cnf.forwarding &&
814 pneigh_lookup(&nd_tbl, &msg->target, dev, 0))) {
815 if (skb->stamp.tv_sec != LOCALLY_ENQUEUED &&
816 skb->pkt_type != PACKET_HOST &&
817 inc != 0 &&
818 idev->nd_parms->proxy_delay != 0) {
819 /*
820 * for anycast or proxy,
821 * sender should delay its response
822 * by a random time between 0 and
823 * MAX_ANYCAST_DELAY_TIME seconds.
824 * (RFC2461) -- yoshfuji
825 */
826 struct sk_buff *n = skb_clone(skb, GFP_ATOMIC);
827 if (n)
828 pneigh_enqueue(&nd_tbl, idev->nd_parms, n);
829 goto out;
830 }
831 } else
832 goto out;
833 }
834
835 if (dad) {
836 struct in6_addr maddr;
837
838 ipv6_addr_all_nodes(&maddr);
839 ndisc_send_na(dev, NULL, &maddr, &msg->target,
840 idev->cnf.forwarding, 0, (ifp != NULL), 1);
841 goto out;
842 }
843
844 if (inc)
845 NEIGH_CACHE_STAT_INC(&nd_tbl, rcv_probes_mcast);
846 else
847 NEIGH_CACHE_STAT_INC(&nd_tbl, rcv_probes_ucast);
848
849 /*
850 * update / create cache entry
851 * for the source address
852 */
853 neigh = __neigh_lookup(&nd_tbl, saddr, dev,
854 !inc || lladdr || !dev->addr_len);
855 if (neigh)
856 neigh_update(neigh, lladdr, NUD_STALE,
857 NEIGH_UPDATE_F_WEAK_OVERRIDE|
858 NEIGH_UPDATE_F_OVERRIDE);
859 if (neigh || !dev->hard_header) {
860 ndisc_send_na(dev, neigh, saddr, &msg->target,
861 idev->cnf.forwarding,
862 1, (ifp != NULL && inc), inc);
863 if (neigh)
864 neigh_release(neigh);
865 }
866
867out:
868 if (ifp)
869 in6_ifa_put(ifp);
870 else
871 in6_dev_put(idev);
872
873 return;
874}
875
876static void ndisc_recv_na(struct sk_buff *skb)
877{
878 struct nd_msg *msg = (struct nd_msg *)skb->h.raw;
879 struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
880 struct in6_addr *daddr = &skb->nh.ipv6h->daddr;
881 u8 *lladdr = NULL;
882 u32 ndoptlen = skb->tail - msg->opt;
883 struct ndisc_options ndopts;
884 struct net_device *dev = skb->dev;
885 struct inet6_ifaddr *ifp;
886 struct neighbour *neigh;
887
888 if (skb->len < sizeof(struct nd_msg)) {
889 ND_PRINTK2(KERN_WARNING
890 "ICMPv6 NA: packet too short\n");
891 return;
892 }
893
894 if (ipv6_addr_is_multicast(&msg->target)) {
895 ND_PRINTK2(KERN_WARNING
896 "ICMPv6 NA: target address is multicast.\n");
897 return;
898 }
899
900 if (ipv6_addr_is_multicast(daddr) &&
901 msg->icmph.icmp6_solicited) {
902 ND_PRINTK2(KERN_WARNING
903 "ICMPv6 NA: solicited NA is multicasted.\n");
904 return;
905 }
906
907 if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts)) {
908 ND_PRINTK2(KERN_WARNING
909 "ICMPv6 NS: invalid ND option\n");
910 return;
911 }
912 if (ndopts.nd_opts_tgt_lladdr) {
913 lladdr = ndisc_opt_addr_data(ndopts.nd_opts_tgt_lladdr, dev);
914 if (!lladdr) {
915 ND_PRINTK2(KERN_WARNING
916 "ICMPv6 NA: invalid link-layer address length\n");
917 return;
918 }
919 }
920 if ((ifp = ipv6_get_ifaddr(&msg->target, dev, 1))) {
921 if (ifp->flags & IFA_F_TENTATIVE) {
922 addrconf_dad_failure(ifp);
923 return;
924 }
925 /* What should we make now? The advertisement
926 is invalid, but ndisc specs say nothing
927 about it. It could be misconfiguration, or
928 an smart proxy agent tries to help us :-)
929 */
930 ND_PRINTK1(KERN_WARNING
931 "ICMPv6 NA: someone advertises our address on %s!\n",
932 ifp->idev->dev->name);
933 in6_ifa_put(ifp);
934 return;
935 }
936 neigh = neigh_lookup(&nd_tbl, &msg->target, dev);
937
938 if (neigh) {
939 u8 old_flags = neigh->flags;
940
941 if (neigh->nud_state & NUD_FAILED)
942 goto out;
943
944 neigh_update(neigh, lladdr,
945 msg->icmph.icmp6_solicited ? NUD_REACHABLE : NUD_STALE,
946 NEIGH_UPDATE_F_WEAK_OVERRIDE|
947 (msg->icmph.icmp6_override ? NEIGH_UPDATE_F_OVERRIDE : 0)|
948 NEIGH_UPDATE_F_OVERRIDE_ISROUTER|
949 (msg->icmph.icmp6_router ? NEIGH_UPDATE_F_ISROUTER : 0));
950
951 if ((old_flags & ~neigh->flags) & NTF_ROUTER) {
952 /*
953 * Change: router to host
954 */
955 struct rt6_info *rt;
956 rt = rt6_get_dflt_router(saddr, dev);
957 if (rt)
958 ip6_del_rt(rt, NULL, NULL);
959 }
960
961out:
962 neigh_release(neigh);
963 }
964}
965
966static void ndisc_recv_rs(struct sk_buff *skb)
967{
968 struct rs_msg *rs_msg = (struct rs_msg *) skb->h.raw;
969 unsigned long ndoptlen = skb->len - sizeof(*rs_msg);
970 struct neighbour *neigh;
971 struct inet6_dev *idev;
972 struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
973 struct ndisc_options ndopts;
974 u8 *lladdr = NULL;
975
976 if (skb->len < sizeof(*rs_msg))
977 return;
978
979 idev = in6_dev_get(skb->dev);
980 if (!idev) {
981 if (net_ratelimit())
982 ND_PRINTK1("ICMP6 RS: can't find in6 device\n");
983 return;
984 }
985
986 /* Don't accept RS if we're not in router mode */
987 if (!idev->cnf.forwarding)
988 goto out;
989
990 /*
991 * Don't update NCE if src = ::;
992 * this implies that the source node has no ip address assigned yet.
993 */
994 if (ipv6_addr_any(saddr))
995 goto out;
996
997 /* Parse ND options */
998 if (!ndisc_parse_options(rs_msg->opt, ndoptlen, &ndopts)) {
999 if (net_ratelimit())
1000 ND_PRINTK2("ICMP6 NS: invalid ND option, ignored\n");
1001 goto out;
1002 }
1003
1004 if (ndopts.nd_opts_src_lladdr) {
1005 lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr,
1006 skb->dev);
1007 if (!lladdr)
1008 goto out;
1009 }
1010
1011 neigh = __neigh_lookup(&nd_tbl, saddr, skb->dev, 1);
1012 if (neigh) {
1013 neigh_update(neigh, lladdr, NUD_STALE,
1014 NEIGH_UPDATE_F_WEAK_OVERRIDE|
1015 NEIGH_UPDATE_F_OVERRIDE|
1016 NEIGH_UPDATE_F_OVERRIDE_ISROUTER);
1017 neigh_release(neigh);
1018 }
1019out:
1020 in6_dev_put(idev);
1021}
1022
1023static void ndisc_router_discovery(struct sk_buff *skb)
1024{
1025 struct ra_msg *ra_msg = (struct ra_msg *) skb->h.raw;
1026 struct neighbour *neigh = NULL;
1027 struct inet6_dev *in6_dev;
1028 struct rt6_info *rt;
1029 int lifetime;
1030 struct ndisc_options ndopts;
1031 int optlen;
1032
1033 __u8 * opt = (__u8 *)(ra_msg + 1);
1034
1035 optlen = (skb->tail - skb->h.raw) - sizeof(struct ra_msg);
1036
1037 if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr) & IPV6_ADDR_LINKLOCAL)) {
1038 ND_PRINTK2(KERN_WARNING
1039 "ICMPv6 RA: source address is not link-local.\n");
1040 return;
1041 }
1042 if (optlen < 0) {
1043 ND_PRINTK2(KERN_WARNING
1044 "ICMPv6 RA: packet too short\n");
1045 return;
1046 }
1047
1048 /*
1049 * set the RA_RECV flag in the interface
1050 */
1051
1052 in6_dev = in6_dev_get(skb->dev);
1053 if (in6_dev == NULL) {
1054 ND_PRINTK0(KERN_ERR
1055 "ICMPv6 RA: can't find inet6 device for %s.\n",
1056 skb->dev->name);
1057 return;
1058 }
1059 if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra) {
1060 in6_dev_put(in6_dev);
1061 return;
1062 }
1063
1064 if (!ndisc_parse_options(opt, optlen, &ndopts)) {
1065 in6_dev_put(in6_dev);
1066 ND_PRINTK2(KERN_WARNING
1067 "ICMP6 RA: invalid ND options\n");
1068 return;
1069 }
1070
1071 if (in6_dev->if_flags & IF_RS_SENT) {
1072 /*
1073 * flag that an RA was received after an RS was sent
1074 * out on this interface.
1075 */
1076 in6_dev->if_flags |= IF_RA_RCVD;
1077 }
1078
1079 /*
1080 * Remember the managed/otherconf flags from most recently
1081 * received RA message (RFC 2462) -- yoshfuji
1082 */
1083 in6_dev->if_flags = (in6_dev->if_flags & ~(IF_RA_MANAGED |
1084 IF_RA_OTHERCONF)) |
1085 (ra_msg->icmph.icmp6_addrconf_managed ?
1086 IF_RA_MANAGED : 0) |
1087 (ra_msg->icmph.icmp6_addrconf_other ?
1088 IF_RA_OTHERCONF : 0);
1089
1090 lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime);
1091
1092 rt = rt6_get_dflt_router(&skb->nh.ipv6h->saddr, skb->dev);
1093
1094 if (rt)
1095 neigh = rt->rt6i_nexthop;
1096
1097 if (rt && lifetime == 0) {
1098 neigh_clone(neigh);
1099 ip6_del_rt(rt, NULL, NULL);
1100 rt = NULL;
1101 }
1102
1103 if (rt == NULL && lifetime) {
1104 ND_PRINTK3(KERN_DEBUG
1105 "ICMPv6 RA: adding default router.\n");
1106
1107 rt = rt6_add_dflt_router(&skb->nh.ipv6h->saddr, skb->dev);
1108 if (rt == NULL) {
1109 ND_PRINTK0(KERN_ERR
1110 "ICMPv6 RA: %s() failed to add default route.\n",
1111 __FUNCTION__);
1112 in6_dev_put(in6_dev);
1113 return;
1114 }
1115
1116 neigh = rt->rt6i_nexthop;
1117 if (neigh == NULL) {
1118 ND_PRINTK0(KERN_ERR
1119 "ICMPv6 RA: %s() got default router without neighbour.\n",
1120 __FUNCTION__);
1121 dst_release(&rt->u.dst);
1122 in6_dev_put(in6_dev);
1123 return;
1124 }
1125 neigh->flags |= NTF_ROUTER;
1126 }
1127
1128 if (rt)
1129 rt->rt6i_expires = jiffies + (HZ * lifetime);
1130
1131 if (ra_msg->icmph.icmp6_hop_limit) {
1132 in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit;
1133 if (rt)
1134 rt->u.dst.metrics[RTAX_HOPLIMIT-1] = ra_msg->icmph.icmp6_hop_limit;
1135 }
1136
1137 /*
1138 * Update Reachable Time and Retrans Timer
1139 */
1140
1141 if (in6_dev->nd_parms) {
1142 unsigned long rtime = ntohl(ra_msg->retrans_timer);
1143
1144 if (rtime && rtime/1000 < MAX_SCHEDULE_TIMEOUT/HZ) {
1145 rtime = (rtime*HZ)/1000;
1146 if (rtime < HZ/10)
1147 rtime = HZ/10;
1148 in6_dev->nd_parms->retrans_time = rtime;
1149 in6_dev->tstamp = jiffies;
1150 inet6_ifinfo_notify(RTM_NEWLINK, in6_dev);
1151 }
1152
1153 rtime = ntohl(ra_msg->reachable_time);
1154 if (rtime && rtime/1000 < MAX_SCHEDULE_TIMEOUT/(3*HZ)) {
1155 rtime = (rtime*HZ)/1000;
1156
1157 if (rtime < HZ/10)
1158 rtime = HZ/10;
1159
1160 if (rtime != in6_dev->nd_parms->base_reachable_time) {
1161 in6_dev->nd_parms->base_reachable_time = rtime;
1162 in6_dev->nd_parms->gc_staletime = 3 * rtime;
1163 in6_dev->nd_parms->reachable_time = neigh_rand_reach_time(rtime);
1164 in6_dev->tstamp = jiffies;
1165 inet6_ifinfo_notify(RTM_NEWLINK, in6_dev);
1166 }
1167 }
1168 }
1169
1170 /*
1171 * Process options.
1172 */
1173
1174 if (!neigh)
1175 neigh = __neigh_lookup(&nd_tbl, &skb->nh.ipv6h->saddr,
1176 skb->dev, 1);
1177 if (neigh) {
1178 u8 *lladdr = NULL;
1179 if (ndopts.nd_opts_src_lladdr) {
1180 lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr,
1181 skb->dev);
1182 if (!lladdr) {
1183 ND_PRINTK2(KERN_WARNING
1184 "ICMPv6 RA: invalid link-layer address length\n");
1185 goto out;
1186 }
1187 }
1188 neigh_update(neigh, lladdr, NUD_STALE,
1189 NEIGH_UPDATE_F_WEAK_OVERRIDE|
1190 NEIGH_UPDATE_F_OVERRIDE|
1191 NEIGH_UPDATE_F_OVERRIDE_ISROUTER|
1192 NEIGH_UPDATE_F_ISROUTER);
1193 }
1194
1195 if (ndopts.nd_opts_pi) {
1196 struct nd_opt_hdr *p;
1197 for (p = ndopts.nd_opts_pi;
1198 p;
1199 p = ndisc_next_option(p, ndopts.nd_opts_pi_end)) {
1200 addrconf_prefix_rcv(skb->dev, (u8*)p, (p->nd_opt_len) << 3);
1201 }
1202 }
1203
1204 if (ndopts.nd_opts_mtu) {
1205 u32 mtu;
1206
1207 memcpy(&mtu, ((u8*)(ndopts.nd_opts_mtu+1))+2, sizeof(mtu));
1208 mtu = ntohl(mtu);
1209
1210 if (mtu < IPV6_MIN_MTU || mtu > skb->dev->mtu) {
1211 ND_PRINTK2(KERN_WARNING
1212 "ICMPv6 RA: invalid mtu: %d\n",
1213 mtu);
1214 } else if (in6_dev->cnf.mtu6 != mtu) {
1215 in6_dev->cnf.mtu6 = mtu;
1216
1217 if (rt)
1218 rt->u.dst.metrics[RTAX_MTU-1] = mtu;
1219
1220 rt6_mtu_change(skb->dev, mtu);
1221 }
1222 }
1223
1224 if (ndopts.nd_opts_tgt_lladdr || ndopts.nd_opts_rh) {
1225 ND_PRINTK2(KERN_WARNING
1226 "ICMPv6 RA: invalid RA options");
1227 }
1228out:
1229 if (rt)
1230 dst_release(&rt->u.dst);
1231 else if (neigh)
1232 neigh_release(neigh);
1233 in6_dev_put(in6_dev);
1234}
1235
1236static void ndisc_redirect_rcv(struct sk_buff *skb)
1237{
1238 struct inet6_dev *in6_dev;
1239 struct icmp6hdr *icmph;
1240 struct in6_addr *dest;
1241 struct in6_addr *target; /* new first hop to destination */
1242 struct neighbour *neigh;
1243 int on_link = 0;
1244 struct ndisc_options ndopts;
1245 int optlen;
1246 u8 *lladdr = NULL;
1247
1248 if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr) & IPV6_ADDR_LINKLOCAL)) {
1249 ND_PRINTK2(KERN_WARNING
1250 "ICMPv6 Redirect: source address is not link-local.\n");
1251 return;
1252 }
1253
1254 optlen = skb->tail - skb->h.raw;
1255 optlen -= sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr);
1256
1257 if (optlen < 0) {
1258 ND_PRINTK2(KERN_WARNING
1259 "ICMPv6 Redirect: packet too short\n");
1260 return;
1261 }
1262
1263 icmph = (struct icmp6hdr *) skb->h.raw;
1264 target = (struct in6_addr *) (icmph + 1);
1265 dest = target + 1;
1266
1267 if (ipv6_addr_is_multicast(dest)) {
1268 ND_PRINTK2(KERN_WARNING
1269 "ICMPv6 Redirect: destination address is multicast.\n");
1270 return;
1271 }
1272
1273 if (ipv6_addr_equal(dest, target)) {
1274 on_link = 1;
1275 } else if (!(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) {
1276 ND_PRINTK2(KERN_WARNING
1277 "ICMPv6 Redirect: target address is not link-local.\n");
1278 return;
1279 }
1280
1281 in6_dev = in6_dev_get(skb->dev);
1282 if (!in6_dev)
1283 return;
1284 if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_redirects) {
1285 in6_dev_put(in6_dev);
1286 return;
1287 }
1288
1289 /* RFC2461 8.1:
1290 * The IP source address of the Redirect MUST be the same as the current
1291 * first-hop router for the specified ICMP Destination Address.
1292 */
1293
1294 if (!ndisc_parse_options((u8*)(dest + 1), optlen, &ndopts)) {
1295 ND_PRINTK2(KERN_WARNING
1296 "ICMPv6 Redirect: invalid ND options\n");
1297 in6_dev_put(in6_dev);
1298 return;
1299 }
1300 if (ndopts.nd_opts_tgt_lladdr) {
1301 lladdr = ndisc_opt_addr_data(ndopts.nd_opts_tgt_lladdr,
1302 skb->dev);
1303 if (!lladdr) {
1304 ND_PRINTK2(KERN_WARNING
1305 "ICMPv6 Redirect: invalid link-layer address length\n");
1306 in6_dev_put(in6_dev);
1307 return;
1308 }
1309 }
1310
1311 neigh = __neigh_lookup(&nd_tbl, target, skb->dev, 1);
1312 if (neigh) {
1313 rt6_redirect(dest, &skb->nh.ipv6h->saddr, neigh, lladdr,
1314 on_link);
1315 neigh_release(neigh);
1316 }
1317 in6_dev_put(in6_dev);
1318}
1319
1320void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
1321 struct in6_addr *target)
1322{
1323 struct sock *sk = ndisc_socket->sk;
1324 int len = sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr);
1325 struct sk_buff *buff;
1326 struct icmp6hdr *icmph;
1327 struct in6_addr saddr_buf;
1328 struct in6_addr *addrp;
1329 struct net_device *dev;
1330 struct rt6_info *rt;
1331 struct dst_entry *dst;
1332 struct inet6_dev *idev;
1333 struct flowi fl;
1334 u8 *opt;
1335 int rd_len;
1336 int err;
1337 int hlen;
1338 u8 ha_buf[MAX_ADDR_LEN], *ha = NULL;
1339
1340 dev = skb->dev;
1341
1342 if (ipv6_get_lladdr(dev, &saddr_buf)) {
1343 ND_PRINTK2(KERN_WARNING
1344 "ICMPv6 Redirect: no link-local address on %s\n",
1345 dev->name);
1346 return;
1347 }
1348
1349 ndisc_flow_init(&fl, NDISC_REDIRECT, &saddr_buf, &skb->nh.ipv6h->saddr);
1350
1351 dst = ip6_route_output(NULL, &fl);
1352 if (dst == NULL)
1353 return;
1354
1355 err = xfrm_lookup(&dst, &fl, NULL, 0);
1356 if (err) {
1357 dst_release(dst);
1358 return;
1359 }
1360
1361 rt = (struct rt6_info *) dst;
1362
1363 if (rt->rt6i_flags & RTF_GATEWAY) {
1364 ND_PRINTK2(KERN_WARNING
1365 "ICMPv6 Redirect: destination is not a neighbour.\n");
1366 dst_release(dst);
1367 return;
1368 }
1369 if (!xrlim_allow(dst, 1*HZ)) {
1370 dst_release(dst);
1371 return;
1372 }
1373
1374 if (dev->addr_len) {
1375 read_lock_bh(&neigh->lock);
1376 if (neigh->nud_state & NUD_VALID) {
1377 memcpy(ha_buf, neigh->ha, dev->addr_len);
1378 read_unlock_bh(&neigh->lock);
1379 ha = ha_buf;
1380 len += ndisc_opt_addr_space(dev);
1381 } else
1382 read_unlock_bh(&neigh->lock);
1383 }
1384
1385 rd_len = min_t(unsigned int,
1386 IPV6_MIN_MTU-sizeof(struct ipv6hdr)-len, skb->len + 8);
1387 rd_len &= ~0x7;
1388 len += rd_len;
1389
1390 buff = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
1391 1, &err);
1392 if (buff == NULL) {
1393 ND_PRINTK0(KERN_ERR
1394 "ICMPv6 Redirect: %s() failed to allocate an skb.\n",
1395 __FUNCTION__);
1396 dst_release(dst);
1397 return;
1398 }
1399
1400 hlen = 0;
1401
1402 skb_reserve(buff, LL_RESERVED_SPACE(dev));
1403 ip6_nd_hdr(sk, buff, dev, &saddr_buf, &skb->nh.ipv6h->saddr,
1404 IPPROTO_ICMPV6, len);
1405
1406 icmph = (struct icmp6hdr *)skb_put(buff, len);
1407 buff->h.raw = (unsigned char*)icmph;
1408
1409 memset(icmph, 0, sizeof(struct icmp6hdr));
1410 icmph->icmp6_type = NDISC_REDIRECT;
1411
1412 /*
1413 * copy target and destination addresses
1414 */
1415
1416 addrp = (struct in6_addr *)(icmph + 1);
1417 ipv6_addr_copy(addrp, target);
1418 addrp++;
1419 ipv6_addr_copy(addrp, &skb->nh.ipv6h->daddr);
1420
1421 opt = (u8*) (addrp + 1);
1422
1423 /*
1424 * include target_address option
1425 */
1426
1427 if (ha)
1428 opt = ndisc_fill_addr_option(opt, ND_OPT_TARGET_LL_ADDR, ha,
1429 dev->addr_len, dev->type);
1430
1431 /*
1432 * build redirect option and copy skb over to the new packet.
1433 */
1434
1435 memset(opt, 0, 8);
1436 *(opt++) = ND_OPT_REDIRECT_HDR;
1437 *(opt++) = (rd_len >> 3);
1438 opt += 6;
1439
1440 memcpy(opt, skb->nh.ipv6h, rd_len - 8);
1441
1442 icmph->icmp6_cksum = csum_ipv6_magic(&saddr_buf, &skb->nh.ipv6h->saddr,
1443 len, IPPROTO_ICMPV6,
1444 csum_partial((u8 *) icmph, len, 0));
1445
1446 buff->dst = dst;
1447 idev = in6_dev_get(dst->dev);
1448 IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
1449 err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, buff, NULL, dst->dev, dst_output);
1450 if (!err) {
1451 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTREDIRECTS);
1452 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
1453 }
1454
1455 if (likely(idev != NULL))
1456 in6_dev_put(idev);
1457}
1458
1459static void pndisc_redo(struct sk_buff *skb)
1460{
1461 ndisc_rcv(skb);
1462 kfree_skb(skb);
1463}
1464
1465int ndisc_rcv(struct sk_buff *skb)
1466{
1467 struct nd_msg *msg;
1468
1469 if (!pskb_may_pull(skb, skb->len))
1470 return 0;
1471
1472 msg = (struct nd_msg *) skb->h.raw;
1473
1474 __skb_push(skb, skb->data-skb->h.raw);
1475
1476 if (skb->nh.ipv6h->hop_limit != 255) {
1477 ND_PRINTK2(KERN_WARNING
1478 "ICMPv6 NDISC: invalid hop-limit: %d\n",
1479 skb->nh.ipv6h->hop_limit);
1480 return 0;
1481 }
1482
1483 if (msg->icmph.icmp6_code != 0) {
1484 ND_PRINTK2(KERN_WARNING
1485 "ICMPv6 NDISC: invalid ICMPv6 code: %d\n",
1486 msg->icmph.icmp6_code);
1487 return 0;
1488 }
1489
1490 switch (msg->icmph.icmp6_type) {
1491 case NDISC_NEIGHBOUR_SOLICITATION:
1492 ndisc_recv_ns(skb);
1493 break;
1494
1495 case NDISC_NEIGHBOUR_ADVERTISEMENT:
1496 ndisc_recv_na(skb);
1497 break;
1498
1499 case NDISC_ROUTER_SOLICITATION:
1500 ndisc_recv_rs(skb);
1501 break;
1502
1503 case NDISC_ROUTER_ADVERTISEMENT:
1504 ndisc_router_discovery(skb);
1505 break;
1506
1507 case NDISC_REDIRECT:
1508 ndisc_redirect_rcv(skb);
1509 break;
1510 };
1511
1512 return 0;
1513}
1514
1515static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
1516{
1517 struct net_device *dev = ptr;
1518
1519 switch (event) {
1520 case NETDEV_CHANGEADDR:
1521 neigh_changeaddr(&nd_tbl, dev);
1522 fib6_run_gc(~0UL);
1523 break;
1524 case NETDEV_DOWN:
1525 neigh_ifdown(&nd_tbl, dev);
1526 fib6_run_gc(~0UL);
1527 break;
1528 default:
1529 break;
1530 }
1531
1532 return NOTIFY_DONE;
1533}
1534
1535static struct notifier_block ndisc_netdev_notifier = {
1536 .notifier_call = ndisc_netdev_event,
1537};
1538
1539#ifdef CONFIG_SYSCTL
1540static void ndisc_warn_deprecated_sysctl(struct ctl_table *ctl,
1541 const char *func, const char *dev_name)
1542{
1543 static char warncomm[TASK_COMM_LEN];
1544 static int warned;
1545 if (strcmp(warncomm, current->comm) && warned < 5) {
1546 strcpy(warncomm, current->comm);
1547 printk(KERN_WARNING
1548 "process `%s' is using deprecated sysctl (%s) "
1549 "net.ipv6.neigh.%s.%s; "
1550 "Use net.ipv6.neigh.%s.%s_ms "
1551 "instead.\n",
1552 warncomm, func,
1553 dev_name, ctl->procname,
1554 dev_name, ctl->procname);
1555 warned++;
1556 }
1557}
1558
1559int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, struct file * filp, void __user *buffer, size_t *lenp, loff_t *ppos)
1560{
1561 struct net_device *dev = ctl->extra1;
1562 struct inet6_dev *idev;
1563 int ret;
1564
1565 if (ctl->ctl_name == NET_NEIGH_RETRANS_TIME ||
1566 ctl->ctl_name == NET_NEIGH_REACHABLE_TIME)
1567 ndisc_warn_deprecated_sysctl(ctl, "syscall", dev ? dev->name : "default");
1568
1569 switch (ctl->ctl_name) {
1570 case NET_NEIGH_RETRANS_TIME:
1571 ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
1572 break;
1573 case NET_NEIGH_REACHABLE_TIME:
1574 ret = proc_dointvec_jiffies(ctl, write,
1575 filp, buffer, lenp, ppos);
1576 break;
1577 case NET_NEIGH_RETRANS_TIME_MS:
1578 case NET_NEIGH_REACHABLE_TIME_MS:
1579 ret = proc_dointvec_ms_jiffies(ctl, write,
1580 filp, buffer, lenp, ppos);
1581 break;
1582 default:
1583 ret = -1;
1584 }
1585
1586 if (write && ret == 0 && dev && (idev = in6_dev_get(dev)) != NULL) {
1587 if (ctl->ctl_name == NET_NEIGH_REACHABLE_TIME ||
1588 ctl->ctl_name == NET_NEIGH_REACHABLE_TIME_MS)
1589 idev->nd_parms->reachable_time = neigh_rand_reach_time(idev->nd_parms->base_reachable_time);
1590 idev->tstamp = jiffies;
1591 inet6_ifinfo_notify(RTM_NEWLINK, idev);
1592 in6_dev_put(idev);
1593 }
1594 return ret;
1595}
1596
1597static int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl, int __user *name,
1598 int nlen, void __user *oldval,
1599 size_t __user *oldlenp,
1600 void __user *newval, size_t newlen,
1601 void **context)
1602{
1603 struct net_device *dev = ctl->extra1;
1604 struct inet6_dev *idev;
1605 int ret;
1606
1607 if (ctl->ctl_name == NET_NEIGH_RETRANS_TIME ||
1608 ctl->ctl_name == NET_NEIGH_REACHABLE_TIME)
1609 ndisc_warn_deprecated_sysctl(ctl, "procfs", dev ? dev->name : "default");
1610
1611 switch (ctl->ctl_name) {
1612 case NET_NEIGH_REACHABLE_TIME:
1613 ret = sysctl_jiffies(ctl, name, nlen,
1614 oldval, oldlenp, newval, newlen,
1615 context);
1616 break;
1617 case NET_NEIGH_RETRANS_TIME_MS:
1618 case NET_NEIGH_REACHABLE_TIME_MS:
1619 ret = sysctl_ms_jiffies(ctl, name, nlen,
1620 oldval, oldlenp, newval, newlen,
1621 context);
1622 break;
1623 default:
1624 ret = 0;
1625 }
1626
1627 if (newval && newlen && ret > 0 &&
1628 dev && (idev = in6_dev_get(dev)) != NULL) {
1629 if (ctl->ctl_name == NET_NEIGH_REACHABLE_TIME ||
1630 ctl->ctl_name == NET_NEIGH_REACHABLE_TIME_MS)
1631 idev->nd_parms->reachable_time = neigh_rand_reach_time(idev->nd_parms->base_reachable_time);
1632 idev->tstamp = jiffies;
1633 inet6_ifinfo_notify(RTM_NEWLINK, idev);
1634 in6_dev_put(idev);
1635 }
1636
1637 return ret;
1638}
1639
1640#endif
1641
1642int __init ndisc_init(struct net_proto_family *ops)
1643{
1644 struct ipv6_pinfo *np;
1645 struct sock *sk;
1646 int err;
1647
1648 err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &ndisc_socket);
1649 if (err < 0) {
1650 ND_PRINTK0(KERN_ERR
1651 "ICMPv6 NDISC: Failed to initialize the control socket (err %d).\n",
1652 err);
1653 ndisc_socket = NULL; /* For safety. */
1654 return err;
1655 }
1656
1657 sk = ndisc_socket->sk;
1658 np = inet6_sk(sk);
1659 sk->sk_allocation = GFP_ATOMIC;
1660 np->hop_limit = 255;
1661 /* Do not loopback ndisc messages */
1662 np->mc_loop = 0;
1663 sk->sk_prot->unhash(sk);
1664
1665 /*
1666 * Initialize the neighbour table
1667 */
1668
1669 neigh_table_init(&nd_tbl);
1670
1671#ifdef CONFIG_SYSCTL
1672 neigh_sysctl_register(NULL, &nd_tbl.parms, NET_IPV6, NET_IPV6_NEIGH,
1673 "ipv6",
1674 &ndisc_ifinfo_sysctl_change,
1675 &ndisc_ifinfo_sysctl_strategy);
1676#endif
1677
1678 register_netdevice_notifier(&ndisc_netdev_notifier);
1679 return 0;
1680}
1681
1682void ndisc_cleanup(void)
1683{
1684#ifdef CONFIG_SYSCTL
1685 neigh_sysctl_unregister(&nd_tbl.parms);
1686#endif
1687 neigh_table_clear(&nd_tbl);
1688 sock_release(ndisc_socket);
1689 ndisc_socket = NULL; /* For safety. */
1690}