11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * NET3: Implementation of the ICMP protocol layer. 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Alan Cox, <alan@redhat.com> 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * Version: $Id: icmp.c,v 1.85 2002/02/01 22:01:03 davem Exp $ 71da177e4SLinus Torvalds * 81da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or 91da177e4SLinus Torvalds * modify it under the terms of the GNU General Public License 101da177e4SLinus Torvalds * as published by the Free Software Foundation; either version 111da177e4SLinus Torvalds * 2 of the License, or (at your option) any later version. 121da177e4SLinus Torvalds * 131da177e4SLinus Torvalds * Some of the function names and the icmp unreach table for this 141da177e4SLinus Torvalds * module were derived from [icmp.c 1.0.11 06/02/93] by 151da177e4SLinus Torvalds * Ross Biro, Fred N. van Kempen, Mark Evans, Alan Cox, Gerhard Koerting. 161da177e4SLinus Torvalds * Other than that this module is a complete rewrite. 171da177e4SLinus Torvalds * 181da177e4SLinus Torvalds * Fixes: 191da177e4SLinus Torvalds * Clemens Fruhwirth : introduce global icmp rate limiting 201da177e4SLinus Torvalds * with icmp type masking ability instead 211da177e4SLinus Torvalds * of broken per type icmp timeouts. 221da177e4SLinus Torvalds * Mike Shaver : RFC1122 checks. 231da177e4SLinus Torvalds * Alan Cox : Multicast ping reply as self. 241da177e4SLinus Torvalds * Alan Cox : Fix atomicity lockup in ip_build_xmit 251da177e4SLinus Torvalds * call. 261da177e4SLinus Torvalds * Alan Cox : Added 216,128 byte paths to the MTU 271da177e4SLinus Torvalds * code. 281da177e4SLinus Torvalds * Martin Mares : RFC1812 checks. 291da177e4SLinus Torvalds * Martin Mares : Can be configured to follow redirects 301da177e4SLinus Torvalds * if acting as a router _without_ a 311da177e4SLinus Torvalds * routing protocol (RFC 1812). 321da177e4SLinus Torvalds * Martin Mares : Echo requests may be configured to 331da177e4SLinus Torvalds * be ignored (RFC 1812). 341da177e4SLinus Torvalds * Martin Mares : Limitation of ICMP error message 351da177e4SLinus Torvalds * transmit rate (RFC 1812). 361da177e4SLinus Torvalds * Martin Mares : TOS and Precedence set correctly 371da177e4SLinus Torvalds * (RFC 1812). 381da177e4SLinus Torvalds * Martin Mares : Now copying as much data from the 391da177e4SLinus Torvalds * original packet as we can without 401da177e4SLinus Torvalds * exceeding 576 bytes (RFC 1812). 411da177e4SLinus Torvalds * Willy Konynenberg : Transparent proxying support. 421da177e4SLinus Torvalds * Keith Owens : RFC1191 correction for 4.2BSD based 431da177e4SLinus Torvalds * path MTU bug. 441da177e4SLinus Torvalds * Thomas Quinot : ICMP Dest Unreach codes up to 15 are 451da177e4SLinus Torvalds * valid (RFC 1812). 461da177e4SLinus Torvalds * Andi Kleen : Check all packet lengths properly 471da177e4SLinus Torvalds * and moved all kfree_skb() up to 481da177e4SLinus Torvalds * icmp_rcv. 491da177e4SLinus Torvalds * Andi Kleen : Move the rate limit bookkeeping 501da177e4SLinus Torvalds * into the dest entry and use a token 511da177e4SLinus Torvalds * bucket filter (thanks to ANK). Make 521da177e4SLinus Torvalds * the rates sysctl configurable. 531da177e4SLinus Torvalds * Yu Tianli : Fixed two ugly bugs in icmp_send 541da177e4SLinus Torvalds * - IP option length was accounted wrongly 551da177e4SLinus Torvalds * - ICMP header length was not accounted 561da177e4SLinus Torvalds * at all. 571da177e4SLinus Torvalds * Tristan Greaves : Added sysctl option to ignore bogus 581da177e4SLinus Torvalds * broadcast responses from broken routers. 591da177e4SLinus Torvalds * 601da177e4SLinus Torvalds * To Fix: 611da177e4SLinus Torvalds * 621da177e4SLinus Torvalds * - Should use skb_pull() instead of all the manual checking. 631da177e4SLinus Torvalds * This would also greatly simply some upper layer error handlers. --AK 641da177e4SLinus Torvalds * 651da177e4SLinus Torvalds */ 661da177e4SLinus Torvalds 671da177e4SLinus Torvalds #include <linux/module.h> 681da177e4SLinus Torvalds #include <linux/types.h> 691da177e4SLinus Torvalds #include <linux/jiffies.h> 701da177e4SLinus Torvalds #include <linux/kernel.h> 711da177e4SLinus Torvalds #include <linux/fcntl.h> 721da177e4SLinus Torvalds #include <linux/socket.h> 731da177e4SLinus Torvalds #include <linux/in.h> 741da177e4SLinus Torvalds #include <linux/inet.h> 7514c85021SArnaldo Carvalho de Melo #include <linux/inetdevice.h> 761da177e4SLinus Torvalds #include <linux/netdevice.h> 771da177e4SLinus Torvalds #include <linux/string.h> 781da177e4SLinus Torvalds #include <linux/netfilter_ipv4.h> 791da177e4SLinus Torvalds #include <net/snmp.h> 801da177e4SLinus Torvalds #include <net/ip.h> 811da177e4SLinus Torvalds #include <net/route.h> 821da177e4SLinus Torvalds #include <net/protocol.h> 831da177e4SLinus Torvalds #include <net/icmp.h> 841da177e4SLinus Torvalds #include <net/tcp.h> 851da177e4SLinus Torvalds #include <net/udp.h> 861da177e4SLinus Torvalds #include <net/raw.h> 871da177e4SLinus Torvalds #include <linux/skbuff.h> 881da177e4SLinus Torvalds #include <net/sock.h> 891da177e4SLinus Torvalds #include <linux/errno.h> 901da177e4SLinus Torvalds #include <linux/timer.h> 911da177e4SLinus Torvalds #include <linux/init.h> 921da177e4SLinus Torvalds #include <asm/system.h> 931da177e4SLinus Torvalds #include <asm/uaccess.h> 941da177e4SLinus Torvalds #include <net/checksum.h> 951da177e4SLinus Torvalds 961da177e4SLinus Torvalds /* 971da177e4SLinus Torvalds * Build xmit assembly blocks 981da177e4SLinus Torvalds */ 991da177e4SLinus Torvalds 1001da177e4SLinus Torvalds struct icmp_bxm { 1011da177e4SLinus Torvalds struct sk_buff *skb; 1021da177e4SLinus Torvalds int offset; 1031da177e4SLinus Torvalds int data_len; 1041da177e4SLinus Torvalds 1051da177e4SLinus Torvalds struct { 1061da177e4SLinus Torvalds struct icmphdr icmph; 107b03d73e3SAl Viro __be32 times[3]; 1081da177e4SLinus Torvalds } data; 1091da177e4SLinus Torvalds int head_len; 1101da177e4SLinus Torvalds struct ip_options replyopts; 1111da177e4SLinus Torvalds unsigned char optbuf[40]; 1121da177e4SLinus Torvalds }; 1131da177e4SLinus Torvalds 1141da177e4SLinus Torvalds /* 1151da177e4SLinus Torvalds * Statistics 1161da177e4SLinus Torvalds */ 117ba89966cSEric Dumazet DEFINE_SNMP_STAT(struct icmp_mib, icmp_statistics) __read_mostly; 1181da177e4SLinus Torvalds 1191da177e4SLinus Torvalds /* An array of errno for error messages from dest unreach. */ 1201da177e4SLinus Torvalds /* RFC 1122: 3.2.2.1 States that NET_UNREACH, HOST_UNREACH and SR_FAILED MUST be considered 'transient errs'. */ 1211da177e4SLinus Torvalds 1221da177e4SLinus Torvalds struct icmp_err icmp_err_convert[] = { 1231da177e4SLinus Torvalds { 1241da177e4SLinus Torvalds .errno = ENETUNREACH, /* ICMP_NET_UNREACH */ 1251da177e4SLinus Torvalds .fatal = 0, 1261da177e4SLinus Torvalds }, 1271da177e4SLinus Torvalds { 1281da177e4SLinus Torvalds .errno = EHOSTUNREACH, /* ICMP_HOST_UNREACH */ 1291da177e4SLinus Torvalds .fatal = 0, 1301da177e4SLinus Torvalds }, 1311da177e4SLinus Torvalds { 1321da177e4SLinus Torvalds .errno = ENOPROTOOPT /* ICMP_PROT_UNREACH */, 1331da177e4SLinus Torvalds .fatal = 1, 1341da177e4SLinus Torvalds }, 1351da177e4SLinus Torvalds { 1361da177e4SLinus Torvalds .errno = ECONNREFUSED, /* ICMP_PORT_UNREACH */ 1371da177e4SLinus Torvalds .fatal = 1, 1381da177e4SLinus Torvalds }, 1391da177e4SLinus Torvalds { 1401da177e4SLinus Torvalds .errno = EMSGSIZE, /* ICMP_FRAG_NEEDED */ 1411da177e4SLinus Torvalds .fatal = 0, 1421da177e4SLinus Torvalds }, 1431da177e4SLinus Torvalds { 1441da177e4SLinus Torvalds .errno = EOPNOTSUPP, /* ICMP_SR_FAILED */ 1451da177e4SLinus Torvalds .fatal = 0, 1461da177e4SLinus Torvalds }, 1471da177e4SLinus Torvalds { 1481da177e4SLinus Torvalds .errno = ENETUNREACH, /* ICMP_NET_UNKNOWN */ 1491da177e4SLinus Torvalds .fatal = 1, 1501da177e4SLinus Torvalds }, 1511da177e4SLinus Torvalds { 1521da177e4SLinus Torvalds .errno = EHOSTDOWN, /* ICMP_HOST_UNKNOWN */ 1531da177e4SLinus Torvalds .fatal = 1, 1541da177e4SLinus Torvalds }, 1551da177e4SLinus Torvalds { 1561da177e4SLinus Torvalds .errno = ENONET, /* ICMP_HOST_ISOLATED */ 1571da177e4SLinus Torvalds .fatal = 1, 1581da177e4SLinus Torvalds }, 1591da177e4SLinus Torvalds { 1601da177e4SLinus Torvalds .errno = ENETUNREACH, /* ICMP_NET_ANO */ 1611da177e4SLinus Torvalds .fatal = 1, 1621da177e4SLinus Torvalds }, 1631da177e4SLinus Torvalds { 1641da177e4SLinus Torvalds .errno = EHOSTUNREACH, /* ICMP_HOST_ANO */ 1651da177e4SLinus Torvalds .fatal = 1, 1661da177e4SLinus Torvalds }, 1671da177e4SLinus Torvalds { 1681da177e4SLinus Torvalds .errno = ENETUNREACH, /* ICMP_NET_UNR_TOS */ 1691da177e4SLinus Torvalds .fatal = 0, 1701da177e4SLinus Torvalds }, 1711da177e4SLinus Torvalds { 1721da177e4SLinus Torvalds .errno = EHOSTUNREACH, /* ICMP_HOST_UNR_TOS */ 1731da177e4SLinus Torvalds .fatal = 0, 1741da177e4SLinus Torvalds }, 1751da177e4SLinus Torvalds { 1761da177e4SLinus Torvalds .errno = EHOSTUNREACH, /* ICMP_PKT_FILTERED */ 1771da177e4SLinus Torvalds .fatal = 1, 1781da177e4SLinus Torvalds }, 1791da177e4SLinus Torvalds { 1801da177e4SLinus Torvalds .errno = EHOSTUNREACH, /* ICMP_PREC_VIOLATION */ 1811da177e4SLinus Torvalds .fatal = 1, 1821da177e4SLinus Torvalds }, 1831da177e4SLinus Torvalds { 1841da177e4SLinus Torvalds .errno = EHOSTUNREACH, /* ICMP_PREC_CUTOFF */ 1851da177e4SLinus Torvalds .fatal = 1, 1861da177e4SLinus Torvalds }, 1871da177e4SLinus Torvalds }; 1881da177e4SLinus Torvalds 1891da177e4SLinus Torvalds /* Control parameters for ECHO replies. */ 190ab32ea5dSBrian Haley int sysctl_icmp_echo_ignore_all __read_mostly; 191ab32ea5dSBrian Haley int sysctl_icmp_echo_ignore_broadcasts __read_mostly = 1; 1921da177e4SLinus Torvalds 1931da177e4SLinus Torvalds /* Control parameter - ignore bogus broadcast responses? */ 194ab32ea5dSBrian Haley int sysctl_icmp_ignore_bogus_error_responses __read_mostly = 1; 1951da177e4SLinus Torvalds 1961da177e4SLinus Torvalds /* 1971da177e4SLinus Torvalds * Configurable global rate limit. 1981da177e4SLinus Torvalds * 1991da177e4SLinus Torvalds * ratelimit defines tokens/packet consumed for dst->rate_token bucket 2001da177e4SLinus Torvalds * ratemask defines which icmp types are ratelimited by setting 2011da177e4SLinus Torvalds * it's bit position. 2021da177e4SLinus Torvalds * 2031da177e4SLinus Torvalds * default: 2041da177e4SLinus Torvalds * dest unreachable (3), source quench (4), 2051da177e4SLinus Torvalds * time exceeded (11), parameter problem (12) 2061da177e4SLinus Torvalds */ 2071da177e4SLinus Torvalds 208ab32ea5dSBrian Haley int sysctl_icmp_ratelimit __read_mostly = 1 * HZ; 209ab32ea5dSBrian Haley int sysctl_icmp_ratemask __read_mostly = 0x1818; 210ab32ea5dSBrian Haley int sysctl_icmp_errors_use_inbound_ifaddr __read_mostly; 2111da177e4SLinus Torvalds 2121da177e4SLinus Torvalds /* 2131da177e4SLinus Torvalds * ICMP control array. This specifies what to do with each ICMP. 2141da177e4SLinus Torvalds */ 2151da177e4SLinus Torvalds 2161da177e4SLinus Torvalds struct icmp_control { 2171da177e4SLinus Torvalds int output_entry; /* Field for increment on output */ 2181da177e4SLinus Torvalds int input_entry; /* Field for increment on input */ 2191da177e4SLinus Torvalds void (*handler)(struct sk_buff *skb); 2201da177e4SLinus Torvalds short error; /* This ICMP is classed as an error message */ 2211da177e4SLinus Torvalds }; 2221da177e4SLinus Torvalds 2239b5b5cffSArjan van de Ven static const struct icmp_control icmp_pointers[NR_ICMP_TYPES+1]; 2241da177e4SLinus Torvalds 2251da177e4SLinus Torvalds /* 2261da177e4SLinus Torvalds * The ICMP socket(s). This is the most convenient way to flow control 2271da177e4SLinus Torvalds * our ICMP output as well as maintain a clean interface throughout 2281da177e4SLinus Torvalds * all layers. All Socketless IP sends will soon be gone. 2291da177e4SLinus Torvalds * 2301da177e4SLinus Torvalds * On SMP we have one ICMP socket per-cpu. 2311da177e4SLinus Torvalds */ 2321da177e4SLinus Torvalds static DEFINE_PER_CPU(struct socket *, __icmp_socket) = NULL; 2331da177e4SLinus Torvalds #define icmp_socket __get_cpu_var(__icmp_socket) 2341da177e4SLinus Torvalds 2351da177e4SLinus Torvalds static __inline__ int icmp_xmit_lock(void) 2361da177e4SLinus Torvalds { 2371da177e4SLinus Torvalds local_bh_disable(); 2381da177e4SLinus Torvalds 2391da177e4SLinus Torvalds if (unlikely(!spin_trylock(&icmp_socket->sk->sk_lock.slock))) { 2401da177e4SLinus Torvalds /* This can happen if the output path signals a 2411da177e4SLinus Torvalds * dst_link_failure() for an outgoing ICMP packet. 2421da177e4SLinus Torvalds */ 2431da177e4SLinus Torvalds local_bh_enable(); 2441da177e4SLinus Torvalds return 1; 2451da177e4SLinus Torvalds } 2461da177e4SLinus Torvalds return 0; 2471da177e4SLinus Torvalds } 2481da177e4SLinus Torvalds 2491da177e4SLinus Torvalds static void icmp_xmit_unlock(void) 2501da177e4SLinus Torvalds { 2511da177e4SLinus Torvalds spin_unlock_bh(&icmp_socket->sk->sk_lock.slock); 2521da177e4SLinus Torvalds } 2531da177e4SLinus Torvalds 2541da177e4SLinus Torvalds /* 2551da177e4SLinus Torvalds * Send an ICMP frame. 2561da177e4SLinus Torvalds */ 2571da177e4SLinus Torvalds 2581da177e4SLinus Torvalds /* 2591da177e4SLinus Torvalds * Check transmit rate limitation for given message. 2601da177e4SLinus Torvalds * The rate information is held in the destination cache now. 2611da177e4SLinus Torvalds * This function is generic and could be used for other purposes 2621da177e4SLinus Torvalds * too. It uses a Token bucket filter as suggested by Alexey Kuznetsov. 2631da177e4SLinus Torvalds * 2641da177e4SLinus Torvalds * Note that the same dst_entry fields are modified by functions in 2651da177e4SLinus Torvalds * route.c too, but these work for packet destinations while xrlim_allow 2661da177e4SLinus Torvalds * works for icmp destinations. This means the rate limiting information 2671da177e4SLinus Torvalds * for one "ip object" is shared - and these ICMPs are twice limited: 2681da177e4SLinus Torvalds * by source and by destination. 2691da177e4SLinus Torvalds * 2701da177e4SLinus Torvalds * RFC 1812: 4.3.2.8 SHOULD be able to limit error message rate 2711da177e4SLinus Torvalds * SHOULD allow setting of rate limits 2721da177e4SLinus Torvalds * 2731da177e4SLinus Torvalds * Shared between ICMPv4 and ICMPv6. 2741da177e4SLinus Torvalds */ 2751da177e4SLinus Torvalds #define XRLIM_BURST_FACTOR 6 2761da177e4SLinus Torvalds int xrlim_allow(struct dst_entry *dst, int timeout) 2771da177e4SLinus Torvalds { 2781da177e4SLinus Torvalds unsigned long now; 2791da177e4SLinus Torvalds int rc = 0; 2801da177e4SLinus Torvalds 2811da177e4SLinus Torvalds now = jiffies; 2821da177e4SLinus Torvalds dst->rate_tokens += now - dst->rate_last; 2831da177e4SLinus Torvalds dst->rate_last = now; 2841da177e4SLinus Torvalds if (dst->rate_tokens > XRLIM_BURST_FACTOR * timeout) 2851da177e4SLinus Torvalds dst->rate_tokens = XRLIM_BURST_FACTOR * timeout; 2861da177e4SLinus Torvalds if (dst->rate_tokens >= timeout) { 2871da177e4SLinus Torvalds dst->rate_tokens -= timeout; 2881da177e4SLinus Torvalds rc = 1; 2891da177e4SLinus Torvalds } 2901da177e4SLinus Torvalds return rc; 2911da177e4SLinus Torvalds } 2921da177e4SLinus Torvalds 2931da177e4SLinus Torvalds static inline int icmpv4_xrlim_allow(struct rtable *rt, int type, int code) 2941da177e4SLinus Torvalds { 2951da177e4SLinus Torvalds struct dst_entry *dst = &rt->u.dst; 2961da177e4SLinus Torvalds int rc = 1; 2971da177e4SLinus Torvalds 2981da177e4SLinus Torvalds if (type > NR_ICMP_TYPES) 2991da177e4SLinus Torvalds goto out; 3001da177e4SLinus Torvalds 3011da177e4SLinus Torvalds /* Don't limit PMTU discovery. */ 3021da177e4SLinus Torvalds if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) 3031da177e4SLinus Torvalds goto out; 3041da177e4SLinus Torvalds 3051da177e4SLinus Torvalds /* No rate limit on loopback */ 3061da177e4SLinus Torvalds if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) 3071da177e4SLinus Torvalds goto out; 3081da177e4SLinus Torvalds 3091da177e4SLinus Torvalds /* Limit if icmp type is enabled in ratemask. */ 3101da177e4SLinus Torvalds if ((1 << type) & sysctl_icmp_ratemask) 3111da177e4SLinus Torvalds rc = xrlim_allow(dst, sysctl_icmp_ratelimit); 3121da177e4SLinus Torvalds out: 3131da177e4SLinus Torvalds return rc; 3141da177e4SLinus Torvalds } 3151da177e4SLinus Torvalds 3161da177e4SLinus Torvalds /* 3171da177e4SLinus Torvalds * Maintain the counters used in the SNMP statistics for outgoing ICMP 3181da177e4SLinus Torvalds */ 3191da177e4SLinus Torvalds static void icmp_out_count(int type) 3201da177e4SLinus Torvalds { 3211da177e4SLinus Torvalds if (type <= NR_ICMP_TYPES) { 3221da177e4SLinus Torvalds ICMP_INC_STATS(icmp_pointers[type].output_entry); 3231da177e4SLinus Torvalds ICMP_INC_STATS(ICMP_MIB_OUTMSGS); 3241da177e4SLinus Torvalds } 3251da177e4SLinus Torvalds } 3261da177e4SLinus Torvalds 3271da177e4SLinus Torvalds /* 3281da177e4SLinus Torvalds * Checksum each fragment, and on the first include the headers and final 3291da177e4SLinus Torvalds * checksum. 3301da177e4SLinus Torvalds */ 3311da177e4SLinus Torvalds static int icmp_glue_bits(void *from, char *to, int offset, int len, int odd, 3321da177e4SLinus Torvalds struct sk_buff *skb) 3331da177e4SLinus Torvalds { 3341da177e4SLinus Torvalds struct icmp_bxm *icmp_param = (struct icmp_bxm *)from; 335*5f92a738SAl Viro __wsum csum; 3361da177e4SLinus Torvalds 3371da177e4SLinus Torvalds csum = skb_copy_and_csum_bits(icmp_param->skb, 3381da177e4SLinus Torvalds icmp_param->offset + offset, 3391da177e4SLinus Torvalds to, len, 0); 3401da177e4SLinus Torvalds 3411da177e4SLinus Torvalds skb->csum = csum_block_add(skb->csum, csum, odd); 3421da177e4SLinus Torvalds if (icmp_pointers[icmp_param->data.icmph.type].error) 3431da177e4SLinus Torvalds nf_ct_attach(skb, icmp_param->skb); 3441da177e4SLinus Torvalds return 0; 3451da177e4SLinus Torvalds } 3461da177e4SLinus Torvalds 3471da177e4SLinus Torvalds static void icmp_push_reply(struct icmp_bxm *icmp_param, 3481da177e4SLinus Torvalds struct ipcm_cookie *ipc, struct rtable *rt) 3491da177e4SLinus Torvalds { 3501da177e4SLinus Torvalds struct sk_buff *skb; 3511da177e4SLinus Torvalds 352cb94c62cSPatrick McHardy if (ip_append_data(icmp_socket->sk, icmp_glue_bits, icmp_param, 3531da177e4SLinus Torvalds icmp_param->data_len+icmp_param->head_len, 3541da177e4SLinus Torvalds icmp_param->head_len, 355cb94c62cSPatrick McHardy ipc, rt, MSG_DONTWAIT) < 0) 356cb94c62cSPatrick McHardy ip_flush_pending_frames(icmp_socket->sk); 357cb94c62cSPatrick McHardy else if ((skb = skb_peek(&icmp_socket->sk->sk_write_queue)) != NULL) { 3581da177e4SLinus Torvalds struct icmphdr *icmph = skb->h.icmph; 359d3bc23e7SAl Viro __wsum csum = 0; 3601da177e4SLinus Torvalds struct sk_buff *skb1; 3611da177e4SLinus Torvalds 3621da177e4SLinus Torvalds skb_queue_walk(&icmp_socket->sk->sk_write_queue, skb1) { 3631da177e4SLinus Torvalds csum = csum_add(csum, skb1->csum); 3641da177e4SLinus Torvalds } 3651da177e4SLinus Torvalds csum = csum_partial_copy_nocheck((void *)&icmp_param->data, 3661da177e4SLinus Torvalds (char *)icmph, 3671da177e4SLinus Torvalds icmp_param->head_len, csum); 3681da177e4SLinus Torvalds icmph->checksum = csum_fold(csum); 3691da177e4SLinus Torvalds skb->ip_summed = CHECKSUM_NONE; 3701da177e4SLinus Torvalds ip_push_pending_frames(icmp_socket->sk); 3711da177e4SLinus Torvalds } 3721da177e4SLinus Torvalds } 3731da177e4SLinus Torvalds 3741da177e4SLinus Torvalds /* 3751da177e4SLinus Torvalds * Driving logic for building and sending ICMP messages. 3761da177e4SLinus Torvalds */ 3771da177e4SLinus Torvalds 3781da177e4SLinus Torvalds static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) 3791da177e4SLinus Torvalds { 3801da177e4SLinus Torvalds struct sock *sk = icmp_socket->sk; 3811da177e4SLinus Torvalds struct inet_sock *inet = inet_sk(sk); 3821da177e4SLinus Torvalds struct ipcm_cookie ipc; 3831da177e4SLinus Torvalds struct rtable *rt = (struct rtable *)skb->dst; 3843ca3c68eSAl Viro __be32 daddr; 3851da177e4SLinus Torvalds 3861da177e4SLinus Torvalds if (ip_options_echo(&icmp_param->replyopts, skb)) 387f00c401bSHorms return; 3881da177e4SLinus Torvalds 3891da177e4SLinus Torvalds if (icmp_xmit_lock()) 3901da177e4SLinus Torvalds return; 3911da177e4SLinus Torvalds 3921da177e4SLinus Torvalds icmp_param->data.icmph.checksum = 0; 3931da177e4SLinus Torvalds icmp_out_count(icmp_param->data.icmph.type); 3941da177e4SLinus Torvalds 3951da177e4SLinus Torvalds inet->tos = skb->nh.iph->tos; 3961da177e4SLinus Torvalds daddr = ipc.addr = rt->rt_src; 3971da177e4SLinus Torvalds ipc.opt = NULL; 3981da177e4SLinus Torvalds if (icmp_param->replyopts.optlen) { 3991da177e4SLinus Torvalds ipc.opt = &icmp_param->replyopts; 4001da177e4SLinus Torvalds if (ipc.opt->srr) 4011da177e4SLinus Torvalds daddr = icmp_param->replyopts.faddr; 4021da177e4SLinus Torvalds } 4031da177e4SLinus Torvalds { 4041da177e4SLinus Torvalds struct flowi fl = { .nl_u = { .ip4_u = 4051da177e4SLinus Torvalds { .daddr = daddr, 4061da177e4SLinus Torvalds .saddr = rt->rt_spec_dst, 4071da177e4SLinus Torvalds .tos = RT_TOS(skb->nh.iph->tos) } }, 4081da177e4SLinus Torvalds .proto = IPPROTO_ICMP }; 409beb8d13bSVenkat Yekkirala security_skb_classify_flow(skb, &fl); 4101da177e4SLinus Torvalds if (ip_route_output_key(&rt, &fl)) 4111da177e4SLinus Torvalds goto out_unlock; 4121da177e4SLinus Torvalds } 4131da177e4SLinus Torvalds if (icmpv4_xrlim_allow(rt, icmp_param->data.icmph.type, 4141da177e4SLinus Torvalds icmp_param->data.icmph.code)) 4151da177e4SLinus Torvalds icmp_push_reply(icmp_param, &ipc, rt); 4161da177e4SLinus Torvalds ip_rt_put(rt); 4171da177e4SLinus Torvalds out_unlock: 4181da177e4SLinus Torvalds icmp_xmit_unlock(); 4191da177e4SLinus Torvalds } 4201da177e4SLinus Torvalds 4211da177e4SLinus Torvalds 4221da177e4SLinus Torvalds /* 4231da177e4SLinus Torvalds * Send an ICMP message in response to a situation 4241da177e4SLinus Torvalds * 4251da177e4SLinus Torvalds * RFC 1122: 3.2.2 MUST send at least the IP header and 8 bytes of header. 4261da177e4SLinus Torvalds * MAY send more (we do). 4271da177e4SLinus Torvalds * MUST NOT change this header information. 4281da177e4SLinus Torvalds * MUST NOT reply to a multicast/broadcast IP address. 4291da177e4SLinus Torvalds * MUST NOT reply to a multicast/broadcast MAC address. 4301da177e4SLinus Torvalds * MUST reply to only the first fragment. 4311da177e4SLinus Torvalds */ 4321da177e4SLinus Torvalds 433e4883014SAl Viro void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) 4341da177e4SLinus Torvalds { 4351da177e4SLinus Torvalds struct iphdr *iph; 4361da177e4SLinus Torvalds int room; 4371da177e4SLinus Torvalds struct icmp_bxm icmp_param; 4381da177e4SLinus Torvalds struct rtable *rt = (struct rtable *)skb_in->dst; 4391da177e4SLinus Torvalds struct ipcm_cookie ipc; 440a61ced5dSAl Viro __be32 saddr; 4411da177e4SLinus Torvalds u8 tos; 4421da177e4SLinus Torvalds 4431da177e4SLinus Torvalds if (!rt) 4441da177e4SLinus Torvalds goto out; 4451da177e4SLinus Torvalds 4461da177e4SLinus Torvalds /* 4471da177e4SLinus Torvalds * Find the original header. It is expected to be valid, of course. 4481da177e4SLinus Torvalds * Check this, icmp_send is called from the most obscure devices 4491da177e4SLinus Torvalds * sometimes. 4501da177e4SLinus Torvalds */ 4511da177e4SLinus Torvalds iph = skb_in->nh.iph; 4521da177e4SLinus Torvalds 4531da177e4SLinus Torvalds if ((u8 *)iph < skb_in->head || (u8 *)(iph + 1) > skb_in->tail) 4541da177e4SLinus Torvalds goto out; 4551da177e4SLinus Torvalds 4561da177e4SLinus Torvalds /* 4571da177e4SLinus Torvalds * No replies to physical multicast/broadcast 4581da177e4SLinus Torvalds */ 4591da177e4SLinus Torvalds if (skb_in->pkt_type != PACKET_HOST) 4601da177e4SLinus Torvalds goto out; 4611da177e4SLinus Torvalds 4621da177e4SLinus Torvalds /* 4631da177e4SLinus Torvalds * Now check at the protocol level 4641da177e4SLinus Torvalds */ 4651da177e4SLinus Torvalds if (rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) 4661da177e4SLinus Torvalds goto out; 4671da177e4SLinus Torvalds 4681da177e4SLinus Torvalds /* 4691da177e4SLinus Torvalds * Only reply to fragment 0. We byte re-order the constant 4701da177e4SLinus Torvalds * mask for efficiency. 4711da177e4SLinus Torvalds */ 4721da177e4SLinus Torvalds if (iph->frag_off & htons(IP_OFFSET)) 4731da177e4SLinus Torvalds goto out; 4741da177e4SLinus Torvalds 4751da177e4SLinus Torvalds /* 4761da177e4SLinus Torvalds * If we send an ICMP error to an ICMP error a mess would result.. 4771da177e4SLinus Torvalds */ 4781da177e4SLinus Torvalds if (icmp_pointers[type].error) { 4791da177e4SLinus Torvalds /* 4801da177e4SLinus Torvalds * We are an error, check if we are replying to an 4811da177e4SLinus Torvalds * ICMP error 4821da177e4SLinus Torvalds */ 4831da177e4SLinus Torvalds if (iph->protocol == IPPROTO_ICMP) { 4841da177e4SLinus Torvalds u8 _inner_type, *itp; 4851da177e4SLinus Torvalds 4861da177e4SLinus Torvalds itp = skb_header_pointer(skb_in, 4871da177e4SLinus Torvalds skb_in->nh.raw + 4881da177e4SLinus Torvalds (iph->ihl << 2) + 4891da177e4SLinus Torvalds offsetof(struct icmphdr, 4901da177e4SLinus Torvalds type) - 4911da177e4SLinus Torvalds skb_in->data, 4921da177e4SLinus Torvalds sizeof(_inner_type), 4931da177e4SLinus Torvalds &_inner_type); 4941da177e4SLinus Torvalds if (itp == NULL) 4951da177e4SLinus Torvalds goto out; 4961da177e4SLinus Torvalds 4971da177e4SLinus Torvalds /* 4981da177e4SLinus Torvalds * Assume any unknown ICMP type is an error. This 4991da177e4SLinus Torvalds * isn't specified by the RFC, but think about it.. 5001da177e4SLinus Torvalds */ 5011da177e4SLinus Torvalds if (*itp > NR_ICMP_TYPES || 5021da177e4SLinus Torvalds icmp_pointers[*itp].error) 5031da177e4SLinus Torvalds goto out; 5041da177e4SLinus Torvalds } 5051da177e4SLinus Torvalds } 5061da177e4SLinus Torvalds 5071da177e4SLinus Torvalds if (icmp_xmit_lock()) 5081da177e4SLinus Torvalds return; 5091da177e4SLinus Torvalds 5101da177e4SLinus Torvalds /* 5111da177e4SLinus Torvalds * Construct source address and options. 5121da177e4SLinus Torvalds */ 5131da177e4SLinus Torvalds 5141da177e4SLinus Torvalds saddr = iph->daddr; 5151c2fb7f9SJ. Simonetti if (!(rt->rt_flags & RTCF_LOCAL)) { 5161c2fb7f9SJ. Simonetti if (sysctl_icmp_errors_use_inbound_ifaddr) 5171c2fb7f9SJ. Simonetti saddr = inet_select_addr(skb_in->dev, 0, RT_SCOPE_LINK); 5181c2fb7f9SJ. Simonetti else 5191da177e4SLinus Torvalds saddr = 0; 5201c2fb7f9SJ. Simonetti } 5211da177e4SLinus Torvalds 5221da177e4SLinus Torvalds tos = icmp_pointers[type].error ? ((iph->tos & IPTOS_TOS_MASK) | 5231da177e4SLinus Torvalds IPTOS_PREC_INTERNETCONTROL) : 5241da177e4SLinus Torvalds iph->tos; 5251da177e4SLinus Torvalds 5261da177e4SLinus Torvalds if (ip_options_echo(&icmp_param.replyopts, skb_in)) 527fa60cf7fSHerbert Xu goto out_unlock; 5281da177e4SLinus Torvalds 5291da177e4SLinus Torvalds 5301da177e4SLinus Torvalds /* 5311da177e4SLinus Torvalds * Prepare data for ICMP header. 5321da177e4SLinus Torvalds */ 5331da177e4SLinus Torvalds 5341da177e4SLinus Torvalds icmp_param.data.icmph.type = type; 5351da177e4SLinus Torvalds icmp_param.data.icmph.code = code; 5361da177e4SLinus Torvalds icmp_param.data.icmph.un.gateway = info; 5371da177e4SLinus Torvalds icmp_param.data.icmph.checksum = 0; 5381da177e4SLinus Torvalds icmp_param.skb = skb_in; 5391da177e4SLinus Torvalds icmp_param.offset = skb_in->nh.raw - skb_in->data; 5401da177e4SLinus Torvalds icmp_out_count(icmp_param.data.icmph.type); 5411da177e4SLinus Torvalds inet_sk(icmp_socket->sk)->tos = tos; 5421da177e4SLinus Torvalds ipc.addr = iph->saddr; 5431da177e4SLinus Torvalds ipc.opt = &icmp_param.replyopts; 5441da177e4SLinus Torvalds 5451da177e4SLinus Torvalds { 5461da177e4SLinus Torvalds struct flowi fl = { 5471da177e4SLinus Torvalds .nl_u = { 5481da177e4SLinus Torvalds .ip4_u = { 5491da177e4SLinus Torvalds .daddr = icmp_param.replyopts.srr ? 5501da177e4SLinus Torvalds icmp_param.replyopts.faddr : 5511da177e4SLinus Torvalds iph->saddr, 5521da177e4SLinus Torvalds .saddr = saddr, 5531da177e4SLinus Torvalds .tos = RT_TOS(tos) 5541da177e4SLinus Torvalds } 5551da177e4SLinus Torvalds }, 5561da177e4SLinus Torvalds .proto = IPPROTO_ICMP, 5571da177e4SLinus Torvalds .uli_u = { 5581da177e4SLinus Torvalds .icmpt = { 5591da177e4SLinus Torvalds .type = type, 5601da177e4SLinus Torvalds .code = code 5611da177e4SLinus Torvalds } 5621da177e4SLinus Torvalds } 5631da177e4SLinus Torvalds }; 564beb8d13bSVenkat Yekkirala security_skb_classify_flow(skb_in, &fl); 5651da177e4SLinus Torvalds if (ip_route_output_key(&rt, &fl)) 5661da177e4SLinus Torvalds goto out_unlock; 5671da177e4SLinus Torvalds } 5681da177e4SLinus Torvalds 5691da177e4SLinus Torvalds if (!icmpv4_xrlim_allow(rt, type, code)) 5701da177e4SLinus Torvalds goto ende; 5711da177e4SLinus Torvalds 5721da177e4SLinus Torvalds /* RFC says return as much as we can without exceeding 576 bytes. */ 5731da177e4SLinus Torvalds 5741da177e4SLinus Torvalds room = dst_mtu(&rt->u.dst); 5751da177e4SLinus Torvalds if (room > 576) 5761da177e4SLinus Torvalds room = 576; 5771da177e4SLinus Torvalds room -= sizeof(struct iphdr) + icmp_param.replyopts.optlen; 5781da177e4SLinus Torvalds room -= sizeof(struct icmphdr); 5791da177e4SLinus Torvalds 5801da177e4SLinus Torvalds icmp_param.data_len = skb_in->len - icmp_param.offset; 5811da177e4SLinus Torvalds if (icmp_param.data_len > room) 5821da177e4SLinus Torvalds icmp_param.data_len = room; 5831da177e4SLinus Torvalds icmp_param.head_len = sizeof(struct icmphdr); 5841da177e4SLinus Torvalds 5851da177e4SLinus Torvalds icmp_push_reply(&icmp_param, &ipc, rt); 5861da177e4SLinus Torvalds ende: 5871da177e4SLinus Torvalds ip_rt_put(rt); 5881da177e4SLinus Torvalds out_unlock: 5891da177e4SLinus Torvalds icmp_xmit_unlock(); 5901da177e4SLinus Torvalds out:; 5911da177e4SLinus Torvalds } 5921da177e4SLinus Torvalds 5931da177e4SLinus Torvalds 5941da177e4SLinus Torvalds /* 5951da177e4SLinus Torvalds * Handle ICMP_DEST_UNREACH, ICMP_TIME_EXCEED, and ICMP_QUENCH. 5961da177e4SLinus Torvalds */ 5971da177e4SLinus Torvalds 5981da177e4SLinus Torvalds static void icmp_unreach(struct sk_buff *skb) 5991da177e4SLinus Torvalds { 6001da177e4SLinus Torvalds struct iphdr *iph; 6011da177e4SLinus Torvalds struct icmphdr *icmph; 6021da177e4SLinus Torvalds int hash, protocol; 6031da177e4SLinus Torvalds struct net_protocol *ipprot; 6041da177e4SLinus Torvalds struct sock *raw_sk; 6051da177e4SLinus Torvalds u32 info = 0; 6061da177e4SLinus Torvalds 6071da177e4SLinus Torvalds /* 6081da177e4SLinus Torvalds * Incomplete header ? 6091da177e4SLinus Torvalds * Only checks for the IP header, there should be an 6101da177e4SLinus Torvalds * additional check for longer headers in upper levels. 6111da177e4SLinus Torvalds */ 6121da177e4SLinus Torvalds 6131da177e4SLinus Torvalds if (!pskb_may_pull(skb, sizeof(struct iphdr))) 6141da177e4SLinus Torvalds goto out_err; 6151da177e4SLinus Torvalds 6161da177e4SLinus Torvalds icmph = skb->h.icmph; 6171da177e4SLinus Torvalds iph = (struct iphdr *)skb->data; 6181da177e4SLinus Torvalds 6191da177e4SLinus Torvalds if (iph->ihl < 5) /* Mangled header, drop. */ 6201da177e4SLinus Torvalds goto out_err; 6211da177e4SLinus Torvalds 6221da177e4SLinus Torvalds if (icmph->type == ICMP_DEST_UNREACH) { 6231da177e4SLinus Torvalds switch (icmph->code & 15) { 6241da177e4SLinus Torvalds case ICMP_NET_UNREACH: 6251da177e4SLinus Torvalds case ICMP_HOST_UNREACH: 6261da177e4SLinus Torvalds case ICMP_PROT_UNREACH: 6271da177e4SLinus Torvalds case ICMP_PORT_UNREACH: 6281da177e4SLinus Torvalds break; 6291da177e4SLinus Torvalds case ICMP_FRAG_NEEDED: 6301da177e4SLinus Torvalds if (ipv4_config.no_pmtu_disc) { 63164ce2073SPatrick McHardy LIMIT_NETDEBUG(KERN_INFO "ICMP: %u.%u.%u.%u: " 6321da177e4SLinus Torvalds "fragmentation needed " 6331da177e4SLinus Torvalds "and DF set.\n", 63464ce2073SPatrick McHardy NIPQUAD(iph->daddr)); 6351da177e4SLinus Torvalds } else { 6361da177e4SLinus Torvalds info = ip_rt_frag_needed(iph, 6371da177e4SLinus Torvalds ntohs(icmph->un.frag.mtu)); 6381da177e4SLinus Torvalds if (!info) 6391da177e4SLinus Torvalds goto out; 6401da177e4SLinus Torvalds } 6411da177e4SLinus Torvalds break; 6421da177e4SLinus Torvalds case ICMP_SR_FAILED: 64364ce2073SPatrick McHardy LIMIT_NETDEBUG(KERN_INFO "ICMP: %u.%u.%u.%u: Source " 6441da177e4SLinus Torvalds "Route Failed.\n", 64564ce2073SPatrick McHardy NIPQUAD(iph->daddr)); 6461da177e4SLinus Torvalds break; 6471da177e4SLinus Torvalds default: 6481da177e4SLinus Torvalds break; 6491da177e4SLinus Torvalds } 6501da177e4SLinus Torvalds if (icmph->code > NR_ICMP_UNREACH) 6511da177e4SLinus Torvalds goto out; 6521da177e4SLinus Torvalds } else if (icmph->type == ICMP_PARAMETERPROB) 6531da177e4SLinus Torvalds info = ntohl(icmph->un.gateway) >> 24; 6541da177e4SLinus Torvalds 6551da177e4SLinus Torvalds /* 6561da177e4SLinus Torvalds * Throw it at our lower layers 6571da177e4SLinus Torvalds * 6581da177e4SLinus Torvalds * RFC 1122: 3.2.2 MUST extract the protocol ID from the passed 6591da177e4SLinus Torvalds * header. 6601da177e4SLinus Torvalds * RFC 1122: 3.2.2.1 MUST pass ICMP unreach messages to the 6611da177e4SLinus Torvalds * transport layer. 6621da177e4SLinus Torvalds * RFC 1122: 3.2.2.2 MUST pass ICMP time expired messages to 6631da177e4SLinus Torvalds * transport layer. 6641da177e4SLinus Torvalds */ 6651da177e4SLinus Torvalds 6661da177e4SLinus Torvalds /* 6671da177e4SLinus Torvalds * Check the other end isnt violating RFC 1122. Some routers send 6681da177e4SLinus Torvalds * bogus responses to broadcast frames. If you see this message 6691da177e4SLinus Torvalds * first check your netmask matches at both ends, if it does then 6701da177e4SLinus Torvalds * get the other vendor to fix their kit. 6711da177e4SLinus Torvalds */ 6721da177e4SLinus Torvalds 6731da177e4SLinus Torvalds if (!sysctl_icmp_ignore_bogus_error_responses && 6741da177e4SLinus Torvalds inet_addr_type(iph->daddr) == RTN_BROADCAST) { 6751da177e4SLinus Torvalds if (net_ratelimit()) 6761da177e4SLinus Torvalds printk(KERN_WARNING "%u.%u.%u.%u sent an invalid ICMP " 6771da177e4SLinus Torvalds "type %u, code %u " 6781da177e4SLinus Torvalds "error to a broadcast: %u.%u.%u.%u on %s\n", 6791da177e4SLinus Torvalds NIPQUAD(skb->nh.iph->saddr), 6801da177e4SLinus Torvalds icmph->type, icmph->code, 6811da177e4SLinus Torvalds NIPQUAD(iph->daddr), 6821da177e4SLinus Torvalds skb->dev->name); 6831da177e4SLinus Torvalds goto out; 6841da177e4SLinus Torvalds } 6851da177e4SLinus Torvalds 6861da177e4SLinus Torvalds /* Checkin full IP header plus 8 bytes of protocol to 6871da177e4SLinus Torvalds * avoid additional coding at protocol handlers. 6881da177e4SLinus Torvalds */ 6891da177e4SLinus Torvalds if (!pskb_may_pull(skb, iph->ihl * 4 + 8)) 6901da177e4SLinus Torvalds goto out; 6911da177e4SLinus Torvalds 6921da177e4SLinus Torvalds iph = (struct iphdr *)skb->data; 6931da177e4SLinus Torvalds protocol = iph->protocol; 6941da177e4SLinus Torvalds 6951da177e4SLinus Torvalds /* 6961da177e4SLinus Torvalds * Deliver ICMP message to raw sockets. Pretty useless feature? 6971da177e4SLinus Torvalds */ 6981da177e4SLinus Torvalds 6991da177e4SLinus Torvalds /* Note: See raw.c and net/raw.h, RAWV4_HTABLE_SIZE==MAX_INET_PROTOS */ 7001da177e4SLinus Torvalds hash = protocol & (MAX_INET_PROTOS - 1); 7011da177e4SLinus Torvalds read_lock(&raw_v4_lock); 7021da177e4SLinus Torvalds if ((raw_sk = sk_head(&raw_v4_htable[hash])) != NULL) { 7031da177e4SLinus Torvalds while ((raw_sk = __raw_v4_lookup(raw_sk, protocol, iph->daddr, 7041da177e4SLinus Torvalds iph->saddr, 7051da177e4SLinus Torvalds skb->dev->ifindex)) != NULL) { 7061da177e4SLinus Torvalds raw_err(raw_sk, skb, info); 7071da177e4SLinus Torvalds raw_sk = sk_next(raw_sk); 7081da177e4SLinus Torvalds iph = (struct iphdr *)skb->data; 7091da177e4SLinus Torvalds } 7101da177e4SLinus Torvalds } 7111da177e4SLinus Torvalds read_unlock(&raw_v4_lock); 7121da177e4SLinus Torvalds 7131da177e4SLinus Torvalds rcu_read_lock(); 7141da177e4SLinus Torvalds ipprot = rcu_dereference(inet_protos[hash]); 7151da177e4SLinus Torvalds if (ipprot && ipprot->err_handler) 7161da177e4SLinus Torvalds ipprot->err_handler(skb, info); 7171da177e4SLinus Torvalds rcu_read_unlock(); 7181da177e4SLinus Torvalds 7191da177e4SLinus Torvalds out: 7201da177e4SLinus Torvalds return; 7211da177e4SLinus Torvalds out_err: 7221da177e4SLinus Torvalds ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); 7231da177e4SLinus Torvalds goto out; 7241da177e4SLinus Torvalds } 7251da177e4SLinus Torvalds 7261da177e4SLinus Torvalds 7271da177e4SLinus Torvalds /* 7281da177e4SLinus Torvalds * Handle ICMP_REDIRECT. 7291da177e4SLinus Torvalds */ 7301da177e4SLinus Torvalds 7311da177e4SLinus Torvalds static void icmp_redirect(struct sk_buff *skb) 7321da177e4SLinus Torvalds { 7331da177e4SLinus Torvalds struct iphdr *iph; 7341da177e4SLinus Torvalds 7351da177e4SLinus Torvalds if (skb->len < sizeof(struct iphdr)) 7361da177e4SLinus Torvalds goto out_err; 7371da177e4SLinus Torvalds 7381da177e4SLinus Torvalds /* 7391da177e4SLinus Torvalds * Get the copied header of the packet that caused the redirect 7401da177e4SLinus Torvalds */ 7411da177e4SLinus Torvalds if (!pskb_may_pull(skb, sizeof(struct iphdr))) 7421da177e4SLinus Torvalds goto out; 7431da177e4SLinus Torvalds 7441da177e4SLinus Torvalds iph = (struct iphdr *)skb->data; 7451da177e4SLinus Torvalds 7461da177e4SLinus Torvalds switch (skb->h.icmph->code & 7) { 7471da177e4SLinus Torvalds case ICMP_REDIR_NET: 7481da177e4SLinus Torvalds case ICMP_REDIR_NETTOS: 7491da177e4SLinus Torvalds /* 7501da177e4SLinus Torvalds * As per RFC recommendations now handle it as a host redirect. 7511da177e4SLinus Torvalds */ 7521da177e4SLinus Torvalds case ICMP_REDIR_HOST: 7531da177e4SLinus Torvalds case ICMP_REDIR_HOSTTOS: 754f86502bfSDavid S. Miller ip_rt_redirect(skb->nh.iph->saddr, iph->daddr, 755f86502bfSDavid S. Miller skb->h.icmph->un.gateway, 756cef2685eSIlia Sotnikov iph->saddr, skb->dev); 7571da177e4SLinus Torvalds break; 7581da177e4SLinus Torvalds } 7591da177e4SLinus Torvalds out: 7601da177e4SLinus Torvalds return; 7611da177e4SLinus Torvalds out_err: 7621da177e4SLinus Torvalds ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); 7631da177e4SLinus Torvalds goto out; 7641da177e4SLinus Torvalds } 7651da177e4SLinus Torvalds 7661da177e4SLinus Torvalds /* 7671da177e4SLinus Torvalds * Handle ICMP_ECHO ("ping") requests. 7681da177e4SLinus Torvalds * 7691da177e4SLinus Torvalds * RFC 1122: 3.2.2.6 MUST have an echo server that answers ICMP echo 7701da177e4SLinus Torvalds * requests. 7711da177e4SLinus Torvalds * RFC 1122: 3.2.2.6 Data received in the ICMP_ECHO request MUST be 7721da177e4SLinus Torvalds * included in the reply. 7731da177e4SLinus Torvalds * RFC 1812: 4.3.3.6 SHOULD have a config option for silently ignoring 7741da177e4SLinus Torvalds * echo requests, MUST have default=NOT. 7751da177e4SLinus Torvalds * See also WRT handling of options once they are done and working. 7761da177e4SLinus Torvalds */ 7771da177e4SLinus Torvalds 7781da177e4SLinus Torvalds static void icmp_echo(struct sk_buff *skb) 7791da177e4SLinus Torvalds { 7801da177e4SLinus Torvalds if (!sysctl_icmp_echo_ignore_all) { 7811da177e4SLinus Torvalds struct icmp_bxm icmp_param; 7821da177e4SLinus Torvalds 7831da177e4SLinus Torvalds icmp_param.data.icmph = *skb->h.icmph; 7841da177e4SLinus Torvalds icmp_param.data.icmph.type = ICMP_ECHOREPLY; 7851da177e4SLinus Torvalds icmp_param.skb = skb; 7861da177e4SLinus Torvalds icmp_param.offset = 0; 7871da177e4SLinus Torvalds icmp_param.data_len = skb->len; 7881da177e4SLinus Torvalds icmp_param.head_len = sizeof(struct icmphdr); 7891da177e4SLinus Torvalds icmp_reply(&icmp_param, skb); 7901da177e4SLinus Torvalds } 7911da177e4SLinus Torvalds } 7921da177e4SLinus Torvalds 7931da177e4SLinus Torvalds /* 7941da177e4SLinus Torvalds * Handle ICMP Timestamp requests. 7951da177e4SLinus Torvalds * RFC 1122: 3.2.2.8 MAY implement ICMP timestamp requests. 7961da177e4SLinus Torvalds * SHOULD be in the kernel for minimum random latency. 7971da177e4SLinus Torvalds * MUST be accurate to a few minutes. 7981da177e4SLinus Torvalds * MUST be updated at least at 15Hz. 7991da177e4SLinus Torvalds */ 8001da177e4SLinus Torvalds static void icmp_timestamp(struct sk_buff *skb) 8011da177e4SLinus Torvalds { 8021da177e4SLinus Torvalds struct timeval tv; 8031da177e4SLinus Torvalds struct icmp_bxm icmp_param; 8041da177e4SLinus Torvalds /* 8051da177e4SLinus Torvalds * Too short. 8061da177e4SLinus Torvalds */ 8071da177e4SLinus Torvalds if (skb->len < 4) 8081da177e4SLinus Torvalds goto out_err; 8091da177e4SLinus Torvalds 8101da177e4SLinus Torvalds /* 8111da177e4SLinus Torvalds * Fill in the current time as ms since midnight UT: 8121da177e4SLinus Torvalds */ 8131da177e4SLinus Torvalds do_gettimeofday(&tv); 8141da177e4SLinus Torvalds icmp_param.data.times[1] = htonl((tv.tv_sec % 86400) * 1000 + 8151da177e4SLinus Torvalds tv.tv_usec / 1000); 8161da177e4SLinus Torvalds icmp_param.data.times[2] = icmp_param.data.times[1]; 8171da177e4SLinus Torvalds if (skb_copy_bits(skb, 0, &icmp_param.data.times[0], 4)) 8181da177e4SLinus Torvalds BUG(); 8191da177e4SLinus Torvalds icmp_param.data.icmph = *skb->h.icmph; 8201da177e4SLinus Torvalds icmp_param.data.icmph.type = ICMP_TIMESTAMPREPLY; 8211da177e4SLinus Torvalds icmp_param.data.icmph.code = 0; 8221da177e4SLinus Torvalds icmp_param.skb = skb; 8231da177e4SLinus Torvalds icmp_param.offset = 0; 8241da177e4SLinus Torvalds icmp_param.data_len = 0; 8251da177e4SLinus Torvalds icmp_param.head_len = sizeof(struct icmphdr) + 12; 8261da177e4SLinus Torvalds icmp_reply(&icmp_param, skb); 8271da177e4SLinus Torvalds out: 8281da177e4SLinus Torvalds return; 8291da177e4SLinus Torvalds out_err: 8301da177e4SLinus Torvalds ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); 8311da177e4SLinus Torvalds goto out; 8321da177e4SLinus Torvalds } 8331da177e4SLinus Torvalds 8341da177e4SLinus Torvalds 8351da177e4SLinus Torvalds /* 8361da177e4SLinus Torvalds * Handle ICMP_ADDRESS_MASK requests. (RFC950) 8371da177e4SLinus Torvalds * 8381da177e4SLinus Torvalds * RFC1122 (3.2.2.9). A host MUST only send replies to 8391da177e4SLinus Torvalds * ADDRESS_MASK requests if it's been configured as an address mask 8401da177e4SLinus Torvalds * agent. Receiving a request doesn't constitute implicit permission to 8411da177e4SLinus Torvalds * act as one. Of course, implementing this correctly requires (SHOULD) 8421da177e4SLinus Torvalds * a way to turn the functionality on and off. Another one for sysctl(), 8431da177e4SLinus Torvalds * I guess. -- MS 8441da177e4SLinus Torvalds * 8451da177e4SLinus Torvalds * RFC1812 (4.3.3.9). A router MUST implement it. 8461da177e4SLinus Torvalds * A router SHOULD have switch turning it on/off. 8471da177e4SLinus Torvalds * This switch MUST be ON by default. 8481da177e4SLinus Torvalds * 8491da177e4SLinus Torvalds * Gratuitous replies, zero-source replies are not implemented, 8501da177e4SLinus Torvalds * that complies with RFC. DO NOT implement them!!! All the idea 8511da177e4SLinus Torvalds * of broadcast addrmask replies as specified in RFC950 is broken. 8521da177e4SLinus Torvalds * The problem is that it is not uncommon to have several prefixes 8531da177e4SLinus Torvalds * on one physical interface. Moreover, addrmask agent can even be 8541da177e4SLinus Torvalds * not aware of existing another prefixes. 8551da177e4SLinus Torvalds * If source is zero, addrmask agent cannot choose correct prefix. 8561da177e4SLinus Torvalds * Gratuitous mask announcements suffer from the same problem. 8571da177e4SLinus Torvalds * RFC1812 explains it, but still allows to use ADDRMASK, 8581da177e4SLinus Torvalds * that is pretty silly. --ANK 8591da177e4SLinus Torvalds * 8601da177e4SLinus Torvalds * All these rules are so bizarre, that I removed kernel addrmask 8611da177e4SLinus Torvalds * support at all. It is wrong, it is obsolete, nobody uses it in 8621da177e4SLinus Torvalds * any case. --ANK 8631da177e4SLinus Torvalds * 8641da177e4SLinus Torvalds * Furthermore you can do it with a usermode address agent program 8651da177e4SLinus Torvalds * anyway... 8661da177e4SLinus Torvalds */ 8671da177e4SLinus Torvalds 8681da177e4SLinus Torvalds static void icmp_address(struct sk_buff *skb) 8691da177e4SLinus Torvalds { 8701da177e4SLinus Torvalds #if 0 8711da177e4SLinus Torvalds if (net_ratelimit()) 8721da177e4SLinus Torvalds printk(KERN_DEBUG "a guy asks for address mask. Who is it?\n"); 8731da177e4SLinus Torvalds #endif 8741da177e4SLinus Torvalds } 8751da177e4SLinus Torvalds 8761da177e4SLinus Torvalds /* 8771da177e4SLinus Torvalds * RFC1812 (4.3.3.9). A router SHOULD listen all replies, and complain 8781da177e4SLinus Torvalds * loudly if an inconsistency is found. 8791da177e4SLinus Torvalds */ 8801da177e4SLinus Torvalds 8811da177e4SLinus Torvalds static void icmp_address_reply(struct sk_buff *skb) 8821da177e4SLinus Torvalds { 8831da177e4SLinus Torvalds struct rtable *rt = (struct rtable *)skb->dst; 8841da177e4SLinus Torvalds struct net_device *dev = skb->dev; 8851da177e4SLinus Torvalds struct in_device *in_dev; 8861da177e4SLinus Torvalds struct in_ifaddr *ifa; 8871da177e4SLinus Torvalds 8881da177e4SLinus Torvalds if (skb->len < 4 || !(rt->rt_flags&RTCF_DIRECTSRC)) 8891da177e4SLinus Torvalds goto out; 8901da177e4SLinus Torvalds 8911da177e4SLinus Torvalds in_dev = in_dev_get(dev); 8921da177e4SLinus Torvalds if (!in_dev) 8931da177e4SLinus Torvalds goto out; 8941da177e4SLinus Torvalds rcu_read_lock(); 8951da177e4SLinus Torvalds if (in_dev->ifa_list && 8961da177e4SLinus Torvalds IN_DEV_LOG_MARTIANS(in_dev) && 8971da177e4SLinus Torvalds IN_DEV_FORWARD(in_dev)) { 898a144ea4bSAl Viro __be32 _mask, *mp; 8991da177e4SLinus Torvalds 9001da177e4SLinus Torvalds mp = skb_header_pointer(skb, 0, sizeof(_mask), &_mask); 90109a62660SKris Katterjohn BUG_ON(mp == NULL); 9021da177e4SLinus Torvalds for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) { 9031da177e4SLinus Torvalds if (*mp == ifa->ifa_mask && 9041da177e4SLinus Torvalds inet_ifa_match(rt->rt_src, ifa)) 9051da177e4SLinus Torvalds break; 9061da177e4SLinus Torvalds } 9071da177e4SLinus Torvalds if (!ifa && net_ratelimit()) { 9081da177e4SLinus Torvalds printk(KERN_INFO "Wrong address mask %u.%u.%u.%u from " 9091da177e4SLinus Torvalds "%s/%u.%u.%u.%u\n", 9101da177e4SLinus Torvalds NIPQUAD(*mp), dev->name, NIPQUAD(rt->rt_src)); 9111da177e4SLinus Torvalds } 9121da177e4SLinus Torvalds } 9131da177e4SLinus Torvalds rcu_read_unlock(); 9141da177e4SLinus Torvalds in_dev_put(in_dev); 9151da177e4SLinus Torvalds out:; 9161da177e4SLinus Torvalds } 9171da177e4SLinus Torvalds 9181da177e4SLinus Torvalds static void icmp_discard(struct sk_buff *skb) 9191da177e4SLinus Torvalds { 9201da177e4SLinus Torvalds } 9211da177e4SLinus Torvalds 9221da177e4SLinus Torvalds /* 9231da177e4SLinus Torvalds * Deal with incoming ICMP packets. 9241da177e4SLinus Torvalds */ 9251da177e4SLinus Torvalds int icmp_rcv(struct sk_buff *skb) 9261da177e4SLinus Torvalds { 9271da177e4SLinus Torvalds struct icmphdr *icmph; 9281da177e4SLinus Torvalds struct rtable *rt = (struct rtable *)skb->dst; 9291da177e4SLinus Torvalds 9301da177e4SLinus Torvalds ICMP_INC_STATS_BH(ICMP_MIB_INMSGS); 9311da177e4SLinus Torvalds 9321da177e4SLinus Torvalds switch (skb->ip_summed) { 93384fa7933SPatrick McHardy case CHECKSUM_COMPLETE: 934d3bc23e7SAl Viro if (!csum_fold(skb->csum)) 9351da177e4SLinus Torvalds break; 936fb286bb2SHerbert Xu /* fall through */ 9371da177e4SLinus Torvalds case CHECKSUM_NONE: 938fb286bb2SHerbert Xu skb->csum = 0; 939fb286bb2SHerbert Xu if (__skb_checksum_complete(skb)) 9401da177e4SLinus Torvalds goto error; 9411da177e4SLinus Torvalds } 9421da177e4SLinus Torvalds 9431da177e4SLinus Torvalds if (!pskb_pull(skb, sizeof(struct icmphdr))) 9441da177e4SLinus Torvalds goto error; 9451da177e4SLinus Torvalds 9461da177e4SLinus Torvalds icmph = skb->h.icmph; 9471da177e4SLinus Torvalds 9481da177e4SLinus Torvalds /* 9491da177e4SLinus Torvalds * 18 is the highest 'known' ICMP type. Anything else is a mystery 9501da177e4SLinus Torvalds * 9511da177e4SLinus Torvalds * RFC 1122: 3.2.2 Unknown ICMP messages types MUST be silently 9521da177e4SLinus Torvalds * discarded. 9531da177e4SLinus Torvalds */ 9541da177e4SLinus Torvalds if (icmph->type > NR_ICMP_TYPES) 9551da177e4SLinus Torvalds goto error; 9561da177e4SLinus Torvalds 9571da177e4SLinus Torvalds 9581da177e4SLinus Torvalds /* 9591da177e4SLinus Torvalds * Parse the ICMP message 9601da177e4SLinus Torvalds */ 9611da177e4SLinus Torvalds 9621da177e4SLinus Torvalds if (rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) { 9631da177e4SLinus Torvalds /* 9641da177e4SLinus Torvalds * RFC 1122: 3.2.2.6 An ICMP_ECHO to broadcast MAY be 9651da177e4SLinus Torvalds * silently ignored (we let user decide with a sysctl). 9661da177e4SLinus Torvalds * RFC 1122: 3.2.2.8 An ICMP_TIMESTAMP MAY be silently 9671da177e4SLinus Torvalds * discarded if to broadcast/multicast. 9681da177e4SLinus Torvalds */ 9694c866aa7SAlexey Kuznetsov if ((icmph->type == ICMP_ECHO || 9704c866aa7SAlexey Kuznetsov icmph->type == ICMP_TIMESTAMP) && 9711da177e4SLinus Torvalds sysctl_icmp_echo_ignore_broadcasts) { 9721da177e4SLinus Torvalds goto error; 9731da177e4SLinus Torvalds } 9741da177e4SLinus Torvalds if (icmph->type != ICMP_ECHO && 9751da177e4SLinus Torvalds icmph->type != ICMP_TIMESTAMP && 9761da177e4SLinus Torvalds icmph->type != ICMP_ADDRESS && 9771da177e4SLinus Torvalds icmph->type != ICMP_ADDRESSREPLY) { 9781da177e4SLinus Torvalds goto error; 9791da177e4SLinus Torvalds } 9801da177e4SLinus Torvalds } 9811da177e4SLinus Torvalds 9821da177e4SLinus Torvalds ICMP_INC_STATS_BH(icmp_pointers[icmph->type].input_entry); 9831da177e4SLinus Torvalds icmp_pointers[icmph->type].handler(skb); 9841da177e4SLinus Torvalds 9851da177e4SLinus Torvalds drop: 9861da177e4SLinus Torvalds kfree_skb(skb); 9871da177e4SLinus Torvalds return 0; 9881da177e4SLinus Torvalds error: 9891da177e4SLinus Torvalds ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); 9901da177e4SLinus Torvalds goto drop; 9911da177e4SLinus Torvalds } 9921da177e4SLinus Torvalds 9931da177e4SLinus Torvalds /* 9941da177e4SLinus Torvalds * This table is the definition of how we handle ICMP. 9951da177e4SLinus Torvalds */ 9969b5b5cffSArjan van de Ven static const struct icmp_control icmp_pointers[NR_ICMP_TYPES + 1] = { 9971da177e4SLinus Torvalds [ICMP_ECHOREPLY] = { 9981da177e4SLinus Torvalds .output_entry = ICMP_MIB_OUTECHOREPS, 9991da177e4SLinus Torvalds .input_entry = ICMP_MIB_INECHOREPS, 10001da177e4SLinus Torvalds .handler = icmp_discard, 10011da177e4SLinus Torvalds }, 10021da177e4SLinus Torvalds [1] = { 10031da177e4SLinus Torvalds .output_entry = ICMP_MIB_DUMMY, 10041da177e4SLinus Torvalds .input_entry = ICMP_MIB_INERRORS, 10051da177e4SLinus Torvalds .handler = icmp_discard, 10061da177e4SLinus Torvalds .error = 1, 10071da177e4SLinus Torvalds }, 10081da177e4SLinus Torvalds [2] = { 10091da177e4SLinus Torvalds .output_entry = ICMP_MIB_DUMMY, 10101da177e4SLinus Torvalds .input_entry = ICMP_MIB_INERRORS, 10111da177e4SLinus Torvalds .handler = icmp_discard, 10121da177e4SLinus Torvalds .error = 1, 10131da177e4SLinus Torvalds }, 10141da177e4SLinus Torvalds [ICMP_DEST_UNREACH] = { 10151da177e4SLinus Torvalds .output_entry = ICMP_MIB_OUTDESTUNREACHS, 10161da177e4SLinus Torvalds .input_entry = ICMP_MIB_INDESTUNREACHS, 10171da177e4SLinus Torvalds .handler = icmp_unreach, 10181da177e4SLinus Torvalds .error = 1, 10191da177e4SLinus Torvalds }, 10201da177e4SLinus Torvalds [ICMP_SOURCE_QUENCH] = { 10211da177e4SLinus Torvalds .output_entry = ICMP_MIB_OUTSRCQUENCHS, 10221da177e4SLinus Torvalds .input_entry = ICMP_MIB_INSRCQUENCHS, 10231da177e4SLinus Torvalds .handler = icmp_unreach, 10241da177e4SLinus Torvalds .error = 1, 10251da177e4SLinus Torvalds }, 10261da177e4SLinus Torvalds [ICMP_REDIRECT] = { 10271da177e4SLinus Torvalds .output_entry = ICMP_MIB_OUTREDIRECTS, 10281da177e4SLinus Torvalds .input_entry = ICMP_MIB_INREDIRECTS, 10291da177e4SLinus Torvalds .handler = icmp_redirect, 10301da177e4SLinus Torvalds .error = 1, 10311da177e4SLinus Torvalds }, 10321da177e4SLinus Torvalds [6] = { 10331da177e4SLinus Torvalds .output_entry = ICMP_MIB_DUMMY, 10341da177e4SLinus Torvalds .input_entry = ICMP_MIB_INERRORS, 10351da177e4SLinus Torvalds .handler = icmp_discard, 10361da177e4SLinus Torvalds .error = 1, 10371da177e4SLinus Torvalds }, 10381da177e4SLinus Torvalds [7] = { 10391da177e4SLinus Torvalds .output_entry = ICMP_MIB_DUMMY, 10401da177e4SLinus Torvalds .input_entry = ICMP_MIB_INERRORS, 10411da177e4SLinus Torvalds .handler = icmp_discard, 10421da177e4SLinus Torvalds .error = 1, 10431da177e4SLinus Torvalds }, 10441da177e4SLinus Torvalds [ICMP_ECHO] = { 10451da177e4SLinus Torvalds .output_entry = ICMP_MIB_OUTECHOS, 10461da177e4SLinus Torvalds .input_entry = ICMP_MIB_INECHOS, 10471da177e4SLinus Torvalds .handler = icmp_echo, 10481da177e4SLinus Torvalds }, 10491da177e4SLinus Torvalds [9] = { 10501da177e4SLinus Torvalds .output_entry = ICMP_MIB_DUMMY, 10511da177e4SLinus Torvalds .input_entry = ICMP_MIB_INERRORS, 10521da177e4SLinus Torvalds .handler = icmp_discard, 10531da177e4SLinus Torvalds .error = 1, 10541da177e4SLinus Torvalds }, 10551da177e4SLinus Torvalds [10] = { 10561da177e4SLinus Torvalds .output_entry = ICMP_MIB_DUMMY, 10571da177e4SLinus Torvalds .input_entry = ICMP_MIB_INERRORS, 10581da177e4SLinus Torvalds .handler = icmp_discard, 10591da177e4SLinus Torvalds .error = 1, 10601da177e4SLinus Torvalds }, 10611da177e4SLinus Torvalds [ICMP_TIME_EXCEEDED] = { 10621da177e4SLinus Torvalds .output_entry = ICMP_MIB_OUTTIMEEXCDS, 10631da177e4SLinus Torvalds .input_entry = ICMP_MIB_INTIMEEXCDS, 10641da177e4SLinus Torvalds .handler = icmp_unreach, 10651da177e4SLinus Torvalds .error = 1, 10661da177e4SLinus Torvalds }, 10671da177e4SLinus Torvalds [ICMP_PARAMETERPROB] = { 10681da177e4SLinus Torvalds .output_entry = ICMP_MIB_OUTPARMPROBS, 10691da177e4SLinus Torvalds .input_entry = ICMP_MIB_INPARMPROBS, 10701da177e4SLinus Torvalds .handler = icmp_unreach, 10711da177e4SLinus Torvalds .error = 1, 10721da177e4SLinus Torvalds }, 10731da177e4SLinus Torvalds [ICMP_TIMESTAMP] = { 10741da177e4SLinus Torvalds .output_entry = ICMP_MIB_OUTTIMESTAMPS, 10751da177e4SLinus Torvalds .input_entry = ICMP_MIB_INTIMESTAMPS, 10761da177e4SLinus Torvalds .handler = icmp_timestamp, 10771da177e4SLinus Torvalds }, 10781da177e4SLinus Torvalds [ICMP_TIMESTAMPREPLY] = { 10791da177e4SLinus Torvalds .output_entry = ICMP_MIB_OUTTIMESTAMPREPS, 10801da177e4SLinus Torvalds .input_entry = ICMP_MIB_INTIMESTAMPREPS, 10811da177e4SLinus Torvalds .handler = icmp_discard, 10821da177e4SLinus Torvalds }, 10831da177e4SLinus Torvalds [ICMP_INFO_REQUEST] = { 10841da177e4SLinus Torvalds .output_entry = ICMP_MIB_DUMMY, 10851da177e4SLinus Torvalds .input_entry = ICMP_MIB_DUMMY, 10861da177e4SLinus Torvalds .handler = icmp_discard, 10871da177e4SLinus Torvalds }, 10881da177e4SLinus Torvalds [ICMP_INFO_REPLY] = { 10891da177e4SLinus Torvalds .output_entry = ICMP_MIB_DUMMY, 10901da177e4SLinus Torvalds .input_entry = ICMP_MIB_DUMMY, 10911da177e4SLinus Torvalds .handler = icmp_discard, 10921da177e4SLinus Torvalds }, 10931da177e4SLinus Torvalds [ICMP_ADDRESS] = { 10941da177e4SLinus Torvalds .output_entry = ICMP_MIB_OUTADDRMASKS, 10951da177e4SLinus Torvalds .input_entry = ICMP_MIB_INADDRMASKS, 10961da177e4SLinus Torvalds .handler = icmp_address, 10971da177e4SLinus Torvalds }, 10981da177e4SLinus Torvalds [ICMP_ADDRESSREPLY] = { 10991da177e4SLinus Torvalds .output_entry = ICMP_MIB_OUTADDRMASKREPS, 11001da177e4SLinus Torvalds .input_entry = ICMP_MIB_INADDRMASKREPS, 11011da177e4SLinus Torvalds .handler = icmp_address_reply, 11021da177e4SLinus Torvalds }, 11031da177e4SLinus Torvalds }; 11041da177e4SLinus Torvalds 11051da177e4SLinus Torvalds void __init icmp_init(struct net_proto_family *ops) 11061da177e4SLinus Torvalds { 11071da177e4SLinus Torvalds struct inet_sock *inet; 11081da177e4SLinus Torvalds int i; 11091da177e4SLinus Torvalds 11106f912042SKAMEZAWA Hiroyuki for_each_possible_cpu(i) { 11111da177e4SLinus Torvalds int err; 11121da177e4SLinus Torvalds 11131da177e4SLinus Torvalds err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_ICMP, 11141da177e4SLinus Torvalds &per_cpu(__icmp_socket, i)); 11151da177e4SLinus Torvalds 11161da177e4SLinus Torvalds if (err < 0) 11171da177e4SLinus Torvalds panic("Failed to create the ICMP control socket.\n"); 11181da177e4SLinus Torvalds 11191da177e4SLinus Torvalds per_cpu(__icmp_socket, i)->sk->sk_allocation = GFP_ATOMIC; 11201da177e4SLinus Torvalds 11211da177e4SLinus Torvalds /* Enough space for 2 64K ICMP packets, including 11221da177e4SLinus Torvalds * sk_buff struct overhead. 11231da177e4SLinus Torvalds */ 11241da177e4SLinus Torvalds per_cpu(__icmp_socket, i)->sk->sk_sndbuf = 11251da177e4SLinus Torvalds (2 * ((64 * 1024) + sizeof(struct sk_buff))); 11261da177e4SLinus Torvalds 11271da177e4SLinus Torvalds inet = inet_sk(per_cpu(__icmp_socket, i)->sk); 11281da177e4SLinus Torvalds inet->uc_ttl = -1; 11291da177e4SLinus Torvalds inet->pmtudisc = IP_PMTUDISC_DONT; 11301da177e4SLinus Torvalds 11311da177e4SLinus Torvalds /* Unhash it so that IP input processing does not even 11321da177e4SLinus Torvalds * see it, we do not wish this socket to see incoming 11331da177e4SLinus Torvalds * packets. 11341da177e4SLinus Torvalds */ 11351da177e4SLinus Torvalds per_cpu(__icmp_socket, i)->sk->sk_prot->unhash(per_cpu(__icmp_socket, i)->sk); 11361da177e4SLinus Torvalds } 11371da177e4SLinus Torvalds } 11381da177e4SLinus Torvalds 11391da177e4SLinus Torvalds EXPORT_SYMBOL(icmp_err_convert); 11401da177e4SLinus Torvalds EXPORT_SYMBOL(icmp_send); 11411da177e4SLinus Torvalds EXPORT_SYMBOL(icmp_statistics); 11421da177e4SLinus Torvalds EXPORT_SYMBOL(xrlim_allow); 1143