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