You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

145 lines
3.4 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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