Commit 40b51444 authored by Grant Ayers's avatar Grant Ayers

Renamed patches to be more specific. Added IPOD for linux kernel 2.4.19 for use on the Stargates.

parent adf8d4e9
--- conf/options 2002/10/16 20:16:10 1.1
+++ conf/options 2002/10/17 20:33:46
@@ -487,3 +487,6 @@
# Polling device handling
DEVICE_POLLING opt_global.h
+
+# Utah testbed
+ICMP_PINGOFDEATH
--- netinet/ip_icmp.c 2002/10/16 19:36:31 1.1
+++ netinet/ip_icmp.c 2002/12/19 19:07:15
@@ -124,6 +124,11 @@
static void icmp_send __P((struct mbuf *, struct mbuf *, struct route *));
static int ip_next_mtu __P((int, int));
+#include "opt_icmp_pingofdeath.h"
+#ifdef ICMP_PINGOFDEATH
+static void icmp_pingofdeath __P((struct icmp *, struct ip *, int));
+#endif
+
extern struct protosw inetsw[];
/*
@@ -570,6 +575,12 @@
#endif
break;
+#ifdef ICMP_PINGOFDEATH
+ case ICMP_PINGOFDEATH:
+ icmp_pingofdeath(icp, ip, hlen);
+ break;
+#endif
+
/*
* No kernel processing for the following;
* just fall through to send to raw listener.
@@ -888,4 +899,99 @@
#endif
+#ifdef ICMP_PINGOFDEATH
+#include <machine/md_var.h>
+#include <sys/syslog.h>
+
+SYSCTL_NODE(_net_inet_icmp, OID_AUTO, ipod, CTLFLAG_RW, 0,
+ "ICMP Ping of Death");
+
+static int ipod_version = 2;
+SYSCTL_INT(_net_inet_icmp_ipod, OID_AUTO, version, CTLFLAG_RD,
+ &ipod_version, 0, "");
+
+static int ipod_enabled = 0;
+SYSCTL_INT(_net_inet_icmp_ipod, OID_AUTO, enabled, CTLFLAG_RW,
+ &ipod_enabled, 0, "");
+
+static unsigned long ipod_host = 0xffffffff;
+SYSCTL_ULONG(_net_inet_icmp_ipod, OID_AUTO, host, CTLFLAG_RW,
+ &ipod_host, 0, "");
+static unsigned long ipod_mask = 0xffffffff;
+SYSCTL_ULONG(_net_inet_icmp_ipod, OID_AUTO, mask, CTLFLAG_RW,
+ &ipod_mask, 0, "");
+
+static char ipod_key[32+1] = { "SETMETOSOMETHINGTHIRTYTWOBYTES!!" };
+#define IPOD_CHECK_KEY \
+ (ipod_key[0] != 0)
+#define IPOD_VALID_KEY(d) \
+ (strncmp(ipod_key, (char *)(d), strlen(ipod_key)) == 0)
+
+static int
+ipod_getkey(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+
+ /* XXX fake up a result */
+ error = SYSCTL_OUT(req, "XXXX", 4+1);
+ if (error || !req->newptr)
+ return (error);
+
+ if ((req->newlen - req->newidx) >= sizeof(ipod_key))
+ return (EINVAL);
+
+ arg2 = (req->newlen - req->newidx);
+ error = SYSCTL_IN(req, ipod_key, arg2);
+ memset(&ipod_key[arg2], 0, sizeof(ipod_key) - arg2);
+
+ return (error);
+}
+
+SYSCTL_PROC(_net_inet_icmp_ipod, OID_AUTO, key, CTLTYPE_STRING | CTLFLAG_RW,
+ NULL, 0, ipod_getkey, "A", "");
+
+static void
+icmp_pingofdeath(icp, ip, hlen)
+ struct icmp *icp;
+ struct ip *ip;
+ int hlen;
+{
+ int doit = 0;
+ /*
+ * If IPOD not enabled or wrong ICMP code, ignore.
+ */
+ if (!ipod_enabled || icp->icmp_code != 6)
+ return;
+
+ /*
+ * First check the source address info.
+ * If host not set, ignore.
+ */
+ if (ipod_host != 0xffffffff &&
+ (ntohl(ip->ip_src.s_addr) & ipod_mask) == 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 (ip->ip_len >= strlen(ipod_key) &&
+ IPOD_VALID_KEY(icp->icmp_data))
+ doit = 1;
+ } else {
+ doit = 1;
+ }
+ }
+
+ if (doit) {
+ ipod_enabled = 0;
+ printf("IPOD: reboot forced by %lx...\n",
+ ntohl(ip->ip_src.s_addr));
+ cpu_reset();
+ } else {
+ log(LOG_ERR, "IPOD: from %lx rejected\n",
+ ntohl(ip->ip_src.s_addr));
+ }
+}
+#endif
--- include/linux/sysctl.h~ 2004-04-13 15:41:44.000000000 -0600
+++ include/linux/sysctl.h 2004-07-12 16:05:14.000000000 -0600
@@ -299,6 +299,13 @@
NET_TCP_FRTO=92,
NET_TCP_LOW_LATENCY=93,
NET_IPV4_IPFRAG_SECRET_INTERVAL=94,
diff -urN linux-2.4.19/include/linux/sysctl.h linux-2.4.19a/include/linux/sysctl.h
--- linux-2.4.19/include/linux/sysctl.h 2002-08-02 18:39:46.000000000 -0600
+++ linux-2.4.19/include/linux/sysctl.h 2005-11-11 14:39:41.000000000 -0700
@@ -291,7 +291,14 @@
NET_IPV4_NONLOCAL_BIND=88,
NET_IPV4_ICMP_RATELIMIT=89,
NET_IPV4_ICMP_RATEMASK=90,
- NET_TCP_TW_REUSE=91
+ NET_TCP_TW_REUSE=91,
+
+ /* CONFIG_ICMP_PINGOFDEATH */
+ NET_IPV4_ICMP_POD_ENABLED=95,
+ NET_IPV4_ICMP_POD_HOST=96,
+ NET_IPV4_ICMP_POD_MASK=97,
+ NET_IPV4_ICMP_POD_KEY=98,
+ NET_IPV4_ICMP_POD_VERSION=99,
+ NET_IPV4_ICMP_IPOD_ENABLED=92,
+ NET_IPV4_ICMP_IPOD_HOST=93,
+ NET_IPV4_ICMP_IPOD_MASK=94,
+ NET_IPV4_ICMP_IPOD_KEY=95,
+ NET_IPV4_ICMP_IPOD_VERSION=96
};
enum {
--- net/ipv4/Config.in~ 2001-12-21 10:42:05.000000000 -0700
+++ net/ipv4/Config.in 2004-07-12 16:06:56.000000000 -0600
@@ -44,3 +44,8 @@
if [ "$CONFIG_NETFILTER" != "n" ]; then
source net/ipv4/netfilter/Config.in
diff -urN linux-2.4.19/net/ipv4/Config.in linux-2.4.19a/net/ipv4/Config.in
--- linux-2.4.19/net/ipv4/Config.in 2001-12-21 10:42:05.000000000 -0700
+++ linux-2.4.19/net/ipv4/Config.in 2005-11-11 14:41:45.000000000 -0700
@@ -15,6 +15,8 @@
bool ' IP: use TOS value as routing key' CONFIG_IP_ROUTE_TOS
bool ' IP: verbose route monitoring' CONFIG_IP_ROUTE_VERBOSE
bool ' IP: large routing tables' CONFIG_IP_ROUTE_LARGE_TABLES
+ # Emulab Special
+ bool ' ICMP: ICMP Ping-of-Death (Emulab)' CONFIG_ICMP_PINGOFDEATH
fi
+
+#
+# Emulab special
+#
+bool ' ICMP: ICMP Ping-of-Death (Emulab)' CONFIG_ICMP_PINGOFDEATH
--- net/ipv4/icmp.c~ 2004-04-13 15:07:12.000000000 -0600
+++ net/ipv4/icmp.c 2004-07-12 16:18:51.000000000 -0600
@@ -840,6 +840,67 @@
bool ' IP: kernel level autoconfiguration' CONFIG_IP_PNP
if [ "$CONFIG_IP_PNP" = "y" ]; then
diff -urN linux-2.4.19/net/ipv4/icmp.c linux-2.4.19a/net/ipv4/icmp.c
--- linux-2.4.19/net/ipv4/icmp.c 2002-08-02 18:39:46.000000000 -0600
+++ linux-2.4.19/net/ipv4/icmp.c 2005-11-11 16:24:24.000000000 -0700
@@ -870,6 +870,67 @@
in_dev_put(in_dev);
}
......@@ -40,75 +45,64 @@
+u32 sysctl_ipod_mask = 0xffffffff;
+char sysctl_ipod_key[32+1] = { "SETMETOSOMETHINGTHIRTYTWOBYTES!!" };
+#define IPOD_CHECK_KEY \
+ (sysctl_ipod_key[0] != 0)
+ (sysctl_ipod_key[0] != 0)
+#define IPOD_VALID_KEY(d) \
+ (strncmp(sysctl_ipod_key, (char *)(d), strlen(sysctl_ipod_key)) == 0)
+ (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;
+ 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));
+ 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;
+ /*
+ * 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;
+ }
+ }
+ /*
+ * 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));
+ }
+ 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)
{
}
8ics[0].IcmpOutSrcQuenchs, &icmp_statistics[0].IcmpInSrcQuenchs, icmp_unreach, 1 },
/* REDIRECT (5) */
{ &icmp_statistics[0].IcmpOutRedirects, &icmp_statistics[0].IcmpInRedirects, icmp_redirect, 1 },
+#ifdef CONFIG_ICMP_PINGOFDEATH
+/* PING_OF_DEATH (6) */
+ { &icmp_statistics[0].dummy, &icmp_statistics[0].dummy, icmp_ping_of_death, 1, },
+#else
{ &icmp_statistics[0].dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1 },
+#endif
{ &icmp_statistics[0].dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1 },
/* ECHO (8) */
{ &icmp_statistics[0].IcmpOutEchos, &icmp_statistics[0].IcmpInEchos, icmp_echo, 0 },
--- net/ipv4/sysctl_net_ipv4.c~ 2004-04-13 15:07:14.000000000 -0600
+++ net/ipv4/sysctl_net_ipv4.c 2004-07-12 16:24:35.000000000 -0600
diff -urN linux-2.4.19/net/ipv4/sysctl_net_ipv4.c linux-2.4.19a/net/ipv4/sysctl_net_ipv4.c
--- linux-2.4.19/net/ipv4/sysctl_net_ipv4.c 2002-08-02 18:39:46.000000000 -0600
+++ linux-2.4.19/net/ipv4/sysctl_net_ipv4.c 2005-11-11 16:34:25.000000000 -0700
@@ -22,6 +22,13 @@
extern int sysctl_icmp_echo_ignore_all;
extern int sysctl_icmp_echo_ignore_broadcasts;
......@@ -123,7 +117,7 @@
/* From ip_fragment.c */
extern int sysctl_ipfrag_low_thresh;
@@ -177,6 +184,18 @@
@@ -176,6 +183,18 @@
{NET_IPV4_ICMP_IGNORE_BOGUS_ERROR_RESPONSES, "icmp_ignore_bogus_error_responses",
&sysctl_icmp_ignore_bogus_error_responses, sizeof(int), 0644, NULL,
&proc_dointvec},
......@@ -138,7 +132,7 @@
+ &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
+#endif
{NET_IPV4_ROUTE, "route", NULL, 0, 0555, ipv4_route_table},
#ifdef CONFIG_IP_MULTICAST
{NET_IPV4_IGMP_MAX_MEMBERSHIPS, "igmp_max_memberships",
--- include/linux/sysctl.h 2002/01/17 18:38:13 1.1
+++ include/linux/sysctl.h 2002/12/19 00:12:10
@@ -284,6 +284,13 @@
NET_TCP_APP_WIN=86,
NET_TCP_ADV_WIN_SCALE=87,
NET_IPV4_NONLOCAL_BIND=88,
+
+ /* CONFIG_ICMP_PINGOFDEATH */
+ NET_IPV4_ICMP_POD_ENABLED=89,
+ NET_IPV4_ICMP_POD_HOST=90,
+ NET_IPV4_ICMP_POD_MASK=91,
+ NET_IPV4_ICMP_POD_KEY=92,
+ NET_IPV4_ICMP_POD_VERSION=93,
};
enum {
--- net/ipv4/Config.in 2001/11/16 22:16:12 1.1
+++ net/ipv4/Config.in 2002/04/17 04:14:30
@@ -50,3 +50,8 @@
if [ "$CONFIG_NETFILTER" != "n" ]; then
source net/ipv4/ipvs/Config.in
fi
+
+#
+# Emulab special
+#
+bool ' ICMP: ICMP Ping-of-Death (Emulab)' CONFIG_ICMP_PINGOFDEATH
--- net/ipv4/icmp.c 2001/11/16 19:13:03 1.1
+++ net/ipv4/icmp.c 2002/12/19 19:15:51
@@ -856,6 +856,67 @@
in_dev_put(in_dev);
}
+#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)
{
}
@@ -962,7 +1023,12 @@
{ &icmp_statistics[0].IcmpOutSrcQuenchs, &icmp_statistics[0].IcmpInSrcQuenchs, icmp_unreach, 1, },
/* REDIRECT (5) */
{ &icmp_statistics[0].IcmpOutRedirects, &icmp_statistics[0].IcmpInRedirects, icmp_redirect, 1, },
+#ifdef CONFIG_ICMP_PINGOFDEATH
+/* PING_OF_DEATH (6) */
+ { &dummy, &dummy, icmp_ping_of_death, 1, },
+#else
{ &dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1, },
+#endif
{ &dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1, },
/* ECHO (8) */
{ &icmp_statistics[0].IcmpOutEchos, &icmp_statistics[0].IcmpInEchos, icmp_echo, 0, },
--- net/ipv4/sysctl_net_ipv4.c 2002/01/17 18:29:00 1.1
+++ net/ipv4/sysctl_net_ipv4.c 2002/12/19 00:11:58
@@ -22,6 +22,13 @@
extern int sysctl_icmp_echo_ignore_all;
extern int sysctl_icmp_echo_ignore_broadcasts;
extern int sysctl_icmp_ignore_bogus_error_responses;
+#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;
@@ -186,6 +193,18 @@
&sysctl_icmp_paramprob_time, sizeof(int), 0644, NULL, &proc_dointvec},
{NET_IPV4_ICMP_ECHOREPLY_RATE, "icmp_echoreply_rate",
&sysctl_icmp_echoreply_time, sizeof(int), 0644, NULL, &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
{NET_IPV4_ROUTE, "route", NULL, 0, 0555, ipv4_route_table},
#ifdef CONFIG_IP_MULTICAST
{NET_IPV4_IGMP_MAX_MEMBERSHIPS, "igmp_max_memberships",
diff -ur linux-2.6.11-orig/include/linux/sysctl.h linux-2.6.11/include/linux/sysctl.h
--- linux-2.6.11-orig/include/linux/sysctl.h 2005-06-17 15:06:02.000000000 -0600
+++ linux-2.6.11/include/linux/sysctl.h 2005-06-21 17:28:31.000000000 -0600
@@ -350,6 +350,13 @@
NET_TCP_MODERATE_RCVBUF=106,
NET_TCP_TSO_WIN_DIVISOR=107,
NET_TCP_BIC_BETA=108,
+
+ /* CONFIG_ICMP_PINGOFDEATH */
+ NET_IPV4_ICMP_POD_ENABLED=109,
+ NET_IPV4_ICMP_POD_HOST=110,
+ NET_IPV4_ICMP_POD_MASK=111,
+ NET_IPV4_ICMP_POD_KEY=112,
+ NET_IPV4_ICMP_POD_VERSION=113,
};
enum {
diff -ur linux-2.6.11-orig/net/ipv4/Kconfig linux-2.6.11/net/ipv4/Kconfig
--- linux-2.6.11-orig/net/ipv4/Kconfig 2005-06-17 15:06:01.000000000 -0600
+++ linux-2.6.11/net/ipv4/Kconfig 2005-06-22 15:21:33.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.11-orig/net/ipv4/icmp.c linux-2.6.11/net/ipv4/icmp.c
--- linux-2.6.11-orig/net/ipv4/icmp.c 2005-06-17 15:06:01.000000000 -0600
+++ linux-2.6.11/net/ipv4/icmp.c 2005-06-22 15:29:10.000000000 -0600
@@ -913,6 +913,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)
{
}
@@ -1027,12 +1088,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.11-orig/net/ipv4/sysctl_net_ipv4.c linux-2.6.11/net/ipv4/sysctl_net_ipv4.c
--- linux-2.6.11-orig/net/ipv4/sysctl_net_ipv4.c 2005-03-02 00:38:17.000000000 -0700
+++ linux-2.6.11/net/ipv4/sysctl_net_ipv4.c 2005-06-21 17:38:50.000000000 -0600
@@ -23,6 +23,13 @@
extern int sysctl_icmp_echo_ignore_all;
extern int sysctl_icmp_echo_ignore_broadcasts;
extern int sysctl_icmp_ignore_bogus_error_responses;
+#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;
@@ -690,6 +697,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 }
};
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,