1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Netlink sockets and messages
13 // Round the length of a netlink message up to align it properly.
14 func nlmAlignOf(msglen
int) int {
15 return (msglen
+ NLMSG_ALIGNTO
- 1) & ^(NLMSG_ALIGNTO
- 1)
18 // Round the length of a netlink route attribute up to align it
20 func rtaAlignOf(attrlen
int) int {
21 return (attrlen
+ RTA_ALIGNTO
- 1) & ^(RTA_ALIGNTO
- 1)
24 // NetlinkRouteRequest represents the request message to receive
25 // routing and link states from the kernel.
26 type NetlinkRouteRequest
struct {
31 func (rr
*NetlinkRouteRequest
) toWireFormat() []byte {
32 b
:= make([]byte, rr
.Header
.Len
)
33 *(*uint32)(unsafe
.Pointer(&b
[0:4][0])) = rr
.Header
.Len
34 *(*uint16)(unsafe
.Pointer(&b
[4:6][0])) = rr
.Header
.Type
35 *(*uint16)(unsafe
.Pointer(&b
[6:8][0])) = rr
.Header
.Flags
36 *(*uint32)(unsafe
.Pointer(&b
[8:12][0])) = rr
.Header
.Seq
37 *(*uint32)(unsafe
.Pointer(&b
[12:16][0])) = rr
.Header
.Pid
38 b
[16] = byte(rr
.Data
.Family
)
42 func newNetlinkRouteRequest(proto
, seq
, family
int) []byte {
43 rr
:= &NetlinkRouteRequest
{}
44 rr
.Header
.Len
= uint32(NLMSG_HDRLEN
+ SizeofRtGenmsg
)
45 rr
.Header
.Type
= uint16(proto
)
46 rr
.Header
.Flags
= NLM_F_DUMP | NLM_F_REQUEST
47 rr
.Header
.Seq
= uint32(seq
)
48 rr
.Data
.Family
= uint8(family
)
49 return rr
.toWireFormat()
52 // NetlinkRIB returns routing information base, as known as RIB,
53 // which consists of network facility information, states and
55 func NetlinkRIB(proto
, family
int) ([]byte, error
) {
61 s
, e
:= Socket(AF_NETLINK
, SOCK_RAW
, 0)
67 lsanl
.Family
= AF_NETLINK
74 wb
:= newNetlinkRouteRequest(proto
, seq
, family
)
75 e
= Sendto(s
, wb
, 0, &lsanl
)
87 rb
= make([]byte, Getpagesize())
88 nr
, _
, e
= Recvfrom(s
, rb
, 0)
92 if nr
< NLMSG_HDRLEN
{
96 tab
= append(tab
, rb
...)
98 msgs
, _
:= ParseNetlinkMessage(rb
)
99 for _
, m
:= range msgs
{
100 if lsa
, e
= Getsockname(s
); e
!= nil {
103 switch v
:= lsa
.(type) {
104 case *SockaddrNetlink
:
105 if m
.Header
.Seq
!= uint32(seq
) || m
.Header
.Pid
!= v
.Pid
{
111 if m
.Header
.Type
== NLMSG_DONE
{
114 if m
.Header
.Type
== NLMSG_ERROR
{
124 // NetlinkMessage represents the netlink message.
125 type NetlinkMessage
struct {
130 // ParseNetlinkMessage parses buf as netlink messages and returns
131 // the slice containing the NetlinkMessage structs.
132 func ParseNetlinkMessage(buf
[]byte) ([]NetlinkMessage
, error
) {
138 msgs
[]NetlinkMessage
141 for len(buf
) >= NLMSG_HDRLEN
{
142 h
, dbuf
, dlen
, e
= netlinkMessageHeaderAndData(buf
)
146 m
:= NetlinkMessage
{}
148 m
.Data
= dbuf
[:int(h
.Len
)-NLMSG_HDRLEN
]
149 msgs
= append(msgs
, m
)
156 func netlinkMessageHeaderAndData(buf
[]byte) (*NlMsghdr
, []byte, int, error
) {
157 h
:= (*NlMsghdr
)(unsafe
.Pointer(&buf
[0]))
158 if int(h
.Len
) < NLMSG_HDRLEN ||
int(h
.Len
) > len(buf
) {
159 return nil, nil, 0, EINVAL
161 return h
, buf
[NLMSG_HDRLEN
:], nlmAlignOf(int(h
.Len
)), nil
164 // NetlinkRouteAttr represents the netlink route attribute.
165 type NetlinkRouteAttr
struct {
170 // ParseNetlinkRouteAttr parses msg's payload as netlink route
171 // attributes and returns the slice containing the NetlinkRouteAttr
173 func ParseNetlinkRouteAttr(msg
*NetlinkMessage
) ([]NetlinkRouteAttr
, error
) {
180 attrs
[]NetlinkRouteAttr
183 switch msg
.Header
.Type
{
184 case RTM_NEWLINK
, RTM_DELLINK
:
185 buf
= msg
.Data
[SizeofIfInfomsg
:]
186 case RTM_NEWADDR
, RTM_DELADDR
:
187 buf
= msg
.Data
[SizeofIfAddrmsg
:]
188 case RTM_NEWROUTE
, RTM_DELROUTE
:
189 buf
= msg
.Data
[SizeofRtMsg
:]
194 for len(buf
) >= SizeofRtAttr
{
195 a
, vbuf
, alen
, e
= netlinkRouteAttrAndValue(buf
)
199 ra
:= NetlinkRouteAttr
{}
201 ra
.Value
= vbuf
[:int(a
.Len
)-SizeofRtAttr
]
202 attrs
= append(attrs
, ra
)
209 func netlinkRouteAttrAndValue(buf
[]byte) (*RtAttr
, []byte, int, error
) {
210 h
:= (*RtAttr
)(unsafe
.Pointer(&buf
[0]))
211 if int(h
.Len
) < SizeofRtAttr ||
int(h
.Len
) > len(buf
) {
212 return nil, nil, 0, EINVAL
214 return h
, buf
[SizeofRtAttr
:], rtaAlignOf(int(h
.Len
)), nil