patch-ipod-linux-2.6.12-1.1387_FC4 4.82 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
diff -ur linux-2.6.12-1.1387_FC4/include/linux/sysctl.h linux-2.6.12/include/linux/sysctl.h
--- linux-2.6.12-1.1387_FC4/include/linux/sysctl.h	2005-07-12 01:00:08.000000000 -0600
+++ linux-2.6.12/include/linux/sysctl.h	2005-07-06 11:25:25.000000000 -0600
@@ -351,6 +351,13 @@
 	NET_TCP_TSO_WIN_DIVISOR=107,
 	NET_TCP_BIC_BETA=108,
 	NET_IPV4_ICMP_ERRORS_USE_INBOUND_IFADDR=109,
+
+   	/* CONFIG_ICMP_PINGOFDEATH */
+  	NET_IPV4_ICMP_POD_ENABLED=110,
+  	NET_IPV4_ICMP_POD_HOST=111,
+  	NET_IPV4_ICMP_POD_MASK=112,
+  	NET_IPV4_ICMP_POD_KEY=113,
+  	NET_IPV4_ICMP_POD_VERSION=114,
 };
 
 enum {
diff -ur linux-2.6.12-1.1387_FC4/net/ipv4/Kconfig linux-2.6.12/net/ipv4/Kconfig
--- linux-2.6.12-1.1387_FC4/net/ipv4/Kconfig	2005-06-17 13:48:29.000000000 -0600
+++ linux-2.6.12/net/ipv4/Kconfig	2005-07-06 11:22:48.000000000 -0600
@@ -407,5 +407,11 @@
 config IP_TCPDIAG_IPV6
 	def_bool (IP_TCPDIAG=y && IPV6=y) || (IP_TCPDIAG=m && IPV6)
 
+#
+# Emulab special
+#
+config ICMP_PINGOFDEATH
+	bool "ICMP: ICMP Ping-of-Death (Emulab)"
+
 source "net/ipv4/ipvs/Kconfig"
 
diff -ur linux-2.6.12-1.1387_FC4/net/ipv4/icmp.c linux-2.6.12/net/ipv4/icmp.c
--- linux-2.6.12-1.1387_FC4/net/ipv4/icmp.c	2005-06-17 13:48:29.000000000 -0600
+++ linux-2.6.12/net/ipv4/icmp.c	2005-07-06 11:22:48.000000000 -0600
@@ -918,6 +918,67 @@
 out:;
 }
 
+#ifdef CONFIG_ICMP_PINGOFDEATH
+#include <linux/reboot.h>
+
+int sysctl_ipod_version = 2;
+int sysctl_ipod_enabled = 0;
+u32 sysctl_ipod_host = 0xffffffff;
+u32 sysctl_ipod_mask = 0xffffffff;
+char sysctl_ipod_key[32+1] = { "SETMETOSOMETHINGTHIRTYTWOBYTES!!" };
+#define IPOD_CHECK_KEY \
+	(sysctl_ipod_key[0] != 0)
+#define IPOD_VALID_KEY(d) \
+	(strncmp(sysctl_ipod_key, (char *)(d), strlen(sysctl_ipod_key)) == 0)
+
+static void icmp_ping_of_death(struct sk_buff *skb)
+{
+	struct icmphdr *icmph = skb->h.icmph;
+	struct iphdr *iph = skb->nh.iph;
+	int doit = 0;
+
+#if 0
+	printk(KERN_INFO "IPOD: got type=6, code=%d, host=%u.%u.%u.%u\n", icmph->code, ntohs(iph->tot_len), NIPQUAD(iph->saddr));
+#endif
+
+	/*
+	 * If IPOD not enabled or wrong ICMP code, ignore.
+	 */
+	if (!sysctl_ipod_enabled || icmph->code != 6)
+		return;
+
+	/*
+	 * First check the source address info.
+	 * If host not set, ignore.
+	 */
+	if (sysctl_ipod_host != 0xffffffff &&
+	    (ntohl(iph->saddr) & sysctl_ipod_mask) == sysctl_ipod_host) {
+		/*
+		 * Now check the key if enabled.
+		 * If packet doesn't contain enough data or key
+		 * is otherwise invalid, ignore.
+		 */
+		if (IPOD_CHECK_KEY) {
+			if (pskb_may_pull(skb, sizeof(sysctl_ipod_key)-1) &&
+			    IPOD_VALID_KEY(skb->data))
+				doit = 1;
+		} else {
+			doit = 1;
+		}
+	}
+
+	if (doit) {
+		sysctl_ipod_enabled = 0;
+		printk(KERN_CRIT "IPOD: reboot forced by %u.%u.%u.%u...\n",
+		       NIPQUAD(iph->saddr));
+		machine_restart(NULL);
+	} else {
+		printk(KERN_WARNING "IPOD: from %u.%u.%u.%u rejected\n",
+		       NIPQUAD(iph->saddr));
+	}
+}
+#endif
+
 static void icmp_discard(struct sk_buff *skb)
 {
 }
@@ -1032,12 +1093,22 @@
 		.handler = icmp_redirect,
 		.error = 1,
 	},
+#ifdef CONFIG_ICMP_PINGOFDEATH
+	/* PING_OF_DEATH (6) */
+	[6] = {
+		.output_entry = ICMP_MIB_DUMMY,
+		.input_entry = ICMP_MIB_DUMMY,
+		.handler = icmp_ping_of_death,
+		.error = 1,
+	},
+#else
 	[6] = {
 		.output_entry = ICMP_MIB_DUMMY,
 		.input_entry = ICMP_MIB_INERRORS,
 		.handler = icmp_discard,
 		.error = 1,
 	},
+#endif
 	[7] = {
 		.output_entry = ICMP_MIB_DUMMY,
 		.input_entry = ICMP_MIB_INERRORS,
diff -ur linux-2.6.12-1.1387_FC4/net/ipv4/sysctl_net_ipv4.c linux-2.6.12/net/ipv4/sysctl_net_ipv4.c
--- linux-2.6.12-1.1387_FC4/net/ipv4/sysctl_net_ipv4.c	2005-06-17 13:48:29.000000000 -0600
+++ linux-2.6.12/net/ipv4/sysctl_net_ipv4.c	2005-07-06 11:27:39.000000000 -0600
@@ -24,6 +24,13 @@
 extern int sysctl_icmp_echo_ignore_broadcasts;
 extern int sysctl_icmp_ignore_bogus_error_responses;
 extern int sysctl_icmp_errors_use_inbound_ifaddr;
+#ifdef CONFIG_ICMP_PINGOFDEATH
+extern int sysctl_ipod_version;
+extern int sysctl_ipod_enabled;
+extern u32 sysctl_ipod_host;
+extern u32 sysctl_ipod_mask;
+extern char sysctl_ipod_key[32+1];
+#endif
 
 /* From ip_fragment.c */
 extern int sysctl_ipfrag_low_thresh;
@@ -699,6 +706,18 @@
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec,
 	},
+#ifdef CONFIG_ICMP_PINGOFDEATH
+ 	{NET_IPV4_ICMP_POD_ENABLED, "icmp_ipod_version",
+ 	 &sysctl_ipod_version, sizeof(int), 0444, NULL, &proc_dointvec},
+ 	{NET_IPV4_ICMP_POD_ENABLED, "icmp_ipod_enabled",
+ 	 &sysctl_ipod_enabled, sizeof(int), 0644, NULL, &proc_dointvec},
+ 	{NET_IPV4_ICMP_POD_HOST, "icmp_ipod_host",
+ 	 &sysctl_ipod_host, sizeof(int), 0644, NULL, &proc_dointvec},
+ 	{NET_IPV4_ICMP_POD_MASK, "icmp_ipod_mask",
+ 	 &sysctl_ipod_mask, sizeof(int), 0644, NULL, &proc_dointvec},
+ 	{NET_IPV4_ICMP_POD_KEY, "icmp_ipod_key",
+ 	 sysctl_ipod_key, sizeof(sysctl_ipod_key), 0600, NULL, &proc_dostring, &sysctl_string},
+#endif
 	{ .ctl_name = 0 }
 };