144d362409d5469aed47d19e7908d19bd194493aThomas Graf/* 244d362409d5469aed47d19e7908d19bd194493aThomas Graf * lib/attr.c Netlink Attributes 344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 444d362409d5469aed47d19e7908d19bd194493aThomas Graf * This library is free software; you can redistribute it and/or 544d362409d5469aed47d19e7908d19bd194493aThomas Graf * modify it under the terms of the GNU Lesser General Public 644d362409d5469aed47d19e7908d19bd194493aThomas Graf * License as published by the Free Software Foundation version 2.1 744d362409d5469aed47d19e7908d19bd194493aThomas Graf * of the License. 844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 9dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch> 1044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1144d362409d5469aed47d19e7908d19bd194493aThomas Graf 1244d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink-local.h> 1344d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netlink.h> 1444d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/utils.h> 1544d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/addr.h> 1644d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/attr.h> 1744d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/msg.h> 1844d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <linux/socket.h> 1944d362409d5469aed47d19e7908d19bd194493aThomas Graf 2044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 2144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @ingroup msg 2244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @defgroup attr Attributes 2344d362409d5469aed47d19e7908d19bd194493aThomas Graf * Netlink Attributes Construction/Parsing Interface 24dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 25dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * \section attr_sec Netlink Attributes 26dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Netlink attributes allow for data chunks of arbitary length to be 27dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * attached to a netlink message. Each attribute is encoded with a 28dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * type and length field, both 16 bits, stored in the attribute header 29dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * preceding the attribute data. The main advantage of using attributes 30dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * over packing everything into the family header is that the interface 31dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * stays extendable as new attributes can supersede old attributes while 32dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * remaining backwards compatible. Also attributes can be defined optional 33dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * thus avoiding the transmission of unnecessary empty data blocks. 34dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Special nested attributes allow for more complex data structures to 35dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * be transmitted, e.g. trees, lists, etc. 36dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 37dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * While not required, netlink attributes typically follow the family 38dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * header of a netlink message and must be properly aligned to NLA_ALIGNTO: 39dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @code 40dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * +----------------+- - -+---------------+- - -+------------+- - -+ 41dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * | Netlink Header | Pad | Family Header | Pad | Attributes | Pad | 42dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * +----------------+- - -+---------------+- - -+------------+- - -+ 43dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @endcode 44dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 45dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * The actual attributes are chained together each separately aligned to 46dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * NLA_ALIGNTO. The position of an attribute is defined based on the 47dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * length field of the preceding attributes: 48dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @code 49dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * +-------------+- - -+-------------+- - -+------ 50dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * | Attribute 1 | Pad | Attribute 2 | Pad | ... 51dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * +-------------+- - -+-------------+- - -+------ 52dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nla_next(attr1)------^ 53dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @endcode 54dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 55dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * The attribute itself consists of the attribute header followed by 56dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * the actual payload also aligned to NLA_ALIGNTO. The function nla_data() 57dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * returns a pointer to the start of the payload while nla_len() returns 58dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * the length of the payload in bytes. 59dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 60dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * \b Note: Be aware, NLA_ALIGNTO equals to 4 bytes, therefore it is not 61dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * safe to dereference any 64 bit data types directly. 62dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 6344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code 64dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * <----------- nla_total_size(payload) -----------> 65dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * <-------- nla_attr_size(payload) ---------> 66dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * +------------------+- - -+- - - - - - - - - +- - -+ 67dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * | Attribute Header | Pad | Payload | Pad | 68dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * +------------------+- - -+- - - - - - - - - +- - -+ 69dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nla_data(nla)-------------^ 70dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * <- nla_len(nla) -> 7144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode 7244d362409d5469aed47d19e7908d19bd194493aThomas Graf * 73dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @subsection attr_datatypes Attribute Data Types 74dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * A number of basic data types are supported to simplify access and 75dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * validation of netlink attributes. This data type information is 76dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * not encoded in the attribute, both the kernel and userspace part 77dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * are required to share this information on their own. 78dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 79dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * One of the major advantages of these basic types is the automatic 80dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * validation of each attribute based on an attribute policy. The 81dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * validation covers most of the checks required to safely use 82dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * attributes and thus keeps the individual sanity check to a minimum. 83dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 84dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Never access attribute payload without ensuring basic validation 85dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * first, attributes may: 86dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * - not be present even though required 87dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * - contain less actual payload than expected 88dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * - fake a attribute length which exceeds the end of the message 89dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * - contain unterminated character strings 90dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 91dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Policies are defined as array of the struct nla_policy. The array is 92dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * indexed with the attribute type, therefore the array must be sized 93dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * accordingly. 94dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @code 95dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * static struct nla_policy my_policy[ATTR_MAX+1] = { 96dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * [ATTR_FOO] = { .type = ..., .minlen = ..., .maxlen = ... }, 97dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * }; 98dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 99dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * err = nla_validate(attrs, attrlen, ATTR_MAX, &my_policy); 100dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @endcode 101dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 102dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Some basic validations are performed on every attribute, regardless of type. 103dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * - If the attribute type exceeds the maximum attribute type specified or 104dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * the attribute type is lesser-or-equal than zero, the attribute will 105dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * be silently ignored. 106dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * - If the payload length falls below the \a minlen value the attribute 107dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * will be rejected. 108dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * - If \a maxlen is non-zero and the payload length exceeds the \a maxlen 109dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * value the attribute will be rejected. 110dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 111dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 112dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @par Unspecific Attribute (NLA_UNSPEC) 113dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * This is the standard type if no type is specified. It is used for 114dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * binary data of arbitary length. Typically this attribute carries 115dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * a binary structure or a stream of bytes. 11644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par 11744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code 118dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // In this example, we will assume a binary structure requires to 119dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // be transmitted. The definition of the structure will typically 120dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // go into a header file available to both the kernel and userspace 121dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // side. 122dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // 123dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // Note: Be careful when putting 64 bit data types into a structure. 124dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // The attribute payload is only aligned to 4 bytes, dereferencing 125dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // the member may fail. 126dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * struct my_struct { 127dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * int a; 128dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * int b; 129dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * }; 130dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 131dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // The validation function will not enforce an exact length match to 132dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // allow structures to grow as required. Note: While it is allowed 133dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // to add members to the end of the structure, changing the order or 134dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // inserting members in the middle of the structure will break your 135dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // binary interface. 136dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * static struct nla_policy my_policy[ATTR_MAX+1] = { 137dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * [ATTR_MY_STRICT] = { .type = NLA_UNSPEC, 138dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * .minlen = sizeof(struct my_struct) }, 139dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 140dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // The binary structure is appened to the message using nla_put() 141dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * struct my_struct foo = { .a = 1, .b = 2 }; 142dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nla_put(msg, ATTR_MY_STRUCT, sizeof(foo), &foo); 143dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 144dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // On the receiving side, a pointer to the structure pointing inside 145dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // the message payload is returned by nla_get(). 146dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * if (attrs[ATTR_MY_STRUCT]) 147dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * struct my_struct *foo = nla_get(attrs[ATTR_MY_STRUCT]); 14844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode 14944d362409d5469aed47d19e7908d19bd194493aThomas Graf * 150dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @par Integers (NLA_U8, NLA_U16, NLA_U32, NLA_U64) 151dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Integers come in different sizes from 8 bit to 64 bit. However, since the 152dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * payload length is aligned to 4 bytes, integers smaller than 32 bit are 153dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * only useful to enforce the maximum range of values. 154dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @par 155dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * \b Note: There is no difference made between signed and unsigned integers. 156dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * The validation only enforces the minimal payload length required to store 157dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * an integer of specified type. 158dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @par 15944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code 160dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // Even though possible, it does not make sense to specify .minlen or 161dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // .maxlen for integer types. The data types implies the corresponding 162dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // minimal payload length. 163dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * static struct nla_policy my_policy[ATTR_MAX+1] = { 164dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * [ATTR_FOO] = { .type = NLA_U32 }, 165dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 166dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // Numeric values can be appended directly using the respective 167dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // nla_put_uxxx() function 168dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nla_put_u32(msg, ATTR_FOO, 123); 169dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 170dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // Same for the receiving side. 171dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * if (attrs[ATTR_FOO]) 172dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * uint32_t foo = nla_get_u32(attrs[ATTR_FOO]); 17344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode 17444d362409d5469aed47d19e7908d19bd194493aThomas Graf * 175dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @par Character string (NLA_STRING) 176dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * This data type represents a NUL terminated character string of variable 177dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * length. For binary data streams the type NLA_UNSPEC is recommended. 178dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @par 17944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code 180dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // Enforce a NUL terminated character string of at most 4 characters 181dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // including the NUL termination. 182dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * static struct nla_policy my_policy[ATTR_MAX+1] = { 183dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * [ATTR_BAR] = { .type = NLA_STRING, maxlen = 4 }, 184dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 185dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // nla_put_string() creates a string attribute of the necessary length 186dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // and appends it to the message including the NUL termination. 187dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nla_put_string(msg, ATTR_BAR, "some text"); 188dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 189dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // It is safe to use the returned character string directly if the 190dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // attribute has been validated as the validation enforces the proper 191dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // termination of the string. 192dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * if (attrs[ATTR_BAR]) 193dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * char *text = nla_get_string(attrs[ATTR_BAR]); 194dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @endcode 195dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 196dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @par Flag (NLA_FLAG) 197dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * This attribute type may be used to indicate the presence of a flag. The 198dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * attribute is only valid if the payload length is zero. The presence of 199dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * the attribute header indicates the presence of the flag. 200dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @par 201dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @code 202dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // This attribute type is special as .minlen and .maxlen have no effect. 203dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * static struct nla_policy my_policy[ATTR_MAX+1] = { 204dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * [ATTR_FLAG] = { .type = NLA_FLAG }, 205dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 206dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // nla_put_flag() appends a zero sized attribute to the message. 207dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nla_put_flag(msg, ATTR_FLAG); 208dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 209dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // There is no need for a receival function, the presence is the value. 210dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * if (attrs[ATTR_FLAG]) 211dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // flag is present 212dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @endcode 213dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 214dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @par Micro Seconds (NLA_MSECS) 215dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 216dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @par Nested Attribute (NLA_NESTED) 217dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Attributes can be nested and put into a container to create groups, lists 218dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * or to construct trees of attributes. Nested attributes are often used to 219dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * pass attributes to a subsystem where the top layer has no knowledge of the 220dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * configuration possibilities of each subsystem. 221dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @par 222dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * \b Note: When validating the attributes using nlmsg_validate() or 223dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nlmsg_parse() it will only affect the top level attributes. Each 224dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * level of nested attributes must be validated seperately using 225dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nla_parse_nested() or nla_validate(). 226dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @par 227dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @code 228dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // The minimal length policy may be used to enforce the presence of at 229dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // least one attribute. 230dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * static struct nla_policy my_policy[ATTR_MAX+1] = { 231dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * [ATTR_OPTS] = { .type = NLA_NESTED, minlen = NLA_HDRLEN }, 232dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 233dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // Nested attributes are constructed by enclosing the attributes 234dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // to be nested with calls to nla_nest_start() respetively nla_nest_end(). 235dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * struct nlattr *opts = nla_nest_start(msg, ATTR_OPTS); 236dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nla_put_u32(msg, ATTR_FOO, 123); 237dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nla_put_string(msg, ATTR_BAR, "some text"); 238dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nla_nest_end(msg, opts); 239dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 240dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // Various methods exist to parse nested attributes, the easiest being 241dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // nla_parse_nested() which also allows validation in the same step. 242dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * if (attrs[ATTR_OPTS]) { 243dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * struct nlattr *nested[ATTR_MAX+1]; 244dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 245dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nla_parse_nested(nested, ATTR_MAX, attrs[ATTR_OPTS], &policy); 246dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 247dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * if (nested[ATTR_FOO]) 248dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * uint32_t foo = nla_get_u32(nested[ATTR_FOO]); 249dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * } 250dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @endcode 251dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 252dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @subsection attr_exceptions Exception Based Attribute Construction 253dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Often a large number of attributes are added to a message in a single 254dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * function. In order to simplify error handling, a second set of 255dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * construction functions exist which jump to a error label when they 256dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * fail instead of returning an error code. This second set consists 257dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * of macros which are named after their error code based counterpart 258dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * except that the name is written all uppercase. 259dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 260dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * All of the macros jump to the target \c nla_put_failure if they fail. 261dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @code 262dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * void my_func(struct nl_msg *msg) 263dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * { 264dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * NLA_PUT_U32(msg, ATTR_FOO, 10); 265dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * NLA_PUT_STRING(msg, ATTR_BAR, "bar"); 266dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 267dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * return 0; 268dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 269dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nla_put_failure: 2708a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * return -NLE_NOMEM; 271dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * } 272dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @endcode 273dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 274dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @subsection attr_examples Examples 275dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @par Example 1.1 Constructing a netlink message with attributes. 276dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @code 277dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * struct nl_msg *build_msg(int ifindex, struct nl_addr *lladdr, int mtu) 27844d362409d5469aed47d19e7908d19bd194493aThomas Graf * { 279dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * struct nl_msg *msg; 280dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * struct nlattr *info, *vlan; 281dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * struct ifinfomsg ifi = { 282dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * .ifi_family = AF_INET, 283dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * .ifi_index = ifindex, 284dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * }; 285dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 286dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // Allocate a new netlink message, type=RTM_SETLINK, flags=NLM_F_ECHO 287dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * if (!(msg = nlmsg_alloc_simple(RTM_SETLINK, NLM_F_ECHO))) 288dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * return NULL; 289dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 290dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // Append the family specific header (struct ifinfomsg) 291dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0) 292dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * goto nla_put_failure 293dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 294dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // Append a 32 bit integer attribute to carry the MTU 295dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * NLA_PUT_U32(msg, IFLA_MTU, mtu); 296dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 297dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // Append a unspecific attribute to carry the link layer address 298dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * NLA_PUT_ADDR(msg, IFLA_ADDRESS, lladdr); 299dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 300dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // Append a container for nested attributes to carry link information 301dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * if (!(info = nla_nest_start(msg, IFLA_LINKINFO))) 302dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * goto nla_put_failure; 303dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 304dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // Put a string attribute into the container 305dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * NLA_PUT_STRING(msg, IFLA_INFO_KIND, "vlan"); 306dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 307dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // Append another container inside the open container to carry 308dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // vlan specific attributes 309dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * if (!(vlan = nla_nest_start(msg, IFLA_INFO_DATA))) 310dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * goto nla_put_failure; 311dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 312dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // add vlan specific info attributes here... 313dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 314dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // Finish nesting the vlan attributes and close the second container. 315dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nla_nest_end(msg, vlan); 316dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 317dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // Finish nesting the link info attribute and close the first container. 318dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nla_nest_end(msg, info); 319dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 320dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * return msg; 321dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 322dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // If any of the construction macros fails, we end up here. 323dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nla_put_failure: 324dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nlmsg_free(msg); 325dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * return NULL; 32644d362409d5469aed47d19e7908d19bd194493aThomas Graf * } 327dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @endcode 328dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 329dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @par Example 2.1 Parsing a netlink message with attributes. 330dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @code 331dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * int parse_message(struct nl_msg *msg) 332dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * { 333dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // The policy defines two attributes: a 32 bit integer and a container 334dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // for nested attributes. 335dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * struct nla_policy attr_policy[ATTR_MAX+1] = { 336dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * [ATTR_FOO] = { .type = NLA_U32 }, 337dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * [ATTR_BAR] = { .type = NLA_NESTED }, 338dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * }; 339dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * struct nlattr *attrs[ATTR_MAX+1]; 340dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * int err; 341dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 342dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // The nlmsg_parse() function will make sure that the message contains 343dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // enough payload to hold the header (struct my_hdr), validates any 344dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // attributes attached to the messages and stores a pointer to each 345dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // attribute in the attrs[] array accessable by attribute type. 346dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * if ((err = nlmsg_parse(nlmsg_hdr(msg), sizeof(struct my_hdr), attrs, 347dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * ATTR_MAX, attr_policy)) < 0) 348dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * goto errout; 34944d362409d5469aed47d19e7908d19bd194493aThomas Graf * 350dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * if (attrs[ATTR_FOO]) { 351dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // It is safe to directly access the attribute payload without 352dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // any further checks since nlmsg_parse() enforced the policy. 353dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * uint32_t foo = nla_get_u32(attrs[ATTR_FOO]); 354dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * } 35544d362409d5469aed47d19e7908d19bd194493aThomas Graf * 356dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * if (attrs[ATTR_BAR]) { 357dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * struct nlattr *nested[NESTED_MAX+1]; 358dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 359dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // Attributes nested in a container can be parsed the same way 360dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // as top level attributes. 361dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * if ((err = nla_parse_nested(nested, NESTED_MAX, attrs[ATTR_BAR], 362dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nested_policy)) < 0) 363dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * goto errout; 364dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 365dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // Process nested attributes here. 366dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * } 367dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 368dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * err = 0; 369dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * errout: 370dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * return err; 371dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * } 37244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode 373dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 37444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 37544d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 37644d362409d5469aed47d19e7908d19bd194493aThomas Graf 37744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 378dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @name Attribute Size Calculation 37944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 38044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 38144d362409d5469aed47d19e7908d19bd194493aThomas Graf 38244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 383dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Return size of attribute whithout padding. 384dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg payload Payload length of attribute. 385dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 386dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @code 387dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * <-------- nla_attr_size(payload) ---------> 388dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * +------------------+- - -+- - - - - - - - - +- - -+ 389dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * | Attribute Header | Pad | Payload | Pad | 390dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * +------------------+- - -+- - - - - - - - - +- - -+ 391dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @endcode 392dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 393dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return Size of attribute in bytes without padding. 39444d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 39544d362409d5469aed47d19e7908d19bd194493aThomas Grafint nla_attr_size(int payload) 39644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 39744d362409d5469aed47d19e7908d19bd194493aThomas Graf return NLA_HDRLEN + payload; 39844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 39944d362409d5469aed47d19e7908d19bd194493aThomas Graf 40044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 401dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Return size of attribute including padding. 402dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg payload Payload length of attribute. 403dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 404dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @code 405dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * <----------- nla_total_size(payload) -----------> 406dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * +------------------+- - -+- - - - - - - - - +- - -+ 407dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * | Attribute Header | Pad | Payload | Pad | 408dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * +------------------+- - -+- - - - - - - - - +- - -+ 409dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @endcode 410dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 411dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return Size of attribute in bytes. 41244d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 41344d362409d5469aed47d19e7908d19bd194493aThomas Grafint nla_total_size(int payload) 41444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 41544d362409d5469aed47d19e7908d19bd194493aThomas Graf return NLA_ALIGN(nla_attr_size(payload)); 41644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 41744d362409d5469aed47d19e7908d19bd194493aThomas Graf 41844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 419dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Return length of padding at the tail of the attribute. 420dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg payload Payload length of attribute. 421dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 422dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @code 423dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * +------------------+- - -+- - - - - - - - - +- - -+ 424dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * | Attribute Header | Pad | Payload | Pad | 425dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * +------------------+- - -+- - - - - - - - - +- - -+ 426dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * <---> 427dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @endcode 428dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 429dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return Length of padding in bytes. 43044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 43144d362409d5469aed47d19e7908d19bd194493aThomas Grafint nla_padlen(int payload) 43244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 43344d362409d5469aed47d19e7908d19bd194493aThomas Graf return nla_total_size(payload) - nla_attr_size(payload); 43444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 43544d362409d5469aed47d19e7908d19bd194493aThomas Graf 43644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 43744d362409d5469aed47d19e7908d19bd194493aThomas Graf 43844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 439dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @name Parsing Attributes 44044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 44144d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 44244d362409d5469aed47d19e7908d19bd194493aThomas Graf 44344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 444dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Return type of the attribute. 445dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla Attribute. 446dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 447dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return Type of attribute. 44844d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 44944d362409d5469aed47d19e7908d19bd194493aThomas Grafint nla_type(const struct nlattr *nla) 45044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 45144d362409d5469aed47d19e7908d19bd194493aThomas Graf return nla->nla_type & NLA_TYPE_MASK; 45244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 45344d362409d5469aed47d19e7908d19bd194493aThomas Graf 45444d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 455dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Return pointer to the payload section. 456dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla Attribute. 457dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 458dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return Pointer to start of payload section. 45944d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 46044d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid *nla_data(const struct nlattr *nla) 46144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 46244d362409d5469aed47d19e7908d19bd194493aThomas Graf return (char *) nla + NLA_HDRLEN; 46344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 46444d362409d5469aed47d19e7908d19bd194493aThomas Graf 46544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 466dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Return length of the payload . 467dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla Attribute 468dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 469dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return Length of payload in bytes. 47044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 47144d362409d5469aed47d19e7908d19bd194493aThomas Grafint nla_len(const struct nlattr *nla) 47244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 47344d362409d5469aed47d19e7908d19bd194493aThomas Graf return nla->nla_len - NLA_HDRLEN; 47444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 47544d362409d5469aed47d19e7908d19bd194493aThomas Graf 47644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 477dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Check if the attribute header and payload can be accessed safely. 478dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla Attribute of any kind. 479dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg remaining Number of bytes remaining in attribute stream. 480dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 481dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Verifies that the header and payload do not exceed the number of 482dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * bytes left in the attribute stream. This function must be called 483dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * before access the attribute header or payload when iterating over 484dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * the attribute stream using nla_next(). 485dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 486dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return True if the attribute can be accessed safely, false otherwise. 48744d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 48844d362409d5469aed47d19e7908d19bd194493aThomas Grafint nla_ok(const struct nlattr *nla, int remaining) 48944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 49044d362409d5469aed47d19e7908d19bd194493aThomas Graf return remaining >= sizeof(*nla) && 49144d362409d5469aed47d19e7908d19bd194493aThomas Graf nla->nla_len >= sizeof(*nla) && 49244d362409d5469aed47d19e7908d19bd194493aThomas Graf nla->nla_len <= remaining; 49344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 49444d362409d5469aed47d19e7908d19bd194493aThomas Graf 49544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 496dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Return next attribute in a stream of attributes. 497dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla Attribute of any kind. 498dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg remaining Variable to count remaining bytes in stream. 499dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 500dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Calculates the offset to the next attribute based on the attribute 501dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * given. The attribute provided is assumed to be accessible, the 502dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * caller is responsible to use nla_ok() beforehand. The offset (length 503dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * of specified attribute including padding) is then subtracted from 504dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * the remaining bytes variable and a pointer to the next attribute is 505dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * returned. 506dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 507dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nla_next() can be called as long as remainig is >0. 50844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 509dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return Pointer to next attribute. 51044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 51144d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nlattr *nla_next(const struct nlattr *nla, int *remaining) 51244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 51344d362409d5469aed47d19e7908d19bd194493aThomas Graf int totlen = NLA_ALIGN(nla->nla_len); 51444d362409d5469aed47d19e7908d19bd194493aThomas Graf 51544d362409d5469aed47d19e7908d19bd194493aThomas Graf *remaining -= totlen; 51644d362409d5469aed47d19e7908d19bd194493aThomas Graf return (struct nlattr *) ((char *) nla + totlen); 51744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 51844d362409d5469aed47d19e7908d19bd194493aThomas Graf 51944d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic uint16_t nla_attr_minlen[NLA_TYPE_MAX+1] = { 52044d362409d5469aed47d19e7908d19bd194493aThomas Graf [NLA_U8] = sizeof(uint8_t), 52144d362409d5469aed47d19e7908d19bd194493aThomas Graf [NLA_U16] = sizeof(uint16_t), 52244d362409d5469aed47d19e7908d19bd194493aThomas Graf [NLA_U32] = sizeof(uint32_t), 52344d362409d5469aed47d19e7908d19bd194493aThomas Graf [NLA_U64] = sizeof(uint64_t), 52444d362409d5469aed47d19e7908d19bd194493aThomas Graf [NLA_STRING] = 1, 52544d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 52644d362409d5469aed47d19e7908d19bd194493aThomas Graf 52744d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int validate_nla(struct nlattr *nla, int maxtype, 52844d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nla_policy *policy) 52944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 53044d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nla_policy *pt; 53144d362409d5469aed47d19e7908d19bd194493aThomas Graf int minlen = 0, type = nla_type(nla); 53244d362409d5469aed47d19e7908d19bd194493aThomas Graf 53344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (type <= 0 || type > maxtype) 53444d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 53544d362409d5469aed47d19e7908d19bd194493aThomas Graf 53644d362409d5469aed47d19e7908d19bd194493aThomas Graf pt = &policy[type]; 53744d362409d5469aed47d19e7908d19bd194493aThomas Graf 53844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (pt->type > NLA_TYPE_MAX) 53944d362409d5469aed47d19e7908d19bd194493aThomas Graf BUG(); 54044d362409d5469aed47d19e7908d19bd194493aThomas Graf 54144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (pt->minlen) 54244d362409d5469aed47d19e7908d19bd194493aThomas Graf minlen = pt->minlen; 54344d362409d5469aed47d19e7908d19bd194493aThomas Graf else if (pt->type != NLA_UNSPEC) 54444d362409d5469aed47d19e7908d19bd194493aThomas Graf minlen = nla_attr_minlen[pt->type]; 54544d362409d5469aed47d19e7908d19bd194493aThomas Graf 54644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (pt->type == NLA_FLAG && nla_len(nla) > 0) 5478a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_RANGE; 54844d362409d5469aed47d19e7908d19bd194493aThomas Graf 54944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (nla_len(nla) < minlen) 5508a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_RANGE; 55144d362409d5469aed47d19e7908d19bd194493aThomas Graf 55244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (pt->maxlen && nla_len(nla) > pt->maxlen) 5538a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_RANGE; 55444d362409d5469aed47d19e7908d19bd194493aThomas Graf 55544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (pt->type == NLA_STRING) { 55644d362409d5469aed47d19e7908d19bd194493aThomas Graf char *data = nla_data(nla); 55744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (data[nla_len(nla) - 1] != '\0') 5588a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_INVAL; 55944d362409d5469aed47d19e7908d19bd194493aThomas Graf } 56044d362409d5469aed47d19e7908d19bd194493aThomas Graf 56144d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 56244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 56344d362409d5469aed47d19e7908d19bd194493aThomas Graf 56444d362409d5469aed47d19e7908d19bd194493aThomas Graf 56544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 566dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Create attribute index based on a stream of attributes. 567dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg tb Index array to be filled (maxtype+1 elements). 568dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg maxtype Maximum attribute type expected and accepted. 569dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg head Head of attribute stream. 570dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg len Length of attribute stream. 571dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg policy Attribute validation policy. 57244d362409d5469aed47d19e7908d19bd194493aThomas Graf * 573dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Iterates over the stream of attributes and stores a pointer to each 574dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * attribute in the index array using the attribute type as index to 575dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * the array. Attribute with a type greater than the maximum type 576dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * specified will be silently ignored in order to maintain backwards 577dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * compatibility. If \a policy is not NULL, the attribute will be 578dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * validated using the specified policy. 57944d362409d5469aed47d19e7908d19bd194493aThomas Graf * 580dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @see nla_validate 58144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code. 58244d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 58344d362409d5469aed47d19e7908d19bd194493aThomas Grafint nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len, 58444d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nla_policy *policy) 58544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 58644d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nlattr *nla; 58744d362409d5469aed47d19e7908d19bd194493aThomas Graf int rem, err; 58844d362409d5469aed47d19e7908d19bd194493aThomas Graf 58944d362409d5469aed47d19e7908d19bd194493aThomas Graf memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1)); 59044d362409d5469aed47d19e7908d19bd194493aThomas Graf 59144d362409d5469aed47d19e7908d19bd194493aThomas Graf nla_for_each_attr(nla, head, len, rem) { 59244d362409d5469aed47d19e7908d19bd194493aThomas Graf int type = nla_type(nla); 59344d362409d5469aed47d19e7908d19bd194493aThomas Graf 59444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (type == 0) { 59544d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(stderr, "Illegal nla->nla_type == 0\n"); 59644d362409d5469aed47d19e7908d19bd194493aThomas Graf continue; 59744d362409d5469aed47d19e7908d19bd194493aThomas Graf } 59844d362409d5469aed47d19e7908d19bd194493aThomas Graf 59944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (type <= maxtype) { 60044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (policy) { 60144d362409d5469aed47d19e7908d19bd194493aThomas Graf err = validate_nla(nla, maxtype, policy); 60244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 60344d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 60444d362409d5469aed47d19e7908d19bd194493aThomas Graf } 60544d362409d5469aed47d19e7908d19bd194493aThomas Graf 60644d362409d5469aed47d19e7908d19bd194493aThomas Graf tb[type] = nla; 60744d362409d5469aed47d19e7908d19bd194493aThomas Graf } 60844d362409d5469aed47d19e7908d19bd194493aThomas Graf } 60944d362409d5469aed47d19e7908d19bd194493aThomas Graf 61044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (rem > 0) 61144d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(stderr, "netlink: %d bytes leftover after parsing " 61244d362409d5469aed47d19e7908d19bd194493aThomas Graf "attributes.\n", rem); 61344d362409d5469aed47d19e7908d19bd194493aThomas Graf 61444d362409d5469aed47d19e7908d19bd194493aThomas Graf err = 0; 61544d362409d5469aed47d19e7908d19bd194493aThomas Graferrout: 61644d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 61744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 61844d362409d5469aed47d19e7908d19bd194493aThomas Graf 61944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 620dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Validate a stream of attributes. 621dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg head Head of attributes stream. 622dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg len Length of attributes stream. 623dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg maxtype Maximum attribute type expected and accepted. 624dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg policy Validation policy. 62544d362409d5469aed47d19e7908d19bd194493aThomas Graf * 626dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Iterates over the stream of attributes and validates each attribute 627dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * one by one using the specified policy. Attributes with a type greater 628dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * than the maximum type specified will be silently ignored in order to 629dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * maintain backwards compatibility. 63044d362409d5469aed47d19e7908d19bd194493aThomas Graf * 631dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * See \ref attr_datatypes for more details on what kind of validation 632dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * checks are performed on each attribute data type. 63344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 63444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code. 63544d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 63644d362409d5469aed47d19e7908d19bd194493aThomas Grafint nla_validate(struct nlattr *head, int len, int maxtype, 63744d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nla_policy *policy) 63844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 63944d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nlattr *nla; 64044d362409d5469aed47d19e7908d19bd194493aThomas Graf int rem, err; 64144d362409d5469aed47d19e7908d19bd194493aThomas Graf 64244d362409d5469aed47d19e7908d19bd194493aThomas Graf nla_for_each_attr(nla, head, len, rem) { 64344d362409d5469aed47d19e7908d19bd194493aThomas Graf err = validate_nla(nla, maxtype, policy); 64444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 64544d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 64644d362409d5469aed47d19e7908d19bd194493aThomas Graf } 64744d362409d5469aed47d19e7908d19bd194493aThomas Graf 64844d362409d5469aed47d19e7908d19bd194493aThomas Graf err = 0; 64944d362409d5469aed47d19e7908d19bd194493aThomas Graferrout: 65044d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 65144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 65244d362409d5469aed47d19e7908d19bd194493aThomas Graf 65344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 654dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Find a single attribute in a stream of attributes. 655dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg head Head of attributes stream. 656dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg len Length of attributes stream. 657dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg attrtype Attribute type to look for. 65844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 659dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Iterates over the stream of attributes and compares each type with 660dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * the type specified. Returns the first attribute which matches the 661dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * type. 662dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 663dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return Pointer to attribute found or NULL. 66444d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 66544d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nlattr *nla_find(struct nlattr *head, int len, int attrtype) 66644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 66744d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nlattr *nla; 66844d362409d5469aed47d19e7908d19bd194493aThomas Graf int rem; 66944d362409d5469aed47d19e7908d19bd194493aThomas Graf 67044d362409d5469aed47d19e7908d19bd194493aThomas Graf nla_for_each_attr(nla, head, len, rem) 67144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (nla_type(nla) == attrtype) 67244d362409d5469aed47d19e7908d19bd194493aThomas Graf return nla; 67344d362409d5469aed47d19e7908d19bd194493aThomas Graf 67444d362409d5469aed47d19e7908d19bd194493aThomas Graf return NULL; 67544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 67644d362409d5469aed47d19e7908d19bd194493aThomas Graf 67744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 67844d362409d5469aed47d19e7908d19bd194493aThomas Graf 67944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 680dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @name Helper Functions 68144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 68244d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 68344d362409d5469aed47d19e7908d19bd194493aThomas Graf 68444d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 685dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Copy attribute payload to another memory area. 686dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg dest Pointer to destination memory area. 687dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg src Attribute 688dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg count Number of bytes to copy at most. 68944d362409d5469aed47d19e7908d19bd194493aThomas Graf * 69044d362409d5469aed47d19e7908d19bd194493aThomas Graf * Note: The number of bytes copied is limited by the length of 691dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * the attribute payload. 69244d362409d5469aed47d19e7908d19bd194493aThomas Graf * 693dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return The number of bytes copied to dest. 69444d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 69544d362409d5469aed47d19e7908d19bd194493aThomas Grafint nla_memcpy(void *dest, struct nlattr *src, int count) 69644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 69744d362409d5469aed47d19e7908d19bd194493aThomas Graf int minlen; 69844d362409d5469aed47d19e7908d19bd194493aThomas Graf 69944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!src) 70044d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 70144d362409d5469aed47d19e7908d19bd194493aThomas Graf 70244d362409d5469aed47d19e7908d19bd194493aThomas Graf minlen = min_t(int, count, nla_len(src)); 70344d362409d5469aed47d19e7908d19bd194493aThomas Graf memcpy(dest, nla_data(src), minlen); 70444d362409d5469aed47d19e7908d19bd194493aThomas Graf 70544d362409d5469aed47d19e7908d19bd194493aThomas Graf return minlen; 70644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 70744d362409d5469aed47d19e7908d19bd194493aThomas Graf 70844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 709dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Copy string attribute payload to a buffer. 710dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg dst Pointer to destination buffer. 711dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla Attribute of type NLA_STRING. 712dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg dstsize Size of destination buffer in bytes. 71344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 714dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Copies at most dstsize - 1 bytes to the destination buffer. 715dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * The result is always a valid NUL terminated string. Unlike 71644d362409d5469aed47d19e7908d19bd194493aThomas Graf * strlcpy the destination buffer is always padded out. 71744d362409d5469aed47d19e7908d19bd194493aThomas Graf * 718dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return The length of string attribute without the terminating NUL. 71944d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 72044d362409d5469aed47d19e7908d19bd194493aThomas Grafsize_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize) 72144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 72244d362409d5469aed47d19e7908d19bd194493aThomas Graf size_t srclen = nla_len(nla); 72344d362409d5469aed47d19e7908d19bd194493aThomas Graf char *src = nla_data(nla); 72444d362409d5469aed47d19e7908d19bd194493aThomas Graf 72544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (srclen > 0 && src[srclen - 1] == '\0') 72644d362409d5469aed47d19e7908d19bd194493aThomas Graf srclen--; 72744d362409d5469aed47d19e7908d19bd194493aThomas Graf 72844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (dstsize > 0) { 72944d362409d5469aed47d19e7908d19bd194493aThomas Graf size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen; 73044d362409d5469aed47d19e7908d19bd194493aThomas Graf 73144d362409d5469aed47d19e7908d19bd194493aThomas Graf memset(dst, 0, dstsize); 73244d362409d5469aed47d19e7908d19bd194493aThomas Graf memcpy(dst, src, len); 73344d362409d5469aed47d19e7908d19bd194493aThomas Graf } 73444d362409d5469aed47d19e7908d19bd194493aThomas Graf 73544d362409d5469aed47d19e7908d19bd194493aThomas Graf return srclen; 73644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 73744d362409d5469aed47d19e7908d19bd194493aThomas Graf 73844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 739dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Compare attribute payload with memory area. 740dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla Attribute. 741dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg data Memory area to compare to. 742dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg size Number of bytes to compare. 743dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 744dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @see memcmp(3) 745dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return An integer less than, equal to, or greater than zero. 74644d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 747dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafint nla_memcmp(const struct nlattr *nla, const void *data, size_t size) 74844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 74944d362409d5469aed47d19e7908d19bd194493aThomas Graf int d = nla_len(nla) - size; 75044d362409d5469aed47d19e7908d19bd194493aThomas Graf 75144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (d == 0) 75244d362409d5469aed47d19e7908d19bd194493aThomas Graf d = memcmp(nla_data(nla), data, size); 75344d362409d5469aed47d19e7908d19bd194493aThomas Graf 75444d362409d5469aed47d19e7908d19bd194493aThomas Graf return d; 75544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 75644d362409d5469aed47d19e7908d19bd194493aThomas Graf 75744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 758dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Compare string attribute payload with string 759dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla Attribute of type NLA_STRING. 760dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg str NUL terminated string. 761dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 762dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @see strcmp(3) 763dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return An integer less than, equal to, or greater than zero. 76444d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 76544d362409d5469aed47d19e7908d19bd194493aThomas Grafint nla_strcmp(const struct nlattr *nla, const char *str) 76644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 76744d362409d5469aed47d19e7908d19bd194493aThomas Graf int len = strlen(str) + 1; 76844d362409d5469aed47d19e7908d19bd194493aThomas Graf int d = nla_len(nla) - len; 76944d362409d5469aed47d19e7908d19bd194493aThomas Graf 77044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (d == 0) 77144d362409d5469aed47d19e7908d19bd194493aThomas Graf d = memcmp(nla_data(nla), str, len); 77244d362409d5469aed47d19e7908d19bd194493aThomas Graf 77344d362409d5469aed47d19e7908d19bd194493aThomas Graf return d; 77444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 77544d362409d5469aed47d19e7908d19bd194493aThomas Graf 77644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 77744d362409d5469aed47d19e7908d19bd194493aThomas Graf 77844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 779dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @name Unspecific Attribute 78044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 78144d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 78244d362409d5469aed47d19e7908d19bd194493aThomas Graf 78344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 784dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Reserve space for a attribute. 785dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg msg Netlink Message. 786dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg attrtype Attribute Type. 787dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg attrlen Length of payload. 788dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 789dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Reserves room for a attribute in the specified netlink message and 790dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * fills in the attribute header (type, length). Returns NULL if there 791dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * is unsuficient space for the attribute. 79244d362409d5469aed47d19e7908d19bd194493aThomas Graf * 793dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Any padding between payload and the start of the next attribute is 794dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * zeroed out. 795dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 796dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return Pointer to start of attribute or NULL on failure. 79744d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 798dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafstruct nlattr *nla_reserve(struct nl_msg *msg, int attrtype, int attrlen) 79944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 80044d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nlattr *nla; 80144d362409d5469aed47d19e7908d19bd194493aThomas Graf int tlen; 80244d362409d5469aed47d19e7908d19bd194493aThomas Graf 803dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf tlen = NLMSG_ALIGN(msg->nm_nlh->nlmsg_len) + nla_total_size(attrlen); 80444d362409d5469aed47d19e7908d19bd194493aThomas Graf 8058a3efffa5b3fde252675239914118664d36a2c24Thomas Graf if ((tlen + msg->nm_nlh->nlmsg_len) > msg->nm_size) 80644d362409d5469aed47d19e7908d19bd194493aThomas Graf return NULL; 80744d362409d5469aed47d19e7908d19bd194493aThomas Graf 808dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf nla = (struct nlattr *) nlmsg_tail(msg->nm_nlh); 80944d362409d5469aed47d19e7908d19bd194493aThomas Graf nla->nla_type = attrtype; 81044d362409d5469aed47d19e7908d19bd194493aThomas Graf nla->nla_len = nla_attr_size(attrlen); 81144d362409d5469aed47d19e7908d19bd194493aThomas Graf 81244d362409d5469aed47d19e7908d19bd194493aThomas Graf memset((unsigned char *) nla + nla->nla_len, 0, nla_padlen(attrlen)); 813dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf msg->nm_nlh->nlmsg_len = tlen; 81444d362409d5469aed47d19e7908d19bd194493aThomas Graf 815936c9844b0ff4aab06301f18fe31e08b1818d0a2Patrick McHardy NL_DBG(2, "msg %p: Reserved %d bytes at offset +%td for attr %d " 816dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf "nlmsg_len=%d\n", msg, attrlen, 817dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf (void *) nla - nlmsg_data(msg->nm_nlh), 818dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf attrtype, msg->nm_nlh->nlmsg_len); 81944d362409d5469aed47d19e7908d19bd194493aThomas Graf 82044d362409d5469aed47d19e7908d19bd194493aThomas Graf return nla; 82144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 82244d362409d5469aed47d19e7908d19bd194493aThomas Graf 82344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 824dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Add a unspecific attribute to netlink message. 825dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg msg Netlink message. 826dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg attrtype Attribute type. 827dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg datalen Length of data to be used as payload. 828dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg data Pointer to data to be used as attribute payload. 829dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 830dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Reserves room for a unspecific attribute and copies the provided data 831dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * into the message as payload of the attribute. Returns an error if there 832dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * is insufficient space for the attribute. 83344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 834dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @see nla_reserve 835dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return 0 on success or a negative error code. 83644d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 837dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafint nla_put(struct nl_msg *msg, int attrtype, int datalen, const void *data) 83844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 83944d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nlattr *nla; 84044d362409d5469aed47d19e7908d19bd194493aThomas Graf 841dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf nla = nla_reserve(msg, attrtype, datalen); 84244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!nla) 8438a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 84444d362409d5469aed47d19e7908d19bd194493aThomas Graf 845dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf memcpy(nla_data(nla), data, datalen); 846936c9844b0ff4aab06301f18fe31e08b1818d0a2Patrick McHardy NL_DBG(2, "msg %p: Wrote %d bytes at offset +%td for attr %d\n", 847dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf msg, datalen, (void *) nla - nlmsg_data(msg->nm_nlh), attrtype); 84844d362409d5469aed47d19e7908d19bd194493aThomas Graf 84944d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 85044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 85144d362409d5469aed47d19e7908d19bd194493aThomas Graf 85244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 853dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Add abstract data as unspecific attribute to netlink message. 854dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg msg Netlink message. 855dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg attrtype Attribute type. 856dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg data Abstract data object. 85744d362409d5469aed47d19e7908d19bd194493aThomas Graf * 858dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Equivalent to nla_put() except that the length of the payload is 859dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * derived from the abstract data object. 860dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 861dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @see nla_put 862dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return 0 on success or a negative error code. 86344d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 864dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafint nla_put_data(struct nl_msg *msg, int attrtype, struct nl_data *data) 86544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 866dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf return nla_put(msg, attrtype, nl_data_get_size(data), 867dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf nl_data_get(data)); 868dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf} 869dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf 87044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 871dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Add abstract address as unspecific attribute to netlink message. 872dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg msg Netlink message. 873dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg attrtype Attribute type. 874dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg addr Abstract address object. 875dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 876dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @see nla_put 877dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return 0 on success or a negative error code. 87844d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 879dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafint nla_put_addr(struct nl_msg *msg, int attrtype, struct nl_addr *addr) 880dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf{ 881dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf return nla_put(msg, attrtype, nl_addr_get_len(addr), 882dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf nl_addr_get_binary_addr(addr)); 883dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf} 884dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf 885dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf/** @} */ 886dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf 88744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 888dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @name Integer Attributes 889dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf */ 890dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf 891dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf/** 892dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Add 8 bit integer attribute to netlink message. 893dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg msg Netlink message. 894dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg attrtype Attribute type. 895dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg value Numeric value to store as payload. 896dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 897dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @see nla_put 898dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return 0 on success or a negative error code. 89944d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 900dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafint nla_put_u8(struct nl_msg *msg, int attrtype, uint8_t value) 90144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 902dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf return nla_put(msg, attrtype, sizeof(uint8_t), &value); 90344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 90444d362409d5469aed47d19e7908d19bd194493aThomas Graf 90544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 906dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Return value of 8 bit integer attribute. 907dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla 8 bit integer attribute 908dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 909dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return Payload as 8 bit integer. 91044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 911dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafuint8_t nla_get_u8(struct nlattr *nla) 91244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 913dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf return *(uint8_t *) nla_data(nla); 91444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 91544d362409d5469aed47d19e7908d19bd194493aThomas Graf 91644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 917dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Add 16 bit integer attribute to netlink message. 918dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg msg Netlink message. 919dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg attrtype Attribute type. 920dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg value Numeric value to store as payload. 921dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 922dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @see nla_put 923dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return 0 on success or a negative error code. 92444d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 925dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafint nla_put_u16(struct nl_msg *msg, int attrtype, uint16_t value) 92644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 927dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf return nla_put(msg, attrtype, sizeof(uint16_t), &value); 92844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 92944d362409d5469aed47d19e7908d19bd194493aThomas Graf 93044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 931dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Return payload of 16 bit integer attribute. 932dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla 16 bit integer attribute 933dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 934dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return Payload as 16 bit integer. 93544d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 936dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafuint16_t nla_get_u16(struct nlattr *nla) 93744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 938dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf return *(uint16_t *) nla_data(nla); 93944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 94044d362409d5469aed47d19e7908d19bd194493aThomas Graf 94144d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 942dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Add 32 bit integer attribute to netlink message. 943dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg msg Netlink message. 944dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg attrtype Attribute type. 945dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg value Numeric value to store as payload. 946dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 947dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @see nla_put 948dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return 0 on success or a negative error code. 94944d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 950dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafint nla_put_u32(struct nl_msg *msg, int attrtype, uint32_t value) 95144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 952dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf return nla_put(msg, attrtype, sizeof(uint32_t), &value); 95344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 95444d362409d5469aed47d19e7908d19bd194493aThomas Graf 95544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 956dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Return payload of 32 bit integer attribute. 957dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla 32 bit integer attribute. 958dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 959dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return Payload as 32 bit integer. 96044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 961dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafuint32_t nla_get_u32(struct nlattr *nla) 96244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 963dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf return *(uint32_t *) nla_data(nla); 96444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 96544d362409d5469aed47d19e7908d19bd194493aThomas Graf 96644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 967dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Add 64 bit integer attribute to netlink message. 968dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg msg Netlink message. 969dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg attrtype Attribute type. 970dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg value Numeric value to store as payload. 971dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 972dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @see nla_put 973dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return 0 on success or a negative error code. 97444d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 975dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafint nla_put_u64(struct nl_msg *msg, int attrtype, uint64_t value) 97644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 977dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf return nla_put(msg, attrtype, sizeof(uint64_t), &value); 97844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 97944d362409d5469aed47d19e7908d19bd194493aThomas Graf 98044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 981dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Return payload of u64 attribute 982dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla u64 netlink attribute 983dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 984dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return Payload as 64 bit integer. 98544d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 986dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafuint64_t nla_get_u64(struct nlattr *nla) 98744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 988dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf uint64_t tmp; 989dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf 990dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf nla_memcpy(&tmp, nla, sizeof(tmp)); 991dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf 992dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf return tmp; 99344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 99444d362409d5469aed47d19e7908d19bd194493aThomas Graf 99544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 99644d362409d5469aed47d19e7908d19bd194493aThomas Graf 99744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 998dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @name String Attribute 99944d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 100044d362409d5469aed47d19e7908d19bd194493aThomas Graf 100144d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 1002dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Add string attribute to netlink message. 1003dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg msg Netlink message. 1004dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg attrtype Attribute type. 1005dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg str NUL terminated string. 100644d362409d5469aed47d19e7908d19bd194493aThomas Graf * 1007dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @see nla_put 1008dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return 0 on success or a negative error code. 100944d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1010dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafint nla_put_string(struct nl_msg *msg, int attrtype, const char *str) 101144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 1012dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf return nla_put(msg, attrtype, strlen(str) + 1, str); 101344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 101444d362409d5469aed47d19e7908d19bd194493aThomas Graf 101544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 1016dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Return payload of string attribute. 1017dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla String attribute. 101844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 1019dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return Pointer to attribute payload. 102044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1021dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafchar *nla_get_string(struct nlattr *nla) 102244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 1023dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf return (char *) nla_data(nla); 102444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 102544d362409d5469aed47d19e7908d19bd194493aThomas Graf 1026d49018fd789d96ec3fa90e41af24fd2796bac9feThomas Grafchar *nla_strdup(struct nlattr *nla) 1027d49018fd789d96ec3fa90e41af24fd2796bac9feThomas Graf{ 1028d49018fd789d96ec3fa90e41af24fd2796bac9feThomas Graf return strdup(nla_get_string(nla)); 1029d49018fd789d96ec3fa90e41af24fd2796bac9feThomas Graf} 1030d49018fd789d96ec3fa90e41af24fd2796bac9feThomas Graf 103144d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 103244d362409d5469aed47d19e7908d19bd194493aThomas Graf 103344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 1034dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @name Flag Attribute 103544d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 103644d362409d5469aed47d19e7908d19bd194493aThomas Graf 103744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 1038dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Add flag netlink attribute to netlink message. 1039dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg msg Netlink message. 1040dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg attrtype Attribute type. 1041dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 1042dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @see nla_put 1043dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return 0 on success or a negative error code. 104444d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1045dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafint nla_put_flag(struct nl_msg *msg, int attrtype) 104644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 1047dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf return nla_put(msg, attrtype, 0, NULL); 104844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 104944d362409d5469aed47d19e7908d19bd194493aThomas Graf 105044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 1051dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Return true if flag attribute is set. 1052dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla Flag netlink attribute. 1053dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 1054dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return True if flag is set, otherwise false. 105544d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1056dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafint nla_get_flag(struct nlattr *nla) 105744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 1058dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf return !!nla; 105944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 106044d362409d5469aed47d19e7908d19bd194493aThomas Graf 1061dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf/** @} */ 1062dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf 106344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 1064dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @name Microseconds Attribute 106544d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 106644d362409d5469aed47d19e7908d19bd194493aThomas Graf 106744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 1068dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Add a msecs netlink attribute to a netlink message 1069dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg n netlink message 1070dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg attrtype attribute type 1071dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg msecs number of msecs 107244d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1073dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafint nla_put_msecs(struct nl_msg *n, int attrtype, unsigned long msecs) 107444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 1075dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf return nla_put_u64(n, attrtype, msecs); 107644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 107744d362409d5469aed47d19e7908d19bd194493aThomas Graf 107844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 1079dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Return payload of msecs attribute 1080dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla msecs netlink attribute 1081dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 1082dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return the number of milliseconds. 108344d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1084dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafunsigned long nla_get_msecs(struct nlattr *nla) 108544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 1086dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf return nla_get_u64(nla); 108744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 108844d362409d5469aed47d19e7908d19bd194493aThomas Graf 1089dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf/** @} */ 1090dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf 109144d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 1092dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @name Nested Attribute 109344d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1094dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf 1095dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf/** 1096dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Add nested attributes to netlink message. 1097dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg msg Netlink message. 1098dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg attrtype Attribute type. 1099dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nested Message containing attributes to be nested. 1100dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 1101dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Takes the attributes found in the \a nested message and appends them 1102dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * to the message \a msg nested in a container of the type \a attrtype. 1103dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * The \a nested message may not have a family specific header. 1104dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 1105dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @see nla_put 1106dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return 0 on success or a negative error code. 1107dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf */ 1108dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafint nla_put_nested(struct nl_msg *msg, int attrtype, struct nl_msg *nested) 110944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 1110dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf return nla_put(msg, attrtype, nlmsg_len(nested->nm_nlh), 1111dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf nlmsg_data(nested->nm_nlh)); 111244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 111344d362409d5469aed47d19e7908d19bd194493aThomas Graf 1114dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf 111544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 1116dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Start a new level of nested attributes. 1117dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg msg Netlink message. 1118dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg attrtype Attribute type of container. 111944d362409d5469aed47d19e7908d19bd194493aThomas Graf * 1120dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return Pointer to container attribute. 112144d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1122dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafstruct nlattr *nla_nest_start(struct nl_msg *msg, int attrtype) 112344d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 1124dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf struct nlattr *start = (struct nlattr *) nlmsg_tail(msg->nm_nlh); 1125dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf 1126dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf if (nla_put(msg, attrtype, 0, NULL) < 0) 1127dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf return NULL; 1128dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf 1129dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf return start; 113044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 113144d362409d5469aed47d19e7908d19bd194493aThomas Graf 113244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 1133dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Finalize nesting of attributes. 1134dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg msg Netlink message. 1135dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg start Container attribute as returned from nla_nest_start(). 1136dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 1137dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Corrects the container attribute header to include the appeneded attributes. 113844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 1139dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return 0 114044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1141dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafint nla_nest_end(struct nl_msg *msg, struct nlattr *start) 114244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 1143dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf start->nla_len = (unsigned char *) nlmsg_tail(msg->nm_nlh) - 1144dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf (unsigned char *) start; 1145dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf return 0; 114644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 114744d362409d5469aed47d19e7908d19bd194493aThomas Graf 114844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 1149dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Create attribute index based on nested attribute 1150dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg tb Index array to be filled (maxtype+1 elements). 1151dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg maxtype Maximum attribute type expected and accepted. 1152dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla Nested Attribute. 1153dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg policy Attribute validation policy. 1154dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 1155dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Feeds the stream of attributes nested into the specified attribute 1156dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * to nla_parse(). 115744d362409d5469aed47d19e7908d19bd194493aThomas Graf * 1158dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @see nla_parse 1159dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return 0 on success or a negative error code. 116044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1161dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafint nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, 1162dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf struct nla_policy *policy) 116344d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 1164dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy); 116544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 116644d362409d5469aed47d19e7908d19bd194493aThomas Graf 116744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 116844d362409d5469aed47d19e7908d19bd194493aThomas Graf 116944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 1170