networking

package
v0.22.168 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 25, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package networking — WSL2 detection + .wslconfig auto-configuration for LAN peer discovery.

The WSL2 NAT layer between the Windows host and the Linux guest drops cross-host UDP multicast on 224.0.0.251:5353, so two clawtool daemons on the same LAN (one in WSL2, one on another device) cannot find each other via mDNS — even though both are dutifully announcing. Microsoft's supported fix is mirrored networking mode: setting `networkingMode=mirrored` under [wsl2] in `%USERPROFILE%\.wslconfig` makes WSL2 share the host's network interfaces directly. No NAT, no multicast bridge, no portproxy / netsh recipes. Requires Windows 11 22H2 (build 22621) or later AND WSL >= 2.0.0; older Windows versions surface a clear "unsupported" result with fallback recommendations.

This package is platform-neutral. `Detect()` returns InWSL2=false on macOS / native Linux / Windows-without-WSL, so every caller (the doctor section, the serve auto-hook, the `clawtool networking` subcommands) can call it unconditionally without runtime guards.

Index

Constants

View Source
const MinMirroredBuild = 22621

MinMirroredBuild is the Windows build number at which `networkingMode=mirrored` first becomes available. Build 22621 = Windows 11 22H2 (the 2022 H2 feature update). Anything below surfaces as an unsupported result with the Windows-host / Tailscale fallback recommendations.

Variables

This section is empty.

Functions

func WriteWSLConfig

func WriteWSLConfig(path string, cfg *WSLConfig) error

WriteWSLConfig serialises cfg to path via atomic temp+rename. Preserves line endings (CRLF on existing Windows-edited files; CRLF when we're creating the file from scratch — the file lives on the Windows filesystem and tools there expect CRLF).

Types

type Action

type Action string

Action enumerates the outcome of EnsureMirrored.

const (
	// ActionNoOp — not running in WSL2; nothing to do.
	ActionNoOp Action = "no-op"

	// ActionAlreadyConfigured — .wslconfig already has
	// networkingMode=mirrored. Idempotent re-runs land here.
	ActionAlreadyConfigured Action = "already-configured"

	// ActionUnsupported — Windows 10 or pre-22H2 Windows 11.
	// Mirrored mode is unavailable; the caller should surface
	// the fallback recommendations (Windows host install /
	// Tailscale).
	ActionUnsupported Action = "unsupported"

	// ActionWouldEdit — DryRun result; the file would have been
	// modified with the diff returned in Result.Diff.
	ActionWouldEdit Action = "would-edit"

	// ActionConfigured — the file was written. The caller MUST
	// surface Result.NextStep (the wsl --shutdown command) so
	// the operator restarts WSL2 into the new mode.
	ActionConfigured Action = "configured"
)

type EnsureOptions

type EnsureOptions struct {
	// DryRun: compute the planned change but don't write the
	// file. The resulting Result includes a Diff field so the
	// caller can preview what would change.
	DryRun bool
}

EnsureOptions controls EnsureMirrored.

type Result

type Result struct {
	// Action is the outcome enum.
	Action Action

	// Reason is a short human-readable explanation. Required
	// for every action; the caller uses it for the operator-
	// facing line.
	Reason string

	// Diff is the unified diff of the .wslconfig change for
	// DryRun + Configured outcomes. Empty for NoOp /
	// AlreadyConfigured / Unsupported.
	Diff string

	// NextStep is the operator-facing follow-up — for the
	// Configured outcome, this is the `wsl --shutdown && wsl`
	// command. Empty otherwise.
	NextStep string

	// ConfigPath is the resolved .wslconfig path the action
	// targeted (or would have targeted). Empty when InWSL2 was
	// false.
	ConfigPath string
}

Result reports what EnsureMirrored did + what the operator should do next.

func EnsureMirrored

func EnsureMirrored(state *WSL2State, opts EnsureOptions) (Result, error)

EnsureMirrored applies the auto-config recipe per the algorithm:

  1. If !state.InWSL2 → ActionNoOp.
  2. If NetworkingMode already "mirrored" → ActionAlreadyConfigured.
  3. If !MirroredSupported → ActionUnsupported with fallback text.
  4. If DryRun → ActionWouldEdit + diff.
  5. Otherwise: read .wslconfig (create if missing), set [wsl2].networkingMode=mirrored, atomic-write, return ActionConfigured with the wsl --shutdown next step.

type WSL2State

type WSL2State struct {
	// InWSL2 is true when /proc/version contains "WSL2" — the
	// canonical kernel-side marker for the WSL2 distro. Native
	// Linux + WSL1 + macOS + Windows-without-WSL all surface
	// false; the rest of the struct is then meaningless and the
	// caller should treat the WSL2 fix as a no-op.
	InWSL2 bool

	// WindowsBuild is the major build number from
	// `cmd.exe /c ver` (e.g. 19045 for Windows 10 22H2 or 22631
	// for Windows 11 23H2). Zero when the probe failed.
	WindowsBuild int

	// WSLVersion is the version string from `wsl.exe --version`
	// (e.g. "2.7.3"). Empty when wsl.exe isn't reachable from
	// inside the distro (very old WSL where --version is
	// missing).
	WSLVersion string

	// WindowsUser is the host-side $env:USERNAME read via
	// powershell.exe. Used to resolve the .wslconfig path
	// (`/mnt/c/Users/<user>/.wslconfig`). Empty when the probe
	// failed; in that case WSLConfigPath is also empty and
	// EnsureMirrored surfaces a clear error.
	WindowsUser string

	// WSLConfigPath is the resolved POSIX path the Linux guest
	// uses to read / write the Windows-side .wslconfig. Empty
	// when WindowsUser wasn't resolvable.
	WSLConfigPath string

	// NetworkingMode is the current value of [wsl2].networkingMode
	// in .wslconfig. Empty string means "key not present" — WSL2
	// then uses the default NAT mode. Known values: "nat",
	// "mirrored", "bridged", "none". We don't validate the value
	// strictly; an unknown mode is preserved verbatim through
	// reads + writes.
	NetworkingMode string

	// MirroredSupported is true when WindowsBuild >=
	// MinMirroredBuild. WSL version isn't a hard gate — any WSL
	// 2.x shipping with Windows 11 22H2 supports mirrored mode;
	// the version field is informational.
	MirroredSupported bool
}

WSL2State is the snapshot the auto-config path keys off. Every field is read-only — callers that want to flip the networking mode call EnsureMirrored, which re-reads + writes the .wslconfig rather than mutating this struct.

func Detect

func Detect() (*WSL2State, error)

Detect probes the host for WSL2 state. Returns a snapshot with InWSL2=false on every non-WSL2 host. Safe to call unconditionally.

type WSLConfig

type WSLConfig struct {
	// contains filtered or unexported fields
}

WSLConfig is an in-memory representation of a Windows `%USERPROFILE%\.wslconfig` file. The file is INI-ish, not strict TOML: `[section]` headers and `key=value` lines, comments with `#` or `;`. We preserve unrelated sections + key order on write so a user who set `[experimental] sparseVhd=true` doesn't see it silently rewritten or lost.

func ReadWSLConfig

func ReadWSLConfig(path string) (*WSLConfig, error)

ReadWSLConfig parses a .wslconfig from disk. Returns an empty (but non-nil) config when the file doesn't exist — the caller can SetNetworkingMode + WriteWSLConfig to create it from scratch.

func (*WSLConfig) Bytes

func (c *WSLConfig) Bytes() []byte

Bytes renders the config back to the on-disk format. Section + key order from the original file is preserved; new keys append to their section in insertion order.

func (*WSLConfig) NetworkingMode

func (c *WSLConfig) NetworkingMode() string

NetworkingMode returns the current value of [wsl2].networkingMode. Empty string when the key isn't set (WSL2 then runs in default NAT mode).

func (*WSLConfig) SetNetworkingMode

func (c *WSLConfig) SetNetworkingMode(mode string)

SetNetworkingMode writes the value under [wsl2]. Creates the section if missing. Empty value removes the key.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL