// 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. // +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 through 11, 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 atatched 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 reprensents 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) { mib := [6]int32{sysCTL_NET, sysAF_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 { return nil, os.NewSyscallError("sysctl", err) } return b[:n], nil }