package netroute
import (
"net"
"sort"
"syscall"
"unsafe"
"github.com/google/gopacket/routing"
)
func New () (routing .Router , error ) {
rtr := &router {}
rtr .ifaces = make (map [int ]net .Interface )
rtr .addrs = make (map [int ]ipAddrs )
tab , err := syscall .NetlinkRIB (syscall .RTM_GETROUTE , syscall .AF_UNSPEC )
if err != nil {
return nil , err
}
msgs , err := syscall .ParseNetlinkMessage (tab )
if err != nil {
return nil , err
}
loop :
for _ , m := range msgs {
switch m .Header .Type {
case syscall .NLMSG_DONE :
break loop
case syscall .RTM_NEWROUTE :
rt := (*syscall .RtMsg )(unsafe .Pointer (&m .Data [0 ]))
routeInfo := rtInfo {}
attrs , err := syscall .ParseNetlinkRouteAttr (&m )
if err != nil {
return nil , err
}
if rt .Family != syscall .AF_INET && rt .Family != syscall .AF_INET6 {
continue loop
}
for _ , attr := range attrs {
switch attr .Attr .Type {
case syscall .RTA_DST :
routeInfo .Dst = &net .IPNet {
IP : net .IP (attr .Value ),
Mask : net .CIDRMask (int (rt .Dst_len ), len (attr .Value )*8 ),
}
case syscall .RTA_SRC :
routeInfo .Src = &net .IPNet {
IP : net .IP (attr .Value ),
Mask : net .CIDRMask (int (rt .Src_len ), len (attr .Value )*8 ),
}
case syscall .RTA_GATEWAY :
routeInfo .Gateway = net .IP (attr .Value )
case syscall .RTA_PREFSRC :
routeInfo .PrefSrc = net .IP (attr .Value )
case syscall .RTA_IIF :
routeInfo .InputIface = *(*uint32 )(unsafe .Pointer (&attr .Value [0 ]))
case syscall .RTA_OIF :
routeInfo .OutputIface = *(*uint32 )(unsafe .Pointer (&attr .Value [0 ]))
case syscall .RTA_PRIORITY :
routeInfo .Priority = *(*uint32 )(unsafe .Pointer (&attr .Value [0 ]))
}
}
if routeInfo .Dst == nil && routeInfo .Src == nil && routeInfo .Gateway == nil {
continue loop
}
switch rt .Family {
case syscall .AF_INET :
rtr .v4 = append (rtr .v4 , &routeInfo )
case syscall .AF_INET6 :
rtr .v6 = append (rtr .v6 , &routeInfo )
default :
continue loop
}
}
}
sort .Sort (rtr .v4 )
sort .Sort (rtr .v6 )
ifaces , err := net .Interfaces ()
if err != nil {
return nil , err
}
for _ , iface := range ifaces {
rtr .ifaces [iface .Index ] = iface
var addrs ipAddrs
ifaceAddrs , err := iface .Addrs ()
if err != nil {
return nil , err
}
for _ , addr := range ifaceAddrs {
if inet , ok := addr .(*net .IPNet ); ok {
if v4 := inet .IP .To4 (); v4 != nil {
if addrs .v4 == nil {
addrs .v4 = v4
}
} else if addrs .v6 == nil {
addrs .v6 = inet .IP
}
}
}
rtr .addrs [iface .Index ] = addrs
}
return rtr , nil
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .