For IPv4 it's valid for a UDP checksum to be 0 (i.e. no checksum). This isn't
the case for IPv6, so if we translate a UDP packet from IPv4 to IPv6 we need to
ensure that the checksum is calculated.
Add a test case to verify this. Rework the server jail so it can listen for TCP
and UDP packets at the same time.
Sponsored by: Rubicon Communications, LLC ("Netgate")
Tables can only be used as a redirspec (i.e. in pf_map_addr()) in round-robin mode.
Enforce this for af-to tables as well.
Add a test case to verify.
Sponsored by: Rubicon Communications, LLC ("Netgate")
We do multiple lookups during the nat64 process, some of which will fail due
to address family mismatches. Do not reset the lookup offset so we actually use
different addresses from the table.
Sponsored by: Rubicon Communications, LLC ("Netgate")
This isn't expected to work, for obvious reasons, but we also expect to not
panic doing this. Exercise this special case.
Sponsored by: Rubicon Communications, LLC ("Netgate")
Just as with reply-to rules we don't know what interface we will send this out
of until we create the state. Create new nat64 rules as floating, but bind them
to the appropriate interface on the first pf_route(), when we do know.
Set state policy if-bound for the nat64 tests to validate this.
See also: 6460322a0
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D47801
Use dmesg(8) instead rather than relying on a particular syslogd
configuration, and just skip the test if we can't access the msgbuf.
While we're here, remove some debugging output that we don't actually
need.
We don't bother tweaking the sysctl in these tests, we'll just try with
it forced both on and off via proccontrol(1). This could be problematic
in the face of pid wrapping if we got really unfortunate, but the
potential solutions need careful consideration- you probably don't want
to assume a certain velocity of messages into syslog, so just checking
the last N lines is probably similarly flakey.
This check for SO_REUSEPORT was added way back in commit 52b65dbe85.
Per the commit log, this commit restricted this port-stealing check to
unicast addresses, and then only if the existing socket does not have
SO_REUSEPORT set. In other words, if there exists a socket bound to
INADDR_ANY, and we bind a socket to INADDR_ANY with the same port, then
the two sockets need not be owned by the same user if the existing
socket has SO_REUSEPORT set.
This is a surprising semantic; bugzilla PR 7713 gives some additional
context. That PR makes a case for the behaviour described above when
binding to a multicast address. But, the SO_REUSEPORT check is only
applied when binding to a non-multicast address, so it doesn't really
make sense. In the PR the committer notes that "unicast applications
don't set SO_REUSEPORT", which makes some sense, but also refers to
"multicast applications that bind to INADDR_ANY", which sounds a bit
suspicious.
OpenBSD performs the multicast check, but not the SO_REUSEPORT check.
DragonflyBSD removed the SO_REUSEPORT (and INADDR_ANY) checks back in
2014 (commit 0323d5fde12a4). NetBSD explicitly copied our logic and
still has it.
The plot thickens: 20 years later, SO_REUSEPORT_LB was ported from
DragonflyBSD: this option provides similar semantics to SO_REUSEPORT,
but for unicast addresses it causes incoming connections/datagrams to be
distributed among all sockets in the group. This commit (1a43cff92a)
inverted the check for SO_REUSEPORT while adding one for
SO_REUSEPORT_LB; this appears to have been inadvertent. However:
- apparently no one has noticed that the semantics were changed;
- sockets belonging to different users can now be bound to the same port
so long as they belong to a single lbgroup bound to INADDR_ANY, which
is not correct.
Simply remove the SO_REUSEPORT(_LB) checks, as their original
justification was dubious and their current implementation is wrong; add
some tests.
Reviewed by: glebius
MFC after: 1 month
Sponsored by: Klara, Inc.
Sponsored by: Stormshield
Differential Revision: https://reviews.freebsd.org/D47832
States created by route-to rules can't be trusted when received with
pfsync version 1301 as they lack the rt and rt_kif information. They
are imported, though, and pf_route() function attempts to recover
the missing information for every forwarded packet.
Move the recovery operation to pfsync_state_import() so that it's
performed only once and if it's impossible don't import the state.
Add an additional check for cases when recovery might produce wrong
results.
Reviewed by: kp
Approved by: kp (mentor)
Sponsored by: InnoGames GmbH
Differential Revision: https://reviews.freebsd.org/D47906
Add support for endpoint-independent mapping ("full cone NAT") in
Libalias's UDP NAT.
This conforms to RFC 4787 requirements 1 and 3. All UDP packets sent out from a
particular internal address:port leave via the same NAT address:port,
regardless of their destination.
Add some libalias tests and supporting defines.
Reviewed by: igoro, thj
Differential Revision: https://reviews.freebsd.org/D46689D
When processing an SCTP ASCONF we re-run the rules processing to check
if the new state should be allowed as well. We used to do so against the
'all' interface, to allow new connections to use any interface.
This is problematic for two reasons, the first being it may unexpectedly
bypass interface restrictions. The more important one is that it
can trigger panics. If the ruleset contains a rule which filters on
interface group we'd attempt to process the group list for the 'all'
interface. As this isn't a real interface it doesn't have an associated
struct ifnet, and we end up dereferencing a NULL pointer.
Solve this by not overriding the interface, instead leaving the physical
interface the SCTP ASCONF arrived on. This implies that we may end up
binding to that interface (if if-bound), and thus denying traffic on
other interfaces. Users can allow this anyway by setting 'state-policy
floating' on the relevant SCTP rules. This arguably better reflects user
intent as well. That is, we'll consider SCTP multihomed states to be
floating if we're in floating mode, and if-bound if we're if-bound.
Update the test cases to account for this, while adding a "pass on
lo" (i.e. pass on an interface group") rule to provoke this issue. Add
separate test cases for the floating and if-bound scenarios.
Reported by: Franco Fichtner <franco@opnsense.org>
MFC after: 3 weeks
Sponsored by: Orange Business Services
"netstat -rn" no longer prints the default route using symbol names, but
the test relied on it. Update it to look for ::/0 instead.
MFC after: 1 week
Fixes: 9206c79961 ("usr.bin/netstat: -n should not print symbolic names")
Source nodes are created quite early in pf_create_state(), even before
the state is allocated, locked and inserted into its hash row. They are
prone to being freed by source node killing or clearing ioctl while
pf_create_state() is still running.
The function pf_map_addr_sn() can be called in two very different paths.
One is for filter rules where it is called from
pf_create_state() after pf_insert_src_node(). In this case it is called
with a given source node and does not perform its own search and must
return the source node.
The other one is for NAT rules where it is called from
pf_get_translation() or its descendants. In this case it is called with
no known source node and performs its own search for source nodes. This
source node is then passed back to pf_create_state() without locking.
The states property of source node is increased in pf_find_src_node()
which allows for the counter to increase when a packet matches the NAT
rule but not a pass keep state rule.
The function pf_map_addr() operates on unlocked source node.
Modify pf_find_src_node() to return locked on source node found, so
that any subsequent operations can access the source node safely.
Move sn->states++ counter increase to pf_insert_src_node() to ensure
that it's called only from pf_create_state() and not from NAT ruleset
path, and have it increased only if the source node has really been
inserted or found, simplifying the cleanup.
Add locking in pf_src_connlimit() and pf_map_addr(). Sprinkle mutex
assertions in pf_map_addr().
Add a function pf_src_node_exists() to check a known source node is
still valid. Use it in pf_create_state() where it's impossible to hold
locks from pf_insert_src_node() because that would cause LoR (nodes
first, then state) against pf_src_connlimit() (state first, then node).
Don't propagate the source node found while parsing the NAT ruleset to
pf_create_state() because it must be found again and locked or created.
Reviewed by: kp
Approved by: kp (mentor)
Sponsored by: InnoGames GmbH
Differential Revision: https://reviews.freebsd.org/D47770
These tests demonstrate the bug that was fixed in ccb973da1f.
Sponsored by: Klara, Inc.
Sponsored by: NetApp, Inc.
Reviewed by: markj
Differential Revision: https://reviews.freebsd.org/D47738
If a fragmented IPv6 packet hits a route-to rule we have to first prevent
the pf_test(PF_OUT) check in pf_route6() from refragmenting (and calling
ip6_output()/ip6_forward()). We then have to refragment in pf_route6() and
transmit the packets on the route-to interface.
Split pf_refragment6() into two parts, the first to perform the refragmentation,
the second to call ip6_output()/ip6_forward() and call the former from
pf_route6().
Add a test case for route-to-ing fragmented IPv6 packets to verify this works
as expected.
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D47684
These tests try to verify that packet prioritisation works as expected. This is
inherently a statistical process, and is difficuly to measure automatically.
Run the tests more times and accept more failures.
Sponsored by: Rubicon Communications, LLC ("Netgate")
The ioctl DIOCRCLRASTATS provides the functionality of clearing stats
not only for the whole table for for addresses stored in that table. The
functionality was missing from pfctl, though. Add it now.
PR: 282877
Obtained from: OpenBSD, kirill <kirill@openbsd.org>, e496dff3a7
MFC after: 3 weeks
These tests assume exclusive use of one or more FIBs and so can't be run
in parallel. Running them in a VNET jail sidesteps this problem.
MFC after: 1 week
Sponsored by: Klara, Inc.
Sponsored by: Stormshield
If during ip_forward() we find a blackhole (or reject) route we should stop
processing and count this in the 'cantforward' counter, just like we already do
for IPv6.
Blackhole routes are set to use the loopback interface, so we don't actually
incorrectly forward traffic, but we do fail to count it as unroutable.
Test this, both for IPv4 and IPv6.
Reviewed by: melifaro
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D47529
compat: test case add was previously removed but not the test itself
pass: test was added twice
Reviewed by: kp
Differential Revision: https://reviews.freebsd.org/D47535
Some pf tests check the output of pfctl -s[sSr] to find if relevant
states, source nodes or rules exist and if their counters have proper
values. The output is multiple lines per entry and contains varying
amount of whitespace. This makes parsing it rather hard.
Provide a function for standardization of output of pfctl -s[sSr] which
converts the output to a single line per entry and reduces whitespace
always to a single space. Adjust existing tests to make use of this
function.
Revieved by: kp
Approved by: kp (mentor)
Differental Revision: https://reviews.freebsd.org/D47435
Don't use string comparisons, use socket.inet_pton() instead. This avoids
confusion when there are different ways to spell the same IP addres.
e.g. 64:ff9b::c000:202 and 64:ff9b::192.0.2.2 are two representations of the same
address.
Sponsored by: Rubicon Communications, LLC ("Netgate")
Fix the find_device function to work regardless of whether "camcontrol
devlist" lists the da device first and the pass device second or vice
versa. On FreeBSD 14 and 15 it apparently always lists da first. But
on 13 it can do it in either order.
MFC after: 2 weeks
MFC with: fe1755fa
Sponsored by: ConnectWise
Reviewed by: emaste, markj, #cam
Differential Revision: https://reviews.freebsd.org/D47446
With this patch, it is possible to call fchmod() on a unix socket prior
to binding it to the filesystem namespace, so that the mode is set
atomically. Without this, one has to call chmod() after bind(), leaving
a window where threads can connect to the socket with the default mode.
After bind(), fchmod() reverts to failing with EINVAL.
This interface is copied from Linux.
The behaviour of fstat() is unmodified, i.e., it continues to return the
mode as set by soo_stat().
PR: 282393
Reviewed by: kib
MFC after: 1 month
Differential Revision: https://reviews.freebsd.org/D47361
Kyua skips tests based on the jail execution environment if a system is
built WITHOUT_JAIL. Thus, the test case does not need to handle it.
Reviewed by: markj
Approved by: markj (mentor)
Differential Revision: https://reviews.freebsd.org/D47105
The SYN|ACK generated by pf needs to inherit M_LOOP from the original
SYN, otherwise it gets dropped by ip6_input().
Fix this by adding an mbuf_flags argument to pf_build_tcp() that can be
used to set both M_SKIP_FIREWALL and M_LOOP as needed. Set M_LOOP on
the output mbuf if it was generated in response to an mbuf with M_LOOP
set.
Add a regression test case. The v4 case had no problems, but the v6
case fails without this change.
Reviewed by: kp
MFC after: 1 month
Sponsored by: Klara, Inc.
Sponsored by: Zenarmor
Differential Revision: https://reviews.freebsd.org/D47257
If sysutils/porch is installed, we'll do some basic testing of tty
behavior. The existing tests primarily cover ICANON-related processing
and corner cases that have been fixed somewhat recently, but I
anticipate growing this out a bit in due time.
Reviewed by: ngie
Differential Revision: https://reviews.freebsd.org/D46806
io.cc relies on `std::setw(..)`, which is exported by the iomanip C++
header. Newer versions of GoogleTest don't export this header, so add
the explicit include.
This unbreaks the build with GoogleTest 1.15.2.
MFC after: 1 week
Differential Revision: https://reviews.freebsd.org/D47194
The update to py-twisted 24.7.0 broke EPSV mode in twisted's ftp server.
Work around this by disabling EPSV (and thus using PASV).
PR: 282154
MFC after: 1 week
Sponsored by: Rubicon Communications, LLC ("Netgate")
What's required and not required to be defined is complicated. Write
tests to enshrine it:
endian.h and sys/endian.h:
[bl]e{16,32,64}toh
hto[bl]e{16,32,64}
byteswap.h:
{__,}bswap_{16,32,64}
sys/endian.h:
{__,}bswap{16,32,64}
_BYTE_ORDER
_BIG_ENDIAN
_LITTLE_ENDIAN
_PDP_ENDIAN
endian.h:
__BYTE_ORDER
__BIG_ENDIAN
__LITTLE_ENDIAN
__PDP_ENDIAN
__FLOAT_WORD_ORDER
We also ensure that the sys/endian.h conditions hold true when
we include both endian.h and sys/endian.h in either order.
NOT TESTED: deprecated symbols, internal to glibc symbols
Sponsored by: Netflix
Discussed with: markj (made the changes he requested)
Differential Revision: https://reviews.freebsd.org/D32052