summaryrefslogtreecommitdiffstats
path: root/src/vendor/golang.org/x/net/route/route.go
blob: 3ab5bcdc011996e6d96f31157e81a3260dea966a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build darwin || dragonfly || freebsd || netbsd || openbsd
// +build darwin dragonfly freebsd netbsd openbsd

// Package route provides basic functions for the manipulation of
// packet routing facilities on BSD variants.
//
// The package supports any version of Darwin, any version of
// DragonFly BSD, FreeBSD 7 and above, NetBSD 6 and above, and OpenBSD
// 5.6 and above.
package route

import (
	"errors"
	"os"
	"syscall"
)

var (
	errUnsupportedMessage = errors.New("unsupported message")
	errMessageMismatch    = errors.New("message mismatch")
	errMessageTooShort    = errors.New("message too short")
	errInvalidMessage     = errors.New("invalid message")
	errInvalidAddr        = errors.New("invalid address")
	errShortBuffer        = errors.New("short buffer")
)

// A RouteMessage represents a message conveying an address prefix, a
// nexthop address and an output interface.
//
// Unlike other messages, this message can be used to query adjacency
// information for the given address prefix, to add a new route, and
// to delete or modify the existing route from the routing information
// base inside the kernel by writing and reading route messages on a
// routing socket.
//
// For the manipulation of routing information, the route message must
// contain appropriate fields that include:
//
//	Version       = <must be specified>
//	Type          = <must be specified>
//	Flags         = <must be specified>
//	Index         = <must be specified if necessary>
//	ID            = <must be specified>
//	Seq           = <must be specified>
//	Addrs         = <must be specified>
//
// The Type field specifies a type of manipulation, the Flags field
// specifies a class of target information and the Addrs field
// specifies target information like the following:
//
//	route.RouteMessage{
//		Version: RTM_VERSION,
//		Type: RTM_GET,
//		Flags: RTF_UP | RTF_HOST,
//		ID: uintptr(os.Getpid()),
//		Seq: 1,
//		Addrs: []route.Addrs{
//			RTAX_DST: &route.Inet4Addr{ ... },
//			RTAX_IFP: &route.LinkAddr{ ... },
//			RTAX_BRD: &route.Inet4Addr{ ... },
//		},
//	}
//
// The values for the above fields depend on the implementation of
// each operating system.
//
// The Err field on a response message contains an error value on the
// requested operation. If non-nil, the requested operation is failed.
type RouteMessage struct {
	Version int     // message version
	Type    int     // message type
	Flags   int     // route flags
	Index   int     // interface index when attached
	ID      uintptr // sender's identifier; usually process ID
	Seq     int     // sequence number
	Err     error   // error on requested operation
	Addrs   []Addr  // addresses

	extOff int    // offset of header extension
	raw    []byte // raw message
}

// Marshal returns the binary encoding of m.
func (m *RouteMessage) Marshal() ([]byte, error) {
	return m.marshal()
}

// A RIBType represents a type of routing information base.
type RIBType int

const (
	RIBTypeRoute     RIBType = syscall.NET_RT_DUMP
	RIBTypeInterface RIBType = syscall.NET_RT_IFLIST
)

// FetchRIB fetches a routing information base from the operating
// system.
//
// The provided af must be an address family.
//
// The provided arg must be a RIBType-specific argument.
// When RIBType is related to routes, arg might be a set of route
// flags. When RIBType is related to network interfaces, arg might be
// an interface index or a set of interface flags. In most cases, zero
// means a wildcard.
func FetchRIB(af int, typ RIBType, arg int) ([]byte, error) {
	try := 0
	for {
		try++
		mib := [6]int32{syscall.CTL_NET, syscall.AF_ROUTE, 0, int32(af), int32(typ), int32(arg)}
		n := uintptr(0)
		if err := sysctl(mib[:], nil, &n, nil, 0); err != nil {
			return nil, os.NewSyscallError("sysctl", err)
		}
		if n == 0 {
			return nil, nil
		}
		b := make([]byte, n)
		if err := sysctl(mib[:], &b[0], &n, nil, 0); err != nil {
			// If the sysctl failed because the data got larger
			// between the two sysctl calls, try a few times
			// before failing. (golang.org/issue/45736).
			const maxTries = 3
			if err == syscall.ENOMEM && try < maxTries {
				continue
			}
			return nil, os.NewSyscallError("sysctl", err)
		}
		return b[:n], nil
	}
}