route.mx raw

   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  //go:build darwin || dragonfly || freebsd || netbsd || openbsd
   6  
   7  // Package routebsd supports reading interface addresses on BSD systems.
   8  // This is a very stripped down version of x/net/route,
   9  // for use by the net package in the standard library.
  10  package routebsd
  11  
  12  import (
  13  	"errors"
  14  	"syscall"
  15  )
  16  
  17  var (
  18  	errMessageMismatch = errors.New("message mismatch")
  19  	errMessageTooShort = errors.New("message too short")
  20  	errInvalidMessage  = errors.New("invalid message")
  21  	errInvalidAddr     = errors.New("invalid address")
  22  )
  23  
  24  // fetchRIB fetches a routing information base from the operating
  25  // system.
  26  //
  27  // The arg is an interface index or 0 for all.
  28  func fetchRIB(typ, arg int) ([]byte, error) {
  29  	try := 0
  30  	for {
  31  		try++
  32  		b, err := syscall.RouteRIB(typ, arg)
  33  
  34  		// If the sysctl failed because the data got larger
  35  		// between the two sysctl calls, try a few times
  36  		// before failing (issue #45736).
  37  		const maxTries = 3
  38  		if err == syscall.ENOMEM && try < maxTries {
  39  			continue
  40  		}
  41  
  42  		return b, err
  43  	}
  44  }
  45  
  46  // FetchRIBMessages fetches a list of addressing messages for an interface.
  47  // The typ argument is something like syscall.NET_RT_IFLIST.
  48  // The argument is an interface index or 0 for all.
  49  func FetchRIBMessages(typ, arg int) ([]Message, error) {
  50  	b, err := fetchRIB(typ, arg)
  51  	if err != nil {
  52  		return nil, err
  53  	}
  54  	ms, err := parseRIB(b)
  55  	if err != nil {
  56  		return nil, err
  57  	}
  58  	return ms, nil
  59  }
  60