windows

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Apr 18, 2026 License: GPL-3.0 Imports: 0 Imported by: 0

Documentation

Overview

Package windows implements the snix Backend on Windows via WinDivert.

We talk to WinDivert.dll directly via windows.LazyDLL so no cgo is required — the snix binary stays a single .exe. The signed WinDivert.sys driver and DLL must be present at runtime; they are loaded by first use of the backend and unloaded on Close.

API version: WinDivert 2.x (filter language v2, 80-byte WINDIVERT_ADDRESS).

Index

Constants

View Source
const (
	LayerNetwork        = 0
	LayerNetworkForward = 1
	LayerFlow           = 2
	LayerSocket         = 3
	LayerReflect        = 4
)

Layer selects what kind of events WinDivert intercepts. We always use Network (raw IP packets pre/post-routing).

View Source
const (
	FlagDefault = 0
	FlagSniff   = 0x0001 // Observe only; packets not dropped from stack.
	FlagDrop    = 0x0002 // Silently drop after capture; don't forward.
)

Flags passed to WinDivertOpen. Default 0 = captures + drops, we re-inject.

View Source
const (
	ParamQueueLength = 0 // max packets waiting userspace, default 4096
	ParamQueueTime   = 1 // ms packets may wait, default 2000
	ParamQueueSize   = 2 // bytes of kernel queue, default 4M
)

WinDivertParam values used with SetParam.

Variables

View Source
var ErrNotElevated = errors.New("snix/windows: process is not running elevated (Administrator)")

ErrNotElevated is returned by IsElevated when the current process token does not have the Administrators group enabled. The caller should surface a clear message telling the user to run elevated.

Functions

func Close

func Close(h handleRaw) error

Close unloads the WinDivert handle.

func IsElevated

func IsElevated() (bool, error)

IsElevated reports whether the current process has the Administrators group in its effective token — i.e. WinDivertOpen will succeed (modulo driver state).

We check via CheckTokenMembership against the well-known SECURITY_BUILTIN_DOMAIN_RID \ DOMAIN_ALIAS_RID_ADMINS SID. This is the standard Win32 pattern and works for both Run-as-admin sessions and services running under LocalSystem.

func IsHandleClosed

func IsHandleClosed(err error) bool

IsHandleClosed reports whether err is the expected graceful signal ("WinDivert handle was closed") that Recv returns after Close().

func Open

func Open(filter string, layer uint32, priority int16, flags uint64) (handleRaw, error)

Open invokes WinDivertOpen. Returns a handle or an error.

func Send

func Send(h handleRaw, pkt []byte, addr *Address) (uint32, error)

Send writes packet pkt back to the stack using addr as the re-injection metadata. Returns bytes written.

func SetParam

func SetParam(h handleRaw, param uint32, value uint64) error

SetParam tunes a kernel parameter on an open handle.

Types

type Address

type Address struct {
	Timestamp int64
	// Packed flags byte for fields Layer(8), Event(8), Flags(8) bits:
	//   [0] Sniffed,[1] Outbound,[2] Loopback,[3] Impostor,
	//   [4] IPv6,[5] IPChecksum,[6] TCPChecksum,[7] UDPChecksum
	// Followed by Reserved1(8).
	LayerEvent uint32 // [0:8]=Layer, [8:16]=Event, [16:24]=flags, [24:32]=Reserved1
	Reserved2  uint32
	Data       [64]byte // union of per-layer data; for network: iface indexes etc.
}

Address is the Go mirror of WINDIVERT_ADDRESS (80 bytes). Layout must match exactly; we verify via a compile-time assertion below.

func Recv

func Recv(h handleRaw, buf []byte) (n uint32, addr Address, err error)

Recv fetches the next packet into buf. Returns the number of bytes and the address metadata. On error, n is undefined.

func (*Address) IPChecksum

func (a *Address) IPChecksum() bool

IPChecksum reports whether WinDivert wants us to recompute the IP csum on send.

func (*Address) Outbound

func (a *Address) Outbound() bool

Outbound extracts the Outbound bit (bit 17 overall: 16 for Layer|Event +1).

func (*Address) SetOutbound

func (a *Address) SetOutbound(v bool)

SetOutbound sets/clears the Outbound bit (used when re-injecting).

func (*Address) TCPChecksum

func (a *Address) TCPChecksum() bool

TCPChecksum reports whether WinDivert wants us to recompute the TCP csum on send.

type Backend

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

Backend implements snix/platform.Backend via WinDivert on Windows.

func New

func New(cfg Config) *Backend

New constructs an unopened Backend.

func (*Backend) Close

func (b *Backend) Close() error

Close tears down the WinDivert handle and stops the recv loop.

func (*Backend) Inject

func (b *Backend) Inject(pkt []byte, dir snixplatform.Direction) error

Inject emits a raw IPv4 packet back onto the stack. The direction is encoded on the address; if the engine hasn't seen any outbound packet yet (very early in a flow), we build a plausible outbound address from zero.

func (*Backend) Open

func (b *Backend) Open(ctx context.Context, scope snixplatform.Scope) error

Open installs a WinDivert filter matching scope and starts the recv loop. Requires Administrator and the WinDivert driver installed.

func (*Backend) Packets

func (b *Backend) Packets() <-chan snixplatform.Packet

Packets is the observed-packet stream.

type Config

type Config struct {
	// Priority is the WinDivert filter priority. Lower wins; leave 0 for default.
	Priority int16
	// ReadBufferSize is the per-Recv buffer length. 65535 covers every frame.
	ReadBufferSize int
	// QueueLength is the kernel-side packet queue cap (WINDIVERT_PARAM_QUEUE_LENGTH).
	// 0 means keep WinDivert's default (4096).
	QueueLength uint64
}

Config tunes the Windows backend.

Jump to

Keyboard shortcuts

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