8#include <linux/socket.h>
10#include <netlink/netlink.h>
11#include <netlink/utils.h>
12#include <netlink/addr.h>
13#include <netlink/attr.h>
14#include <netlink/msg.h>
16#include "nl-priv-dynamic-core/nl-core.h"
17#include "nl-aux-core/nl-core.h"
56 return NLA_HDRLEN + payload;
110 return nla->nla_type & NLA_TYPE_MASK;
121 return (
char *) nla + NLA_HDRLEN;
132 return _nla_len(nla);
147int nla_ok(
const struct nlattr *nla,
int remaining)
149 _NL_STATIC_ASSERT(
sizeof(*nla) == NLA_HDRLEN);
151 return remaining >= (int)
sizeof(*nla) &&
152 nla->nla_len >=
sizeof(*nla) &&
153 nla->nla_len <= remaining;
172struct nlattr *
nla_next(
const struct nlattr *nla,
int *remaining)
174 int totlen = NLA_ALIGN(nla->nla_len);
176 *remaining -= totlen;
177 return (
struct nlattr *) ((
char *) nla + totlen);
180static uint16_t nla_attr_minlen[NLA_TYPE_MAX+1] = {
181 [
NLA_U8] =
sizeof(uint8_t),
187 [NLA_SINT] =
sizeof(uint32_t),
188 [NLA_UINT] =
sizeof(uint32_t),
191static int validate_nla(
const struct nlattr *nla,
int maxtype,
203 if (
pt->type > NLA_TYPE_MAX)
251 memset(tb, 0,
sizeof(
struct nlattr *) * (maxtype + 1));
260 err = validate_nla(nla, maxtype, policy);
266 NL_DBG(1,
"Attribute of type %#x found multiple times in message, "
267 "previous attribute is being ignored.\n", type);
273 NL_DBG(1,
"netlink: %d bytes leftover after parsing "
274 "attributes.\n", rem);
299 const struct nlattr *nla;
303 err = validate_nla(nla, maxtype, policy);
325struct nlattr *
nla_find(
const struct nlattr *head,
int len,
int attrtype)
327 const struct nlattr *nla;
332 return (
struct nlattr*)nla;
355int nla_memcpy(
void *dest,
const struct nlattr *src,
int count)
362 minlen = _NL_MIN(count,
nla_len(src));
367 memcpy(dest,
nla_data(src), minlen);
383size_t nla_strlcpy(
char *dst,
const struct nlattr *nla,
size_t dstsize)
388 if (srclen > 0 && src[srclen - 1] ==
'\0')
392 size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen;
394 memset(dst, 0, dstsize);
395 memcpy(dst, src, len);
410int nla_memcmp(
const struct nlattr *nla,
const void *data,
size_t size)
415 d = memcmp(
nla_data(nla), data, size);
430 int len = strlen(str) + 1;
434 d = memcmp(
nla_data(nla), str, len);
461struct nlattr *
nla_reserve(
struct nl_msg *msg,
int attrtype,
int attrlen)
469 tlen = NLMSG_ALIGN(msg->nm_nlh->nlmsg_len) +
nla_total_size(attrlen);
471 if (tlen > msg->nm_size || tlen > UINT32_MAX)
474 nla = (
struct nlattr *) nlmsg_tail(msg->nm_nlh);
475 nla->nla_type = attrtype;
479 memset((
unsigned char *) nla + nla->nla_len, 0,
nla_padlen(attrlen));
480 msg->nm_nlh->nlmsg_len = tlen;
482 NL_DBG(2,
"msg %p: attr <%p> %d: Reserved %d (%d) bytes at offset +%td "
483 "nlmsg_len=%d\n", msg, nla, nla->nla_type,
485 (
char *) nla - (
char *)
nlmsg_data(msg->nm_nlh),
486 msg->nm_nlh->nlmsg_len);
505int nla_put(
struct nl_msg *msg,
int attrtype,
int datalen,
const void *data)
518 memcpy(
nla_data(nla), data, datalen);
519 NL_DBG(2,
"msg %p: attr <%p> %d: Wrote %d bytes at offset +%td\n",
520 msg, nla, nla->nla_type, datalen,
521 (
char *) nla - (
char *)
nlmsg_data(msg->nm_nlh));
539int nla_put_data(
struct nl_msg *msg,
int attrtype,
const struct nl_data *data)
554int nla_put_addr(
struct nl_msg *msg,
int attrtype,
struct nl_addr *addr)
578int nla_put_s8(
struct nl_msg *msg,
int attrtype, int8_t value)
580 return nla_put(msg, attrtype,
sizeof(int8_t), &value);
591 return *(
const int8_t *)
nla_data(nla);
603int nla_put_u8(
struct nl_msg *msg,
int attrtype, uint8_t value)
605 return nla_put(msg, attrtype,
sizeof(uint8_t), &value);
616 return *(
const uint8_t *)
nla_data(nla);
630 return nla_put(msg, attrtype,
sizeof(int16_t), &value);
641 return *(
const int16_t *)
nla_data(nla);
655 return nla_put(msg, attrtype,
sizeof(uint16_t), &value);
666 return *(
const uint16_t *)
nla_data(nla);
680 return nla_put(msg, attrtype,
sizeof(int32_t), &value);
691 return *(
const int32_t *)
nla_data(nla);
705 return nla_put(msg, attrtype,
sizeof(uint32_t), &value);
716 return *(
const uint32_t *)
nla_data(nla);
730 return nla_put(msg, attrtype,
sizeof(int64_t), &value);
743 if (nla && _nla_len(nla) >=
sizeof(tmp))
744 memcpy(&tmp,
nla_data(nla),
sizeof(tmp));
760 return nla_put(msg, attrtype,
sizeof(uint64_t), &value);
773 if (nla && _nla_len(nla) >=
sizeof(tmp))
774 memcpy(&tmp,
nla_data(nla),
sizeof(tmp));
790 int64_t tmp64 = value;
791 int32_t tmp32 = value;
795 return nla_put(msg, attrtype,
sizeof(int64_t), &value);
806 if (nla && _nla_len(nla) ==
sizeof(int32_t))
822 uint64_t tmp64 = value;
823 uint32_t tmp32 = value;
827 return nla_put(msg, attrtype,
sizeof(uint64_t), &value);
838 if (nla && _nla_len(nla) ==
sizeof(uint32_t))
860 return nla_put(msg, attrtype, strlen(str) + 1, str);
874char *nla_strdup(
const struct nlattr *nla)
895 return nla_put(msg, attrtype, 0, NULL);
957 const struct nl_msg *nested)
959 NL_DBG(2,
"msg %p: attr <> %d: adding msg %p as nested attribute\n",
960 msg, attrtype, nested);
976 struct nlattr *start = (
struct nlattr *) nlmsg_tail(msg->nm_nlh);
978 if (
nla_put(msg, NLA_F_NESTED | attrtype, 0, NULL) < 0)
981 NL_DBG(2,
"msg %p: attr <%p> %d: starting nesting\n",
982 msg, start, start->nla_type);
987static int _nest_end(
struct nl_msg *msg,
struct nlattr *start,
int keep_empty)
991 len = (
char *) nlmsg_tail(msg->nm_nlh) - (
char *) start;
994 || (!keep_empty && len == NLA_HDRLEN)) {
1002 return (len == NLA_HDRLEN) ? 0 : -NLE_ATTRSIZE;
1005 start->nla_len = len;
1007 pad = NLMSG_ALIGN(msg->nm_nlh->nlmsg_len) - msg->nm_nlh->nlmsg_len;
1018 NL_DBG(2,
"msg %p: attr <%p> %d: added %zu bytes of padding\n",
1019 msg, start, start->nla_type, pad);
1022 NL_DBG(2,
"msg %p: attr <%p> %d: closing nesting, len=%u\n",
1023 msg, start, start->nla_type, start->nla_len);
1039 return _nest_end (msg, start, 0);
1054 return _nest_end (msg, start, 1);
1079 len = (
char *) nlmsg_tail(msg->nm_nlh) - (
char *) attr;
1083 msg->nm_nlh->nlmsg_len -= len;
1084 memset(nlmsg_tail(msg->nm_nlh), 0, len);
1115 return !!(attr->nla_type & NLA_F_NESTED);
void * nl_addr_get_binary_addr(const struct nl_addr *addr)
Get binary address of abstract address object.
unsigned int nl_addr_get_len(const struct nl_addr *addr)
Get length of binary address of abstract address object.
int nla_validate(const struct nlattr *head, int len, int maxtype, const struct nla_policy *policy)
Validate a stream of attributes.
int nla_put_s16(struct nl_msg *msg, int attrtype, int16_t value)
Add 16 bit signed integer attribute to netlink message.
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
int nla_put_u16(struct nl_msg *msg, int attrtype, uint16_t value)
Add 16 bit integer attribute to netlink message.
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
int nla_strcmp(const struct nlattr *nla, const char *str)
Compare string attribute payload with string.
int nla_put_data(struct nl_msg *msg, int attrtype, const struct nl_data *data)
Add abstract data as unspecific attribute to netlink message.
int nla_put_nested(struct nl_msg *msg, int attrtype, const struct nl_msg *nested)
Add nested attributes to netlink message.
struct nlattr * nla_next(const struct nlattr *nla, int *remaining)
Return next attribute in a stream of attributes.
int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len, const struct nla_policy *policy)
Create attribute index based on a stream of attributes.
int nla_put_string(struct nl_msg *msg, int attrtype, const char *str)
Add string attribute to netlink message.
uint64_t nla_get_u64(const struct nlattr *nla)
Return payload of u64 attribute.
int nla_get_flag(const struct nlattr *nla)
Return true if flag attribute is set.
int nla_type(const struct nlattr *nla)
Return type of the attribute.
int nla_put_u64(struct nl_msg *msg, int attrtype, uint64_t value)
Add 64 bit integer attribute to netlink message.
uint64_t nla_get_uint(const struct nlattr *nla)
Return payload of variable-length unsigned integer attribute.
int nla_ok(const struct nlattr *nla, int remaining)
Check if the attribute header and payload can be accessed safely.
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
int nla_is_nested(const struct nlattr *attr)
Return true if attribute has NLA_F_NESTED flag set.
int nla_put_u32(struct nl_msg *msg, int attrtype, uint32_t value)
Add 32 bit integer attribute to netlink message.
int nla_put_addr(struct nl_msg *msg, int attrtype, struct nl_addr *addr)
Add abstract address as unspecific attribute to netlink message.
int nla_memcmp(const struct nlattr *nla, const void *data, size_t size)
Compare attribute payload with memory area.
int nla_put_uint(struct nl_msg *msg, int attrtype, uint64_t value)
Add variable-length unsigned integer attribute to netlink message.
int nla_put_s64(struct nl_msg *msg, int attrtype, int64_t value)
Add 64 bit signed integer attribute to netlink message.
#define nla_for_each_attr(pos, head, len, rem)
Iterate over a stream of attributes.
int nla_put_msecs(struct nl_msg *n, int attrtype, unsigned long msecs)
Add a msecs netlink attribute to a netlink message.
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
int nla_attr_size(int payload)
Return size of attribute whithout padding.
int16_t nla_get_s16(const struct nlattr *nla)
Return payload of 16 bit signed integer attribute.
int64_t nla_get_s64(const struct nlattr *nla)
Return payload of s64 attribute.
int nla_put_flag(struct nl_msg *msg, int attrtype)
Add flag netlink attribute to netlink message.
int nla_put_s32(struct nl_msg *msg, int attrtype, int32_t value)
Add 32 bit signed integer attribute to netlink message.
int nla_memcpy(void *dest, const struct nlattr *src, int count)
Copy attribute payload to another memory area.
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
unsigned long nla_get_msecs(const struct nlattr *nla)
Return payload of msecs attribute.
size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize)
Copy string attribute payload to a buffer.
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy)
Create attribute index based on nested attribute.
int64_t nla_get_sint(const struct nlattr *nla)
Return payload of variable-length signed integer attribute.
char * nla_get_string(const struct nlattr *nla)
Return payload of string attribute.
int32_t nla_get_s32(const struct nlattr *nla)
Return payload of 32 bit signed integer attribute.
void nla_nest_cancel(struct nl_msg *msg, const struct nlattr *attr)
Cancel the addition of a nested attribute.
int nla_len(const struct nlattr *nla)
Return length of the payload .
int nla_put_u8(struct nl_msg *msg, int attrtype, uint8_t value)
Add 8 bit integer attribute to netlink message.
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
int nla_nest_end_keep_empty(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes without stripping off empty attributes.
int8_t nla_get_s8(const struct nlattr *nla)
Return value of 8 bit signed integer attribute.
struct nlattr * nla_find(const struct nlattr *head, int len, int attrtype)
Find a single attribute in a stream of attributes.
int nla_padlen(int payload)
Return length of padding at the tail of the attribute.
int nla_put(struct nl_msg *msg, int attrtype, int datalen, const void *data)
Add a unspecific attribute to netlink message.
int nla_put_s8(struct nl_msg *msg, int attrtype, int8_t value)
Add 8 bit signed integer attribute to netlink message.
struct nlattr * nla_reserve(struct nl_msg *msg, int attrtype, int attrlen)
Reserve space for a attribute.
int nla_total_size(int payload)
Return size of attribute including padding.
int nla_put_sint(struct nl_msg *msg, int attrtype, int64_t value)
Add variable-length signed integer attribute to netlink message.
@ NLA_STRING
NUL terminated character string.
@ NLA_UNSPEC
Unspecified type, binary data chunk.
size_t nl_data_get_size(const struct nl_data *data)
Get size of data buffer of abstract data object.
void * nl_data_get(const struct nl_data *data)
Get data buffer of abstract data object.
void * nlmsg_data(const struct nlmsghdr *nlh)
Return pointer to message payload.
void * nlmsg_reserve(struct nl_msg *n, size_t len, int pad)
Reserve room for additional data in a netlink message.
int nlmsg_datalen(const struct nlmsghdr *nlh)
Return length of message payload.
Attribute validation policy.
uint16_t minlen
Minimal length of payload required.
uint16_t type
Type of attribute or NLA_UNSPEC.