mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-15 12:54:27 +00:00
Add test cases for ping with IP options in the response
MFC after: 1 week Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D37210
This commit is contained in:
parent
526f57bf85
commit
e35cfc606a
|
@ -6,9 +6,13 @@ SRCS.in_cksum_test= in_cksum_test.c ../utils.c
|
|||
PACKAGE= tests
|
||||
|
||||
ATF_TESTS_SH+= ping_test
|
||||
# Exclusive because each injection test case uses the same IP addresses
|
||||
TEST_METADATA.ping_test+= is_exclusive="true"
|
||||
|
||||
${PACKAGE}FILES+= ping_c1_s56_t1.out
|
||||
${PACKAGE}FILES+= ping_6_c1_s8_t1.out
|
||||
${PACKAGE}FILES+= ping_c1_s56_t1_S127.out
|
||||
${PACKAGE}FILES+= ping_c1_s8_t1_S1.out
|
||||
${PACKAGE}FILES+= injection.py
|
||||
|
||||
.include <bsd.test.mk>
|
||||
|
|
83
sbin/ping/tests/injection.py
Normal file
83
sbin/ping/tests/injection.py
Normal file
|
@ -0,0 +1,83 @@
|
|||
#! /usr/bin/env python3
|
||||
# Used to inject various malformed packets
|
||||
|
||||
import errno
|
||||
import logging
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
logging.getLogger("scapy").setLevel(logging.CRITICAL)
|
||||
|
||||
from scapy.all import IP, ICMP, IPOption
|
||||
import scapy.layers.all
|
||||
from scapy.layers.inet import ICMPEcho_am
|
||||
from scapy.layers.tuntap import TunTapInterface
|
||||
|
||||
SRC_ADDR = "192.0.2.14"
|
||||
DST_ADDR = "192.0.2.15"
|
||||
|
||||
mode = sys.argv[1]
|
||||
ip = None
|
||||
|
||||
# fill opts with nop (0x01)
|
||||
opts = b''
|
||||
for x in range(40):
|
||||
opts += b'\x01'
|
||||
|
||||
|
||||
# Create and configure a tun interface with an RFC5737 nonrouteable address
|
||||
create_proc = subprocess.run(
|
||||
args=["ifconfig", "tun", "create"],
|
||||
capture_output=True,
|
||||
check=True,
|
||||
text=True)
|
||||
iface = create_proc.stdout.strip()
|
||||
tun = TunTapInterface(iface)
|
||||
with open("tun.txt", "w") as f:
|
||||
f.write(iface)
|
||||
subprocess.run(["ifconfig", tun.iface, "up"])
|
||||
subprocess.run(["ifconfig", tun.iface, SRC_ADDR, DST_ADDR])
|
||||
|
||||
ping = subprocess.Popen(
|
||||
args=["/sbin/ping", "-v", "-c1", "-t1", DST_ADDR],
|
||||
text=True
|
||||
)
|
||||
# Wait for /sbin/ping to ping us
|
||||
echo_req = tun.recv()
|
||||
|
||||
# Construct the response packet
|
||||
if mode == "opts":
|
||||
# Sending reply with IP options
|
||||
echo_reply = IP(
|
||||
dst=SRC_ADDR,
|
||||
src=DST_ADDR,
|
||||
options=IPOption(opts)
|
||||
)/ICMP(type=0, code=0, id=echo_req.payload.id)/echo_req.payload.payload
|
||||
elif mode == "pip":
|
||||
# packet in packet (inner has options)
|
||||
|
||||
inner = IP(
|
||||
dst=SRC_ADDR,
|
||||
src=DST_ADDR,
|
||||
options=IPOption(opts)
|
||||
)/ICMP(type=0, code=0, id=echo_req.payload.id)/echo_req.payload.payload
|
||||
outer = IP(
|
||||
dst=SRC_ADDR,
|
||||
src=DST_ADDR
|
||||
)/ICMP(type=3, code=1) # host unreach
|
||||
|
||||
echo_reply = outer/inner
|
||||
elif mode == "reply":
|
||||
# Sending normal echo reply
|
||||
echo_reply = IP(
|
||||
dst=SRC_ADDR,
|
||||
src=DST_ADDR,
|
||||
)/ICMP(type=0, code=0, id=echo_req.payload.id)/echo_req.payload.payload
|
||||
else:
|
||||
print("unknown mode {}".format(mode))
|
||||
exit(1)
|
||||
|
||||
tun.send(echo_reply)
|
||||
outs, errs = ping.communicate()
|
||||
|
||||
sys.exit(ping.returncode)
|
|
@ -153,6 +153,56 @@ ping6_46_body()
|
|||
ping6 -4 -6 localhost
|
||||
}
|
||||
|
||||
atf_test_case "inject_opts" "cleanup"
|
||||
inject_opts_head()
|
||||
{
|
||||
atf_set "descr" "Inject an ECHO REPLY with IP options"
|
||||
atf_set "require.user" "root"
|
||||
atf_set "require.progs" "python3" "scapy"
|
||||
}
|
||||
inject_opts_body()
|
||||
{
|
||||
atf_check -s exit:0 -o match:"wrong total length" -o match:"NOP" python3 $(atf_get_srcdir)/injection.py opts
|
||||
}
|
||||
inject_opts_cleanup()
|
||||
{
|
||||
ifconfig `cat tun.txt` destroy
|
||||
}
|
||||
|
||||
atf_test_case "inject_pip" "cleanup"
|
||||
inject_pip_head()
|
||||
{
|
||||
atf_set "descr" "Inject an ICMP error with a quoted packet with IP options"
|
||||
atf_set "require.user" "root"
|
||||
atf_set "require.progs" "python3" "scapy"
|
||||
}
|
||||
inject_pip_body()
|
||||
{
|
||||
atf_check -s exit:2 -o match:"Destination Host Unreachable" -o not-match:"01010101" python3 $(atf_get_srcdir)/injection.py pip
|
||||
}
|
||||
inject_pip_cleanup()
|
||||
{
|
||||
ifconfig `cat tun.txt` destroy
|
||||
}
|
||||
|
||||
# This is redundant with the ping_ tests, but it serves to ensure that scapy.py
|
||||
# is working correctly.
|
||||
atf_test_case "inject_reply" "cleanup"
|
||||
inject_reply_head()
|
||||
{
|
||||
atf_set "descr" "Basic ping test with packet injection"
|
||||
atf_set "require.user" "root"
|
||||
atf_set "require.progs" "python3" "scapy"
|
||||
}
|
||||
inject_reply_body()
|
||||
{
|
||||
atf_check -s exit:0 -o match:"1 packets transmitted, 1 packets received" python3 $(atf_get_srcdir)/injection.py reply
|
||||
}
|
||||
inject_reply_cleanup()
|
||||
{
|
||||
ifconfig `cat tun.txt` destroy
|
||||
}
|
||||
|
||||
atf_init_test_cases()
|
||||
{
|
||||
atf_add_test_case ping_c1_s56_t1
|
||||
|
@ -164,6 +214,9 @@ atf_init_test_cases()
|
|||
atf_add_test_case ping6_c1t4
|
||||
atf_add_test_case ping_46
|
||||
atf_add_test_case ping6_46
|
||||
atf_add_test_case inject_opts
|
||||
atf_add_test_case inject_pip
|
||||
atf_add_test_case inject_reply
|
||||
}
|
||||
|
||||
check_ping_statistics()
|
||||
|
|
Loading…
Reference in a new issue