tun

package
v0.12.0 Latest Latest
Warning

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

Go to latest
Published: May 3, 2026 License: CC0-1.0 Imports: 7 Imported by: 0

Documentation

Overview

Package tun provides a TUN (network tunnel) interface for handling virtual network devices. It defines the Tun interface, which is compatible with wireguard-go and similar projects, along with utility functions for I/O adaptation, testing, and bidirectional packet copying.

Index

Constants

View Source
const (
	EventUp = 1 << iota
	EventDown
	EventMTUUpdate
)

Variables

View Source
var ErrReadOnClosedChan = errors.Join(
	os.ErrClosed,
	errors.New("tun: read on closed Tun channel"),
)
View Source
var ErrReadOnClosedPipe = errors.Join(
	os.ErrClosed,
	errors.New("tun: read on closed Tun"),
)
View Source
var ErrWriteOnClosedChan = errors.Join(
	os.ErrClosed,
	errors.New("tun: write on closed Tun channel"),
)
View Source
var ErrWriteOnClosedPipe = errors.Join(
	os.ErrClosed,
	errors.New("tun: write on closed Tun"),
)

Functions

func Copy

func Copy(a, b Tun) error

Copy copies packets bidirectionally between two Tun implementations. It uses the batch nature of the Tun interface for optimal performance. Copy blocks until one of the Tuns is closed or encounters an error, then closes both Tuns and returns the first error encountered (if any).

func Pipe

func Pipe(batch int, mtu, mwo, mro int) (Tun, Tun)

Pipe creates two connected Tun implementations that are bound together via Channel instances. Packets written to one Tun can be read from the other, similar to net.Pipe.

Types

type CallbackTUN added in v0.5.0

type CallbackTUN struct {
	Tun
	OnRead  func(n int, err error)
	OnWrite func(n int, err error)
}

CallbackTUN wraps a Tun interface adding callbacks for read and write operations.

func (*CallbackTUN) Read added in v0.5.0

func (t *CallbackTUN) Read(
	bufs [][]byte,
	sizes []int,
	offset int,
) (n int, err error)

func (*CallbackTUN) Write added in v0.5.0

func (t *CallbackTUN) Write(bufs [][]byte, offset int) (n int, err error)

type Channel added in v0.5.0

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

Channel is a batched communication channel for byte slices that partially implements Tun interface. For bi-directional full Tun implementation see Pipe.

func NewChan added in v0.5.0

func NewChan() *Channel

NewChan builds a new Channel.

func (*Channel) Close added in v0.5.0

func (ch *Channel) Close() (err error)

func (*Channel) Read added in v0.5.0

func (p *Channel) Read(
	bufs [][]byte,
	sizes []int,
	offset int,
) (n int, err error)

func (*Channel) Write added in v0.5.0

func (p *Channel) Write(bufs [][]byte, offset int) (written int, err error)

type Event

type Event int

type Forwarder added in v0.5.0

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

Forwarder manages bidirectional forwarding between two TUN devices. It runs two goroutines: one for reading from the read TUN and one for writing to the write TUN. The forwarder can be reconfigured dynamically (e.g., swap TUN devices) without stopping.

For bi-directional forwarding see Point2Point.

func NewForwarder added in v0.5.0

func NewForwarder(pool bufpool.Pool) *Forwarder

NewForwarder creates a new Forwarder with the given buffer pool (can be nil). It starts the reader and writer goroutines. The forwarder initially has no TUN devices and must be configured via SetReadTun and SetWriteTun.

func (*Forwarder) SetReadTun added in v0.5.0

func (f *Forwarder) SetReadTun(tun Tun)

SetReadTun dynamically replaces the TUN device used for reading. The old read TUN (if any) is closed. If the forwarder is stopped, this call does nothing.

func (*Forwarder) SetWriteTun added in v0.5.0

func (f *Forwarder) SetWriteTun(tun Tun)

SetWriteTun dynamically replaces the TUN device used for writing. The old write TUN (if any) is closed. If the forwarder is stopped, this call does nothing.

func (*Forwarder) Stop added in v0.5.0

func (f *Forwarder) Stop()

Stop gracefully shuts down the forwarder. It closes the TUN devices, signals the goroutines to exit, waits for them, and releases all pooled buffers.

type IO

type IO struct {
	Tun
	// contains filtered or unexported fields
}

IO is an io.ReadWriteCloser wrapper for a Tun. It adapts the batch-oriented Tun interface to the single-buffer io.ReadWriteCloser interface, handling one packet at a time.

func NewIO

func NewIO(tun Tun, pool bufpool.Pool) *IO

NewIO creates a new IO wrapper for the given Tun.

func (*IO) Close

func (r *IO) Close() error

Close implements io.Closer. It closes the underlying Device.

func (*IO) Read

func (r *IO) Read(p []byte) (int, error)

Read implements io.Reader. It reads a single packet from the Device.

func (*IO) Write

func (r *IO) Write(p []byte) (int, error)

Write implements io.Writer. It writes a single packet to the Device.

type Point2Point added in v0.5.0

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

Point2Point manages bidirectional forwarding between two TUN devices, conventionally named A and B. It can be reconfigured dynamically (e.g., swap TUN devices) without stopping.

func NewP2P added in v0.5.0

func NewP2P(pool bufpool.Pool) *Point2Point

NewP2P creates a new Point2Point instance using the provided buffer pool. Point2Point start with no TUN devices and must be configured using SetA and SetB.

func (*Point2Point) SetA added in v0.5.0

func (p *Point2Point) SetA(tun Tun)

SetA configures the given TUN device as endpoint A. Endpoint A will be used for reading packets to send to B, and will also receive packets coming from B (i.e., writes from B to A are written to this TUN).

func (*Point2Point) SetB added in v0.5.0

func (p *Point2Point) SetB(tun Tun)

SetB configures the given TUN device as endpoint B. Endpoint B will be used for reading packets to send to A, and will also receive packets coming from A (i.e., writes from A to B are written to this TUN).

func (*Point2Point) Stop added in v0.5.0

func (p *Point2Point) Stop()

Stop gracefully shuts down both internal forwarders, releasing all resources and waiting for goroutines to finish.

type Tun

type Tun interface {
	// File returns the file descriptor of the tun device.
	// It may be nil for virtual/mock/etc implementations.
	File() *os.File

	// Read a batch of packets from Tun.
	// If original source (e.g. linux tun interface) ruturn additional headers,
	// they are stripped under the hood.
	// On a successful read it returns the number of packets read, and sets
	// packet lengths within the sizes slice. len(sizes) must be >= len(bufs).
	// Callers must size bufs from the source Tun's BatchSize(); a single Read
	// may yield multiple logical packets, and some native TUN implementations
	// can require multiple buffers even for one inbound frame.
	// A nonzero offset can be used to instruct the Tun on where to begin
	// reading into each element of the bufs slice.
	Read(bufs [][]byte, sizes []int, offset int) (n int, err error)

	// Write one or more packets to the tun (without any additional headers).
	// On a successful write it returns the number of packets written. A nonzero
	// offset can be used to instruct the Device on where to begin writing from
	// each packet contained within the bufs slice. Callers must chunk writes
	// using the destination Tun's BatchSize() and handle partial writes.
	Write(bufs [][]byte, offset int) (int, error)

	// MWO stands for Minimal Write Offset.
	// It is typically used by native tun implementations to reserver space for
	// OS specific headers.
	MWO() int

	// MRO stands for Minimal Read Offset.
	// It isn't used anywhere at the moment but added for future use.
	MRO() int

	// MTU returns the MTU of the Device.
	MTU() (int, error)

	// Name returns the current name of the Device.
	Name() (string, error)

	// Events returns a channel of type Event, which is fed Device events.
	Events() <-chan Event

	// Close stops the Device and closes the Event channel.
	Close() error

	// BatchSize returns the preferred/max number of packets that this Tun can
	// read or write in a single read/write call. BatchSize must not change over
	// the lifetime of a Device. Callers must not assume symmetric batch
	// compatibility across two different Tun implementations: reads should be
	// sized from the source Tun, and writes should be chunked for the
	// destination Tun.
	BatchSize() int
}

Tun interface is borrowed from wireguard-go. There is multiple projects that use same or similar interfaces so it is a good choice for a de-facto standard role.

Jump to

Keyboard shortcuts

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