Import 2.3.41pre2
[davej-history.git] / net / ipv6 / ndisc.c
blob4a9af93e1c209fd58744c5fe81c128fc9d32fb2f
1 /*
2 * Neighbour Discovery for IPv6
3 * Linux INET6 implementation
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
7 * Mike Shaver <shaver@ingenia.com>
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.
16 * Changes:
18 * Lars Fenneberg : fixed MTU setting on receipt
19 * of an RA.
21 * Janos Farkas : kmalloc failure checks
22 * Alexey Kuznetsov : state machine reworked
23 * and moved to net/core.
26 /* Set to 3 to get tracing... */
27 #define ND_DEBUG 1
29 #define ND_PRINTK(x...) printk(KERN_DEBUG x)
30 #define ND_NOPRINTK(x...) do { ; } while(0)
31 #define ND_PRINTK0 ND_PRINTK
32 #define ND_PRINTK1 ND_NOPRINTK
33 #define ND_PRINTK2 ND_NOPRINTK
34 #if ND_DEBUG >= 1
35 #undef ND_PRINTK1
36 #define ND_PRINTK1 ND_PRINTK
37 #endif
38 #if ND_DEBUG >= 2
39 #undef ND_PRINTK2
40 #define ND_PRINTK2 ND_PRINTK
41 #endif
43 #define __NO_VERSION__
44 #include <linux/module.h>
45 #include <linux/config.h>
46 #include <linux/errno.h>
47 #include <linux/types.h>
48 #include <linux/socket.h>
49 #include <linux/sockios.h>
50 #include <linux/sched.h>
51 #include <linux/net.h>
52 #include <linux/in6.h>
53 #include <linux/route.h>
54 #include <linux/init.h>
55 #ifdef CONFIG_SYSCTL
56 #include <linux/sysctl.h>
57 #endif
59 #include <linux/if_arp.h>
60 #include <linux/ipv6.h>
61 #include <linux/icmpv6.h>
63 #include <net/sock.h>
64 #include <net/snmp.h>
66 #include <net/ipv6.h>
67 #include <net/protocol.h>
68 #include <net/ndisc.h>
69 #include <net/ip6_route.h>
70 #include <net/addrconf.h>
71 #include <net/icmp.h>
73 #include <net/checksum.h>
74 #include <linux/proc_fs.h>
76 static struct socket *ndisc_socket;
78 static u32 ndisc_hash(const void *pkey, const struct net_device *dev);
79 static int ndisc_constructor(struct neighbour *neigh);
80 static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb);
81 static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb);
82 static int pndisc_constructor(struct pneigh_entry *n);
83 static void pndisc_destructor(struct pneigh_entry *n);
84 static void pndisc_redo(struct sk_buff *skb);
86 static struct neigh_ops ndisc_generic_ops =
88 AF_INET6,
89 NULL,
90 ndisc_solicit,
91 ndisc_error_report,
92 neigh_resolve_output,
93 neigh_connected_output,
94 dev_queue_xmit,
95 dev_queue_xmit
98 static struct neigh_ops ndisc_hh_ops =
100 AF_INET6,
101 NULL,
102 ndisc_solicit,
103 ndisc_error_report,
104 neigh_resolve_output,
105 neigh_resolve_output,
106 dev_queue_xmit,
107 dev_queue_xmit
111 static struct neigh_ops ndisc_direct_ops =
113 AF_INET6,
114 NULL,
115 NULL,
116 NULL,
117 dev_queue_xmit,
118 dev_queue_xmit,
119 dev_queue_xmit,
120 dev_queue_xmit
123 struct neigh_table nd_tbl =
125 NULL,
126 AF_INET6,
127 sizeof(struct neighbour) + sizeof(struct in6_addr),
128 sizeof(struct in6_addr),
129 ndisc_hash,
130 ndisc_constructor,
131 pndisc_constructor,
132 pndisc_destructor,
133 pndisc_redo,
134 "ndisc_cache",
135 { NULL, NULL, &nd_tbl, 0, NULL, NULL,
136 30*HZ, 1*HZ, 60*HZ, 30*HZ, 5*HZ, 3, 3, 0, 3, 1*HZ, (8*HZ)/10, 64, 0 },
137 30*HZ, 128, 512, 1024,
140 #define NDISC_OPT_SPACE(len) (((len)+2+7)&~7)
142 static u8 *ndisc_fill_option(u8 *opt, int type, void *data, int data_len)
144 int space = NDISC_OPT_SPACE(data_len);
146 opt[0] = type;
147 opt[1] = space>>3;
148 memcpy(opt+2, data, data_len);
149 data_len += 2;
150 opt += data_len;
151 if ((space -= data_len) > 0)
152 memset(opt, 0, space);
153 return opt + space;
156 int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int dir)
158 switch (dev->type) {
159 case ARPHRD_ETHER:
160 case ARPHRD_IEEE802: /* Not sure. Check it later. --ANK */
161 case ARPHRD_FDDI:
162 ipv6_eth_mc_map(addr, buf);
163 return 0;
164 case ARPHRD_IEEE802_TR:
165 ipv6_tr_mc_map(addr,buf);
166 return 0;
167 default:
168 if (dir) {
169 memcpy(buf, dev->broadcast, dev->addr_len);
170 return 0;
173 return -EINVAL;
176 static u32 ndisc_hash(const void *pkey, const struct net_device *dev)
178 u32 hash_val;
180 hash_val = *(u32*)(pkey + sizeof(struct in6_addr) - 4);
181 hash_val ^= (hash_val>>16);
182 hash_val ^= hash_val>>8;
183 hash_val ^= hash_val>>3;
184 hash_val = (hash_val^dev->ifindex)&NEIGH_HASHMASK;
186 return hash_val;
189 static int ndisc_constructor(struct neighbour *neigh)
191 struct in6_addr *addr = (struct in6_addr*)&neigh->primary_key;
192 struct net_device *dev = neigh->dev;
193 struct inet6_dev *in6_dev = in6_dev_get(dev);
194 int addr_type;
196 if (in6_dev == NULL)
197 return -EINVAL;
199 addr_type = ipv6_addr_type(addr);
200 if (in6_dev->nd_parms)
201 neigh->parms = in6_dev->nd_parms;
203 if (addr_type&IPV6_ADDR_MULTICAST)
204 neigh->type = RTN_MULTICAST;
205 else
206 neigh->type = RTN_UNICAST;
207 if (dev->hard_header == NULL) {
208 neigh->nud_state = NUD_NOARP;
209 neigh->ops = &ndisc_direct_ops;
210 neigh->output = neigh->ops->queue_xmit;
211 } else {
212 if (addr_type&IPV6_ADDR_MULTICAST) {
213 neigh->nud_state = NUD_NOARP;
214 ndisc_mc_map(addr, neigh->ha, dev, 1);
215 } else if (dev->flags&(IFF_NOARP|IFF_LOOPBACK)) {
216 neigh->nud_state = NUD_NOARP;
217 memcpy(neigh->ha, dev->dev_addr, dev->addr_len);
218 if (dev->flags&IFF_LOOPBACK)
219 neigh->type = RTN_LOCAL;
220 } else if (dev->flags&IFF_POINTOPOINT) {
221 neigh->nud_state = NUD_NOARP;
222 memcpy(neigh->ha, dev->broadcast, dev->addr_len);
224 if (dev->hard_header_cache)
225 neigh->ops = &ndisc_hh_ops;
226 else
227 neigh->ops = &ndisc_generic_ops;
228 if (neigh->nud_state&NUD_VALID)
229 neigh->output = neigh->ops->connected_output;
230 else
231 neigh->output = neigh->ops->output;
233 in6_dev_put(in6_dev);
234 return 0;
237 static int pndisc_constructor(struct pneigh_entry *n)
239 struct in6_addr *addr = (struct in6_addr*)&n->key;
240 struct in6_addr maddr;
241 struct net_device *dev = n->dev;
243 if (dev == NULL || __in6_dev_get(dev) == NULL)
244 return -EINVAL;
245 #ifndef CONFIG_IPV6_NO_PB
246 addrconf_addr_solict_mult_old(addr, &maddr);
247 ipv6_dev_mc_inc(dev, &maddr);
248 #endif
249 #ifdef CONFIG_IPV6_EUI64
250 addrconf_addr_solict_mult_new(addr, &maddr);
251 ipv6_dev_mc_inc(dev, &maddr);
252 #endif
253 return 0;
256 static void pndisc_destructor(struct pneigh_entry *n)
258 struct in6_addr *addr = (struct in6_addr*)&n->key;
259 struct in6_addr maddr;
260 struct net_device *dev = n->dev;
262 if (dev == NULL || __in6_dev_get(dev) == NULL)
263 return;
264 #ifndef CONFIG_IPV6_NO_PB
265 addrconf_addr_solict_mult_old(addr, &maddr);
266 ipv6_dev_mc_dec(dev, &maddr);
267 #endif
268 #ifdef CONFIG_IPV6_EUI64
269 addrconf_addr_solict_mult_new(addr, &maddr);
270 ipv6_dev_mc_dec(dev, &maddr);
271 #endif
276 static int
277 ndisc_build_ll_hdr(struct sk_buff *skb, struct net_device *dev,
278 struct in6_addr *daddr, struct neighbour *neigh, int len)
280 unsigned char ha[MAX_ADDR_LEN];
281 unsigned char *h_dest = NULL;
283 skb_reserve(skb, (dev->hard_header_len + 15) & ~15);
285 if (dev->hard_header) {
286 if (ipv6_addr_type(daddr) & IPV6_ADDR_MULTICAST) {
287 ndisc_mc_map(daddr, ha, dev, 1);
288 h_dest = ha;
289 } else if (neigh) {
290 read_lock_bh(&neigh->lock);
291 if (neigh->nud_state&NUD_VALID) {
292 memcpy(ha, neigh->ha, dev->addr_len);
293 h_dest = ha;
295 read_unlock_bh(&neigh->lock);
296 } else {
297 neigh = neigh_lookup(&nd_tbl, daddr, dev);
298 if (neigh) {
299 read_lock_bh(&neigh->lock);
300 if (neigh->nud_state&NUD_VALID) {
301 memcpy(ha, neigh->ha, dev->addr_len);
302 h_dest = ha;
304 read_unlock_bh(&neigh->lock);
305 neigh_release(neigh);
309 if (dev->hard_header(skb, dev, ETH_P_IPV6, h_dest, NULL, len) < 0)
310 return 0;
313 return 1;
318 * Send a Neighbour Advertisement
321 void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
322 struct in6_addr *daddr, struct in6_addr *solicited_addr,
323 int router, int solicited, int override, int inc_opt)
325 struct sock *sk = ndisc_socket->sk;
326 struct nd_msg *msg;
327 int len;
328 struct sk_buff *skb;
329 int err;
331 len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
333 if (inc_opt) {
334 if (dev->addr_len)
335 len += NDISC_OPT_SPACE(dev->addr_len);
336 else
337 inc_opt = 0;
340 skb = sock_alloc_send_skb(sk, MAX_HEADER + len + dev->hard_header_len + 15,
341 0, 0, &err);
343 if (skb == NULL) {
344 ND_PRINTK1("send_na: alloc skb failed\n");
345 return;
348 if (ndisc_build_ll_hdr(skb, dev, daddr, neigh, len) == 0) {
349 kfree_skb(skb);
350 return;
353 ip6_nd_hdr(sk, skb, dev, solicited_addr, daddr, IPPROTO_ICMPV6, len);
355 msg = (struct nd_msg *) skb_put(skb, len);
357 msg->icmph.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT;
358 msg->icmph.icmp6_code = 0;
359 msg->icmph.icmp6_cksum = 0;
361 msg->icmph.icmp6_unused = 0;
362 msg->icmph.icmp6_router = router;
363 msg->icmph.icmp6_solicited = solicited;
364 msg->icmph.icmp6_override = !!override;
366 /* Set the target address. */
367 ipv6_addr_copy(&msg->target, solicited_addr);
369 if (inc_opt)
370 ndisc_fill_option((void*)&msg->opt, ND_OPT_TARGET_LL_ADDR, dev->dev_addr, dev->addr_len);
372 /* checksum */
373 msg->icmph.icmp6_cksum = csum_ipv6_magic(solicited_addr, daddr, len,
374 IPPROTO_ICMPV6,
375 csum_partial((__u8 *) msg,
376 len, 0));
378 dev_queue_xmit(skb);
380 ICMP6_INC_STATS(Icmp6OutNeighborAdvertisements);
381 ICMP6_INC_STATS(Icmp6OutMsgs);
384 void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
385 struct in6_addr *solicit,
386 struct in6_addr *daddr, struct in6_addr *saddr)
388 struct sock *sk = ndisc_socket->sk;
389 struct sk_buff *skb;
390 struct nd_msg *msg;
391 struct in6_addr addr_buf;
392 int len;
393 int err;
395 len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
396 if (dev->addr_len)
397 len += NDISC_OPT_SPACE(dev->addr_len);
399 skb = sock_alloc_send_skb(sk, MAX_HEADER + len + dev->hard_header_len + 15,
400 0, 0, &err);
401 if (skb == NULL) {
402 ND_PRINTK1("send_ns: alloc skb failed\n");
403 return;
406 if (saddr == NULL) {
407 if (ipv6_get_lladdr(dev, &addr_buf)) {
408 kfree_skb(skb);
409 return;
411 saddr = &addr_buf;
414 if (ndisc_build_ll_hdr(skb, dev, daddr, neigh, len) == 0) {
415 kfree_skb(skb);
416 return;
419 ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len);
421 msg = (struct nd_msg *)skb_put(skb, len);
422 msg->icmph.icmp6_type = NDISC_NEIGHBOUR_SOLICITATION;
423 msg->icmph.icmp6_code = 0;
424 msg->icmph.icmp6_cksum = 0;
425 msg->icmph.icmp6_unused = 0;
427 /* Set the target address. */
428 ipv6_addr_copy(&msg->target, solicit);
430 if (dev->addr_len)
431 ndisc_fill_option((void*)&msg->opt, ND_OPT_SOURCE_LL_ADDR, dev->dev_addr, dev->addr_len);
433 /* checksum */
434 msg->icmph.icmp6_cksum = csum_ipv6_magic(&skb->nh.ipv6h->saddr,
435 daddr, len,
436 IPPROTO_ICMPV6,
437 csum_partial((__u8 *) msg,
438 len, 0));
439 /* send it! */
440 dev_queue_xmit(skb);
442 ICMP6_INC_STATS(Icmp6OutNeighborSolicits);
443 ICMP6_INC_STATS(Icmp6OutMsgs);
446 void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
447 struct in6_addr *daddr)
449 struct sock *sk = ndisc_socket->sk;
450 struct sk_buff *skb;
451 struct icmp6hdr *hdr;
452 __u8 * opt;
453 int len;
454 int err;
456 len = sizeof(struct icmp6hdr);
457 if (dev->addr_len)
458 len += NDISC_OPT_SPACE(dev->addr_len);
460 skb = sock_alloc_send_skb(sk, MAX_HEADER + len + dev->hard_header_len + 15,
461 0, 0, &err);
462 if (skb == NULL) {
463 ND_PRINTK1("send_ns: alloc skb failed\n");
464 return;
467 if (ndisc_build_ll_hdr(skb, dev, daddr, NULL, len) == 0) {
468 kfree_skb(skb);
469 return;
472 ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len);
474 hdr = (struct icmp6hdr *) skb_put(skb, len);
475 hdr->icmp6_type = NDISC_ROUTER_SOLICITATION;
476 hdr->icmp6_code = 0;
477 hdr->icmp6_cksum = 0;
478 hdr->icmp6_unused = 0;
480 opt = (u8*) (hdr + 1);
482 if (dev->addr_len)
483 ndisc_fill_option(opt, ND_OPT_SOURCE_LL_ADDR, dev->dev_addr, dev->addr_len);
485 /* checksum */
486 hdr->icmp6_cksum = csum_ipv6_magic(&skb->nh.ipv6h->saddr, daddr, len,
487 IPPROTO_ICMPV6,
488 csum_partial((__u8 *) hdr, len, 0));
490 /* send it! */
491 dev_queue_xmit(skb);
493 ICMP6_INC_STATS(Icmp6OutRouterSolicits);
494 ICMP6_INC_STATS(Icmp6OutMsgs);
498 static u8 * ndisc_find_option(u8 *opt, int opt_len, int len, int option)
500 while (opt_len <= len) {
501 int l = opt[1]<<3;
503 if (opt[0] == option && l >= opt_len)
504 return opt + 2;
506 if (l == 0) {
507 if (net_ratelimit())
508 printk(KERN_WARNING "ndisc: option has 0 len\n");
509 return NULL;
512 opt += l;
513 len -= l;
515 return NULL;
519 static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb)
522 * "The sender MUST return an ICMP
523 * destination unreachable"
525 dst_link_failure(skb);
526 kfree_skb(skb);
529 /* Called with locked neigh: either read or both */
531 static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
533 struct in6_addr *saddr = NULL;
534 struct in6_addr mcaddr;
535 struct net_device *dev = neigh->dev;
536 struct in6_addr *target = (struct in6_addr *)&neigh->primary_key;
537 int probes = atomic_read(&neigh->probes);
539 if (skb && ipv6_chk_addr(&skb->nh.ipv6h->saddr, dev))
540 saddr = &skb->nh.ipv6h->saddr;
542 if ((probes -= neigh->parms->ucast_probes) < 0) {
543 if (!(neigh->nud_state&NUD_VALID))
544 ND_PRINTK1("trying to ucast probe in NUD_INVALID\n");
545 ndisc_send_ns(dev, neigh, target, target, saddr);
546 } else if ((probes -= neigh->parms->app_probes) < 0) {
547 #ifdef CONFIG_ARPD
548 neigh_app_ns(neigh);
549 #endif
550 } else {
551 #ifdef CONFIG_IPV6_EUI64
552 addrconf_addr_solict_mult_new(target, &mcaddr);
553 ndisc_send_ns(dev, NULL, target, &mcaddr, saddr);
554 #endif
555 #ifndef CONFIG_IPV6_NO_PB
556 addrconf_addr_solict_mult_old(target, &mcaddr);
557 ndisc_send_ns(dev, NULL, target, &mcaddr, saddr);
558 #endif
563 static void ndisc_update(struct neighbour *neigh, u8* opt, int len, int type)
565 opt = ndisc_find_option(opt, neigh->dev->addr_len+2, len, type);
566 neigh_update(neigh, opt, NUD_STALE, 1, 1);
569 static void ndisc_router_discovery(struct sk_buff *skb)
571 struct ra_msg *ra_msg = (struct ra_msg *) skb->h.raw;
572 struct neighbour *neigh;
573 struct inet6_dev *in6_dev;
574 struct rt6_info *rt;
575 int lifetime;
576 int optlen;
578 __u8 * opt = (__u8 *)(ra_msg + 1);
580 optlen = (skb->tail - skb->h.raw) - sizeof(struct ra_msg);
582 if (skb->nh.ipv6h->hop_limit != 255) {
583 printk(KERN_INFO
584 "NDISC: fake router advertisment received\n");
585 return;
589 * set the RA_RECV flag in the interface
592 in6_dev = in6_dev_get(skb->dev);
593 if (in6_dev == NULL) {
594 ND_PRINTK1("RA: can't find in6 device\n");
595 return;
597 if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra) {
598 in6_dev_put(in6_dev);
599 return;
602 if (in6_dev->if_flags & IF_RS_SENT) {
604 * flag that an RA was received after an RS was sent
605 * out on this interface.
607 in6_dev->if_flags |= IF_RA_RCVD;
610 lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime);
612 rt = rt6_get_dflt_router(&skb->nh.ipv6h->saddr, skb->dev);
614 if (rt && lifetime == 0) {
615 ip6_del_rt(rt);
616 rt = NULL;
619 if (rt == NULL && lifetime) {
620 ND_PRINTK2("ndisc_rdisc: adding default router\n");
622 rt = rt6_add_dflt_router(&skb->nh.ipv6h->saddr, skb->dev);
623 if (rt == NULL) {
624 ND_PRINTK1("route_add failed\n");
625 in6_dev_put(in6_dev);
626 return;
629 neigh = rt->rt6i_nexthop;
630 if (neigh == NULL) {
631 ND_PRINTK1("nd: add default router: null neighbour\n");
632 dst_release(&rt->u.dst);
633 in6_dev_put(in6_dev);
634 return;
636 neigh->flags |= NTF_ROUTER;
639 * If we where using an "all destinations on link" route
640 * delete it
643 rt6_purge_dflt_routers(RTF_ALLONLINK);
646 if (rt)
647 rt->rt6i_expires = jiffies + (HZ * lifetime);
649 if (ra_msg->icmph.icmp6_hop_limit)
650 in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit;
653 * Update Reachable Time and Retrans Timer
656 if (in6_dev->nd_parms) {
657 if (ra_msg->retrans_timer)
658 in6_dev->nd_parms->retrans_time = (ntohl(ra_msg->retrans_timer)*HZ)/1000;
660 if (ra_msg->reachable_time) {
661 __u32 rtime = (ntohl(ra_msg->reachable_time)*HZ)/1000;
663 if (rtime != in6_dev->nd_parms->base_reachable_time) {
664 in6_dev->nd_parms->base_reachable_time = rtime;
665 in6_dev->nd_parms->gc_staletime = 3 * rtime;
666 in6_dev->nd_parms->reachable_time = neigh_rand_reach_time(rtime);
672 * Process options.
675 while (optlen > 0) {
676 int len = (opt[1] << 3);
678 if (len == 0) {
679 ND_PRINTK0("RA: opt has 0 len\n");
680 break;
683 switch(*opt) {
684 case ND_OPT_SOURCE_LL_ADDR:
686 if (rt == NULL)
687 break;
689 if ((neigh = rt->rt6i_nexthop) != NULL &&
690 skb->dev->addr_len + 2 >= len)
691 neigh_update(neigh, opt+2, NUD_STALE, 1, 1);
692 break;
694 case ND_OPT_PREFIX_INFO:
695 addrconf_prefix_rcv(skb->dev, opt, len);
696 break;
698 case ND_OPT_MTU:
700 int mtu;
702 mtu = htonl(*(__u32 *)(opt+4));
704 if (mtu < IPV6_MIN_MTU || mtu > skb->dev->mtu) {
705 ND_PRINTK0("NDISC: router "
706 "announcement with mtu = %d\n",
707 mtu);
708 break;
711 if (in6_dev->cnf.mtu6 != mtu) {
712 in6_dev->cnf.mtu6 = mtu;
714 if (rt)
715 rt->u.dst.pmtu = mtu;
717 rt6_mtu_change(skb->dev, mtu);
720 break;
722 case ND_OPT_TARGET_LL_ADDR:
723 case ND_OPT_REDIRECT_HDR:
724 ND_PRINTK0("got illegal option with RA");
725 break;
726 default:
727 ND_PRINTK0("unkown option in RA\n");
729 optlen -= len;
730 opt += len;
732 if (rt)
733 dst_release(&rt->u.dst);
734 in6_dev_put(in6_dev);
737 static void ndisc_redirect_rcv(struct sk_buff *skb)
739 struct inet6_dev *in6_dev;
740 struct icmp6hdr *icmph;
741 struct in6_addr *dest;
742 struct in6_addr *target; /* new first hop to destination */
743 struct neighbour *neigh;
744 int on_link = 0;
745 int optlen;
747 if (skb->nh.ipv6h->hop_limit != 255) {
748 printk(KERN_WARNING "NDISC: fake ICMP redirect received\n");
749 return;
752 if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr) & IPV6_ADDR_LINKLOCAL)) {
753 printk(KERN_WARNING "ICMP redirect: source address is not linklocal\n");
754 return;
757 optlen = skb->tail - skb->h.raw;
758 optlen -= sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr);
760 if (optlen < 0) {
761 printk(KERN_WARNING "ICMP redirect: packet too small\n");
762 return;
765 icmph = (struct icmp6hdr *) skb->h.raw;
766 target = (struct in6_addr *) (icmph + 1);
767 dest = target + 1;
769 if (ipv6_addr_type(dest) & IPV6_ADDR_MULTICAST) {
770 printk(KERN_WARNING "ICMP redirect for multicast addr\n");
771 return;
774 if (ipv6_addr_cmp(dest, target) == 0) {
775 on_link = 1;
776 } else if (!(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) {
777 printk(KERN_WARNING "ICMP redirect: target address is not linklocal\n");
778 return;
781 in6_dev = in6_dev_get(skb->dev);
782 if (!in6_dev)
783 return;
784 if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_redirects) {
785 in6_dev_put(in6_dev);
786 return;
789 /* passed validation tests */
792 We install redirect only if nexthop state is valid.
795 neigh = __neigh_lookup(&nd_tbl, target, skb->dev, 1);
796 if (neigh) {
797 ndisc_update(neigh, (u8*)(dest + 1), optlen, ND_OPT_TARGET_LL_ADDR);
798 if (neigh->nud_state&NUD_VALID)
799 rt6_redirect(dest, &skb->nh.ipv6h->saddr, neigh, on_link);
800 else
801 __neigh_event_send(neigh, NULL);
802 neigh_release(neigh);
804 in6_dev_put(in6_dev);
807 void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
808 struct in6_addr *target)
810 struct sock *sk = ndisc_socket->sk;
811 int len = sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr);
812 struct sk_buff *buff;
813 struct icmp6hdr *icmph;
814 struct in6_addr saddr_buf;
815 struct in6_addr *addrp;
816 struct net_device *dev;
817 struct rt6_info *rt;
818 u8 *opt;
819 int rd_len;
820 int err;
821 int hlen;
823 dev = skb->dev;
824 rt = rt6_lookup(&skb->nh.ipv6h->saddr, NULL, dev->ifindex, 1);
826 if (rt == NULL)
827 return;
829 if (rt->rt6i_flags & RTF_GATEWAY) {
830 ND_PRINTK1("ndisc_send_redirect: not a neighbour\n");
831 dst_release(&rt->u.dst);
832 return;
834 if (!xrlim_allow(&rt->u.dst, 1*HZ)) {
835 dst_release(&rt->u.dst);
836 return;
838 dst_release(&rt->u.dst);
840 if (dev->addr_len) {
841 if (neigh->nud_state&NUD_VALID) {
842 len += NDISC_OPT_SPACE(dev->addr_len);
843 } else {
844 /* If nexthop is not valid, do not redirect!
845 We will make it later, when will be sure,
846 that it is alive.
848 return;
852 rd_len = min(IPV6_MIN_MTU-sizeof(struct ipv6hdr)-len, skb->len + 8);
853 rd_len &= ~0x7;
854 len += rd_len;
856 if (ipv6_get_lladdr(dev, &saddr_buf)) {
857 ND_PRINTK1("redirect: no link_local addr for dev\n");
858 return;
861 buff = sock_alloc_send_skb(sk, MAX_HEADER + len + dev->hard_header_len + 15,
862 0, 0, &err);
863 if (buff == NULL) {
864 ND_PRINTK1("ndisc_send_redirect: alloc_skb failed\n");
865 return;
868 hlen = 0;
870 if (ndisc_build_ll_hdr(buff, dev, &skb->nh.ipv6h->saddr, NULL, len) == 0) {
871 kfree_skb(buff);
872 return;
875 ip6_nd_hdr(sk, buff, dev, &saddr_buf, &skb->nh.ipv6h->saddr,
876 IPPROTO_ICMPV6, len);
878 icmph = (struct icmp6hdr *) skb_put(buff, len);
880 memset(icmph, 0, sizeof(struct icmp6hdr));
881 icmph->icmp6_type = NDISC_REDIRECT;
884 * copy target and destination addresses
887 addrp = (struct in6_addr *)(icmph + 1);
888 ipv6_addr_copy(addrp, target);
889 addrp++;
890 ipv6_addr_copy(addrp, &skb->nh.ipv6h->daddr);
892 opt = (u8*) (addrp + 1);
895 * include target_address option
898 if (dev->addr_len)
899 opt = ndisc_fill_option(opt, ND_OPT_TARGET_LL_ADDR, neigh->ha, dev->addr_len);
902 * build redirect option and copy skb over to the new packet.
905 memset(opt, 0, 8);
906 *(opt++) = ND_OPT_REDIRECT_HDR;
907 *(opt++) = (rd_len >> 3);
908 opt += 6;
910 memcpy(opt, skb->nh.ipv6h, rd_len - 8);
912 icmph->icmp6_cksum = csum_ipv6_magic(&saddr_buf, &skb->nh.ipv6h->saddr,
913 len, IPPROTO_ICMPV6,
914 csum_partial((u8 *) icmph, len, 0));
916 dev_queue_xmit(buff);
918 ICMP6_INC_STATS(Icmp6OutRedirects);
919 ICMP6_INC_STATS(Icmp6OutMsgs);
922 static __inline__ struct neighbour *
923 ndisc_recv_ns(struct in6_addr *saddr, struct sk_buff *skb)
925 u8 *opt;
927 opt = skb->h.raw;
928 opt += sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
929 opt = ndisc_find_option(opt, skb->dev->addr_len+2, skb->tail - opt, ND_OPT_SOURCE_LL_ADDR);
931 return neigh_event_ns(&nd_tbl, opt, saddr, skb->dev);
934 static __inline__ int ndisc_recv_na(struct neighbour *neigh, struct sk_buff *skb)
936 struct nd_msg *msg = (struct nd_msg *) skb->h.raw;
937 u8 *opt;
939 opt = skb->h.raw;
940 opt += sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
941 opt = ndisc_find_option(opt, skb->dev->addr_len+2, skb->tail - opt, ND_OPT_TARGET_LL_ADDR);
943 return neigh_update(neigh, opt,
944 msg->icmph.icmp6_solicited ? NUD_REACHABLE : NUD_STALE,
945 msg->icmph.icmp6_override, 1);
948 static void pndisc_redo(struct sk_buff *skb)
950 ndisc_rcv(skb, skb->len);
951 kfree_skb(skb);
954 int ndisc_rcv(struct sk_buff *skb, unsigned long len)
956 struct net_device *dev = skb->dev;
957 struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
958 struct in6_addr *daddr = &skb->nh.ipv6h->daddr;
959 struct nd_msg *msg = (struct nd_msg *) skb->h.raw;
960 struct neighbour *neigh;
961 struct inet6_ifaddr *ifp;
963 switch (msg->icmph.icmp6_type) {
964 case NDISC_NEIGHBOUR_SOLICITATION:
965 if ((ifp = ipv6_get_ifaddr(&msg->target, dev)) != NULL) {
966 int addr_type = ipv6_addr_type(saddr);
968 if (ifp->flags & IFA_F_TENTATIVE) {
969 /* Address is tentative. If the source
970 is unspecified address, it is someone
971 does DAD, otherwise we ignore solicitations
972 until DAD timer expires.
974 if (addr_type == IPV6_ADDR_ANY) {
975 if (dev->type == ARPHRD_IEEE802_TR) {
976 unsigned char *sadr = skb->mac.raw ;
977 if (((sadr[8] &0x7f) != (dev->dev_addr[0] & 0x7f)) ||
978 (sadr[9] != dev->dev_addr[1]) ||
979 (sadr[10] != dev->dev_addr[2]) ||
980 (sadr[11] != dev->dev_addr[3]) ||
981 (sadr[12] != dev->dev_addr[4]) ||
982 (sadr[13] != dev->dev_addr[5]))
984 addrconf_dad_failure(ifp) ;
986 } else {
987 addrconf_dad_failure(ifp);
989 } else
990 in6_ifa_put(ifp);
991 return 0;
994 if (addr_type == IPV6_ADDR_ANY) {
995 struct in6_addr maddr;
997 ipv6_addr_all_nodes(&maddr);
998 ndisc_send_na(dev, NULL, &maddr, &ifp->addr,
999 ifp->idev->cnf.forwarding, 0, 1, 1);
1000 in6_ifa_put(ifp);
1001 return 0;
1004 if (addr_type & IPV6_ADDR_UNICAST) {
1005 int inc = ipv6_addr_type(daddr)&IPV6_ADDR_MULTICAST;
1007 if (inc)
1008 nd_tbl.stats.rcv_probes_mcast++;
1009 else
1010 nd_tbl.stats.rcv_probes_ucast++;
1013 * update / create cache entry
1014 * for the source adddress
1017 neigh = ndisc_recv_ns(saddr, skb);
1019 if (neigh) {
1020 ndisc_send_na(dev, neigh, saddr, &ifp->addr,
1021 ifp->idev->cnf.forwarding, 1, inc, inc);
1022 neigh_release(neigh);
1025 in6_ifa_put(ifp);
1026 } else {
1027 struct inet6_dev *in6_dev = in6_dev_get(dev);
1028 int addr_type = ipv6_addr_type(saddr);
1030 if (in6_dev && in6_dev->cnf.forwarding &&
1031 (addr_type & IPV6_ADDR_UNICAST) &&
1032 pneigh_lookup(&nd_tbl, &msg->target, dev, 0)) {
1033 int inc = ipv6_addr_type(daddr)&IPV6_ADDR_MULTICAST;
1035 if (skb->stamp.tv_sec == 0 ||
1036 skb->pkt_type == PACKET_HOST ||
1037 inc == 0 ||
1038 in6_dev->nd_parms->proxy_delay == 0) {
1039 if (inc)
1040 nd_tbl.stats.rcv_probes_mcast++;
1041 else
1042 nd_tbl.stats.rcv_probes_ucast++;
1044 neigh = ndisc_recv_ns(saddr, skb);
1046 if (neigh) {
1047 ndisc_send_na(dev, neigh, saddr, &msg->target,
1048 0, 1, 0, inc);
1049 neigh_release(neigh);
1051 } else {
1052 /* Hack. It will be freed upon exit from
1053 ndisc_rcv
1055 atomic_inc(&skb->users);
1056 pneigh_enqueue(&nd_tbl, in6_dev->nd_parms, skb);
1057 in6_dev_put(in6_dev);
1058 return 0;
1061 if (in6_dev)
1062 in6_dev_put(in6_dev);
1065 return 0;
1067 case NDISC_NEIGHBOUR_ADVERTISEMENT:
1068 if ((ipv6_addr_type(saddr)&IPV6_ADDR_MULTICAST) &&
1069 msg->icmph.icmp6_solicited) {
1070 ND_PRINTK0("NDISC: solicited NA is multicasted\n");
1071 return 0;
1073 if ((ifp = ipv6_get_ifaddr(&msg->target, dev))) {
1074 if (ifp->flags & IFA_F_TENTATIVE) {
1075 addrconf_dad_failure(ifp);
1076 return 0;
1078 /* What should we make now? The advertisement
1079 is invalid, but ndisc specs say nothing
1080 about it. It could be misconfiguration, or
1081 an smart proxy agent tries to help us :-)
1083 ND_PRINTK0("%s: someone avertise our address!\n",
1084 ifp->idev->dev->name);
1085 in6_ifa_put(ifp);
1086 return 0;
1088 neigh = neigh_lookup(&nd_tbl, &msg->target, skb->dev);
1090 if (neigh) {
1091 if (neigh->flags & NTF_ROUTER) {
1092 if (msg->icmph.icmp6_router == 0) {
1094 * Change: router to host
1096 struct rt6_info *rt;
1097 rt = rt6_get_dflt_router(saddr, skb->dev);
1098 if (rt) {
1099 /* It is safe only because
1100 we aer in BH */
1101 dst_release(&rt->u.dst);
1102 ip6_del_rt(rt);
1105 } else {
1106 if (msg->icmph.icmp6_router)
1107 neigh->flags |= NTF_ROUTER;
1110 ndisc_recv_na(neigh, skb);
1111 neigh_release(neigh);
1113 break;
1115 case NDISC_ROUTER_ADVERTISEMENT:
1116 ndisc_router_discovery(skb);
1117 break;
1119 case NDISC_REDIRECT:
1120 ndisc_redirect_rcv(skb);
1121 break;
1124 return 0;
1127 #ifdef CONFIG_PROC_FS
1128 #ifndef CONFIG_RTNETLINK
1129 static int ndisc_get_info(char *buffer, char **start, off_t offset, int length)
1131 int len=0;
1132 off_t pos=0;
1133 int size;
1134 unsigned long now = jiffies;
1135 int i;
1137 for (i = 0; i <= NEIGH_HASHMASK; i++) {
1138 struct neighbour *neigh;
1140 read_lock_bh(&nd_tbl.lock);
1141 for (neigh = nd_tbl.hash_buckets[i]; neigh; neigh = neigh->next) {
1142 int j;
1144 size = 0;
1145 for (j=0; j<16; j++) {
1146 sprintf(buffer+len+size, "%02x", neigh->primary_key[j]);
1147 size += 2;
1150 read_lock(&neigh->lock);
1151 size += sprintf(buffer+len+size,
1152 " %02x %02x %02x %02x %08lx %08lx %08x %04x %04x %04x %8s ", i,
1153 128,
1154 neigh->type,
1155 neigh->nud_state,
1156 now - neigh->used,
1157 now - neigh->confirmed,
1158 neigh->parms->reachable_time,
1159 neigh->parms->gc_staletime,
1160 atomic_read(&neigh->refcnt) - 1,
1161 neigh->flags | (!neigh->hh ? 0 : (neigh->hh->hh_output==dev_queue_xmit ? 4 : 2)),
1162 neigh->dev->name);
1164 if ((neigh->nud_state&NUD_VALID) && neigh->dev->addr_len) {
1165 for (j=0; j < neigh->dev->addr_len; j++) {
1166 sprintf(buffer+len+size, "%02x", neigh->ha[j]);
1167 size += 2;
1169 } else {
1170 size += sprintf(buffer+len+size, "000000000000");
1172 read_unlock(&neigh->lock);
1173 size += sprintf(buffer+len+size, "\n");
1174 len += size;
1175 pos += size;
1177 if (pos <= offset)
1178 len=0;
1179 if (pos >= offset+length) {
1180 read_unlock_bh(&nd_tbl.lock);
1181 goto done;
1184 read_unlock_bh(&nd_tbl.lock);
1187 done:
1189 *start = buffer+len-(pos-offset); /* Start of wanted data */
1190 len = pos-offset; /* Start slop */
1191 if (len>length)
1192 len = length; /* Ending slop */
1193 if (len<0)
1194 len = 0;
1195 return len;
1198 #endif
1199 #endif /* CONFIG_PROC_FS */
1202 int __init ndisc_init(struct net_proto_family *ops)
1204 struct sock *sk;
1205 int err;
1207 ndisc_socket = sock_alloc();
1208 if (ndisc_socket == NULL) {
1209 printk(KERN_ERR
1210 "Failed to create the NDISC control socket.\n");
1211 return -1;
1213 ndisc_socket->inode->i_uid = 0;
1214 ndisc_socket->inode->i_gid = 0;
1215 ndisc_socket->type = SOCK_RAW;
1217 if((err = ops->create(ndisc_socket, IPPROTO_ICMPV6)) < 0) {
1218 printk(KERN_DEBUG
1219 "Failed to initializee the NDISC control socket (err %d).\n",
1220 err);
1221 sock_release(ndisc_socket);
1222 ndisc_socket = NULL; /* For safety. */
1223 return err;
1226 sk = ndisc_socket->sk;
1227 sk->allocation = GFP_ATOMIC;
1228 sk->net_pinfo.af_inet6.hop_limit = 255;
1229 /* Do not loopback ndisc messages */
1230 sk->net_pinfo.af_inet6.mc_loop = 0;
1231 sk->prot->unhash(sk);
1234 * Initialize the neighbour table
1237 neigh_table_init(&nd_tbl);
1239 #ifdef CONFIG_PROC_FS
1240 #ifndef CONFIG_RTNETLINK
1241 proc_net_create("ndisc", 0, ndisc_get_info);
1242 #endif
1243 #endif
1244 #ifdef CONFIG_SYSCTL
1245 neigh_sysctl_register(NULL, &nd_tbl.parms, NET_IPV6, NET_IPV6_NEIGH, "ipv6");
1246 #endif
1248 return 0;
1251 void ndisc_cleanup(void)
1253 #ifdef CONFIG_PROC_FS
1254 #ifndef CONFIG_RTNETLINK
1255 proc_net_remove("ndisc");
1256 #endif
1257 #endif
1258 neigh_table_clear(&nd_tbl);
1259 sock_release(ndisc_socket);
1260 ndisc_socket = NULL; /* For safety. */