brintos

brintos / linux-shallow public Read only

0
0
Text · 2.6 KiB · 2b8a118 Raw
91 lines · python
1#!/bin/env python32# SPDX-License-Identifier: GPL-2.03 4"""5This script helps generate fragmented UDP packets.6 7While it is technically possible to dynamically generate8fragmented packets in C, it is much harder to read and write9said code. `scapy` is relatively industry standard and really10easy to read / write.11 12So we choose to write this script that generates a valid C13header. Rerun script and commit generated file after any14modifications.15"""16 17import argparse18import os19 20from scapy.all import *21 22 23# These constants must stay in sync with `ip_check_defrag.c`24VETH1_ADDR = "172.16.1.200"25VETH0_ADDR6 = "fc00::100"26VETH1_ADDR6 = "fc00::200"27CLIENT_PORT = 4887828SERVER_PORT = 4887929MAGIC_MESSAGE = "THIS IS THE ORIGINAL MESSAGE, PLEASE REASSEMBLE ME"30 31 32def print_header(f):33    f.write("// SPDX-License-Identifier: GPL-2.0\n")34    f.write("/* DO NOT EDIT -- this file is generated */\n")35    f.write("\n")36    f.write("#ifndef _IP_CHECK_DEFRAG_FRAGS_H\n")37    f.write("#define _IP_CHECK_DEFRAG_FRAGS_H\n")38    f.write("\n")39    f.write("#include <stdint.h>\n")40    f.write("\n")41 42 43def print_frags(f, frags, v6):44    for idx, frag in enumerate(frags):45        # 10 bytes per line to keep width in check46        chunks = [frag[i : i + 10] for i in range(0, len(frag), 10)]47        chunks_fmted = [", ".join([str(hex(b)) for b in chunk]) for chunk in chunks]48        suffix = "6" if v6 else ""49 50        f.write(f"static uint8_t frag{suffix}_{idx}[] = {{\n")51        for chunk in chunks_fmted:52            f.write(f"\t{chunk},\n")53        f.write(f"}};\n")54 55 56def print_trailer(f):57    f.write("\n")58    f.write("#endif /* _IP_CHECK_DEFRAG_FRAGS_H */\n")59 60 61def main(f):62    # srcip of 0 is filled in by IP_HDRINCL63    sip = "0.0.0.0"64    sip6 = VETH0_ADDR665    dip = VETH1_ADDR66    dip6 = VETH1_ADDR667    sport = CLIENT_PORT68    dport = SERVER_PORT69    payload = MAGIC_MESSAGE.encode()70 71    # Disable UDPv4 checksums to keep code simpler72    pkt = IP(src=sip,dst=dip) / UDP(sport=sport,dport=dport,chksum=0) / Raw(load=payload)73    # UDPv6 requires a checksum74    # Also pin the ipv6 fragment header ID, otherwise it's a random value75    pkt6 = IPv6(src=sip6,dst=dip6) / IPv6ExtHdrFragment(id=0xBEEF) / UDP(sport=sport,dport=dport) / Raw(load=payload)76 77    frags = [f.build() for f in pkt.fragment(24)]78    frags6 = [f.build() for f in fragment6(pkt6, 72)]79 80    print_header(f)81    print_frags(f, frags, False)82    print_frags(f, frags6, True)83    print_trailer(f)84 85 86if __name__ == "__main__":87    dir = os.path.dirname(os.path.realpath(__file__))88    header = f"{dir}/ip_check_defrag_frags.h"89    with open(header, "w") as f:90        main(f)91