Reputation: 27005
Using Go what package, native function, syscall could be used to obtain the default gateway on a *nix system
I would like to avoid creating a wrapper arround netstat, route, ip, etc commands, or read, parse an existing file, the idea is to obtain the values the most os/platform agnostic way posible.
For example this is the output of the route command:
$ route -n get default
route to: default
destination: default
mask: default
gateway: 192.168.1.1
interface: en1
flags: <UP,GATEWAY,DONE,STATIC,PRCLONING>
recvpipe sendpipe ssthresh rtt,msec rttvar hopcount mtu expire
0 0 0 0 0 0 1500 0
I would like to do something simliar in order to just print/obtain the gateeway address/interface.
Upvotes: 6
Views: 6613
Reputation: 1764
There's github.com/jackpal/gateway. It supports multiple platforms and has a very straightforward interface:
package main
import (
"fmt"
"github.com/jackpal/gateway"
)
func main() {
gatewayIP, err := gateway.DiscoverGateway()
if err != nil {
panic(err)
}
fmt.Println("Gateway IP:", gatewayIP)
}
It also has a DiscoverInterface
function which can obtain the IP address of the interface through which the default gateway is reached.
Upvotes: 0
Reputation: 138
Play with the RoutedInterface() code at https://github.com/golang/net/blob/master/internal/nettest/interface.go
Sample code snip:
rifs := nettest.RoutedInterface("ip", net.FlagUp | net.FlagBroadcast)
if rifs != nil {
fmt.Println("Routed interface is ",rifs.HardwareAddr.String())
fmt.Println("Flags are", rifs.Flags.String())
}
Note: You will need to copy the golang code into a local library, since /internal calls are not allowed directly.
Upvotes: -4
Reputation: 3236
For Linux, you can use the procfs as suggested by captncraig. Here is a snippet that extracts the gateway address and convert it to quad dotted ipV4.
/* /proc/net/route file:
Iface Destination Gateway Flags RefCnt Use Metric Mask
eno1 00000000 C900A8C0 0003 0 0 100 00000000 0 00
eno1 0000A8C0 00000000 0001 0 0 100 00FFFFFF 0 00
*/
const (
file = "/proc/net/route"
line = 1 // line containing the gateway addr. (first line: 0)
sep = "\t" // field separator
field = 2 // field containing hex gateway address (first field: 0)
)
func main() {
file, err := os.Open(file)
if err != nil {
log.Fatal(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
// jump to line containing the agteway address
for i := 0; i < line; i++ {
scanner.Scan()
}
// get field containing gateway address
tokens := strings.Split(scanner.Text(), sep)
gatewayHex := "0x" + tokens[field]
// cast hex address to uint32
d, _ := strconv.ParseInt(gatewayHex, 0, 64)
d32 := uint32(d)
// make net.IP address from uint32
ipd32 := make(net.IP, 4)
binary.LittleEndian.PutUint32(ipd32, d32)
fmt.Printf("%T --> %[1]v\n", ipd32)
// format net.IP to dotted ipV4 string
ip := net.IP(ipd32).String()
fmt.Printf("%T --> %[1]v\n", ip)
// exit scanner
break
}
}
Upvotes: 4
Reputation: 23138
One option would be to read /proc/net/route
. On one of my systems this contains:
Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
team0 00000000 010017BA 0003 0 0 0 00000000 0 0 0
team0 0000070A 00000000 0001 0 0 0 00FEFFFF 0 0 0
You could read that in, capture the gateway with some text processing, and convert the hex string to a net.IP. Kinda a runaround, but I could not find any package that can access this for you in the std lib or elsewhere.
Upvotes: 2