ipod IPOD_DIST
authorAaron Klingaman <alk@cs.princeton.edu>
Mon, 12 Apr 2004 17:00:14 +0000 (17:00 +0000)
committerAaron Klingaman <alk@cs.princeton.edu>
Mon, 12 Apr 2004 17:00:14 +0000 (17:00 +0000)
14 files changed:
INTEL_LICENSE.txt [new file with mode: 0644]
Makefile [new file with mode: 0644]
README [new file with mode: 0644]
disable_pod.sh [new file with mode: 0755]
enable_pod.sh [new file with mode: 0755]
ipod.spec [new file with mode: 0644]
pl-podcntl [new file with mode: 0755]
pl-poddoit.c [new file with mode: 0644]
pl-podset [new file with mode: 0755]
pl-podzap [new file with mode: 0755]
pod.src [new file with mode: 0755]
shell_include [new file with mode: 0755]
status_pod.sh [new file with mode: 0755]
test-pod [new file with mode: 0755]

diff --git a/INTEL_LICENSE.txt b/INTEL_LICENSE.txt
new file mode 100644 (file)
index 0000000..f0b394d
--- /dev/null
@@ -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 (file)
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 (file)
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 (executable)
index 0000000..bba89f8
--- /dev/null
@@ -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 (executable)
index 0000000..e48c91b
--- /dev/null
@@ -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 (file)
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 (executable)
index 0000000..0d0c191
--- /dev/null
@@ -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 (file)
index 0000000..20e72c2
--- /dev/null
@@ -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 (executable)
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 (executable)
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 (executable)
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 (executable)
index 0000000..b404f85
--- /dev/null
@@ -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 (executable)
index 0000000..2431244
--- /dev/null
@@ -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 (executable)
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
+
+