ia64/linux-2.6.18-xen.hg

view net/ipv6/ndisc.c @ 673:3161879fdf22

[IA64] xencomm: support XENMEM_add_to_physmap and XENMEM_remove_from_phsymap

support XENMEM_add_to_physmap and XENMEM_remove_from_phsymap.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author Isaku Yamahata <yamahata@valinux.co.jp>
date Tue Sep 16 21:26:15 2008 +0900 (2008-09-16)
parents 831230e53067
children
line source
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 */
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 */
28 /* Set to 3 to get tracing... */
29 #define ND_DEBUG 1
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
50 #include <linux/module.h>
51 #include <linux/errno.h>
52 #include <linux/types.h>
53 #include <linux/socket.h>
54 #include <linux/sockios.h>
55 #include <linux/sched.h>
56 #include <linux/net.h>
57 #include <linux/in6.h>
58 #include <linux/route.h>
59 #include <linux/init.h>
60 #include <linux/rcupdate.h>
61 #ifdef CONFIG_SYSCTL
62 #include <linux/sysctl.h>
63 #endif
65 #include <linux/if_arp.h>
66 #include <linux/ipv6.h>
67 #include <linux/icmpv6.h>
68 #include <linux/jhash.h>
70 #include <net/sock.h>
71 #include <net/snmp.h>
73 #include <net/ipv6.h>
74 #include <net/protocol.h>
75 #include <net/ndisc.h>
76 #include <net/ip6_route.h>
77 #include <net/addrconf.h>
78 #include <net/icmp.h>
80 #include <net/flow.h>
81 #include <net/ip6_checksum.h>
82 #include <linux/proc_fs.h>
84 #include <linux/netfilter.h>
85 #include <linux/netfilter_ipv6.h>
87 static struct socket *ndisc_socket;
89 static u32 ndisc_hash(const void *pkey, const struct net_device *dev);
90 static int ndisc_constructor(struct neighbour *neigh);
91 static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb);
92 static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb);
93 static int pndisc_constructor(struct pneigh_entry *n);
94 static void pndisc_destructor(struct pneigh_entry *n);
95 static void pndisc_redo(struct sk_buff *skb);
97 static struct neigh_ops ndisc_generic_ops = {
98 .family = AF_INET6,
99 .solicit = ndisc_solicit,
100 .error_report = ndisc_error_report,
101 .output = neigh_resolve_output,
102 .connected_output = neigh_connected_output,
103 .hh_output = dev_queue_xmit,
104 .queue_xmit = dev_queue_xmit,
105 };
107 static struct neigh_ops ndisc_hh_ops = {
108 .family = AF_INET6,
109 .solicit = ndisc_solicit,
110 .error_report = ndisc_error_report,
111 .output = neigh_resolve_output,
112 .connected_output = neigh_resolve_output,
113 .hh_output = dev_queue_xmit,
114 .queue_xmit = dev_queue_xmit,
115 };
118 static struct neigh_ops ndisc_direct_ops = {
119 .family = AF_INET6,
120 .output = dev_queue_xmit,
121 .connected_output = dev_queue_xmit,
122 .hh_output = dev_queue_xmit,
123 .queue_xmit = dev_queue_xmit,
124 };
126 struct neigh_table nd_tbl = {
127 .family = AF_INET6,
128 .entry_size = sizeof(struct neighbour) + sizeof(struct in6_addr),
129 .key_len = sizeof(struct in6_addr),
130 .hash = ndisc_hash,
131 .constructor = ndisc_constructor,
132 .pconstructor = pndisc_constructor,
133 .pdestructor = pndisc_destructor,
134 .proxy_redo = pndisc_redo,
135 .id = "ndisc_cache",
136 .parms = {
137 .tbl = &nd_tbl,
138 .base_reachable_time = 30 * HZ,
139 .retrans_time = 1 * HZ,
140 .gc_staletime = 60 * HZ,
141 .reachable_time = 30 * HZ,
142 .delay_probe_time = 5 * HZ,
143 .queue_len = 3,
144 .ucast_probes = 3,
145 .mcast_probes = 3,
146 .anycast_delay = 1 * HZ,
147 .proxy_delay = (8 * HZ) / 10,
148 .proxy_qlen = 64,
149 },
150 .gc_interval = 30 * HZ,
151 .gc_thresh1 = 128,
152 .gc_thresh2 = 512,
153 .gc_thresh3 = 1024,
154 };
156 /* ND options */
157 struct ndisc_options {
158 struct nd_opt_hdr *nd_opt_array[__ND_OPT_ARRAY_MAX];
159 #ifdef CONFIG_IPV6_ROUTE_INFO
160 struct nd_opt_hdr *nd_opts_ri;
161 struct nd_opt_hdr *nd_opts_ri_end;
162 #endif
163 };
165 #define nd_opts_src_lladdr nd_opt_array[ND_OPT_SOURCE_LL_ADDR]
166 #define nd_opts_tgt_lladdr nd_opt_array[ND_OPT_TARGET_LL_ADDR]
167 #define nd_opts_pi nd_opt_array[ND_OPT_PREFIX_INFO]
168 #define nd_opts_pi_end nd_opt_array[__ND_OPT_PREFIX_INFO_END]
169 #define nd_opts_rh nd_opt_array[ND_OPT_REDIRECT_HDR]
170 #define nd_opts_mtu nd_opt_array[ND_OPT_MTU]
172 #define NDISC_OPT_SPACE(len) (((len)+2+7)&~7)
174 /*
175 * Return the padding between the option length and the start of the
176 * link addr. Currently only IP-over-InfiniBand needs this, although
177 * if RFC 3831 IPv6-over-Fibre Channel is ever implemented it may
178 * also need a pad of 2.
179 */
180 static int ndisc_addr_option_pad(unsigned short type)
181 {
182 switch (type) {
183 case ARPHRD_INFINIBAND: return 2;
184 default: return 0;
185 }
186 }
188 static inline int ndisc_opt_addr_space(struct net_device *dev)
189 {
190 return NDISC_OPT_SPACE(dev->addr_len + ndisc_addr_option_pad(dev->type));
191 }
193 static u8 *ndisc_fill_addr_option(u8 *opt, int type, void *data, int data_len,
194 unsigned short addr_type)
195 {
196 int space = NDISC_OPT_SPACE(data_len);
197 int pad = ndisc_addr_option_pad(addr_type);
199 opt[0] = type;
200 opt[1] = space>>3;
202 memset(opt + 2, 0, pad);
203 opt += pad;
204 space -= pad;
206 memcpy(opt+2, data, data_len);
207 data_len += 2;
208 opt += data_len;
209 if ((space -= data_len) > 0)
210 memset(opt, 0, space);
211 return opt + space;
212 }
214 static struct nd_opt_hdr *ndisc_next_option(struct nd_opt_hdr *cur,
215 struct nd_opt_hdr *end)
216 {
217 int type;
218 if (!cur || !end || cur >= end)
219 return NULL;
220 type = cur->nd_opt_type;
221 do {
222 cur = ((void *)cur) + (cur->nd_opt_len << 3);
223 } while(cur < end && cur->nd_opt_type != type);
224 return (cur <= end && cur->nd_opt_type == type ? cur : NULL);
225 }
227 static struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len,
228 struct ndisc_options *ndopts)
229 {
230 struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)opt;
232 if (!nd_opt || opt_len < 0 || !ndopts)
233 return NULL;
234 memset(ndopts, 0, sizeof(*ndopts));
235 while (opt_len) {
236 int l;
237 if (opt_len < sizeof(struct nd_opt_hdr))
238 return NULL;
239 l = nd_opt->nd_opt_len << 3;
240 if (opt_len < l || l == 0)
241 return NULL;
242 switch (nd_opt->nd_opt_type) {
243 case ND_OPT_SOURCE_LL_ADDR:
244 case ND_OPT_TARGET_LL_ADDR:
245 case ND_OPT_MTU:
246 case ND_OPT_REDIRECT_HDR:
247 if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) {
248 ND_PRINTK2(KERN_WARNING
249 "%s(): duplicated ND6 option found: type=%d\n",
250 __FUNCTION__,
251 nd_opt->nd_opt_type);
252 } else {
253 ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt;
254 }
255 break;
256 case ND_OPT_PREFIX_INFO:
257 ndopts->nd_opts_pi_end = nd_opt;
258 if (ndopts->nd_opt_array[nd_opt->nd_opt_type] == 0)
259 ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt;
260 break;
261 #ifdef CONFIG_IPV6_ROUTE_INFO
262 case ND_OPT_ROUTE_INFO:
263 ndopts->nd_opts_ri_end = nd_opt;
264 if (!ndopts->nd_opts_ri)
265 ndopts->nd_opts_ri = nd_opt;
266 break;
267 #endif
268 default:
269 /*
270 * Unknown options must be silently ignored,
271 * to accommodate future extension to the protocol.
272 */
273 ND_PRINTK2(KERN_NOTICE
274 "%s(): ignored unsupported option; type=%d, len=%d\n",
275 __FUNCTION__,
276 nd_opt->nd_opt_type, nd_opt->nd_opt_len);
277 }
278 opt_len -= l;
279 nd_opt = ((void *)nd_opt) + l;
280 }
281 return ndopts;
282 }
284 static inline u8 *ndisc_opt_addr_data(struct nd_opt_hdr *p,
285 struct net_device *dev)
286 {
287 u8 *lladdr = (u8 *)(p + 1);
288 int lladdrlen = p->nd_opt_len << 3;
289 int prepad = ndisc_addr_option_pad(dev->type);
290 if (lladdrlen != NDISC_OPT_SPACE(dev->addr_len + prepad))
291 return NULL;
292 return (lladdr + prepad);
293 }
295 int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int dir)
296 {
297 switch (dev->type) {
298 case ARPHRD_ETHER:
299 case ARPHRD_IEEE802: /* Not sure. Check it later. --ANK */
300 case ARPHRD_FDDI:
301 ipv6_eth_mc_map(addr, buf);
302 return 0;
303 case ARPHRD_IEEE802_TR:
304 ipv6_tr_mc_map(addr,buf);
305 return 0;
306 case ARPHRD_ARCNET:
307 ipv6_arcnet_mc_map(addr, buf);
308 return 0;
309 case ARPHRD_INFINIBAND:
310 ipv6_ib_mc_map(addr, buf);
311 return 0;
312 default:
313 if (dir) {
314 memcpy(buf, dev->broadcast, dev->addr_len);
315 return 0;
316 }
317 }
318 return -EINVAL;
319 }
321 static u32 ndisc_hash(const void *pkey, const struct net_device *dev)
322 {
323 const u32 *p32 = pkey;
324 u32 addr_hash, i;
326 addr_hash = 0;
327 for (i = 0; i < (sizeof(struct in6_addr) / sizeof(u32)); i++)
328 addr_hash ^= *p32++;
330 return jhash_2words(addr_hash, dev->ifindex, nd_tbl.hash_rnd);
331 }
333 static int ndisc_constructor(struct neighbour *neigh)
334 {
335 struct in6_addr *addr = (struct in6_addr*)&neigh->primary_key;
336 struct net_device *dev = neigh->dev;
337 struct inet6_dev *in6_dev;
338 struct neigh_parms *parms;
339 int is_multicast = ipv6_addr_is_multicast(addr);
341 rcu_read_lock();
342 in6_dev = in6_dev_get(dev);
343 if (in6_dev == NULL) {
344 rcu_read_unlock();
345 return -EINVAL;
346 }
348 parms = in6_dev->nd_parms;
349 __neigh_parms_put(neigh->parms);
350 neigh->parms = neigh_parms_clone(parms);
351 rcu_read_unlock();
353 neigh->type = is_multicast ? RTN_MULTICAST : RTN_UNICAST;
354 if (dev->hard_header == NULL) {
355 neigh->nud_state = NUD_NOARP;
356 neigh->ops = &ndisc_direct_ops;
357 neigh->output = neigh->ops->queue_xmit;
358 } else {
359 if (is_multicast) {
360 neigh->nud_state = NUD_NOARP;
361 ndisc_mc_map(addr, neigh->ha, dev, 1);
362 } else if (dev->flags&(IFF_NOARP|IFF_LOOPBACK)) {
363 neigh->nud_state = NUD_NOARP;
364 memcpy(neigh->ha, dev->dev_addr, dev->addr_len);
365 if (dev->flags&IFF_LOOPBACK)
366 neigh->type = RTN_LOCAL;
367 } else if (dev->flags&IFF_POINTOPOINT) {
368 neigh->nud_state = NUD_NOARP;
369 memcpy(neigh->ha, dev->broadcast, dev->addr_len);
370 }
371 if (dev->hard_header_cache)
372 neigh->ops = &ndisc_hh_ops;
373 else
374 neigh->ops = &ndisc_generic_ops;
375 if (neigh->nud_state&NUD_VALID)
376 neigh->output = neigh->ops->connected_output;
377 else
378 neigh->output = neigh->ops->output;
379 }
380 in6_dev_put(in6_dev);
381 return 0;
382 }
384 static int pndisc_constructor(struct pneigh_entry *n)
385 {
386 struct in6_addr *addr = (struct in6_addr*)&n->key;
387 struct in6_addr maddr;
388 struct net_device *dev = n->dev;
390 if (dev == NULL || __in6_dev_get(dev) == NULL)
391 return -EINVAL;
392 addrconf_addr_solict_mult(addr, &maddr);
393 ipv6_dev_mc_inc(dev, &maddr);
394 return 0;
395 }
397 static void pndisc_destructor(struct pneigh_entry *n)
398 {
399 struct in6_addr *addr = (struct in6_addr*)&n->key;
400 struct in6_addr maddr;
401 struct net_device *dev = n->dev;
403 if (dev == NULL || __in6_dev_get(dev) == NULL)
404 return;
405 addrconf_addr_solict_mult(addr, &maddr);
406 ipv6_dev_mc_dec(dev, &maddr);
407 }
409 /*
410 * Send a Neighbour Advertisement
411 */
413 static inline void ndisc_flow_init(struct flowi *fl, u8 type,
414 struct in6_addr *saddr, struct in6_addr *daddr)
415 {
416 memset(fl, 0, sizeof(*fl));
417 ipv6_addr_copy(&fl->fl6_src, saddr);
418 ipv6_addr_copy(&fl->fl6_dst, daddr);
419 fl->proto = IPPROTO_ICMPV6;
420 fl->fl_icmp_type = type;
421 fl->fl_icmp_code = 0;
422 }
424 static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
425 struct in6_addr *daddr, struct in6_addr *solicited_addr,
426 int router, int solicited, int override, int inc_opt)
427 {
428 struct in6_addr tmpaddr;
429 struct inet6_ifaddr *ifp;
430 struct inet6_dev *idev;
431 struct flowi fl;
432 struct dst_entry* dst;
433 struct sock *sk = ndisc_socket->sk;
434 struct in6_addr *src_addr;
435 struct nd_msg *msg;
436 int len;
437 struct sk_buff *skb;
438 int err;
440 len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
442 /* for anycast or proxy, solicited_addr != src_addr */
443 ifp = ipv6_get_ifaddr(solicited_addr, dev, 1);
444 if (ifp) {
445 src_addr = solicited_addr;
446 in6_ifa_put(ifp);
447 } else {
448 if (ipv6_dev_get_saddr(dev, daddr, &tmpaddr))
449 return;
450 src_addr = &tmpaddr;
451 }
453 ndisc_flow_init(&fl, NDISC_NEIGHBOUR_ADVERTISEMENT, src_addr, daddr);
455 dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output);
456 if (!dst)
457 return;
459 err = xfrm_lookup(&dst, &fl, NULL, 0);
460 if (err < 0)
461 return;
463 if (inc_opt) {
464 if (dev->addr_len)
465 len += ndisc_opt_addr_space(dev);
466 else
467 inc_opt = 0;
468 }
470 skb = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
471 1, &err);
473 if (skb == NULL) {
474 ND_PRINTK0(KERN_ERR
475 "ICMPv6 NA: %s() failed to allocate an skb.\n",
476 __FUNCTION__);
477 dst_release(dst);
478 return;
479 }
481 skb_reserve(skb, LL_RESERVED_SPACE(dev));
482 ip6_nd_hdr(sk, skb, dev, src_addr, daddr, IPPROTO_ICMPV6, len);
484 msg = (struct nd_msg *)skb_put(skb, len);
485 skb->h.raw = (unsigned char*)msg;
487 msg->icmph.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT;
488 msg->icmph.icmp6_code = 0;
489 msg->icmph.icmp6_cksum = 0;
491 msg->icmph.icmp6_unused = 0;
492 msg->icmph.icmp6_router = router;
493 msg->icmph.icmp6_solicited = solicited;
494 msg->icmph.icmp6_override = !!override;
496 /* Set the target address. */
497 ipv6_addr_copy(&msg->target, solicited_addr);
499 if (inc_opt)
500 ndisc_fill_addr_option(msg->opt, ND_OPT_TARGET_LL_ADDR, dev->dev_addr,
501 dev->addr_len, dev->type);
503 /* checksum */
504 msg->icmph.icmp6_cksum = csum_ipv6_magic(src_addr, daddr, len,
505 IPPROTO_ICMPV6,
506 csum_partial((__u8 *) msg,
507 len, 0));
509 skb->dst = dst;
510 idev = in6_dev_get(dst->dev);
511 IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
512 err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
513 if (!err) {
514 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTNEIGHBORADVERTISEMENTS);
515 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
516 }
518 if (likely(idev != NULL))
519 in6_dev_put(idev);
520 }
522 void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
523 struct in6_addr *solicit,
524 struct in6_addr *daddr, struct in6_addr *saddr)
525 {
526 struct flowi fl;
527 struct dst_entry* dst;
528 struct inet6_dev *idev;
529 struct sock *sk = ndisc_socket->sk;
530 struct sk_buff *skb;
531 struct nd_msg *msg;
532 struct in6_addr addr_buf;
533 int len;
534 int err;
535 int send_llinfo;
537 if (saddr == NULL) {
538 if (ipv6_get_lladdr(dev, &addr_buf))
539 return;
540 saddr = &addr_buf;
541 }
543 ndisc_flow_init(&fl, NDISC_NEIGHBOUR_SOLICITATION, saddr, daddr);
545 dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output);
546 if (!dst)
547 return;
549 err = xfrm_lookup(&dst, &fl, NULL, 0);
550 if (err < 0)
551 return;
553 len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
554 send_llinfo = dev->addr_len && !ipv6_addr_any(saddr);
555 if (send_llinfo)
556 len += ndisc_opt_addr_space(dev);
558 skb = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
559 1, &err);
560 if (skb == NULL) {
561 ND_PRINTK0(KERN_ERR
562 "ICMPv6 NA: %s() failed to allocate an skb.\n",
563 __FUNCTION__);
564 dst_release(dst);
565 return;
566 }
568 skb_reserve(skb, LL_RESERVED_SPACE(dev));
569 ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len);
571 msg = (struct nd_msg *)skb_put(skb, len);
572 skb->h.raw = (unsigned char*)msg;
573 msg->icmph.icmp6_type = NDISC_NEIGHBOUR_SOLICITATION;
574 msg->icmph.icmp6_code = 0;
575 msg->icmph.icmp6_cksum = 0;
576 msg->icmph.icmp6_unused = 0;
578 /* Set the target address. */
579 ipv6_addr_copy(&msg->target, solicit);
581 if (send_llinfo)
582 ndisc_fill_addr_option(msg->opt, ND_OPT_SOURCE_LL_ADDR, dev->dev_addr,
583 dev->addr_len, dev->type);
585 /* checksum */
586 msg->icmph.icmp6_cksum = csum_ipv6_magic(&skb->nh.ipv6h->saddr,
587 daddr, len,
588 IPPROTO_ICMPV6,
589 csum_partial((__u8 *) msg,
590 len, 0));
591 /* send it! */
592 skb->dst = dst;
593 idev = in6_dev_get(dst->dev);
594 IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
595 err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
596 if (!err) {
597 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTNEIGHBORSOLICITS);
598 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
599 }
601 if (likely(idev != NULL))
602 in6_dev_put(idev);
603 }
605 void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
606 struct in6_addr *daddr)
607 {
608 struct flowi fl;
609 struct dst_entry* dst;
610 struct inet6_dev *idev;
611 struct sock *sk = ndisc_socket->sk;
612 struct sk_buff *skb;
613 struct icmp6hdr *hdr;
614 __u8 * opt;
615 int len;
616 int err;
618 ndisc_flow_init(&fl, NDISC_ROUTER_SOLICITATION, saddr, daddr);
620 dst = ndisc_dst_alloc(dev, NULL, daddr, ip6_output);
621 if (!dst)
622 return;
624 err = xfrm_lookup(&dst, &fl, NULL, 0);
625 if (err < 0)
626 return;
628 len = sizeof(struct icmp6hdr);
629 if (dev->addr_len)
630 len += ndisc_opt_addr_space(dev);
632 skb = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
633 1, &err);
634 if (skb == NULL) {
635 ND_PRINTK0(KERN_ERR
636 "ICMPv6 RS: %s() failed to allocate an skb.\n",
637 __FUNCTION__);
638 dst_release(dst);
639 return;
640 }
642 skb_reserve(skb, LL_RESERVED_SPACE(dev));
643 ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len);
645 hdr = (struct icmp6hdr *)skb_put(skb, len);
646 skb->h.raw = (unsigned char*)hdr;
647 hdr->icmp6_type = NDISC_ROUTER_SOLICITATION;
648 hdr->icmp6_code = 0;
649 hdr->icmp6_cksum = 0;
650 hdr->icmp6_unused = 0;
652 opt = (u8*) (hdr + 1);
654 if (dev->addr_len)
655 ndisc_fill_addr_option(opt, ND_OPT_SOURCE_LL_ADDR, dev->dev_addr,
656 dev->addr_len, dev->type);
658 /* checksum */
659 hdr->icmp6_cksum = csum_ipv6_magic(&skb->nh.ipv6h->saddr, daddr, len,
660 IPPROTO_ICMPV6,
661 csum_partial((__u8 *) hdr, len, 0));
663 /* send it! */
664 skb->dst = dst;
665 idev = in6_dev_get(dst->dev);
666 IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
667 err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
668 if (!err) {
669 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTROUTERSOLICITS);
670 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
671 }
673 if (likely(idev != NULL))
674 in6_dev_put(idev);
675 }
678 static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb)
679 {
680 /*
681 * "The sender MUST return an ICMP
682 * destination unreachable"
683 */
684 dst_link_failure(skb);
685 kfree_skb(skb);
686 }
688 /* Called with locked neigh: either read or both */
690 static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
691 {
692 struct in6_addr *saddr = NULL;
693 struct in6_addr mcaddr;
694 struct net_device *dev = neigh->dev;
695 struct in6_addr *target = (struct in6_addr *)&neigh->primary_key;
696 int probes = atomic_read(&neigh->probes);
698 if (skb && ipv6_chk_addr(&skb->nh.ipv6h->saddr, dev, 1))
699 saddr = &skb->nh.ipv6h->saddr;
701 if ((probes -= neigh->parms->ucast_probes) < 0) {
702 if (!(neigh->nud_state & NUD_VALID)) {
703 ND_PRINTK1(KERN_DEBUG
704 "%s(): trying to ucast probe in NUD_INVALID: "
705 NIP6_FMT "\n",
706 __FUNCTION__,
707 NIP6(*target));
708 }
709 ndisc_send_ns(dev, neigh, target, target, saddr);
710 } else if ((probes -= neigh->parms->app_probes) < 0) {
711 #ifdef CONFIG_ARPD
712 neigh_app_ns(neigh);
713 #endif
714 } else {
715 addrconf_addr_solict_mult(target, &mcaddr);
716 ndisc_send_ns(dev, NULL, target, &mcaddr, saddr);
717 }
718 }
720 static void ndisc_recv_ns(struct sk_buff *skb)
721 {
722 struct nd_msg *msg = (struct nd_msg *)skb->h.raw;
723 struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
724 struct in6_addr *daddr = &skb->nh.ipv6h->daddr;
725 u8 *lladdr = NULL;
726 u32 ndoptlen = skb->tail - msg->opt;
727 struct ndisc_options ndopts;
728 struct net_device *dev = skb->dev;
729 struct inet6_ifaddr *ifp;
730 struct inet6_dev *idev = NULL;
731 struct neighbour *neigh;
732 int dad = ipv6_addr_any(saddr);
733 int inc;
735 if (ipv6_addr_is_multicast(&msg->target)) {
736 ND_PRINTK2(KERN_WARNING
737 "ICMPv6 NS: multicast target address");
738 return;
739 }
741 /*
742 * RFC2461 7.1.1:
743 * DAD has to be destined for solicited node multicast address.
744 */
745 if (dad &&
746 !(daddr->s6_addr32[0] == htonl(0xff020000) &&
747 daddr->s6_addr32[1] == htonl(0x00000000) &&
748 daddr->s6_addr32[2] == htonl(0x00000001) &&
749 daddr->s6_addr [12] == 0xff )) {
750 ND_PRINTK2(KERN_WARNING
751 "ICMPv6 NS: bad DAD packet (wrong destination)\n");
752 return;
753 }
755 if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts)) {
756 ND_PRINTK2(KERN_WARNING
757 "ICMPv6 NS: invalid ND options\n");
758 return;
759 }
761 if (ndopts.nd_opts_src_lladdr) {
762 lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr, dev);
763 if (!lladdr) {
764 ND_PRINTK2(KERN_WARNING
765 "ICMPv6 NS: invalid link-layer address length\n");
766 return;
767 }
769 /* RFC2461 7.1.1:
770 * If the IP source address is the unspecified address,
771 * there MUST NOT be source link-layer address option
772 * in the message.
773 */
774 if (dad) {
775 ND_PRINTK2(KERN_WARNING
776 "ICMPv6 NS: bad DAD packet (link-layer address option)\n");
777 return;
778 }
779 }
781 inc = ipv6_addr_is_multicast(daddr);
783 if ((ifp = ipv6_get_ifaddr(&msg->target, dev, 1)) != NULL) {
784 if (ifp->flags & IFA_F_TENTATIVE) {
785 /* Address is tentative. If the source
786 is unspecified address, it is someone
787 does DAD, otherwise we ignore solicitations
788 until DAD timer expires.
789 */
790 if (!dad)
791 goto out;
792 if (dev->type == ARPHRD_IEEE802_TR) {
793 unsigned char *sadr = skb->mac.raw;
794 if (((sadr[8] ^ dev->dev_addr[0]) & 0x7f) == 0 &&
795 sadr[9] == dev->dev_addr[1] &&
796 sadr[10] == dev->dev_addr[2] &&
797 sadr[11] == dev->dev_addr[3] &&
798 sadr[12] == dev->dev_addr[4] &&
799 sadr[13] == dev->dev_addr[5]) {
800 /* looped-back to us */
801 goto out;
802 }
803 }
804 addrconf_dad_failure(ifp);
805 return;
806 }
808 idev = ifp->idev;
809 } else {
810 idev = in6_dev_get(dev);
811 if (!idev) {
812 /* XXX: count this drop? */
813 return;
814 }
816 if (ipv6_chk_acast_addr(dev, &msg->target) ||
817 (idev->cnf.forwarding &&
818 pneigh_lookup(&nd_tbl, &msg->target, dev, 0))) {
819 if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) &&
820 skb->pkt_type != PACKET_HOST &&
821 inc != 0 &&
822 idev->nd_parms->proxy_delay != 0) {
823 /*
824 * for anycast or proxy,
825 * sender should delay its response
826 * by a random time between 0 and
827 * MAX_ANYCAST_DELAY_TIME seconds.
828 * (RFC2461) -- yoshfuji
829 */
830 struct sk_buff *n = skb_clone(skb, GFP_ATOMIC);
831 if (n)
832 pneigh_enqueue(&nd_tbl, idev->nd_parms, n);
833 goto out;
834 }
835 } else
836 goto out;
837 }
839 if (dad) {
840 struct in6_addr maddr;
842 ipv6_addr_all_nodes(&maddr);
843 ndisc_send_na(dev, NULL, &maddr, &msg->target,
844 idev->cnf.forwarding, 0, (ifp != NULL), 1);
845 goto out;
846 }
848 if (inc)
849 NEIGH_CACHE_STAT_INC(&nd_tbl, rcv_probes_mcast);
850 else
851 NEIGH_CACHE_STAT_INC(&nd_tbl, rcv_probes_ucast);
853 /*
854 * update / create cache entry
855 * for the source address
856 */
857 neigh = __neigh_lookup(&nd_tbl, saddr, dev,
858 !inc || lladdr || !dev->addr_len);
859 if (neigh)
860 neigh_update(neigh, lladdr, NUD_STALE,
861 NEIGH_UPDATE_F_WEAK_OVERRIDE|
862 NEIGH_UPDATE_F_OVERRIDE);
863 if (neigh || !dev->hard_header) {
864 ndisc_send_na(dev, neigh, saddr, &msg->target,
865 idev->cnf.forwarding,
866 1, (ifp != NULL && inc), inc);
867 if (neigh)
868 neigh_release(neigh);
869 }
871 out:
872 if (ifp)
873 in6_ifa_put(ifp);
874 else
875 in6_dev_put(idev);
877 return;
878 }
880 static void ndisc_recv_na(struct sk_buff *skb)
881 {
882 struct nd_msg *msg = (struct nd_msg *)skb->h.raw;
883 struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
884 struct in6_addr *daddr = &skb->nh.ipv6h->daddr;
885 u8 *lladdr = NULL;
886 u32 ndoptlen = skb->tail - msg->opt;
887 struct ndisc_options ndopts;
888 struct net_device *dev = skb->dev;
889 struct inet6_ifaddr *ifp;
890 struct neighbour *neigh;
892 if (skb->len < sizeof(struct nd_msg)) {
893 ND_PRINTK2(KERN_WARNING
894 "ICMPv6 NA: packet too short\n");
895 return;
896 }
898 if (ipv6_addr_is_multicast(&msg->target)) {
899 ND_PRINTK2(KERN_WARNING
900 "ICMPv6 NA: target address is multicast.\n");
901 return;
902 }
904 if (ipv6_addr_is_multicast(daddr) &&
905 msg->icmph.icmp6_solicited) {
906 ND_PRINTK2(KERN_WARNING
907 "ICMPv6 NA: solicited NA is multicasted.\n");
908 return;
909 }
911 if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts)) {
912 ND_PRINTK2(KERN_WARNING
913 "ICMPv6 NS: invalid ND option\n");
914 return;
915 }
916 if (ndopts.nd_opts_tgt_lladdr) {
917 lladdr = ndisc_opt_addr_data(ndopts.nd_opts_tgt_lladdr, dev);
918 if (!lladdr) {
919 ND_PRINTK2(KERN_WARNING
920 "ICMPv6 NA: invalid link-layer address length\n");
921 return;
922 }
923 }
924 if ((ifp = ipv6_get_ifaddr(&msg->target, dev, 1))) {
925 if (ifp->flags & IFA_F_TENTATIVE) {
926 addrconf_dad_failure(ifp);
927 return;
928 }
929 /* What should we make now? The advertisement
930 is invalid, but ndisc specs say nothing
931 about it. It could be misconfiguration, or
932 an smart proxy agent tries to help us :-)
933 */
934 ND_PRINTK1(KERN_WARNING
935 "ICMPv6 NA: someone advertises our address on %s!\n",
936 ifp->idev->dev->name);
937 in6_ifa_put(ifp);
938 return;
939 }
940 neigh = neigh_lookup(&nd_tbl, &msg->target, dev);
942 if (neigh) {
943 u8 old_flags = neigh->flags;
945 if (neigh->nud_state & NUD_FAILED)
946 goto out;
948 neigh_update(neigh, lladdr,
949 msg->icmph.icmp6_solicited ? NUD_REACHABLE : NUD_STALE,
950 NEIGH_UPDATE_F_WEAK_OVERRIDE|
951 (msg->icmph.icmp6_override ? NEIGH_UPDATE_F_OVERRIDE : 0)|
952 NEIGH_UPDATE_F_OVERRIDE_ISROUTER|
953 (msg->icmph.icmp6_router ? NEIGH_UPDATE_F_ISROUTER : 0));
955 if ((old_flags & ~neigh->flags) & NTF_ROUTER) {
956 /*
957 * Change: router to host
958 */
959 struct rt6_info *rt;
960 rt = rt6_get_dflt_router(saddr, dev);
961 if (rt)
962 ip6_del_rt(rt, NULL, NULL, NULL);
963 }
965 out:
966 neigh_release(neigh);
967 }
968 }
970 static void ndisc_recv_rs(struct sk_buff *skb)
971 {
972 struct rs_msg *rs_msg = (struct rs_msg *) skb->h.raw;
973 unsigned long ndoptlen = skb->len - sizeof(*rs_msg);
974 struct neighbour *neigh;
975 struct inet6_dev *idev;
976 struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
977 struct ndisc_options ndopts;
978 u8 *lladdr = NULL;
980 if (skb->len < sizeof(*rs_msg))
981 return;
983 idev = in6_dev_get(skb->dev);
984 if (!idev) {
985 if (net_ratelimit())
986 ND_PRINTK1("ICMP6 RS: can't find in6 device\n");
987 return;
988 }
990 /* Don't accept RS if we're not in router mode */
991 if (!idev->cnf.forwarding)
992 goto out;
994 /*
995 * Don't update NCE if src = ::;
996 * this implies that the source node has no ip address assigned yet.
997 */
998 if (ipv6_addr_any(saddr))
999 goto out;
1001 /* Parse ND options */
1002 if (!ndisc_parse_options(rs_msg->opt, ndoptlen, &ndopts)) {
1003 if (net_ratelimit())
1004 ND_PRINTK2("ICMP6 NS: invalid ND option, ignored\n");
1005 goto out;
1008 if (ndopts.nd_opts_src_lladdr) {
1009 lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr,
1010 skb->dev);
1011 if (!lladdr)
1012 goto out;
1015 neigh = __neigh_lookup(&nd_tbl, saddr, skb->dev, 1);
1016 if (neigh) {
1017 neigh_update(neigh, lladdr, NUD_STALE,
1018 NEIGH_UPDATE_F_WEAK_OVERRIDE|
1019 NEIGH_UPDATE_F_OVERRIDE|
1020 NEIGH_UPDATE_F_OVERRIDE_ISROUTER);
1021 neigh_release(neigh);
1023 out:
1024 in6_dev_put(idev);
1027 static void ndisc_router_discovery(struct sk_buff *skb)
1029 struct ra_msg *ra_msg = (struct ra_msg *) skb->h.raw;
1030 struct neighbour *neigh = NULL;
1031 struct inet6_dev *in6_dev;
1032 struct rt6_info *rt = NULL;
1033 int lifetime;
1034 struct ndisc_options ndopts;
1035 int optlen;
1036 unsigned int pref = 0;
1038 __u8 * opt = (__u8 *)(ra_msg + 1);
1040 optlen = (skb->tail - skb->h.raw) - sizeof(struct ra_msg);
1042 if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr) & IPV6_ADDR_LINKLOCAL)) {
1043 ND_PRINTK2(KERN_WARNING
1044 "ICMPv6 RA: source address is not link-local.\n");
1045 return;
1047 if (optlen < 0) {
1048 ND_PRINTK2(KERN_WARNING
1049 "ICMPv6 RA: packet too short\n");
1050 return;
1053 /*
1054 * set the RA_RECV flag in the interface
1055 */
1057 in6_dev = in6_dev_get(skb->dev);
1058 if (in6_dev == NULL) {
1059 ND_PRINTK0(KERN_ERR
1060 "ICMPv6 RA: can't find inet6 device for %s.\n",
1061 skb->dev->name);
1062 return;
1064 if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra) {
1065 in6_dev_put(in6_dev);
1066 return;
1069 if (!ndisc_parse_options(opt, optlen, &ndopts)) {
1070 in6_dev_put(in6_dev);
1071 ND_PRINTK2(KERN_WARNING
1072 "ICMP6 RA: invalid ND options\n");
1073 return;
1076 if (in6_dev->if_flags & IF_RS_SENT) {
1077 /*
1078 * flag that an RA was received after an RS was sent
1079 * out on this interface.
1080 */
1081 in6_dev->if_flags |= IF_RA_RCVD;
1084 /*
1085 * Remember the managed/otherconf flags from most recently
1086 * received RA message (RFC 2462) -- yoshfuji
1087 */
1088 in6_dev->if_flags = (in6_dev->if_flags & ~(IF_RA_MANAGED |
1089 IF_RA_OTHERCONF)) |
1090 (ra_msg->icmph.icmp6_addrconf_managed ?
1091 IF_RA_MANAGED : 0) |
1092 (ra_msg->icmph.icmp6_addrconf_other ?
1093 IF_RA_OTHERCONF : 0);
1095 if (!in6_dev->cnf.accept_ra_defrtr)
1096 goto skip_defrtr;
1098 lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime);
1100 #ifdef CONFIG_IPV6_ROUTER_PREF
1101 pref = ra_msg->icmph.icmp6_router_pref;
1102 /* 10b is handled as if it were 00b (medium) */
1103 if (pref == ICMPV6_ROUTER_PREF_INVALID ||
1104 in6_dev->cnf.accept_ra_rtr_pref)
1105 pref = ICMPV6_ROUTER_PREF_MEDIUM;
1106 #endif
1108 rt = rt6_get_dflt_router(&skb->nh.ipv6h->saddr, skb->dev);
1110 if (rt)
1111 neigh = rt->rt6i_nexthop;
1113 if (rt && lifetime == 0) {
1114 neigh_clone(neigh);
1115 ip6_del_rt(rt, NULL, NULL, NULL);
1116 rt = NULL;
1119 if (rt == NULL && lifetime) {
1120 ND_PRINTK3(KERN_DEBUG
1121 "ICMPv6 RA: adding default router.\n");
1123 rt = rt6_add_dflt_router(&skb->nh.ipv6h->saddr, skb->dev, pref);
1124 if (rt == NULL) {
1125 ND_PRINTK0(KERN_ERR
1126 "ICMPv6 RA: %s() failed to add default route.\n",
1127 __FUNCTION__);
1128 in6_dev_put(in6_dev);
1129 return;
1132 neigh = rt->rt6i_nexthop;
1133 if (neigh == NULL) {
1134 ND_PRINTK0(KERN_ERR
1135 "ICMPv6 RA: %s() got default router without neighbour.\n",
1136 __FUNCTION__);
1137 dst_release(&rt->u.dst);
1138 in6_dev_put(in6_dev);
1139 return;
1141 neigh->flags |= NTF_ROUTER;
1142 } else if (rt) {
1143 rt->rt6i_flags |= (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref);
1146 if (rt)
1147 rt->rt6i_expires = jiffies + (HZ * lifetime);
1149 if (ra_msg->icmph.icmp6_hop_limit) {
1150 in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit;
1151 if (rt)
1152 rt->u.dst.metrics[RTAX_HOPLIMIT-1] = ra_msg->icmph.icmp6_hop_limit;
1155 skip_defrtr:
1157 /*
1158 * Update Reachable Time and Retrans Timer
1159 */
1161 if (in6_dev->nd_parms) {
1162 unsigned long rtime = ntohl(ra_msg->retrans_timer);
1164 if (rtime && rtime/1000 < MAX_SCHEDULE_TIMEOUT/HZ) {
1165 rtime = (rtime*HZ)/1000;
1166 if (rtime < HZ/10)
1167 rtime = HZ/10;
1168 in6_dev->nd_parms->retrans_time = rtime;
1169 in6_dev->tstamp = jiffies;
1170 inet6_ifinfo_notify(RTM_NEWLINK, in6_dev);
1173 rtime = ntohl(ra_msg->reachable_time);
1174 if (rtime && rtime/1000 < MAX_SCHEDULE_TIMEOUT/(3*HZ)) {
1175 rtime = (rtime*HZ)/1000;
1177 if (rtime < HZ/10)
1178 rtime = HZ/10;
1180 if (rtime != in6_dev->nd_parms->base_reachable_time) {
1181 in6_dev->nd_parms->base_reachable_time = rtime;
1182 in6_dev->nd_parms->gc_staletime = 3 * rtime;
1183 in6_dev->nd_parms->reachable_time = neigh_rand_reach_time(rtime);
1184 in6_dev->tstamp = jiffies;
1185 inet6_ifinfo_notify(RTM_NEWLINK, in6_dev);
1190 /*
1191 * Process options.
1192 */
1194 if (!neigh)
1195 neigh = __neigh_lookup(&nd_tbl, &skb->nh.ipv6h->saddr,
1196 skb->dev, 1);
1197 if (neigh) {
1198 u8 *lladdr = NULL;
1199 if (ndopts.nd_opts_src_lladdr) {
1200 lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr,
1201 skb->dev);
1202 if (!lladdr) {
1203 ND_PRINTK2(KERN_WARNING
1204 "ICMPv6 RA: invalid link-layer address length\n");
1205 goto out;
1208 neigh_update(neigh, lladdr, NUD_STALE,
1209 NEIGH_UPDATE_F_WEAK_OVERRIDE|
1210 NEIGH_UPDATE_F_OVERRIDE|
1211 NEIGH_UPDATE_F_OVERRIDE_ISROUTER|
1212 NEIGH_UPDATE_F_ISROUTER);
1215 #ifdef CONFIG_IPV6_ROUTE_INFO
1216 if (in6_dev->cnf.accept_ra_rtr_pref && ndopts.nd_opts_ri) {
1217 struct nd_opt_hdr *p;
1218 for (p = ndopts.nd_opts_ri;
1219 p;
1220 p = ndisc_next_option(p, ndopts.nd_opts_ri_end)) {
1221 if (((struct route_info *)p)->prefix_len > in6_dev->cnf.accept_ra_rt_info_max_plen)
1222 continue;
1223 rt6_route_rcv(skb->dev, (u8*)p, (p->nd_opt_len) << 3,
1224 &skb->nh.ipv6h->saddr);
1227 #endif
1229 if (in6_dev->cnf.accept_ra_pinfo && ndopts.nd_opts_pi) {
1230 struct nd_opt_hdr *p;
1231 for (p = ndopts.nd_opts_pi;
1232 p;
1233 p = ndisc_next_option(p, ndopts.nd_opts_pi_end)) {
1234 addrconf_prefix_rcv(skb->dev, (u8*)p, (p->nd_opt_len) << 3);
1238 if (ndopts.nd_opts_mtu) {
1239 u32 mtu;
1241 memcpy(&mtu, ((u8*)(ndopts.nd_opts_mtu+1))+2, sizeof(mtu));
1242 mtu = ntohl(mtu);
1244 if (mtu < IPV6_MIN_MTU || mtu > skb->dev->mtu) {
1245 ND_PRINTK2(KERN_WARNING
1246 "ICMPv6 RA: invalid mtu: %d\n",
1247 mtu);
1248 } else if (in6_dev->cnf.mtu6 != mtu) {
1249 in6_dev->cnf.mtu6 = mtu;
1251 if (rt)
1252 rt->u.dst.metrics[RTAX_MTU-1] = mtu;
1254 rt6_mtu_change(skb->dev, mtu);
1258 if (ndopts.nd_opts_tgt_lladdr || ndopts.nd_opts_rh) {
1259 ND_PRINTK2(KERN_WARNING
1260 "ICMPv6 RA: invalid RA options");
1262 out:
1263 if (rt)
1264 dst_release(&rt->u.dst);
1265 else if (neigh)
1266 neigh_release(neigh);
1267 in6_dev_put(in6_dev);
1270 static void ndisc_redirect_rcv(struct sk_buff *skb)
1272 struct inet6_dev *in6_dev;
1273 struct icmp6hdr *icmph;
1274 struct in6_addr *dest;
1275 struct in6_addr *target; /* new first hop to destination */
1276 struct neighbour *neigh;
1277 int on_link = 0;
1278 struct ndisc_options ndopts;
1279 int optlen;
1280 u8 *lladdr = NULL;
1282 if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr) & IPV6_ADDR_LINKLOCAL)) {
1283 ND_PRINTK2(KERN_WARNING
1284 "ICMPv6 Redirect: source address is not link-local.\n");
1285 return;
1288 optlen = skb->tail - skb->h.raw;
1289 optlen -= sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr);
1291 if (optlen < 0) {
1292 ND_PRINTK2(KERN_WARNING
1293 "ICMPv6 Redirect: packet too short\n");
1294 return;
1297 icmph = (struct icmp6hdr *) skb->h.raw;
1298 target = (struct in6_addr *) (icmph + 1);
1299 dest = target + 1;
1301 if (ipv6_addr_is_multicast(dest)) {
1302 ND_PRINTK2(KERN_WARNING
1303 "ICMPv6 Redirect: destination address is multicast.\n");
1304 return;
1307 if (ipv6_addr_equal(dest, target)) {
1308 on_link = 1;
1309 } else if (!(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) {
1310 ND_PRINTK2(KERN_WARNING
1311 "ICMPv6 Redirect: target address is not link-local.\n");
1312 return;
1315 in6_dev = in6_dev_get(skb->dev);
1316 if (!in6_dev)
1317 return;
1318 if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_redirects) {
1319 in6_dev_put(in6_dev);
1320 return;
1323 /* RFC2461 8.1:
1324 * The IP source address of the Redirect MUST be the same as the current
1325 * first-hop router for the specified ICMP Destination Address.
1326 */
1328 if (!ndisc_parse_options((u8*)(dest + 1), optlen, &ndopts)) {
1329 ND_PRINTK2(KERN_WARNING
1330 "ICMPv6 Redirect: invalid ND options\n");
1331 in6_dev_put(in6_dev);
1332 return;
1334 if (ndopts.nd_opts_tgt_lladdr) {
1335 lladdr = ndisc_opt_addr_data(ndopts.nd_opts_tgt_lladdr,
1336 skb->dev);
1337 if (!lladdr) {
1338 ND_PRINTK2(KERN_WARNING
1339 "ICMPv6 Redirect: invalid link-layer address length\n");
1340 in6_dev_put(in6_dev);
1341 return;
1345 neigh = __neigh_lookup(&nd_tbl, target, skb->dev, 1);
1346 if (neigh) {
1347 rt6_redirect(dest, &skb->nh.ipv6h->saddr, neigh, lladdr,
1348 on_link);
1349 neigh_release(neigh);
1351 in6_dev_put(in6_dev);
1354 void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
1355 struct in6_addr *target)
1357 struct sock *sk = ndisc_socket->sk;
1358 int len = sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr);
1359 struct sk_buff *buff;
1360 struct icmp6hdr *icmph;
1361 struct in6_addr saddr_buf;
1362 struct in6_addr *addrp;
1363 struct net_device *dev;
1364 struct rt6_info *rt;
1365 struct dst_entry *dst;
1366 struct inet6_dev *idev;
1367 struct flowi fl;
1368 u8 *opt;
1369 int rd_len;
1370 int err;
1371 int hlen;
1372 u8 ha_buf[MAX_ADDR_LEN], *ha = NULL;
1374 dev = skb->dev;
1376 if (ipv6_get_lladdr(dev, &saddr_buf)) {
1377 ND_PRINTK2(KERN_WARNING
1378 "ICMPv6 Redirect: no link-local address on %s\n",
1379 dev->name);
1380 return;
1383 ndisc_flow_init(&fl, NDISC_REDIRECT, &saddr_buf, &skb->nh.ipv6h->saddr);
1385 dst = ip6_route_output(NULL, &fl);
1386 if (dst == NULL)
1387 return;
1389 err = xfrm_lookup(&dst, &fl, NULL, 0);
1390 if (err)
1391 return;
1393 rt = (struct rt6_info *) dst;
1395 if (rt->rt6i_flags & RTF_GATEWAY) {
1396 ND_PRINTK2(KERN_WARNING
1397 "ICMPv6 Redirect: destination is not a neighbour.\n");
1398 dst_release(dst);
1399 return;
1401 if (!xrlim_allow(dst, 1*HZ)) {
1402 dst_release(dst);
1403 return;
1406 if (dev->addr_len) {
1407 read_lock_bh(&neigh->lock);
1408 if (neigh->nud_state & NUD_VALID) {
1409 memcpy(ha_buf, neigh->ha, dev->addr_len);
1410 read_unlock_bh(&neigh->lock);
1411 ha = ha_buf;
1412 len += ndisc_opt_addr_space(dev);
1413 } else
1414 read_unlock_bh(&neigh->lock);
1417 rd_len = min_t(unsigned int,
1418 IPV6_MIN_MTU-sizeof(struct ipv6hdr)-len, skb->len + 8);
1419 rd_len &= ~0x7;
1420 len += rd_len;
1422 buff = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
1423 1, &err);
1424 if (buff == NULL) {
1425 ND_PRINTK0(KERN_ERR
1426 "ICMPv6 Redirect: %s() failed to allocate an skb.\n",
1427 __FUNCTION__);
1428 dst_release(dst);
1429 return;
1432 hlen = 0;
1434 skb_reserve(buff, LL_RESERVED_SPACE(dev));
1435 ip6_nd_hdr(sk, buff, dev, &saddr_buf, &skb->nh.ipv6h->saddr,
1436 IPPROTO_ICMPV6, len);
1438 icmph = (struct icmp6hdr *)skb_put(buff, len);
1439 buff->h.raw = (unsigned char*)icmph;
1441 memset(icmph, 0, sizeof(struct icmp6hdr));
1442 icmph->icmp6_type = NDISC_REDIRECT;
1444 /*
1445 * copy target and destination addresses
1446 */
1448 addrp = (struct in6_addr *)(icmph + 1);
1449 ipv6_addr_copy(addrp, target);
1450 addrp++;
1451 ipv6_addr_copy(addrp, &skb->nh.ipv6h->daddr);
1453 opt = (u8*) (addrp + 1);
1455 /*
1456 * include target_address option
1457 */
1459 if (ha)
1460 opt = ndisc_fill_addr_option(opt, ND_OPT_TARGET_LL_ADDR, ha,
1461 dev->addr_len, dev->type);
1463 /*
1464 * build redirect option and copy skb over to the new packet.
1465 */
1467 memset(opt, 0, 8);
1468 *(opt++) = ND_OPT_REDIRECT_HDR;
1469 *(opt++) = (rd_len >> 3);
1470 opt += 6;
1472 memcpy(opt, skb->nh.ipv6h, rd_len - 8);
1474 icmph->icmp6_cksum = csum_ipv6_magic(&saddr_buf, &skb->nh.ipv6h->saddr,
1475 len, IPPROTO_ICMPV6,
1476 csum_partial((u8 *) icmph, len, 0));
1478 buff->dst = dst;
1479 idev = in6_dev_get(dst->dev);
1480 IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
1481 err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, buff, NULL, dst->dev, dst_output);
1482 if (!err) {
1483 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTREDIRECTS);
1484 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
1487 if (likely(idev != NULL))
1488 in6_dev_put(idev);
1491 static void pndisc_redo(struct sk_buff *skb)
1493 ndisc_recv_ns(skb);
1494 kfree_skb(skb);
1497 int ndisc_rcv(struct sk_buff *skb)
1499 struct nd_msg *msg;
1501 if (!pskb_may_pull(skb, skb->len))
1502 return 0;
1504 msg = (struct nd_msg *) skb->h.raw;
1506 __skb_push(skb, skb->data-skb->h.raw);
1508 if (skb->nh.ipv6h->hop_limit != 255) {
1509 ND_PRINTK2(KERN_WARNING
1510 "ICMPv6 NDISC: invalid hop-limit: %d\n",
1511 skb->nh.ipv6h->hop_limit);
1512 return 0;
1515 if (msg->icmph.icmp6_code != 0) {
1516 ND_PRINTK2(KERN_WARNING
1517 "ICMPv6 NDISC: invalid ICMPv6 code: %d\n",
1518 msg->icmph.icmp6_code);
1519 return 0;
1522 memset(NEIGH_CB(skb), 0, sizeof(struct neighbour_cb));
1524 switch (msg->icmph.icmp6_type) {
1525 case NDISC_NEIGHBOUR_SOLICITATION:
1526 ndisc_recv_ns(skb);
1527 break;
1529 case NDISC_NEIGHBOUR_ADVERTISEMENT:
1530 ndisc_recv_na(skb);
1531 break;
1533 case NDISC_ROUTER_SOLICITATION:
1534 ndisc_recv_rs(skb);
1535 break;
1537 case NDISC_ROUTER_ADVERTISEMENT:
1538 ndisc_router_discovery(skb);
1539 break;
1541 case NDISC_REDIRECT:
1542 ndisc_redirect_rcv(skb);
1543 break;
1544 };
1546 return 0;
1549 static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
1551 struct net_device *dev = ptr;
1553 switch (event) {
1554 case NETDEV_CHANGEADDR:
1555 neigh_changeaddr(&nd_tbl, dev);
1556 fib6_run_gc(~0UL);
1557 break;
1558 case NETDEV_DOWN:
1559 neigh_ifdown(&nd_tbl, dev);
1560 fib6_run_gc(~0UL);
1561 break;
1562 default:
1563 break;
1566 return NOTIFY_DONE;
1569 static struct notifier_block ndisc_netdev_notifier = {
1570 .notifier_call = ndisc_netdev_event,
1571 };
1573 #ifdef CONFIG_SYSCTL
1574 static void ndisc_warn_deprecated_sysctl(struct ctl_table *ctl,
1575 const char *func, const char *dev_name)
1577 static char warncomm[TASK_COMM_LEN];
1578 static int warned;
1579 if (strcmp(warncomm, current->comm) && warned < 5) {
1580 strcpy(warncomm, current->comm);
1581 printk(KERN_WARNING
1582 "process `%s' is using deprecated sysctl (%s) "
1583 "net.ipv6.neigh.%s.%s; "
1584 "Use net.ipv6.neigh.%s.%s_ms "
1585 "instead.\n",
1586 warncomm, func,
1587 dev_name, ctl->procname,
1588 dev_name, ctl->procname);
1589 warned++;
1593 int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, struct file * filp, void __user *buffer, size_t *lenp, loff_t *ppos)
1595 struct net_device *dev = ctl->extra1;
1596 struct inet6_dev *idev;
1597 int ret;
1599 if (ctl->ctl_name == NET_NEIGH_RETRANS_TIME ||
1600 ctl->ctl_name == NET_NEIGH_REACHABLE_TIME)
1601 ndisc_warn_deprecated_sysctl(ctl, "syscall", dev ? dev->name : "default");
1603 switch (ctl->ctl_name) {
1604 case NET_NEIGH_RETRANS_TIME:
1605 ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
1606 break;
1607 case NET_NEIGH_REACHABLE_TIME:
1608 ret = proc_dointvec_jiffies(ctl, write,
1609 filp, buffer, lenp, ppos);
1610 break;
1611 case NET_NEIGH_RETRANS_TIME_MS:
1612 case NET_NEIGH_REACHABLE_TIME_MS:
1613 ret = proc_dointvec_ms_jiffies(ctl, write,
1614 filp, buffer, lenp, ppos);
1615 break;
1616 default:
1617 ret = -1;
1620 if (write && ret == 0 && dev && (idev = in6_dev_get(dev)) != NULL) {
1621 if (ctl->ctl_name == NET_NEIGH_REACHABLE_TIME ||
1622 ctl->ctl_name == NET_NEIGH_REACHABLE_TIME_MS)
1623 idev->nd_parms->reachable_time = neigh_rand_reach_time(idev->nd_parms->base_reachable_time);
1624 idev->tstamp = jiffies;
1625 inet6_ifinfo_notify(RTM_NEWLINK, idev);
1626 in6_dev_put(idev);
1628 return ret;
1631 static int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl, int __user *name,
1632 int nlen, void __user *oldval,
1633 size_t __user *oldlenp,
1634 void __user *newval, size_t newlen,
1635 void **context)
1637 struct net_device *dev = ctl->extra1;
1638 struct inet6_dev *idev;
1639 int ret;
1641 if (ctl->ctl_name == NET_NEIGH_RETRANS_TIME ||
1642 ctl->ctl_name == NET_NEIGH_REACHABLE_TIME)
1643 ndisc_warn_deprecated_sysctl(ctl, "procfs", dev ? dev->name : "default");
1645 switch (ctl->ctl_name) {
1646 case NET_NEIGH_REACHABLE_TIME:
1647 ret = sysctl_jiffies(ctl, name, nlen,
1648 oldval, oldlenp, newval, newlen,
1649 context);
1650 break;
1651 case NET_NEIGH_RETRANS_TIME_MS:
1652 case NET_NEIGH_REACHABLE_TIME_MS:
1653 ret = sysctl_ms_jiffies(ctl, name, nlen,
1654 oldval, oldlenp, newval, newlen,
1655 context);
1656 break;
1657 default:
1658 ret = 0;
1661 if (newval && newlen && ret > 0 &&
1662 dev && (idev = in6_dev_get(dev)) != NULL) {
1663 if (ctl->ctl_name == NET_NEIGH_REACHABLE_TIME ||
1664 ctl->ctl_name == NET_NEIGH_REACHABLE_TIME_MS)
1665 idev->nd_parms->reachable_time = neigh_rand_reach_time(idev->nd_parms->base_reachable_time);
1666 idev->tstamp = jiffies;
1667 inet6_ifinfo_notify(RTM_NEWLINK, idev);
1668 in6_dev_put(idev);
1671 return ret;
1674 #endif
1676 int __init ndisc_init(struct net_proto_family *ops)
1678 struct ipv6_pinfo *np;
1679 struct sock *sk;
1680 int err;
1682 err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &ndisc_socket);
1683 if (err < 0) {
1684 ND_PRINTK0(KERN_ERR
1685 "ICMPv6 NDISC: Failed to initialize the control socket (err %d).\n",
1686 err);
1687 ndisc_socket = NULL; /* For safety. */
1688 return err;
1691 sk = ndisc_socket->sk;
1692 np = inet6_sk(sk);
1693 sk->sk_allocation = GFP_ATOMIC;
1694 np->hop_limit = 255;
1695 /* Do not loopback ndisc messages */
1696 np->mc_loop = 0;
1697 sk->sk_prot->unhash(sk);
1699 /*
1700 * Initialize the neighbour table
1701 */
1703 neigh_table_init(&nd_tbl);
1705 #ifdef CONFIG_SYSCTL
1706 neigh_sysctl_register(NULL, &nd_tbl.parms, NET_IPV6, NET_IPV6_NEIGH,
1707 "ipv6",
1708 &ndisc_ifinfo_sysctl_change,
1709 &ndisc_ifinfo_sysctl_strategy);
1710 #endif
1712 register_netdevice_notifier(&ndisc_netdev_notifier);
1713 return 0;
1716 void ndisc_cleanup(void)
1718 #ifdef CONFIG_SYSCTL
1719 neigh_sysctl_unregister(&nd_tbl.parms);
1720 #endif
1721 neigh_table_clear(&nd_tbl);
1722 sock_release(ndisc_socket);
1723 ndisc_socket = NULL; /* For safety. */