6#include <netlink-private/netlink.h>
7#include <netlink/netlink.h>
8#include <netlink/utils.h>
9#include <netlink/addr.h>
10#include <netlink/attr.h>
11#include <netlink/msg.h>
12#include <linux/socket.h>
51 return NLA_HDRLEN + payload;
105 return nla->nla_type & NLA_TYPE_MASK;
116 return (
char *) nla + NLA_HDRLEN;
127 return nla->nla_len - NLA_HDRLEN;
142int nla_ok(
const struct nlattr *nla,
int remaining)
144 return remaining >= (int)
sizeof(*nla) &&
145 nla->nla_len >=
sizeof(*nla) &&
146 nla->nla_len <= remaining;
165struct nlattr *
nla_next(
const struct nlattr *nla,
int *remaining)
167 int totlen = NLA_ALIGN(nla->nla_len);
169 *remaining -= totlen;
170 return (
struct nlattr *) ((
char *) nla + totlen);
173static uint16_t nla_attr_minlen[NLA_TYPE_MAX+1] = {
174 [
NLA_U8] =
sizeof(uint8_t),
182static int validate_nla(
const struct nlattr *nla,
int maxtype,
189 if (type < 0 || type > maxtype)
194 if (pt->
type > NLA_TYPE_MAX)
210 if (data[
nla_len(nla) - 1] !=
'\0')
236int nla_parse(
struct nlattr *tb[],
int maxtype,
struct nlattr *head,
int len,
242 memset(tb, 0,
sizeof(
struct nlattr *) * (maxtype + 1));
251 err = validate_nla(nla, maxtype, policy);
257 NL_DBG(1,
"Attribute of type %#x found multiple times in message, "
258 "previous attribute is being ignored.\n", type);
264 NL_DBG(1,
"netlink: %d bytes leftover after parsing "
265 "attributes.\n", rem);
290 const struct nlattr *nla;
294 err = validate_nla(nla, maxtype, policy);
316struct nlattr *
nla_find(
const struct nlattr *head,
int len,
int attrtype)
318 const struct nlattr *nla;
323 return (
struct nlattr*)nla;
346int nla_memcpy(
void *dest,
const struct nlattr *src,
int count)
353 minlen = min_t(
int, count,
nla_len(src));
354 memcpy(dest,
nla_data(src), minlen);
371size_t nla_strlcpy(
char *dst,
const struct nlattr *nla,
size_t dstsize)
376 if (srclen > 0 && src[srclen - 1] ==
'\0')
380 size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen;
382 memset(dst, 0, dstsize);
383 memcpy(dst, src, len);
398int nla_memcmp(
const struct nlattr *nla,
const void *data,
size_t size)
403 d = memcmp(
nla_data(nla), data, size);
418 int len = strlen(str) + 1;
422 d = memcmp(
nla_data(nla), str, len);
449struct nlattr *
nla_reserve(
struct nl_msg *msg,
int attrtype,
int attrlen)
457 tlen = NLMSG_ALIGN(msg->nm_nlh->nlmsg_len) +
nla_total_size(attrlen);
459 if (tlen > msg->nm_size)
462 nla = (
struct nlattr *) nlmsg_tail(msg->nm_nlh);
463 nla->nla_type = attrtype;
467 memset((
unsigned char *) nla + nla->nla_len, 0,
nla_padlen(attrlen));
468 msg->nm_nlh->nlmsg_len = tlen;
470 NL_DBG(2,
"msg %p: attr <%p> %d: Reserved %d (%d) bytes at offset +%td "
471 "nlmsg_len=%d\n", msg, nla, nla->nla_type,
473 (
char *) nla - (
char *)
nlmsg_data(msg->nm_nlh),
474 msg->nm_nlh->nlmsg_len);
493int nla_put(
struct nl_msg *msg,
int attrtype,
int datalen,
const void *data)
506 memcpy(
nla_data(nla), data, datalen);
507 NL_DBG(2,
"msg %p: attr <%p> %d: Wrote %d bytes at offset +%td\n",
508 msg, nla, nla->nla_type, datalen,
509 (
char *) nla - (
char *)
nlmsg_data(msg->nm_nlh));
527int nla_put_data(
struct nl_msg *msg,
int attrtype,
const struct nl_data *data)
542int nla_put_addr(
struct nl_msg *msg,
int attrtype,
struct nl_addr *addr)
566int nla_put_s8(
struct nl_msg *msg,
int attrtype, int8_t value)
568 return nla_put(msg, attrtype,
sizeof(int8_t), &value);
579 return *(
const int8_t *)
nla_data(nla);
591int nla_put_u8(
struct nl_msg *msg,
int attrtype, uint8_t value)
593 return nla_put(msg, attrtype,
sizeof(uint8_t), &value);
604 return *(
const uint8_t *)
nla_data(nla);
618 return nla_put(msg, attrtype,
sizeof(int16_t), &value);
629 return *(
const int16_t *)
nla_data(nla);
643 return nla_put(msg, attrtype,
sizeof(uint16_t), &value);
654 return *(
const uint16_t *)
nla_data(nla);
668 return nla_put(msg, attrtype,
sizeof(int32_t), &value);
679 return *(
const int32_t *)
nla_data(nla);
693 return nla_put(msg, attrtype,
sizeof(uint32_t), &value);
704 return *(
const uint32_t *)
nla_data(nla);
718 return nla_put(msg, attrtype,
sizeof(int64_t), &value);
731 if (nla &&
nla_len(nla) >=
sizeof(tmp))
732 memcpy(&tmp,
nla_data(nla),
sizeof(tmp));
748 return nla_put(msg, attrtype,
sizeof(uint64_t), &value);
761 if (nla &&
nla_len(nla) >=
sizeof(tmp))
762 memcpy(&tmp,
nla_data(nla),
sizeof(tmp));
784 return nla_put(msg, attrtype, strlen(str) + 1, str);
798char *nla_strdup(
const struct nlattr *nla)
819 return nla_put(msg, attrtype, 0, NULL);
881 const struct nl_msg *nested)
883 NL_DBG(2,
"msg %p: attr <> %d: adding msg %p as nested attribute\n",
884 msg, attrtype, nested);
900 struct nlattr *start = (
struct nlattr *) nlmsg_tail(msg->nm_nlh);
902 if (
nla_put(msg, NLA_F_NESTED | attrtype, 0, NULL) < 0)
905 NL_DBG(2,
"msg %p: attr <%p> %d: starting nesting\n",
906 msg, start, start->nla_type);
911static int _nest_end(
struct nl_msg *msg,
struct nlattr *start,
int keep_empty)
915 len = (
char *) nlmsg_tail(msg->nm_nlh) - (
char *) start;
918 || (!keep_empty && len == NLA_HDRLEN)) {
926 return (len == NLA_HDRLEN) ? 0 : -NLE_ATTRSIZE;
929 start->nla_len = len;
931 pad = NLMSG_ALIGN(msg->nm_nlh->nlmsg_len) - msg->nm_nlh->nlmsg_len;
942 NL_DBG(2,
"msg %p: attr <%p> %d: added %zu bytes of padding\n",
943 msg, start, start->nla_type, pad);
946 NL_DBG(2,
"msg %p: attr <%p> %d: closing nesting, len=%u\n",
947 msg, start, start->nla_type, start->nla_len);
963 return _nest_end (msg, start, 0);
978 return _nest_end (msg, start, 1);
994 len = (
char *) nlmsg_tail(msg->nm_nlh) - (
char *) attr;
998 msg->nm_nlh->nlmsg_len -= len;
999 memset(nlmsg_tail(msg->nm_nlh), 0, len);
1030 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.
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_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.
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.
@ 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 maxlen
Maximal length of payload allowed.
uint16_t minlen
Minimal length of payload required.
uint16_t type
Type of attribute or NLA_UNSPEC.