Page MenuHomeFreeBSD

kern: wg: add support for removing Allowed-IPs
ClosedPublic

Authored by kevans on May 21 2025, 4:00 AM.
Tags
None
Referenced Files
F124431664: D50448.id156857.diff
Sat, Jul 26, 12:45 PM
F124393939: D50448.diff
Sat, Jul 26, 1:29 AM
Unknown Object (File)
Thu, Jul 24, 5:19 AM
Unknown Object (File)
Thu, Jul 24, 5:15 AM
Unknown Object (File)
Tue, Jul 22, 1:27 PM
Unknown Object (File)
Tue, Jul 22, 12:24 AM
Unknown Object (File)
Mon, Jul 21, 5:26 AM
Unknown Object (File)
Sat, Jul 19, 12:15 AM

Details

Summary

This was recently added to Linux to improve incremental update support,
as you could previously add Allowed-IPs but not remove without replacing
the whole set (and thus, potentially disrupting existing traffic).

Removal is incredibly straightforward; we'll find it in p_aips first
to ensure that it's actually valid for this peer, then we'll delete it
from the radix tree before we remove the corresponding p_aips entry.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 64785
Build 61669: arc lint + arc unit

Event Timeline

jason_zx2c4.com added inline comments.
sys/dev/wg/if_wg.c
635

This seems kind of inefficient -- O(n). Instead, you can look up the IP in the trie itself, making sure that it's an exact match, and then after double check that node->peer==peer.

That's what we do on Linux and in Go:

https://git.zx2c4.com/wireguard-linux/tree/drivers/net/wireguard/allowedips.c?h=devel#n283
https://git.zx2c4.com/wireguard-go/tree/device/allowedips.go#n259

sys/dev/wg/if_wg.h
37

Would it be better to have this macro be constructed by oring together the various supported flags for future proofing?

Search the radix tree instead to improve efficiency, make
WG_ALLOWEDIP_VALID_FLAGS an alias for WG_ALLOWEDIP_REMOVE at the moment to make
it clear we want to eventually OR anything else in.

sys/dev/wg/if_wg.c
651

I think you actually have to check if (aip->a_peer != peer) { unlock...(); return ENOENT; }, because the user could conceivably try to delete an aip that belongs to a different peer. See line 291 here: https://git.zx2c4.com/wireguard-linux/tree/drivers/net/wireguard/allowedips.c#n283

It finds the node with an exact match (not nearest match!), and then checks that the node's peer is the peer we want.

Similar code in the go, which is maybe clearer: https://git.zx2c4.com/wireguard-go/tree/device/allowedips.go#n258

	if prefix.Addr().Is6() {
		ip := prefix.Addr().As16()
		node, exact = table.IPv6.nodePlacement(ip[:], uint8(prefix.Bits()))
	} else if prefix.Addr().Is4() {
		ip := prefix.Addr().As4()
		node, exact = table.IPv4.nodePlacement(ip[:], uint8(prefix.Bits()))
	}

First looks up the node and whether or not it's an exact match. Then:

	if !exact || node == nil || peer != node.peer {
		return
	}
	node.remove()

It checks to see if it's exact, if it's actually a node, and if it's a node for the peer in question.

sys/dev/wg/if_wg.c
651

Whoops, yeah, meant to return to that. Will fix

kevans marked an inline comment as done.

Fix the case where an Allowed-IP exists, but belongs to another peer. This was
an easy panic button, a test will be added both for this and for stealing away
an allowed-ip with the +syntax (which, naturally, still works fine).

While we're here, remove some stray debug output and fix the lookup failure
case. Treating it as a silent success (because the allowed-ip is not there) is
more consistent with how it's done in the Linux and Go implementations.

This revision is now accepted and ready to land.Jun 17 2025, 5:04 PM