patch-ipod-linux-2.6.25 4.43 KB
Newer Older
1 2
--- linux-2.6.25/net/ipv4/Kconfig	2008-08-29 09:50:50.000000000 -0600
+++ linux-2.6.25-emulab/net/ipv4/Kconfig	2008-08-29 09:53:39.000000000 -0600
3 4 5 6 7 8 9 10
@@ -632,5 +632,11 @@
 
 	  If unsure, say N.
 
+#
+# Emulab special
+#
+config ICMP_PINGOFDEATH
11
+        bool "ICMP: ICMP Ping-of-Death (Emulab)"
12 13 14
+
 source "net/ipv4/ipvs/Kconfig"
 
15 16
--- linux-2.6.25/net/ipv4/icmp.c	2008-08-29 09:51:02.000000000 -0600
+++ linux-2.6.25-emulab/net/ipv4/icmp.c	2008-08-29 09:57:02.000000000 -0600
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
@@ -973,6 +973,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 = icmp_hdr(skb);
+	struct iphdr *iph = ip_hdr(skb);
+	int doit = 0;
+
+#if 0
41
+        printk(KERN_INFO "IPOD: got type=6, code=%d, host=%u.%u.%u.%u\n", icmph->code, ntohs(iph->tot_len), NIPQUAD(iph->saddr));
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
+#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.
+                 */
61 62 63 64 65 66 67 68
+                 if (IPOD_CHECK_KEY) {
+                         if (pskb_may_pull(skb, sizeof(sysctl_ipod_key)-1) &&
+			     IPOD_VALID_KEY(skb->data))
+			         doit = 1;
+		 } else {
+		         doit = 1;
+		 }
+	}
69 70 71 72 73 74 75
+
+	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 {
76
+	        printk(KERN_WARNING "IPOD: from %u.%u.%u.%u rejected\n",
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
+		       NIPQUAD(iph->saddr));
+	}
+}
+#endif
+
 static void icmp_discard(struct sk_buff *skb)
 {
 }
@@ -1094,10 +1155,18 @@
 		.handler = icmp_redirect,
 		.error = 1,
 	},
+#ifdef CONFIG_ICMP_PINGOFDEATH
+	/* PING_OF_DEATH (6) */
+	[6] = {
92 93
+	  .handler = icmp_ping_of_death,
+	  .error = 1,
94 95 96 97 98 99 100 101 102 103
+	},
+#else
 	[6] = {
 		.handler = icmp_discard,
 		.error = 1,
 	},
+#endif
 	[7] = {
 		.handler = icmp_discard,
 		.error = 1,
104 105
--- linux-2.6.25/net/ipv4/sysctl_net_ipv4.c	2008-08-29 09:51:18.000000000 -0600
+++ linux-2.6.25-emulab/net/ipv4/sysctl_net_ipv4.c	2008-08-29 09:58:52.000000000 -0600
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
@@ -23,6 +23,14 @@
 #include <net/cipso_ipv4.h>
 #include <net/inet_frag.h>
 
+#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
+
 static int zero;
 static int tcp_retr1_max = 255;
 static int ip_local_port_range_min[] = { 1, 1 };
@@ -801,6 +809,49 @@
 		.strategy	= &sysctl_intvec,
 		.extra1		= &zero
 	},
+#ifdef CONFIG_ICMP_PINGOFDEATH
+	{
127
+	        .ctl_name       = CTL_UNNUMBERED,
128 129 130 131 132 133 134
+		.procname       = "icmp_ipod_version",
+		.data           = &sysctl_ipod_version,
+		.maxlen         = sizeof(int),
+		.mode           = 0444,
+		.proc_handler   = &proc_dointvec,
+	},
+	{
135
+	        .ctl_name       = CTL_UNNUMBERED,
136 137 138 139 140 141 142
+		.procname       = "icmp_ipod_enabled",
+		.data           = &sysctl_ipod_enabled,
+		.maxlen         = sizeof(int),
+		.mode           = 0644,
+		.proc_handler   = &proc_dointvec,
+	},
+	{
143
+	        .ctl_name       = CTL_UNNUMBERED,
144 145 146 147 148 149 150
+		.procname       = "icmp_ipod_host",
+		.data           = &sysctl_ipod_host,
+		.maxlen         = sizeof(int),
+		.mode           = 0644,
+		.proc_handler   = &proc_dointvec,
+	},
+	{
151
+	        .ctl_name       = CTL_UNNUMBERED,
152 153 154 155 156 157 158
+		.procname       = "icmp_ipod_mask",
+		.data           = &sysctl_ipod_mask,
+		.maxlen         = sizeof(int),
+		.mode           = 0644,
+		.proc_handler   = &proc_dointvec,
+	},
+	{
159
+	        .ctl_name       = CTL_UNNUMBERED,
160 161 162 163 164 165 166 167 168 169 170
+		.procname       = "icmp_ipod_key",
+		.data           = sysctl_ipod_key,
+		.maxlen         = sizeof(sysctl_ipod_key),
+		.mode           = 0600,
+		.proc_handler   = &proc_dostring,
+		.strategy       = &sysctl_string,
+	},
+#endif
 	{ .ctl_name = 0 }
 };