From b78b4a0b9256d477c3bdb70693a66de3da3865d2 Mon Sep 17 00:00:00 2001
From: Aaron Klingaman <alk@cs.princeton.edu>
Date: Mon, 12 Apr 2004 17:00:14 +0000
Subject: [PATCH] ipod

---
 INTEL_LICENSE.txt |  40 ++++++
 Makefile          |  37 +++++
 README            |  55 ++++++++
 disable_pod.sh    |  28 ++++
 enable_pod.sh     |  76 +++++++++++
 ipod.spec         |  50 +++++++
 pl-podcntl        |  96 +++++++++++++
 pl-poddoit.c      | 336 ++++++++++++++++++++++++++++++++++++++++++++++
 pl-podset         |  46 +++++++
 pl-podzap         |  41 ++++++
 pod.src           | 122 +++++++++++++++++
 shell_include     | 129 ++++++++++++++++++
 status_pod.sh     |  27 ++++
 test-pod          |  80 +++++++++++
 14 files changed, 1163 insertions(+)
 create mode 100644 INTEL_LICENSE.txt
 create mode 100644 Makefile
 create mode 100644 README
 create mode 100755 disable_pod.sh
 create mode 100755 enable_pod.sh
 create mode 100644 ipod.spec
 create mode 100755 pl-podcntl
 create mode 100644 pl-poddoit.c
 create mode 100755 pl-podset
 create mode 100755 pl-podzap
 create mode 100755 pod.src
 create mode 100755 shell_include
 create mode 100755 status_pod.sh
 create mode 100755 test-pod

diff --git a/INTEL_LICENSE.txt b/INTEL_LICENSE.txt
new file mode 100644
index 0000000..f0b394d
--- /dev/null
+++ b/INTEL_LICENSE.txt
@@ -0,0 +1,40 @@
+# Copyright (c) 2003 Intel Corporation
+# All rights reserved.
+
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+
+#     * Redistributions in binary form must reproduce the above
+#       copyright notice, this list of conditions and the following
+#       disclaimer in the documentation and/or other materials provided
+#       with the distribution.
+
+#     * Neither the name of the Intel Corporation nor the names of its
+#       contributors may be used to endorse or promote products derived
+#       from this software without specific prior written permission.
+
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF
+# YOUR JURISDICTION. It is licensee's responsibility to comply with any
+# export regulations applicable in licensee's jurisdiction. Under
+# CURRENT (May 2000) U.S. export regulations this software is eligible
+# for export from the U.S. and can be downloaded by or otherwise
+# exported or reexported worldwide EXCEPT to U.S. embargoed destinations
+# which include Cuba, Iraq, Libya, North Korea, Iran, Syria, Sudan,
+# Afghanistan and any other country to which the U.S. has embargoed
+# goods and services.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..338dc58
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,37 @@
+# Makefile for building and installing the application
+#   level tools for the Planetlab "ping of death" feature.
+#
+# Targets are:
+# all: builds all of the components
+# install: installes the tools into the planetlab bin directory
+# test: runs the tests on the current machine
+#
+
+ALLBUILD=pl-poddoit pod ipod-2.0.tar.gz
+PLBIN=/usr/local/planetlab/bin/
+INIT=/etc/init.d/
+
+all: $(ALLBUILD)
+
+pod: pod.src disable_pod.sh  enable_pod.sh  status_pod.sh
+	./shell_include --source pod.src --destination pod 
+
+ipod-2.0.tar.gz: pod ipod.spec
+	mkdir ipod-2.0
+	cp ipod.spec disable_pod.sh enable_pod.sh INTEL_LICENSE.txt ipod.patch \
+	Makefile pl-podcntl pl-poddoit.c pl-podset pl-podzap pod.src \
+	README shell_include status_pod.sh test-pod ipod-2.0
+	tar cvfz ipod-2.0.tar.gz ipod-2.0
+	rm -rf ipod-2.0
+
+pl-poddoit: pl-poddoit.c
+	gcc pl-poddoit.c -o pl-poddoit
+
+install: all
+	cp pl-poddoit $(PLBIN)
+	chmod 555 $(PLBIN)/pl-poddoit
+	cp pod $(INIT)
+	chmod 555 $(INIT)/pod
+
+clean:
+	rm -f pod pl-poddoit ipod-2.0.tar.gz
diff --git a/README b/README
new file mode 100644
index 0000000..584c47e
--- /dev/null
+++ b/README
@@ -0,0 +1,55 @@
+Planetlab Ping-of-Death (POD)
+-----------------------------
+The Planetlab POD is a Linux kernel patch that creates the feature
+of resetting and rebooting a computer when a particularily
+formatted ICMP "ping" commmand is received.
+
+A PlanetLab node's kernel gets a host, mask and hash value through
+sysctl's that are performed on the node.  The node then looks
+for an ICMP packet from a host matching the host/mask and, if the
+packet payload is the hash value, the node forces an immediate
+reboot.
+
+From a controlling host's side, one invokes commands on the
+remote node to set the host, mask and hash values and remembering
+the hash value.  When the rebooting of a remote node is required,
+the remembered hash value is looked up and sent to the node
+in a specially constructed ICMP packet.
+
+This POD system uses the same packet definition as EMULAB and uses
+the some code from EMULAB to generate and transmit the packet.
+No reason to invent something new.
+
+The remote execution (ssh commands) are all done as "idsl1".
+
+Contolling host tools:
+pl-podset:  set the host and hash on a remote node
+        Call: pl-podset hostIP maskIP targetName
+        Uses ssh to call 'pl-podcntl' on the remote node to
+        set the host and hash in that node.  Also saves the
+        information into the file './HashFile'.
+pl-podzap: send ICMP packet to node to resetit
+        Call: pl-podzap targetName
+        Fetches parameters from the file './HashFile' and
+        calls 'pl-poddoit' on the 'hostIP' machine to send the 
+        reset ICMP packet to the specified target node.
+        Note that this relies on the planetlab node that
+        was specified in the 'pl-podset' command to actually
+        do the packet transmission.
+pl-poddoit: send the ICMP packet (called by 'pl-podzap')
+        Routine that constructs an ICMP packet of the proper
+        format and send it to the node.
+
+Planetlab node scripts:
+pl-podcntl: set the host and hash into the kernel
+        Call: pl-podcntl hostIP maskIP hashValue
+        Sets the specified values into the kernel and enables
+        the POD filtering operation.
+
+EXAMPLE
+-------
+Setting a node to be able to reset (assuming running on 123.123.12.23):
+    pl-podset 123.123.12.23 255.255.255.255 planetlab-1.stanford.edu
+
+To later reset the node (command performed on 123.123.12.23):
+    pl-podzap planetlab-1.stanford.edu
diff --git a/disable_pod.sh b/disable_pod.sh
new file mode 100755
index 0000000..bba89f8
--- /dev/null
+++ b/disable_pod.sh
@@ -0,0 +1,28 @@
+#! /bin/bash
+#include INTEL_LICENSE.txt
+#
+########################################################################
+#
+# Disable Ping Of Death
+#
+########################################################################
+#
+# DESCRIPTION
+#
+# The disable_pod function turns off the pod syscntl
+#
+# HISTORY
+#
+# May 17, 2003    -   Paul Brett <paul.brett@intel.com>
+#                     Initial version based on the work of 
+#                     Robert Adams <robert.adams@intel.com> and EMULAB
+#
+
+function disable_pod()
+{
+    local SYSCTL=/sbin/sysctl
+    $SYSCTL -w net.ipv4.icmp_ipod_enabled=0 >/dev/null
+    return 0
+}
+
+
diff --git a/enable_pod.sh b/enable_pod.sh
new file mode 100755
index 0000000..e48c91b
--- /dev/null
+++ b/enable_pod.sh
@@ -0,0 +1,76 @@
+#! /bin/bash
+#include INTEL_LICENSE.txt
+#
+########################################################################
+#
+# Enable Ping Of Death
+#
+########################################################################
+#
+# DESCRIPTION
+#
+# The Enable_POD function is passed the IP_SUBNET, IP_MASK and HASH and
+# does all the dirty muching about with syscontrols
+#
+# HISTORY
+#
+# May 17, 2003    -   Paul Brett <paul.brett@intel.com>
+#                     Initial version based on the work of 
+#                     Robert Adams <robert.adams@intel.com> and EMULAB
+#
+
+function enable_pod()
+{
+    local SYSCTL=/sbin/sysctl
+
+    local IP_SUBNET=$1
+    local IP_MASK=$2
+    local IP_HASH=$3
+
+    # Grotesque sed/awk converts IP addrs into an integer for sysctl
+    local IPODHOST=`echo $IP_SUBNET | \
+              sed -e 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1 \2 \3 \4/' | \
+              awk '{ printf "%d\n", $1*16777216+$2*65536+$3*256+$4 }'`
+    local IPODMASK=`echo $IP_MASK | \
+              sed -e 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1 \2 \3 \4/' | \
+              awk '{ printf "%d\n", $1*16777216+$2*65536+$3*256+$4 }'`
+    local IPODKEY=`echo $HASH | \
+              sed -e 's/\(.*\)/\1/'`
+
+    # figure out the version
+    local version=`$SYSCTL net.ipv4.icmp_ipod_version 2>/dev/null`
+    if [[ "$version" == "" ]]
+    then
+        $SYSCTL net.ipv4.icmp_ipod_enabled >/dev/null 2>&1
+        case $? in
+            0)
+                version=1
+                ;;
+            *)
+                version=0
+                ;;
+        esac
+    fi
+
+    # enable if possible
+    case $version in
+        0)
+            return 1
+            ;;
+        1)
+            $SYSCTL -w net.ipv4.icmp_ipod_host=$IPODHOST >/dev/null
+            $SYSCTL -w net.ipv4.icmp_ipod_enabled=1 >/dev/null
+            Success=0
+            ;;
+        *)
+            $SYSCTL -w net.ipv4.icmp_ipod_host=$IPODHOST >/dev/null
+            Success=$?
+            $SYSCTL -w net.ipv4.icmp_ipod_mask=$IPODMASK >/dev/null
+            $SYSCTL -w net.ipv4.icmp_ipod_key=$IPODKEY >/dev/null
+            $SYSCTL -w net.ipv4.icmp_ipod_enabled=1 >/dev/null
+        ;;
+    esac
+    return $Success
+}
+
+
diff --git a/ipod.spec b/ipod.spec
new file mode 100644
index 0000000..3161ead
--- /dev/null
+++ b/ipod.spec
@@ -0,0 +1,50 @@
+Summary: PlanetLab ICMP Ping of Death
+Name: ipod
+Version: 2.0
+Release: 2
+Copyright: GPL
+Group: System Environment/Kernel
+Source: ipod-2.0.tar.gz
+
+%description
+Startup service to enable Ping Of Death
+
+%prep
+
+%setup
+
+%build
+make
+
+%install
+make install
+
+%clean
+
+%files
+%defattr(-, root, root)
+/etc/init.d/pod
+/usr/local/planetlab/bin/pl-poddoit
+
+%pre
+
+%post 
+RUNLEVEL=`/sbin/runlevel`
+
+if [ "$1" = 1 ]; then
+	chkconfig --add pod
+	chkconfig pod on
+
+	if [[ "$RUNLEVEL" != "unknown" ]]; then
+		/etc/init.d/pod start
+	fi
+fi
+
+%preun
+if [ "$1" = 0 ]; then
+	chkconfig pod off
+	chkconfig --del pod
+fi
+
+%postun
+
diff --git a/pl-podcntl b/pl-podcntl
new file mode 100755
index 0000000..0d0c191
--- /dev/null
+++ b/pl-podcntl
@@ -0,0 +1,96 @@
+#/bin/sh -
+#
+# Enable ICMP ping-of-death.  Runs on the target node and sets the
+# passed parameters into the kernel.
+# Invocation: pl-podcntl HOSTIP HOSTMASK HASH
+
+# -----------------------------------------------------------------
+# $Header: /shareddata/CVS/planetlab/admin/ipod/pl-podcntl,v 1.2 2003/01/18 01:43:48 radams Exp $
+#
+# Copyright (c) 2003 Intel Corporation
+# All rights reserved.
+# This file is distributed under the terms in the attached INTEL_LICENSE
+# file.  If you do not find this file, a copy can be obtained by
+# writing to Intel Research Berkeley; Attention: Intel License Inquiry;
+# 2150 Shattuck Avenue; Berkeley, CA 94704
+# -----------------------------------------------------------------
+
+# Modified from origional EMULAB script.  Origional copyright:
+# EMULAB-COPYRIGHT
+# Copyright (c) 2000-2002 University of Utah and the Flux Group.
+# All rights reserved.
+#
+# Enable ICMP ping-of-death
+# Support both the old style (host only) and the new style (host+mask+key)
+#
+
+IPODHOSTP=$1
+IPODMASKP=$2
+IPODHASHP=$3
+
+SYSCTL="/sbin/sysctl"
+
+# Grotesque sed/awk converts IP addrs into an integer for sysctl
+if [ x"$IPODHOSTP" != x ]; then
+	IPODHOST=`echo $IPODHOSTP | \
+		sed -e 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1 \2 \3 \4/' | \
+		awk '{ printf "%d\n", $1*16777216+$2*65536+$3*256+$4 }'`
+	IPODMASK=`echo $IPODMASKP | \
+		sed -e 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1 \2 \3 \4/' | \
+		awk '{ printf "%d\n", $1*16777216+$2*65536+$3*256+$4 }'`
+	IPODKEY=`echo $IPODHASHP | \
+		sed -e 's/\(.*\)/\1/'`
+
+	echo "IPODHOST = $IPODHOST"
+	echo "IPODMASK = $IPODMASK"
+	echo "IPODKEY = $IPODKEY"
+
+	# figure out the version
+	version=`$SYSCTL net.ipv4.icmp_ipod_version 2>/dev/null`
+	if [ "$version"x = x ]; then
+		$SYSCTL net.ipv4.icmp_ipod_enabled >/dev/null 2>&1
+		case $? in
+		0)
+			version=1
+			;;
+		*)
+			version=0
+			;;
+		esac
+	fi
+
+	echo "Version = $version"
+	# enable if possible
+	case $version in
+	0)
+		echo "*** WARNING: no IPOD sysctls, not enabled"
+		exit 1
+		;;
+	1)
+		$SYSCTL -w net.ipv4.icmp_ipod_host=$IPODHOST >/dev/null
+		$SYSCTL -w net.ipv4.icmp_ipod_enabled=1 >/dev/null
+		str="Old-style"
+		;;
+	*)
+		$SYSCTL -w net.ipv4.icmp_ipod_host=$IPODHOST >/dev/null
+		Success=$?
+		$SYSCTL -w net.ipv4.icmp_ipod_mask=$IPODMASK >/dev/null
+		$SYSCTL -w net.ipv4.icmp_ipod_key=$IPODKEY >/dev/null
+		$SYSCTL -w net.ipv4.icmp_ipod_enabled=1 >/dev/null
+		str="Authenticated"
+		;;
+	esac
+	echo Success = $Success
+	if [[ $Success -eq 0 ]] ; then
+		IPODHOST=`echo $IPODINFO | \
+            sed -e 's/.*HOST=\([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*\).*/\1/'`
+		IPODMASK=`echo $IPODINFO | \
+            sed -e 's/.*MASK=\([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*\).*/\1/'`
+        echo "$str IPOD enabled from $IPODHOST/$IPODMASK"
+    else
+        echo "*** WARNING: could not set IPOD info, not enabled"
+    fi
+else
+	echo "*** WARNING: no IPOD info, not enabled"
+fi
+
diff --git a/pl-poddoit.c b/pl-poddoit.c
new file mode 100644
index 0000000..20e72c2
--- /dev/null
+++ b/pl-poddoit.c
@@ -0,0 +1,336 @@
+/*
+ * EMULAB-COPYRIGHT
+ * Copyright (c) 2000-2002 University of Utah and the Flux Group.
+ * All rights reserved.
+ */
+
+/*
+ *  Send the magical ping of death ICMP type
+ */
+
+
+#include <time.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+#include <arpa/inet.h>
+
+#define IPOD_ICMPTYPE	6
+#define IPOD_ICMPCODE	6
+#define IPOD_IPLEN	666
+#define IPOD_IDLEN	32
+
+int icmpid = 0;
+static char myid[IPOD_IDLEN];
+static int myidlen = 0;
+
+u_short in_cksum(u_short *addr, int len);
+void icmpmap_init();  /* For getting information */
+void icmp_info(struct icmp *icmp, char *outbuf, int maxlen);
+
+/*
+ * We perform lookups on the hosts, and then store them in a chain
+ * here.
+ */
+
+struct hostdesc {
+	char *hostname;
+	struct in_addr hostaddr;
+	struct hostdesc *next;
+};
+
+struct hostdesc *hostnames;
+struct hostdesc *hosttail;
+
+/*
+ * Set up the list of hosts.  Return the count.
+ */
+
+int makehosts(char **hostlist)
+{
+	int i;
+	struct hostent *hp;
+	struct in_addr tmpaddr;
+	int hostcount = 0;
+	
+	for (i = 0; hostlist[i]; i++) {
+#ifdef DEBUG
+		printf("Resolving %s\n", hostlist[i]);
+#endif
+		if (!hostlist[i] ||
+		    !hostlist[i][0] ||
+		    strlen(hostlist[i]) > MAXHOSTNAMELEN) {
+		    fprintf(stderr, "bad host entry, exiting\n");
+		    exit(-1);
+		}
+		if (!inet_aton(hostlist[i], &tmpaddr)) {
+			if ((hp = gethostbyname(hostlist[i])) == NULL) {
+				/* Could not resolve it.  Skip it. */
+				fprintf(stderr, "%s: unknown host\n",
+					hostlist[i]);
+				continue;
+			}
+			else {
+				memcpy(&tmpaddr.s_addr,
+				       hp->h_addr_list[0],
+				       hp->h_length);
+			}
+		}
+
+		/* The host has been resolved.  Put it in the chain */
+		/* We want to stick it on the end. */
+		if (hostnames == NULL) {
+			hostnames = (struct hostdesc *)
+				malloc(sizeof(*hostnames));
+			if (hostnames == NULL) {
+				perror("hostnames malloc failed");
+				exit(-1);
+			}
+			hosttail = hostnames;
+		} else {
+			hosttail->next = (struct hostdesc *)
+				malloc(sizeof(*hostnames));
+			if (hosttail->next == NULL) {
+				perror("hosttail->next malloc failed");
+				exit(-1);
+			}
+			hosttail = hosttail->next;
+		}
+		hosttail->hostname = strdup(hostlist[i]);
+		if (hosttail->hostname == NULL) {
+			perror("strdup failed");
+			exit(-1);
+		}
+		hosttail->hostaddr = tmpaddr;
+		hosttail->next = NULL;
+		hostcount++;
+	}
+	return hostcount;
+}
+
+void usage(char *prog)
+{
+   fprintf(stderr, "%s [ -i identityfile ] target [ target ... ]\n", prog);
+}
+
+/*
+ * Set up a packet.  Returns the length of the ICMP portion.
+ */
+
+void initpacket(char *buf, int querytype, struct in_addr fromaddr)
+{
+   struct ip *ip = (struct ip *)buf;
+   struct icmp *icmp = (struct icmp *)(ip + 1);
+
+   /* things we customize */
+   int icmplen = 0;
+
+   ip->ip_src = fromaddr;	/* if 0,  have kernel fill in */
+   ip->ip_v   = 4;		/* Always use ipv4 for now */
+   ip->ip_hl  = sizeof *ip >> 2;
+   ip->ip_tos = 0;
+   ip->ip_id  = htons(4321);
+   ip->ip_ttl = 255;
+   ip->ip_p   = 1;
+   ip->ip_sum = 0;                 /* kernel fills in */
+
+   icmp->icmp_seq   = 1;
+   icmp->icmp_cksum = 0;           /* We'll compute it later. */
+   icmp->icmp_type  = querytype; 
+   icmp->icmp_code  = IPOD_ICMPCODE;
+   if (myidlen)
+      memcpy(icmp->icmp_data, myid, myidlen);
+
+   ip->ip_len = IPOD_IPLEN;
+   icmplen = IPOD_IPLEN - sizeof(struct ip);
+   icmp->icmp_cksum = in_cksum((u_short *)icmp, icmplen);
+}
+
+/*
+ * Send all of the ICMP queries.
+ */
+
+void sendpings(int s, int querytype, struct hostdesc *head, int delay,
+	       struct in_addr fromaddr)
+     
+{
+	char buf[1500];
+	struct ip *ip = (struct ip *)buf;
+	struct sockaddr_in dst;
+
+	bzero(buf, 1500);
+	initpacket(buf, querytype, fromaddr);
+	dst.sin_family = AF_INET;
+#ifdef DA_HAS_SIN_LEN
+	dst.sin_len = sizeof(dst);
+#endif
+
+	while (head != NULL) {
+		int rc;
+#ifdef DEBUG
+		printf("pinging %s\n", head->hostname);
+#endif
+		ip->ip_dst.s_addr = head->hostaddr.s_addr;
+		dst.sin_addr = head->hostaddr;
+		rc = sendto(s, buf, ip->ip_len, 0,
+			   (struct sockaddr *)&dst,
+			   sizeof(dst));
+                if (rc != ip->ip_len) {
+			perror("sendto");
+		}
+		/* Don't flood small pipes. */
+		if (delay)
+			usleep(delay);
+		head = head->next;
+	}
+}
+
+/*
+ * Handles our timeout for us.  Called by the signal handler
+ * when we get a SIGARLM.
+ */
+
+void myexit(int whatsig)
+{
+	exit(0);
+}
+
+/*
+ * Open a raw socket for receiving ICMP.  Tell the kernel we want
+ * to supply the IP headers.
+ */
+
+int get_icmp_socket()
+{
+	int s;
+	int on = 1;
+	if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
+		perror("socket");
+		exit(1);
+	}
+	if (setsockopt(s, IPPROTO_IP, IP_HDRINCL,
+		       (const char *)&on, sizeof(on)) < 0) {
+		perror("IP_HDRINCL");
+		exit(1);
+	}
+	return s;
+}
+
+int
+main(int argc, char **argv)
+{
+   int s;
+
+   char *progname;
+   extern char *optarg;         /* getopt variable declarations */
+   extern int optind;
+   char ch;                     /* Holds the getopt result */
+   int hostcount;
+   int delay = 0;
+   int querytype = ICMP_TSTAMP;
+   struct in_addr fromaddr;
+   int timeout = 5;  /* Default to 5 seconds */
+   int identityfile;
+
+   fromaddr.s_addr = 0;
+
+   progname = argv[0];
+
+   querytype = IPOD_ICMPTYPE;  /* the magical death packet number */
+
+   while ((ch = getopt(argc, argv, "i:")) != -1)
+      switch(ch)
+      {
+      case 'i':
+	 if (optarg[0] == '-')
+	    identityfile = 0;
+	 else if ((identityfile = open(optarg, 0)) < 0)
+	 {
+	    perror(optarg);
+	    exit(1);
+	 }
+	 myidlen = read(identityfile, myid, IPOD_IDLEN);
+	 if (optarg[0] != '-')
+	    close(identityfile);
+         if (myidlen != IPOD_IDLEN)
+	 {
+	    fprintf(stderr, "%s: cannot read %d-byte identity\n",
+		    optarg[0] != '-' ? optarg : "<stdin>", IPOD_IDLEN);
+	    exit(2);
+	 }
+         break;
+      default:
+         usage(progname);
+	 exit(-1);
+      }
+
+   argc -= optind;
+   argv += optind;
+   if (!argv[0] || !strlen(argv[0])) 
+   {
+      usage(progname);
+      exit(-1);
+   }
+
+   hostcount = makehosts(argv);
+
+   s = get_icmp_socket();
+
+   signal(SIGALRM, myexit);
+   alarm(timeout);
+   sendpings(s, querytype, hostnames, delay, fromaddr);
+   exit(0);
+}
+   
+/*
+ * in_cksum --
+ *	Checksum routine for Internet Protocol family headers (C Version)
+ *      From FreeBSD's ping.c
+ */
+
+u_short
+in_cksum(addr, len)
+	u_short *addr;
+	int len;
+{
+	register int nleft = len;
+	register u_short *w = addr;
+	register int sum = 0;
+	u_short answer = 0;
+
+	/*
+	 * Our algorithm is simple, using a 32 bit accumulator (sum), we add
+	 * sequential 16 bit words to it, and at the end, fold back all the
+	 * carry bits from the top 16 bits into the lower 16 bits.
+	 */
+	while (nleft > 1)  {
+		sum += *w++;
+		nleft -= 2;
+	}
+
+	/* mop up an odd byte, if necessary */
+	if (nleft == 1) {
+		*(u_char *)(&answer) = *(u_char *)w ;
+		sum += answer;
+	}
+
+	/* add back carry outs from top 16 bits to low 16 bits */
+	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
+	sum += (sum >> 16);			/* add carry */
+	answer = ~sum;				/* truncate to 16 bits */
+	return(answer);
+}
+
diff --git a/pl-podset b/pl-podset
new file mode 100755
index 0000000..4d69d32
--- /dev/null
+++ b/pl-podset
@@ -0,0 +1,46 @@
+#! /bin/bash
+Invocation="pl-podset HOSTIPAddr TARGETIPAddr"
+# Run on a controlling computer to set the pod parameters on a
+# remote node.  A hash code is generated and set into the remote
+# node and stored in a local file for later invocation.
+# -----------------------------------------------------------------
+# $Header: /shareddata/CVS/planetlab/admin/ipod/pl-podset,v 1.3 2003/01/18 01:43:48 radams Exp $
+#
+# Copyright (c) 2003 Intel Corporation
+# All rights reserved.
+# This file is distributed under the terms in the attached INTEL_LICENSE
+# file.  If you do not find this file, a copy can be obtained by
+# writing to Intel Research Berkeley; Attention: Intel License Inquiry;
+# 2150 Shattuck Avenue; Berkeley, CA 94704
+# -----------------------------------------------------------------
+
+HOSTIP=$1
+TARGETIP=$2
+
+if [[ x$HOSTIP == x || x$TARGETIP == x ]] ; then
+    echo "Invocation: $Invocation"
+    exit 1
+fi
+
+DATEE=`date +%Y%m%d%H%M`
+TEMPFILE="/tmp/HashFile_$RANDOM"
+HASHFILE="./HashFile"
+PLBIN="/usr/local/planetlab/bin"
+
+HASHCODE=`printf "%04x%04x%04x%04x%04x%04x%04x%04x\n" $RANDOM $RANDOM $RANDOM $RANDOM $RANDOM $RANDOM $RANDOM $RANDOM`
+
+#echo "HOSTIP = $HOSTIP"
+#echo "TARGETIP = $TARGETIP"
+#echo "HASHCODE = '$HASHCODE'"
+
+ssh idsl1@$TARGETIP "sudo $PLBIN/pl-podcntl $HOSTIP 255.255.255.255 $HASHCODE"
+
+if [[ -f $HASHFILE ]] ; then
+    grep -v "$TARGETIP" $HASHFILE > $TEMPFILE
+else
+    touch $HASHFILE
+    touch $TEMPFILE
+fi
+echo "$DATEE    $HOSTIP $TARGETIP   $HASHCODE" >> $TEMPFILE
+mv $HASHFILE $HASHFILE.last
+mv $TEMPFILE $HASHFILE
diff --git a/pl-podzap b/pl-podzap
new file mode 100755
index 0000000..9cfcbcb
--- /dev/null
+++ b/pl-podzap
@@ -0,0 +1,41 @@
+#! /bin/bash
+Invocation="pl-podzap TargetHostName"
+# Fetches the hash code from the saved hash code file and commands
+# the specified PlanetLab node to send
+# the properly constructed ICMP message to the remote node to
+# reset it.
+# -----------------------------------------------------------------
+# $Header: /shareddata/CVS/planetlab/admin/ipod/pl-podzap,v 1.4 2003/01/18 01:43:48 radams Exp $
+#
+# Copyright (c) 2003 Intel Corporation
+# All rights reserved.
+# This file is distributed under the terms in the attached INTEL_LICENSE
+# file.  If you do not find this file, a copy can be obtained by
+# writing to Intel Research Berkeley; Attention: Intel License Inquiry;
+# 2150 Shattuck Avenue, suite 1300; Berkeley, CA 94704
+# -----------------------------------------------------------------
+
+TARGETIP=$1
+
+if [[ x$TARGETIP == x ]] ; then
+    echo "Invocation: $Invocation"
+    exit 1
+fi
+
+PLBIN="/usr/local/planetlab/bin"
+HASHFILE="./HashFile"
+
+set `grep "$TARGETIP" $HASHFILE`
+DATEE=$1
+HOSTIP=$2
+TARGETIPP=$3
+HASHCODE=$4
+
+if [[ x$HASHCODE != x ]] ; then
+    echo "DATEE=$DATEE, HOSTIP=$HOSTIP, TARGETIPP=$TARGETIPP, HASHCODE = '$HASHCODE'"
+
+    ssh idsl1@$HOSTIP "echo $HASHCODE | sudo $PLBIN/pl-poddoit -i - $TARGETIP"
+else
+    echo "No hash code found for specified target node"
+fi
+
diff --git a/pod.src b/pod.src
new file mode 100755
index 0000000..057e8b1
--- /dev/null
+++ b/pod.src
@@ -0,0 +1,122 @@
+#! /bin/bash
+#include INTEL_LICENSE.txt
+#
+########################################################################
+#
+# PlanetLab Ping Of Death
+#
+########################################################################
+#
+# DESCRIPTION
+#
+# This shell script takes care of starting and stopping Planetlab
+# Ping-Of-Death.
+#
+# The Planetlab POD is a Linux kernel patch that creates the feature
+# of resetting and rebooting a computer when a particularily
+# formatted ICMP "ping" commmand is received.
+#
+# A PlanetLab node's kernel gets a host, mask and hash value through
+# sysctl's that are performed on the node.  The node then looks
+# for an ICMP packet from a host matching the host/mask and, if the
+# packet payload is the hash value, the node forces an immediate
+# reboot.
+#
+# HISTORY
+#
+# May 17, 2003    -   Paul Brett <paul.brett@intel.com>
+#                     Initial version based on the work of 
+#                     Robert Adams <robert.adams@intel.com> and EMULAB
+#
+# chkconfig: - 11 99
+# description: enable Ping of Death
+
+# Source function library.
+. /etc/init.d/functions
+
+# Source networking configuration.
+. /etc/sysconfig/network
+
+#include enable_pod.sh
+#include disable_pod.sh
+#include status_pod.sh
+
+echo -n "PlanetLab Ping Of Death "
+
+CONF=/etc/ipod.conf
+
+if [[ -r $CONF ]]
+then
+    # load the POD configuration file
+    . $CONF
+else
+    # no POD configuration file - failed
+    echo
+    action $"Missing configuration file $CONF" /bin/false
+    exit 1
+fi
+
+# Check that networking is up.
+if [[ ${NETWORKING} = "no" ]]
+then
+    action $"" /bin/false
+    exit 1
+fi
+
+# Check the POD parameters
+if [[ "$HASH" == "" ]]
+then
+    echo 
+    action $"Missing HASH in $CONF" /bin/false
+    exit 1
+fi
+
+if [[ "$IP_SUBNET" == "" ]]
+then
+    echo
+    action $"Missing IP_SUBNET in $CONF" /bin/false
+    exit 1
+fi
+
+if [[ "$IP_MASK" == "" ]]
+then
+    echo
+    action $"Missing IP_MASK in $CONF" /bin/false
+    exit 1
+fi
+
+# See how we were called.
+case "$1" in
+  start)
+        enable_pod $IP_SUBNET $IP_MASK $IP_HASH
+        RETVAL=$?
+        if [[ $RETVAL -eq 0 ]]
+        then
+            action $"" /bin/true
+        else
+            action $"" /bin/false
+        fi
+        ;;
+  stop)
+        disable_pod
+        RETVAL=$?
+        if [[ $RETVAL -eq 0 ]]
+        then
+            action $"" /bin/true
+        else
+            action $"" /bin/false
+        fi
+        ;;
+  status)
+        status_pod
+        RETVAL=$?
+        ;;
+  restart|reload)
+        disable_pod
+        enable_pod
+        RETVAL=$?
+        ;;
+  *)
+        echo $"Usage: $0 {start|stop|restart|status}"
+        exit 1
+esac
diff --git a/shell_include b/shell_include
new file mode 100755
index 0000000..b404f85
--- /dev/null
+++ b/shell_include
@@ -0,0 +1,129 @@
+#!/usr/bin/perl
+
+use strict;
+use Getopt::Long;
+
+my $source = "";
+my $destination = "";
+my $make;
+my $help;
+
+my @lines;
+my %included;
+
+########################################################################
+#
+# usage
+#
+
+sub usage()
+{
+    print "Usage: shell_include --source <file> --destination <file> [--make] [--help]\n";
+    print "\n";
+    print "--make will output makefile dependencies to stdout and exit\n";
+    print "--help will output this text and exit\n";
+    print "\n";
+}
+########################################################################
+#
+# check_options
+#
+
+sub check_options()
+{
+    if ( !GetOptions( 
+                     's|source=s' => \$source,
+	             'd|destination=s' => \$destination,
+                     'm|make' => \$make,
+                     'h|help' => \$help ) ) 
+    {
+        &usage;
+        exit 1;
+    }
+
+    if ( $help ) {
+        &usage;
+        exit 0;
+    };
+
+    die( "Missing input file - use --source <file>" ) if ( $source eq "" );
+    die( "Missing output file - use --destination <file>") if ( $destination eq "" );
+}
+
+########################################################################
+#
+# read_input : Read in the initial input file into @lines
+#
+
+sub read_input()
+{
+    open( SOURCE, $source ) || die ( "Cannot open input file : $source" );
+    while ( <SOURCE> ) {
+        @lines = ( @lines, $_ );
+    };
+    close( SOURCE );
+}
+
+########################################################################
+#
+# Process #include directives
+#
+sub process_includes()
+{
+    my $changed = 0;
+    my @newlines;
+
+    foreach my $line ( @lines ) {
+
+        if ( $line =~ /^(\s*)\#include(\s+)(\S+)/ ) {
+            $changed = 1;
+            my $filename = $3;
+            if ( ! defined $included{ $filename } ) {
+                open( INC, $filename ) || die ( "Cannot open include file : $filename" );
+                @newlines = ( @newlines, "########################################################################\n" );
+                @newlines = ( @newlines, "#\n" );
+                @newlines = ( @newlines, "# Included file : $filename\n" );
+                @newlines = ( @newlines, "#\n" );
+                while( <INC> ) {
+                    @newlines = ( @newlines, $_ );
+                }
+                close( INC );
+                @newlines = ( @newlines, "#\n" );
+                @newlines = ( @newlines, "# End of included file : $filename\n" );
+                @newlines = ( @newlines, "#\n" );
+                @newlines = ( @newlines, "########################################################################\n" );
+                $included{ $filename } = "";
+            }
+        } else {
+            @newlines = ( @newlines, $line );
+        }
+    }
+    @lines = @newlines;
+    return $changed;
+}
+
+########################################################################
+#
+# write_output : write the final set of lines to the output file
+#
+sub write_output() 
+{
+    open( DEST, ">$destination" ) || die( "Cannot open output file : $destination" );
+    foreach my $line ( @lines ) {
+        print DEST $line;
+    }
+    close( DEST );
+}
+
+&check_options;
+&read_input;
+while ( &process_includes ) { };
+if ( $make ) {
+    print "$destination: $source ";
+    foreach my $inc ( sort( keys( %included ) ) ) {
+        print "$inc ";
+    };
+    print "\n";
+} else {
+    &write_output;
+}
diff --git a/status_pod.sh b/status_pod.sh
new file mode 100755
index 0000000..2431244
--- /dev/null
+++ b/status_pod.sh
@@ -0,0 +1,27 @@
+#!/bin/bash 
+
+function status_pod()
+{
+
+    local SYSCTL="/sbin/sysctl"
+
+    # Check that IPOD is built into this kernel
+    local version
+    version=`$SYSCTL -n net.ipv4.icmp_ipod_version 2> /dev/null`
+    if [[ $? -ne 0 ]]
+    then
+        echo "Not installed"
+        return 255
+    fi
+
+    # Check if it has been enabled
+    local enabled=`$SYSCTL -n net.ipv4.icmp_ipod_enabled`
+    echo -n "version $version "
+    if [[ $enabled -eq 1 ]]
+    then 
+        echo "Enabled"
+    else 
+        echo "Disabled"
+    fi
+    return $enabled
+}
diff --git a/test-pod b/test-pod
new file mode 100755
index 0000000..1d6d1b6
--- /dev/null
+++ b/test-pod
@@ -0,0 +1,80 @@
+#! /bin/sh
+# Script to test the "ping-of-death" ("POD") functionality.
+# This script is run on a machine that has the POD feature patched
+# into the kernel and has the tools installed in the machine. 
+#
+# The process is:
+#   * build the kernel with the pod patch
+#   * install the kernel on a machine
+#   * reboot to run that kernel
+#   * on the machine with that kernel, run this script
+#   * if you answer "y" to the question, you will reboot that machine
+#
+# This script was built from the pl-pod* script files.  It has no
+# dependency on them other than it expects /usr/local/planetlab/bin/pl-poddoit
+# to exist to send the POD packet.
+# -----------------------------------------------------------------
+# $Header: /shareddata/CVS/planetlab/admin/ipod/test-pod,v 1.2 2003/01/18 01:52:10 radams Exp $
+#
+# Copyright (c) 2003 Intel Corporation
+# All rights reserved.
+# This file is distributed under the terms in the attached INTEL_LICENSE
+# file.  If you do not find this file, a copy can be obtained by
+# writing to Intel Research Berkeley; Attention: Intel License Inquiry;
+# 2150 Shattuck Avenue, suite 1300; Berkeley, CA 94704
+# -----------------------------------------------------------------
+
+PLBIN="/usr/local/planetlab/bin"
+PLDOIT="$PLBIN/pl-poddoit"
+
+SYSCTL="/sbin/sysctl"
+
+if ! [[ -x $PLDOIT ]] ; then
+    echo "CONFIG ERROR: the send POD executable not available at $PLDOIT"
+    exit 1
+fi
+
+IPODHOSTP=`hostname -i`
+IPODMASKP="255.255.255.255"
+IPODHASHP=`printf "%04x%04x%04x%04x%04x%04x%04x%04x\n" $RANDOM $RANDOM $RANDOM $RANDOM $RANDOM $RANDOM $RANDOM $RANDOM`
+
+echo "IPODHOST = $IPODHOSTP"
+echo "IPODMASK = $IPODMASKP"
+echo "IPODKEY = $IPODHASHP"
+
+echo "=== Set the set parameters into the kernel ==="
+IPODHOST=`echo $IPODHOSTP | \
+    sed -e 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1 \2 \3 \4/' | \
+    awk '{ printf "%d\n", $1*16777216+$2*65536+$3*256+$4 }'`
+IPODMASK=`echo $IPODMASKP | \
+    sed -e 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1 \2 \3 \4/' | \
+    awk '{ printf "%d\n", $1*16777216+$2*65536+$3*256+$4 }'`
+IPODKEY=`echo $IPODHASHP | \
+    sed -e 's/\(.*\)/\1/'`
+$SYSCTL -w net.ipv4.icmp_ipod_host=$IPODHOST >/dev/null
+Success=$?
+$SYSCTL -w net.ipv4.icmp_ipod_mask=$IPODMASK >/dev/null
+$SYSCTL -w net.ipv4.icmp_ipod_key=$IPODKEY >/dev/null
+$SYSCTL -w net.ipv4.icmp_ipod_enabled=1 >/dev/null
+if [[ $Success -eq 0 ]] ; then
+    echo "SUCCESS setting parameters"
+else
+    echo "FAILURE to set POD parameters"
+    exit 1
+fi
+
+echo "=== Try to reset with wrong payload -- this should fail ==="
+echo echo "01234567890123456789012345678901" \| $PLDOIT -i - $IPODHOSTP
+echo "01234567890123456789012345678901" | $PLDOIT -i - $IPODHOSTP
+
+echo "=== Reset host ==="
+echo "THIS NEXT STEP WILL RESET THIS COMPUTER!!!!"
+read -p "Enter 'y' if you wish to reset this computer: " REPLY
+if [[ x"$REPLY" == "xy" ]] ; then
+    echo $IPODHASHP | $PLDOIT -i - $IPODHOSTP
+    echo echo $IPODHASHP \| $PLDOIT -i - $IPODHOSTP
+else
+    echo "Final reset test not performed."
+fi
+
+
-- 
2.47.0