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