【问题标题】:what syscall/method could I use to get the default network gateway我可以使用什么系统调用/方法来获取默认网络网关
【发布时间】:2017-04-02 15:21:24
【问题描述】:

使用Go 可以使用什么包、本机函数、系统调用来获取*nix system 上的默认网关

我想避免创建一个围绕netstat、路由、ip 等命令的包装器,或者读取、解析现有文件,我的想法是尽可能多地获取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

我想做一些类似的事情来打印/获取网关地址/接口。

【问题讨论】:

  • net.Interfaces() 是否包含网关? golang.org/pkg/net/#Interfaces
  • @dm03514 我不相信。
  • 出于好奇,你为什么需要这个?
  • @captncraig 在使用 VPN 时了解/打印默认网关路由

标签: networking go system-calls


【解决方案1】:

一种选择是阅读/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。有点绕路,但我在 std lib 或其他地方找不到任何可以为您访问它的包。

【讨论】:

  • 这似乎是在 linux 上,但是对于 unixes(freebsd、mac os 等)我想要一些与操作系统无关的东西。
【解决方案2】:

对于 Linux,您可以使用 captncraig 建议的 procfs。这是一个提取网关地址并将其转换为四点 ipV4 的 sn-p。

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

【讨论】:

  • 这是我想避免的事情,我想知道一些系统调用,以使这更与操作系统无关
  • @nbari:系统调用将不再使其与操作系统无关,系统调用更加依赖于系统。每个操作系统都有自己需要使用的工具。您可能会找到netstat 命令的一些子集,它将在大多数操作系统上打印路由表,否则只需为每个操作系统调用适当的命令。
  • @JimB 我的目标是使用系统调用,尽管我必须维护它们并且交叉编译是为了避免依赖外部命令,这样我就可以生成一个可以运行的二进制文件几乎所有系统都一样。
  • 如果您要自定义每个平台的系统调用,那么无论如何您都将在每个平台上创建一个带有构建标签的文件。如果它使用系统调用或执行某些东西,它们同样不可移植。只需执行您的操作系统上可用的工具即可。
  • 导入会很好;)
【解决方案3】:

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。

【讨论】:

  • 不确定为什么会被接受,因为问题询问网关 IP。如果您查看 interface.go 链接,代码对网关没有任何作用;它只是检查本地接口上的地址并返回一个它满意的地址。
  • 我无法使用 nettest 包检索接口的网关 IP。你能说得更具体些吗?
  • 这里有点迷糊,上面的代码其实是对的,它确实返回了具有可路由配置的接口。这是实际工作的示例代码的链接:play.golang.org/p/iIOQ136z3_B
猜你喜欢
  • 2020-02-18
  • 2014-10-19
  • 1970-01-01
  • 2023-04-07
  • 1970-01-01
  • 1970-01-01
  • 2012-11-18
  • 2012-06-12
  • 2018-06-02
相关资源
最近更新 更多