package syscall
import
func ( int) int {
return ( + NLMSG_ALIGNTO - 1) & ^(NLMSG_ALIGNTO - 1)
}
func ( int) int {
return ( + RTA_ALIGNTO - 1) & ^(RTA_ALIGNTO - 1)
}
type NetlinkRouteRequest struct {
Header NlMsghdr
Data RtGenmsg
}
func ( *NetlinkRouteRequest) () []byte {
:= make([]byte, .Header.Len)
*(*uint32)(unsafe.Pointer(&[0:4][0])) = .Header.Len
*(*uint16)(unsafe.Pointer(&[4:6][0])) = .Header.Type
*(*uint16)(unsafe.Pointer(&[6:8][0])) = .Header.Flags
*(*uint32)(unsafe.Pointer(&[8:12][0])) = .Header.Seq
*(*uint32)(unsafe.Pointer(&[12:16][0])) = .Header.Pid
[16] = byte(.Data.Family)
return
}
func (, , int) []byte {
:= &NetlinkRouteRequest{}
.Header.Len = uint32(NLMSG_HDRLEN + SizeofRtGenmsg)
.Header.Type = uint16()
.Header.Flags = NLM_F_DUMP | NLM_F_REQUEST
.Header.Seq = uint32()
.Data.Family = uint8()
return .toWireFormat()
}
func (, int) ([]byte, error) {
, := cloexecSocket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)
if != nil {
return nil,
}
defer Close()
:= &SockaddrNetlink{Family: AF_NETLINK}
if := Bind(, ); != nil {
return nil,
}
:= newNetlinkRouteRequest(, 1, )
if := Sendto(, , 0, ); != nil {
return nil,
}
var []byte
:= make([]byte, Getpagesize())
:
for {
:=
, , := Recvfrom(, , 0)
if != nil {
return nil,
}
if < NLMSG_HDRLEN {
return nil, EINVAL
}
= [:]
= append(, ...)
, := ParseNetlinkMessage()
if != nil {
return nil,
}
for , := range {
, := Getsockname()
if != nil {
return nil,
}
switch v := .(type) {
case *SockaddrNetlink:
if .Header.Seq != 1 || .Header.Pid != .Pid {
return nil, EINVAL
}
default:
return nil, EINVAL
}
if .Header.Type == NLMSG_DONE {
break
}
if .Header.Type == NLMSG_ERROR {
return nil, EINVAL
}
}
}
return , nil
}
type NetlinkMessage struct {
Header NlMsghdr
Data []byte
}
func ( []byte) ([]NetlinkMessage, error) {
var []NetlinkMessage
for len() >= NLMSG_HDRLEN {
, , , := netlinkMessageHeaderAndData()
if != nil {
return nil,
}
:= NetlinkMessage{Header: *, Data: [:int(.Len)-NLMSG_HDRLEN]}
= append(, )
= [:]
}
return , nil
}
func ( []byte) (*NlMsghdr, []byte, int, error) {
:= (*NlMsghdr)(unsafe.Pointer(&[0]))
:= nlmAlignOf(int(.Len))
if int(.Len) < NLMSG_HDRLEN || > len() {
return nil, nil, 0, EINVAL
}
return , [NLMSG_HDRLEN:], , nil
}
type NetlinkRouteAttr struct {
Attr RtAttr
Value []byte
}
func ( *NetlinkMessage) ([]NetlinkRouteAttr, error) {
var []byte
switch .Header.Type {
case RTM_NEWLINK, RTM_DELLINK:
= .Data[SizeofIfInfomsg:]
case RTM_NEWADDR, RTM_DELADDR:
= .Data[SizeofIfAddrmsg:]
case RTM_NEWROUTE, RTM_DELROUTE:
= .Data[SizeofRtMsg:]
default:
return nil, EINVAL
}
var []NetlinkRouteAttr
for len() >= SizeofRtAttr {
, , , := netlinkRouteAttrAndValue()
if != nil {
return nil,
}
:= NetlinkRouteAttr{Attr: *, Value: [:int(.Len)-SizeofRtAttr]}
= append(, )
= [:]
}
return , nil
}
func ( []byte) (*RtAttr, []byte, int, error) {
:= (*RtAttr)(unsafe.Pointer(&[0]))
if int(.Len) < SizeofRtAttr || int(.Len) > len() {
return nil, nil, 0, EINVAL
}
return , [SizeofRtAttr:], rtaAlignOf(int(.Len)), nil
}