/
netlink_linux.go
48 lines (40 loc) · 1.36 KB
/
netlink_linux.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// Package netlink contains the bare minimum needed to partially parse netlink messages.
package netlink
import (
"errors"
"syscall"
"unsafe"
"golang.org/x/sys/unix"
)
// Error types.
var (
ErrNotType20 = errors.New("NetlinkMessage wrong type")
ErrParseFailed = errors.New("Unable to parse InetDiagMsg")
)
// TODO - get these from sys/unix or syscall
const (
RTA_ALIGNTO = 4
SizeofNlMsghdr = 0x10
SizeofNlAttr = 0x4
SizeofRtAttr = 0x4
EINVAL = syscall.Errno(0x16)
)
// TODO use unix instead.
type NlMsghdr = syscall.NlMsghdr
type NetlinkMessage = syscall.NetlinkMessage
type RtAttr = syscall.RtAttr
type NetlinkRouteAttr = syscall.NetlinkRouteAttr
/*********************************************************************************************
* Low level netlink message stuff
*********************************************************************************************/
// rtaAlignOf rounds the length of a netlink route attribute up to align it properly.
func rtaAlignOf(attrlen int) int {
return (attrlen + unix.RTA_ALIGNTO - 1) & ^(unix.RTA_ALIGNTO - 1)
}
func netlinkRouteAttrAndValue(b []byte) (*unix.RtAttr, []byte, int, error) {
a := (*unix.RtAttr)(unsafe.Pointer(&b[0]))
if int(a.Len) < unix.SizeofRtAttr || int(a.Len) > len(b) {
return nil, nil, 0, unix.EINVAL
}
return a, b[unix.SizeofRtAttr:], rtaAlignOf(int(a.Len)), nil
}