1*8f79da2aSbluhm#!/usr/local/bin/python3 2*8f79da2aSbluhm 3*8f79da2aSbluhmprint("ping6 fragments with options total larger than IP maximum packet") 4*8f79da2aSbluhm 5*8f79da2aSbluhm# |--------| 6*8f79da2aSbluhm# ... ... 7*8f79da2aSbluhm# |--------| 8*8f79da2aSbluhm# drop first fragment with ECN conflict, reinsert with longer unfrag part 9*8f79da2aSbluhm# |---------| 10*8f79da2aSbluhm# HopByHop|---------| 11*8f79da2aSbluhm 12*8f79da2aSbluhmimport os 13*8f79da2aSbluhmfrom addr import * 14*8f79da2aSbluhmfrom scapy.all import * 15*8f79da2aSbluhm 16*8f79da2aSbluhmpid=os.getpid() 17*8f79da2aSbluhmeid=pid & 0xffff 18*8f79da2aSbluhmpayload=b"ABCDEFGHIJKLMNOP" 19*8f79da2aSbluhmpacket=IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6)/ \ 20*8f79da2aSbluhm ICMPv6EchoRequest(id=eid, data=4095*payload) 21*8f79da2aSbluhmplen=IPv6(raw(packet)).plen 22*8f79da2aSbluhmprint("plen=%u" % (plen)) 23*8f79da2aSbluhmif plen != 0xfff8: 24*8f79da2aSbluhm print("PLEN!=%u" % (0xfff8)) 25*8f79da2aSbluhm exit(2) 26*8f79da2aSbluhmbytes=bytes(packet) 27*8f79da2aSbluhm 28*8f79da2aSbluhmfrag=[] 29*8f79da2aSbluhmfid=pid & 0xffffffff 30*8f79da2aSbluhmoff=2**7 31*8f79da2aSbluhmwhile off < 2**13: 32*8f79da2aSbluhm frag.append(IPv6ExtHdrFragment(nh=58, id=fid, offset=off)/ \ 33*8f79da2aSbluhm bytes[40+off*8:40+off*8+2**10]) 34*8f79da2aSbluhm off+=2**7 35*8f79da2aSbluhmeth=[] 36*8f79da2aSbluhmfor f in frag: 37*8f79da2aSbluhm pkt=IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6)/f 38*8f79da2aSbluhm eth.append(Ether(src=LOCAL_MAC, dst=REMOTE_MAC)/pkt) 39*8f79da2aSbluhm 40*8f79da2aSbluhm# first fragment with ECN to be dropped 41*8f79da2aSbluhmeth.append(Ether(src=LOCAL_MAC, dst=REMOTE_MAC)/ 42*8f79da2aSbluhm IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6, tc=3)/ 43*8f79da2aSbluhm IPv6ExtHdrFragment(nh=58, id=fid, m=1)/bytes[40:40+2**10]) 44*8f79da2aSbluhm 45*8f79da2aSbluhm# resend first fragment with unfragmentable part too long for IP plen 46*8f79da2aSbluhmeth.append(Ether(src=LOCAL_MAC, dst=REMOTE_MAC)/ 47*8f79da2aSbluhm IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6)/ 48*8f79da2aSbluhm IPv6ExtHdrHopByHop(options=PadN(optdata="\0"*4))/ 49*8f79da2aSbluhm IPv6ExtHdrFragment(nh=58, id=fid, m=1)/bytes[40:40+2**10]) 50*8f79da2aSbluhm 51*8f79da2aSbluhmif os.fork() == 0: 52*8f79da2aSbluhm time.sleep(1) 53*8f79da2aSbluhm sendp(eth, iface=LOCAL_IF) 54*8f79da2aSbluhm os._exit(0) 55*8f79da2aSbluhm 56*8f79da2aSbluhmans=sniff(iface=LOCAL_IF, timeout=3, filter= 57*8f79da2aSbluhm "ip6 and src "+REMOTE_ADDR6+" and dst "+LOCAL_ADDR6+" and icmp6") 58*8f79da2aSbluhmfor a in ans: 59*8f79da2aSbluhm print("type %d" % (a.payload.payload.type)) 60*8f79da2aSbluhm print("icmp %s" % (icmp6types[a.payload.payload.type])) 61*8f79da2aSbluhm if a and a.type == ETH_P_IPV6 and \ 62*8f79da2aSbluhm ipv6nh[a.payload.nh] == 'ICMPv6' and \ 63*8f79da2aSbluhm icmp6types[a.payload.payload.type] == 'Parameter problem': 64*8f79da2aSbluhm print("code=%u" % (a.payload.payload.code)) 65*8f79da2aSbluhm # 0: 'erroneous header field encountered' 66*8f79da2aSbluhm if a.payload.payload.code != 0: 67*8f79da2aSbluhm print("WRONG PARAMETER PROBLEM CODE") 68*8f79da2aSbluhm exit(1) 69*8f79da2aSbluhm ptr=a.payload.payload.ptr 70*8f79da2aSbluhm print("ptr=%u" % (ptr)) 71*8f79da2aSbluhm # 42: sizeof IPv6 header + offset in fragment header 72*8f79da2aSbluhm if ptr != 42: 73*8f79da2aSbluhm print("PTR!=%u" % (ptr)) 74*8f79da2aSbluhm exit(1) 75*8f79da2aSbluhm exit(0) 76*8f79da2aSbluhmprint("NO ICMP PARAMETER PROBLEM") 77*8f79da2aSbluhmexit(2) 78