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