1 /*
2  *	Internet Control Message Protocol (ICMPv6)
3  *	Linux INET6 implementation
4  *
5  *	Authors:
6  *	Pedro Roque		<pedro_m@yahoo.com>
7  *
8  *	$Id: icmp.c,v 1.37 2001/09/18 22:29:10 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  */
30 
31 #include <linux/module.h>
32 #include <linux/errno.h>
33 #include <linux/types.h>
34 #include <linux/socket.h>
35 #include <linux/in.h>
36 #include <linux/kernel.h>
37 #include <linux/sched.h>
38 #include <linux/sockios.h>
39 #include <linux/net.h>
40 #include <linux/skbuff.h>
41 #include <linux/init.h>
42 
43 #ifdef CONFIG_SYSCTL
44 #include <linux/sysctl.h>
45 #endif
46 
47 #include <linux/inet.h>
48 #include <linux/netdevice.h>
49 #include <linux/icmpv6.h>
50 
51 #include <net/ip.h>
52 #include <net/sock.h>
53 
54 #include <net/ipv6.h>
55 #include <net/checksum.h>
56 #include <net/protocol.h>
57 #include <net/raw.h>
58 #include <net/rawv6.h>
59 #include <net/transp_v6.h>
60 #include <net/ip6_route.h>
61 #include <net/addrconf.h>
62 #include <net/icmp.h>
63 
64 #include <asm/uaccess.h>
65 #include <asm/system.h>
66 
67 struct icmpv6_mib icmpv6_statistics[NR_CPUS*2];
68 
69 /*
70  *	ICMP socket(s) for flow control.
71  */
72 
73 static struct socket *__icmpv6_socket[NR_CPUS];
74 #define icmpv6_socket	__icmpv6_socket[smp_processor_id()]
75 #define icmpv6_socket_cpu(X) __icmpv6_socket[(X)]
76 
77 int icmpv6_rcv(struct sk_buff *skb);
78 
79 static struct inet6_protocol icmpv6_protocol =
80 {
81 	icmpv6_rcv,		/* handler		*/
82 	NULL,			/* error control	*/
83 	NULL,			/* next			*/
84 	IPPROTO_ICMPV6,		/* protocol ID		*/
85 	0,			/* copy			*/
86 	NULL,			/* data			*/
87 	"ICMPv6"	       	/* name			*/
88 };
89 
90 struct icmpv6_msg {
91 	struct icmp6hdr		icmph;
92 	struct sk_buff		*skb;
93 	int			offset;
94 	struct in6_addr		*daddr;
95 	int			len;
96 	__u32			csum;
97 };
98 
99 
icmpv6_xmit_lock(void)100 static int icmpv6_xmit_lock(void)
101 {
102 	local_bh_disable();
103 	if (unlikely(!spin_trylock(&icmpv6_socket->sk->lock.slock))) {
104 		/* This can happen if the output path (f.e. SIT or
105 		 * ip6ip6 tunnel) signals dst_link_failure() for an
106 		 * outgoing ICMP6 packet.
107 		 */
108 		local_bh_enable();
109 		return 1;
110 	}
111 	return 0;
112 }
113 
icmpv6_xmit_unlock(void)114 static void icmpv6_xmit_unlock(void)
115 {
116 	spin_unlock_bh(&icmpv6_socket->sk->lock.slock);
117 }
118 
119 /*
120  *	getfrag callback
121  */
122 
icmpv6_getfrag(const void * data,struct in6_addr * saddr,char * buff,unsigned int offset,unsigned int len)123 static int icmpv6_getfrag(const void *data, struct in6_addr *saddr,
124 			   char *buff, unsigned int offset, unsigned int len)
125 {
126 	struct icmpv6_msg *msg = (struct icmpv6_msg *) data;
127 	struct icmp6hdr *icmph;
128 	__u32 csum;
129 
130 	if (offset) {
131 		csum = skb_copy_and_csum_bits(msg->skb, msg->offset +
132 					      (offset - sizeof(struct icmp6hdr)),
133 					      buff, len, msg->csum);
134 		msg->csum = csum;
135 		return 0;
136 	}
137 
138 	csum = csum_partial_copy_nocheck((void *) &msg->icmph, buff,
139 					 sizeof(struct icmp6hdr), msg->csum);
140 
141 	csum = skb_copy_and_csum_bits(msg->skb, msg->offset,
142 				      buff + sizeof(struct icmp6hdr),
143 				      len - sizeof(struct icmp6hdr), csum);
144 
145 	icmph = (struct icmp6hdr *) buff;
146 
147 	icmph->icmp6_cksum = csum_ipv6_magic(saddr, msg->daddr, msg->len,
148 					     IPPROTO_ICMPV6, csum);
149 	return 0;
150 }
151 
152 
153 /*
154  * Slightly more convenient version of icmpv6_send.
155  */
icmpv6_param_prob(struct sk_buff * skb,int code,int pos)156 void icmpv6_param_prob(struct sk_buff *skb, int code, int pos)
157 {
158 	icmpv6_send(skb, ICMPV6_PARAMPROB, code, pos, skb->dev);
159 	kfree_skb(skb);
160 }
161 
162 /*
163  * Figure out, may we reply to this packet with icmp error.
164  *
165  * We do not reply, if:
166  *	- it was icmp error message.
167  *	- it is truncated, so that it is known, that protocol is ICMPV6
168  *	  (i.e. in the middle of some exthdr)
169  *
170  *	--ANK (980726)
171  */
172 
is_ineligible(struct sk_buff * skb)173 static int is_ineligible(struct sk_buff *skb)
174 {
175 	int ptr = (u8*)(skb->nh.ipv6h+1) - skb->data;
176 	int len = skb->len - ptr;
177 	__u8 nexthdr = skb->nh.ipv6h->nexthdr;
178 
179 	if (len < 0)
180 		return 1;
181 
182 	ptr = ipv6_skip_exthdr(skb, ptr, &nexthdr, len);
183 	if (ptr < 0)
184 		return 0;
185 	if (nexthdr == IPPROTO_ICMPV6) {
186 		u8 type;
187 		if (skb_copy_bits(skb, ptr+offsetof(struct icmp6hdr, icmp6_type),
188 				  &type, 1)
189 		    || !(type & ICMPV6_INFOMSG_MASK))
190 			return 1;
191 	}
192 	return 0;
193 }
194 
195 int sysctl_icmpv6_time = 1*HZ;
196 
197 /*
198  * Check the ICMP output rate limit
199  */
icmpv6_xrlim_allow(struct sock * sk,int type,struct flowi * fl)200 static inline int icmpv6_xrlim_allow(struct sock *sk, int type,
201 				     struct flowi *fl)
202 {
203 	struct dst_entry *dst;
204 	int res = 0;
205 
206 	/* Informational messages are not limited. */
207 	if (type & ICMPV6_INFOMSG_MASK)
208 		return 1;
209 
210 	/* Do not limit pmtu discovery, it would break it. */
211 	if (type == ICMPV6_PKT_TOOBIG)
212 		return 1;
213 
214 	/*
215 	 * Look up the output route.
216 	 * XXX: perhaps the expire for routing entries cloned by
217 	 * this lookup should be more aggressive (not longer than timeout).
218 	 */
219 	dst = ip6_route_output(sk, fl);
220 	if (dst->error) {
221 		IP6_INC_STATS(Ip6OutNoRoutes);
222 	} else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) {
223 		res = 1;
224 	} else {
225 		struct rt6_info *rt = (struct rt6_info *)dst;
226 		int tmo = sysctl_icmpv6_time;
227 
228 		/* Give more bandwidth to wider prefixes. */
229 		if (rt->rt6i_dst.plen < 128)
230 			tmo >>= ((128 - rt->rt6i_dst.plen)>>5);
231 
232 		res = xrlim_allow(dst, tmo);
233 	}
234 	dst_release(dst);
235 	return res;
236 }
237 
238 /*
239  *	an inline helper for the "simple" if statement below
240  *	checks if parameter problem report is caused by an
241  *	unrecognized IPv6 option that has the Option Type
242  *	highest-order two bits set to 10
243  */
244 
opt_unrec(struct sk_buff * skb,__u32 offset)245 static __inline__ int opt_unrec(struct sk_buff *skb, __u32 offset)
246 {
247 	u8 optval;
248 
249 	offset += skb->nh.raw - skb->data;
250 	if (skb_copy_bits(skb, offset, &optval, 1))
251 		return 1;
252 	return (optval&0xC0) == 0x80;
253 }
254 
255 /*
256  *	Send an ICMP message in response to a packet in error
257  */
258 
icmpv6_send(struct sk_buff * skb,int type,int code,__u32 info,struct net_device * dev)259 void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
260 		 struct net_device *dev)
261 {
262 	struct ipv6hdr *hdr = skb->nh.ipv6h;
263 	struct sock *sk = icmpv6_socket->sk;
264 	struct in6_addr *saddr = NULL;
265 	int iif = 0;
266 	struct icmpv6_msg msg;
267 	struct flowi fl;
268 	int addr_type = 0;
269 	int len;
270 
271 	if ((u8*)hdr < skb->head || (u8*)(hdr+1) > skb->tail)
272 		return;
273 
274 	/*
275 	 *	Make sure we respect the rules
276 	 *	i.e. RFC 1885 2.4(e)
277 	 *	Rule (e.1) is enforced by not using icmpv6_send
278 	 *	in any code that processes icmp errors.
279 	 */
280 	addr_type = ipv6_addr_type(&hdr->daddr);
281 
282 	if (ipv6_chk_addr(&hdr->daddr, skb->dev))
283 		saddr = &hdr->daddr;
284 
285 	/*
286 	 *	Dest addr check
287 	 */
288 
289 	if ((addr_type & IPV6_ADDR_MULTICAST || skb->pkt_type != PACKET_HOST)) {
290 		if (type != ICMPV6_PKT_TOOBIG &&
291 		    !(type == ICMPV6_PARAMPROB &&
292 		      code == ICMPV6_UNK_OPTION &&
293 		      (opt_unrec(skb, info))))
294 			return;
295 
296 		saddr = NULL;
297 	}
298 
299 	addr_type = ipv6_addr_type(&hdr->saddr);
300 
301 	/*
302 	 *	Source addr check
303 	 */
304 
305 	if (addr_type & IPV6_ADDR_LINKLOCAL)
306 		iif = skb->dev->ifindex;
307 
308 	/*
309 	 *	Must not send if we know that source is Anycast also.
310 	 *	for now we don't know that.
311 	 */
312 	if ((addr_type == IPV6_ADDR_ANY) || (addr_type & IPV6_ADDR_MULTICAST)) {
313 		if (net_ratelimit())
314 			printk(KERN_DEBUG "icmpv6_send: addr_any/mcast source\n");
315 		return;
316 	}
317 
318 	/*
319 	 *	Never answer to a ICMP packet.
320 	 */
321 	if (is_ineligible(skb)) {
322 		if (net_ratelimit())
323 			printk(KERN_DEBUG "icmpv6_send: no reply to icmp error\n");
324 		return;
325 	}
326 
327 	fl.proto = IPPROTO_ICMPV6;
328 	fl.nl_u.ip6_u.daddr = &hdr->saddr;
329 	fl.nl_u.ip6_u.saddr = saddr;
330 	fl.oif = iif;
331 	fl.fl6_flowlabel = 0;
332 	fl.uli_u.icmpt.type = type;
333 	fl.uli_u.icmpt.code = code;
334 
335 	if (icmpv6_xmit_lock())
336 		return;
337 
338 	if (!icmpv6_xrlim_allow(sk, type, &fl))
339 		goto out;
340 
341 	/*
342 	 *	ok. kick it. checksum will be provided by the
343 	 *	getfrag_t callback.
344 	 */
345 
346 	msg.icmph.icmp6_type = type;
347 	msg.icmph.icmp6_code = code;
348 	msg.icmph.icmp6_cksum = 0;
349 	msg.icmph.icmp6_pointer = htonl(info);
350 
351 	msg.skb = skb;
352 	msg.offset = skb->nh.raw - skb->data;
353 	msg.csum = 0;
354 	msg.daddr = &hdr->saddr;
355 
356 	len = skb->len - msg.offset + sizeof(struct icmp6hdr);
357 	len = min_t(unsigned int, len, IPV6_MIN_MTU - sizeof(struct ipv6hdr));
358 
359 	if (len < 0) {
360 		if (net_ratelimit())
361 			printk(KERN_DEBUG "icmp: len problem\n");
362 		goto out;
363 	}
364 
365 	msg.len = len;
366 
367 	ip6_build_xmit(sk, icmpv6_getfrag, &msg, &fl, len, NULL, -1,
368 		       MSG_DONTWAIT);
369 	if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB)
370 		(&(icmpv6_statistics[smp_processor_id()*2].Icmp6OutDestUnreachs))[type-1]++;
371 	ICMP6_INC_STATS_BH(Icmp6OutMsgs);
372 out:
373 	icmpv6_xmit_unlock();
374 }
375 
icmpv6_echo_reply(struct sk_buff * skb)376 static void icmpv6_echo_reply(struct sk_buff *skb)
377 {
378 	struct sock *sk = icmpv6_socket->sk;
379 	struct icmp6hdr *icmph = (struct icmp6hdr *) skb->h.raw;
380 	struct in6_addr *saddr;
381 	struct icmpv6_msg msg;
382 	struct flowi fl;
383 
384 	saddr = &skb->nh.ipv6h->daddr;
385 
386 	if (ipv6_addr_type(saddr) & IPV6_ADDR_MULTICAST ||
387 	    ipv6_chk_acast_addr(0, saddr))
388 		saddr = NULL;
389 
390 	msg.icmph.icmp6_type = ICMPV6_ECHO_REPLY;
391 	msg.icmph.icmp6_code = 0;
392 	msg.icmph.icmp6_cksum = 0;
393 	msg.icmph.icmp6_identifier = icmph->icmp6_identifier;
394 	msg.icmph.icmp6_sequence = icmph->icmp6_sequence;
395 
396 	msg.skb = skb;
397 	msg.offset = 0;
398 	msg.csum = 0;
399 	msg.len = skb->len + sizeof(struct icmp6hdr);
400 	msg.daddr =  &skb->nh.ipv6h->saddr;
401 
402 	fl.proto = IPPROTO_ICMPV6;
403 	fl.nl_u.ip6_u.daddr = msg.daddr;
404 	fl.nl_u.ip6_u.saddr = saddr;
405 	fl.oif = skb->dev->ifindex;
406 	fl.fl6_flowlabel = 0;
407 	fl.uli_u.icmpt.type = ICMPV6_ECHO_REPLY;
408 	fl.uli_u.icmpt.code = 0;
409 
410 	if (icmpv6_xmit_lock())
411 		return;
412 
413 	ip6_build_xmit(sk, icmpv6_getfrag, &msg, &fl, msg.len, NULL, -1,
414 		       MSG_DONTWAIT);
415 	ICMP6_INC_STATS_BH(Icmp6OutEchoReplies);
416 	ICMP6_INC_STATS_BH(Icmp6OutMsgs);
417 
418 	icmpv6_xmit_unlock();
419 }
420 
icmpv6_notify(struct sk_buff * skb,int type,int code,u32 info)421 static void icmpv6_notify(struct sk_buff *skb, int type, int code, u32 info)
422 {
423 	struct in6_addr *saddr, *daddr;
424 	struct inet6_protocol *ipprot;
425 	struct sock *sk;
426 	int inner_offset;
427 	int hash;
428 	u8 nexthdr;
429 
430 	if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
431 		return;
432 
433 	nexthdr = ((struct ipv6hdr *)skb->data)->nexthdr;
434 	if (ipv6_ext_hdr(nexthdr)) {
435 		/* now skip over extension headers */
436 		inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr, skb->len - sizeof(struct ipv6hdr));
437 		if (inner_offset<0)
438 			return;
439 	} else {
440 		inner_offset = sizeof(struct ipv6hdr);
441 	}
442 
443 	/* Checkin header including 8 bytes of inner protocol header. */
444 	if (!pskb_may_pull(skb, inner_offset+8))
445 		return;
446 
447 	saddr = &skb->nh.ipv6h->saddr;
448 	daddr = &skb->nh.ipv6h->daddr;
449 
450 	/* BUGGG_FUTURE: we should try to parse exthdrs in this packet.
451 	   Without this we will not able f.e. to make source routed
452 	   pmtu discovery.
453 	   Corresponding argument (opt) to notifiers is already added.
454 	   --ANK (980726)
455 	 */
456 
457 	hash = nexthdr & (MAX_INET_PROTOS - 1);
458 
459 	for (ipprot = (struct inet6_protocol *) inet6_protos[hash];
460 	     ipprot != NULL;
461 	     ipprot=(struct inet6_protocol *)ipprot->next) {
462 		if (ipprot->protocol != nexthdr)
463 			continue;
464 
465 		if (ipprot->err_handler)
466 			ipprot->err_handler(skb, NULL, type, code, inner_offset, info);
467 	}
468 
469 	read_lock(&raw_v6_lock);
470 	if ((sk = raw_v6_htable[hash]) != NULL) {
471 		while((sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr))) {
472 			rawv6_err(sk, skb, NULL, type, code, inner_offset, info);
473 			sk = sk->next;
474 		}
475 	}
476 	read_unlock(&raw_v6_lock);
477 }
478 
479 /*
480  *	Handle icmp messages
481  */
482 
icmpv6_rcv(struct sk_buff * skb)483 int icmpv6_rcv(struct sk_buff *skb)
484 {
485 	struct net_device *dev = skb->dev;
486 	struct in6_addr *saddr, *daddr;
487 	struct ipv6hdr *orig_hdr;
488 	struct icmp6hdr *hdr;
489 	int type;
490 
491 	ICMP6_INC_STATS_BH(Icmp6InMsgs);
492 
493 	saddr = &skb->nh.ipv6h->saddr;
494 	daddr = &skb->nh.ipv6h->daddr;
495 
496 	/* Perform checksum. */
497 	if (skb->ip_summed == CHECKSUM_HW) {
498 		skb->ip_summed = CHECKSUM_UNNECESSARY;
499 		if (csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6,
500 				    skb->csum)) {
501 			if (net_ratelimit())
502 				printk(KERN_DEBUG "ICMPv6 hw checksum failed\n");
503 			skb->ip_summed = CHECKSUM_NONE;
504 		}
505 	}
506 	if (skb->ip_summed == CHECKSUM_NONE) {
507 		if (csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6,
508 				    skb_checksum(skb, 0, skb->len, 0))) {
509 			if (net_ratelimit())
510 				printk(KERN_DEBUG "ICMPv6 checksum failed [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x > %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]\n",
511 				       ntohs(saddr->s6_addr16[0]),
512 				       ntohs(saddr->s6_addr16[1]),
513 				       ntohs(saddr->s6_addr16[2]),
514 				       ntohs(saddr->s6_addr16[3]),
515 				       ntohs(saddr->s6_addr16[4]),
516 				       ntohs(saddr->s6_addr16[5]),
517 				       ntohs(saddr->s6_addr16[6]),
518 				       ntohs(saddr->s6_addr16[7]),
519 				       ntohs(daddr->s6_addr16[0]),
520 				       ntohs(daddr->s6_addr16[1]),
521 				       ntohs(daddr->s6_addr16[2]),
522 				       ntohs(daddr->s6_addr16[3]),
523 				       ntohs(daddr->s6_addr16[4]),
524 				       ntohs(daddr->s6_addr16[5]),
525 				       ntohs(daddr->s6_addr16[6]),
526 				       ntohs(daddr->s6_addr16[7]));
527 			goto discard_it;
528 		}
529 	}
530 
531 	if (!pskb_pull(skb, sizeof(struct icmp6hdr)))
532 		goto discard_it;
533 
534 	hdr = (struct icmp6hdr *) skb->h.raw;
535 
536 	type = hdr->icmp6_type;
537 
538 	if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB)
539 		(&icmpv6_statistics[smp_processor_id()*2].Icmp6InDestUnreachs)[type-ICMPV6_DEST_UNREACH]++;
540 	else if (type >= ICMPV6_ECHO_REQUEST && type <= NDISC_REDIRECT)
541 		(&icmpv6_statistics[smp_processor_id()*2].Icmp6InEchos)[type-ICMPV6_ECHO_REQUEST]++;
542 
543 	switch (type) {
544 	case ICMPV6_ECHO_REQUEST:
545 		icmpv6_echo_reply(skb);
546 		break;
547 
548 	case ICMPV6_ECHO_REPLY:
549 		/* we coulnd't care less */
550 		break;
551 
552 	case ICMPV6_PKT_TOOBIG:
553 		/* BUGGG_FUTURE: if packet contains rthdr, we cannot update
554 		   standard destination cache. Seems, only "advanced"
555 		   destination cache will allow to solve this problem
556 		   --ANK (980726)
557 		 */
558 		if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
559 			goto discard_it;
560 		hdr = (struct icmp6hdr *) skb->h.raw;
561 		orig_hdr = (struct ipv6hdr *) (hdr + 1);
562 		rt6_pmtu_discovery(&orig_hdr->daddr, &orig_hdr->saddr, dev,
563 				   ntohl(hdr->icmp6_mtu));
564 
565 		/*
566 		 *	Drop through to notify
567 		 */
568 
569 	case ICMPV6_DEST_UNREACH:
570 	case ICMPV6_TIME_EXCEED:
571 	case ICMPV6_PARAMPROB:
572 		icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu);
573 		break;
574 
575 	case NDISC_ROUTER_SOLICITATION:
576 	case NDISC_ROUTER_ADVERTISEMENT:
577 	case NDISC_NEIGHBOUR_SOLICITATION:
578 	case NDISC_NEIGHBOUR_ADVERTISEMENT:
579 	case NDISC_REDIRECT:
580 		if (skb_is_nonlinear(skb) &&
581 		    skb_linearize(skb, GFP_ATOMIC) != 0) {
582 			kfree_skb(skb);
583 			return 0;
584 		}
585 
586 		ndisc_rcv(skb);
587 		break;
588 
589 	case ICMPV6_MGM_QUERY:
590 		igmp6_event_query(skb);
591 		break;
592 
593 	case ICMPV6_MGM_REPORT:
594 		igmp6_event_report(skb);
595 		break;
596 
597 	case ICMPV6_MGM_REDUCTION:
598 	case ICMPV6_MLD2_REPORT:
599 		break;
600 
601 	default:
602 		if (net_ratelimit())
603 			printk(KERN_DEBUG "icmpv6: msg of unkown type\n");
604 
605 		/* informational */
606 		if (type & ICMPV6_INFOMSG_MASK)
607 			break;
608 
609 		/*
610 		 * error of unkown type.
611 		 * must pass to upper level
612 		 */
613 
614 		icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu);
615 	};
616 	kfree_skb(skb);
617 	return 0;
618 
619 discard_it:
620 	ICMP6_INC_STATS_BH(Icmp6InErrors);
621 	kfree_skb(skb);
622 	return 0;
623 }
624 
icmpv6_init(struct net_proto_family * ops)625 int __init icmpv6_init(struct net_proto_family *ops)
626 {
627 	struct sock *sk;
628 	int err, i, j;
629 
630 	for (i = 0; i < NR_CPUS; i++) {
631 		icmpv6_socket_cpu(i) = sock_alloc();
632 		if (icmpv6_socket_cpu(i) == NULL) {
633 			printk(KERN_ERR
634 			       "Failed to create the ICMP6 control socket.\n");
635 			err = -1;
636 			goto fail;
637 		}
638 		icmpv6_socket_cpu(i)->inode->i_uid = 0;
639 		icmpv6_socket_cpu(i)->inode->i_gid = 0;
640 		icmpv6_socket_cpu(i)->type = SOCK_RAW;
641 
642 		if ((err = ops->create(icmpv6_socket_cpu(i), IPPROTO_ICMPV6)) < 0) {
643 			printk(KERN_ERR
644 			       "Failed to initialize the ICMP6 control socket "
645 			       "(err %d).\n",
646 			       err);
647 			goto fail;
648 		}
649 
650 		sk = icmpv6_socket_cpu(i)->sk;
651 		sk->allocation = GFP_ATOMIC;
652 
653 		/* Enough space for 2 64K ICMP packets, including
654 		 * sk_buff struct overhead.
655 		 */
656 		sk->sndbuf =
657 			(2 * ((64 * 1024) + sizeof(struct sk_buff)));
658 
659 		sk->prot->unhash(sk);
660 	}
661 
662 	inet6_add_protocol(&icmpv6_protocol);
663 
664 	return 0;
665 fail:
666 	for (j = 0; j < i; j++) {
667 		sock_release(icmpv6_socket_cpu(j));
668 		icmpv6_socket_cpu(j) = NULL;
669 	}
670 	return err;
671 }
672 
icmpv6_cleanup(void)673 void icmpv6_cleanup(void)
674 {
675 	int i;
676 
677 	for (i = 0; i < NR_CPUS; i++) {
678 		sock_release(icmpv6_socket_cpu(i));
679 		icmpv6_socket_cpu(i) = NULL;
680 	}
681 	inet6_del_protocol(&icmpv6_protocol);
682 }
683 
684 static struct icmp6_err {
685 	int err;
686 	int fatal;
687 } tab_unreach[] = {
688 	{ ENETUNREACH,	0},	/* NOROUTE		*/
689 	{ EACCES,	1},	/* ADM_PROHIBITED	*/
690 	{ EHOSTUNREACH,	0},	/* Was NOT_NEIGHBOUR, now reserved */
691 	{ EHOSTUNREACH,	0},	/* ADDR_UNREACH		*/
692 	{ ECONNREFUSED,	1},	/* PORT_UNREACH		*/
693 };
694 
icmpv6_err_convert(int type,int code,int * err)695 int icmpv6_err_convert(int type, int code, int *err)
696 {
697 	int fatal = 0;
698 
699 	*err = EPROTO;
700 
701 	switch (type) {
702 	case ICMPV6_DEST_UNREACH:
703 		fatal = 1;
704 		if (code <= ICMPV6_PORT_UNREACH) {
705 			*err  = tab_unreach[code].err;
706 			fatal = tab_unreach[code].fatal;
707 		}
708 		break;
709 
710 	case ICMPV6_PKT_TOOBIG:
711 		*err = EMSGSIZE;
712 		break;
713 
714 	case ICMPV6_PARAMPROB:
715 		*err = EPROTO;
716 		fatal = 1;
717 		break;
718 
719 	case ICMPV6_TIME_EXCEED:
720 		*err = EHOSTUNREACH;
721 		break;
722 	};
723 
724 	return fatal;
725 }
726 
727 #ifdef CONFIG_SYSCTL
728 ctl_table ipv6_icmp_table[] = {
729 	{NET_IPV6_ICMP_RATELIMIT, "ratelimit",
730 	&sysctl_icmpv6_time, sizeof(int), 0644, NULL, &proc_dointvec},
731 	{0},
732 };
733 #endif
734 
735