...
1 package nl
2
3 import (
4 "encoding/binary"
5 "fmt"
6 "log"
7 )
8
9 type Attribute struct {
10 Type uint16
11 Value []byte
12 }
13
14 func ParseAttributes(data []byte) <-chan Attribute {
15 native := NativeEndian()
16 result := make(chan Attribute)
17
18 go func() {
19 i := 0
20 for i+4 < len(data) {
21 length := int(native.Uint16(data[i : i+2]))
22 attrType := native.Uint16(data[i+2 : i+4])
23
24 if length < 4 {
25 log.Printf("attribute 0x%02x has invalid length of %d bytes", attrType, length)
26 break
27 }
28
29 if len(data) < i+length {
30 log.Printf("attribute 0x%02x of length %d is truncated, only %d bytes remaining", attrType, length, len(data)-i)
31 break
32 }
33
34 result <- Attribute{
35 Type: attrType,
36 Value: data[i+4 : i+length],
37 }
38 i += rtaAlignOf(length)
39 }
40 close(result)
41 }()
42
43 return result
44 }
45
46 func PrintAttributes(data []byte) {
47 printAttributes(data, 0)
48 }
49
50 func printAttributes(data []byte, level int) {
51 for attr := range ParseAttributes(data) {
52 for i := 0; i < level; i++ {
53 print("> ")
54 }
55 nested := attr.Type&NLA_F_NESTED != 0
56 fmt.Printf("type=%d nested=%v len=%v %v\n", attr.Type&NLA_TYPE_MASK, nested, len(attr.Value), attr.Value)
57 if nested {
58 printAttributes(attr.Value, level+1)
59 }
60 }
61 }
62
63
64 func (attr *Attribute) Uint32() uint32 {
65 if attr.Type&NLA_F_NET_BYTEORDER != 0 {
66 return binary.BigEndian.Uint32(attr.Value)
67 } else {
68 return NativeEndian().Uint32(attr.Value)
69 }
70 }
71
72
73 func (attr *Attribute) Uint64() uint64 {
74 if attr.Type&NLA_F_NET_BYTEORDER != 0 {
75 return binary.BigEndian.Uint64(attr.Value)
76 } else {
77 return NativeEndian().Uint64(attr.Value)
78 }
79 }
80
View as plain text