Home | History | Annotate | Download | only in route
      1 // Copyright 2016 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 // +build darwin dragonfly freebsd netbsd openbsd
      6 
      7 // Package route provides basic functions for the manipulation of
      8 // packet routing facilities on BSD variants.
      9 //
     10 // The package supports any version of Darwin, any version of
     11 // DragonFly BSD, FreeBSD 7 through 11, NetBSD 6 and above, and
     12 // OpenBSD 5.6 and above.
     13 package route
     14 
     15 import (
     16 	"errors"
     17 	"os"
     18 	"syscall"
     19 )
     20 
     21 var (
     22 	errUnsupportedMessage = errors.New("unsupported message")
     23 	errMessageMismatch    = errors.New("message mismatch")
     24 	errMessageTooShort    = errors.New("message too short")
     25 	errInvalidMessage     = errors.New("invalid message")
     26 	errInvalidAddr        = errors.New("invalid address")
     27 	errShortBuffer        = errors.New("short buffer")
     28 )
     29 
     30 // A RouteMessage represents a message conveying an address prefix, a
     31 // nexthop address and an output interface.
     32 //
     33 // Unlike other messages, this message can be used to query adjacency
     34 // information for the given address prefix, to add a new route, and
     35 // to delete or modify the existing route from the routing information
     36 // base inside the kernel by writing and reading route messages on a
     37 // routing socket.
     38 //
     39 // For the manipulation of routing information, the route message must
     40 // contain appropriate fields that include:
     41 //
     42 //	Version       = <must be specified>
     43 //	Type          = <must be specified>
     44 //	Flags         = <must be specified>
     45 //	Index         = <must be specified if necessary>
     46 //	ID            = <must be specified>
     47 //	Seq           = <must be specified>
     48 //	Addrs         = <must be specified>
     49 //
     50 // The Type field specifies a type of manipulation, the Flags field
     51 // specifies a class of target information and the Addrs field
     52 // specifies target information like the following:
     53 //
     54 //	route.RouteMessage{
     55 //		Version: RTM_VERSION,
     56 //		Type: RTM_GET,
     57 //		Flags: RTF_UP | RTF_HOST,
     58 //		ID: uintptr(os.Getpid()),
     59 //		Seq: 1,
     60 //		Addrs: []route.Addrs{
     61 //			RTAX_DST: &route.Inet4Addr{ ... },
     62 //			RTAX_IFP: &route.LinkAddr{ ... },
     63 //			RTAX_BRD: &route.Inet4Addr{ ... },
     64 //		},
     65 //	}
     66 //
     67 // The values for the above fields depend on the implementation of
     68 // each operating system.
     69 //
     70 // The Err field on a response message contains an error value on the
     71 // requested operation. If non-nil, the requested operation is failed.
     72 type RouteMessage struct {
     73 	Version int     // message version
     74 	Type    int     // message type
     75 	Flags   int     // route flags
     76 	Index   int     // interface index when atatched
     77 	ID      uintptr // sender's identifier; usually process ID
     78 	Seq     int     // sequence number
     79 	Err     error   // error on requested operation
     80 	Addrs   []Addr  // addresses
     81 
     82 	extOff int    // offset of header extension
     83 	raw    []byte // raw message
     84 }
     85 
     86 // Marshal returns the binary encoding of m.
     87 func (m *RouteMessage) Marshal() ([]byte, error) {
     88 	return m.marshal()
     89 }
     90 
     91 // A RIBType reprensents a type of routing information base.
     92 type RIBType int
     93 
     94 const (
     95 	RIBTypeRoute     RIBType = syscall.NET_RT_DUMP
     96 	RIBTypeInterface RIBType = syscall.NET_RT_IFLIST
     97 )
     98 
     99 // FetchRIB fetches a routing information base from the operating
    100 // system.
    101 //
    102 // The provided af must be an address family.
    103 //
    104 // The provided arg must be a RIBType-specific argument.
    105 // When RIBType is related to routes, arg might be a set of route
    106 // flags. When RIBType is related to network interfaces, arg might be
    107 // an interface index or a set of interface flags. In most cases, zero
    108 // means a wildcard.
    109 func FetchRIB(af int, typ RIBType, arg int) ([]byte, error) {
    110 	mib := [6]int32{sysCTL_NET, sysAF_ROUTE, 0, int32(af), int32(typ), int32(arg)}
    111 	n := uintptr(0)
    112 	if err := sysctl(mib[:], nil, &n, nil, 0); err != nil {
    113 		return nil, os.NewSyscallError("sysctl", err)
    114 	}
    115 	if n == 0 {
    116 		return nil, nil
    117 	}
    118 	b := make([]byte, n)
    119 	if err := sysctl(mib[:], &b[0], &n, nil, 0); err != nil {
    120 		return nil, os.NewSyscallError("sysctl", err)
    121 	}
    122 	return b[:n], nil
    123 }
    124