Setting tag plcapi-5.4-2
[plcapi.git] / PLC / POD.py
1 # Marc E. Fiuczynski <mef@cs.princeton.edu>
2 # Copyright (C) 2004 The Trustees of Princeton University
3 #
4 # Client ping of death program for both udp & icmp
5 #
6 # modified for inclusion by api by Aaron K
7
8 import struct
9 import os
10 import array
11 import getopt
12 from socket import *
13
14 UPOD_PORT = 664
15
16 def _in_cksum(packet):
17     """THE RFC792 states: 'The 16 bit one's complement of
18     the one's complement sum of all 16 bit words in the header.'
19     Generates a checksum of a (ICMP) packet. Based on in_chksum found
20     in ping.c on FreeBSD.
21     """
22
23     # add byte if not dividable by 2
24     if len(packet) & 1:
25         packet = packet + '\0'
26
27     # split into 16-bit word and insert into a binary array
28     words = array.array('h', packet)
29     sum = 0
30
31     # perform ones complement arithmetic on 16-bit words
32     for word in words:
33         sum += (word & 0xffff)
34
35     hi = sum >> 16
36     lo = sum & 0xffff
37     sum = hi + lo
38     sum = sum + (sum >> 16)
39
40     return (~sum) & 0xffff # return ones complement
41
42 def _construct(id, data):
43     """Constructs a ICMP IPOD packet
44     """
45     ICMP_TYPE = 6 # ping of death code used by PLK
46     ICMP_CODE = 0
47     ICMP_CHECKSUM = 0
48     ICMP_ID = 0
49     ICMP_SEQ_NR = 0
50
51     header = struct.pack('bbHHh', ICMP_TYPE, ICMP_CODE, ICMP_CHECKSUM, \
52                          ICMP_ID, ICMP_SEQ_NR+id)
53
54     packet = header + data          # ping packet without checksum
55     checksum = _in_cksum(packet)    # make checksum
56
57     # construct header with correct checksum
58     header = struct.pack('bbHHh', ICMP_TYPE, ICMP_CODE, checksum, ICMP_ID, \
59                          ICMP_SEQ_NR+id)
60
61     # ping packet *with* checksum
62     packet = header + data
63
64     # a perfectly formatted ICMP echo packet
65     return packet
66
67 def icmp_pod(host,key):
68     uid = os.getuid()
69     if uid <> 0:
70         print "must be root to send icmp pod"
71         return
72
73     s = socket(AF_INET, SOCK_RAW, getprotobyname("icmp"))
74     packet = _construct(0, key) # make a ping packet
75     addr = (host,1)
76     print 'pod sending icmp-based reboot request to %s' % host
77     for i in range(1,10):
78         s.sendto(packet, addr)
79
80 def udp_pod(host,key,fromaddr=('', 0)):
81     addr = host, UPOD_PORT
82     s = socket(AF_INET, SOCK_DGRAM)
83     s.bind(fromaddr)
84     packet = key
85     print 'pod sending udp-based reboot request to %s' % host
86     for i in range(1,10):
87         s.sendto(packet, addr)
88
89 def noop_pod(host,key):
90     pass