2017-04-17 10:33:09 +05:30

142 lines
3.3 KiB
Go
Executable File

// +build linux
package nlgo
import (
"log"
"net"
"syscall"
"testing"
"unsafe"
)
// This basic rtnetlink example lists up link interfaces.
func Example() {
sock := NlSocketAlloc()
defer NlSocketFree(sock)
if err := NlConnect(sock, syscall.NETLINK_ROUTE); err != nil {
panic(err)
}
req := make([]byte, NLMSG_ALIGN(syscall.SizeofIfInfomsg))
if err := NlSendSimple(sock, syscall.RTM_GETLINK, syscall.NLM_F_DUMP, req); err != nil {
panic(err)
}
func() {
for {
buf := make([]byte, syscall.Getpagesize())
if nn, _, err := syscall.Recvfrom(sock.Fd, buf, syscall.MSG_TRUNC); err != nil {
panic(err)
} else if nn > len(buf) {
panic("out of recv buf")
} else {
buf = buf[:nn]
}
if msgs, err := syscall.ParseNetlinkMessage(buf); err != nil {
panic(err)
} else {
for _, msg := range msgs {
switch msg.Header.Type {
case syscall.RTM_NEWLINK:
ifinfo := (*syscall.IfInfomsg)(unsafe.Pointer(&msg.Data[0]))
if attrs, err := RouteLinkPolicy.Parse(msg.Data[NLA_ALIGN(syscall.SizeofIfInfomsg):]); err != nil {
panic(err)
} else {
log.Print("ifinfomsg=", ifinfo, " attrs=", attrs)
}
case syscall.NLMSG_DONE:
return
default:
log.Print("unhandled msg", msg.Header)
}
}
}
}
}()
}
// This is RTNLGRP_LINK listener example. RTNLGRP_LINK is newer version of RTMGRP_LINK.
func ExampleNlSocketAddMembership() {
sock := NlSocketAlloc()
defer NlSocketFree(sock)
if err := NlConnect(sock, syscall.NETLINK_ROUTE); err != nil {
panic(err)
}
if err := NlSocketAddMembership(sock, syscall.RTNLGRP_LINK); err != nil {
panic(err)
}
for {
buf := make([]byte, syscall.Getpagesize())
if nn, _, err := syscall.Recvfrom(sock.Fd, buf, syscall.MSG_TRUNC); err != nil {
panic(err)
} else if nn > len(buf) {
panic("out of recv buf")
} else {
buf = buf[:nn]
}
if msgs, err := syscall.ParseNetlinkMessage(buf); err != nil {
panic(err)
} else {
for _, msg := range msgs {
switch msg.Header.Type {
case syscall.RTM_NEWLINK, syscall.RTM_DELLINK, syscall.RTM_GETLINK:
ifinfo := (*syscall.IfInfomsg)(unsafe.Pointer(&msg.Data[0]))
if attrs, err := RouteLinkPolicy.Parse(msg.Data[NLA_ALIGN(syscall.SizeofIfInfomsg):]); err != nil {
panic(err)
} else {
log.Print("ifinfomsg=", ifinfo, " attrs=", attrs)
}
default:
log.Print("unhandled msg")
}
}
}
}
}
func TestRoute(t *testing.T) {
if hub, err := NewRtHub(); err != nil {
panic(err)
} else {
defer hub.Close()
req := syscall.NetlinkMessage{
Header: syscall.NlMsghdr{
Type: syscall.RTM_GETROUTE,
Flags: syscall.NLM_F_REQUEST,
},
}
(*RtMessage)(&req).Set(
syscall.RtMsg{
Family: syscall.AF_INET6,
},
AttrSlice{
Attr{
Header: syscall.NlAttr{
Type: syscall.RTA_DST,
},
Value: Binary(net.ParseIP("2001:503:ba3e::2:30").To16()),
},
},
)
if msgs, err := hub.Sync(req); err != nil {
panic(err)
} else {
for _, msg := range msgs {
switch msg.Header.Type {
case syscall.NLMSG_ERROR:
err := NlMsgerr(msg)
if err.Payload().Error != 0 {
t.Error(err)
}
case syscall.RTM_NEWROUTE:
if attr, err := RtMessage(msg).Attrs(); err != nil {
t.Error(err)
} else {
t.Log(attr)
}
}
}
}
}
}