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