你可以使用什么系统调用/方法来获取默认的网络网关。

huangapple go评论116阅读模式
英文:

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

问题

使用Go语言,可以使用哪个包、本地函数或系统调用来获取*nix系统上的默认网关?

我想避免创建一个包装器来调用netstat、route、ip等命令,或者读取、解析现有文件,我的想法是以最兼容不同操作系统/平台的方式获取这些值。

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

  1. $ route -n get default
  2. route to: default
  3. destination: default
  4. mask: default
  5. gateway: 192.168.1.1
  6. interface: en1
  7. flags: <UP,GATEWAY,DONE,STATIC,PRCLONING>
  8. recvpipe sendpipe ssthresh rtt,msec rttvar hopcount mtu expire
  9. 0 0 0 0 0 0 1500 0

我想做类似的事情,只是打印/获取网关地址和接口。

英文:

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:

  1. $ route -n get default
  2. route to: default
  3. destination: default
  4. mask: default
  5. gateway: 192.168.1.1
  6. interface: en1
  7. flags: &lt;UP,GATEWAY,DONE,STATIC,PRCLONING&gt;
  8. recvpipe sendpipe ssthresh rtt,msec rttvar hopcount mtu expire
  9. 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.

答案1

得分: 4

对于Linux系统,你可以使用procfs,如captncraig所建议的。以下是一个代码片段,提取网关地址并将其转换为点分十进制的IPv4地址。

  1. /* /proc/net/route文件内容:
  2. Iface Destination Gateway Flags RefCnt Use Metric Mask
  3. eno1 00000000 C900A8C0 0003 0 0 100 00000000 0 00 eno1 0000A8C0 00000000 0001 0 0 100 00FFFFFF 0 00
  4. */
  5. const (
  6. file = "/proc/net/route"
  7. line = 1 // 包含网关地址的行号(第一行为0)
  8. sep = "\t" // 字段分隔符
  9. field = 2 // 包含十六进制网关地址的字段号(第一个字段为0)
  10. )
  11. func main() {
  12. file, err := os.Open(file)
  13. if err != nil {
  14. log.Fatal(err)
  15. }
  16. defer file.Close()
  17. scanner := bufio.NewScanner(file)
  18. for scanner.Scan() {
  19. // 跳转到包含网关地址的行
  20. for i := 0; i < line; i++ {
  21. scanner.Scan()
  22. }
  23. // 获取包含网关地址的字段
  24. tokens := strings.Split(scanner.Text(), sep)
  25. gatewayHex := "0x" + tokens[field]
  26. // 将十六进制地址转换为uint32
  27. d, _ := strconv.ParseInt(gatewayHex, 0, 64)
  28. d32 := uint32(d)
  29. // 从uint32创建net.IP地址
  30. ipd32 := make(net.IP, 4)
  31. binary.LittleEndian.PutUint32(ipd32, d32)
  32. fmt.Printf("%T --> %[1]v\n", ipd32)
  33. // 将net.IP格式化为点分十进制的IPv4字符串
  34. ip := net.IP(ipd32).String()
  35. fmt.Printf("%T --> %[1]v\n", ip)
  36. // 退出扫描器
  37. break
  38. }
  39. }
英文:

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.

  1. /* /proc/net/route file:
  2. Iface Destination Gateway Flags RefCnt Use Metric Mask
  3. eno1 00000000 C900A8C0 0003 0 0 100 00000000 0 00
  4. eno1 0000A8C0 00000000 0001 0 0 100 00FFFFFF 0 00
  5. */
  6. const (
  7. file = &quot;/proc/net/route&quot;
  8. line = 1 // line containing the gateway addr. (first line: 0)
  9. sep = &quot;\t&quot; // field separator
  10. field = 2 // field containing hex gateway address (first field: 0)
  11. )
  12. func main() {
  13. file, err := os.Open(file)
  14. if err != nil {
  15. log.Fatal(err)
  16. }
  17. defer file.Close()
  18. scanner := bufio.NewScanner(file)
  19. for scanner.Scan() {
  20. // jump to line containing the agteway address
  21. for i := 0; i &lt; line; i++ {
  22. scanner.Scan()
  23. }
  24. // get field containing gateway address
  25. tokens := strings.Split(scanner.Text(), sep)
  26. gatewayHex := &quot;0x&quot; + tokens[field]
  27. // cast hex address to uint32
  28. d, _ := strconv.ParseInt(gatewayHex, 0, 64)
  29. d32 := uint32(d)
  30. // make net.IP address from uint32
  31. ipd32 := make(net.IP, 4)
  32. binary.LittleEndian.PutUint32(ipd32, d32)
  33. fmt.Printf(&quot;%T --&gt; %[1]v\n&quot;, ipd32)
  34. // format net.IP to dotted ipV4 string
  35. ip := net.IP(ipd32).String()
  36. fmt.Printf(&quot;%T --&gt; %[1]v\n&quot;, ip)
  37. // exit scanner
  38. break
  39. }
  40. }

答案2

得分: 2

一种选择是读取/proc/net/route文件。在我的某个系统上,该文件包含以下内容:

  1. 接口 目标 网关 标志 引用计数 使用 度量 掩码 MTU 窗口 IRTT
  2. team0 00000000 010017BA 0003 0 0 0 00000000 0 0 0
  3. team0 0000070A 00000000 0001 0 0 0 00FEFFFF 0 0 0

你可以读取该文件,使用一些文本处理技术捕获网关,并将十六进制字符串转换为net.IP类型。这有点绕弯,但我找不到任何可以在标准库或其他地方为您访问此内容的包。

英文:

One option would be to read /proc/net/route. On one of my systems this contains:

  1. Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
  2. team0 00000000 010017BA 0003 0 0 0 00000000 0 0 0
  3. 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.

答案3

得分: 0

这里有一个名为 github.com/jackpal/gateway 的库。它支持多个平台,并且具有非常直观的接口:

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/jackpal/gateway"
  5. )
  6. func main() {
  7. gatewayIP, err := gateway.DiscoverGateway()
  8. if err != nil {
  9. panic(err)
  10. }
  11. fmt.Println("网关 IP:", gatewayIP)
  12. }

它还有一个 DiscoverInterface 函数,可以获取通过默认网关访问的接口的 IP 地址。

英文:

There's github.com/jackpal/gateway. It supports multiple platforms and has a very straightforward interface:

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. &quot;github.com/jackpal/gateway&quot;
  5. )
  6. func main() {
  7. gatewayIP, err := gateway.DiscoverGateway()
  8. if err != nil {
  9. panic(err)
  10. }
  11. fmt.Println(&quot;Gateway IP:&quot;, gatewayIP)
  12. }

It also has a DiscoverInterface function which can obtain the IP address of the interface through which the default gateway is reached.

答案4

得分: -4

在https://github.com/golang/net/blob/master/internal/nettest/interface.go上玩RoutedInterface()代码。

示例代码片段:

  1. rifs := nettest.RoutedInterface("ip", net.FlagUp | net.FlagBroadcast)
  2. if rifs != nil {
  3. fmt.Println("Routed interface is ",rifs.HardwareAddr.String())
  4. fmt.Println("Flags are", rifs.Flags.String())
  5. }

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

英文:

Play with the RoutedInterface() code at https://github.com/golang/net/blob/master/internal/nettest/interface.go

Sample code snip:

  1. rifs := nettest.RoutedInterface(&quot;ip&quot;, net.FlagUp | net.FlagBroadcast)
  2. if rifs != nil {
  3. fmt.Println(&quot;Routed interface is &quot;,rifs.HardwareAddr.String())
  4. fmt.Println(&quot;Flags are&quot;, rifs.Flags.String())
  5. }

Note: You will need to copy the golang code into a local library, since /internal calls are not allowed directly.

huangapple
  • 本文由 发表于 2016年11月19日 01:23:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/40682760.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定