parse_attr_linux.go 1.7 KB

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