github.com/sagernet/netlink@v0.0.0-20240612041022-b9a21c07ac6a/nl/parse_attr_linux.go (about) 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 // Uint32 returns the uint32 value respecting the NET_BYTEORDER flag 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 // Uint64 returns the uint64 value respecting the NET_BYTEORDER flag 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 }