162306a36Sopenharmony_ci#!/bin/env python3 262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci""" 562306a36Sopenharmony_ciThis script helps generate fragmented UDP packets. 662306a36Sopenharmony_ci 762306a36Sopenharmony_ciWhile it is technically possible to dynamically generate 862306a36Sopenharmony_cifragmented packets in C, it is much harder to read and write 962306a36Sopenharmony_cisaid code. `scapy` is relatively industry standard and really 1062306a36Sopenharmony_cieasy to read / write. 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ciSo we choose to write this script that generates a valid C 1362306a36Sopenharmony_ciheader. Rerun script and commit generated file after any 1462306a36Sopenharmony_cimodifications. 1562306a36Sopenharmony_ci""" 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ciimport argparse 1862306a36Sopenharmony_ciimport os 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cifrom scapy.all import * 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci# These constants must stay in sync with `ip_check_defrag.c` 2462306a36Sopenharmony_ciVETH1_ADDR = "172.16.1.200" 2562306a36Sopenharmony_ciVETH0_ADDR6 = "fc00::100" 2662306a36Sopenharmony_ciVETH1_ADDR6 = "fc00::200" 2762306a36Sopenharmony_ciCLIENT_PORT = 48878 2862306a36Sopenharmony_ciSERVER_PORT = 48879 2962306a36Sopenharmony_ciMAGIC_MESSAGE = "THIS IS THE ORIGINAL MESSAGE, PLEASE REASSEMBLE ME" 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cidef print_header(f): 3362306a36Sopenharmony_ci f.write("// SPDX-License-Identifier: GPL-2.0\n") 3462306a36Sopenharmony_ci f.write("/* DO NOT EDIT -- this file is generated */\n") 3562306a36Sopenharmony_ci f.write("\n") 3662306a36Sopenharmony_ci f.write("#ifndef _IP_CHECK_DEFRAG_FRAGS_H\n") 3762306a36Sopenharmony_ci f.write("#define _IP_CHECK_DEFRAG_FRAGS_H\n") 3862306a36Sopenharmony_ci f.write("\n") 3962306a36Sopenharmony_ci f.write("#include <stdint.h>\n") 4062306a36Sopenharmony_ci f.write("\n") 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cidef print_frags(f, frags, v6): 4462306a36Sopenharmony_ci for idx, frag in enumerate(frags): 4562306a36Sopenharmony_ci # 10 bytes per line to keep width in check 4662306a36Sopenharmony_ci chunks = [frag[i : i + 10] for i in range(0, len(frag), 10)] 4762306a36Sopenharmony_ci chunks_fmted = [", ".join([str(hex(b)) for b in chunk]) for chunk in chunks] 4862306a36Sopenharmony_ci suffix = "6" if v6 else "" 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci f.write(f"static uint8_t frag{suffix}_{idx}[] = {{\n") 5162306a36Sopenharmony_ci for chunk in chunks_fmted: 5262306a36Sopenharmony_ci f.write(f"\t{chunk},\n") 5362306a36Sopenharmony_ci f.write(f"}};\n") 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cidef print_trailer(f): 5762306a36Sopenharmony_ci f.write("\n") 5862306a36Sopenharmony_ci f.write("#endif /* _IP_CHECK_DEFRAG_FRAGS_H */\n") 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cidef main(f): 6262306a36Sopenharmony_ci # srcip of 0 is filled in by IP_HDRINCL 6362306a36Sopenharmony_ci sip = "0.0.0.0" 6462306a36Sopenharmony_ci sip6 = VETH0_ADDR6 6562306a36Sopenharmony_ci dip = VETH1_ADDR 6662306a36Sopenharmony_ci dip6 = VETH1_ADDR6 6762306a36Sopenharmony_ci sport = CLIENT_PORT 6862306a36Sopenharmony_ci dport = SERVER_PORT 6962306a36Sopenharmony_ci payload = MAGIC_MESSAGE.encode() 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci # Disable UDPv4 checksums to keep code simpler 7262306a36Sopenharmony_ci pkt = IP(src=sip,dst=dip) / UDP(sport=sport,dport=dport,chksum=0) / Raw(load=payload) 7362306a36Sopenharmony_ci # UDPv6 requires a checksum 7462306a36Sopenharmony_ci # Also pin the ipv6 fragment header ID, otherwise it's a random value 7562306a36Sopenharmony_ci pkt6 = IPv6(src=sip6,dst=dip6) / IPv6ExtHdrFragment(id=0xBEEF) / UDP(sport=sport,dport=dport) / Raw(load=payload) 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci frags = [f.build() for f in pkt.fragment(24)] 7862306a36Sopenharmony_ci frags6 = [f.build() for f in fragment6(pkt6, 72)] 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci print_header(f) 8162306a36Sopenharmony_ci print_frags(f, frags, False) 8262306a36Sopenharmony_ci print_frags(f, frags6, True) 8362306a36Sopenharmony_ci print_trailer(f) 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ciif __name__ == "__main__": 8762306a36Sopenharmony_ci dir = os.path.dirname(os.path.realpath(__file__)) 8862306a36Sopenharmony_ci header = f"{dir}/ip_check_defrag_frags.h" 8962306a36Sopenharmony_ci with open(header, "w") as f: 9062306a36Sopenharmony_ci main(f) 91