1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
#!/usr/local/bin/python2.7
import argparse
import scapy.all as sp
import sys
import threading
PAYLOAD_MAGIC = 0x42c0ffee
class Sniffer(threading.Thread):
def __init__(self, recvif):
threading.Thread.__init__(self)
self._recvif = recvif
self.start()
def run(self):
self.packets = sp.sniff(iface=self._recvif, timeout=3)
def check_ping_request(packet, dst_ip):
"""
Verify that the packet matches what we'd have sent
"""
ip = packet.getlayer(sp.IP)
if not ip:
return False
if ip.dst != dst_ip:
return False
icmp = packet.getlayer(sp.ICMP)
if not icmp:
return False
if sp.icmptypes[icmp.type] != 'echo-request':
return False
raw = packet.getlayer(sp.Raw)
if not raw:
return False
if raw.load != str(PAYLOAD_MAGIC):
return False
return True
def ping(send_if, dst_ip):
req = sp.Ether() \
/ sp.IP(dst=dst_ip) \
/ sp.ICMP(type='echo-request') \
/ sp.Raw(PAYLOAD_MAGIC)
sp.sendp(req, iface=send_if, verbose=False)
def main():
parser = argparse.ArgumentParser("pft_ping.py",
description="Ping test tool")
parser.add_argument('--sendif', nargs=1,
required=True,
help='The interface through which the packet(s) will be sent')
parser.add_argument('--recvif', nargs=1,
help='The interface on which to expect the ICMP echo response')
parser.add_argument('--to', nargs=1,
required=True,
help='The destination IP address for the ICMP echo request')
args = parser.parse_args()
sniffer = None
if not args.recvif is None:
sniffer = Sniffer(args.recvif[0])
ping(args.sendif[0], args.to[0])
if sniffer:
sniffer.join()
for packet in sniffer.packets:
if check_ping_request(packet, args.to[0]):
sys.exit(0)
# We did not get the packet we expected
sys.exit(1)
if __name__ == '__main__':
main()
|