[][src]Module neli::nlattr

Netlink attribute handler This module aims to provide simple parsing for generic netlink attributes, including parsing for nested attributes.

Due to netlink's loose treatment of types, parsing attributes can be hard to model in Rust. neli's current solution is the following:

// This was received from the socket
let nlmsg = neli::nl::Nlmsghdr::new(None, neli::consts::GenlId::Ctrl, Vec::new(), None, None,
        neli::genl::Genlmsghdr::new(neli::consts::CtrlCmd::Unspec, 2, Vec::new()).unwrap());

// Get parsing handler for the attributes in this message where the next call
// to either get_nested_attributes() or get_payload_with() will expect a u16 type
// to be provided
let mut handle = nlmsg.nl_payload.get_attr_handle();

// Get the nested attribute where the Nlattr field of nla_type is equal to 1 and return
// a handler containing only this nested attribute internally
let mut next = handle.get_nested_attributes::<u16>(1).unwrap();

// Get the nested attribute where the Nlattr field of nla_type is equal to 1 and return
// the payload of this attribute as a u32
let thirty_two_bit_integer = next.get_attr_payload_as::<u32>(1).unwrap();

Design decisions

Nested attributes are represented by Vec<u8> payloads inside top level attributes. They are parsed during traversal to provide the ability to parse one attribute header using a different generic type for the nested attribute type parameters, the typical case when parsing nested attributes. To traverse a nested attribute, look at the documentation for .get_nested_attributes() and AttrHandle as well as the examples/ directory for code examples of how to traverse nested attributes.

Padding has been reworked using .strip() and .pad(). This is to be able to reason more clearly about where padding is expected and where it is not. Padding expectations in the attribute case of this library is defined as follows:

  • Attributes containing a primitive datatype (Nl implementation defined in lib.rs) should always report a length that is unpadded when using .size() and the representation when deserialized should always be stripped of padding
  • Attributes containing nested attributes should always be aligned to the number of bytes represented by libc::NLA_ALIGNTO
    • This is the way the kernel represents it for every standard generic netlink family I have seen
    • It also makes sense as every message payload should be padded by the serialization method of the header containing it
    • Headers encapsulating the structure on the level above it have no concept of the padding on the level below it
      • For example, Genlmsghdr will never get involved in padding for any data structure other than the payload defined for Genlmsghdr - this includes all of the attribute payloads contained in the Genlmsghdr payload
      • Only Nlattr knows what is padding and what is not in its own payload - to every other serialization and deserialization method, it may or may not be padding

Structs

Nlattr

Struct representing netlink attributes and payloads

Enums

AttrHandle

Handle returned by Genlmsghdr for traversing nested attribute structures