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