xref: /openbsd-src/regress/sys/net/pf_forward/ping6_mtu.py (revision 85c0d959848defb37e9bba4516fccc8400e0b535)
1*85c0d959Sbluhm#!/usr/local/bin/python3
20d0cafa0Sbluhm# check wether path mtu to dst is as expected
30d0cafa0Sbluhm
40d0cafa0Sbluhmimport os
52dff962aSbluhmimport threading
60d0cafa0Sbluhmfrom addr import *
70d0cafa0Sbluhmfrom scapy.all import *
80d0cafa0Sbluhm
95004ddd2Sbluhm# usage: ping6_mtu src dst size icmp6-size
105004ddd2Sbluhm
112dff962aSbluhm# work around the broken sniffing of packages with bad checksum
122dff962aSbluhm#a=srp1(eth, iface=SRC_IF, timeout=2)
132dff962aSbluhmclass Sniff1(threading.Thread):
142dff962aSbluhm	filter = None
152dff962aSbluhm	captured = None
162dff962aSbluhm	packet = None
172dff962aSbluhm	def run(self):
182dff962aSbluhm		self.captured = sniff(iface=SRC_IF, filter=self.filter,
192dff962aSbluhm		    count=1, timeout=3)
202dff962aSbluhm		if self.captured:
212dff962aSbluhm			self.packet = self.captured[0]
222dff962aSbluhm
235004ddd2Sbluhmsrcaddr=sys.argv[1]
245004ddd2Sbluhmdstaddr=sys.argv[2]
255004ddd2Sbluhmsize=int(sys.argv[3])
265004ddd2Sbluhmexpect=int(sys.argv[4])
279ae5678bSbluhmeid=os.getpid() & 0xffff
289ae5678bSbluhmhdr=IPv6(src=srcaddr, dst=dstaddr)/ICMPv6EchoRequest(id=eid)
29*85c0d959Sbluhmpayload="a" * (size - len(bytes(hdr)))
305004ddd2Sbluhmip=hdr/payload
31*85c0d959Sbluhmiplen=IPv6(bytes(ip)).plen
32621b42f7Sbluhmeth=Ether(src=SRC_MAC, dst=PF_MAC)/ip
3398a41332Sbluhm
342dff962aSbluhmsniffer = Sniff1();
351ca2c44dSbluhm# pcap cannot access icmp6, check for packet too big, avoid neighbor discovery
361ca2c44dSbluhmsniffer.filter = "ip6 and dst %s and icmp6 and ip6[40] = 2 and ip6[41] = 0" \
371ca2c44dSbluhm    % srcaddr
382dff962aSbluhmsniffer.start()
399a7ee091Sbluhmtime.sleep(1)
4098a41332Sbluhmsendp(eth, iface=SRC_IF)
412dff962aSbluhmsniffer.join(timeout=5)
422dff962aSbluhma = sniffer.packet
4398a41332Sbluhm
441ca2c44dSbluhmif a is None:
45*85c0d959Sbluhm	print("no packet sniffed")
461ca2c44dSbluhm	exit(2)
479c70e3bfSbluhmif a and a.type == ETH_P_IPV6 and \
480d0cafa0Sbluhm    ipv6nh[a.payload.nh] == 'ICMPv6' and \
490d0cafa0Sbluhm    icmp6types[a.payload.payload.type] == 'Packet too big':
500d0cafa0Sbluhm	mtu=a.payload.payload.mtu
51*85c0d959Sbluhm	print("mtu=%d" % (mtu))
52621b42f7Sbluhm	if mtu != expect:
53*85c0d959Sbluhm		print("MTU!=%d" % (expect))
540d0cafa0Sbluhm		exit(1)
55a2cb595eSbluhm	iip=a.payload.payload.payload
56a2cb595eSbluhm	iiplen=iip.plen
57a2cb595eSbluhm	if iiplen != iplen:
58*85c0d959Sbluhm		print("inner IPv6 plen %d!=%d" % (iiplen, iplen))
59a2cb595eSbluhm		exit(1)
60a2cb595eSbluhm	isrc=iip.src
61a2cb595eSbluhm	if isrc != srcaddr:
62*85c0d959Sbluhm		print("inner IPv6 src %d!=%d" % (isrc, srcaddr))
63a2cb595eSbluhm		exit(1)
64a2cb595eSbluhm	idst=iip.dst
65a2cb595eSbluhm	if idst != dstaddr:
66*85c0d959Sbluhm		print("inner IPv6 dst %d!=%d" % (idst, dstaddr))
67621b42f7Sbluhm		exit(1)
68621b42f7Sbluhm	exit(0)
69*85c0d959Sbluhmprint("MTU=UNKNOWN")
700d0cafa0Sbluhmexit(2)
71