syscall/method 我可以使用什么来获取默认网络网关

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

使用Go what package, native function, syscall could be used to obtain the default gateway on a *nix system

我想避免在 netstat, route, ip, etc commands, or read, parse an existing file, the idea is to obtain the values the most os/platform agnostic 附近创建包装器。

例如,这是 route 命令的输出:

$ 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

我想做一些类似的事情,以便 print/obtain 网关 address/interface。

一种选择是阅读 /proc/net/route。在我的一个系统上,它包含:

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                                                                              

您可以读取它,通过一些文本处理捕获网关,并将十六进制字符串转换为 net.IP。有点绕口令,但我在标准库或其他地方找不到任何可以为您访问它的包。

对于 Linux,您可以按照 captncraig 的建议使用 procfs。这是提取网关地址并将其转换为四点分 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
    }
}

使用 https://github.com/golang/net/blob/master/internal/nettest/interface.go

处的 RoutedInterface() 代码

示例代码片段:

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())
}

注意:您需要将 golang 代码复制到本地库中,因为 /internal 不允许直接调用。