11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * NET3: Implementation of the ICMP protocol layer. 31da177e4SLinus Torvalds * 4113aa838SAlan Cox * Alan Cox, <alan@lxorguk.ukuu.org.uk> 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or 71da177e4SLinus Torvalds * modify it under the terms of the GNU General Public License 81da177e4SLinus Torvalds * as published by the Free Software Foundation; either version 91da177e4SLinus Torvalds * 2 of the License, or (at your option) any later version. 101da177e4SLinus Torvalds * 111da177e4SLinus Torvalds * Some of the function names and the icmp unreach table for this 121da177e4SLinus Torvalds * module were derived from [icmp.c 1.0.11 06/02/93] by 131da177e4SLinus Torvalds * Ross Biro, Fred N. van Kempen, Mark Evans, Alan Cox, Gerhard Koerting. 141da177e4SLinus Torvalds * Other than that this module is a complete rewrite. 151da177e4SLinus Torvalds * 161da177e4SLinus Torvalds * Fixes: 171da177e4SLinus Torvalds * Clemens Fruhwirth : introduce global icmp rate limiting 181da177e4SLinus Torvalds * with icmp type masking ability instead 191da177e4SLinus Torvalds * of broken per type icmp timeouts. 201da177e4SLinus Torvalds * Mike Shaver : RFC1122 checks. 211da177e4SLinus Torvalds * Alan Cox : Multicast ping reply as self. 221da177e4SLinus Torvalds * Alan Cox : Fix atomicity lockup in ip_build_xmit 231da177e4SLinus Torvalds * call. 241da177e4SLinus Torvalds * Alan Cox : Added 216,128 byte paths to the MTU 251da177e4SLinus Torvalds * code. 261da177e4SLinus Torvalds * Martin Mares : RFC1812 checks. 271da177e4SLinus Torvalds * Martin Mares : Can be configured to follow redirects 281da177e4SLinus Torvalds * if acting as a router _without_ a 291da177e4SLinus Torvalds * routing protocol (RFC 1812). 301da177e4SLinus Torvalds * Martin Mares : Echo requests may be configured to 311da177e4SLinus Torvalds * be ignored (RFC 1812). 321da177e4SLinus Torvalds * Martin Mares : Limitation of ICMP error message 331da177e4SLinus Torvalds * transmit rate (RFC 1812). 341da177e4SLinus Torvalds * Martin Mares : TOS and Precedence set correctly 351da177e4SLinus Torvalds * (RFC 1812). 361da177e4SLinus Torvalds * Martin Mares : Now copying as much data from the 371da177e4SLinus Torvalds * original packet as we can without 381da177e4SLinus Torvalds * exceeding 576 bytes (RFC 1812). 391da177e4SLinus Torvalds * Willy Konynenberg : Transparent proxying support. 401da177e4SLinus Torvalds * Keith Owens : RFC1191 correction for 4.2BSD based 411da177e4SLinus Torvalds * path MTU bug. 421da177e4SLinus Torvalds * Thomas Quinot : ICMP Dest Unreach codes up to 15 are 431da177e4SLinus Torvalds * valid (RFC 1812). 441da177e4SLinus Torvalds * Andi Kleen : Check all packet lengths properly 451da177e4SLinus Torvalds * and moved all kfree_skb() up to 461da177e4SLinus Torvalds * icmp_rcv. 471da177e4SLinus Torvalds * Andi Kleen : Move the rate limit bookkeeping 481da177e4SLinus Torvalds * into the dest entry and use a token 491da177e4SLinus Torvalds * bucket filter (thanks to ANK). Make 501da177e4SLinus Torvalds * the rates sysctl configurable. 511da177e4SLinus Torvalds * Yu Tianli : Fixed two ugly bugs in icmp_send 521da177e4SLinus Torvalds * - IP option length was accounted wrongly 531da177e4SLinus Torvalds * - ICMP header length was not accounted 541da177e4SLinus Torvalds * at all. 551da177e4SLinus Torvalds * Tristan Greaves : Added sysctl option to ignore bogus 561da177e4SLinus Torvalds * broadcast responses from broken routers. 571da177e4SLinus Torvalds * 581da177e4SLinus Torvalds * To Fix: 591da177e4SLinus Torvalds * 601da177e4SLinus Torvalds * - Should use skb_pull() instead of all the manual checking. 611da177e4SLinus Torvalds * This would also greatly simply some upper layer error handlers. --AK 621da177e4SLinus Torvalds * 631da177e4SLinus Torvalds */ 641da177e4SLinus Torvalds 651da177e4SLinus Torvalds #include <linux/module.h> 661da177e4SLinus Torvalds #include <linux/types.h> 671da177e4SLinus Torvalds #include <linux/jiffies.h> 681da177e4SLinus Torvalds #include <linux/kernel.h> 691da177e4SLinus Torvalds #include <linux/fcntl.h> 701da177e4SLinus Torvalds #include <linux/socket.h> 711da177e4SLinus Torvalds #include <linux/in.h> 721da177e4SLinus Torvalds #include <linux/inet.h> 7314c85021SArnaldo Carvalho de Melo #include <linux/inetdevice.h> 741da177e4SLinus Torvalds #include <linux/netdevice.h> 751da177e4SLinus Torvalds #include <linux/string.h> 761da177e4SLinus Torvalds #include <linux/netfilter_ipv4.h> 771da177e4SLinus Torvalds #include <net/snmp.h> 781da177e4SLinus Torvalds #include <net/ip.h> 791da177e4SLinus Torvalds #include <net/route.h> 801da177e4SLinus Torvalds #include <net/protocol.h> 811da177e4SLinus Torvalds #include <net/icmp.h> 821da177e4SLinus Torvalds #include <net/tcp.h> 831da177e4SLinus Torvalds #include <net/udp.h> 841da177e4SLinus Torvalds #include <net/raw.h> 851da177e4SLinus Torvalds #include <linux/skbuff.h> 861da177e4SLinus Torvalds #include <net/sock.h> 871da177e4SLinus Torvalds #include <linux/errno.h> 881da177e4SLinus Torvalds #include <linux/timer.h> 891da177e4SLinus Torvalds #include <linux/init.h> 901da177e4SLinus Torvalds #include <asm/system.h> 911da177e4SLinus Torvalds #include <asm/uaccess.h> 921da177e4SLinus Torvalds #include <net/checksum.h> 938b7817f3SHerbert Xu #include <net/xfrm.h> 94c1e9894dSDenis V. Lunev #include <net/inet_common.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 /* An array of errno for error messages from dest unreach. */ 1151da177e4SLinus Torvalds /* RFC 1122: 3.2.2.1 States that NET_UNREACH, HOST_UNREACH and SR_FAILED MUST be considered 'transient errs'. */ 1161da177e4SLinus Torvalds 1171da177e4SLinus Torvalds struct icmp_err icmp_err_convert[] = { 1181da177e4SLinus Torvalds { 1191da177e4SLinus Torvalds .errno = ENETUNREACH, /* ICMP_NET_UNREACH */ 1201da177e4SLinus Torvalds .fatal = 0, 1211da177e4SLinus Torvalds }, 1221da177e4SLinus Torvalds { 1231da177e4SLinus Torvalds .errno = EHOSTUNREACH, /* ICMP_HOST_UNREACH */ 1241da177e4SLinus Torvalds .fatal = 0, 1251da177e4SLinus Torvalds }, 1261da177e4SLinus Torvalds { 1271da177e4SLinus Torvalds .errno = ENOPROTOOPT /* ICMP_PROT_UNREACH */, 1281da177e4SLinus Torvalds .fatal = 1, 1291da177e4SLinus Torvalds }, 1301da177e4SLinus Torvalds { 1311da177e4SLinus Torvalds .errno = ECONNREFUSED, /* ICMP_PORT_UNREACH */ 1321da177e4SLinus Torvalds .fatal = 1, 1331da177e4SLinus Torvalds }, 1341da177e4SLinus Torvalds { 1351da177e4SLinus Torvalds .errno = EMSGSIZE, /* ICMP_FRAG_NEEDED */ 1361da177e4SLinus Torvalds .fatal = 0, 1371da177e4SLinus Torvalds }, 1381da177e4SLinus Torvalds { 1391da177e4SLinus Torvalds .errno = EOPNOTSUPP, /* ICMP_SR_FAILED */ 1401da177e4SLinus Torvalds .fatal = 0, 1411da177e4SLinus Torvalds }, 1421da177e4SLinus Torvalds { 1431da177e4SLinus Torvalds .errno = ENETUNREACH, /* ICMP_NET_UNKNOWN */ 1441da177e4SLinus Torvalds .fatal = 1, 1451da177e4SLinus Torvalds }, 1461da177e4SLinus Torvalds { 1471da177e4SLinus Torvalds .errno = EHOSTDOWN, /* ICMP_HOST_UNKNOWN */ 1481da177e4SLinus Torvalds .fatal = 1, 1491da177e4SLinus Torvalds }, 1501da177e4SLinus Torvalds { 1511da177e4SLinus Torvalds .errno = ENONET, /* ICMP_HOST_ISOLATED */ 1521da177e4SLinus Torvalds .fatal = 1, 1531da177e4SLinus Torvalds }, 1541da177e4SLinus Torvalds { 1551da177e4SLinus Torvalds .errno = ENETUNREACH, /* ICMP_NET_ANO */ 1561da177e4SLinus Torvalds .fatal = 1, 1571da177e4SLinus Torvalds }, 1581da177e4SLinus Torvalds { 1591da177e4SLinus Torvalds .errno = EHOSTUNREACH, /* ICMP_HOST_ANO */ 1601da177e4SLinus Torvalds .fatal = 1, 1611da177e4SLinus Torvalds }, 1621da177e4SLinus Torvalds { 1631da177e4SLinus Torvalds .errno = ENETUNREACH, /* ICMP_NET_UNR_TOS */ 1641da177e4SLinus Torvalds .fatal = 0, 1651da177e4SLinus Torvalds }, 1661da177e4SLinus Torvalds { 1671da177e4SLinus Torvalds .errno = EHOSTUNREACH, /* ICMP_HOST_UNR_TOS */ 1681da177e4SLinus Torvalds .fatal = 0, 1691da177e4SLinus Torvalds }, 1701da177e4SLinus Torvalds { 1711da177e4SLinus Torvalds .errno = EHOSTUNREACH, /* ICMP_PKT_FILTERED */ 1721da177e4SLinus Torvalds .fatal = 1, 1731da177e4SLinus Torvalds }, 1741da177e4SLinus Torvalds { 1751da177e4SLinus Torvalds .errno = EHOSTUNREACH, /* ICMP_PREC_VIOLATION */ 1761da177e4SLinus Torvalds .fatal = 1, 1771da177e4SLinus Torvalds }, 1781da177e4SLinus Torvalds { 1791da177e4SLinus Torvalds .errno = EHOSTUNREACH, /* ICMP_PREC_CUTOFF */ 1801da177e4SLinus Torvalds .fatal = 1, 1811da177e4SLinus Torvalds }, 1821da177e4SLinus Torvalds }; 1831da177e4SLinus Torvalds 1841da177e4SLinus Torvalds /* 1851da177e4SLinus Torvalds * ICMP control array. This specifies what to do with each ICMP. 1861da177e4SLinus Torvalds */ 1871da177e4SLinus Torvalds 1881da177e4SLinus Torvalds struct icmp_control { 1891da177e4SLinus Torvalds void (*handler)(struct sk_buff *skb); 1901da177e4SLinus Torvalds short error; /* This ICMP is classed as an error message */ 1911da177e4SLinus Torvalds }; 1921da177e4SLinus Torvalds 1939b5b5cffSArjan van de Ven static const struct icmp_control icmp_pointers[NR_ICMP_TYPES+1]; 1941da177e4SLinus Torvalds 1951da177e4SLinus Torvalds /* 1961da177e4SLinus Torvalds * The ICMP socket(s). This is the most convenient way to flow control 1971da177e4SLinus Torvalds * our ICMP output as well as maintain a clean interface throughout 1981da177e4SLinus Torvalds * all layers. All Socketless IP sends will soon be gone. 1991da177e4SLinus Torvalds * 2001da177e4SLinus Torvalds * On SMP we have one ICMP socket per-cpu. 2011da177e4SLinus Torvalds */ 2024a6ad7a1SDenis V. Lunev static struct sock *icmp_sk(struct net *net) 2034a6ad7a1SDenis V. Lunev { 2044a6ad7a1SDenis V. Lunev return net->ipv4.icmp_sk[smp_processor_id()]; 2054a6ad7a1SDenis V. Lunev } 2061da177e4SLinus Torvalds 207fdc0bde9SDenis V. Lunev static inline struct sock *icmp_xmit_lock(struct net *net) 2081da177e4SLinus Torvalds { 209fdc0bde9SDenis V. Lunev struct sock *sk; 210fdc0bde9SDenis V. Lunev 2111da177e4SLinus Torvalds local_bh_disable(); 2121da177e4SLinus Torvalds 213fdc0bde9SDenis V. Lunev sk = icmp_sk(net); 214fdc0bde9SDenis V. Lunev 215405666dbSDenis V. Lunev if (unlikely(!spin_trylock(&sk->sk_lock.slock))) { 2161da177e4SLinus Torvalds /* This can happen if the output path signals a 2171da177e4SLinus Torvalds * dst_link_failure() for an outgoing ICMP packet. 2181da177e4SLinus Torvalds */ 2191da177e4SLinus Torvalds local_bh_enable(); 220fdc0bde9SDenis V. Lunev return NULL; 2211da177e4SLinus Torvalds } 222fdc0bde9SDenis V. Lunev return sk; 2231da177e4SLinus Torvalds } 2241da177e4SLinus Torvalds 225405666dbSDenis V. Lunev static inline void icmp_xmit_unlock(struct sock *sk) 2261da177e4SLinus Torvalds { 227405666dbSDenis V. Lunev spin_unlock_bh(&sk->sk_lock.slock); 2281da177e4SLinus Torvalds } 2291da177e4SLinus Torvalds 2301da177e4SLinus Torvalds /* 2311da177e4SLinus Torvalds * Send an ICMP frame. 2321da177e4SLinus Torvalds */ 2331da177e4SLinus Torvalds 2341da177e4SLinus Torvalds /* 2351da177e4SLinus Torvalds * Check transmit rate limitation for given message. 2361da177e4SLinus Torvalds * The rate information is held in the destination cache now. 2371da177e4SLinus Torvalds * This function is generic and could be used for other purposes 2381da177e4SLinus Torvalds * too. It uses a Token bucket filter as suggested by Alexey Kuznetsov. 2391da177e4SLinus Torvalds * 2401da177e4SLinus Torvalds * Note that the same dst_entry fields are modified by functions in 2411da177e4SLinus Torvalds * route.c too, but these work for packet destinations while xrlim_allow 2421da177e4SLinus Torvalds * works for icmp destinations. This means the rate limiting information 2431da177e4SLinus Torvalds * for one "ip object" is shared - and these ICMPs are twice limited: 2441da177e4SLinus Torvalds * by source and by destination. 2451da177e4SLinus Torvalds * 2461da177e4SLinus Torvalds * RFC 1812: 4.3.2.8 SHOULD be able to limit error message rate 2471da177e4SLinus Torvalds * SHOULD allow setting of rate limits 2481da177e4SLinus Torvalds * 2491da177e4SLinus Torvalds * Shared between ICMPv4 and ICMPv6. 2501da177e4SLinus Torvalds */ 2511da177e4SLinus Torvalds #define XRLIM_BURST_FACTOR 6 2521da177e4SLinus Torvalds int xrlim_allow(struct dst_entry *dst, int timeout) 2531da177e4SLinus Torvalds { 25469a73829SEric Dumazet unsigned long now, token = dst->rate_tokens; 2551da177e4SLinus Torvalds int rc = 0; 2561da177e4SLinus Torvalds 2571da177e4SLinus Torvalds now = jiffies; 25869a73829SEric Dumazet token += now - dst->rate_last; 2591da177e4SLinus Torvalds dst->rate_last = now; 26069a73829SEric Dumazet if (token > XRLIM_BURST_FACTOR * timeout) 26169a73829SEric Dumazet token = XRLIM_BURST_FACTOR * timeout; 26269a73829SEric Dumazet if (token >= timeout) { 26369a73829SEric Dumazet token -= timeout; 2641da177e4SLinus Torvalds rc = 1; 2651da177e4SLinus Torvalds } 26669a73829SEric Dumazet dst->rate_tokens = token; 2671da177e4SLinus Torvalds return rc; 2681da177e4SLinus Torvalds } 2691da177e4SLinus Torvalds 270b34a95eeSPavel Emelyanov static inline int icmpv4_xrlim_allow(struct net *net, struct rtable *rt, 271b34a95eeSPavel Emelyanov int type, int code) 2721da177e4SLinus Torvalds { 2731da177e4SLinus Torvalds struct dst_entry *dst = &rt->u.dst; 2741da177e4SLinus Torvalds int rc = 1; 2751da177e4SLinus Torvalds 2761da177e4SLinus Torvalds if (type > NR_ICMP_TYPES) 2771da177e4SLinus Torvalds goto out; 2781da177e4SLinus Torvalds 2791da177e4SLinus Torvalds /* Don't limit PMTU discovery. */ 2801da177e4SLinus Torvalds if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) 2811da177e4SLinus Torvalds goto out; 2821da177e4SLinus Torvalds 2831da177e4SLinus Torvalds /* No rate limit on loopback */ 2841da177e4SLinus Torvalds if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) 2851da177e4SLinus Torvalds goto out; 2861da177e4SLinus Torvalds 2871da177e4SLinus Torvalds /* Limit if icmp type is enabled in ratemask. */ 288b34a95eeSPavel Emelyanov if ((1 << type) & net->ipv4.sysctl_icmp_ratemask) 289b34a95eeSPavel Emelyanov rc = xrlim_allow(dst, net->ipv4.sysctl_icmp_ratelimit); 2901da177e4SLinus Torvalds out: 2911da177e4SLinus Torvalds return rc; 2921da177e4SLinus Torvalds } 2931da177e4SLinus Torvalds 2941da177e4SLinus Torvalds /* 2951da177e4SLinus Torvalds * Maintain the counters used in the SNMP statistics for outgoing ICMP 2961da177e4SLinus Torvalds */ 2970388b004SPavel Emelyanov void icmp_out_count(struct net *net, unsigned char type) 2981da177e4SLinus Torvalds { 299903fc196SPavel Emelyanov ICMPMSGOUT_INC_STATS(net, type); 30075c939bbSPavel Emelyanov ICMP_INC_STATS(net, ICMP_MIB_OUTMSGS); 3011da177e4SLinus Torvalds } 3021da177e4SLinus Torvalds 3031da177e4SLinus Torvalds /* 3041da177e4SLinus Torvalds * Checksum each fragment, and on the first include the headers and final 3051da177e4SLinus Torvalds * checksum. 3061da177e4SLinus Torvalds */ 3071da177e4SLinus Torvalds static int icmp_glue_bits(void *from, char *to, int offset, int len, int odd, 3081da177e4SLinus Torvalds struct sk_buff *skb) 3091da177e4SLinus Torvalds { 3101da177e4SLinus Torvalds struct icmp_bxm *icmp_param = (struct icmp_bxm *)from; 3115f92a738SAl Viro __wsum csum; 3121da177e4SLinus Torvalds 3131da177e4SLinus Torvalds csum = skb_copy_and_csum_bits(icmp_param->skb, 3141da177e4SLinus Torvalds icmp_param->offset + offset, 3151da177e4SLinus Torvalds to, len, 0); 3161da177e4SLinus Torvalds 3171da177e4SLinus Torvalds skb->csum = csum_block_add(skb->csum, csum, odd); 3181da177e4SLinus Torvalds if (icmp_pointers[icmp_param->data.icmph.type].error) 3191da177e4SLinus Torvalds nf_ct_attach(skb, icmp_param->skb); 3201da177e4SLinus Torvalds return 0; 3211da177e4SLinus Torvalds } 3221da177e4SLinus Torvalds 3231da177e4SLinus Torvalds static void icmp_push_reply(struct icmp_bxm *icmp_param, 3242e77d89bSEric Dumazet struct ipcm_cookie *ipc, struct rtable **rt) 3251da177e4SLinus Torvalds { 3261e3cf683SDenis V. Lunev struct sock *sk; 3271da177e4SLinus Torvalds struct sk_buff *skb; 3281da177e4SLinus Torvalds 3292e77d89bSEric Dumazet sk = icmp_sk(dev_net((*rt)->u.dst.dev)); 3301e3cf683SDenis V. Lunev if (ip_append_data(sk, icmp_glue_bits, icmp_param, 3311da177e4SLinus Torvalds icmp_param->data_len+icmp_param->head_len, 3321da177e4SLinus Torvalds icmp_param->head_len, 333cb94c62cSPatrick McHardy ipc, rt, MSG_DONTWAIT) < 0) 3341e3cf683SDenis V. Lunev ip_flush_pending_frames(sk); 3351e3cf683SDenis V. Lunev else if ((skb = skb_peek(&sk->sk_write_queue)) != NULL) { 33688c7664fSArnaldo Carvalho de Melo struct icmphdr *icmph = icmp_hdr(skb); 337d3bc23e7SAl Viro __wsum csum = 0; 3381da177e4SLinus Torvalds struct sk_buff *skb1; 3391da177e4SLinus Torvalds 3401e3cf683SDenis V. Lunev skb_queue_walk(&sk->sk_write_queue, skb1) { 3411da177e4SLinus Torvalds csum = csum_add(csum, skb1->csum); 3421da177e4SLinus Torvalds } 3431da177e4SLinus Torvalds csum = csum_partial_copy_nocheck((void *)&icmp_param->data, 3441da177e4SLinus Torvalds (char *)icmph, 3451da177e4SLinus Torvalds icmp_param->head_len, csum); 3461da177e4SLinus Torvalds icmph->checksum = csum_fold(csum); 3471da177e4SLinus Torvalds skb->ip_summed = CHECKSUM_NONE; 3481e3cf683SDenis V. Lunev ip_push_pending_frames(sk); 3491da177e4SLinus Torvalds } 3501da177e4SLinus Torvalds } 3511da177e4SLinus Torvalds 3521da177e4SLinus Torvalds /* 3531da177e4SLinus Torvalds * Driving logic for building and sending ICMP messages. 3541da177e4SLinus Torvalds */ 3551da177e4SLinus Torvalds 3561da177e4SLinus Torvalds static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) 3571da177e4SLinus Torvalds { 3581da177e4SLinus Torvalds struct ipcm_cookie ipc; 359*511c3f92SEric Dumazet struct rtable *rt = skb_rtable(skb); 360c346dca1SYOSHIFUJI Hideaki struct net *net = dev_net(rt->u.dst.dev); 361fdc0bde9SDenis V. Lunev struct sock *sk; 362fdc0bde9SDenis V. Lunev struct inet_sock *inet; 3633ca3c68eSAl Viro __be32 daddr; 3641da177e4SLinus Torvalds 3651da177e4SLinus Torvalds if (ip_options_echo(&icmp_param->replyopts, skb)) 366f00c401bSHorms return; 3671da177e4SLinus Torvalds 368fdc0bde9SDenis V. Lunev sk = icmp_xmit_lock(net); 369fdc0bde9SDenis V. Lunev if (sk == NULL) 3701da177e4SLinus Torvalds return; 371fdc0bde9SDenis V. Lunev inet = inet_sk(sk); 3721da177e4SLinus Torvalds 3731da177e4SLinus Torvalds icmp_param->data.icmph.checksum = 0; 3741da177e4SLinus Torvalds 375eddc9ec5SArnaldo Carvalho de Melo inet->tos = ip_hdr(skb)->tos; 3761da177e4SLinus Torvalds daddr = ipc.addr = rt->rt_src; 3771da177e4SLinus Torvalds ipc.opt = NULL; 37851f31cabSPatrick Ohly ipc.shtx.flags = 0; 3791da177e4SLinus Torvalds if (icmp_param->replyopts.optlen) { 3801da177e4SLinus Torvalds ipc.opt = &icmp_param->replyopts; 3811da177e4SLinus Torvalds if (ipc.opt->srr) 3821da177e4SLinus Torvalds daddr = icmp_param->replyopts.faddr; 3831da177e4SLinus Torvalds } 3841da177e4SLinus Torvalds { 3851da177e4SLinus Torvalds struct flowi fl = { .nl_u = { .ip4_u = 3861da177e4SLinus Torvalds { .daddr = daddr, 3871da177e4SLinus Torvalds .saddr = rt->rt_spec_dst, 388eddc9ec5SArnaldo Carvalho de Melo .tos = RT_TOS(ip_hdr(skb)->tos) } }, 3891da177e4SLinus Torvalds .proto = IPPROTO_ICMP }; 390beb8d13bSVenkat Yekkirala security_skb_classify_flow(skb, &fl); 3914a6ad7a1SDenis V. Lunev if (ip_route_output_key(net, &rt, &fl)) 3921da177e4SLinus Torvalds goto out_unlock; 3931da177e4SLinus Torvalds } 394b34a95eeSPavel Emelyanov if (icmpv4_xrlim_allow(net, rt, icmp_param->data.icmph.type, 3951da177e4SLinus Torvalds icmp_param->data.icmph.code)) 3962e77d89bSEric Dumazet icmp_push_reply(icmp_param, &ipc, &rt); 3971da177e4SLinus Torvalds ip_rt_put(rt); 3981da177e4SLinus Torvalds out_unlock: 399405666dbSDenis V. Lunev icmp_xmit_unlock(sk); 4001da177e4SLinus Torvalds } 4011da177e4SLinus Torvalds 4021da177e4SLinus Torvalds 4031da177e4SLinus Torvalds /* 4041da177e4SLinus Torvalds * Send an ICMP message in response to a situation 4051da177e4SLinus Torvalds * 4061da177e4SLinus Torvalds * RFC 1122: 3.2.2 MUST send at least the IP header and 8 bytes of header. 4071da177e4SLinus Torvalds * MAY send more (we do). 4081da177e4SLinus Torvalds * MUST NOT change this header information. 4091da177e4SLinus Torvalds * MUST NOT reply to a multicast/broadcast IP address. 4101da177e4SLinus Torvalds * MUST NOT reply to a multicast/broadcast MAC address. 4111da177e4SLinus Torvalds * MUST reply to only the first fragment. 4121da177e4SLinus Torvalds */ 4131da177e4SLinus Torvalds 414e4883014SAl Viro void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) 4151da177e4SLinus Torvalds { 4161da177e4SLinus Torvalds struct iphdr *iph; 4171da177e4SLinus Torvalds int room; 4181da177e4SLinus Torvalds struct icmp_bxm icmp_param; 419*511c3f92SEric Dumazet struct rtable *rt = skb_rtable(skb_in); 4201da177e4SLinus Torvalds struct ipcm_cookie ipc; 421a61ced5dSAl Viro __be32 saddr; 4221da177e4SLinus Torvalds u8 tos; 423dde1bc0eSDenis V. Lunev struct net *net; 4244a6ad7a1SDenis V. Lunev struct sock *sk; 4251da177e4SLinus Torvalds 4261da177e4SLinus Torvalds if (!rt) 4271da177e4SLinus Torvalds goto out; 428c346dca1SYOSHIFUJI Hideaki net = dev_net(rt->u.dst.dev); 4291da177e4SLinus Torvalds 4301da177e4SLinus Torvalds /* 4311da177e4SLinus Torvalds * Find the original header. It is expected to be valid, of course. 4321da177e4SLinus Torvalds * Check this, icmp_send is called from the most obscure devices 4331da177e4SLinus Torvalds * sometimes. 4341da177e4SLinus Torvalds */ 435eddc9ec5SArnaldo Carvalho de Melo iph = ip_hdr(skb_in); 4361da177e4SLinus Torvalds 43727a884dcSArnaldo Carvalho de Melo if ((u8 *)iph < skb_in->head || 43827a884dcSArnaldo Carvalho de Melo (skb_in->network_header + sizeof(*iph)) > skb_in->tail) 4391da177e4SLinus Torvalds goto out; 4401da177e4SLinus Torvalds 4411da177e4SLinus Torvalds /* 4421da177e4SLinus Torvalds * No replies to physical multicast/broadcast 4431da177e4SLinus Torvalds */ 4441da177e4SLinus Torvalds if (skb_in->pkt_type != PACKET_HOST) 4451da177e4SLinus Torvalds goto out; 4461da177e4SLinus Torvalds 4471da177e4SLinus Torvalds /* 4481da177e4SLinus Torvalds * Now check at the protocol level 4491da177e4SLinus Torvalds */ 4501da177e4SLinus Torvalds if (rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) 4511da177e4SLinus Torvalds goto out; 4521da177e4SLinus Torvalds 4531da177e4SLinus Torvalds /* 4541da177e4SLinus Torvalds * Only reply to fragment 0. We byte re-order the constant 4551da177e4SLinus Torvalds * mask for efficiency. 4561da177e4SLinus Torvalds */ 4571da177e4SLinus Torvalds if (iph->frag_off & htons(IP_OFFSET)) 4581da177e4SLinus Torvalds goto out; 4591da177e4SLinus Torvalds 4601da177e4SLinus Torvalds /* 4611da177e4SLinus Torvalds * If we send an ICMP error to an ICMP error a mess would result.. 4621da177e4SLinus Torvalds */ 4631da177e4SLinus Torvalds if (icmp_pointers[type].error) { 4641da177e4SLinus Torvalds /* 4651da177e4SLinus Torvalds * We are an error, check if we are replying to an 4661da177e4SLinus Torvalds * ICMP error 4671da177e4SLinus Torvalds */ 4681da177e4SLinus Torvalds if (iph->protocol == IPPROTO_ICMP) { 4691da177e4SLinus Torvalds u8 _inner_type, *itp; 4701da177e4SLinus Torvalds 4711da177e4SLinus Torvalds itp = skb_header_pointer(skb_in, 472d56f90a7SArnaldo Carvalho de Melo skb_network_header(skb_in) + 4731da177e4SLinus Torvalds (iph->ihl << 2) + 4741da177e4SLinus Torvalds offsetof(struct icmphdr, 4751da177e4SLinus Torvalds type) - 4761da177e4SLinus Torvalds skb_in->data, 4771da177e4SLinus Torvalds sizeof(_inner_type), 4781da177e4SLinus Torvalds &_inner_type); 4791da177e4SLinus Torvalds if (itp == NULL) 4801da177e4SLinus Torvalds goto out; 4811da177e4SLinus Torvalds 4821da177e4SLinus Torvalds /* 4831da177e4SLinus Torvalds * Assume any unknown ICMP type is an error. This 4841da177e4SLinus Torvalds * isn't specified by the RFC, but think about it.. 4851da177e4SLinus Torvalds */ 4861da177e4SLinus Torvalds if (*itp > NR_ICMP_TYPES || 4871da177e4SLinus Torvalds icmp_pointers[*itp].error) 4881da177e4SLinus Torvalds goto out; 4891da177e4SLinus Torvalds } 4901da177e4SLinus Torvalds } 4911da177e4SLinus Torvalds 492fdc0bde9SDenis V. Lunev sk = icmp_xmit_lock(net); 493fdc0bde9SDenis V. Lunev if (sk == NULL) 4941da177e4SLinus Torvalds return; 4951da177e4SLinus Torvalds 4961da177e4SLinus Torvalds /* 4971da177e4SLinus Torvalds * Construct source address and options. 4981da177e4SLinus Torvalds */ 4991da177e4SLinus Torvalds 5001da177e4SLinus Torvalds saddr = iph->daddr; 5011c2fb7f9SJ. Simonetti if (!(rt->rt_flags & RTCF_LOCAL)) { 5026e1d9103SPatrick McHardy struct net_device *dev = NULL; 5036e1d9103SPatrick McHardy 504a24022e1SPavel Emelyanov if (rt->fl.iif && 505b34a95eeSPavel Emelyanov net->ipv4.sysctl_icmp_errors_use_inbound_ifaddr) 506dde1bc0eSDenis V. Lunev dev = dev_get_by_index(net, rt->fl.iif); 5076e1d9103SPatrick McHardy 5086e1d9103SPatrick McHardy if (dev) { 5096e1d9103SPatrick McHardy saddr = inet_select_addr(dev, 0, RT_SCOPE_LINK); 5106e1d9103SPatrick McHardy dev_put(dev); 5116e1d9103SPatrick McHardy } else 5121da177e4SLinus Torvalds saddr = 0; 5131c2fb7f9SJ. Simonetti } 5141da177e4SLinus Torvalds 5151da177e4SLinus Torvalds tos = icmp_pointers[type].error ? ((iph->tos & IPTOS_TOS_MASK) | 5161da177e4SLinus Torvalds IPTOS_PREC_INTERNETCONTROL) : 5171da177e4SLinus Torvalds iph->tos; 5181da177e4SLinus Torvalds 5191da177e4SLinus Torvalds if (ip_options_echo(&icmp_param.replyopts, skb_in)) 520fa60cf7fSHerbert Xu goto out_unlock; 5211da177e4SLinus Torvalds 5221da177e4SLinus Torvalds 5231da177e4SLinus Torvalds /* 5241da177e4SLinus Torvalds * Prepare data for ICMP header. 5251da177e4SLinus Torvalds */ 5261da177e4SLinus Torvalds 5271da177e4SLinus Torvalds icmp_param.data.icmph.type = type; 5281da177e4SLinus Torvalds icmp_param.data.icmph.code = code; 5291da177e4SLinus Torvalds icmp_param.data.icmph.un.gateway = info; 5301da177e4SLinus Torvalds icmp_param.data.icmph.checksum = 0; 5311da177e4SLinus Torvalds icmp_param.skb = skb_in; 532d56f90a7SArnaldo Carvalho de Melo icmp_param.offset = skb_network_offset(skb_in); 533405666dbSDenis V. Lunev inet_sk(sk)->tos = tos; 5341da177e4SLinus Torvalds ipc.addr = iph->saddr; 5351da177e4SLinus Torvalds ipc.opt = &icmp_param.replyopts; 53651f31cabSPatrick Ohly ipc.shtx.flags = 0; 5371da177e4SLinus Torvalds 5381da177e4SLinus Torvalds { 5391da177e4SLinus Torvalds struct flowi fl = { 5401da177e4SLinus Torvalds .nl_u = { 5411da177e4SLinus Torvalds .ip4_u = { 5421da177e4SLinus Torvalds .daddr = icmp_param.replyopts.srr ? 5431da177e4SLinus Torvalds icmp_param.replyopts.faddr : 5441da177e4SLinus Torvalds iph->saddr, 5451da177e4SLinus Torvalds .saddr = saddr, 5461da177e4SLinus Torvalds .tos = RT_TOS(tos) 5471da177e4SLinus Torvalds } 5481da177e4SLinus Torvalds }, 5491da177e4SLinus Torvalds .proto = IPPROTO_ICMP, 5501da177e4SLinus Torvalds .uli_u = { 5511da177e4SLinus Torvalds .icmpt = { 5521da177e4SLinus Torvalds .type = type, 5531da177e4SLinus Torvalds .code = code 5541da177e4SLinus Torvalds } 5551da177e4SLinus Torvalds } 5561da177e4SLinus Torvalds }; 5578b7817f3SHerbert Xu int err; 5588b7817f3SHerbert Xu struct rtable *rt2; 5598b7817f3SHerbert Xu 560beb8d13bSVenkat Yekkirala security_skb_classify_flow(skb_in, &fl); 561dde1bc0eSDenis V. Lunev if (__ip_route_output_key(net, &rt, &fl)) 5628b7817f3SHerbert Xu goto out_unlock; 5638b7817f3SHerbert Xu 5648b7817f3SHerbert Xu /* No need to clone since we're just using its address. */ 5658b7817f3SHerbert Xu rt2 = rt; 5668b7817f3SHerbert Xu 56752479b62SAlexey Dobriyan err = xfrm_lookup(net, (struct dst_entry **)&rt, &fl, NULL, 0); 5688b7817f3SHerbert Xu switch (err) { 5698b7817f3SHerbert Xu case 0: 5708b7817f3SHerbert Xu if (rt != rt2) 5718b7817f3SHerbert Xu goto route_done; 5728b7817f3SHerbert Xu break; 5738b7817f3SHerbert Xu case -EPERM: 5748b7817f3SHerbert Xu rt = NULL; 5758b7817f3SHerbert Xu break; 5768b7817f3SHerbert Xu default: 5771da177e4SLinus Torvalds goto out_unlock; 5781da177e4SLinus Torvalds } 5791da177e4SLinus Torvalds 5808b7817f3SHerbert Xu if (xfrm_decode_session_reverse(skb_in, &fl, AF_INET)) 581af268182SHerbert Xu goto relookup_failed; 5828b7817f3SHerbert Xu 583dde1bc0eSDenis V. Lunev if (inet_addr_type(net, fl.fl4_src) == RTN_LOCAL) 584dde1bc0eSDenis V. Lunev err = __ip_route_output_key(net, &rt2, &fl); 5858b7817f3SHerbert Xu else { 5868b7817f3SHerbert Xu struct flowi fl2 = {}; 5878b7817f3SHerbert Xu struct dst_entry *odst; 5888b7817f3SHerbert Xu 5898b7817f3SHerbert Xu fl2.fl4_dst = fl.fl4_src; 590dde1bc0eSDenis V. Lunev if (ip_route_output_key(net, &rt2, &fl2)) 591af268182SHerbert Xu goto relookup_failed; 5928b7817f3SHerbert Xu 5938b7817f3SHerbert Xu /* Ugh! */ 5948b7817f3SHerbert Xu odst = skb_in->dst; 5958b7817f3SHerbert Xu err = ip_route_input(skb_in, fl.fl4_dst, fl.fl4_src, 5968b7817f3SHerbert Xu RT_TOS(tos), rt2->u.dst.dev); 5978b7817f3SHerbert Xu 5988b7817f3SHerbert Xu dst_release(&rt2->u.dst); 599*511c3f92SEric Dumazet rt2 = skb_rtable(skb_in); 6008b7817f3SHerbert Xu skb_in->dst = odst; 6018b7817f3SHerbert Xu } 6028b7817f3SHerbert Xu 6038b7817f3SHerbert Xu if (err) 604af268182SHerbert Xu goto relookup_failed; 6058b7817f3SHerbert Xu 60652479b62SAlexey Dobriyan err = xfrm_lookup(net, (struct dst_entry **)&rt2, &fl, NULL, 6078b7817f3SHerbert Xu XFRM_LOOKUP_ICMP); 608af268182SHerbert Xu switch (err) { 609af268182SHerbert Xu case 0: 6108b7817f3SHerbert Xu dst_release(&rt->u.dst); 6118b7817f3SHerbert Xu rt = rt2; 612af268182SHerbert Xu break; 613af268182SHerbert Xu case -EPERM: 614af268182SHerbert Xu goto ende; 615af268182SHerbert Xu default: 616af268182SHerbert Xu relookup_failed: 617af268182SHerbert Xu if (!rt) 6188b7817f3SHerbert Xu goto out_unlock; 619af268182SHerbert Xu break; 620af268182SHerbert Xu } 6218b7817f3SHerbert Xu } 6228b7817f3SHerbert Xu 6238b7817f3SHerbert Xu route_done: 624b34a95eeSPavel Emelyanov if (!icmpv4_xrlim_allow(net, rt, type, code)) 6251da177e4SLinus Torvalds goto ende; 6261da177e4SLinus Torvalds 6271da177e4SLinus Torvalds /* RFC says return as much as we can without exceeding 576 bytes. */ 6281da177e4SLinus Torvalds 6291da177e4SLinus Torvalds room = dst_mtu(&rt->u.dst); 6301da177e4SLinus Torvalds if (room > 576) 6311da177e4SLinus Torvalds room = 576; 6321da177e4SLinus Torvalds room -= sizeof(struct iphdr) + icmp_param.replyopts.optlen; 6331da177e4SLinus Torvalds room -= sizeof(struct icmphdr); 6341da177e4SLinus Torvalds 6351da177e4SLinus Torvalds icmp_param.data_len = skb_in->len - icmp_param.offset; 6361da177e4SLinus Torvalds if (icmp_param.data_len > room) 6371da177e4SLinus Torvalds icmp_param.data_len = room; 6381da177e4SLinus Torvalds icmp_param.head_len = sizeof(struct icmphdr); 6391da177e4SLinus Torvalds 6402e77d89bSEric Dumazet icmp_push_reply(&icmp_param, &ipc, &rt); 6411da177e4SLinus Torvalds ende: 6421da177e4SLinus Torvalds ip_rt_put(rt); 6431da177e4SLinus Torvalds out_unlock: 644405666dbSDenis V. Lunev icmp_xmit_unlock(sk); 6451da177e4SLinus Torvalds out:; 6461da177e4SLinus Torvalds } 6471da177e4SLinus Torvalds 6481da177e4SLinus Torvalds 6491da177e4SLinus Torvalds /* 6501da177e4SLinus Torvalds * Handle ICMP_DEST_UNREACH, ICMP_TIME_EXCEED, and ICMP_QUENCH. 6511da177e4SLinus Torvalds */ 6521da177e4SLinus Torvalds 6531da177e4SLinus Torvalds static void icmp_unreach(struct sk_buff *skb) 6541da177e4SLinus Torvalds { 6551da177e4SLinus Torvalds struct iphdr *iph; 6561da177e4SLinus Torvalds struct icmphdr *icmph; 6571da177e4SLinus Torvalds int hash, protocol; 6581da177e4SLinus Torvalds struct net_protocol *ipprot; 6591da177e4SLinus Torvalds u32 info = 0; 660dde1bc0eSDenis V. Lunev struct net *net; 661dde1bc0eSDenis V. Lunev 662c346dca1SYOSHIFUJI Hideaki net = dev_net(skb->dst->dev); 6631da177e4SLinus Torvalds 6641da177e4SLinus Torvalds /* 6651da177e4SLinus Torvalds * Incomplete header ? 6661da177e4SLinus Torvalds * Only checks for the IP header, there should be an 6671da177e4SLinus Torvalds * additional check for longer headers in upper levels. 6681da177e4SLinus Torvalds */ 6691da177e4SLinus Torvalds 6701da177e4SLinus Torvalds if (!pskb_may_pull(skb, sizeof(struct iphdr))) 6711da177e4SLinus Torvalds goto out_err; 6721da177e4SLinus Torvalds 67388c7664fSArnaldo Carvalho de Melo icmph = icmp_hdr(skb); 6741da177e4SLinus Torvalds iph = (struct iphdr *)skb->data; 6751da177e4SLinus Torvalds 6761da177e4SLinus Torvalds if (iph->ihl < 5) /* Mangled header, drop. */ 6771da177e4SLinus Torvalds goto out_err; 6781da177e4SLinus Torvalds 6791da177e4SLinus Torvalds if (icmph->type == ICMP_DEST_UNREACH) { 6801da177e4SLinus Torvalds switch (icmph->code & 15) { 6811da177e4SLinus Torvalds case ICMP_NET_UNREACH: 6821da177e4SLinus Torvalds case ICMP_HOST_UNREACH: 6831da177e4SLinus Torvalds case ICMP_PROT_UNREACH: 6841da177e4SLinus Torvalds case ICMP_PORT_UNREACH: 6851da177e4SLinus Torvalds break; 6861da177e4SLinus Torvalds case ICMP_FRAG_NEEDED: 6871da177e4SLinus Torvalds if (ipv4_config.no_pmtu_disc) { 688673d57e7SHarvey Harrison LIMIT_NETDEBUG(KERN_INFO "ICMP: %pI4: fragmentation needed and DF set.\n", 689673d57e7SHarvey Harrison &iph->daddr); 6901da177e4SLinus Torvalds } else { 691dde1bc0eSDenis V. Lunev info = ip_rt_frag_needed(net, iph, 6920010e465STimo Teras ntohs(icmph->un.frag.mtu), 6930010e465STimo Teras skb->dev); 6941da177e4SLinus Torvalds if (!info) 6951da177e4SLinus Torvalds goto out; 6961da177e4SLinus Torvalds } 6971da177e4SLinus Torvalds break; 6981da177e4SLinus Torvalds case ICMP_SR_FAILED: 699673d57e7SHarvey Harrison LIMIT_NETDEBUG(KERN_INFO "ICMP: %pI4: Source Route Failed.\n", 700673d57e7SHarvey Harrison &iph->daddr); 7011da177e4SLinus Torvalds break; 7021da177e4SLinus Torvalds default: 7031da177e4SLinus Torvalds break; 7041da177e4SLinus Torvalds } 7051da177e4SLinus Torvalds if (icmph->code > NR_ICMP_UNREACH) 7061da177e4SLinus Torvalds goto out; 7071da177e4SLinus Torvalds } else if (icmph->type == ICMP_PARAMETERPROB) 7081da177e4SLinus Torvalds info = ntohl(icmph->un.gateway) >> 24; 7091da177e4SLinus Torvalds 7101da177e4SLinus Torvalds /* 7111da177e4SLinus Torvalds * Throw it at our lower layers 7121da177e4SLinus Torvalds * 7131da177e4SLinus Torvalds * RFC 1122: 3.2.2 MUST extract the protocol ID from the passed 7141da177e4SLinus Torvalds * header. 7151da177e4SLinus Torvalds * RFC 1122: 3.2.2.1 MUST pass ICMP unreach messages to the 7161da177e4SLinus Torvalds * transport layer. 7171da177e4SLinus Torvalds * RFC 1122: 3.2.2.2 MUST pass ICMP time expired messages to 7181da177e4SLinus Torvalds * transport layer. 7191da177e4SLinus Torvalds */ 7201da177e4SLinus Torvalds 7211da177e4SLinus Torvalds /* 7221da177e4SLinus Torvalds * Check the other end isnt violating RFC 1122. Some routers send 7231da177e4SLinus Torvalds * bogus responses to broadcast frames. If you see this message 7241da177e4SLinus Torvalds * first check your netmask matches at both ends, if it does then 7251da177e4SLinus Torvalds * get the other vendor to fix their kit. 7261da177e4SLinus Torvalds */ 7271da177e4SLinus Torvalds 728b34a95eeSPavel Emelyanov if (!net->ipv4.sysctl_icmp_ignore_bogus_error_responses && 729dde1bc0eSDenis V. Lunev inet_addr_type(net, iph->daddr) == RTN_BROADCAST) { 7301da177e4SLinus Torvalds if (net_ratelimit()) 731673d57e7SHarvey Harrison printk(KERN_WARNING "%pI4 sent an invalid ICMP " 7321da177e4SLinus Torvalds "type %u, code %u " 733673d57e7SHarvey Harrison "error to a broadcast: %pI4 on %s\n", 734673d57e7SHarvey Harrison &ip_hdr(skb)->saddr, 7351da177e4SLinus Torvalds icmph->type, icmph->code, 736673d57e7SHarvey Harrison &iph->daddr, 7371da177e4SLinus Torvalds skb->dev->name); 7381da177e4SLinus Torvalds goto out; 7391da177e4SLinus Torvalds } 7401da177e4SLinus Torvalds 7411da177e4SLinus Torvalds /* Checkin full IP header plus 8 bytes of protocol to 7421da177e4SLinus Torvalds * avoid additional coding at protocol handlers. 7431da177e4SLinus Torvalds */ 7441da177e4SLinus Torvalds if (!pskb_may_pull(skb, iph->ihl * 4 + 8)) 7451da177e4SLinus Torvalds goto out; 7461da177e4SLinus Torvalds 7471da177e4SLinus Torvalds iph = (struct iphdr *)skb->data; 7481da177e4SLinus Torvalds protocol = iph->protocol; 7491da177e4SLinus Torvalds 7501da177e4SLinus Torvalds /* 7511da177e4SLinus Torvalds * Deliver ICMP message to raw sockets. Pretty useless feature? 7521da177e4SLinus Torvalds */ 7537bc54c90SPavel Emelyanov raw_icmp_error(skb, protocol, info); 7541da177e4SLinus Torvalds 7551da177e4SLinus Torvalds hash = protocol & (MAX_INET_PROTOS - 1); 7561da177e4SLinus Torvalds rcu_read_lock(); 7571da177e4SLinus Torvalds ipprot = rcu_dereference(inet_protos[hash]); 7581da177e4SLinus Torvalds if (ipprot && ipprot->err_handler) 7591da177e4SLinus Torvalds ipprot->err_handler(skb, info); 7601da177e4SLinus Torvalds rcu_read_unlock(); 7611da177e4SLinus Torvalds 7621da177e4SLinus Torvalds out: 7631da177e4SLinus Torvalds return; 7641da177e4SLinus Torvalds out_err: 765dcfc23caSPavel Emelyanov ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); 7661da177e4SLinus Torvalds goto out; 7671da177e4SLinus Torvalds } 7681da177e4SLinus Torvalds 7691da177e4SLinus Torvalds 7701da177e4SLinus Torvalds /* 7711da177e4SLinus Torvalds * Handle ICMP_REDIRECT. 7721da177e4SLinus Torvalds */ 7731da177e4SLinus Torvalds 7741da177e4SLinus Torvalds static void icmp_redirect(struct sk_buff *skb) 7751da177e4SLinus Torvalds { 7761da177e4SLinus Torvalds struct iphdr *iph; 7771da177e4SLinus Torvalds 7781da177e4SLinus Torvalds if (skb->len < sizeof(struct iphdr)) 7791da177e4SLinus Torvalds goto out_err; 7801da177e4SLinus Torvalds 7811da177e4SLinus Torvalds /* 7821da177e4SLinus Torvalds * Get the copied header of the packet that caused the redirect 7831da177e4SLinus Torvalds */ 7841da177e4SLinus Torvalds if (!pskb_may_pull(skb, sizeof(struct iphdr))) 7851da177e4SLinus Torvalds goto out; 7861da177e4SLinus Torvalds 7871da177e4SLinus Torvalds iph = (struct iphdr *)skb->data; 7881da177e4SLinus Torvalds 78988c7664fSArnaldo Carvalho de Melo switch (icmp_hdr(skb)->code & 7) { 7901da177e4SLinus Torvalds case ICMP_REDIR_NET: 7911da177e4SLinus Torvalds case ICMP_REDIR_NETTOS: 7921da177e4SLinus Torvalds /* 7931da177e4SLinus Torvalds * As per RFC recommendations now handle it as a host redirect. 7941da177e4SLinus Torvalds */ 7951da177e4SLinus Torvalds case ICMP_REDIR_HOST: 7961da177e4SLinus Torvalds case ICMP_REDIR_HOSTTOS: 797eddc9ec5SArnaldo Carvalho de Melo ip_rt_redirect(ip_hdr(skb)->saddr, iph->daddr, 79888c7664fSArnaldo Carvalho de Melo icmp_hdr(skb)->un.gateway, 799cef2685eSIlia Sotnikov iph->saddr, skb->dev); 8001da177e4SLinus Torvalds break; 8011da177e4SLinus Torvalds } 8021da177e4SLinus Torvalds out: 8031da177e4SLinus Torvalds return; 8041da177e4SLinus Torvalds out_err: 805dcfc23caSPavel Emelyanov ICMP_INC_STATS_BH(dev_net(skb->dev), ICMP_MIB_INERRORS); 8061da177e4SLinus Torvalds goto out; 8071da177e4SLinus Torvalds } 8081da177e4SLinus Torvalds 8091da177e4SLinus Torvalds /* 8101da177e4SLinus Torvalds * Handle ICMP_ECHO ("ping") requests. 8111da177e4SLinus Torvalds * 8121da177e4SLinus Torvalds * RFC 1122: 3.2.2.6 MUST have an echo server that answers ICMP echo 8131da177e4SLinus Torvalds * requests. 8141da177e4SLinus Torvalds * RFC 1122: 3.2.2.6 Data received in the ICMP_ECHO request MUST be 8151da177e4SLinus Torvalds * included in the reply. 8161da177e4SLinus Torvalds * RFC 1812: 4.3.3.6 SHOULD have a config option for silently ignoring 8171da177e4SLinus Torvalds * echo requests, MUST have default=NOT. 8181da177e4SLinus Torvalds * See also WRT handling of options once they are done and working. 8191da177e4SLinus Torvalds */ 8201da177e4SLinus Torvalds 8211da177e4SLinus Torvalds static void icmp_echo(struct sk_buff *skb) 8221da177e4SLinus Torvalds { 823b34a95eeSPavel Emelyanov struct net *net; 824b34a95eeSPavel Emelyanov 825789e41e6SPavel Emelyanov net = dev_net(skb->dst->dev); 826b34a95eeSPavel Emelyanov if (!net->ipv4.sysctl_icmp_echo_ignore_all) { 8271da177e4SLinus Torvalds struct icmp_bxm icmp_param; 8281da177e4SLinus Torvalds 82988c7664fSArnaldo Carvalho de Melo icmp_param.data.icmph = *icmp_hdr(skb); 8301da177e4SLinus Torvalds icmp_param.data.icmph.type = ICMP_ECHOREPLY; 8311da177e4SLinus Torvalds icmp_param.skb = skb; 8321da177e4SLinus Torvalds icmp_param.offset = 0; 8331da177e4SLinus Torvalds icmp_param.data_len = skb->len; 8341da177e4SLinus Torvalds icmp_param.head_len = sizeof(struct icmphdr); 8351da177e4SLinus Torvalds icmp_reply(&icmp_param, skb); 8361da177e4SLinus Torvalds } 8371da177e4SLinus Torvalds } 8381da177e4SLinus Torvalds 8391da177e4SLinus Torvalds /* 8401da177e4SLinus Torvalds * Handle ICMP Timestamp requests. 8411da177e4SLinus Torvalds * RFC 1122: 3.2.2.8 MAY implement ICMP timestamp requests. 8421da177e4SLinus Torvalds * SHOULD be in the kernel for minimum random latency. 8431da177e4SLinus Torvalds * MUST be accurate to a few minutes. 8441da177e4SLinus Torvalds * MUST be updated at least at 15Hz. 8451da177e4SLinus Torvalds */ 8461da177e4SLinus Torvalds static void icmp_timestamp(struct sk_buff *skb) 8471da177e4SLinus Torvalds { 848f25c3d61SYOSHIFUJI Hideaki struct timespec tv; 8491da177e4SLinus Torvalds struct icmp_bxm icmp_param; 8501da177e4SLinus Torvalds /* 8511da177e4SLinus Torvalds * Too short. 8521da177e4SLinus Torvalds */ 8531da177e4SLinus Torvalds if (skb->len < 4) 8541da177e4SLinus Torvalds goto out_err; 8551da177e4SLinus Torvalds 8561da177e4SLinus Torvalds /* 8571da177e4SLinus Torvalds * Fill in the current time as ms since midnight UT: 8581da177e4SLinus Torvalds */ 859f25c3d61SYOSHIFUJI Hideaki getnstimeofday(&tv); 860f25c3d61SYOSHIFUJI Hideaki icmp_param.data.times[1] = htonl((tv.tv_sec % 86400) * MSEC_PER_SEC + 861f25c3d61SYOSHIFUJI Hideaki tv.tv_nsec / NSEC_PER_MSEC); 8621da177e4SLinus Torvalds icmp_param.data.times[2] = icmp_param.data.times[1]; 8631da177e4SLinus Torvalds if (skb_copy_bits(skb, 0, &icmp_param.data.times[0], 4)) 8641da177e4SLinus Torvalds BUG(); 86588c7664fSArnaldo Carvalho de Melo icmp_param.data.icmph = *icmp_hdr(skb); 8661da177e4SLinus Torvalds icmp_param.data.icmph.type = ICMP_TIMESTAMPREPLY; 8671da177e4SLinus Torvalds icmp_param.data.icmph.code = 0; 8681da177e4SLinus Torvalds icmp_param.skb = skb; 8691da177e4SLinus Torvalds icmp_param.offset = 0; 8701da177e4SLinus Torvalds icmp_param.data_len = 0; 8711da177e4SLinus Torvalds icmp_param.head_len = sizeof(struct icmphdr) + 12; 8721da177e4SLinus Torvalds icmp_reply(&icmp_param, skb); 8731da177e4SLinus Torvalds out: 8741da177e4SLinus Torvalds return; 8751da177e4SLinus Torvalds out_err: 876dcfc23caSPavel Emelyanov ICMP_INC_STATS_BH(dev_net(skb->dst->dev), ICMP_MIB_INERRORS); 8771da177e4SLinus Torvalds goto out; 8781da177e4SLinus Torvalds } 8791da177e4SLinus Torvalds 8801da177e4SLinus Torvalds 8811da177e4SLinus Torvalds /* 8821da177e4SLinus Torvalds * Handle ICMP_ADDRESS_MASK requests. (RFC950) 8831da177e4SLinus Torvalds * 8841da177e4SLinus Torvalds * RFC1122 (3.2.2.9). A host MUST only send replies to 8851da177e4SLinus Torvalds * ADDRESS_MASK requests if it's been configured as an address mask 8861da177e4SLinus Torvalds * agent. Receiving a request doesn't constitute implicit permission to 8871da177e4SLinus Torvalds * act as one. Of course, implementing this correctly requires (SHOULD) 8881da177e4SLinus Torvalds * a way to turn the functionality on and off. Another one for sysctl(), 8891da177e4SLinus Torvalds * I guess. -- MS 8901da177e4SLinus Torvalds * 8911da177e4SLinus Torvalds * RFC1812 (4.3.3.9). A router MUST implement it. 8921da177e4SLinus Torvalds * A router SHOULD have switch turning it on/off. 8931da177e4SLinus Torvalds * This switch MUST be ON by default. 8941da177e4SLinus Torvalds * 8951da177e4SLinus Torvalds * Gratuitous replies, zero-source replies are not implemented, 8961da177e4SLinus Torvalds * that complies with RFC. DO NOT implement them!!! All the idea 8971da177e4SLinus Torvalds * of broadcast addrmask replies as specified in RFC950 is broken. 8981da177e4SLinus Torvalds * The problem is that it is not uncommon to have several prefixes 8991da177e4SLinus Torvalds * on one physical interface. Moreover, addrmask agent can even be 9001da177e4SLinus Torvalds * not aware of existing another prefixes. 9011da177e4SLinus Torvalds * If source is zero, addrmask agent cannot choose correct prefix. 9021da177e4SLinus Torvalds * Gratuitous mask announcements suffer from the same problem. 9031da177e4SLinus Torvalds * RFC1812 explains it, but still allows to use ADDRMASK, 9041da177e4SLinus Torvalds * that is pretty silly. --ANK 9051da177e4SLinus Torvalds * 9061da177e4SLinus Torvalds * All these rules are so bizarre, that I removed kernel addrmask 9071da177e4SLinus Torvalds * support at all. It is wrong, it is obsolete, nobody uses it in 9081da177e4SLinus Torvalds * any case. --ANK 9091da177e4SLinus Torvalds * 9101da177e4SLinus Torvalds * Furthermore you can do it with a usermode address agent program 9111da177e4SLinus Torvalds * anyway... 9121da177e4SLinus Torvalds */ 9131da177e4SLinus Torvalds 9141da177e4SLinus Torvalds static void icmp_address(struct sk_buff *skb) 9151da177e4SLinus Torvalds { 9161da177e4SLinus Torvalds #if 0 9171da177e4SLinus Torvalds if (net_ratelimit()) 9181da177e4SLinus Torvalds printk(KERN_DEBUG "a guy asks for address mask. Who is it?\n"); 9191da177e4SLinus Torvalds #endif 9201da177e4SLinus Torvalds } 9211da177e4SLinus Torvalds 9221da177e4SLinus Torvalds /* 9231da177e4SLinus Torvalds * RFC1812 (4.3.3.9). A router SHOULD listen all replies, and complain 9241da177e4SLinus Torvalds * loudly if an inconsistency is found. 9251da177e4SLinus Torvalds */ 9261da177e4SLinus Torvalds 9271da177e4SLinus Torvalds static void icmp_address_reply(struct sk_buff *skb) 9281da177e4SLinus Torvalds { 929*511c3f92SEric Dumazet struct rtable *rt = skb_rtable(skb); 9301da177e4SLinus Torvalds struct net_device *dev = skb->dev; 9311da177e4SLinus Torvalds struct in_device *in_dev; 9321da177e4SLinus Torvalds struct in_ifaddr *ifa; 9331da177e4SLinus Torvalds 9341da177e4SLinus Torvalds if (skb->len < 4 || !(rt->rt_flags&RTCF_DIRECTSRC)) 9351da177e4SLinus Torvalds goto out; 9361da177e4SLinus Torvalds 9371da177e4SLinus Torvalds in_dev = in_dev_get(dev); 9381da177e4SLinus Torvalds if (!in_dev) 9391da177e4SLinus Torvalds goto out; 9401da177e4SLinus Torvalds rcu_read_lock(); 9411da177e4SLinus Torvalds if (in_dev->ifa_list && 9421da177e4SLinus Torvalds IN_DEV_LOG_MARTIANS(in_dev) && 9431da177e4SLinus Torvalds IN_DEV_FORWARD(in_dev)) { 944a144ea4bSAl Viro __be32 _mask, *mp; 9451da177e4SLinus Torvalds 9461da177e4SLinus Torvalds mp = skb_header_pointer(skb, 0, sizeof(_mask), &_mask); 94709a62660SKris Katterjohn BUG_ON(mp == NULL); 9481da177e4SLinus Torvalds for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) { 9491da177e4SLinus Torvalds if (*mp == ifa->ifa_mask && 9501da177e4SLinus Torvalds inet_ifa_match(rt->rt_src, ifa)) 9511da177e4SLinus Torvalds break; 9521da177e4SLinus Torvalds } 9531da177e4SLinus Torvalds if (!ifa && net_ratelimit()) { 954673d57e7SHarvey Harrison printk(KERN_INFO "Wrong address mask %pI4 from %s/%pI4\n", 955673d57e7SHarvey Harrison mp, dev->name, &rt->rt_src); 9561da177e4SLinus Torvalds } 9571da177e4SLinus Torvalds } 9581da177e4SLinus Torvalds rcu_read_unlock(); 9591da177e4SLinus Torvalds in_dev_put(in_dev); 9601da177e4SLinus Torvalds out:; 9611da177e4SLinus Torvalds } 9621da177e4SLinus Torvalds 9631da177e4SLinus Torvalds static void icmp_discard(struct sk_buff *skb) 9641da177e4SLinus Torvalds { 9651da177e4SLinus Torvalds } 9661da177e4SLinus Torvalds 9671da177e4SLinus Torvalds /* 9681da177e4SLinus Torvalds * Deal with incoming ICMP packets. 9691da177e4SLinus Torvalds */ 9701da177e4SLinus Torvalds int icmp_rcv(struct sk_buff *skb) 9711da177e4SLinus Torvalds { 9721da177e4SLinus Torvalds struct icmphdr *icmph; 973*511c3f92SEric Dumazet struct rtable *rt = skb_rtable(skb); 974fd54d716SPavel Emelyanov struct net *net = dev_net(rt->u.dst.dev); 9751da177e4SLinus Torvalds 976aebcf82cSHerbert Xu if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { 977def8b4faSAlexey Dobriyan struct sec_path *sp = skb_sec_path(skb); 9788b7817f3SHerbert Xu int nh; 9798b7817f3SHerbert Xu 980def8b4faSAlexey Dobriyan if (!(sp && sp->xvec[sp->len - 1]->props.flags & 981aebcf82cSHerbert Xu XFRM_STATE_ICMP)) 982aebcf82cSHerbert Xu goto drop; 983aebcf82cSHerbert Xu 9848b7817f3SHerbert Xu if (!pskb_may_pull(skb, sizeof(*icmph) + sizeof(struct iphdr))) 9858b7817f3SHerbert Xu goto drop; 9868b7817f3SHerbert Xu 9878b7817f3SHerbert Xu nh = skb_network_offset(skb); 9888b7817f3SHerbert Xu skb_set_network_header(skb, sizeof(*icmph)); 9898b7817f3SHerbert Xu 9908b7817f3SHerbert Xu if (!xfrm4_policy_check_reverse(NULL, XFRM_POLICY_IN, skb)) 9918b7817f3SHerbert Xu goto drop; 9928b7817f3SHerbert Xu 9938b7817f3SHerbert Xu skb_set_network_header(skb, nh); 9948b7817f3SHerbert Xu } 9958b7817f3SHerbert Xu 996dcfc23caSPavel Emelyanov ICMP_INC_STATS_BH(net, ICMP_MIB_INMSGS); 9971da177e4SLinus Torvalds 9981da177e4SLinus Torvalds switch (skb->ip_summed) { 99984fa7933SPatrick McHardy case CHECKSUM_COMPLETE: 1000d3bc23e7SAl Viro if (!csum_fold(skb->csum)) 10011da177e4SLinus Torvalds break; 1002fb286bb2SHerbert Xu /* fall through */ 10031da177e4SLinus Torvalds case CHECKSUM_NONE: 1004fb286bb2SHerbert Xu skb->csum = 0; 1005fb286bb2SHerbert Xu if (__skb_checksum_complete(skb)) 10061da177e4SLinus Torvalds goto error; 10071da177e4SLinus Torvalds } 10081da177e4SLinus Torvalds 10098cf22943SHerbert Xu if (!pskb_pull(skb, sizeof(*icmph))) 10108cf22943SHerbert Xu goto error; 10111da177e4SLinus Torvalds 101288c7664fSArnaldo Carvalho de Melo icmph = icmp_hdr(skb); 10131da177e4SLinus Torvalds 1014f66ac03dSPavel Emelyanov ICMPMSGIN_INC_STATS_BH(net, icmph->type); 10151da177e4SLinus Torvalds /* 10161da177e4SLinus Torvalds * 18 is the highest 'known' ICMP type. Anything else is a mystery 10171da177e4SLinus Torvalds * 10181da177e4SLinus Torvalds * RFC 1122: 3.2.2 Unknown ICMP messages types MUST be silently 10191da177e4SLinus Torvalds * discarded. 10201da177e4SLinus Torvalds */ 10211da177e4SLinus Torvalds if (icmph->type > NR_ICMP_TYPES) 10221da177e4SLinus Torvalds goto error; 10231da177e4SLinus Torvalds 10241da177e4SLinus Torvalds 10251da177e4SLinus Torvalds /* 10261da177e4SLinus Torvalds * Parse the ICMP message 10271da177e4SLinus Torvalds */ 10281da177e4SLinus Torvalds 10291da177e4SLinus Torvalds if (rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) { 10301da177e4SLinus Torvalds /* 10311da177e4SLinus Torvalds * RFC 1122: 3.2.2.6 An ICMP_ECHO to broadcast MAY be 10321da177e4SLinus Torvalds * silently ignored (we let user decide with a sysctl). 10331da177e4SLinus Torvalds * RFC 1122: 3.2.2.8 An ICMP_TIMESTAMP MAY be silently 10341da177e4SLinus Torvalds * discarded if to broadcast/multicast. 10351da177e4SLinus Torvalds */ 10364c866aa7SAlexey Kuznetsov if ((icmph->type == ICMP_ECHO || 10374c866aa7SAlexey Kuznetsov icmph->type == ICMP_TIMESTAMP) && 1038b34a95eeSPavel Emelyanov net->ipv4.sysctl_icmp_echo_ignore_broadcasts) { 10391da177e4SLinus Torvalds goto error; 10401da177e4SLinus Torvalds } 10411da177e4SLinus Torvalds if (icmph->type != ICMP_ECHO && 10421da177e4SLinus Torvalds icmph->type != ICMP_TIMESTAMP && 10431da177e4SLinus Torvalds icmph->type != ICMP_ADDRESS && 10441da177e4SLinus Torvalds icmph->type != ICMP_ADDRESSREPLY) { 10451da177e4SLinus Torvalds goto error; 10461da177e4SLinus Torvalds } 10471da177e4SLinus Torvalds } 10481da177e4SLinus Torvalds 10491da177e4SLinus Torvalds icmp_pointers[icmph->type].handler(skb); 10501da177e4SLinus Torvalds 10511da177e4SLinus Torvalds drop: 10521da177e4SLinus Torvalds kfree_skb(skb); 10531da177e4SLinus Torvalds return 0; 10541da177e4SLinus Torvalds error: 1055dcfc23caSPavel Emelyanov ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); 10561da177e4SLinus Torvalds goto drop; 10571da177e4SLinus Torvalds } 10581da177e4SLinus Torvalds 10591da177e4SLinus Torvalds /* 10601da177e4SLinus Torvalds * This table is the definition of how we handle ICMP. 10611da177e4SLinus Torvalds */ 10629b5b5cffSArjan van de Ven static const struct icmp_control icmp_pointers[NR_ICMP_TYPES + 1] = { 10631da177e4SLinus Torvalds [ICMP_ECHOREPLY] = { 10641da177e4SLinus Torvalds .handler = icmp_discard, 10651da177e4SLinus Torvalds }, 10661da177e4SLinus Torvalds [1] = { 10671da177e4SLinus Torvalds .handler = icmp_discard, 10681da177e4SLinus Torvalds .error = 1, 10691da177e4SLinus Torvalds }, 10701da177e4SLinus Torvalds [2] = { 10711da177e4SLinus Torvalds .handler = icmp_discard, 10721da177e4SLinus Torvalds .error = 1, 10731da177e4SLinus Torvalds }, 10741da177e4SLinus Torvalds [ICMP_DEST_UNREACH] = { 10751da177e4SLinus Torvalds .handler = icmp_unreach, 10761da177e4SLinus Torvalds .error = 1, 10771da177e4SLinus Torvalds }, 10781da177e4SLinus Torvalds [ICMP_SOURCE_QUENCH] = { 10791da177e4SLinus Torvalds .handler = icmp_unreach, 10801da177e4SLinus Torvalds .error = 1, 10811da177e4SLinus Torvalds }, 10821da177e4SLinus Torvalds [ICMP_REDIRECT] = { 10831da177e4SLinus Torvalds .handler = icmp_redirect, 10841da177e4SLinus Torvalds .error = 1, 10851da177e4SLinus Torvalds }, 10861da177e4SLinus Torvalds [6] = { 10871da177e4SLinus Torvalds .handler = icmp_discard, 10881da177e4SLinus Torvalds .error = 1, 10891da177e4SLinus Torvalds }, 10901da177e4SLinus Torvalds [7] = { 10911da177e4SLinus Torvalds .handler = icmp_discard, 10921da177e4SLinus Torvalds .error = 1, 10931da177e4SLinus Torvalds }, 10941da177e4SLinus Torvalds [ICMP_ECHO] = { 10951da177e4SLinus Torvalds .handler = icmp_echo, 10961da177e4SLinus Torvalds }, 10971da177e4SLinus Torvalds [9] = { 10981da177e4SLinus Torvalds .handler = icmp_discard, 10991da177e4SLinus Torvalds .error = 1, 11001da177e4SLinus Torvalds }, 11011da177e4SLinus Torvalds [10] = { 11021da177e4SLinus Torvalds .handler = icmp_discard, 11031da177e4SLinus Torvalds .error = 1, 11041da177e4SLinus Torvalds }, 11051da177e4SLinus Torvalds [ICMP_TIME_EXCEEDED] = { 11061da177e4SLinus Torvalds .handler = icmp_unreach, 11071da177e4SLinus Torvalds .error = 1, 11081da177e4SLinus Torvalds }, 11091da177e4SLinus Torvalds [ICMP_PARAMETERPROB] = { 11101da177e4SLinus Torvalds .handler = icmp_unreach, 11111da177e4SLinus Torvalds .error = 1, 11121da177e4SLinus Torvalds }, 11131da177e4SLinus Torvalds [ICMP_TIMESTAMP] = { 11141da177e4SLinus Torvalds .handler = icmp_timestamp, 11151da177e4SLinus Torvalds }, 11161da177e4SLinus Torvalds [ICMP_TIMESTAMPREPLY] = { 11171da177e4SLinus Torvalds .handler = icmp_discard, 11181da177e4SLinus Torvalds }, 11191da177e4SLinus Torvalds [ICMP_INFO_REQUEST] = { 11201da177e4SLinus Torvalds .handler = icmp_discard, 11211da177e4SLinus Torvalds }, 11221da177e4SLinus Torvalds [ICMP_INFO_REPLY] = { 11231da177e4SLinus Torvalds .handler = icmp_discard, 11241da177e4SLinus Torvalds }, 11251da177e4SLinus Torvalds [ICMP_ADDRESS] = { 11261da177e4SLinus Torvalds .handler = icmp_address, 11271da177e4SLinus Torvalds }, 11281da177e4SLinus Torvalds [ICMP_ADDRESSREPLY] = { 11291da177e4SLinus Torvalds .handler = icmp_address_reply, 11301da177e4SLinus Torvalds }, 11311da177e4SLinus Torvalds }; 11321da177e4SLinus Torvalds 11334a6ad7a1SDenis V. Lunev static void __net_exit icmp_sk_exit(struct net *net) 11341da177e4SLinus Torvalds { 11351da177e4SLinus Torvalds int i; 11361da177e4SLinus Torvalds 11375c8cafd6SDenis V. Lunev for_each_possible_cpu(i) 1138c1e9894dSDenis V. Lunev inet_ctl_sock_destroy(net->ipv4.icmp_sk[i]); 11394a6ad7a1SDenis V. Lunev kfree(net->ipv4.icmp_sk); 11404a6ad7a1SDenis V. Lunev net->ipv4.icmp_sk = NULL; 1141a5710d65SDenis V. Lunev } 1142a5710d65SDenis V. Lunev 1143263173afSAdrian Bunk static int __net_init icmp_sk_init(struct net *net) 1144a5710d65SDenis V. Lunev { 1145a5710d65SDenis V. Lunev int i, err; 1146a5710d65SDenis V. Lunev 11474a6ad7a1SDenis V. Lunev net->ipv4.icmp_sk = 11484a6ad7a1SDenis V. Lunev kzalloc(nr_cpu_ids * sizeof(struct sock *), GFP_KERNEL); 11494a6ad7a1SDenis V. Lunev if (net->ipv4.icmp_sk == NULL) 115079c91159SDenis V. Lunev return -ENOMEM; 115179c91159SDenis V. Lunev 1152a5710d65SDenis V. Lunev for_each_possible_cpu(i) { 11531e3cf683SDenis V. Lunev struct sock *sk; 11541da177e4SLinus Torvalds 1155c1e9894dSDenis V. Lunev err = inet_ctl_sock_create(&sk, PF_INET, 1156c1e9894dSDenis V. Lunev SOCK_RAW, IPPROTO_ICMP, net); 11571da177e4SLinus Torvalds if (err < 0) 1158a5710d65SDenis V. Lunev goto fail; 11591da177e4SLinus Torvalds 1160c1e9894dSDenis V. Lunev net->ipv4.icmp_sk[i] = sk; 11611da177e4SLinus Torvalds 11621da177e4SLinus Torvalds /* Enough space for 2 64K ICMP packets, including 11631da177e4SLinus Torvalds * sk_buff struct overhead. 11641da177e4SLinus Torvalds */ 11651e3cf683SDenis V. Lunev sk->sk_sndbuf = 11661da177e4SLinus Torvalds (2 * ((64 * 1024) + sizeof(struct sk_buff))); 11671da177e4SLinus Torvalds 1168c1e9894dSDenis V. Lunev inet_sk(sk)->pmtudisc = IP_PMTUDISC_DONT; 11691da177e4SLinus Torvalds } 1170a24022e1SPavel Emelyanov 1171a24022e1SPavel Emelyanov /* Control parameters for ECHO replies. */ 1172a24022e1SPavel Emelyanov net->ipv4.sysctl_icmp_echo_ignore_all = 0; 1173a24022e1SPavel Emelyanov net->ipv4.sysctl_icmp_echo_ignore_broadcasts = 1; 1174a24022e1SPavel Emelyanov 1175a24022e1SPavel Emelyanov /* Control parameter - ignore bogus broadcast responses? */ 1176a24022e1SPavel Emelyanov net->ipv4.sysctl_icmp_ignore_bogus_error_responses = 1; 1177a24022e1SPavel Emelyanov 1178a24022e1SPavel Emelyanov /* 1179a24022e1SPavel Emelyanov * Configurable global rate limit. 1180a24022e1SPavel Emelyanov * 1181a24022e1SPavel Emelyanov * ratelimit defines tokens/packet consumed for dst->rate_token 1182a24022e1SPavel Emelyanov * bucket ratemask defines which icmp types are ratelimited by 1183a24022e1SPavel Emelyanov * setting it's bit position. 1184a24022e1SPavel Emelyanov * 1185a24022e1SPavel Emelyanov * default: 1186a24022e1SPavel Emelyanov * dest unreachable (3), source quench (4), 1187a24022e1SPavel Emelyanov * time exceeded (11), parameter problem (12) 1188a24022e1SPavel Emelyanov */ 1189a24022e1SPavel Emelyanov 1190a24022e1SPavel Emelyanov net->ipv4.sysctl_icmp_ratelimit = 1 * HZ; 1191a24022e1SPavel Emelyanov net->ipv4.sysctl_icmp_ratemask = 0x1818; 1192a24022e1SPavel Emelyanov net->ipv4.sysctl_icmp_errors_use_inbound_ifaddr = 0; 1193a24022e1SPavel Emelyanov 1194a5710d65SDenis V. Lunev return 0; 1195a5710d65SDenis V. Lunev 1196a5710d65SDenis V. Lunev fail: 11971d1c8d13SDenis V. Lunev for_each_possible_cpu(i) 1198c1e9894dSDenis V. Lunev inet_ctl_sock_destroy(net->ipv4.icmp_sk[i]); 11991d1c8d13SDenis V. Lunev kfree(net->ipv4.icmp_sk); 1200a5710d65SDenis V. Lunev return err; 12011da177e4SLinus Torvalds } 12021da177e4SLinus Torvalds 12034a6ad7a1SDenis V. Lunev static struct pernet_operations __net_initdata icmp_sk_ops = { 12044a6ad7a1SDenis V. Lunev .init = icmp_sk_init, 12054a6ad7a1SDenis V. Lunev .exit = icmp_sk_exit, 12064a6ad7a1SDenis V. Lunev }; 12074a6ad7a1SDenis V. Lunev 12084a6ad7a1SDenis V. Lunev int __init icmp_init(void) 12094a6ad7a1SDenis V. Lunev { 1210959d2726SEric W. Biederman return register_pernet_subsys(&icmp_sk_ops); 12114a6ad7a1SDenis V. Lunev } 12124a6ad7a1SDenis V. Lunev 12131da177e4SLinus Torvalds EXPORT_SYMBOL(icmp_err_convert); 12141da177e4SLinus Torvalds EXPORT_SYMBOL(icmp_send); 12151da177e4SLinus Torvalds EXPORT_SYMBOL(xrlim_allow); 1216