3 # Marc E. Fiuczynski <mef@cs.princeton.edu>
4 # Copyright (C) 2004 The Trustees of Princeton University
6 # Client ping of death program for both udp & icmp
16 sys.stdout = sys.stderr
17 print 'Usage: pod -i identityfile [--icmp,--udp] hostnamelist'
18 print ' -i identity key where key may be - for stdin'
19 print ' --icmp icmp protocol only'
20 print ' --udp udp protocol only'
21 print ' by default both icmp and udp are used'
26 def _in_cksum(packet):
27 """THE RFC792 states: 'The 16 bit one's complement of
28 the one's complement sum of all 16 bit words in the header.'
29 Generates a checksum of a (ICMP) packet. Based on in_chksum found
33 # add byte if not dividable by 2
35 packet = packet + '\0'
37 # split into 16-bit word and insert into a binary array
38 words = array.array('h', packet)
41 # perform ones complement arithmetic on 16-bit words
43 sum += (word & 0xffff)
48 sum = sum + (sum >> 16)
50 return (~sum) & 0xffff # return ones complement
52 def _construct(id, data):
53 """Constructs a ICMP IPOD packet
55 ICMP_TYPE = 6 # ping of death code used by PLK
61 header = struct.pack('bbHHh', ICMP_TYPE, ICMP_CODE, ICMP_CHECKSUM, \
62 ICMP_ID, ICMP_SEQ_NR+id)
64 packet = header + data # ping packet without checksum
65 checksum = _in_cksum(packet) # make checksum
67 # construct header with correct checksum
68 header = struct.pack('bbHHh', ICMP_TYPE, ICMP_CODE, checksum, ICMP_ID, \
71 # ping packet *with* checksum
72 packet = header + data
74 # a perfectly formatted ICMP echo packet
77 def icmp_pod(host,key):
80 print "must be root to send icmp pod"
83 s = socket(AF_INET, SOCK_RAW, getprotobyname("icmp"))
84 packet = _construct(0, key) # make a ping packet
86 print 'pod sending icmp-based reboot request to %s' % host
88 s.sendto(packet, addr)
90 def udp_pod(host,key):
91 addr = host, UPOD_PORT
92 s = socket(AF_INET, SOCK_DGRAM)
95 print 'pod sending udp-based reboot request to %s' % host
97 s.sendto(packet, addr)
99 def noop_pod(host,key):
104 opts, args = getopt.getopt(sys.argv[1:], "i:", ["icmp","udp"])
105 except getops.GetoptError:
110 protos = {'udp' : udp_pod, 'icmp' : icmp_pod}
118 if len(a)==1 and a[0]=='-':
119 key = sys.stdin.readline()
127 print '%s not found' % a
135 protocols = ['udp','icmp']
137 for protocol in protocols:
138 pod = protos.get(protocol,noop_pod)