-
Notifications
You must be signed in to change notification settings - Fork 1
/
testttl.py
executable file
·154 lines (119 loc) · 4.32 KB
/
testttl.py
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#!/usr/bin/python
import dpkt
import dnet
import socket
import time
import sys
SRC_IP = socket.gethostbyname_ex(socket.gethostname())[2][0]
SPORT = 5555
TIMEOUT = 1.2 #seconds
MIN_TTL = 1
MAX_TTL = 20
icmp_sock = None
# for planet lab: listen on the one udp port we send packets from
# so we get their responses
udp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udp_sock.bind(("", SPORT))
def get_icmp_sock(timeout=TIMEOUT):
global icmp_sock
if icmp_sock == None:
icmp_sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
icmp_sock.setsockopt(socket.SOL_IP, socket.IP_HDRINCL, 1)
icmp_sock.settimeout(timeout)
elif icmp_sock.gettimeout() != timeout:
icmp_sock.settimeout(timeout)
return icmp_sock
def test_dest(dest, min_ttl=MIN_TTL, src_ip=SRC_IP):
icmp_sock = get_icmp_sock()
ip = dnet.ip()
for ttl in range(min_ttl, MAX_TTL):
udp = dpkt.udp.UDP(sport=SPORT, dport=ttl)
udp.data = "pkt %d " % ttl
udp.data += 'A'*250
udp.ulen += len(udp.data)
pkt = dpkt.ip.IP(src=socket.inet_aton(src_ip), dst=socket.inet_aton(dest), ttl=ttl, id=ttl, p=0x11)
pkt.data = udp
pkt.len += len(str(pkt.data))
ip.send(str(pkt))
time.sleep(.001)
timeout = time.time() + TIMEOUT # give a few seconds for all routers to respond
hops = {}
while time.time() < timeout:
try:
data, addr = icmp_sock.recvfrom(1508)
except socket.timeout:
return hops
ip_pkt = dpkt.ip.IP(data)
icmp_pkt = ip_pkt.data
inner_ip_pkt = icmp_pkt.data.data
payload_data = inner_ip_pkt.data
#print '%s (hop %d) sent %d bytes' % (addr[0], inner_ip_pkt.id, len(payload_data))
hops[payload_data.dport] = (addr[0], len(payload_data))
if (addr[0] == dest):
return hops
return hops
'''
Some destinations append garbage data to your payload - this function
attempts to confirm the actual length by sending a payload of 'AAAAAAA...'
and seeing just how many AAAA's we get back
'''
def confirm_max_mtu(host, hop, reported_payload_len=1024, src_ip=SRC_IP):
icmp_sock = get_icmp_sock()
ip = dnet.ip()
udp = dpkt.udp.UDP(sport=SPORT, dport=hop)
udp.data = 'A'*reported_payload_len
udp.ulen += len(udp.data)
pkt = dpkt.ip.IP(src=socket.inet_aton(src_ip), dst=socket.inet_aton(host), ttl=hop, id=hop, p=0x11)
pkt.data = udp
pkt.len += len(str(pkt.data))
ip.send(str(pkt))
timeout = time.time() + TIMEOUT # give a few seconds for all routers to respond
while time.time() < timeout:
try:
data, addr = icmp_sock.recvfrom(1508)
except socket.timeout:
return -1
ip_pkt = dpkt.ip.IP(data)
icmp_pkt = ip_pkt.data
inner_ip_pkt = icmp_pkt.data.data
udp_pkt = inner_ip_pkt.data
payload = udp_pkt.data
return len(payload) - len(payload.replace('A'*8, ''))
return -1
def print_hops(hops, min_ttl=MIN_TTL):
if len(hops.keys()) == 0:
return 0
for ttl in range(min_ttl, max(hops.keys())+1):
if ttl in hops:
addr, payload_len = hops[ttl]
else:
addr = '*'
payload_len = 0
print '% 3d % 15s % 4d bytes' % (ttl, addr, payload_len)
def get_max_payload_len(hops, min_ttl=MIN_TTL):
if len(hops.keys()) == 0:
return (0, 0)
max_payload_len = 0
max_payload_len_ttl = 0
for ttl in range(min_ttl, max(hops.keys())+1):
if ttl in hops:
addr, payload_len = hops[ttl]
if payload_len > max_payload_len:
max_payload_len = payload_len
max_payload_len_ttl = ttl
return (max_payload_len_ttl, max_payload_len)
if __name__ == "__main__":
if len(sys.argv) == 1:
print 'Usage'
print ''
print '%s dest_ip [min_ttl=1]' % (sys.argv[0])
print ' Finds the MTUs of TTL exceeded messages for routers'
print ' between here and dest_ip (starting at hop min_ttl)'
sys.exit(1)
min_ttl = 1
if len(sys.argv) > 1:
dest = sys.argv[1]
if len(sys.argv) > 2:
min_ttl = sys.argv[2]
hops = test_dest(dest, min_ttl)
print_hops(hops, min_ttl)