forked from abneptis/GoNetlink
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathattribute.go
76 lines (67 loc) · 1.8 KB
/
attribute.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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package netlink
/*
Copyright (c) 2011, Abneptis LLC. All rights reserved.
Original Author: James D. Nurmi <[email protected]>
See LICENSE for details
*/
import "fmt"
import "bytes"
import (
"encoding/binary"
"errors"
)
// A basic netlink type used for identifying
// nlattrs in a message.
type AttributeType uint16
// An attribute is used to hold an Netlink Attribute.
// An attribute is stored as a Length-Type-Value tuple.
// Length and Type are 16 bit integers, so values may not
// exceed 2^16.
type Attribute struct {
Type AttributeType
Body []byte
}
// Marshals a netlink attribute as a full LTV tuple.
func (self Attribute) MarshalNetlink() (out []byte, err error) {
l := len(self.Body)
out = make([]byte, l+4)
binary.LittleEndian.PutUint16(out[0:2], uint16(len(self.Body)+4))
binary.LittleEndian.PutUint16(out[2:4], uint16(self.Type))
copy(out[4:], self.Body[0:])
out = Padded(out)
return
}
// Unmarshals a netlink attribute.
func UnmarshalAttributes(in []byte) (out []Attribute, err error) {
pos := 0
for pos < len(in) {
l := binary.LittleEndian.Uint16(in[pos : pos+2])
if int(l) > len(in)-pos {
err = errors.New("Can't parse attribute (too long)")
break
}
if l > 4 {
t := binary.LittleEndian.Uint16(in[pos+2 : pos+4])
out = append(out, Attribute{Type: AttributeType(t), Body: in[pos+4 : pos+int(l)]})
pos = Align(pos + int(l))
} else {
err = errors.New(fmt.Sprintf("Invalid Attribute (Len: %d):", l))
break
}
}
return
}
// Returns the bytes of a marshalled list of attributes.
// Any marshalling error will cause the sequence to abort.
func MarshalAttributes(in []Attribute) (out []byte, err error) {
for i := range in {
var b []byte
b, err = in[i].MarshalNetlink()
if err == nil {
out = bytes.Join([][]byte{out, b}, []byte{})
} else {
break
}
}
return
}