patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / net / ipv6 / ndisc.c
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 #ifdef CONFIG_SYSCTL
62 #include <linux/sysctl.h>
63 #endif
64
65 #include <linux/if_arp.h>
66 #include <linux/ipv6.h>
67 #include <linux/icmpv6.h>
68
69 #include <net/sock.h>
70 #include <net/snmp.h>
71
72 #include <net/ipv6.h>
73 #include <net/protocol.h>
74 #include <net/ndisc.h>
75 #include <net/ip6_route.h>
76 #include <net/addrconf.h>
77 #include <net/icmp.h>
78
79 #include <net/flow.h>
80 #include <net/checksum.h>
81 #include <linux/proc_fs.h>
82
83 #include <linux/netfilter.h>
84 #include <linux/netfilter_ipv6.h>
85
86 static struct socket *ndisc_socket;
87
88 static u32 ndisc_hash(const void *pkey, const struct net_device *dev);
89 static int ndisc_constructor(struct neighbour *neigh);
90 static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb);
91 static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb);
92 static int pndisc_constructor(struct pneigh_entry *n);
93 static void pndisc_destructor(struct pneigh_entry *n);
94 static void pndisc_redo(struct sk_buff *skb);
95
96 static struct neigh_ops ndisc_generic_ops = {
97         .family =               AF_INET6,
98         .solicit =              ndisc_solicit,
99         .error_report =         ndisc_error_report,
100         .output =               neigh_resolve_output,
101         .connected_output =     neigh_connected_output,
102         .hh_output =            dev_queue_xmit,
103         .queue_xmit =           dev_queue_xmit,
104 };
105
106 static struct neigh_ops ndisc_hh_ops = {
107         .family =               AF_INET6,
108         .solicit =              ndisc_solicit,
109         .error_report =         ndisc_error_report,
110         .output =               neigh_resolve_output,
111         .connected_output =     neigh_resolve_output,
112         .hh_output =            dev_queue_xmit,
113         .queue_xmit =           dev_queue_xmit,
114 };
115
116
117 static struct neigh_ops ndisc_direct_ops = {
118         .family =               AF_INET6,
119         .output =               dev_queue_xmit,
120         .connected_output =     dev_queue_xmit,
121         .hh_output =            dev_queue_xmit,
122         .queue_xmit =           dev_queue_xmit,
123 };
124
125 struct neigh_table nd_tbl = {
126         .family =       AF_INET6,
127         .entry_size =   sizeof(struct neighbour) + sizeof(struct in6_addr),
128         .key_len =      sizeof(struct in6_addr),
129         .hash =         ndisc_hash,
130         .constructor =  ndisc_constructor,
131         .pconstructor = pndisc_constructor,
132         .pdestructor =  pndisc_destructor,
133         .proxy_redo =   pndisc_redo,
134         .id =           "ndisc_cache",
135         .parms = {
136                 .tbl =                  &nd_tbl,
137                 .base_reachable_time =  30 * HZ,
138                 .retrans_time =  1 * HZ,
139                 .gc_staletime = 60 * HZ,
140                 .reachable_time =               30 * HZ,
141                 .delay_probe_time =      5 * HZ,
142                 .queue_len =             3,
143                 .ucast_probes =  3,
144                 .mcast_probes =  3,
145                 .anycast_delay =         1 * HZ,
146                 .proxy_delay =          (8 * HZ) / 10,
147                 .proxy_qlen =           64,
148         },
149         .gc_interval =    30 * HZ,
150         .gc_thresh1 =    128,
151         .gc_thresh2 =    512,
152         .gc_thresh3 =   1024,
153 };
154
155 /* ND options */
156 struct ndisc_options {
157         struct nd_opt_hdr *nd_opt_array[7];
158         struct nd_opt_hdr *nd_opt_piend;
159 };
160
161 #define nd_opts_src_lladdr      nd_opt_array[ND_OPT_SOURCE_LL_ADDR]
162 #define nd_opts_tgt_lladdr      nd_opt_array[ND_OPT_TARGET_LL_ADDR]
163 #define nd_opts_pi              nd_opt_array[ND_OPT_PREFIX_INFO]
164 #define nd_opts_pi_end          nd_opt_piend
165 #define nd_opts_rh              nd_opt_array[ND_OPT_REDIRECT_HDR]
166 #define nd_opts_mtu             nd_opt_array[ND_OPT_MTU]
167
168 #define NDISC_OPT_SPACE(len) (((len)+2+7)&~7)
169
170 static u8 *ndisc_fill_option(u8 *opt, int type, void *data, int data_len)
171 {
172         int space = NDISC_OPT_SPACE(data_len);
173
174         opt[0] = type;
175         opt[1] = space>>3;
176         memcpy(opt+2, data, data_len);
177         data_len += 2;
178         opt += data_len;
179         if ((space -= data_len) > 0)
180                 memset(opt, 0, space);
181         return opt + space;
182 }
183
184 static struct nd_opt_hdr *ndisc_next_option(struct nd_opt_hdr *cur,
185                                             struct nd_opt_hdr *end)
186 {
187         int type;
188         if (!cur || !end || cur >= end)
189                 return NULL;
190         type = cur->nd_opt_type;
191         do {
192                 cur = ((void *)cur) + (cur->nd_opt_len << 3);
193         } while(cur < end && cur->nd_opt_type != type);
194         return (cur <= end && cur->nd_opt_type == type ? cur : NULL);
195 }
196
197 static struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len,
198                                                  struct ndisc_options *ndopts)
199 {
200         struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)opt;
201
202         if (!nd_opt || opt_len < 0 || !ndopts)
203                 return NULL;
204         memset(ndopts, 0, sizeof(*ndopts));
205         while (opt_len) {
206                 int l;
207                 if (opt_len < sizeof(struct nd_opt_hdr))
208                         return NULL;
209                 l = nd_opt->nd_opt_len << 3;
210                 if (opt_len < l || l == 0)
211                         return NULL;
212                 switch (nd_opt->nd_opt_type) {
213                 case ND_OPT_SOURCE_LL_ADDR:
214                 case ND_OPT_TARGET_LL_ADDR:
215                 case ND_OPT_MTU:
216                 case ND_OPT_REDIRECT_HDR:
217                         if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) {
218                                 ND_PRINTK2(KERN_WARNING
219                                            "%s(): duplicated ND6 option found: type=%d\n",
220                                            __FUNCTION__,
221                                            nd_opt->nd_opt_type);
222                         } else {
223                                 ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt;
224                         }
225                         break;
226                 case ND_OPT_PREFIX_INFO:
227                         ndopts->nd_opts_pi_end = nd_opt;
228                         if (ndopts->nd_opt_array[nd_opt->nd_opt_type] == 0)
229                                 ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt;
230                         break;
231                 default:
232                         /*
233                          * Unknown options must be silently ignored,
234                          * to accommodate future extension to the protocol.
235                          */
236                         ND_PRINTK2(KERN_NOTICE
237                                    "%s(): ignored unsupported option; type=%d, len=%d\n",
238                                    __FUNCTION__,
239                                    nd_opt->nd_opt_type, nd_opt->nd_opt_len);
240                 }
241                 opt_len -= l;
242                 nd_opt = ((void *)nd_opt) + l;
243         }
244         return ndopts;
245 }
246
247 int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int dir)
248 {
249         switch (dev->type) {
250         case ARPHRD_ETHER:
251         case ARPHRD_IEEE802:    /* Not sure. Check it later. --ANK */
252         case ARPHRD_FDDI:
253                 ipv6_eth_mc_map(addr, buf);
254                 return 0;
255         case ARPHRD_IEEE802_TR:
256                 ipv6_tr_mc_map(addr,buf);
257                 return 0;
258         case ARPHRD_ARCNET:
259                 ipv6_arcnet_mc_map(addr, buf);
260                 return 0;
261         default:
262                 if (dir) {
263                         memcpy(buf, dev->broadcast, dev->addr_len);
264                         return 0;
265                 }
266         }
267         return -EINVAL;
268 }
269
270 static u32 ndisc_hash(const void *pkey, const struct net_device *dev)
271 {
272         u32 hash_val;
273
274         hash_val = *(u32*)(pkey + sizeof(struct in6_addr) - 4);
275         hash_val ^= (hash_val>>16);
276         hash_val ^= hash_val>>8;
277         hash_val ^= hash_val>>3;
278         hash_val = (hash_val^dev->ifindex)&NEIGH_HASHMASK;
279
280         return hash_val;
281 }
282
283 static int ndisc_constructor(struct neighbour *neigh)
284 {
285         struct in6_addr *addr = (struct in6_addr*)&neigh->primary_key;
286         struct net_device *dev = neigh->dev;
287         struct inet6_dev *in6_dev = in6_dev_get(dev);
288         int is_multicast = ipv6_addr_is_multicast(addr);
289
290         if (in6_dev == NULL)
291                 return -EINVAL;
292
293         if (in6_dev->nd_parms)
294                 neigh->parms = in6_dev->nd_parms;
295
296         neigh->type = is_multicast ? RTN_MULTICAST : RTN_UNICAST;
297         if (dev->hard_header == NULL) {
298                 neigh->nud_state = NUD_NOARP;
299                 neigh->ops = &ndisc_direct_ops;
300                 neigh->output = neigh->ops->queue_xmit;
301         } else {
302                 if (is_multicast) {
303                         neigh->nud_state = NUD_NOARP;
304                         ndisc_mc_map(addr, neigh->ha, dev, 1);
305                 } else if (dev->flags&(IFF_NOARP|IFF_LOOPBACK)) {
306                         neigh->nud_state = NUD_NOARP;
307                         memcpy(neigh->ha, dev->dev_addr, dev->addr_len);
308                         if (dev->flags&IFF_LOOPBACK)
309                                 neigh->type = RTN_LOCAL;
310                 } else if (dev->flags&IFF_POINTOPOINT) {
311                         neigh->nud_state = NUD_NOARP;
312                         memcpy(neigh->ha, dev->broadcast, dev->addr_len);
313                 }
314                 if (dev->hard_header_cache)
315                         neigh->ops = &ndisc_hh_ops;
316                 else
317                         neigh->ops = &ndisc_generic_ops;
318                 if (neigh->nud_state&NUD_VALID)
319                         neigh->output = neigh->ops->connected_output;
320                 else
321                         neigh->output = neigh->ops->output;
322         }
323         in6_dev_put(in6_dev);
324         return 0;
325 }
326
327 static int pndisc_constructor(struct pneigh_entry *n)
328 {
329         struct in6_addr *addr = (struct in6_addr*)&n->key;
330         struct in6_addr maddr;
331         struct net_device *dev = n->dev;
332
333         if (dev == NULL || __in6_dev_get(dev) == NULL)
334                 return -EINVAL;
335         addrconf_addr_solict_mult(addr, &maddr);
336         ipv6_dev_mc_inc(dev, &maddr);
337         return 0;
338 }
339
340 static void pndisc_destructor(struct pneigh_entry *n)
341 {
342         struct in6_addr *addr = (struct in6_addr*)&n->key;
343         struct in6_addr maddr;
344         struct net_device *dev = n->dev;
345
346         if (dev == NULL || __in6_dev_get(dev) == NULL)
347                 return;
348         addrconf_addr_solict_mult(addr, &maddr);
349         ipv6_dev_mc_dec(dev, &maddr);
350 }
351
352 /*
353  *      Send a Neighbour Advertisement
354  */
355
356 static inline void ndisc_flow_init(struct flowi *fl, u8 type,
357                             struct in6_addr *saddr, struct in6_addr *daddr)
358 {
359         memset(fl, 0, sizeof(*fl));
360         ipv6_addr_copy(&fl->fl6_src, saddr);
361         ipv6_addr_copy(&fl->fl6_dst, daddr);
362         fl->proto               = IPPROTO_ICMPV6;
363         fl->fl_icmp_type        = type;
364         fl->fl_icmp_code        = 0;
365 }
366
367 static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
368                    struct in6_addr *daddr, struct in6_addr *solicited_addr,
369                    int router, int solicited, int override, int inc_opt) 
370 {
371         struct in6_addr tmpaddr;
372         struct inet6_ifaddr *ifp;
373         struct inet6_dev *idev;
374         struct flowi fl;
375         struct dst_entry* dst;
376         struct sock *sk = ndisc_socket->sk;
377         struct in6_addr *src_addr;
378         struct nd_msg *msg;
379         int len;
380         struct sk_buff *skb;
381         int err;
382
383         len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
384
385         /* for anycast or proxy, solicited_addr != src_addr */
386         ifp = ipv6_get_ifaddr(solicited_addr, dev, 1);
387         if (ifp) {
388                 src_addr = solicited_addr;
389                 in6_ifa_put(ifp);
390         } else {
391                 if (ipv6_dev_get_saddr(dev, daddr, &tmpaddr, 0))
392                         return;
393                 src_addr = &tmpaddr;
394         }
395
396         ndisc_flow_init(&fl, NDISC_NEIGHBOUR_ADVERTISEMENT, src_addr, daddr);
397
398         dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output);
399         if (!dst)
400                 return;
401
402         err = xfrm_lookup(&dst, &fl, NULL, 0);
403         if (err < 0) {
404                 dst_release(dst);
405                 return;
406         }
407
408         if (inc_opt) {
409                 if (dev->addr_len)
410                         len += NDISC_OPT_SPACE(dev->addr_len);
411                 else
412                         inc_opt = 0;
413         }
414
415         skb = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
416                                   1, &err);
417
418         if (skb == NULL) {
419                 ND_PRINTK0(KERN_ERR
420                            "ICMPv6 NA: %s() failed to allocate an skb.\n", 
421                            __FUNCTION__);
422                 dst_release(dst);
423                 return;
424         }
425
426         skb_reserve(skb, LL_RESERVED_SPACE(dev));
427         ip6_nd_hdr(sk, skb, dev, src_addr, daddr, IPPROTO_ICMPV6, len);
428
429         msg = (struct nd_msg *)skb_put(skb, len);
430         skb->h.raw = (unsigned char*)msg;
431
432         msg->icmph.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT;
433         msg->icmph.icmp6_code = 0;
434         msg->icmph.icmp6_cksum = 0;
435
436         msg->icmph.icmp6_unused = 0;
437         msg->icmph.icmp6_router    = router;
438         msg->icmph.icmp6_solicited = solicited;
439         msg->icmph.icmp6_override  = !!override;
440
441         /* Set the target address. */
442         ipv6_addr_copy(&msg->target, solicited_addr);
443
444         if (inc_opt)
445                 ndisc_fill_option(msg->opt, ND_OPT_TARGET_LL_ADDR, dev->dev_addr, dev->addr_len);
446
447         /* checksum */
448         msg->icmph.icmp6_cksum = csum_ipv6_magic(src_addr, daddr, len, 
449                                                  IPPROTO_ICMPV6,
450                                                  csum_partial((__u8 *) msg, 
451                                                               len, 0));
452
453         skb->dst = dst;
454         idev = in6_dev_get(dst->dev);
455         IP6_INC_STATS(OutRequests);
456         err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
457         if (!err) {
458                 ICMP6_INC_STATS(idev, Icmp6OutNeighborAdvertisements);
459                 ICMP6_INC_STATS(idev, Icmp6OutMsgs);
460         }
461
462         if (likely(idev != NULL))
463                 in6_dev_put(idev);
464 }        
465
466 void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
467                    struct in6_addr *solicit,
468                    struct in6_addr *daddr, struct in6_addr *saddr) 
469 {
470         struct flowi fl;
471         struct dst_entry* dst;
472         struct inet6_dev *idev;
473         struct sock *sk = ndisc_socket->sk;
474         struct sk_buff *skb;
475         struct nd_msg *msg;
476         struct in6_addr addr_buf;
477         int len;
478         int err;
479         int send_llinfo;
480
481         if (saddr == NULL) {
482                 if (ipv6_get_lladdr(dev, &addr_buf))
483                         return;
484                 saddr = &addr_buf;
485         }
486
487         ndisc_flow_init(&fl, NDISC_NEIGHBOUR_SOLICITATION, saddr, daddr);
488
489         dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output);
490         if (!dst)
491                 return;
492
493         err = xfrm_lookup(&dst, &fl, NULL, 0);
494         if (err < 0) {
495                 dst_release(dst);
496                 return;
497         }
498
499         len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
500         send_llinfo = dev->addr_len && !ipv6_addr_any(saddr);
501         if (send_llinfo)
502                 len += NDISC_OPT_SPACE(dev->addr_len);
503
504         skb = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
505                                   1, &err);
506         if (skb == NULL) {
507                 ND_PRINTK0(KERN_ERR
508                            "ICMPv6 NA: %s() failed to allocate an skb.\n", 
509                            __FUNCTION__);
510                 dst_release(dst);
511                 return;
512         }
513
514         skb_reserve(skb, LL_RESERVED_SPACE(dev));
515         ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len);
516
517         msg = (struct nd_msg *)skb_put(skb, len);
518         skb->h.raw = (unsigned char*)msg;
519         msg->icmph.icmp6_type = NDISC_NEIGHBOUR_SOLICITATION;
520         msg->icmph.icmp6_code = 0;
521         msg->icmph.icmp6_cksum = 0;
522         msg->icmph.icmp6_unused = 0;
523
524         /* Set the target address. */
525         ipv6_addr_copy(&msg->target, solicit);
526
527         if (send_llinfo)
528                 ndisc_fill_option(msg->opt, ND_OPT_SOURCE_LL_ADDR, dev->dev_addr, dev->addr_len);
529
530         /* checksum */
531         msg->icmph.icmp6_cksum = csum_ipv6_magic(&skb->nh.ipv6h->saddr,
532                                                  daddr, len, 
533                                                  IPPROTO_ICMPV6,
534                                                  csum_partial((__u8 *) msg, 
535                                                               len, 0));
536         /* send it! */
537         skb->dst = dst;
538         idev = in6_dev_get(dst->dev);
539         IP6_INC_STATS(OutRequests);
540         err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
541         if (!err) {
542                 ICMP6_INC_STATS(idev, Icmp6OutNeighborSolicits);
543                 ICMP6_INC_STATS(idev, Icmp6OutMsgs);
544         }
545
546         if (likely(idev != NULL))
547                 in6_dev_put(idev);
548 }
549
550 void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
551                    struct in6_addr *daddr)
552 {
553         struct flowi fl;
554         struct dst_entry* dst;
555         struct inet6_dev *idev;
556         struct sock *sk = ndisc_socket->sk;
557         struct sk_buff *skb;
558         struct icmp6hdr *hdr;
559         __u8 * opt;
560         int len;
561         int err;
562
563         ndisc_flow_init(&fl, NDISC_ROUTER_SOLICITATION, saddr, daddr);
564
565         dst = ndisc_dst_alloc(dev, NULL, daddr, ip6_output);
566         if (!dst)
567                 return;
568
569         err = xfrm_lookup(&dst, &fl, NULL, 0);
570         if (err < 0) {
571                 dst_release(dst);
572                 return;
573         }
574
575         len = sizeof(struct icmp6hdr);
576         if (dev->addr_len)
577                 len += NDISC_OPT_SPACE(dev->addr_len);
578
579         skb = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
580                                   1, &err);
581         if (skb == NULL) {
582                 ND_PRINTK0(KERN_ERR
583                            "ICMPv6 RS: %s() failed to allocate an skb.\n", 
584                            __FUNCTION__);
585                 dst_release(dst);
586                 return;
587         }
588
589         skb_reserve(skb, LL_RESERVED_SPACE(dev));
590         ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len);
591
592         hdr = (struct icmp6hdr *)skb_put(skb, len);
593         skb->h.raw = (unsigned char*)hdr;
594         hdr->icmp6_type = NDISC_ROUTER_SOLICITATION;
595         hdr->icmp6_code = 0;
596         hdr->icmp6_cksum = 0;
597         hdr->icmp6_unused = 0;
598
599         opt = (u8*) (hdr + 1);
600
601         if (dev->addr_len)
602                 ndisc_fill_option(opt, ND_OPT_SOURCE_LL_ADDR, dev->dev_addr, dev->addr_len);
603
604         /* checksum */
605         hdr->icmp6_cksum = csum_ipv6_magic(&skb->nh.ipv6h->saddr, daddr, len,
606                                            IPPROTO_ICMPV6,
607                                            csum_partial((__u8 *) hdr, len, 0));
608
609         /* send it! */
610         skb->dst = dst;
611         idev = in6_dev_get(dst->dev);
612         IP6_INC_STATS(OutRequests);     
613         err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
614         if (!err) {
615                 ICMP6_INC_STATS(idev, Icmp6OutRouterSolicits);
616                 ICMP6_INC_STATS(idev, Icmp6OutMsgs);
617         }
618
619         if (likely(idev != NULL))
620                 in6_dev_put(idev);
621 }
622                    
623
624 static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb)
625 {
626         /*
627          *      "The sender MUST return an ICMP
628          *       destination unreachable"
629          */
630         dst_link_failure(skb);
631         kfree_skb(skb);
632 }
633
634 /* Called with locked neigh: either read or both */
635
636 static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
637 {
638         struct in6_addr *saddr = NULL;
639         struct in6_addr mcaddr;
640         struct net_device *dev = neigh->dev;
641         struct in6_addr *target = (struct in6_addr *)&neigh->primary_key;
642         int probes = atomic_read(&neigh->probes);
643
644         if (skb && ipv6_chk_addr(&skb->nh.ipv6h->saddr, dev, 1))
645                 saddr = &skb->nh.ipv6h->saddr;
646
647         if ((probes -= neigh->parms->ucast_probes) < 0) {
648                 if (!(neigh->nud_state & NUD_VALID)) {
649                         ND_PRINTK1(KERN_DEBUG
650                                    "%s(): trying to ucast probe in NUD_INVALID: "
651                                    "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
652                                    __FUNCTION__,
653                                    NIP6(*target));
654                 }
655                 ndisc_send_ns(dev, neigh, target, target, saddr);
656         } else if ((probes -= neigh->parms->app_probes) < 0) {
657 #ifdef CONFIG_ARPD
658                 neigh_app_ns(neigh);
659 #endif
660         } else {
661                 addrconf_addr_solict_mult(target, &mcaddr);
662                 ndisc_send_ns(dev, NULL, target, &mcaddr, saddr);
663         }
664 }
665
666 static void ndisc_recv_ns(struct sk_buff *skb)
667 {
668         struct nd_msg *msg = (struct nd_msg *)skb->h.raw;
669         struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
670         struct in6_addr *daddr = &skb->nh.ipv6h->daddr;
671         u8 *lladdr = NULL;
672         int lladdrlen = 0;
673         u32 ndoptlen = skb->tail - msg->opt;
674         struct ndisc_options ndopts;
675         struct net_device *dev = skb->dev;
676         struct inet6_ifaddr *ifp;
677         struct inet6_dev *idev = NULL;
678         struct neighbour *neigh;
679         int dad = ipv6_addr_any(saddr);
680         int inc;
681
682         if (ipv6_addr_is_multicast(&msg->target)) {
683                 ND_PRINTK2(KERN_WARNING 
684                            "ICMPv6 NS: multicast target address");
685                 return;
686         }
687
688         /*
689          * RFC2461 7.1.1:
690          * DAD has to be destined for solicited node multicast address.
691          */
692         if (dad &&
693             !(daddr->s6_addr32[0] == htonl(0xff020000) &&
694               daddr->s6_addr32[1] == htonl(0x00000000) &&
695               daddr->s6_addr32[2] == htonl(0x00000001) &&
696               daddr->s6_addr [12] == 0xff )) {
697                 ND_PRINTK2(KERN_WARNING
698                            "ICMPv6 NS: bad DAD packet (wrong destination)\n");
699                 return;
700         }
701
702         if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts)) {
703                 ND_PRINTK2(KERN_WARNING 
704                            "ICMPv6 NS: invalid ND options\n");
705                 return;
706         }
707
708         if (ndopts.nd_opts_src_lladdr) {
709                 lladdr = (u8*)(ndopts.nd_opts_src_lladdr + 1);
710                 lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
711                 if (lladdrlen != NDISC_OPT_SPACE(dev->addr_len)) {
712                         ND_PRINTK2(KERN_WARNING
713                                    "ICMPv6 NS: invalid link-layer address length\n");
714                         return;
715                 }
716
717                 /* RFC2461 7.1.1:
718                  *      If the IP source address is the unspecified address, 
719                  *      there MUST NOT be source link-layer address option 
720                  *      in the message.
721                  */
722                 if (dad) {
723                         ND_PRINTK2(KERN_WARNING 
724                                    "ICMPv6 NS: bad DAD packet (link-layer address option)\n");
725                         return;
726                 }
727         }
728
729         inc = ipv6_addr_is_multicast(daddr);
730
731         if ((ifp = ipv6_get_ifaddr(&msg->target, dev, 1)) != NULL) {
732                 if (ifp->flags & IFA_F_TENTATIVE) {
733                         /* Address is tentative. If the source
734                            is unspecified address, it is someone
735                            does DAD, otherwise we ignore solicitations
736                            until DAD timer expires.
737                          */
738                         if (!dad)
739                                 goto out;
740                         if (dev->type == ARPHRD_IEEE802_TR) {
741                                 unsigned char *sadr = skb->mac.raw;
742                                 if (((sadr[8] ^ dev->dev_addr[0]) & 0x7f) == 0 &&
743                                     sadr[9] == dev->dev_addr[1] &&
744                                     sadr[10] == dev->dev_addr[2] &&
745                                     sadr[11] == dev->dev_addr[3] &&
746                                     sadr[12] == dev->dev_addr[4] &&
747                                     sadr[13] == dev->dev_addr[5]) {
748                                         /* looped-back to us */
749                                         goto out;
750                                 }
751                         }
752                         addrconf_dad_failure(ifp); 
753                         return;
754                 }
755
756                 idev = ifp->idev;
757         } else {
758                 idev = in6_dev_get(dev);
759                 if (!idev) {
760                         /* XXX: count this drop? */
761                         return;
762                 }
763
764                 if (ipv6_chk_acast_addr(dev, &msg->target) ||
765                     (idev->cnf.forwarding && 
766                      pneigh_lookup(&nd_tbl, &msg->target, dev, 0))) {
767                         if (skb->stamp.tv_sec != LOCALLY_ENQUEUED &&
768                             skb->pkt_type != PACKET_HOST &&
769                             inc != 0 &&
770                             idev->nd_parms->proxy_delay != 0) {
771                                 /*
772                                  * for anycast or proxy,
773                                  * sender should delay its response 
774                                  * by a random time between 0 and 
775                                  * MAX_ANYCAST_DELAY_TIME seconds.
776                                  * (RFC2461) -- yoshfuji
777                                  */
778                                 struct sk_buff *n = skb_clone(skb, GFP_ATOMIC);
779                                 if (n)
780                                         pneigh_enqueue(&nd_tbl, idev->nd_parms, n);
781                                 goto out;
782                         }
783                 } else
784                         goto out;
785         }
786
787         if (dad) {
788                 struct in6_addr maddr;
789
790                 ipv6_addr_all_nodes(&maddr);
791                 ndisc_send_na(dev, NULL, &maddr, &msg->target,
792                               idev->cnf.forwarding, 0, (ifp != NULL), 1);
793                 goto out;
794         }
795
796         if (inc)
797                 nd_tbl.stats.rcv_probes_mcast++;
798         else
799                 nd_tbl.stats.rcv_probes_ucast++;
800
801         /* 
802          *      update / create cache entry
803          *      for the source address
804          */
805         neigh = neigh_event_ns(&nd_tbl, lladdr, saddr, dev);
806
807         if (neigh || !dev->hard_header) {
808                 ndisc_send_na(dev, neigh, saddr, &msg->target,
809                               idev->cnf.forwarding, 
810                               1, (ifp != NULL && inc), inc);
811                 if (neigh)
812                         neigh_release(neigh);
813         }
814
815 out:
816         if (ifp)
817                 in6_ifa_put(ifp);
818         else
819                 in6_dev_put(idev);
820
821         return;
822 }
823
824 static void ndisc_recv_na(struct sk_buff *skb)
825 {
826         struct nd_msg *msg = (struct nd_msg *)skb->h.raw;
827         struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
828         struct in6_addr *daddr = &skb->nh.ipv6h->daddr;
829         u8 *lladdr = NULL;
830         int lladdrlen = 0;
831         u32 ndoptlen = skb->tail - msg->opt;
832         struct ndisc_options ndopts;
833         struct net_device *dev = skb->dev;
834         struct inet6_ifaddr *ifp;
835         struct neighbour *neigh;
836
837         if (skb->len < sizeof(struct nd_msg)) {
838                 ND_PRINTK2(KERN_WARNING
839                            "ICMPv6 NA: packet too short\n");
840                 return;
841         }
842
843         if (ipv6_addr_is_multicast(&msg->target)) {
844                 ND_PRINTK2(KERN_WARNING
845                            "ICMPv6 NA: target address is multicast.\n");
846                 return;
847         }
848
849         if (ipv6_addr_is_multicast(daddr) &&
850             msg->icmph.icmp6_solicited) {
851                 ND_PRINTK2(KERN_WARNING
852                            "ICMPv6 NA: solicited NA is multicasted.\n");
853                 return;
854         }
855                 
856         if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts)) {
857                 ND_PRINTK2(KERN_WARNING
858                            "ICMPv6 NS: invalid ND option\n");
859                 return;
860         }
861         if (ndopts.nd_opts_tgt_lladdr) {
862                 lladdr = (u8*)(ndopts.nd_opts_tgt_lladdr + 1);
863                 lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
864                 if (lladdrlen != NDISC_OPT_SPACE(dev->addr_len)) {
865                         ND_PRINTK2(KERN_WARNING
866                                    "ICMPv6 NA: invalid link-layer address length\n");
867                         return;
868                 }
869         }
870         if ((ifp = ipv6_get_ifaddr(&msg->target, dev, 1))) {
871                 if (ifp->flags & IFA_F_TENTATIVE) {
872                         addrconf_dad_failure(ifp);
873                         return;
874                 }
875                 /* What should we make now? The advertisement
876                    is invalid, but ndisc specs say nothing
877                    about it. It could be misconfiguration, or
878                    an smart proxy agent tries to help us :-)
879                  */
880                 ND_PRINTK1(KERN_WARNING
881                            "ICMPv6 NA: someone advertises our address on %s!\n",
882                            ifp->idev->dev->name);
883                 in6_ifa_put(ifp);
884                 return;
885         }
886         neigh = neigh_lookup(&nd_tbl, &msg->target, dev);
887
888         if (neigh) {
889                 if (neigh->flags & NTF_ROUTER) {
890                         if (msg->icmph.icmp6_router == 0) {
891                                 /*
892                                  *      Change: router to host
893                                  */
894                                 struct rt6_info *rt;
895                                 rt = rt6_get_dflt_router(saddr, dev);
896                                 if (rt)
897                                         ip6_del_rt(rt, NULL, NULL);
898                         }
899                 } else {
900                         if (msg->icmph.icmp6_router)
901                                 neigh->flags |= NTF_ROUTER;
902                 }
903
904                 neigh_update(neigh, lladdr,
905                              msg->icmph.icmp6_solicited ? NUD_REACHABLE : NUD_STALE,
906                              msg->icmph.icmp6_override, 1);
907                 neigh_release(neigh);
908         }
909 }
910
911 static void ndisc_router_discovery(struct sk_buff *skb)
912 {
913         struct ra_msg *ra_msg = (struct ra_msg *) skb->h.raw;
914         struct neighbour *neigh;
915         struct inet6_dev *in6_dev;
916         struct rt6_info *rt;
917         int lifetime;
918         struct ndisc_options ndopts;
919         int optlen;
920
921         __u8 * opt = (__u8 *)(ra_msg + 1);
922
923         optlen = (skb->tail - skb->h.raw) - sizeof(struct ra_msg);
924
925         if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr) & IPV6_ADDR_LINKLOCAL)) {
926                 ND_PRINTK2(KERN_WARNING
927                            "ICMPv6 RA: source address is not link-local.\n");
928                 return;
929         }
930         if (optlen < 0) {
931                 ND_PRINTK2(KERN_WARNING 
932                            "ICMPv6 RA: packet too short\n");
933                 return;
934         }
935
936         /*
937          *      set the RA_RECV flag in the interface
938          */
939
940         in6_dev = in6_dev_get(skb->dev);
941         if (in6_dev == NULL) {
942                 ND_PRINTK0(KERN_ERR
943                            "ICMPv6 RA: can't find inet6 device for %s.\n",
944                            skb->dev->name);
945                 return;
946         }
947         if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra) {
948                 in6_dev_put(in6_dev);
949                 return;
950         }
951
952         if (!ndisc_parse_options(opt, optlen, &ndopts)) {
953                 in6_dev_put(in6_dev);
954                 ND_PRINTK2(KERN_WARNING
955                            "ICMP6 RA: invalid ND options\n");
956                 return;
957         }
958
959         if (in6_dev->if_flags & IF_RS_SENT) {
960                 /*
961                  *      flag that an RA was received after an RS was sent
962                  *      out on this interface.
963                  */
964                 in6_dev->if_flags |= IF_RA_RCVD;
965         }
966
967         /*
968          * Remember the managed/otherconf flags from most recently
969          * received RA message (RFC 2462) -- yoshfuji
970          */
971         in6_dev->if_flags = (in6_dev->if_flags & ~(IF_RA_MANAGED |
972                                 IF_RA_OTHERCONF)) |
973                                 (ra_msg->icmph.icmp6_addrconf_managed ?
974                                         IF_RA_MANAGED : 0) |
975                                 (ra_msg->icmph.icmp6_addrconf_other ?
976                                         IF_RA_OTHERCONF : 0);
977
978         lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime);
979
980         rt = rt6_get_dflt_router(&skb->nh.ipv6h->saddr, skb->dev);
981
982         if (rt && lifetime == 0) {
983                 ip6_del_rt(rt, NULL, NULL);
984                 rt = NULL;
985         }
986
987         if (rt == NULL && lifetime) {
988                 ND_PRINTK3(KERN_DEBUG
989                            "ICMPv6 RA: adding default router.\n");
990
991                 rt = rt6_add_dflt_router(&skb->nh.ipv6h->saddr, skb->dev);
992                 if (rt == NULL) {
993                         ND_PRINTK0(KERN_ERR
994                                    "ICMPv6 RA: %s() failed to add default route.\n",
995                                    __FUNCTION__);
996                         in6_dev_put(in6_dev);
997                         return;
998                 }
999
1000                 neigh = rt->rt6i_nexthop;
1001                 if (neigh == NULL) {
1002                         ND_PRINTK0(KERN_ERR
1003                                    "ICMPv6 RA: %s() got default router without neighbour.\n",
1004                                    __FUNCTION__);
1005                         dst_release(&rt->u.dst);
1006                         in6_dev_put(in6_dev);
1007                         return;
1008                 }
1009                 neigh->flags |= NTF_ROUTER;
1010
1011                 /*
1012                  *      If we where using an "all destinations on link" route
1013                  *      delete it
1014                  */
1015
1016                 rt6_purge_dflt_routers(RTF_ALLONLINK);
1017         }
1018
1019         if (rt)
1020                 rt->rt6i_expires = jiffies + (HZ * lifetime);
1021
1022         if (ra_msg->icmph.icmp6_hop_limit)
1023                 in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit;
1024
1025         /*
1026          *      Update Reachable Time and Retrans Timer
1027          */
1028
1029         if (in6_dev->nd_parms) {
1030                 unsigned long rtime = ntohl(ra_msg->retrans_timer);
1031
1032                 if (rtime && rtime/1000 < MAX_SCHEDULE_TIMEOUT/HZ) {
1033                         rtime = (rtime*HZ)/1000;
1034                         if (rtime < HZ/10)
1035                                 rtime = HZ/10;
1036                         in6_dev->nd_parms->retrans_time = rtime;
1037                         in6_dev->tstamp = jiffies;
1038                         inet6_ifinfo_notify(RTM_NEWLINK, in6_dev);
1039                 }
1040
1041                 rtime = ntohl(ra_msg->reachable_time);
1042                 if (rtime && rtime/1000 < MAX_SCHEDULE_TIMEOUT/(3*HZ)) {
1043                         rtime = (rtime*HZ)/1000;
1044
1045                         if (rtime < HZ/10)
1046                                 rtime = HZ/10;
1047
1048                         if (rtime != in6_dev->nd_parms->base_reachable_time) {
1049                                 in6_dev->nd_parms->base_reachable_time = rtime;
1050                                 in6_dev->nd_parms->gc_staletime = 3 * rtime;
1051                                 in6_dev->nd_parms->reachable_time = neigh_rand_reach_time(rtime);
1052                                 in6_dev->tstamp = jiffies;
1053                                 inet6_ifinfo_notify(RTM_NEWLINK, in6_dev);
1054                         }
1055                 }
1056         }
1057
1058         /*
1059          *      Process options.
1060          */
1061
1062         if (rt && (neigh = rt->rt6i_nexthop) != NULL) {
1063                 u8 *lladdr = NULL;
1064                 int lladdrlen;
1065                 if (ndopts.nd_opts_src_lladdr) {
1066                         lladdr = (u8*)((ndopts.nd_opts_src_lladdr)+1);
1067                         lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
1068                         if (lladdrlen != NDISC_OPT_SPACE(skb->dev->addr_len)) {
1069                                 ND_PRINTK2(KERN_WARNING
1070                                            "ICMPv6 RA: invalid link-layer address length\n");
1071                                 goto out;
1072                         }
1073                 }
1074                 neigh_update(neigh, lladdr, NUD_STALE, 1, 1);
1075         }
1076
1077         if (ndopts.nd_opts_pi) {
1078                 struct nd_opt_hdr *p;
1079                 for (p = ndopts.nd_opts_pi;
1080                      p;
1081                      p = ndisc_next_option(p, ndopts.nd_opts_pi_end)) {
1082                         addrconf_prefix_rcv(skb->dev, (u8*)p, (p->nd_opt_len) << 3);
1083                 }
1084         }
1085
1086         if (ndopts.nd_opts_mtu) {
1087                 u32 mtu;
1088
1089                 memcpy(&mtu, ((u8*)(ndopts.nd_opts_mtu+1))+2, sizeof(mtu));
1090                 mtu = ntohl(mtu);
1091
1092                 if (mtu < IPV6_MIN_MTU || mtu > skb->dev->mtu) {
1093                         ND_PRINTK2(KERN_WARNING
1094                                    "ICMPv6 RA: invalid mtu: %d\n",
1095                                    mtu);
1096                 } else if (in6_dev->cnf.mtu6 != mtu) {
1097                         in6_dev->cnf.mtu6 = mtu;
1098
1099                         if (rt)
1100                                 rt->u.dst.metrics[RTAX_MTU-1] = mtu;
1101
1102                         rt6_mtu_change(skb->dev, mtu);
1103                 }
1104         }
1105                         
1106         if (ndopts.nd_opts_tgt_lladdr || ndopts.nd_opts_rh) {
1107                 ND_PRINTK2(KERN_WARNING
1108                            "ICMPv6 RA: invalid RA options");
1109         }
1110 out:
1111         if (rt)
1112                 dst_release(&rt->u.dst);
1113         in6_dev_put(in6_dev);
1114 }
1115
1116 static void ndisc_redirect_rcv(struct sk_buff *skb)
1117 {
1118         struct inet6_dev *in6_dev;
1119         struct icmp6hdr *icmph;
1120         struct in6_addr *dest;
1121         struct in6_addr *target;        /* new first hop to destination */
1122         struct neighbour *neigh;
1123         int on_link = 0;
1124         struct ndisc_options ndopts;
1125         int optlen;
1126         u8 *lladdr = NULL;
1127         int lladdrlen;
1128
1129         if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr) & IPV6_ADDR_LINKLOCAL)) {
1130                 ND_PRINTK2(KERN_WARNING
1131                            "ICMPv6 Redirect: source address is not link-local.\n");
1132                 return;
1133         }
1134
1135         optlen = skb->tail - skb->h.raw;
1136         optlen -= sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr);
1137
1138         if (optlen < 0) {
1139                 ND_PRINTK2(KERN_WARNING
1140                            "ICMPv6 Redirect: packet too short\n");
1141                 return;
1142         }
1143
1144         icmph = (struct icmp6hdr *) skb->h.raw;
1145         target = (struct in6_addr *) (icmph + 1);
1146         dest = target + 1;
1147
1148         if (ipv6_addr_is_multicast(dest)) {
1149                 ND_PRINTK2(KERN_WARNING
1150                            "ICMPv6 Redirect: destination address is multicast.\n");
1151                 return;
1152         }
1153
1154         if (ipv6_addr_cmp(dest, target) == 0) {
1155                 on_link = 1;
1156         } else if (!(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) {
1157                 ND_PRINTK2(KERN_WARNING 
1158                            "ICMPv6 Redirect: target address is not link-local.\n");
1159                 return;
1160         }
1161
1162         in6_dev = in6_dev_get(skb->dev);
1163         if (!in6_dev)
1164                 return;
1165         if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_redirects) {
1166                 in6_dev_put(in6_dev);
1167                 return;
1168         }
1169
1170         /* RFC2461 8.1: 
1171          *      The IP source address of the Redirect MUST be the same as the current
1172          *      first-hop router for the specified ICMP Destination Address.
1173          */
1174                 
1175         if (!ndisc_parse_options((u8*)(dest + 1), optlen, &ndopts)) {
1176                 ND_PRINTK2(KERN_WARNING
1177                            "ICMPv6 Redirect: invalid ND options\n");
1178                 in6_dev_put(in6_dev);
1179                 return;
1180         }
1181         if (ndopts.nd_opts_tgt_lladdr) {
1182                 lladdr = (u8*)(ndopts.nd_opts_tgt_lladdr + 1);
1183                 lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
1184                 if (lladdrlen != NDISC_OPT_SPACE(skb->dev->addr_len)) {
1185                         ND_PRINTK2(KERN_WARNING
1186                                    "ICMPv6 Redirect: invalid link-layer address length\n");
1187                         in6_dev_put(in6_dev);
1188                         return;
1189                 }
1190         }
1191         /* passed validation tests */
1192
1193         /*
1194            We install redirect only if nexthop state is valid.
1195          */
1196
1197         neigh = __neigh_lookup(&nd_tbl, target, skb->dev, 1);
1198         if (neigh) {
1199                 neigh_update(neigh, lladdr, NUD_STALE, 1, 1);
1200                 if (neigh->nud_state&NUD_VALID)
1201                         rt6_redirect(dest, &skb->nh.ipv6h->saddr, neigh, on_link);
1202                 else
1203                         __neigh_event_send(neigh, NULL);
1204                 neigh_release(neigh);
1205         }
1206         in6_dev_put(in6_dev);
1207 }
1208
1209 void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
1210                          struct in6_addr *target)
1211 {
1212         struct sock *sk = ndisc_socket->sk;
1213         int len = sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr);
1214         struct sk_buff *buff;
1215         struct icmp6hdr *icmph;
1216         struct in6_addr saddr_buf;
1217         struct in6_addr *addrp;
1218         struct net_device *dev;
1219         struct rt6_info *rt;
1220         struct dst_entry *dst;
1221         struct inet6_dev *idev;
1222         struct flowi fl;
1223         u8 *opt;
1224         int rd_len;
1225         int err;
1226         int hlen;
1227
1228         dev = skb->dev;
1229
1230         if (ipv6_get_lladdr(dev, &saddr_buf)) {
1231                 ND_PRINTK2(KERN_WARNING
1232                            "ICMPv6 Redirect: no link-local address on %s\n",
1233                            dev->name);
1234                 return;
1235         }
1236
1237         ndisc_flow_init(&fl, NDISC_REDIRECT, &saddr_buf, &skb->nh.ipv6h->saddr);
1238
1239         rt = rt6_lookup(&skb->nh.ipv6h->saddr, NULL, dev->ifindex, 1);
1240         if (rt == NULL)
1241                 return;
1242         dst = &rt->u.dst;
1243
1244         err = xfrm_lookup(&dst, &fl, NULL, 0);
1245         if (err) {
1246                 dst_release(dst);
1247                 return;
1248         }
1249
1250         rt = (struct rt6_info *) dst;
1251
1252         if (rt->rt6i_flags & RTF_GATEWAY) {
1253                 ND_PRINTK2(KERN_WARNING
1254                            "ICMPv6 Redirect: destination is not a neighbour.\n");
1255                 dst_release(dst);
1256                 return;
1257         }
1258         if (!xrlim_allow(dst, 1*HZ)) {
1259                 dst_release(dst);
1260                 return;
1261         }
1262
1263         if (dev->addr_len) {
1264                 if (neigh->nud_state&NUD_VALID) {
1265                         len  += NDISC_OPT_SPACE(dev->addr_len);
1266                 } else {
1267                         /* If nexthop is not valid, do not redirect!
1268                            We will make it later, when will be sure,
1269                            that it is alive.
1270                          */
1271                         dst_release(dst);
1272                         return;
1273                 }
1274         }
1275
1276         rd_len = min_t(unsigned int,
1277                      IPV6_MIN_MTU-sizeof(struct ipv6hdr)-len, skb->len + 8);
1278         rd_len &= ~0x7;
1279         len += rd_len;
1280
1281         buff = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
1282                                    1, &err);
1283         if (buff == NULL) {
1284                 ND_PRINTK0(KERN_ERR
1285                            "ICMPv6 Redirect: %s() failed to allocate an skb.\n",
1286                            __FUNCTION__);
1287                 dst_release(dst);
1288                 return;
1289         }
1290
1291         hlen = 0;
1292
1293         skb_reserve(buff, LL_RESERVED_SPACE(dev));
1294         ip6_nd_hdr(sk, buff, dev, &saddr_buf, &skb->nh.ipv6h->saddr,
1295                    IPPROTO_ICMPV6, len);
1296
1297         icmph = (struct icmp6hdr *)skb_put(buff, len);
1298         buff->h.raw = (unsigned char*)icmph;
1299
1300         memset(icmph, 0, sizeof(struct icmp6hdr));
1301         icmph->icmp6_type = NDISC_REDIRECT;
1302
1303         /*
1304          *      copy target and destination addresses
1305          */
1306
1307         addrp = (struct in6_addr *)(icmph + 1);
1308         ipv6_addr_copy(addrp, target);
1309         addrp++;
1310         ipv6_addr_copy(addrp, &skb->nh.ipv6h->daddr);
1311
1312         opt = (u8*) (addrp + 1);
1313
1314         /*
1315          *      include target_address option
1316          */
1317
1318         if (dev->addr_len)
1319                 opt = ndisc_fill_option(opt, ND_OPT_TARGET_LL_ADDR, neigh->ha, dev->addr_len);
1320
1321         /*
1322          *      build redirect option and copy skb over to the new packet.
1323          */
1324
1325         memset(opt, 0, 8);      
1326         *(opt++) = ND_OPT_REDIRECT_HDR;
1327         *(opt++) = (rd_len >> 3);
1328         opt += 6;
1329
1330         memcpy(opt, skb->nh.ipv6h, rd_len - 8);
1331
1332         icmph->icmp6_cksum = csum_ipv6_magic(&saddr_buf, &skb->nh.ipv6h->saddr,
1333                                              len, IPPROTO_ICMPV6,
1334                                              csum_partial((u8 *) icmph, len, 0));
1335
1336         buff->dst = dst;
1337         idev = in6_dev_get(dst->dev);
1338         IP6_INC_STATS(OutRequests);
1339         err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, buff, NULL, dst->dev, dst_output);
1340         if (!err) {
1341                 ICMP6_INC_STATS(idev, Icmp6OutRedirects);
1342                 ICMP6_INC_STATS(idev, Icmp6OutMsgs);
1343         }
1344
1345         if (likely(idev != NULL))
1346                 in6_dev_put(idev);
1347 }
1348
1349 static void pndisc_redo(struct sk_buff *skb)
1350 {
1351         ndisc_rcv(skb);
1352         kfree_skb(skb);
1353 }
1354
1355 int ndisc_rcv(struct sk_buff *skb)
1356 {
1357         struct nd_msg *msg;
1358
1359         if (!pskb_may_pull(skb, skb->len))
1360                 return 0;
1361
1362         msg = (struct nd_msg *) skb->h.raw;
1363
1364         __skb_push(skb, skb->data-skb->h.raw);
1365
1366         if (skb->nh.ipv6h->hop_limit != 255) {
1367                 ND_PRINTK2(KERN_WARNING
1368                            "ICMPv6 NDISC: invalid hop-limit: %d\n",
1369                            skb->nh.ipv6h->hop_limit);
1370                 return 0;
1371         }
1372
1373         if (msg->icmph.icmp6_code != 0) {
1374                 ND_PRINTK2(KERN_WARNING 
1375                            "ICMPv6 NDISC: invalid ICMPv6 code: %d\n",
1376                            msg->icmph.icmp6_code);
1377                 return 0;
1378         }
1379
1380         switch (msg->icmph.icmp6_type) {
1381         case NDISC_NEIGHBOUR_SOLICITATION:
1382                 ndisc_recv_ns(skb);
1383                 break;
1384
1385         case NDISC_NEIGHBOUR_ADVERTISEMENT:
1386                 ndisc_recv_na(skb);
1387                 break;
1388
1389         case NDISC_ROUTER_ADVERTISEMENT:
1390                 ndisc_router_discovery(skb);
1391                 break;
1392
1393         case NDISC_REDIRECT:
1394                 ndisc_redirect_rcv(skb);
1395                 break;
1396         };
1397
1398         return 0;
1399 }
1400
1401 static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
1402 {
1403         struct net_device *dev = ptr;
1404
1405         switch (event) {
1406         case NETDEV_CHANGEADDR:
1407                 neigh_changeaddr(&nd_tbl, dev);
1408                 fib6_run_gc(0);
1409                 break;
1410         case NETDEV_DOWN:
1411                 neigh_ifdown(&nd_tbl, dev);
1412                 fib6_run_gc(0);
1413                 break;
1414         default:
1415                 break;
1416         }
1417
1418         return NOTIFY_DONE;
1419 }
1420
1421 static struct notifier_block ndisc_netdev_notifier = {
1422         .notifier_call = ndisc_netdev_event,
1423 };
1424
1425 #ifdef CONFIG_SYSCTL
1426 int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, struct file * filp, void __user *buffer, size_t *lenp)
1427 {
1428         struct net_device *dev = ctl->extra1;
1429         struct inet6_dev *idev;
1430
1431         if (write && dev && (idev = in6_dev_get(dev)) != NULL) {
1432                 idev->tstamp = jiffies;
1433                 inet6_ifinfo_notify(RTM_NEWLINK, idev);
1434                 in6_dev_put(idev);
1435         }
1436         return proc_dointvec(ctl, write, filp, buffer, lenp);
1437 }
1438 #endif
1439
1440 int __init ndisc_init(struct net_proto_family *ops)
1441 {
1442         struct ipv6_pinfo *np;
1443         struct sock *sk;
1444         int err;
1445
1446         err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &ndisc_socket);
1447         if (err < 0) {
1448                 ND_PRINTK0(KERN_ERR
1449                            "ICMPv6 NDISC: Failed to initialize the control socket (err %d).\n", 
1450                            err);
1451                 ndisc_socket = NULL; /* For safety. */
1452                 return err;
1453         }
1454
1455         sk = ndisc_socket->sk;
1456         np = inet6_sk(sk);
1457         sk->sk_allocation = GFP_ATOMIC;
1458         np->hop_limit = 255;
1459         /* Do not loopback ndisc messages */
1460         np->mc_loop = 0;
1461         sk->sk_prot->unhash(sk);
1462
1463         /*
1464          * Initialize the neighbour table
1465          */
1466         
1467         neigh_table_init(&nd_tbl);
1468
1469 #ifdef CONFIG_SYSCTL
1470         neigh_sysctl_register(NULL, &nd_tbl.parms, NET_IPV6, NET_IPV6_NEIGH, 
1471                               "ipv6", &ndisc_ifinfo_sysctl_change);
1472 #endif
1473
1474         register_netdevice_notifier(&ndisc_netdev_notifier);
1475         return 0;
1476 }
1477
1478 void ndisc_cleanup(void)
1479 {
1480 #ifdef CONFIG_SYSCTL
1481         neigh_sysctl_unregister(&nd_tbl.parms);
1482 #endif
1483         neigh_table_clear(&nd_tbl);
1484         sock_release(ndisc_socket);
1485         ndisc_socket = NULL; /* For safety. */
1486 }