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