英文:
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: <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.
答案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 = "/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
}
}
答案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 (
"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.
答案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("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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论