|  | // 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 | 
|  | } |