Skip to content

Comments

[client] skip UAPI listener in netstack mode#5397

Open
pappz wants to merge 1 commit intomainfrom
fix/netstack-skip-uapi
Open

[client] skip UAPI listener in netstack mode#5397
pappz wants to merge 1 commit intomainfrom
fix/netstack-skip-uapi

Conversation

@pappz
Copy link
Contributor

@pappz pappz commented Feb 19, 2026

Describe your changes

In netstack (proxy) mode, the process lacks permission to create
/var/run/wireguard, making the UAPI listener unnecessary and causing
a misleading error log. Introduce NewUSPConfigurerNoUAPI and use it
for the netstack device to avoid attempting to open the UAPI socket
entirely. Also consolidate UAPI error logging to a single call site.

Issue ticket number and link

Stack

Checklist

  • Is it a bug fix
  • Is a typo/documentation fix
  • Is a feature enhancement
  • It is a refactor
  • Created tests that fail without the change (if possible)

By submitting this pull request, you confirm that you have read and agree to the terms of the Contributor License Agreement.

Documentation

Select exactly one:

  • I added/updated documentation for this change
  • Documentation is not needed for this change (explain why)

Docs PR URL (required if "docs added" is checked)

Paste the PR link from https://github.com/netbirdio/docs here:

https://github.com/netbirdio/docs/pull/__

Summary by CodeRabbit

  • Bug Fixes
    • Improved error handling in UAPI operations with proper resource cleanup on failures.

In netstack (proxy) mode, the process lacks permission to create
/var/run/wireguard, making the UAPI listener unnecessary and causing
a misleading error log. Introduce NewUSPConfigurerNoUAPI and use it
for the netstack device to avoid attempting to open the UAPI socket
entirely. Also consolidate UAPI error logging to a single call site.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 19, 2026

📝 Walkthrough

Walkthrough

The changes remove logrus logging from UAPI error handling in the configurer, introduce a new constructor variant that skips UAPI initialization, and update device creation to use this variant. Resource cleanup is improved with explicit socket closure on failure.

Changes

Cohort / File(s) Summary
UAPI Error Handling
client/iface/configurer/uapi.go
Removed logrus import and log.Errorf calls. Added explicit socket closure on UAPIListen failure before returning error.
Configurer Constructor
client/iface/configurer/usp.go
Added NewUSPConfigurerNoUAPI constructor that initializes WGUSPConfigurer fields without invoking startUAPI, providing an alternative initialization path.
Device Initialization
client/iface/device/device_netstack.go
Updated device configurer initialization from NewUSPConfigurer to NewUSPConfigurerNoUAPI, with unchanged error handling for subsequent ConfigureInterface call.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 No UAPI logs to clutter the way,
A new constructor springs into play,
Sockets now close when errors appear,
Clean initialization, crystal and clear! 🌿

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: skipping UAPI listener in netstack mode, which aligns with the primary objective of the changeset.
Description check ✅ Passed The description provides context for the changes (netstack mode permission issues), explains the solution, and correctly marks it as a refactor with documentation not needed. However, the issue ticket number and link sections are empty.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/netstack-skip-uapi

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@sonarqubecloud
Copy link

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
client/iface/device/device_netstack.go (1)

83-89: Pre-existing: t.device is not closed on ConfigureInterface failure.

After tunIface.Close() is called, t.device (which wraps the now-closed tun) is left running. wireguard-go's internal goroutines will attempt further reads from the closed tun and will log errors or panic. t.device.Close() should be called here, before tunIface.Close() (so the device can drain cleanly), or at minimum immediately after.

♻️ Proposed fix
 	err = t.configurer.ConfigureInterface(t.key, t.port)
 	if err != nil {
+		t.device.Close()
 		if cErr := tunIface.Close(); cErr != nil {
 			log.Debugf("failed to close tun device: %v", cErr)
 		}
 		return nil, fmt.Errorf("error configuring interface: %s", err)
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/iface/device/device_netstack.go` around lines 83 - 89, When
ConfigureInterface fails (error returned from t.configurer.ConfigureInterface),
ensure the wireguard device is cleanly shut down by calling t.device.Close()
before (or at minimum immediately after) closing the underlying tun with
tunIface.Close(); update the error-handling block that currently calls
tunIface.Close() to first call t.device.Close() (handle and log any error from
t.device.Close()), then call tunIface.Close() and return the formatted error
from ConfigureInterface so the device's goroutines can drain and won't continue
reading a closed tun.
client/iface/configurer/usp.go (1)

334-348: Optional: guard Linux socket cleanup behind the UAPI-started condition.

When the NoUAPI constructor is used on Linux, Close() still issues an os.Stat call for the socket path that was never created. The os.Stat guard keeps this safe, but it performs a syscall unnecessarily and slightly obscures intent. Consider gating the block on whether UAPI was ever started.

♻️ Proposed change
 func (t *WGUSPConfigurer) Close() {
 	if t.uapiListener != nil {
 		err := t.uapiListener.Close()
 		if err != nil {
 			log.Errorf("failed to close uapi listener: %v", err)
 		}
+
+		if runtime.GOOS == "linux" {
+			sockPath := "/var/run/wireguard/" + t.deviceName + ".sock"
+			if _, statErr := os.Stat(sockPath); statErr == nil {
+				_ = os.Remove(sockPath)
+			}
+		}
 	}
-
-	if runtime.GOOS == "linux" {
-		sockPath := "/var/run/wireguard/" + t.deviceName + ".sock"
-		if _, statErr := os.Stat(sockPath); statErr == nil {
-			_ = os.Remove(sockPath)
-		}
-	}
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/iface/configurer/usp.go` around lines 334 - 348, The Linux socket
unlink in WGUSPConfigurer.Close currently runs unconditionally; change it to run
only when UAPI was actually started by guarding the socket cleanup on the same
condition that indicates UAPI was created (e.g., check t.uapiListener != nil or
an explicit flag you add), so the os.Stat/remove syscall is skipped when NoUAPI
constructor was used; update the Close method to perform the socket cleanup
(using t.deviceName) only when t.uapiListener (or your uapi-started flag) is
non-nil/true.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@client/iface/configurer/usp.go`:
- Around line 334-348: The Linux socket unlink in WGUSPConfigurer.Close
currently runs unconditionally; change it to run only when UAPI was actually
started by guarding the socket cleanup on the same condition that indicates UAPI
was created (e.g., check t.uapiListener != nil or an explicit flag you add), so
the os.Stat/remove syscall is skipped when NoUAPI constructor was used; update
the Close method to perform the socket cleanup (using t.deviceName) only when
t.uapiListener (or your uapi-started flag) is non-nil/true.

In `@client/iface/device/device_netstack.go`:
- Around line 83-89: When ConfigureInterface fails (error returned from
t.configurer.ConfigureInterface), ensure the wireguard device is cleanly shut
down by calling t.device.Close() before (or at minimum immediately after)
closing the underlying tun with tunIface.Close(); update the error-handling
block that currently calls tunIface.Close() to first call t.device.Close()
(handle and log any error from t.device.Close()), then call tunIface.Close() and
return the formatted error from ConfigureInterface so the device's goroutines
can drain and won't continue reading a closed tun.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants