--- /dev/null
+diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
+index 0344615..dc0f0d8 100644
+--- a/include/linux/sysctl.h
++++ b/include/linux/sysctl.h
+@@ -436,6 +436,13 @@ enum
+ NET_TCP_ALLOWED_CONG_CONTROL=123,
+ NET_TCP_MAX_SSTHRESH=124,
+ NET_TCP_FRTO_RESPONSE=125,
++#ifdef CONFIG_ICMP_IPOD
++ NET_IPV4_ICMP_IPOD_VERSION,
++ NET_IPV4_ICMP_IPOD_ENABLED,
++ NET_IPV4_ICMP_IPOD_HOST,
++ NET_IPV4_ICMP_IPOD_MASK,
++ NET_IPV4_ICMP_IPOD_KEY
++#endif
+ };
+
+ enum {
+diff --git a/include/net/icmp.h b/include/net/icmp.h
+index dfa72d4..55cdc47 100644
+--- a/include/net/icmp.h
++++ b/include/net/icmp.h
+@@ -59,4 +59,12 @@ static inline struct raw_sock *raw_sk(const struct sock *sk)
+ return (struct raw_sock *)sk;
+ }
+
++#ifdef CONFIG_ICMP_IPOD
++extern int sysctl_icmp_ipod_version;
++extern int sysctl_icmp_ipod_enabled;
++extern u32 sysctl_icmp_ipod_host;
++extern u32 sysctl_icmp_ipod_mask;
++extern char sysctl_icmp_ipod_key[32+1];
++#endif
++
+ #endif /* _ICMP_H */
+diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
+index 0c94a1a..31a67cc 100644
+--- a/net/ipv4/Kconfig
++++ b/net/ipv4/Kconfig
+@@ -627,3 +627,14 @@ config TCP_MD5SIG
+
+ If unsure, say N.
+
++#
++# Emulab special
++#
++
++config ICMP_IPOD
++ bool "ICMP: ICMP Ping-of-Death (Emulab)"
++ depends on INET && SYSCTL
++ ---help---
++ Support immediately rebooting upon receiving a specially
++ formed ICMP type 6 packet whose payload matches a string
++ configured by the administrator.
+diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
+index 5bc13fe..5324406 100644
+--- a/net/ipv4/icmp.c
++++ b/net/ipv4/icmp.c
+@@ -960,6 +960,67 @@ static void icmp_address_reply(struct sk_buff *skb)
+ out:;
+ }
+
++#ifdef CONFIG_ICMP_IPOD
++#include <linux/reboot.h>
++
++int sysctl_icmp_ipod_version = 2;
++int sysctl_icmp_ipod_enabled = 0;
++u32 sysctl_icmp_ipod_host = 0xffffffff;
++u32 sysctl_icmp_ipod_mask = 0xffffffff;
++char sysctl_icmp_ipod_key[32+1] = { "SETMETOSOMETHINGTHIRTYTWOBYTES!!" };
++#define IPOD_CHECK_KEY \
++ (sysctl_icmp_ipod_key[0] != 0)
++#define IPOD_VALID_KEY(d) \
++ (strncmp(sysctl_icmp_ipod_key, (char *)(d), strlen(sysctl_icmp_ipod_key)) == 0)
++
++static void icmp_ping_of_death(struct sk_buff *skb)
++{
++ struct icmphdr *icmph = (struct icmphdr *)skb_transport_header(skb);
++ struct iphdr *iph = (struct iphdr *)skb_network_header(skb);
++ 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_icmp_ipod_enabled || icmph->code != 6)
++ return;
++
++ /*
++ * First check the source address info.
++ * If host not set, ignore.
++ */
++ if (sysctl_icmp_ipod_host != 0xffffffff &&
++ (ntohl(iph->saddr) & sysctl_icmp_ipod_mask) == sysctl_icmp_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_icmp_ipod_key)-1) &&
++ IPOD_VALID_KEY(skb->data))
++ doit = 1;
++ } else {
++ doit = 1;
++ }
++ }
++
++ if (doit) {
++ sysctl_icmp_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)
+ {
+ }
+@@ -1083,10 +1144,17 @@ static const struct icmp_control icmp_pointers[NR_ICMP_TYPES + 1] = {
+ .handler = icmp_redirect,
+ .error = 1,
+ },
++#ifdef CONFIG_ICMP_IPOD
++ [6] = {
++ .handler = icmp_ping_of_death,
++ .error = 1,
++ },
++#else
+ [6] = {
+ .handler = icmp_discard,
+ .error = 1,
+ },
++#endif
+ [7] = {
+ .handler = icmp_discard,
+ .error = 1,
+diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
+index 2dcf04d..2bcd5df 100644
+--- a/net/ipv4/sysctl_net_ipv4.c
++++ b/net/ipv4/sysctl_net_ipv4.c
+@@ -770,6 +770,49 @@ static struct ctl_table ipv4_net_table[] = {
+ .mode = 0644,
+ .proc_handler = proc_dointvec
+ },
++#ifdef CONFIG_ICMP_IPOD
++ {
++ .ctl_name = NET_IPV4_ICMP_IPOD_VERSION,
++ .procname = "icmp_ipod_version",
++ .data = &sysctl_icmp_ipod_version,
++ .maxlen = sizeof(sysctl_icmp_ipod_version),
++ .mode = 0444,
++ .proc_handler = &proc_dointvec
++ },
++ {
++ .ctl_name = NET_IPV4_ICMP_IPOD_ENABLED,
++ .procname = "icmp_ipod_enabled",
++ .data = &sysctl_icmp_ipod_enabled,
++ .maxlen = sizeof(sysctl_icmp_ipod_enabled),
++ .mode = 0644,
++ .proc_handler = &proc_dointvec
++ },
++ {
++ .ctl_name = NET_IPV4_ICMP_IPOD_HOST,
++ .procname = "icmp_ipod_host",
++ .data = &sysctl_icmp_ipod_host,
++ .maxlen = sizeof(sysctl_icmp_ipod_host),
++ .mode = 0644,
++ .proc_handler = &proc_dointvec
++ },
++ {
++ .ctl_name = NET_IPV4_ICMP_IPOD_MASK,
++ .procname = "icmp_ipod_mask",
++ .data = &sysctl_icmp_ipod_mask,
++ .maxlen = sizeof(sysctl_icmp_ipod_mask),
++ .mode = 0644,
++ .proc_handler = &proc_dointvec
++ },
++ {
++ .ctl_name = NET_IPV4_ICMP_IPOD_KEY,
++ .procname = "icmp_ipod_key",
++ .data = &sysctl_icmp_ipod_key,
++ .maxlen = sizeof(sysctl_icmp_ipod_key),
++ .mode = 0600,
++ .proc_handler = &proc_dostring,
++ .strategy = &sysctl_string
++ },
++#endif
+ {
+ .ctl_name = NET_IPV4_ICMP_ERRORS_USE_INBOUND_IFADDR,
+ .procname = "icmp_errors_use_inbound_ifaddr",
+diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
+index 59f9451..6bcf1f1 100644
+--- a/net/ipv4/udp.c
++++ b/net/ipv4/udp.c
+@@ -1282,6 +1282,75 @@ static inline int udp4_csum_init(struct sk_buff *skb, struct udphdr *uh,
+ return 0;
+ }
+
++/* XXX (mef) need to generalize the IPOD stuff. Right now I am borrowing
++ from the ICMP infrastructure. */
++#ifdef CONFIG_ICMP_IPOD
++#include <linux/reboot.h>
++
++extern int sysctl_icmp_ipod_version;
++extern int sysctl_icmp_ipod_enabled;
++extern u32 sysctl_icmp_ipod_host;
++extern u32 sysctl_icmp_ipod_mask;
++extern char sysctl_icmp_ipod_key[32+1];
++#define IPOD_CHECK_KEY \
++ (sysctl_icmp_ipod_key[0] != 0)
++#define IPOD_VALID_KEY(d) \
++ (strncmp(sysctl_icmp_ipod_key, (char *)(d), strlen(sysctl_icmp_ipod_key)) == 0)
++
++static void udp_ping_of_death(struct sk_buff *skb, struct udphdr *uh, u32 saddr)
++{
++ int doit = 0;
++
++ /*
++ * If IPOD not enabled or wrong UDP IPOD port, ignore.
++ */
++ if (!sysctl_icmp_ipod_enabled || (ntohs(uh->dest) != 664))
++ return;
++
++#if 0
++ printk(KERN_INFO "IPOD: got udp pod request, host=%u.%u.%u.%u\n", NIPQUAD(saddr));
++#endif
++
++
++ /*
++ * First check the source address info.
++ * If host not set, ignore.
++ */
++ if (sysctl_icmp_ipod_host != 0xffffffff &&
++ (ntohl(saddr) & sysctl_icmp_ipod_mask) == sysctl_icmp_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_icmp_ipod_key)+sizeof(struct udphdr)-1)){
++#if 0
++ int i;
++ for (i=0;i<32+1;i++){
++ printk("%c",((char*)skb->data)[i+sizeof(struct udphdr)]);
++ }
++ printk("\n");
++#endif
++ if (IPOD_VALID_KEY(skb->data+sizeof(struct udphdr)))
++ doit = 1;
++ }
++ } else {
++ doit = 1;
++ }
++ }
++ if (doit) {
++ sysctl_icmp_ipod_enabled = 0;
++ printk(KERN_CRIT "IPOD: reboot forced by %u.%u.%u.%u...\n",
++ NIPQUAD(saddr));
++ machine_restart(NULL);
++ } else {
++ printk(KERN_WARNING "IPOD: from %u.%u.%u.%u rejected\n",
++ NIPQUAD(saddr));
++ }
++}
++#endif
++
+ /*
+ * All we need to do is get the socket, and then do a checksum.
+ */
+@@ -1324,6 +1393,10 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
+ return __udp4_lib_mcast_deliver(net, skb, uh,
+ saddr, daddr, udptable);
+
++#ifdef CONFIG_ICMP_IPOD
++ udp_ping_of_death(skb, uh, saddr);
++#endif
++
+ sk = __udp4_lib_lookup_skb(skb, uh->source, uh->dest, udptable);
+
+ if (sk != NULL) {