procnetroute

package
v0.0.9 Latest Latest
Warning

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

Go to latest
Published: Mar 30, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Overview

Package procnetroute reads the Linux IPv4 routing table from /proc/net/route.

This package is in builtins/internal/ and is therefore exempt from the builtinAllowedSymbols allowlist check. It may use OS-specific APIs freely.

Sandbox bypass

ReadRoutes intentionally bypasses the AllowedPaths sandbox (callCtx.OpenFile) and calls os.Open directly. This is safe because procPath is always a kernel-managed pseudo-filesystem root (/proc by default) that is hardcoded by the caller — it is never derived from user-supplied input and cannot be redirected by a shell script. The caller is responsible for ensuring that procPath remains a safe, non-user-controlled path.

/proc/net/route format (tab-separated, one route per line after the header):

Iface  Destination  Gateway  Flags  RefCnt  Use  Metric  Mask  MTU  Window  IRTT
eth0   00000000     0101A8C0 0003   0       0    100     00000000 0  0       0

All IP fields are little-endian uint32 hex: 192.168.1.1 is encoded as 0x0101A8C0 (first octet in the least-significant byte).

Index

Constants

View Source
const (
	FlagUp      = uint32(0x0001) // RTF_UP
	FlagGateway = uint32(0x0002) // RTF_GATEWAY
	FlagReject  = uint32(0x0200) // RTF_REJECT — kernel will refuse to route to this destination
)

Routing-table flags (from linux/route.h).

View Source
const DefaultProcPath = procpath.Default

DefaultProcPath is the default proc filesystem root. ReadRoutes appends "net/route" to this path to locate the routing table.

View Source
const MaxLineBytes = 1 << 20 // 1 MiB

MaxLineBytes is the per-line buffer cap for the route-table scanner. If any line in the route file exceeds this limit the scanner returns bufio.ErrTooLong and ReadRoutes returns an error; processing is aborted rather than allowing unbounded allocation.

View Source
const MaxRoutes = 10_000

MaxRoutes caps the number of UP route entries retained in memory to prevent memory exhaustion.

View Source
const MaxTotalLines = MaxRoutes * 10 // 100 000 lines

MaxTotalLines caps the total number of lines (UP + non-UP + malformed) scanned per ReadRoutes call. This bounds CPU time for pathological /proc/net/route files with many non-UP/malformed lines before MaxRoutes UP entries are found. MaxRoutes is the memory guard; MaxTotalLines is the scan-time guard.

Variables

View Source
var ErrMaxRoutes = errors.New("procnetroute: route table truncated: exceeded MaxRoutes limit")

ErrMaxRoutes is returned by readRoutes when the route table exceeds MaxRoutes UP entries. Callers should treat this as a hard failure: the route table was truncated and any LPM result derived from partial data may be incorrect.

View Source
var ErrMaxTotalLines = errors.New("procnetroute: route table truncated: exceeded MaxTotalLines limit")

ErrMaxTotalLines is returned by readRoutes when more than MaxTotalLines lines are scanned. Callers should treat this as a hard failure: the route table was truncated and any LPM result derived from partial data may be incorrect.

Functions

func HexToIPStr

func HexToIPStr(val uint32) string

HexToIPStr converts a /proc/net/route little-endian uint32 to dotted-decimal. The encoding stores the first octet in the least-significant byte: 192.168.1.1 is encoded as 0x0101A8C0, and HexToIPStr(0x0101A8C0) = "192.168.1.1".

func IsContiguousMask

func IsContiguousMask(v uint32) bool

IsContiguousMask reports whether v is a valid CIDR subnet mask in the little-endian encoding used by /proc/net/route, where the first octet is stored in the least-significant byte. For example:

  • /24 (255.255.255.0) is stored as 0x00FFFFFF
  • /25 (255.255.255.128) is stored as 0x80FFFFFF
  • /28 (255.255.255.240) is stored as 0xF0FFFFFF

Non-contiguous masks (e.g. 0xF0F0F0F0) are not valid CIDR prefixes and would produce misleading output from LongestPrefixMatch and formatRoute.

func Popcount

func Popcount(v uint32) int

Popcount returns the number of set bits in v (used for prefix length).

Types

type Route

type Route struct {
	Iface  string
	Dest   uint32
	GW     uint32
	Flags  uint32
	Metric uint32
	Mask   uint32
}

Route holds a parsed entry from /proc/net/route. IP fields use the same little-endian uint32 encoding as /proc/net/route: for 192.168.1.1 the stored value is 0x0101A8C0 and HexToIPStr(0x0101A8C0) returns "192.168.1.1".

func LongestPrefixMatch

func LongestPrefixMatch(routes []Route, addr uint32) *Route

LongestPrefixMatch returns the route that best matches addr by longest-prefix-match with metric as a tie-breaker (lower metric wins), or nil if no route matches.

func ReadRoutes

func ReadRoutes(ctx context.Context, procPath string) ([]Route, error)

ReadRoutes opens procPath/net/route and returns all UP route entries. procPath is the proc filesystem root (e.g. DefaultProcPath or a test override). It is implemented on Linux and returns an error on other platforms.

Sandbox bypass: this function calls os.Open directly, bypassing the AllowedPaths sandbox enforced by callCtx.OpenFile. This is intentional — procPath must always be a safe, hardcoded kernel pseudo-filesystem path (e.g. /proc) that is not controllable from user scripts. Never pass a path derived from user input.

Safety invariants:

(a) /proc-prefix requirement: all callers MUST pass a path that starts with
    /proc. No runtime assertion enforces this — tests override procPath with
    a temp-directory tree to inject synthetic route data, so a /proc-prefix
    check would break those tests. This invariant is caller-enforced only.

(b) No ".." components: enforced at runtime by the strings.Contains check
    below. The check is applied to the ORIGINAL path (before filepath.Clean)
    so traversal sequences like "/proc/../etc/passwd" are caught — after
    Clean, such a path becomes "/etc/passwd" and no longer contains "..".
    Temp-directory overrides used by tests never contain "..".
    Note: the check is deliberately conservative: any path whose component
    names happen to contain ".." as a substring (e.g. "/proc..backup") is
    also rejected. This is a theoretical false-positive that never occurs in
    practice since procPath is always "/proc" or a t.TempDir() path.

Jump to

Keyboard shortcuts

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