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