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

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

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

问题

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

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

例如,这是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

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

英文:

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: &lt;UP,GATEWAY,DONE,STATIC,PRCLONING&gt;
 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.

答案1

得分: 4

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

/* /proc/net/route文件内容:
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    // 包含网关地址的行号(第一行为0)
	sep   = "\t" // 字段分隔符
	field = 2    // 包含十六进制网关地址的字段号(第一个字段为0)
)

func main() {

	file, err := os.Open(file)
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {

		// 跳转到包含网关地址的行
		for i := 0; i < line; i++ {
			scanner.Scan()
		}

		// 获取包含网关地址的字段
		tokens := strings.Split(scanner.Text(), sep)
		gatewayHex := "0x" + tokens[field]

		// 将十六进制地址转换为uint32
		d, _ := strconv.ParseInt(gatewayHex, 0, 64)
		d32 := uint32(d)

		// 从uint32创建net.IP地址
		ipd32 := make(net.IP, 4)
		binary.LittleEndian.PutUint32(ipd32, d32)
		fmt.Printf("%T --> %[1]v\n", ipd32)

		// 将net.IP格式化为点分十进制的IPv4字符串
		ip := net.IP(ipd32).String()
		fmt.Printf("%T --> %[1]v\n", ip)

		// 退出扫描器
		break
	}
}
英文:

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  = &quot;/proc/net/route&quot;
	line  = 1    // line containing the gateway addr. (first line: 0)
	sep   = &quot;\t&quot; // 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 &lt; line; i++ {
			scanner.Scan()
		}

		// get field containing gateway address
		tokens := strings.Split(scanner.Text(), sep)
		gatewayHex := &quot;0x&quot; + 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(&quot;%T --&gt; %[1]v\n&quot;, ipd32)

		// format net.IP to dotted ipV4 string
		ip := net.IP(ipd32).String()
		fmt.Printf(&quot;%T --&gt; %[1]v\n&quot;, ip)

		// exit scanner
		break
	}
}

答案2

得分: 2

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

接口	目标	网关	标志	引用计数	使用	度量	掩码	MTU	窗口	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类型。这有点绕弯,但我找不到任何可以在标准库或其他地方为您访问此内容的包。

英文:

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.

答案3

得分: 0

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

package main

import (
	"fmt"

	"github.com/jackpal/gateway"
)

func main() {
	gatewayIP, err := gateway.DiscoverGateway()
	if err != nil {
		panic(err)
	}
	fmt.Println("网关 IP:", gatewayIP)
}

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

英文:

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

package main

import (
	&quot;fmt&quot;

	&quot;github.com/jackpal/gateway&quot;
)

func main() {
	gatewayIP, err := gateway.DiscoverGateway()
	if err != nil {
		panic(err)
	}
	fmt.Println(&quot;Gateway IP:&quot;, gatewayIP)
}

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()代码。

示例代码片段:

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

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

英文:

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

Sample code snip:

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

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:

确定