|
|
package netTest
|
|
|
|
|
|
//原文链接:https://blog.csdn.net/qq_38858546/article/details/119873424
|
|
|
//【golang】syscall 获取本机网卡IP、网关,可以通过IP地址来进行路由选择(多网卡)
|
|
|
import (
|
|
|
"fmt"
|
|
|
"net"
|
|
|
"sort"
|
|
|
"syscall"
|
|
|
"testing"
|
|
|
"unsafe"
|
|
|
)
|
|
|
|
|
|
type rtInfo struct {
|
|
|
Dst net.IPNet
|
|
|
Gateway, PrefSrc net.IP
|
|
|
OutputIface uint32
|
|
|
Priority uint32
|
|
|
}
|
|
|
|
|
|
type routeSlice []*rtInfo
|
|
|
|
|
|
type router struct {
|
|
|
ifaces []net.Interface
|
|
|
addrs []net.IP
|
|
|
v4 routeSlice
|
|
|
}
|
|
|
|
|
|
func getRouteInfo() (*router, error) {
|
|
|
rtr := &router{}
|
|
|
|
|
|
tab, err := syscall.NetlinkRIB(syscall.RTM_GETROUTE, syscall.AF_INET)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
|
|
|
msgs, err := syscall.ParseNetlinkMessage(tab)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
|
|
|
for _, m := range msgs {
|
|
|
switch m.Header.Type {
|
|
|
case syscall.NLMSG_DONE:
|
|
|
break
|
|
|
case syscall.RTM_NEWROUTE:
|
|
|
rtmsg := (*syscall.RtMsg)(unsafe.Pointer(&m.Data[0]))
|
|
|
attrs, err := syscall.ParseNetlinkRouteAttr(&m)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
routeInfo := rtInfo{}
|
|
|
rtr.v4 = append(rtr.v4, &routeInfo)
|
|
|
for _, attr := range attrs {
|
|
|
switch attr.Attr.Type {
|
|
|
case syscall.RTA_DST:
|
|
|
routeInfo.Dst.IP = net.IP(attr.Value)
|
|
|
routeInfo.Dst.Mask = net.CIDRMask(int(rtmsg.Dst_len), len(attr.Value)*8)
|
|
|
case syscall.RTA_GATEWAY:
|
|
|
routeInfo.Gateway = net.IPv4(attr.Value[0], attr.Value[1], attr.Value[2], attr.Value[3])
|
|
|
case syscall.RTA_OIF:
|
|
|
routeInfo.OutputIface = *(*uint32)(unsafe.Pointer(&attr.Value[0]))
|
|
|
case syscall.RTA_PRIORITY:
|
|
|
routeInfo.Priority = *(*uint32)(unsafe.Pointer(&attr.Value[0]))
|
|
|
case syscall.RTA_PREFSRC:
|
|
|
routeInfo.PrefSrc = net.IPv4(attr.Value[0], attr.Value[1], attr.Value[2], attr.Value[3])
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
sort.Slice(rtr.v4, func(i, j int) bool {
|
|
|
return rtr.v4[i].Priority < rtr.v4[j].Priority
|
|
|
})
|
|
|
|
|
|
ifaces, err := net.Interfaces()
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
|
|
|
for i, iface := range ifaces {
|
|
|
|
|
|
if i != iface.Index-1 {
|
|
|
break
|
|
|
}
|
|
|
|
|
|
if iface.Flags&net.FlagUp == 0 {
|
|
|
continue
|
|
|
}
|
|
|
rtr.ifaces = append(rtr.ifaces, iface)
|
|
|
ifaceAddrs, err := iface.Addrs()
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
var addrs net.IP
|
|
|
for _, addr := range ifaceAddrs {
|
|
|
if inet, ok := addr.(*net.IPNet); ok {
|
|
|
if v4 := inet.IP.To4(); v4 != nil {
|
|
|
if addrs == nil {
|
|
|
addrs = v4
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
rtr.addrs = append(rtr.addrs, addrs)
|
|
|
}
|
|
|
return rtr, nil
|
|
|
}
|
|
|
|
|
|
func TestRoute(tt *testing.T) {
|
|
|
newRoute, err := getRouteInfo()
|
|
|
if err != nil {
|
|
|
fmt.Println(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
fmt.Println("**************************************")
|
|
|
fmt.Printf("%-15v %-15v %-15v\n", "interfaceName", "gateway", "ip")
|
|
|
for _, rt := range newRoute.v4 {
|
|
|
if rt.Gateway != nil {
|
|
|
fmt.Printf("%-15v %-15v %-15v\n", newRoute.ifaces[rt.OutputIface-1].Name, rt.Gateway.String(), newRoute.addrs[rt.OutputIface-1])
|
|
|
}
|
|
|
}
|
|
|
fmt.Println("**************************************")
|
|
|
|
|
|
newRoute.getRoute(net.ParseIP("192.168.2.100"))
|
|
|
newRoute.getRoute(net.ParseIP("10.10.100.100"))
|
|
|
newRoute.getRoute(net.ParseIP("172.1.2.100"))
|
|
|
}
|
|
|
|
|
|
func (r *router) getRoute(dst net.IP) {
|
|
|
for _, rt := range r.v4 {
|
|
|
if rt.Dst.IP != nil && !rt.Dst.Contains(dst) {
|
|
|
continue
|
|
|
}
|
|
|
fmt.Printf("%-15v : ", dst.String())
|
|
|
if rt.PrefSrc == nil {
|
|
|
fmt.Println(r.ifaces[rt.OutputIface-1].Name, rt.Gateway.String(), r.addrs[rt.OutputIface-1].String())
|
|
|
} else {
|
|
|
fmt.Println(r.ifaces[rt.OutputIface-1].Name, rt.Gateway.String(), rt.PrefSrc.String())
|
|
|
}
|
|
|
return
|
|
|
}
|
|
|
}
|