github.com/vishvananda/netlink@v1.3.0/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  }