| Subject: net: sysrq via icmp | 
 | From: Carsten Emde <C.Emde@osadl.org> | 
 | Date: Tue, 19 Jul 2011 13:51:17 +0100 | 
 |  | 
 | There are (probably rare) situations when a system crashed and the system | 
 | console becomes unresponsive but the network icmp layer still is alive. | 
 | Wouldn't it be wonderful, if we then could submit a sysreq command via ping? | 
 |  | 
 | This patch provides this facility. Please consult the updated documentation | 
 | Documentation/sysrq.txt for details. | 
 |  | 
 | Signed-off-by: Carsten Emde <C.Emde@osadl.org> | 
 |  | 
 | --- | 
 |  Documentation/sysrq.txt    |   11 +++++++++-- | 
 |  include/net/netns/ipv4.h   |    1 + | 
 |  net/ipv4/icmp.c            |   30 ++++++++++++++++++++++++++++++ | 
 |  net/ipv4/sysctl_net_ipv4.c |    7 +++++++ | 
 |  4 files changed, 47 insertions(+), 2 deletions(-) | 
 |  | 
 | --- a/Documentation/sysrq.txt | 
 | +++ b/Documentation/sysrq.txt | 
 | @@ -59,10 +59,17 @@ On PowerPC - Press 'ALT - Print Screen ( | 
 |  On other - If you know of the key combos for other architectures, please | 
 |             let me know so I can add them to this section. | 
 |   | 
 | -On all -  write a character to /proc/sysrq-trigger.  e.g.: | 
 | - | 
 | +On all -  write a character to /proc/sysrq-trigger, e.g.: | 
 |  		echo t > /proc/sysrq-trigger | 
 |   | 
 | +On all - Enable network SysRq by writing a cookie to icmp_echo_sysrq, e.g. | 
 | +		echo 0x01020304 >/proc/sys/net/ipv4/icmp_echo_sysrq | 
 | +	 Send an ICMP echo request with this pattern plus the particular | 
 | +	 SysRq command key. Example: | 
 | +		# ping -c1 -s57 -p0102030468 | 
 | +	 will trigger the SysRq-H (help) command. | 
 | + | 
 | + | 
 |  *  What are the 'command' keys? | 
 |  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 
 |  'b'     - Will immediately reboot the system without syncing or unmounting | 
 | --- a/include/net/netns/ipv4.h | 
 | +++ b/include/net/netns/ipv4.h | 
 | @@ -70,6 +70,7 @@ struct netns_ipv4 { | 
 |   | 
 |  	int sysctl_icmp_echo_ignore_all; | 
 |  	int sysctl_icmp_echo_ignore_broadcasts; | 
 | +	int sysctl_icmp_echo_sysrq; | 
 |  	int sysctl_icmp_ignore_bogus_error_responses; | 
 |  	int sysctl_icmp_ratelimit; | 
 |  	int sysctl_icmp_ratemask; | 
 | --- a/net/ipv4/icmp.c | 
 | +++ b/net/ipv4/icmp.c | 
 | @@ -69,6 +69,7 @@ | 
 |  #include <linux/jiffies.h> | 
 |  #include <linux/kernel.h> | 
 |  #include <linux/fcntl.h> | 
 | +#include <linux/sysrq.h> | 
 |  #include <linux/socket.h> | 
 |  #include <linux/in.h> | 
 |  #include <linux/inet.h> | 
 | @@ -899,6 +900,30 @@ static bool icmp_redirect(struct sk_buff | 
 |  } | 
 |   | 
 |  /* | 
 | + * 32bit and 64bit have different timestamp length, so we check for | 
 | + * the cookie at offset 20 and verify it is repeated at offset 50 | 
 | + */ | 
 | +#define CO_POS0		20 | 
 | +#define CO_POS1		50 | 
 | +#define CO_SIZE		sizeof(int) | 
 | +#define ICMP_SYSRQ_SIZE	57 | 
 | + | 
 | +/* | 
 | + * We got a ICMP_SYSRQ_SIZE sized ping request. Check for the cookie | 
 | + * pattern and if it matches send the next byte as a trigger to sysrq. | 
 | + */ | 
 | +static void icmp_check_sysrq(struct net *net, struct sk_buff *skb) | 
 | +{ | 
 | +	int cookie = htonl(net->ipv4.sysctl_icmp_echo_sysrq); | 
 | +	char *p = skb->data; | 
 | + | 
 | +	if (!memcmp(&cookie, p + CO_POS0, CO_SIZE) && | 
 | +	    !memcmp(&cookie, p + CO_POS1, CO_SIZE) && | 
 | +	    p[CO_POS0 + CO_SIZE] == p[CO_POS1 + CO_SIZE]) | 
 | +		handle_sysrq(p[CO_POS0 + CO_SIZE]); | 
 | +} | 
 | + | 
 | +/* | 
 |   *	Handle ICMP_ECHO ("ping") requests. | 
 |   * | 
 |   *	RFC 1122: 3.2.2.6 MUST have an echo server that answers ICMP echo | 
 | @@ -925,6 +950,11 @@ static bool icmp_echo(struct sk_buff *sk | 
 |  		icmp_param.data_len	   = skb->len; | 
 |  		icmp_param.head_len	   = sizeof(struct icmphdr); | 
 |  		icmp_reply(&icmp_param, skb); | 
 | + | 
 | +		if (skb->len == ICMP_SYSRQ_SIZE && | 
 | +		    net->ipv4.sysctl_icmp_echo_sysrq) { | 
 | +			icmp_check_sysrq(net, skb); | 
 | +		} | 
 |  	} | 
 |  	/* should there be an ICMP stat for ignored echos? */ | 
 |  	return true; | 
 | --- a/net/ipv4/sysctl_net_ipv4.c | 
 | +++ b/net/ipv4/sysctl_net_ipv4.c | 
 | @@ -681,6 +681,13 @@ static struct ctl_table ipv4_net_table[] | 
 |  		.proc_handler	= proc_dointvec | 
 |  	}, | 
 |  	{ | 
 | +		.procname	= "icmp_echo_sysrq", | 
 | +		.data		= &init_net.ipv4.sysctl_icmp_echo_sysrq, | 
 | +		.maxlen		= sizeof(int), | 
 | +		.mode		= 0644, | 
 | +		.proc_handler	= proc_dointvec | 
 | +	}, | 
 | +	{ | 
 |  		.procname	= "icmp_ignore_bogus_error_responses", | 
 |  		.data		= &init_net.ipv4.sysctl_icmp_ignore_bogus_error_responses, | 
 |  		.maxlen		= sizeof(int), |