def nla_nest_start(msg, attrtype): """ Start a new level of nested attributes """ start = nlattr(nlmsg_tail(msg.nm_nlh)) if nla_put(msg, attrtype, 0, None) < 0: return None return start
def genlmsg_attrdata(gnlh, hdrlen): """Return nlattr at the start of message attributes. https://github.com/thom311/libnl/blob/libnl3_2_25/lib/genl/genl.c#L287 Positional arguments: gnlh -- Generic Netlink message header (genlmsghdr class instance). hdrlen -- length of user header (integer). Returns: nlattr class instance with others in its payload. """ return nlattr(genlmsg_user_data(gnlh, hdrlen))
def nla_parse_nested(tb, maxtype, nla, policy): """Create attribute index based on nested attribute. https://github.com/thom311/libnl/blob/libnl3_2_25/lib/attr.c#L885 Feeds the stream of attributes nested into the specified attribute to nla_parse(). Positional arguments: tb -- dictionary to be filled (maxtype+1 elements). maxtype -- maximum attribute type expected and accepted (integer). nla -- nested attribute (nlattr class instance). policy -- attribute validation policy. Returns: 0 on success or a negative error code. """ return nla_parse(tb, maxtype, nlattr(nla_data(nla)), nla_len(nla), policy)
def nla_for_each_nested(nla, rem): """Iterate over a stream of nested attributes. https://github.com/thom311/libnl/blob/libnl3_2_25/include/netlink/attr.h#L274 Positional arguments: nla -- attribute containing the nested attributes (nlattr class instance). rem -- initialized to len, holds bytes currently remaining in stream (c_int). Returns: Generator yielding nlattr instances. """ pos = nlattr(nla_data(nla)) rem.value = nla_len(nla) while nla_ok(pos, rem): yield pos pos = nla_next(pos, rem)
def nla_next(nla, remaining): """Return next attribute in a stream of attributes. https://github.com/thom311/libnl/blob/libnl3_2_25/lib/attr.c#L171 Calculates the offset to the next attribute based on the attribute given. The attribute provided is assumed to be accessible, the caller is responsible to use nla_ok() beforehand. The offset (length of specified attribute including padding) is then subtracted from the remaining bytes variable and a pointer to the next attribute is returned. nla_next() can be called as long as remaining is >0. Positional arguments: nla -- attribute of any kind (nlattr class instance). remaining -- number of bytes remaining in attribute stream (c_int). Returns: Next nlattr class instance. """ totlen = int(NLA_ALIGN(nla.nla_len)) remaining.value -= totlen return nlattr(bytearray_ptr(nla.bytearray, totlen))
def nla_reserve(msg, attrtype, attrlen): """Reserve space for an attribute. https://github.com/thom311/libnl/blob/libnl3_2_25/lib/attr.c#L456 Reserves room for an attribute in the specified Netlink message and fills in the attribute header (type, length). Returns None if there is insufficient space for the attribute. Any padding between payload and the start of the next attribute is zeroed out. Positional arguments: msg -- Netlink message (nl_msg class instance). attrtype -- attribute type (integer). attrlen -- length of payload (integer). Returns: nlattr class instance allocated to the new space or None on failure. """ tlen = NLMSG_ALIGN(msg.nm_nlh.nlmsg_len) + nla_total_size(attrlen) if tlen > msg.nm_size: return None nla = nlattr(nlmsg_tail(msg.nm_nlh)) nla.nla_type = attrtype nla.nla_len = nla_attr_size(attrlen) if attrlen: padlen = nla_padlen(attrlen) nla.bytearray[nla.nla_len:nla.nla_len + padlen] = bytearray(b'\0') * padlen msg.nm_nlh.nlmsg_len = tlen _LOGGER.debug( 'msg 0x%x: attr <0x%x> %d: Reserved %d (%d) bytes at offset +%d nlmsg_len=%d', id(msg), id(nla), nla.nla_type, nla_total_size(attrlen), attrlen, nla.bytearray.slice.start - nlmsg_data(msg.nm_nlh).slice.start, msg.nm_nlh.nlmsg_len) return nla
def nla_reserve(msg, attrtype, attrlen): """Reserve space for an attribute. https://github.com/thom311/libnl/blob/libnl3_2_25/lib/attr.c#L456 Reserves room for an attribute in the specified Netlink message and fills in the attribute header (type, length). Returns None if there is insufficient space for the attribute. Any padding between payload and the start of the next attribute is zeroed out. Positional arguments: msg -- Netlink message (nl_msg class instance). attrtype -- attribute type (integer). attrlen -- length of payload (integer). Returns: nlattr class instance allocated to the new space or None on failure. """ tlen = NLMSG_ALIGN(msg.nm_nlh.nlmsg_len) + nla_total_size(attrlen) if tlen > msg.nm_size: return None nla = nlattr(nlmsg_tail(msg.nm_nlh)) nla.nla_type = attrtype nla.nla_len = nla_attr_size(attrlen) if attrlen: padlen = nla_padlen(attrlen) nla.bytearray[nla.nla_len:nla.nla_len + padlen] = bytearray(b'\0') * padlen msg.nm_nlh.nlmsg_len = tlen _LOGGER.debug('msg 0x%x: attr <0x%x> %d: Reserved %d (%d) bytes at offset +%d nlmsg_len=%d', id(msg), id(nla), nla.nla_type, nla_total_size(attrlen), attrlen, nla.bytearray.slice.start - nlmsg_data(msg.nm_nlh).slice.start, msg.nm_nlh.nlmsg_len) return nla