pf: implement set-tos for IPv6
Extend the existing set-tos keyword to also be able to set traffic class on IPv6 traffic. Add tests for this as well. Reviewed by: kp Differential Revision: https://reviews.freebsd.org/D31564
This commit is contained in:
parent
c138424148
commit
0a7d1fc6f6
@ -157,7 +157,7 @@ static int pf_reassemble(struct mbuf **, struct ip *, int, u_short *);
|
||||
#ifdef INET6
|
||||
static int pf_reassemble6(struct mbuf **, struct ip6_hdr *,
|
||||
struct ip6_frag *, uint16_t, uint16_t, u_short *);
|
||||
static void pf_scrub_ip6(struct mbuf **, uint8_t);
|
||||
static void pf_scrub_ip6(struct mbuf **, uint32_t, uint8_t, uint8_t);
|
||||
#endif /* INET6 */
|
||||
|
||||
#define DPFPRINTF(x) do { \
|
||||
@ -1283,7 +1283,7 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kkif *kif,
|
||||
if (sizeof(struct ip6_hdr) + plen > m->m_pkthdr.len)
|
||||
goto shortpkt;
|
||||
|
||||
pf_scrub_ip6(&m, r->min_ttl);
|
||||
pf_scrub_ip6(&m, r->rule_flag, r->min_ttl, r->set_tos);
|
||||
|
||||
return (PF_PASS);
|
||||
|
||||
@ -2032,7 +2032,7 @@ pf_scrub_ip(struct mbuf **m0, u_int32_t flags, u_int8_t min_ttl, u_int8_t tos)
|
||||
|
||||
#ifdef INET6
|
||||
static void
|
||||
pf_scrub_ip6(struct mbuf **m0, u_int8_t min_ttl)
|
||||
pf_scrub_ip6(struct mbuf **m0, u_int32_t flags, u_int8_t min_ttl, u_int8_t tos)
|
||||
{
|
||||
struct mbuf *m = *m0;
|
||||
struct ip6_hdr *h = mtod(m, struct ip6_hdr *);
|
||||
@ -2040,5 +2040,11 @@ pf_scrub_ip6(struct mbuf **m0, u_int8_t min_ttl)
|
||||
/* Enforce a minimum ttl, may cause endless packet loops */
|
||||
if (min_ttl && h->ip6_hlim < min_ttl)
|
||||
h->ip6_hlim = min_ttl;
|
||||
|
||||
/* Enforce tos. Set traffic class bits */
|
||||
if (flags & PFRULE_SET_TOS) {
|
||||
h->ip6_flow &= IPV6_FLOWLABEL_MASK | IPV6_VERSION_MASK;
|
||||
h->ip6_flow |= htonl((tos | IPV6_ECN(h)) << 20);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -115,6 +115,14 @@ def check_ping6_request(args, packet):
|
||||
if icmp.data != PAYLOAD_MAGIC:
|
||||
return False
|
||||
|
||||
# Wait to check expectations until we've established this is the packet we
|
||||
# sent.
|
||||
if args.expect_tc:
|
||||
if ip.tc != int(args.expect_tc[0]):
|
||||
print("Unexpected traffic class value %d, expected %d" \
|
||||
% (ip.tc, int(args.expect_tc[0])))
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def check_ping_reply(args, packet):
|
||||
@ -147,6 +155,12 @@ def check_ping4_reply(args, packet):
|
||||
if raw.load != PAYLOAD_MAGIC:
|
||||
return False
|
||||
|
||||
if args.expect_tos:
|
||||
if ip.tos != int(args.expect_tos[0]):
|
||||
print("Unexpected ToS value %d, expected %d" \
|
||||
% (ip.tos, int(args.expect_tos[0])))
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def check_ping6_reply(args, packet):
|
||||
@ -170,6 +184,12 @@ def check_ping6_reply(args, packet):
|
||||
print("data mismatch")
|
||||
return False
|
||||
|
||||
if args.expect_tc:
|
||||
if ip.tc != int(args.expect_tc[0]):
|
||||
print("Unexpected traffic class value %d, expected %d" \
|
||||
% (ip.tc, int(args.expect_tc[0])))
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def ping(send_if, dst_ip, args):
|
||||
@ -192,8 +212,11 @@ def ping6(send_if, dst_ip, args):
|
||||
ip6 = sp.IPv6(dst=dst_ip)
|
||||
icmp = sp.ICMPv6EchoRequest(data=sp.raw(PAYLOAD_MAGIC))
|
||||
|
||||
if args.send_tc:
|
||||
ip6.tc = int(args.send_tc[0])
|
||||
|
||||
if args.fromaddr:
|
||||
ip.src = args.fromaddr[0]
|
||||
ip6.src = args.fromaddr[0]
|
||||
|
||||
req = ether / ip6 / icmp
|
||||
sp.sendp(req, iface=send_if, verbose=False)
|
||||
@ -274,10 +297,14 @@ def main():
|
||||
# Packet settings
|
||||
parser.add_argument('--send-tos', nargs=1,
|
||||
help='Set the ToS value for the transmitted packet')
|
||||
parser.add_argument('--send-tc', nargs=1,
|
||||
help='Set the traffic class value for the transmitted packet')
|
||||
|
||||
# Expectations
|
||||
parser.add_argument('--expect-tos', nargs=1,
|
||||
help='The expected ToS value in the received packet')
|
||||
parser.add_argument('--expect-tc', nargs=1,
|
||||
help='The expected traffic class value in the received packet')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
|
@ -4,6 +4,8 @@
|
||||
#
|
||||
# Copyright (c) 2017 Kristof Provost <kp@FreeBSD.org>
|
||||
#
|
||||
# Copyright (c) 2021 Samuel Robinette
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
@ -114,7 +116,93 @@ v4_cleanup()
|
||||
pft_cleanup
|
||||
}
|
||||
|
||||
atf_test_case "v6" "cleanup"
|
||||
v6_head()
|
||||
{
|
||||
atf_set descr 'set-tos6 test'
|
||||
atf_set require.user root
|
||||
|
||||
# We need scapy to be installed for out test scripts to work
|
||||
atf_set require.progs scapy
|
||||
}
|
||||
|
||||
v6_body()
|
||||
{
|
||||
pft_init
|
||||
|
||||
epair=$(vnet_mkepair)
|
||||
ifconfig ${epair}a inet6 add 2001:db8:192::1
|
||||
vnet_mkjail alcatraz ${epair}b
|
||||
jexec alcatraz ifconfig ${epair}b inet6 add 2001:db8:192::2
|
||||
|
||||
route -6 add 2001:db8:192::2 2001:db8:192::1
|
||||
jexec alcatraz route -6 add 2001:db8:192::1 2001:db8:192::2
|
||||
|
||||
jexec alcatraz pfctl -e
|
||||
|
||||
# No change is done if not requested
|
||||
pft_set_rules alcatraz "scrub out proto ipv6-icmp"
|
||||
atf_check -s exit:1 -o ignore -e ignore ${common_dir}/pft_ping.py \
|
||||
--ip6 \
|
||||
--sendif ${epair}a \
|
||||
--to 2001:db8:192::2 \
|
||||
--replyif ${epair}a \
|
||||
--expect-tc 42
|
||||
|
||||
# The requested ToS is set
|
||||
pft_set_rules alcatraz "scrub out proto ipv6-icmp set-tos 42"
|
||||
atf_check -s exit:0 -o ignore -e ignore ${common_dir}/pft_ping.py \
|
||||
--ip6 \
|
||||
--sendif ${epair}a \
|
||||
--to 2001:db8:192::2 \
|
||||
--replyif ${epair}a \
|
||||
--expect-tc 42
|
||||
|
||||
# ToS is not changed if the scrub rule does not match
|
||||
pft_set_rules alcatraz "scrub out from 2001:db8:192::3 set-tos 42"
|
||||
atf_check -s exit:1 -o ignore -e ignore ${common_dir}/pft_ping.py \
|
||||
--ip6 \
|
||||
--sendif ${epair}a \
|
||||
--to 2001:db8:192::2 \
|
||||
--replyif ${epair}a \
|
||||
--expect-tc 42
|
||||
|
||||
# Multiple scrub rules match as expected
|
||||
pft_set_rules alcatraz "scrub out from 2001:db8:192::3 set-tos 13" \
|
||||
"scrub out proto ipv6-icmp set-tos 14"
|
||||
atf_check -s exit:0 -o ignore -e ignore ${common_dir}/pft_ping.py \
|
||||
--ip6 \
|
||||
--sendif ${epair}a \
|
||||
--to 2001:db8:192::2 \
|
||||
--replyif ${epair}a \
|
||||
--expect-tc 14
|
||||
|
||||
# And this works even if the packet already has ToS values set
|
||||
atf_check -s exit:0 -o ignore -e ignore ${common_dir}/pft_ping.py \
|
||||
--ip6 \
|
||||
--sendif ${epair}a \
|
||||
--to 2001:db8:192::2 \
|
||||
--replyif ${epair}a \
|
||||
--send-tc 42 \
|
||||
--expect-tc 14
|
||||
|
||||
# ToS values are unmolested if the packets do not match a scrub rule
|
||||
pft_set_rules alcatraz "scrub out from 2001:db8:192::3 set-tos 13"
|
||||
atf_check -s exit:0 -o ignore -e ignore ${common_dir}/pft_ping.py \
|
||||
--ip6 \
|
||||
--sendif ${epair}a \
|
||||
--to 2001:db8:192::2 \
|
||||
--replyif ${epair}a \
|
||||
--expect-tc 0
|
||||
}
|
||||
|
||||
v6_cleanup()
|
||||
{
|
||||
pft_cleanup
|
||||
}
|
||||
|
||||
atf_init_test_cases()
|
||||
{
|
||||
atf_add_test_case "v4"
|
||||
atf_add_test_case "v6"
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user