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
- Variables
- func Close(h handleRaw) error
- func IsElevated() (bool, error)
- func IsHandleClosed(err error) bool
- func Open(filter string, layer uint32, priority int16, flags uint64) (handleRaw, error)
- func Send(h handleRaw, pkt []byte, addr *Address) (uint32, error)
- func SetParam(h handleRaw, param uint32, value uint64) error
- type Address
- type Backend
- type Config
Constants ¶
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).
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.
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 ¶
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 IsElevated ¶
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 ¶
IsHandleClosed reports whether err is the expected graceful signal ("WinDivert handle was closed") that Recv returns after Close().
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 ¶
Recv fetches the next packet into buf. Returns the number of bytes and the address metadata. On error, n is undefined.
func (*Address) IPChecksum ¶
IPChecksum reports whether WinDivert wants us to recompute the IP csum on send.
func (*Address) Outbound ¶
Outbound extracts the Outbound bit (bit 17 overall: 16 for Layer|Event +1).
func (*Address) SetOutbound ¶
SetOutbound sets/clears the Outbound bit (used when re-injecting).
func (*Address) TCPChecksum ¶
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 (*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 ¶
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.