Linux-2.6.12-rc2
[linux-flexiantxendom0-natty.git] / net / ipv6 / icmp.c
1 /*
2  *      Internet Control Message Protocol (ICMPv6)
3  *      Linux INET6 implementation
4  *
5  *      Authors:
6  *      Pedro Roque             <roque@di.fc.ul.pt>
7  *
8  *      $Id: icmp.c,v 1.38 2002/02/08 03:57:19 davem Exp $
9  *
10  *      Based on net/ipv4/icmp.c
11  *
12  *      RFC 1885
13  *
14  *      This program is free software; you can redistribute it and/or
15  *      modify it under the terms of the GNU General Public License
16  *      as published by the Free Software Foundation; either version
17  *      2 of the License, or (at your option) any later version.
18  */
19
20 /*
21  *      Changes:
22  *
23  *      Andi Kleen              :       exception handling
24  *      Andi Kleen                      add rate limits. never reply to a icmp.
25  *                                      add more length checks and other fixes.
26  *      yoshfuji                :       ensure to sent parameter problem for
27  *                                      fragments.
28  *      YOSHIFUJI Hideaki @USAGI:       added sysctl for icmp rate limit.
29  *      Randy Dunlap and
30  *      YOSHIFUJI Hideaki @USAGI:       Per-interface statistics support
31  *      Kazunori MIYAZAWA @USAGI:       change output process to use ip6_append_data
32  */
33
34 #include <linux/module.h>
35 #include <linux/errno.h>
36 #include <linux/types.h>
37 #include <linux/socket.h>
38 #include <linux/in.h>
39 #include <linux/kernel.h>
40 #include <linux/sched.h>
41 #include <linux/sockios.h>
42 #include <linux/net.h>
43 #include <linux/skbuff.h>
44 #include <linux/init.h>
45
46 #ifdef CONFIG_SYSCTL
47 #include <linux/sysctl.h>
48 #endif
49
50 #include <linux/inet.h>
51 #include <linux/netdevice.h>
52 #include <linux/icmpv6.h>
53
54 #include <net/ip.h>
55 #include <net/sock.h>
56
57 #include <net/ipv6.h>
58 #include <net/ip6_checksum.h>
59 #include <net/protocol.h>
60 #include <net/raw.h>
61 #include <net/rawv6.h>
62 #include <net/transp_v6.h>
63 #include <net/ip6_route.h>
64 #include <net/addrconf.h>
65 #include <net/icmp.h>
66
67 #include <asm/uaccess.h>
68 #include <asm/system.h>
69
70 DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics);
71
72 /*
73  *      The ICMP socket(s). This is the most convenient way to flow control
74  *      our ICMP output as well as maintain a clean interface throughout
75  *      all layers. All Socketless IP sends will soon be gone.
76  *
77  *      On SMP we have one ICMP socket per-cpu.
78  */
79 static DEFINE_PER_CPU(struct socket *, __icmpv6_socket) = NULL;
80 #define icmpv6_socket   __get_cpu_var(__icmpv6_socket)
81
82 static int icmpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp);
83
84 static struct inet6_protocol icmpv6_protocol = {
85         .handler        =       icmpv6_rcv,
86         .flags          =       INET6_PROTO_FINAL,
87 };
88
89 static __inline__ int icmpv6_xmit_lock(void)
90 {
91         local_bh_disable();
92
93         if (unlikely(!spin_trylock(&icmpv6_socket->sk->sk_lock.slock))) {
94                 /* This can happen if the output path (f.e. SIT or
95                  * ip6ip6 tunnel) signals dst_link_failure() for an
96                  * outgoing ICMP6 packet.
97                  */
98                 local_bh_enable();
99                 return 1;
100         }
101         return 0;
102 }
103
104 static __inline__ void icmpv6_xmit_unlock(void)
105 {
106         spin_unlock_bh(&icmpv6_socket->sk->sk_lock.slock);
107 }
108
109 /* 
110  * Slightly more convenient version of icmpv6_send.
111  */
112 void icmpv6_param_prob(struct sk_buff *skb, int code, int pos)
113 {
114         icmpv6_send(skb, ICMPV6_PARAMPROB, code, pos, skb->dev);
115         kfree_skb(skb);
116 }
117
118 /*
119  * Figure out, may we reply to this packet with icmp error.
120  *
121  * We do not reply, if:
122  *      - it was icmp error message.
123  *      - it is truncated, so that it is known, that protocol is ICMPV6
124  *        (i.e. in the middle of some exthdr)
125  *
126  *      --ANK (980726)
127  */
128
129 static int is_ineligible(struct sk_buff *skb)
130 {
131         int ptr = (u8*)(skb->nh.ipv6h+1) - skb->data;
132         int len = skb->len - ptr;
133         __u8 nexthdr = skb->nh.ipv6h->nexthdr;
134
135         if (len < 0)
136                 return 1;
137
138         ptr = ipv6_skip_exthdr(skb, ptr, &nexthdr, len);
139         if (ptr < 0)
140                 return 0;
141         if (nexthdr == IPPROTO_ICMPV6) {
142                 u8 _type, *tp;
143                 tp = skb_header_pointer(skb,
144                         ptr+offsetof(struct icmp6hdr, icmp6_type),
145                         sizeof(_type), &_type);
146                 if (tp == NULL ||
147                     !(*tp & ICMPV6_INFOMSG_MASK))
148                         return 1;
149         }
150         return 0;
151 }
152
153 static int sysctl_icmpv6_time = 1*HZ; 
154
155 /* 
156  * Check the ICMP output rate limit 
157  */
158 static inline int icmpv6_xrlim_allow(struct sock *sk, int type,
159                                      struct flowi *fl)
160 {
161         struct dst_entry *dst;
162         int res = 0;
163
164         /* Informational messages are not limited. */
165         if (type & ICMPV6_INFOMSG_MASK)
166                 return 1;
167
168         /* Do not limit pmtu discovery, it would break it. */
169         if (type == ICMPV6_PKT_TOOBIG)
170                 return 1;
171
172         /* 
173          * Look up the output route.
174          * XXX: perhaps the expire for routing entries cloned by
175          * this lookup should be more aggressive (not longer than timeout).
176          */
177         dst = ip6_route_output(sk, fl);
178         if (dst->error) {
179                 IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES);
180         } else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) {
181                 res = 1;
182         } else {
183                 struct rt6_info *rt = (struct rt6_info *)dst;
184                 int tmo = sysctl_icmpv6_time;
185
186                 /* Give more bandwidth to wider prefixes. */
187                 if (rt->rt6i_dst.plen < 128)
188                         tmo >>= ((128 - rt->rt6i_dst.plen)>>5);
189
190                 res = xrlim_allow(dst, tmo);
191         }
192         dst_release(dst);
193         return res;
194 }
195
196 /*
197  *      an inline helper for the "simple" if statement below
198  *      checks if parameter problem report is caused by an
199  *      unrecognized IPv6 option that has the Option Type 
200  *      highest-order two bits set to 10
201  */
202
203 static __inline__ int opt_unrec(struct sk_buff *skb, __u32 offset)
204 {
205         u8 _optval, *op;
206
207         offset += skb->nh.raw - skb->data;
208         op = skb_header_pointer(skb, offset, sizeof(_optval), &_optval);
209         if (op == NULL)
210                 return 1;
211         return (*op & 0xC0) == 0x80;
212 }
213
214 static int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct icmp6hdr *thdr, int len)
215 {
216         struct sk_buff *skb;
217         struct icmp6hdr *icmp6h;
218         int err = 0;
219
220         if ((skb = skb_peek(&sk->sk_write_queue)) == NULL)
221                 goto out;
222
223         icmp6h = (struct icmp6hdr*) skb->h.raw;
224         memcpy(icmp6h, thdr, sizeof(struct icmp6hdr));
225         icmp6h->icmp6_cksum = 0;
226
227         if (skb_queue_len(&sk->sk_write_queue) == 1) {
228                 skb->csum = csum_partial((char *)icmp6h,
229                                         sizeof(struct icmp6hdr), skb->csum);
230                 icmp6h->icmp6_cksum = csum_ipv6_magic(&fl->fl6_src,
231                                                       &fl->fl6_dst,
232                                                       len, fl->proto,
233                                                       skb->csum);
234         } else {
235                 u32 tmp_csum = 0;
236
237                 skb_queue_walk(&sk->sk_write_queue, skb) {
238                         tmp_csum = csum_add(tmp_csum, skb->csum);
239                 }
240
241                 tmp_csum = csum_partial((char *)icmp6h,
242                                         sizeof(struct icmp6hdr), tmp_csum);
243                 tmp_csum = csum_ipv6_magic(&fl->fl6_src,
244                                            &fl->fl6_dst,
245                                            len, fl->proto, tmp_csum);
246                 icmp6h->icmp6_cksum = tmp_csum;
247         }
248         if (icmp6h->icmp6_cksum == 0)
249                 icmp6h->icmp6_cksum = -1;
250         ip6_push_pending_frames(sk);
251 out:
252         return err;
253 }
254
255 struct icmpv6_msg {
256         struct sk_buff  *skb;
257         int             offset;
258 };
259
260 static int icmpv6_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb)
261 {
262         struct icmpv6_msg *msg = (struct icmpv6_msg *) from;
263         struct sk_buff *org_skb = msg->skb;
264         __u32 csum = 0;
265
266         csum = skb_copy_and_csum_bits(org_skb, msg->offset + offset,
267                                       to, len, csum);
268         skb->csum = csum_block_add(skb->csum, csum, odd);
269         return 0;
270 }
271
272 /*
273  *      Send an ICMP message in response to a packet in error
274  */
275 void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, 
276                  struct net_device *dev)
277 {
278         struct inet6_dev *idev = NULL;
279         struct ipv6hdr *hdr = skb->nh.ipv6h;
280         struct sock *sk = icmpv6_socket->sk;
281         struct ipv6_pinfo *np = inet6_sk(sk);
282         struct in6_addr *saddr = NULL;
283         struct dst_entry *dst;
284         struct icmp6hdr tmp_hdr;
285         struct flowi fl;
286         struct icmpv6_msg msg;
287         int iif = 0;
288         int addr_type = 0;
289         int len;
290         int hlimit;
291         int err = 0;
292
293         if ((u8*)hdr < skb->head || (u8*)(hdr+1) > skb->tail)
294                 return;
295
296         /*
297          *      Make sure we respect the rules 
298          *      i.e. RFC 1885 2.4(e)
299          *      Rule (e.1) is enforced by not using icmpv6_send
300          *      in any code that processes icmp errors.
301          */
302         addr_type = ipv6_addr_type(&hdr->daddr);
303
304         if (ipv6_chk_addr(&hdr->daddr, skb->dev, 0))
305                 saddr = &hdr->daddr;
306
307         /*
308          *      Dest addr check
309          */
310
311         if ((addr_type & IPV6_ADDR_MULTICAST || skb->pkt_type != PACKET_HOST)) {
312                 if (type != ICMPV6_PKT_TOOBIG &&
313                     !(type == ICMPV6_PARAMPROB && 
314                       code == ICMPV6_UNK_OPTION && 
315                       (opt_unrec(skb, info))))
316                         return;
317
318                 saddr = NULL;
319         }
320
321         addr_type = ipv6_addr_type(&hdr->saddr);
322
323         /*
324          *      Source addr check
325          */
326
327         if (addr_type & IPV6_ADDR_LINKLOCAL)
328                 iif = skb->dev->ifindex;
329
330         /*
331          *      Must not send if we know that source is Anycast also.
332          *      for now we don't know that.
333          */
334         if ((addr_type == IPV6_ADDR_ANY) || (addr_type & IPV6_ADDR_MULTICAST)) {
335                 LIMIT_NETDEBUG(
336                         printk(KERN_DEBUG "icmpv6_send: addr_any/mcast source\n"));
337                 return;
338         }
339
340         /* 
341          *      Never answer to a ICMP packet.
342          */
343         if (is_ineligible(skb)) {
344                 LIMIT_NETDEBUG(
345                         printk(KERN_DEBUG "icmpv6_send: no reply to icmp error\n")); 
346                 return;
347         }
348
349         memset(&fl, 0, sizeof(fl));
350         fl.proto = IPPROTO_ICMPV6;
351         ipv6_addr_copy(&fl.fl6_dst, &hdr->saddr);
352         if (saddr)
353                 ipv6_addr_copy(&fl.fl6_src, saddr);
354         fl.oif = iif;
355         fl.fl_icmp_type = type;
356         fl.fl_icmp_code = code;
357
358         if (icmpv6_xmit_lock())
359                 return;
360
361         if (!icmpv6_xrlim_allow(sk, type, &fl))
362                 goto out;
363
364         tmp_hdr.icmp6_type = type;
365         tmp_hdr.icmp6_code = code;
366         tmp_hdr.icmp6_cksum = 0;
367         tmp_hdr.icmp6_pointer = htonl(info);
368
369         if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
370                 fl.oif = np->mcast_oif;
371
372         err = ip6_dst_lookup(sk, &dst, &fl);
373         if (err)
374                 goto out;
375         if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
376                 goto out_dst_release;
377
378         if (ipv6_addr_is_multicast(&fl.fl6_dst))
379                 hlimit = np->mcast_hops;
380         else
381                 hlimit = np->hop_limit;
382         if (hlimit < 0)
383                 hlimit = dst_metric(dst, RTAX_HOPLIMIT);
384         if (hlimit < 0)
385                 hlimit = ipv6_get_hoplimit(dst->dev);
386
387         msg.skb = skb;
388         msg.offset = skb->nh.raw - skb->data;
389
390         len = skb->len - msg.offset;
391         len = min_t(unsigned int, len, IPV6_MIN_MTU - sizeof(struct ipv6hdr) -sizeof(struct icmp6hdr));
392         if (len < 0) {
393                 LIMIT_NETDEBUG(
394                         printk(KERN_DEBUG "icmp: len problem\n"));
395                 goto out_dst_release;
396         }
397
398         idev = in6_dev_get(skb->dev);
399
400         err = ip6_append_data(sk, icmpv6_getfrag, &msg,
401                               len + sizeof(struct icmp6hdr),
402                               sizeof(struct icmp6hdr),
403                               hlimit, NULL, &fl, (struct rt6_info*)dst,
404                               MSG_DONTWAIT);
405         if (err) {
406                 ip6_flush_pending_frames(sk);
407                 goto out_put;
408         }
409         err = icmpv6_push_pending_frames(sk, &fl, &tmp_hdr, len + sizeof(struct icmp6hdr));
410
411         if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB)
412                 ICMP6_INC_STATS_OFFSET_BH(idev, ICMP6_MIB_OUTDESTUNREACHS, type - ICMPV6_DEST_UNREACH);
413         ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS);
414
415 out_put:
416         if (likely(idev != NULL))
417                 in6_dev_put(idev);
418 out_dst_release:
419         dst_release(dst);
420 out:
421         icmpv6_xmit_unlock();
422 }
423
424 static void icmpv6_echo_reply(struct sk_buff *skb)
425 {
426         struct sock *sk = icmpv6_socket->sk;
427         struct inet6_dev *idev;
428         struct ipv6_pinfo *np = inet6_sk(sk);
429         struct in6_addr *saddr = NULL;
430         struct icmp6hdr *icmph = (struct icmp6hdr *) skb->h.raw;
431         struct icmp6hdr tmp_hdr;
432         struct flowi fl;
433         struct icmpv6_msg msg;
434         struct dst_entry *dst;
435         int err = 0;
436         int hlimit;
437
438         saddr = &skb->nh.ipv6h->daddr;
439
440         if (!ipv6_unicast_destination(skb))
441                 saddr = NULL;
442
443         memcpy(&tmp_hdr, icmph, sizeof(tmp_hdr));
444         tmp_hdr.icmp6_type = ICMPV6_ECHO_REPLY;
445
446         memset(&fl, 0, sizeof(fl));
447         fl.proto = IPPROTO_ICMPV6;
448         ipv6_addr_copy(&fl.fl6_dst, &skb->nh.ipv6h->saddr);
449         if (saddr)
450                 ipv6_addr_copy(&fl.fl6_src, saddr);
451         fl.oif = skb->dev->ifindex;
452         fl.fl_icmp_type = ICMPV6_ECHO_REPLY;
453
454         if (icmpv6_xmit_lock())
455                 return;
456
457         if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
458                 fl.oif = np->mcast_oif;
459
460         err = ip6_dst_lookup(sk, &dst, &fl);
461         if (err)
462                 goto out;
463         if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
464                 goto out_dst_release;
465
466         if (ipv6_addr_is_multicast(&fl.fl6_dst))
467                 hlimit = np->mcast_hops;
468         else
469                 hlimit = np->hop_limit;
470         if (hlimit < 0)
471                 hlimit = dst_metric(dst, RTAX_HOPLIMIT);
472         if (hlimit < 0)
473                 hlimit = ipv6_get_hoplimit(dst->dev);
474
475         idev = in6_dev_get(skb->dev);
476
477         msg.skb = skb;
478         msg.offset = 0;
479
480         err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr),
481                                 sizeof(struct icmp6hdr), hlimit, NULL, &fl,
482                                 (struct rt6_info*)dst, MSG_DONTWAIT);
483
484         if (err) {
485                 ip6_flush_pending_frames(sk);
486                 goto out_put;
487         }
488         err = icmpv6_push_pending_frames(sk, &fl, &tmp_hdr, skb->len + sizeof(struct icmp6hdr));
489
490         ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTECHOREPLIES);
491         ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS);
492
493 out_put: 
494         if (likely(idev != NULL))
495                 in6_dev_put(idev);
496 out_dst_release:
497         dst_release(dst);
498 out: 
499         icmpv6_xmit_unlock();
500 }
501
502 static void icmpv6_notify(struct sk_buff *skb, int type, int code, u32 info)
503 {
504         struct in6_addr *saddr, *daddr;
505         struct inet6_protocol *ipprot;
506         struct sock *sk;
507         int inner_offset;
508         int hash;
509         u8 nexthdr;
510
511         if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
512                 return;
513
514         nexthdr = ((struct ipv6hdr *)skb->data)->nexthdr;
515         if (ipv6_ext_hdr(nexthdr)) {
516                 /* now skip over extension headers */
517                 inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr, skb->len - sizeof(struct ipv6hdr));
518                 if (inner_offset<0)
519                         return;
520         } else {
521                 inner_offset = sizeof(struct ipv6hdr);
522         }
523
524         /* Checkin header including 8 bytes of inner protocol header. */
525         if (!pskb_may_pull(skb, inner_offset+8))
526                 return;
527
528         saddr = &skb->nh.ipv6h->saddr;
529         daddr = &skb->nh.ipv6h->daddr;
530
531         /* BUGGG_FUTURE: we should try to parse exthdrs in this packet.
532            Without this we will not able f.e. to make source routed
533            pmtu discovery.
534            Corresponding argument (opt) to notifiers is already added.
535            --ANK (980726)
536          */
537
538         hash = nexthdr & (MAX_INET_PROTOS - 1);
539
540         rcu_read_lock();
541         ipprot = rcu_dereference(inet6_protos[hash]);
542         if (ipprot && ipprot->err_handler)
543                 ipprot->err_handler(skb, NULL, type, code, inner_offset, info);
544         rcu_read_unlock();
545
546         read_lock(&raw_v6_lock);
547         if ((sk = sk_head(&raw_v6_htable[hash])) != NULL) {
548                 while((sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr))) {
549                         rawv6_err(sk, skb, NULL, type, code, inner_offset, info);
550                         sk = sk_next(sk);
551                 }
552         }
553         read_unlock(&raw_v6_lock);
554 }
555   
556 /*
557  *      Handle icmp messages
558  */
559
560 static int icmpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
561 {
562         struct sk_buff *skb = *pskb;
563         struct net_device *dev = skb->dev;
564         struct inet6_dev *idev = __in6_dev_get(dev);
565         struct in6_addr *saddr, *daddr;
566         struct ipv6hdr *orig_hdr;
567         struct icmp6hdr *hdr;
568         int type;
569
570         ICMP6_INC_STATS_BH(idev, ICMP6_MIB_INMSGS);
571
572         saddr = &skb->nh.ipv6h->saddr;
573         daddr = &skb->nh.ipv6h->daddr;
574
575         /* Perform checksum. */
576         if (skb->ip_summed == CHECKSUM_HW) {
577                 skb->ip_summed = CHECKSUM_UNNECESSARY;
578                 if (csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6,
579                                     skb->csum)) {
580                         LIMIT_NETDEBUG(
581                                 printk(KERN_DEBUG "ICMPv6 hw checksum failed\n"));
582                         skb->ip_summed = CHECKSUM_NONE;
583                 }
584         }
585         if (skb->ip_summed == CHECKSUM_NONE) {
586                 if (csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6,
587                                     skb_checksum(skb, 0, skb->len, 0))) {
588                         LIMIT_NETDEBUG(
589                                 printk(KERN_DEBUG "ICMPv6 checksum failed [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x > %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]\n",
590                                        NIP6(*saddr), NIP6(*daddr)));
591                         goto discard_it;
592                 }
593         }
594
595         if (!pskb_pull(skb, sizeof(struct icmp6hdr)))
596                 goto discard_it;
597
598         hdr = (struct icmp6hdr *) skb->h.raw;
599
600         type = hdr->icmp6_type;
601
602         if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB)
603                 ICMP6_INC_STATS_OFFSET_BH(idev, ICMP6_MIB_INDESTUNREACHS, type - ICMPV6_DEST_UNREACH);
604         else if (type >= ICMPV6_ECHO_REQUEST && type <= NDISC_REDIRECT)
605                 ICMP6_INC_STATS_OFFSET_BH(idev, ICMP6_MIB_INECHOS, type - ICMPV6_ECHO_REQUEST);
606
607         switch (type) {
608         case ICMPV6_ECHO_REQUEST:
609                 icmpv6_echo_reply(skb);
610                 break;
611
612         case ICMPV6_ECHO_REPLY:
613                 /* we couldn't care less */
614                 break;
615
616         case ICMPV6_PKT_TOOBIG:
617                 /* BUGGG_FUTURE: if packet contains rthdr, we cannot update
618                    standard destination cache. Seems, only "advanced"
619                    destination cache will allow to solve this problem
620                    --ANK (980726)
621                  */
622                 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
623                         goto discard_it;
624                 hdr = (struct icmp6hdr *) skb->h.raw;
625                 orig_hdr = (struct ipv6hdr *) (hdr + 1);
626                 rt6_pmtu_discovery(&orig_hdr->daddr, &orig_hdr->saddr, dev,
627                                    ntohl(hdr->icmp6_mtu));
628
629                 /*
630                  *      Drop through to notify
631                  */
632
633         case ICMPV6_DEST_UNREACH:
634         case ICMPV6_TIME_EXCEED:
635         case ICMPV6_PARAMPROB:
636                 icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu);
637                 break;
638
639         case NDISC_ROUTER_SOLICITATION:
640         case NDISC_ROUTER_ADVERTISEMENT:
641         case NDISC_NEIGHBOUR_SOLICITATION:
642         case NDISC_NEIGHBOUR_ADVERTISEMENT:
643         case NDISC_REDIRECT:
644                 ndisc_rcv(skb);
645                 break;
646
647         case ICMPV6_MGM_QUERY:
648                 igmp6_event_query(skb);
649                 break;
650
651         case ICMPV6_MGM_REPORT:
652                 igmp6_event_report(skb);
653                 break;
654
655         case ICMPV6_MGM_REDUCTION:
656         case ICMPV6_NI_QUERY:
657         case ICMPV6_NI_REPLY:
658         case ICMPV6_MLD2_REPORT:
659         case ICMPV6_DHAAD_REQUEST:
660         case ICMPV6_DHAAD_REPLY:
661         case ICMPV6_MOBILE_PREFIX_SOL:
662         case ICMPV6_MOBILE_PREFIX_ADV:
663                 break;
664
665         default:
666                 LIMIT_NETDEBUG(
667                         printk(KERN_DEBUG "icmpv6: msg of unknown type\n"));
668
669                 /* informational */
670                 if (type & ICMPV6_INFOMSG_MASK)
671                         break;
672
673                 /* 
674                  * error of unknown type. 
675                  * must pass to upper level 
676                  */
677
678                 icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu);
679         };
680         kfree_skb(skb);
681         return 0;
682
683 discard_it:
684         ICMP6_INC_STATS_BH(idev, ICMP6_MIB_INERRORS);
685         kfree_skb(skb);
686         return 0;
687 }
688
689 int __init icmpv6_init(struct net_proto_family *ops)
690 {
691         struct sock *sk;
692         int err, i, j;
693
694         for (i = 0; i < NR_CPUS; i++) {
695                 if (!cpu_possible(i))
696                         continue;
697
698                 err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6,
699                                        &per_cpu(__icmpv6_socket, i));
700                 if (err < 0) {
701                         printk(KERN_ERR
702                                "Failed to initialize the ICMP6 control socket "
703                                "(err %d).\n",
704                                err);
705                         goto fail;
706                 }
707
708                 sk = per_cpu(__icmpv6_socket, i)->sk;
709                 sk->sk_allocation = GFP_ATOMIC;
710
711                 /* Enough space for 2 64K ICMP packets, including
712                  * sk_buff struct overhead.
713                  */
714                 sk->sk_sndbuf =
715                         (2 * ((64 * 1024) + sizeof(struct sk_buff)));
716
717                 sk->sk_prot->unhash(sk);
718         }
719
720
721         if (inet6_add_protocol(&icmpv6_protocol, IPPROTO_ICMPV6) < 0) {
722                 printk(KERN_ERR "Failed to register ICMP6 protocol\n");
723                 err = -EAGAIN;
724                 goto fail;
725         }
726
727         return 0;
728
729  fail:
730         for (j = 0; j < i; j++) {
731                 if (!cpu_possible(j))
732                         continue;
733                 sock_release(per_cpu(__icmpv6_socket, j));
734         }
735
736         return err;
737 }
738
739 void icmpv6_cleanup(void)
740 {
741         int i;
742
743         for (i = 0; i < NR_CPUS; i++) {
744                 if (!cpu_possible(i))
745                         continue;
746                 sock_release(per_cpu(__icmpv6_socket, i));
747         }
748         inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6);
749 }
750
751 static struct icmp6_err {
752         int err;
753         int fatal;
754 } tab_unreach[] = {
755         {       /* NOROUTE */
756                 .err    = ENETUNREACH,
757                 .fatal  = 0,
758         },
759         {       /* ADM_PROHIBITED */
760                 .err    = EACCES,
761                 .fatal  = 1,
762         },
763         {       /* Was NOT_NEIGHBOUR, now reserved */
764                 .err    = EHOSTUNREACH,
765                 .fatal  = 0,
766         },
767         {       /* ADDR_UNREACH */
768                 .err    = EHOSTUNREACH,
769                 .fatal  = 0,
770         },
771         {       /* PORT_UNREACH */
772                 .err    = ECONNREFUSED,
773                 .fatal  = 1,
774         },
775 };
776
777 int icmpv6_err_convert(int type, int code, int *err)
778 {
779         int fatal = 0;
780
781         *err = EPROTO;
782
783         switch (type) {
784         case ICMPV6_DEST_UNREACH:
785                 fatal = 1;
786                 if (code <= ICMPV6_PORT_UNREACH) {
787                         *err  = tab_unreach[code].err;
788                         fatal = tab_unreach[code].fatal;
789                 }
790                 break;
791
792         case ICMPV6_PKT_TOOBIG:
793                 *err = EMSGSIZE;
794                 break;
795                 
796         case ICMPV6_PARAMPROB:
797                 *err = EPROTO;
798                 fatal = 1;
799                 break;
800
801         case ICMPV6_TIME_EXCEED:
802                 *err = EHOSTUNREACH;
803                 break;
804         };
805
806         return fatal;
807 }
808
809 #ifdef CONFIG_SYSCTL
810 ctl_table ipv6_icmp_table[] = {
811         {
812                 .ctl_name       = NET_IPV6_ICMP_RATELIMIT,
813                 .procname       = "ratelimit",
814                 .data           = &sysctl_icmpv6_time,
815                 .maxlen         = sizeof(int),
816                 .mode           = 0644,
817                 .proc_handler   = &proc_dointvec
818         },
819         { .ctl_name = 0 },
820 };
821 #endif
822