| // 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 |
| |
| // Package routebsd supports reading interface addresses on BSD systems. |
| // This is a very stripped down version of x/net/route, |
| // for use by the net package in the standard library. |
| package routebsd |
| |
| import ( |
| "errors" |
| "syscall" |
| ) |
| |
| var ( |
| errMessageMismatch = errors.New("message mismatch") |
| errMessageTooShort = errors.New("message too short") |
| errInvalidMessage = errors.New("invalid message") |
| errInvalidAddr = errors.New("invalid address") |
| ) |
| |
| // fetchRIB fetches a routing information base from the operating |
| // system. |
| // |
| // The arg is an interface index or 0 for all. |
| func fetchRIB(typ, arg int) ([]byte, error) { |
| try := 0 |
| for { |
| try++ |
| b, err := syscall.RouteRIB(typ, arg) |
| |
| // If the sysctl failed because the data got larger |
| // between the two sysctl calls, try a few times |
| // before failing (issue #45736). |
| const maxTries = 3 |
| if err == syscall.ENOMEM && try < maxTries { |
| continue |
| } |
| |
| return b, err |
| } |
| } |
| |
| // FetchRIBMessages fetches a list of addressing messages for an interface. |
| // The typ argument is something like syscall.NET_RT_IFLIST. |
| // The argument is an interface index or 0 for all. |
| func FetchRIBMessages(typ, arg int) ([]Message, error) { |
| b, err := fetchRIB(typ, arg) |
| if err != nil { |
| return nil, err |
| } |
| ms, err := parseRIB(b) |
| if err != nil { |
| return nil, err |
| } |
| return ms, nil |
| } |