2 * Internet Control Message Protocol (ICMPv6)
3 * Linux INET6 implementation
6 * Pedro Roque <roque@di.fc.ul.pt>
8 * $Id: icmp.c,v 1.1.1.1 2005/04/11 02:51:13 jack Exp $
10 * Based on net/ipv4/icmp.c
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.
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
28 * YOSHIFUJI Hideaki @USAGI: added sysctl for icmp rate limit.
31 #define __NO_VERSION__
32 #include <linux/module.h>
33 #include <linux/errno.h>
34 #include <linux/types.h>
35 #include <linux/socket.h>
37 #include <linux/kernel.h>
38 #include <linux/sched.h>
39 #include <linux/sockios.h>
40 #include <linux/net.h>
41 #include <linux/skbuff.h>
42 #include <linux/init.h>
45 #include <linux/sysctl.h>
48 #include <linux/inet.h>
49 #include <linux/netdevice.h>
50 #include <linux/icmpv6.h>
56 #include <net/checksum.h>
57 #include <net/protocol.h>
59 #include <net/rawv6.h>
60 #include <net/transp_v6.h>
61 #include <net/ip6_route.h>
62 #include <net/addrconf.h>
65 #include <asm/uaccess.h>
66 #include <asm/system.h>
68 struct icmpv6_mib icmpv6_statistics[NR_CPUS*2];
71 * ICMP socket for flow control.
74 struct socket *icmpv6_socket;
76 int icmpv6_rcv(struct sk_buff *skb);
78 static struct inet6_protocol icmpv6_protocol =
80 icmpv6_rcv, /* handler */
81 NULL, /* error control */
83 IPPROTO_ICMPV6, /* protocol ID */
90 struct icmp6hdr icmph;
93 struct in6_addr *daddr;
99 static int icmpv6_xmit_holder = -1;
101 static int icmpv6_xmit_lock_bh(void)
103 if (!spin_trylock(&icmpv6_socket->sk->lock.slock)) {
104 if (icmpv6_xmit_holder == smp_processor_id())
106 spin_lock(&icmpv6_socket->sk->lock.slock);
108 icmpv6_xmit_holder = smp_processor_id();
112 static __inline__ int icmpv6_xmit_lock(void)
116 ret = icmpv6_xmit_lock_bh();
122 static void icmpv6_xmit_unlock_bh(void)
124 icmpv6_xmit_holder = -1;
125 spin_unlock(&icmpv6_socket->sk->lock.slock);
128 static __inline__ void icmpv6_xmit_unlock(void)
130 icmpv6_xmit_unlock_bh();
140 static int icmpv6_getfrag(const void *data, struct in6_addr *saddr,
141 char *buff, unsigned int offset, unsigned int len)
143 struct icmpv6_msg *msg = (struct icmpv6_msg *) data;
144 struct icmp6hdr *icmph;
148 csum = skb_copy_and_csum_bits(msg->skb, msg->offset +
149 (offset - sizeof(struct icmp6hdr)),
150 buff, len, msg->csum);
155 csum = csum_partial_copy_nocheck((void *) &msg->icmph, buff,
156 sizeof(struct icmp6hdr), msg->csum);
158 csum = skb_copy_and_csum_bits(msg->skb, msg->offset,
159 buff + sizeof(struct icmp6hdr),
160 len - sizeof(struct icmp6hdr), csum);
162 icmph = (struct icmp6hdr *) buff;
164 icmph->icmp6_cksum = csum_ipv6_magic(saddr, msg->daddr, msg->len,
165 IPPROTO_ICMPV6, csum);
171 * Slightly more convenient version of icmpv6_send.
173 void icmpv6_param_prob(struct sk_buff *skb, int code, int pos)
175 icmpv6_send(skb, ICMPV6_PARAMPROB, code, pos, skb->dev);
180 * Figure out, may we reply to this packet with icmp error.
182 * We do not reply, if:
183 * - it was icmp error message.
184 * - it is truncated, so that it is known, that protocol is ICMPV6
185 * (i.e. in the middle of some exthdr)
190 static int is_ineligible(struct sk_buff *skb)
192 int ptr = (u8*)(skb->nh.ipv6h+1) - skb->data;
193 int len = skb->len - ptr;
194 __u8 nexthdr = skb->nh.ipv6h->nexthdr;
199 ptr = ipv6_skip_exthdr(skb, ptr, &nexthdr, len);
202 if (nexthdr == IPPROTO_ICMPV6) {
204 if (skb_copy_bits(skb, ptr+offsetof(struct icmp6hdr, icmp6_type),
206 || !(type & ICMPV6_INFOMSG_MASK))
212 int sysctl_icmpv6_time = 1*HZ;
215 * Check the ICMP output rate limit
217 static inline int icmpv6_xrlim_allow(struct sock *sk, int type,
220 struct dst_entry *dst;
223 /* Informational messages are not limited. */
224 if (type & ICMPV6_INFOMSG_MASK)
227 /* Do not limit pmtu discovery, it would break it. */
228 if (type == ICMPV6_PKT_TOOBIG)
232 * Look up the output route.
233 * XXX: perhaps the expire for routing entries cloned by
234 * this lookup should be more aggressive (not longer than timeout).
236 dst = ip6_route_output(sk, fl);
238 IP6_INC_STATS(Ip6OutNoRoutes);
239 } else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) {
242 struct rt6_info *rt = (struct rt6_info *)dst;
243 int tmo = sysctl_icmpv6_time;
245 /* Give more bandwidth to wider prefixes. */
246 if (rt->rt6i_dst.plen < 128)
247 tmo >>= ((128 - rt->rt6i_dst.plen)>>5);
249 res = xrlim_allow(dst, tmo);
256 * an inline helper for the "simple" if statement below
257 * checks if parameter problem report is caused by an
258 * unrecognized IPv6 option that has the Option Type
259 * highest-order two bits set to 10
262 static __inline__ int opt_unrec(struct sk_buff *skb, __u32 offset)
266 offset += skb->nh.raw - skb->data;
267 if (skb_copy_bits(skb, offset, &optval, 1))
269 return (optval&0xC0) == 0x80;
273 * Send an ICMP message in response to a packet in error
276 void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
277 struct net_device *dev)
279 struct ipv6hdr *hdr = skb->nh.ipv6h;
280 struct sock *sk = icmpv6_socket->sk;
281 struct in6_addr *saddr = NULL;
283 struct icmpv6_msg msg;
288 if ((u8*)hdr < skb->head || (u8*)(hdr+1) > skb->tail)
292 * Make sure we respect the rules
293 * i.e. RFC 1885 2.4(e)
294 * Rule (e.1) is enforced by not using icmpv6_send
295 * in any code that processes icmp errors.
297 addr_type = ipv6_addr_type(&hdr->daddr);
299 if (ipv6_chk_addr(&hdr->daddr, skb->dev))
306 if ((addr_type & IPV6_ADDR_MULTICAST || skb->pkt_type != PACKET_HOST)) {
307 if (type != ICMPV6_PKT_TOOBIG &&
308 !(type == ICMPV6_PARAMPROB &&
309 code == ICMPV6_UNK_OPTION &&
310 (opt_unrec(skb, info))))
316 addr_type = ipv6_addr_type(&hdr->saddr);
322 if (addr_type & IPV6_ADDR_LINKLOCAL)
323 iif = skb->dev->ifindex;
326 * Must not send if we know that source is Anycast also.
327 * for now we don't know that.
329 if ((addr_type == IPV6_ADDR_ANY) || (addr_type & IPV6_ADDR_MULTICAST)) {
331 printk(KERN_DEBUG "icmpv6_send: addr_any/mcast source\n");
336 * Never answer to a ICMP packet.
338 if (is_ineligible(skb)) {
340 printk(KERN_DEBUG "icmpv6_send: no reply to icmp error\n");
344 fl.proto = IPPROTO_ICMPV6;
345 fl.nl_u.ip6_u.daddr = &hdr->saddr;
346 fl.nl_u.ip6_u.saddr = saddr;
348 fl.fl6_flowlabel = 0;
349 fl.uli_u.icmpt.type = type;
350 fl.uli_u.icmpt.code = code;
352 if (icmpv6_xmit_lock())
355 if (!icmpv6_xrlim_allow(sk, type, &fl))
359 * ok. kick it. checksum will be provided by the
360 * getfrag_t callback.
363 msg.icmph.icmp6_type = type;
364 msg.icmph.icmp6_code = code;
365 msg.icmph.icmp6_cksum = 0;
366 msg.icmph.icmp6_pointer = htonl(info);
369 msg.offset = skb->nh.raw - skb->data;
371 msg.daddr = &hdr->saddr;
373 len = skb->len - msg.offset + sizeof(struct icmp6hdr);
374 len = min_t(unsigned int, len, IPV6_MIN_MTU - sizeof(struct ipv6hdr));
378 printk(KERN_DEBUG "icmp: len problem\n");
384 ip6_build_xmit(sk, icmpv6_getfrag, &msg, &fl, len, NULL, -1,
386 if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB)
387 (&(icmpv6_statistics[smp_processor_id()*2].Icmp6OutDestUnreachs))[type-1]++;
388 ICMP6_INC_STATS_BH(Icmp6OutMsgs);
390 icmpv6_xmit_unlock();
393 static void icmpv6_echo_reply(struct sk_buff *skb)
395 struct sock *sk = icmpv6_socket->sk;
396 struct icmp6hdr *icmph = (struct icmp6hdr *) skb->h.raw;
397 struct in6_addr *saddr;
398 struct icmpv6_msg msg;
401 saddr = &skb->nh.ipv6h->daddr;
403 if (ipv6_addr_type(saddr) & IPV6_ADDR_MULTICAST)
406 msg.icmph.icmp6_type = ICMPV6_ECHO_REPLY;
407 msg.icmph.icmp6_code = 0;
408 msg.icmph.icmp6_cksum = 0;
409 msg.icmph.icmp6_identifier = icmph->icmp6_identifier;
410 msg.icmph.icmp6_sequence = icmph->icmp6_sequence;
415 msg.len = skb->len + sizeof(struct icmp6hdr);
416 msg.daddr = &skb->nh.ipv6h->saddr;
418 fl.proto = IPPROTO_ICMPV6;
419 fl.nl_u.ip6_u.daddr = msg.daddr;
420 fl.nl_u.ip6_u.saddr = saddr;
421 fl.oif = skb->dev->ifindex;
422 fl.fl6_flowlabel = 0;
423 fl.uli_u.icmpt.type = ICMPV6_ECHO_REPLY;
424 fl.uli_u.icmpt.code = 0;
426 if (icmpv6_xmit_lock_bh())
429 ip6_build_xmit(sk, icmpv6_getfrag, &msg, &fl, msg.len, NULL, -1,
431 ICMP6_INC_STATS_BH(Icmp6OutEchoReplies);
432 ICMP6_INC_STATS_BH(Icmp6OutMsgs);
434 icmpv6_xmit_unlock_bh();
437 static void icmpv6_notify(struct sk_buff *skb, int type, int code, u32 info)
439 struct in6_addr *saddr, *daddr;
440 struct inet6_protocol *ipprot;
446 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
449 nexthdr = ((struct ipv6hdr *)skb->data)->nexthdr;
450 if (ipv6_ext_hdr(nexthdr)) {
451 /* now skip over extension headers */
452 inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr, skb->len - sizeof(struct ipv6hdr));
456 inner_offset = sizeof(struct ipv6hdr);
459 /* Checkin header including 8 bytes of inner protocol header. */
460 if (!pskb_may_pull(skb, inner_offset+8))
463 saddr = &skb->nh.ipv6h->saddr;
464 daddr = &skb->nh.ipv6h->daddr;
466 /* BUGGG_FUTURE: we should try to parse exthdrs in this packet.
467 Without this we will not able f.e. to make source routed
469 Corresponding argument (opt) to notifiers is already added.
473 hash = nexthdr & (MAX_INET_PROTOS - 1);
475 for (ipprot = (struct inet6_protocol *) inet6_protos[hash];
477 ipprot=(struct inet6_protocol *)ipprot->next) {
478 if (ipprot->protocol != nexthdr)
481 if (ipprot->err_handler)
482 ipprot->err_handler(skb, NULL, type, code, inner_offset, info);
485 read_lock(&raw_v6_lock);
486 if ((sk = raw_v6_htable[hash]) != NULL) {
487 while((sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr))) {
488 rawv6_err(sk, skb, NULL, type, code, inner_offset, info);
492 read_unlock(&raw_v6_lock);
496 * Handle icmp messages
499 int icmpv6_rcv(struct sk_buff *skb)
501 struct net_device *dev = skb->dev;
502 struct in6_addr *saddr, *daddr;
503 struct ipv6hdr *orig_hdr;
504 struct icmp6hdr *hdr;
507 ICMP6_INC_STATS_BH(Icmp6InMsgs);
509 saddr = &skb->nh.ipv6h->saddr;
510 daddr = &skb->nh.ipv6h->daddr;
512 /* Perform checksum. */
513 if (skb->ip_summed == CHECKSUM_HW) {
514 skb->ip_summed = CHECKSUM_UNNECESSARY;
515 if (csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6,
518 printk(KERN_DEBUG "ICMPv6 hw checksum failed\n");
519 skb->ip_summed = CHECKSUM_NONE;
522 if (skb->ip_summed == CHECKSUM_NONE) {
523 if (csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6,
524 skb_checksum(skb, 0, skb->len, 0))) {
526 printk(KERN_DEBUG "ICMPv6 checksum failed [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x > %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]\n",
527 ntohs(saddr->s6_addr16[0]),
528 ntohs(saddr->s6_addr16[1]),
529 ntohs(saddr->s6_addr16[2]),
530 ntohs(saddr->s6_addr16[3]),
531 ntohs(saddr->s6_addr16[4]),
532 ntohs(saddr->s6_addr16[5]),
533 ntohs(saddr->s6_addr16[6]),
534 ntohs(saddr->s6_addr16[7]),
535 ntohs(daddr->s6_addr16[0]),
536 ntohs(daddr->s6_addr16[1]),
537 ntohs(daddr->s6_addr16[2]),
538 ntohs(daddr->s6_addr16[3]),
539 ntohs(daddr->s6_addr16[4]),
540 ntohs(daddr->s6_addr16[5]),
541 ntohs(daddr->s6_addr16[6]),
542 ntohs(daddr->s6_addr16[7]));
547 if (!pskb_pull(skb, sizeof(struct icmp6hdr)))
550 hdr = (struct icmp6hdr *) skb->h.raw;
552 type = hdr->icmp6_type;
554 if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB)
555 (&icmpv6_statistics[smp_processor_id()*2].Icmp6InDestUnreachs)[type-ICMPV6_DEST_UNREACH]++;
556 else if (type >= ICMPV6_ECHO_REQUEST && type <= NDISC_REDIRECT)
557 (&icmpv6_statistics[smp_processor_id()*2].Icmp6InEchos)[type-ICMPV6_ECHO_REQUEST]++;
560 case ICMPV6_ECHO_REQUEST:
561 icmpv6_echo_reply(skb);
564 case ICMPV6_ECHO_REPLY:
565 /* we coulnd't care less */
568 case ICMPV6_PKT_TOOBIG:
569 /* BUGGG_FUTURE: if packet contains rthdr, we cannot update
570 standard destination cache. Seems, only "advanced"
571 destination cache will allow to solve this problem
574 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
576 hdr = (struct icmp6hdr *) skb->h.raw;
577 orig_hdr = (struct ipv6hdr *) (hdr + 1);
578 rt6_pmtu_discovery(&orig_hdr->daddr, &orig_hdr->saddr, dev,
579 ntohl(hdr->icmp6_mtu));
582 * Drop through to notify
585 case ICMPV6_DEST_UNREACH:
586 case ICMPV6_TIME_EXCEED:
587 case ICMPV6_PARAMPROB:
588 icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu);
591 case NDISC_ROUTER_SOLICITATION:
592 case NDISC_ROUTER_ADVERTISEMENT:
593 case NDISC_NEIGHBOUR_SOLICITATION:
594 case NDISC_NEIGHBOUR_ADVERTISEMENT:
596 if (skb_is_nonlinear(skb) &&
597 skb_linearize(skb, GFP_ATOMIC) != 0) {
605 case ICMPV6_MGM_QUERY:
606 igmp6_event_query(skb);
609 case ICMPV6_MGM_REPORT:
610 igmp6_event_report(skb);
613 case ICMPV6_MGM_REDUCTION:
618 printk(KERN_DEBUG "icmpv6: msg of unkown type\n");
621 if (type & ICMPV6_INFOMSG_MASK)
625 * error of unkown type.
626 * must pass to upper level
629 icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu);
635 ICMP6_INC_STATS_BH(Icmp6InErrors);
640 int __init icmpv6_init(struct net_proto_family *ops)
645 icmpv6_socket = sock_alloc();
646 if (icmpv6_socket == NULL) {
648 "Failed to create the ICMP6 control socket.\n");
651 icmpv6_socket->inode->i_uid = 0;
652 icmpv6_socket->inode->i_gid = 0;
653 icmpv6_socket->type = SOCK_RAW;
655 if ((err = ops->create(icmpv6_socket, IPPROTO_ICMPV6)) < 0) {
657 "Failed to initialize the ICMP6 control socket (err %d).\n",
659 sock_release(icmpv6_socket);
660 icmpv6_socket = NULL; /* for safety */
664 sk = icmpv6_socket->sk;
665 sk->allocation = GFP_ATOMIC;
666 sk->sndbuf = SK_WMEM_MAX*2;
667 sk->prot->unhash(sk);
669 inet6_add_protocol(&icmpv6_protocol);
674 void icmpv6_cleanup(void)
676 sock_release(icmpv6_socket);
677 icmpv6_socket = NULL; /* For safety. */
678 inet6_del_protocol(&icmpv6_protocol);
681 static struct icmp6_err {
685 { ENETUNREACH, 0}, /* NOROUTE */
686 { EACCES, 1}, /* ADM_PROHIBITED */
687 { EHOSTUNREACH, 0}, /* Was NOT_NEIGHBOUR, now reserved */
688 { EHOSTUNREACH, 0}, /* ADDR_UNREACH */
689 { ECONNREFUSED, 1}, /* PORT_UNREACH */
692 int icmpv6_err_convert(int type, int code, int *err)
699 case ICMPV6_DEST_UNREACH:
701 if (code <= ICMPV6_PORT_UNREACH) {
702 *err = tab_unreach[code].err;
703 fatal = tab_unreach[code].fatal;
707 case ICMPV6_PKT_TOOBIG:
711 case ICMPV6_PARAMPROB:
716 case ICMPV6_TIME_EXCEED:
725 ctl_table ipv6_icmp_table[] = {
726 {NET_IPV6_ICMP_RATELIMIT, "ratelimit",
727 &sysctl_icmpv6_time, sizeof(int), 0644, NULL, &proc_dointvec},