nbari
nbari

Reputation: 27005

what syscall/method could I use to get the default network gateway

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

Answers (4)

kbolino
kbolino

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

Cassey
Cassey

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

ripat
ripat

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

captncraig
captncraig

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

Related Questions