]> err.no Git - linux-2.6/blob - net/ipv6/icmp.c
ee9f1d36346c647c5aadd5e4137561790ded9590
[linux-2.6] / 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);
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;
281         struct ipv6_pinfo *np;
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         sk = icmpv6_socket->sk;
362         np = inet6_sk(sk);
363
364         if (!icmpv6_xrlim_allow(sk, type, &fl))
365                 goto out;
366
367         tmp_hdr.icmp6_type = type;
368         tmp_hdr.icmp6_code = code;
369         tmp_hdr.icmp6_cksum = 0;
370         tmp_hdr.icmp6_pointer = htonl(info);
371
372         if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
373                 fl.oif = np->mcast_oif;
374
375         err = ip6_dst_lookup(sk, &dst, &fl);
376         if (err)
377                 goto out;
378         if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
379                 goto out_dst_release;
380
381         if (ipv6_addr_is_multicast(&fl.fl6_dst))
382                 hlimit = np->mcast_hops;
383         else
384                 hlimit = np->hop_limit;
385         if (hlimit < 0)
386                 hlimit = dst_metric(dst, RTAX_HOPLIMIT);
387         if (hlimit < 0)
388                 hlimit = ipv6_get_hoplimit(dst->dev);
389
390         msg.skb = skb;
391         msg.offset = skb->nh.raw - skb->data;
392
393         len = skb->len - msg.offset;
394         len = min_t(unsigned int, len, IPV6_MIN_MTU - sizeof(struct ipv6hdr) -sizeof(struct icmp6hdr));
395         if (len < 0) {
396                 LIMIT_NETDEBUG(
397                         printk(KERN_DEBUG "icmp: len problem\n"));
398                 goto out_dst_release;
399         }
400
401         idev = in6_dev_get(skb->dev);
402
403         err = ip6_append_data(sk, icmpv6_getfrag, &msg,
404                               len + sizeof(struct icmp6hdr),
405                               sizeof(struct icmp6hdr),
406                               hlimit, NULL, &fl, (struct rt6_info*)dst,
407                               MSG_DONTWAIT);
408         if (err) {
409                 ip6_flush_pending_frames(sk);
410                 goto out_put;
411         }
412         err = icmpv6_push_pending_frames(sk, &fl, &tmp_hdr, len + sizeof(struct icmp6hdr));
413
414         if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB)
415                 ICMP6_INC_STATS_OFFSET_BH(idev, ICMP6_MIB_OUTDESTUNREACHS, type - ICMPV6_DEST_UNREACH);
416         ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS);
417
418 out_put:
419         if (likely(idev != NULL))
420                 in6_dev_put(idev);
421 out_dst_release:
422         dst_release(dst);
423 out:
424         icmpv6_xmit_unlock();
425 }
426
427 static void icmpv6_echo_reply(struct sk_buff *skb)
428 {
429         struct sock *sk;
430         struct inet6_dev *idev;
431         struct ipv6_pinfo *np;
432         struct in6_addr *saddr = NULL;
433         struct icmp6hdr *icmph = (struct icmp6hdr *) skb->h.raw;
434         struct icmp6hdr tmp_hdr;
435         struct flowi fl;
436         struct icmpv6_msg msg;
437         struct dst_entry *dst;
438         int err = 0;
439         int hlimit;
440
441         saddr = &skb->nh.ipv6h->daddr;
442
443         if (!ipv6_unicast_destination(skb))
444                 saddr = NULL;
445
446         memcpy(&tmp_hdr, icmph, sizeof(tmp_hdr));
447         tmp_hdr.icmp6_type = ICMPV6_ECHO_REPLY;
448
449         memset(&fl, 0, sizeof(fl));
450         fl.proto = IPPROTO_ICMPV6;
451         ipv6_addr_copy(&fl.fl6_dst, &skb->nh.ipv6h->saddr);
452         if (saddr)
453                 ipv6_addr_copy(&fl.fl6_src, saddr);
454         fl.oif = skb->dev->ifindex;
455         fl.fl_icmp_type = ICMPV6_ECHO_REPLY;
456
457         if (icmpv6_xmit_lock())
458                 return;
459
460         sk = icmpv6_socket->sk;
461         np = inet6_sk(sk);
462
463         if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
464                 fl.oif = np->mcast_oif;
465
466         err = ip6_dst_lookup(sk, &dst, &fl);
467         if (err)
468                 goto out;
469         if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
470                 goto out_dst_release;
471
472         if (ipv6_addr_is_multicast(&fl.fl6_dst))
473                 hlimit = np->mcast_hops;
474         else
475                 hlimit = np->hop_limit;
476         if (hlimit < 0)
477                 hlimit = dst_metric(dst, RTAX_HOPLIMIT);
478         if (hlimit < 0)
479                 hlimit = ipv6_get_hoplimit(dst->dev);
480
481         idev = in6_dev_get(skb->dev);
482
483         msg.skb = skb;
484         msg.offset = 0;
485
486         err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr),
487                                 sizeof(struct icmp6hdr), hlimit, NULL, &fl,
488                                 (struct rt6_info*)dst, MSG_DONTWAIT);
489
490         if (err) {
491                 ip6_flush_pending_frames(sk);
492                 goto out_put;
493         }
494         err = icmpv6_push_pending_frames(sk, &fl, &tmp_hdr, skb->len + sizeof(struct icmp6hdr));
495
496         ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTECHOREPLIES);
497         ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS);
498
499 out_put: 
500         if (likely(idev != NULL))
501                 in6_dev_put(idev);
502 out_dst_release:
503         dst_release(dst);
504 out: 
505         icmpv6_xmit_unlock();
506 }
507
508 static void icmpv6_notify(struct sk_buff *skb, int type, int code, u32 info)
509 {
510         struct in6_addr *saddr, *daddr;
511         struct inet6_protocol *ipprot;
512         struct sock *sk;
513         int inner_offset;
514         int hash;
515         u8 nexthdr;
516
517         if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
518                 return;
519
520         nexthdr = ((struct ipv6hdr *)skb->data)->nexthdr;
521         if (ipv6_ext_hdr(nexthdr)) {
522                 /* now skip over extension headers */
523                 inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr);
524                 if (inner_offset<0)
525                         return;
526         } else {
527                 inner_offset = sizeof(struct ipv6hdr);
528         }
529
530         /* Checkin header including 8 bytes of inner protocol header. */
531         if (!pskb_may_pull(skb, inner_offset+8))
532                 return;
533
534         saddr = &skb->nh.ipv6h->saddr;
535         daddr = &skb->nh.ipv6h->daddr;
536
537         /* BUGGG_FUTURE: we should try to parse exthdrs in this packet.
538            Without this we will not able f.e. to make source routed
539            pmtu discovery.
540            Corresponding argument (opt) to notifiers is already added.
541            --ANK (980726)
542          */
543
544         hash = nexthdr & (MAX_INET_PROTOS - 1);
545
546         rcu_read_lock();
547         ipprot = rcu_dereference(inet6_protos[hash]);
548         if (ipprot && ipprot->err_handler)
549                 ipprot->err_handler(skb, NULL, type, code, inner_offset, info);
550         rcu_read_unlock();
551
552         read_lock(&raw_v6_lock);
553         if ((sk = sk_head(&raw_v6_htable[hash])) != NULL) {
554                 while((sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr,
555                                             skb->dev->ifindex))) {
556                         rawv6_err(sk, skb, NULL, type, code, inner_offset, info);
557                         sk = sk_next(sk);
558                 }
559         }
560         read_unlock(&raw_v6_lock);
561 }
562   
563 /*
564  *      Handle icmp messages
565  */
566
567 static int icmpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
568 {
569         struct sk_buff *skb = *pskb;
570         struct net_device *dev = skb->dev;
571         struct inet6_dev *idev = __in6_dev_get(dev);
572         struct in6_addr *saddr, *daddr;
573         struct ipv6hdr *orig_hdr;
574         struct icmp6hdr *hdr;
575         int type;
576
577         ICMP6_INC_STATS_BH(idev, ICMP6_MIB_INMSGS);
578
579         saddr = &skb->nh.ipv6h->saddr;
580         daddr = &skb->nh.ipv6h->daddr;
581
582         /* Perform checksum. */
583         if (skb->ip_summed == CHECKSUM_HW) {
584                 skb->ip_summed = CHECKSUM_UNNECESSARY;
585                 if (csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6,
586                                     skb->csum)) {
587                         LIMIT_NETDEBUG(
588                                 printk(KERN_DEBUG "ICMPv6 hw checksum failed\n"));
589                         skb->ip_summed = CHECKSUM_NONE;
590                 }
591         }
592         if (skb->ip_summed == CHECKSUM_NONE) {
593                 if (csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6,
594                                     skb_checksum(skb, 0, skb->len, 0))) {
595                         LIMIT_NETDEBUG(
596                                 printk(KERN_DEBUG "ICMPv6 checksum failed [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x > %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]\n",
597                                        NIP6(*saddr), NIP6(*daddr)));
598                         goto discard_it;
599                 }
600         }
601
602         if (!pskb_pull(skb, sizeof(struct icmp6hdr)))
603                 goto discard_it;
604
605         hdr = (struct icmp6hdr *) skb->h.raw;
606
607         type = hdr->icmp6_type;
608
609         if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB)
610                 ICMP6_INC_STATS_OFFSET_BH(idev, ICMP6_MIB_INDESTUNREACHS, type - ICMPV6_DEST_UNREACH);
611         else if (type >= ICMPV6_ECHO_REQUEST && type <= NDISC_REDIRECT)
612                 ICMP6_INC_STATS_OFFSET_BH(idev, ICMP6_MIB_INECHOS, type - ICMPV6_ECHO_REQUEST);
613
614         switch (type) {
615         case ICMPV6_ECHO_REQUEST:
616                 icmpv6_echo_reply(skb);
617                 break;
618
619         case ICMPV6_ECHO_REPLY:
620                 /* we couldn't care less */
621                 break;
622
623         case ICMPV6_PKT_TOOBIG:
624                 /* BUGGG_FUTURE: if packet contains rthdr, we cannot update
625                    standard destination cache. Seems, only "advanced"
626                    destination cache will allow to solve this problem
627                    --ANK (980726)
628                  */
629                 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
630                         goto discard_it;
631                 hdr = (struct icmp6hdr *) skb->h.raw;
632                 orig_hdr = (struct ipv6hdr *) (hdr + 1);
633                 rt6_pmtu_discovery(&orig_hdr->daddr, &orig_hdr->saddr, dev,
634                                    ntohl(hdr->icmp6_mtu));
635
636                 /*
637                  *      Drop through to notify
638                  */
639
640         case ICMPV6_DEST_UNREACH:
641         case ICMPV6_TIME_EXCEED:
642         case ICMPV6_PARAMPROB:
643                 icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu);
644                 break;
645
646         case NDISC_ROUTER_SOLICITATION:
647         case NDISC_ROUTER_ADVERTISEMENT:
648         case NDISC_NEIGHBOUR_SOLICITATION:
649         case NDISC_NEIGHBOUR_ADVERTISEMENT:
650         case NDISC_REDIRECT:
651                 ndisc_rcv(skb);
652                 break;
653
654         case ICMPV6_MGM_QUERY:
655                 igmp6_event_query(skb);
656                 break;
657
658         case ICMPV6_MGM_REPORT:
659                 igmp6_event_report(skb);
660                 break;
661
662         case ICMPV6_MGM_REDUCTION:
663         case ICMPV6_NI_QUERY:
664         case ICMPV6_NI_REPLY:
665         case ICMPV6_MLD2_REPORT:
666         case ICMPV6_DHAAD_REQUEST:
667         case ICMPV6_DHAAD_REPLY:
668         case ICMPV6_MOBILE_PREFIX_SOL:
669         case ICMPV6_MOBILE_PREFIX_ADV:
670                 break;
671
672         default:
673                 LIMIT_NETDEBUG(
674                         printk(KERN_DEBUG "icmpv6: msg of unknown type\n"));
675
676                 /* informational */
677                 if (type & ICMPV6_INFOMSG_MASK)
678                         break;
679
680                 /* 
681                  * error of unknown type. 
682                  * must pass to upper level 
683                  */
684
685                 icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu);
686         };
687         kfree_skb(skb);
688         return 0;
689
690 discard_it:
691         ICMP6_INC_STATS_BH(idev, ICMP6_MIB_INERRORS);
692         kfree_skb(skb);
693         return 0;
694 }
695
696 int __init icmpv6_init(struct net_proto_family *ops)
697 {
698         struct sock *sk;
699         int err, i, j;
700
701         for (i = 0; i < NR_CPUS; i++) {
702                 if (!cpu_possible(i))
703                         continue;
704
705                 err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6,
706                                        &per_cpu(__icmpv6_socket, i));
707                 if (err < 0) {
708                         printk(KERN_ERR
709                                "Failed to initialize the ICMP6 control socket "
710                                "(err %d).\n",
711                                err);
712                         goto fail;
713                 }
714
715                 sk = per_cpu(__icmpv6_socket, i)->sk;
716                 sk->sk_allocation = GFP_ATOMIC;
717
718                 /* Enough space for 2 64K ICMP packets, including
719                  * sk_buff struct overhead.
720                  */
721                 sk->sk_sndbuf =
722                         (2 * ((64 * 1024) + sizeof(struct sk_buff)));
723
724                 sk->sk_prot->unhash(sk);
725         }
726
727
728         if (inet6_add_protocol(&icmpv6_protocol, IPPROTO_ICMPV6) < 0) {
729                 printk(KERN_ERR "Failed to register ICMP6 protocol\n");
730                 err = -EAGAIN;
731                 goto fail;
732         }
733
734         return 0;
735
736  fail:
737         for (j = 0; j < i; j++) {
738                 if (!cpu_possible(j))
739                         continue;
740                 sock_release(per_cpu(__icmpv6_socket, j));
741         }
742
743         return err;
744 }
745
746 void icmpv6_cleanup(void)
747 {
748         int i;
749
750         for (i = 0; i < NR_CPUS; i++) {
751                 if (!cpu_possible(i))
752                         continue;
753                 sock_release(per_cpu(__icmpv6_socket, i));
754         }
755         inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6);
756 }
757
758 static struct icmp6_err {
759         int err;
760         int fatal;
761 } tab_unreach[] = {
762         {       /* NOROUTE */
763                 .err    = ENETUNREACH,
764                 .fatal  = 0,
765         },
766         {       /* ADM_PROHIBITED */
767                 .err    = EACCES,
768                 .fatal  = 1,
769         },
770         {       /* Was NOT_NEIGHBOUR, now reserved */
771                 .err    = EHOSTUNREACH,
772                 .fatal  = 0,
773         },
774         {       /* ADDR_UNREACH */
775                 .err    = EHOSTUNREACH,
776                 .fatal  = 0,
777         },
778         {       /* PORT_UNREACH */
779                 .err    = ECONNREFUSED,
780                 .fatal  = 1,
781         },
782 };
783
784 int icmpv6_err_convert(int type, int code, int *err)
785 {
786         int fatal = 0;
787
788         *err = EPROTO;
789
790         switch (type) {
791         case ICMPV6_DEST_UNREACH:
792                 fatal = 1;
793                 if (code <= ICMPV6_PORT_UNREACH) {
794                         *err  = tab_unreach[code].err;
795                         fatal = tab_unreach[code].fatal;
796                 }
797                 break;
798
799         case ICMPV6_PKT_TOOBIG:
800                 *err = EMSGSIZE;
801                 break;
802                 
803         case ICMPV6_PARAMPROB:
804                 *err = EPROTO;
805                 fatal = 1;
806                 break;
807
808         case ICMPV6_TIME_EXCEED:
809                 *err = EHOSTUNREACH;
810                 break;
811         };
812
813         return fatal;
814 }
815
816 #ifdef CONFIG_SYSCTL
817 ctl_table ipv6_icmp_table[] = {
818         {
819                 .ctl_name       = NET_IPV6_ICMP_RATELIMIT,
820                 .procname       = "ratelimit",
821                 .data           = &sysctl_icmpv6_time,
822                 .maxlen         = sizeof(int),
823                 .mode           = 0644,
824                 .proc_handler   = &proc_dointvec
825         },
826         { .ctl_name = 0 },
827 };
828 #endif
829