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