140 Commits

Author SHA1 Message Date
Cory Snider
558df8d6de d/libn/i/nftables: make Table a reference type
Table.Close() had a value receiver, so setting t.t = nil only modified
the callee's copy of the handle. The caller's Table was left looking
valid:

	t, _ := nftables.NewTable(...)
	t.Close()
	t.IsValid() // true

Worse, Close() only dropped the nftables handle, and nftApply() opens a
new one whenever it finds none. So Apply() and Reload() on a closed table
silently reopened a handle and carried on updating the ruleset.

At the root of it, a Table looked like a plain value but behaved like a
reference, and nothing stopped it from being copied. So embed table in
Table by value and hand out *Table instead. The Table/table split is
still needed - table's fields have to be exported for text/template -
but reference semantics are now visible at every call site, and they're
enforced: because table contains a sync.Mutex, "go vet" reports both a
copy of a Table and a method or function that takes one by value, so the
shape of this bug is no longer expressible.

Close() therefore can't invalidate the table by clearing a pointer, it
has to record the state. Add a closed flag, and refuse to open a new
nftables handle for a table that's been closed.

Apply() checked neither for a closed table nor for a nil *Table, which
would have panicked. It now reports an error, checking the closed state
with applyLock held so that it can't race with Close(), and before the
in-memory table is touched so that a rejected update isn't recorded as
applied.

The invalid table is now a nil *Table rather than a zero-value Table,
which also removes the need for consumers to return an empty Table
alongside an error. That made it obvious that the nftabler was leaking
the table it had just created when it gave up on setting up IPv6, so
close it.

Signed-off-by: Cory Snider <csnider@mirantis.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 10:52:59 -04:00
Sebastiaan van Stijn
ef7dc1e4f2 libnetwork: clarify dropLegacyFilterDirectAccess TODO
Correct the version referenced in the comment describing the migration
performed by Network.dropLegacyFilterDirectAccess.

The migration was introduced in v28.2.0, not v28.0.2. Also update the
TODO to clarify that the migration can be removed once we no longer
expect upgrades from v28.0.x or v28.1.x directly to a release that
includes the migration.

Refs: a0ff0a361e ("libnetwork: drop
legacy direct access filter rules")

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-07-25 21:02:24 +02:00
Sebastiaan van Stijn
d23f959a08 daemon/libnetwork: fix perfsprint linting
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-07-06 15:36:17 +02:00
Jintao Zhang
de262b667f libnetwork/drivers/bridge: configureIPForwarding: fix dropped error message
The early return duplicated the length check, making the custom error
path unreachable. As a result, a nil error was wrapped and returned
instead of the intended error message.

Signed-off-by: Jintao Zhang <zhangjintao9020@gmail.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-06-22 09:44:34 +02:00
Cory Snider
9106d6b8f4 libn/d/overlay: clean up rules from other fw mode
Stale rules in one firewall backend could persist if the daemon's
firewall backend is switched without rebooting the host, which could
interfere with the rules being programmed for the current firewall
backend. Have the overlay network driver delete any stale nftables table
when starting in iptables mode, and delete any stale iptables per-VNI
encryption rules when programming encryption for the VNI in nftables
mode.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2026-06-11 18:43:08 -04:00
Cory Snider
8e3e9f4cf9 d/libn/i/nftables: cgo nftables without nft cmd
When the daemon is linked against libnftables it programs the kernel
without invoking the `nft` command. Allow the nftables firewall backend
to be enabled when libnftables is used, irrespective of whether `nft` is
installed on the host.

Update the bridge network driver to clean up stale nftables tables in
iptables mode without depending on the `nft` command.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2026-06-11 10:54:46 +02:00
Cory Snider
0e44a01d8c libn/d/overlay: add nftables support
Port the firewall ruleset for encrypted overlay networks to nftables.
Maximize compatibility with the most distros by only using nftables
features that are widely available. Use the deprecated 'meta secpath
exists' expression instead of the more modern 'meta ipsec exists'.
Extract the VNI from VXLAN packets using the more widely available '@th'
raw payload expressions instead of '@ih' or 'vxlan vni' expressions.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2026-06-10 10:34:40 -04:00
Cory Snider
41f81c8bc3 d/libn/i/nftables: support general maps, sets
An nftables vmap is just a map whose element values are of type
`verdict`. Generalize VMap, VMapElement and Set to support any element
type.

Add a fluent API to build arbitrary tuple and mapping types from the
composition of other types or the 'typeof' an nftables expression.
Block the invalid composition of named types and `typeof` expressions at
compile time.

There are only a handful of contexts where the data type needs to be
specified: set and map definitions. Modelling set and map types as a
singular "nft type" does not align well with the semantics of nftables.
Map types are always composite types with a key and a value part. Set
types do not have a value part; it is an error to create a map with a
set type or vice versa. Encode this distinction into the Go type system
so it is a compile-time error to try to use a set type in a map context
or a map type in a set context.

Drop the 'NftType' prefix from the primitive set-type constants. The
prefix stutters with the package name and, as discussed above, it is not
accurate to call them "nft types." Verdicts cannot be used as set
elements or map keys. Provide dedicated methods to construct verdict-map
types from set types instead of modelling verdicts as types themselves.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2026-06-09 17:20:10 -04:00
Sebastiaan van Stijn
2ed9c69d99 libnet/drivers/bridge: clearConntrackEntries: move vars where used
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-05-07 17:41:14 +02:00
Sebastiaan van Stijn
0fef616242 Merge pull request #52423 from CarsonLenze/master
Change Conntrack to delete by Both Port And IP
2026-05-05 09:57:57 +02:00
Sebastiaan van Stijn
ee7e401904 Merge pull request #52436 from thaJeztah/peerdb_cleanups
libnetwork/drivers/overlay: minor cleanups in peerdb
2026-05-04 12:12:55 +02:00
Sebastiaan van Stijn
dbaa2f6f79 libnetwork/drivers/overlay: minor cleanups in peerdb
- use structured logs where suitable
- rename/remove some intermediate vars to reduce shadowing

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-04-23 16:24:07 +02:00
CarsonLenze
a836506d19 Change Conntrack to delete by Both Port And IP
Signed-off-by: CarsonLenze <carsonlenze@gmail.com>

Change to use PortBinding

Signed-off-by: CarsonLenze <carsonlenze@gmail.com>
2026-04-22 18:40:04 -04:00
Akihiro Suda
84aedb8055 rootless: support detach-netns mode
Now `dockerd-rootless.sh` launches RootlessKit with `--detach-netns`
so as to run the daemon in the host network namespace.

The libnetwork namespaces are allocated inside the "detached" netns
(`$ROOTLESSKIT_STATE_DIR/netns`) that is associated with slirp4netns,
vpnkit, pasta, etc., as the rootless daemon has no `CAP_NET_ADMIN` for
the host network namespace.

This will enable:
- Accelerated (and deflaked) `docker pull`, `docker push`, `docker build`, etc
- Proper support for `docker pull 127.0.0.1:.../...`
- Proper support for `dockern run --net=host`

See also:
- rootless-containers/rootlesskit PR 379
- containerd/nerdctl PR 2723

NOTE: libnetwork contains code generated by Claude Code

Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
2026-04-10 02:02:51 +09:00
Sebastiaan van Stijn
f7aea04bb3 go fix (GOOS=linux and windows)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-03-25 23:23:41 +01:00
Sebastiaan van Stijn
a436529bbc libnetwork: nftabler.Cleanup: pass context and make logs more useful
The Cleanup function oportunistically tries to cleanup old rule (if any).
In cases where the rules didn't exist, it would log the error returned
by the command, but this would always be `exit status 1`, which doesn't
provide details about the actual failure (i.e., if it's the expected
"does not exist").

We could improve the code by first calling `nft list table` to check if
rules were found, but that would expose a similar problem (error could
be due to the rules not present, or "other cause".

This patch just changes the logs to be more informative, and passes the
context to allow cancelling the command if the context is cancelled.

Before this patch:

    INFO[2026-02-21T13:30:10.428457589Z] Deleting nftables IPv4 rules                  error="exit status 1"
    INFO[2026-02-21T13:30:10.453012214Z] Deleting nftables IPv6 rules                  error="exit status 1"

With this patch:

    INFO[2026-02-21T14:10:06.183933878Z] Deleting nftables IPv4 rules                  error="exit status 1" output="Error: Could not process rule: No such file or directory\ndelete table ip docker-bridges"
    INFO[2026-02-21T14:10:06.212198878Z] Deleting nftables IPv6 rules                  error="exit status 1" output="Error: Could not process rule: No such file or directory\ndelete table ip6 docker-bridges"

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-02-21 15:18:54 +01:00
Sebastiaan van Stijn
34653f13ee daemon/libnetwork: update go:generate import paths
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-02-12 16:04:36 +01:00
Cory Snider
51664a25d7 libn/d/overlay: calculate SPI like older engines
The Security Parameter Index value signals to the recipient which key to
decrypt the packet with. The overlay driver derives the SPI value for a
flow from a hash digest of the source and destination IP addresses. The
source and destination need to derive the same digest given the same
information as the SPI values are not signaled over the overlay driver's
control plane. Refactoring the overlay driver to use netip types
accidentally changed the hash function to digest IPv4 addresses in
4-byte form, causing newer engines to calculate a different SPI value
for a flow than older engines would. Restore the original calculation
by hashing IPv4 addresses in their 16-byte form, and refactor the
buildSPI function to take netip.Addr parameters to prevent 16-byte vs
4-byte mixups from being possible in the future.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2026-01-27 18:32:10 -05:00
Sebastiaan van Stijn
17de27ffc2 daemon: gofumpt
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-01-24 17:16:05 +01:00
Sebastiaan van Stijn
1b5b00c98c fix grammar: user defined / user specified -> user-(defined|specified)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-01-19 13:43:06 +01:00
Paweł Gronowski
71fd582aa2 modernize: Use strings.Builder instead of string concatenation
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-12-15 18:56:34 +01:00
Paweł Gronowski
3df05205f4 modernize: Use range int
Added in Go 1.22

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-12-15 18:56:34 +01:00
Sebastiaan van Stijn
99066209a2 libnetwork/options: GenerateFromModel: use generics
Use generics so that the produced output is already in the right
type.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-12-10 01:48:48 +01:00
Albin Kerouanton
52fae09ec0 libnet/pms/nat: don't bind IPv6 ports if not supported by port driver
In rootless mode, the Engine needs to call the rootless port driver to
know which IP address it should bind to inside of its network namespace.

The slirp4netns port drivers doesn't support binding to IPv6 address, so
we need to detect that before listening on the port.

Before commit 201968cc0, this wasn't a problem because the Engine was
binding the port, then calling rootless port driver to learn whether the
proto/IP family was supported, and listen on the port if so.

Starting with that commit, the Engine does bind + listen in one go, and
then calls the port driver — this is too late. Fix the bug by checking
if the port driver supports the PortBindingReq, and only allocate the
port if so.

Signed-off-by: Albin Kerouanton <albin.kerouanton@docker.com>
2025-11-28 19:40:34 +01:00
Albin Kerouanton
20634eddce Merge pull request #51496 from thaJeztah/discoverapi_cleanups
libnetwork: some minor refactor / cleanups
2025-11-27 12:22:01 +01:00
Rob Murray
a2de9bb334 Unmap more netip.Addr vars created using AddrFromSlice
Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-11-24 16:51:14 +00:00
Rob Murray
ed10b98506 Restore missing nwEndpointsMu.Lock
- introduced by 4f7afb8 (Remove libnet's logic to track a driver's
  port mapping state)

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-11-18 15:38:48 +00:00
Sebastiaan van Stijn
e59d1b4563 libnetwork/drivers/overlay: DiscoverNew: move logic to setKeys, updateKeys
Make the DiscoverNew switch only responsible for asserting the correct
data type, and push the conversion logic into the setKeys and updateKeys
methods.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-11-16 23:36:04 +01:00
Sebastiaan van Stijn
f40b45ca1f libnetwork/drivers/overlay: use structured logs in some places
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-11-16 23:36:04 +01:00
Rob Murray
7989fea6d2 Merge pull request #51241 from thaJeztah/overlay_pass_context
libnetwork/drivers/overlay: pass context for logger
2025-10-21 14:22:12 +01:00
Sebastiaan van Stijn
ee3cab4158 libnetwork/drivers/overlay: pass context for logger
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-10-21 15:08:03 +02:00
Sebastiaan van Stijn
bdc7474826 Merge pull request #51229 from olljanat/win-overlay-custom-dns
libnetwork: support custom DNS servers in Windows overlay driver
2025-10-21 14:40:07 +02:00
Olli Janatuinen
48c2d8c458 libnetwork: support custom DNS servers in Windows overlay driver
Signed-off-by: Olli Janatuinen <olli.janatuinen@gmail.com>
2025-10-21 07:33:02 +00:00
Sebastiaan van Stijn
10faa629fe libnetwork/drivers/macvlan, ipvlan: assorted minor cleanups
- Inline some vars and align between drivers
- Remove nested if's where possible
- Use `WithError` for some logs, and use the context if available
- Scope variables locally where only used locally and, the reverse,
  make it clear where a (function-)global variable is used.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-10-20 08:52:09 +02:00
Sebastiaan van Stijn
a013147c40 libnetwork/drivers/macvlan: parentHasSingleUser: don't create copy of networks
This function was calling driver.getNetworks, which copies the networks map
into a new slice. As we're not mutating the networks, we can just use the
networks map itself to check if there's any networks configured with the
same parent.

While changing;

- Also change the signature to accept the parent to compare to as a string
- Return early once we determined there's more than one user

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-10-20 08:14:45 +02:00
Sebastiaan van Stijn
65296cd0e7 libnetwork/drivers/macvlan, ipvlan: un-embed mutexes
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-10-20 08:14:44 +02:00
Sebastiaan van Stijn
a2f4f09f91 libnetwork/drivers/macvlan, ipvlan: remove unused sync.Once
Both were added as part of the initial implementation in commit [moby@ea30113]
([libnetwork@1d6f2c5]), but never used.

[moby@ea30113]: ea30113303
[libnetwork@1d6f2c5]: 1d6f2c59c4

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-10-20 08:14:44 +02:00
Sebastiaan van Stijn
5276dd8e9a libnetwork/drivers/ipvlan: remove ifaceGateway utility
This utility was only called with two constant values;

    const (
        defaultV4RouteCidr = "0.0.0.0/0"
        defaultV6RouteCidr = "::/0"
    )

However;

- calling it would always execute a `net.ParseCIDR`
- verify if it would produce an error (which would be very unlikely)
- it used a `staticRoute` struct that was ONLY used for this function
- and immediately deconstructed into its components
- furthermore, the `NextHop` field would be discarded by jinfo.AddStaticRoute,
  which only used the third argument for `routeType == types.NEXTHOP`

This patch:

- removes the `ifaceGateway` and associated `staticRoute` and consts
- defines two package-level vars for `defaultV4Net` and `defaultV6Net`,
  which can be reused (no need to parse / construct them for every join)

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-10-20 08:14:44 +02:00
Sebastiaan van Stijn
d481c09fa7 libnetwork/drivers/macvlan, ipvlan: make driver.leave a stub
These drivers did not do anything meaningful in the `Leave` method; they
would check if the network and/or endpoint were missing, in which case
they produced an error, but the network and endpoint (if present) would
not be used, so it was only validation.

Such validation could still be relevant elsewhere, but looking at where
this method is called; the `Driver.Leave()` is called in two places, both
of which don't handle the error, other than logging it as a warning / error;

It's called by `Endpoint.sbJoin()`, as part of the rollback;
d5c838dc5e/daemon/libnetwork/endpoint.go (L539-L545)

And `Endpoint.sbLeave()`, which also discards the error;
d5c838dc5e/daemon/libnetwork/endpoint.go (L772-L776)

Based on he above, this code looks to be redundant, so replacing it with
a stub; returning `nil`.

As replacing the code removed the use of network.getEndpoint, which was effectively
a copy of network.endpoint (which didn't have error handling), I merged the two
methods, and removed custom error-handling elsewhere.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-10-20 08:14:44 +02:00
Sebastiaan van Stijn
aec6e7f7b6 libnetwork/drivers/macvlan, ipvlan: remove networkTable, endpointTable
These types were just a straight map[string]XXX, with no methods or other
properties attached.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-10-20 08:14:44 +02:00
Sebastiaan van Stijn
bf7277f8fe libnetwork/drivers/macvlan, ipvlan: remove getSubnetforIPv6, getSubnetforIPv4
These methods were just wrappers around getSubnetforIP; let's peel away the
abstraction and call it directly; we're already checking for n.config.Ipv4Subnet
and n.config.Ipv6Subnets on the call-site, so may as well just pass it in.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-10-20 08:14:34 +02:00
Sebastiaan van Stijn
a294445345 ibnetwork/drivers/macvlan, ipvlan: align and fix potential panic
There were some missing checks whether ep.addr, ep.addrv6 were nil,
which could panic in getSubnetForIP.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-10-19 13:35:25 +02:00
Sebastiaan van Stijn
17425cff08 libnetwork/drivers/macvlan, ipvlan: driver.Join: don't fetch endpoint twice
The function was fetching a reference to the endpoint twice; while this
did give the option for an early return, in practice it didn't mean much,
because it could still fail if the endpoint was removed in between.

This code still has a race condition, because while a reference to the
endpoint is retrieved while acquiring a lock, the result is mutated without.
This probably needs to either have some accessor, or the function should
keep a lock for the whole operation (possibly switching to an RWMutex).

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-10-19 13:17:56 +02:00
Rob Murray
9912ccd7b3 Clean up bridge device on network create error
When the bridge driver encounters an error during network
creation, delete the bridge device if one has been added.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-10-09 15:52:25 +01:00
Cory Snider
d5c838dc5e internal: move sliceutil from daemon/internal
These utilities are very handy to use in integration tests, too. Move
the package so it can be imported by them.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2025-10-03 21:39:14 +02:00
Cory Snider
46ab36ae46 daemon/internal: move netiputil from libnetwork
These utilities are going to be needed elsewhere in the daemon to handle
netip values from API requests.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2025-10-03 21:39:13 +02:00
Rob Murray
b26972f9f2 Merge pull request #51033 from robmry/use-libnftables
Use libnftables in dynamically linked binary
2025-10-03 16:53:06 +01:00
Sebastiaan van Stijn
8905c3052b daemon/libnetwork: use t.Context() in tests
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-09-25 22:53:41 +02:00
Rob Murray
6db6de2c20 Use libnftables in dynamically linked binary
Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-09-24 18:27:17 +01:00
Rob Murray
de5e64b3bd Add option WithSetNsHandles for testutil SetupTestOSContextEx
Allow tests to run in parallel with separate network namespaces,
without modifying the global-state namespace/netlink handles in
the "ns" package ... only useful for tests that don't depend on
package "ns".

Use the new option in iptabler/nftabler tests.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-09-23 17:35:58 +01:00