From b78b4a0b9256d477c3bdb70693a66de3da3865d2 Mon Sep 17 00:00:00 2001 From: Aaron Klingaman Date: Mon, 12 Apr 2004 17:00:14 +0000 Subject: [PATCH 1/1] 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 +# Initial version based on the work of +# Robert Adams 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 +# Initial version based on the work of +# Robert Adams 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 : "", 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 +# Initial version based on the work of +# Robert Adams 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 --destination [--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 " ) if ( $source eq "" ); + die( "Missing output file - use --destination ") 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 ( ) { + @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( ) { + @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.43.0