xref: /freebsd/sbin/ping/tests/injection.py (revision e35cfc60)
1e35cfc60SAlan Somers#! /usr/bin/env python3
2e35cfc60SAlan Somers# Used to inject various malformed packets
3e35cfc60SAlan Somers
4e35cfc60SAlan Somersimport errno
5e35cfc60SAlan Somersimport logging
6e35cfc60SAlan Somersimport subprocess
7e35cfc60SAlan Somersimport sys
8e35cfc60SAlan Somers
9e35cfc60SAlan Somerslogging.getLogger("scapy").setLevel(logging.CRITICAL)
10e35cfc60SAlan Somers
11e35cfc60SAlan Somersfrom scapy.all import IP, ICMP, IPOption
12e35cfc60SAlan Somersimport scapy.layers.all
13e35cfc60SAlan Somersfrom scapy.layers.inet import ICMPEcho_am
14e35cfc60SAlan Somersfrom scapy.layers.tuntap import TunTapInterface
15e35cfc60SAlan Somers
16e35cfc60SAlan SomersSRC_ADDR = "192.0.2.14"
17e35cfc60SAlan SomersDST_ADDR = "192.0.2.15"
18e35cfc60SAlan Somers
19e35cfc60SAlan Somersmode = sys.argv[1]
20e35cfc60SAlan Somersip = None
21e35cfc60SAlan Somers
22e35cfc60SAlan Somers# fill opts with nop (0x01)
23e35cfc60SAlan Somersopts = b''
24e35cfc60SAlan Somersfor x in range(40):
25e35cfc60SAlan Somers    opts += b'\x01'
26e35cfc60SAlan Somers
27e35cfc60SAlan Somers
28e35cfc60SAlan Somers# Create and configure a tun interface with an RFC5737 nonrouteable address
29e35cfc60SAlan Somerscreate_proc = subprocess.run(
30e35cfc60SAlan Somers    args=["ifconfig", "tun", "create"],
31e35cfc60SAlan Somers    capture_output=True,
32e35cfc60SAlan Somers    check=True,
33e35cfc60SAlan Somers    text=True)
34e35cfc60SAlan Somersiface = create_proc.stdout.strip()
35e35cfc60SAlan Somerstun = TunTapInterface(iface)
36e35cfc60SAlan Somerswith open("tun.txt", "w") as f:
37e35cfc60SAlan Somers    f.write(iface)
38e35cfc60SAlan Somerssubprocess.run(["ifconfig", tun.iface, "up"])
39e35cfc60SAlan Somerssubprocess.run(["ifconfig", tun.iface, SRC_ADDR, DST_ADDR])
40e35cfc60SAlan Somers
41e35cfc60SAlan Somersping = subprocess.Popen(
42e35cfc60SAlan Somers        args=["/sbin/ping", "-v", "-c1", "-t1", DST_ADDR],
43e35cfc60SAlan Somers        text=True
44e35cfc60SAlan Somers)
45e35cfc60SAlan Somers# Wait for /sbin/ping to ping us
46e35cfc60SAlan Somersecho_req = tun.recv()
47e35cfc60SAlan Somers
48e35cfc60SAlan Somers# Construct the response packet
49e35cfc60SAlan Somersif mode == "opts":
50e35cfc60SAlan Somers    # Sending reply with IP options
51e35cfc60SAlan Somers    echo_reply = IP(
52e35cfc60SAlan Somers        dst=SRC_ADDR,
53e35cfc60SAlan Somers        src=DST_ADDR,
54e35cfc60SAlan Somers        options=IPOption(opts)
55e35cfc60SAlan Somers    )/ICMP(type=0, code=0, id=echo_req.payload.id)/echo_req.payload.payload
56e35cfc60SAlan Somerselif mode == "pip":
57e35cfc60SAlan Somers    # packet in packet (inner has options)
58e35cfc60SAlan Somers
59e35cfc60SAlan Somers    inner = IP(
60e35cfc60SAlan Somers        dst=SRC_ADDR,
61e35cfc60SAlan Somers        src=DST_ADDR,
62e35cfc60SAlan Somers        options=IPOption(opts)
63e35cfc60SAlan Somers    )/ICMP(type=0, code=0, id=echo_req.payload.id)/echo_req.payload.payload
64e35cfc60SAlan Somers    outer = IP(
65e35cfc60SAlan Somers        dst=SRC_ADDR,
66e35cfc60SAlan Somers        src=DST_ADDR
67e35cfc60SAlan Somers    )/ICMP(type=3, code=1)  # host unreach
68e35cfc60SAlan Somers
69e35cfc60SAlan Somers    echo_reply = outer/inner
70e35cfc60SAlan Somerselif mode == "reply":
71e35cfc60SAlan Somers    # Sending normal echo reply
72e35cfc60SAlan Somers    echo_reply = IP(
73e35cfc60SAlan Somers        dst=SRC_ADDR,
74e35cfc60SAlan Somers        src=DST_ADDR,
75e35cfc60SAlan Somers    )/ICMP(type=0, code=0, id=echo_req.payload.id)/echo_req.payload.payload
76e35cfc60SAlan Somerselse:
77e35cfc60SAlan Somers    print("unknown mode {}".format(mode))
78e35cfc60SAlan Somers    exit(1)
79e35cfc60SAlan Somers
80e35cfc60SAlan Somerstun.send(echo_reply)
81e35cfc60SAlan Somersouts, errs = ping.communicate()
82e35cfc60SAlan Somers
83e35cfc60SAlan Somerssys.exit(ping.returncode)
84