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->nla_len - NLA_HDRLEN;
147int nla_ok(
const struct nlattr *nla,
int remaining)
149 return remaining >= (int)
sizeof(*nla) &&
150 nla->nla_len >=
sizeof(*nla) &&
151 nla->nla_len <= remaining;
170struct nlattr *
nla_next(
const struct nlattr *nla,
int *remaining)
172 int totlen = NLA_ALIGN(nla->nla_len);
174 *remaining -= totlen;
175 return (
struct nlattr *) ((
char *) nla + totlen);
178static uint16_t nla_attr_minlen[NLA_TYPE_MAX+1] = {
179 [
NLA_U8] =
sizeof(uint8_t),
187static int validate_nla(
const struct nlattr *nla,
int maxtype,
194 if (type < 0 || type > maxtype)
199 if (pt->
type > NLA_TYPE_MAX)
215 if (data[
nla_len(nla) - 1] !=
'\0')
241int nla_parse(
struct nlattr *tb[],
int maxtype,
struct nlattr *head,
int len,
247 memset(tb, 0,
sizeof(
struct nlattr *) * (maxtype + 1));
256 err = validate_nla(nla, maxtype, policy);
262 NL_DBG(1,
"Attribute of type %#x found multiple times in message, "
263 "previous attribute is being ignored.\n", type);
269 NL_DBG(1,
"netlink: %d bytes leftover after parsing "
270 "attributes.\n", rem);
295 const struct nlattr *nla;
299 err = validate_nla(nla, maxtype, policy);
321struct nlattr *
nla_find(
const struct nlattr *head,
int len,
int attrtype)
323 const struct nlattr *nla;
328 return (
struct nlattr*)nla;
351int nla_memcpy(
void *dest,
const struct nlattr *src,
int count)
358 minlen = _NL_MIN(count,
nla_len(src));
363 memcpy(dest,
nla_data(src), minlen);
379size_t nla_strlcpy(
char *dst,
const struct nlattr *nla,
size_t dstsize)
384 if (srclen > 0 && src[srclen - 1] ==
'\0')
388 size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen;
390 memset(dst, 0, dstsize);
391 memcpy(dst, src, len);
406int nla_memcmp(
const struct nlattr *nla,
const void *data,
size_t size)
411 d = memcmp(
nla_data(nla), data, size);
426 int len = strlen(str) + 1;
430 d = memcmp(
nla_data(nla), str, len);
457struct nlattr *
nla_reserve(
struct nl_msg *msg,
int attrtype,
int attrlen)
465 tlen = NLMSG_ALIGN(msg->nm_nlh->nlmsg_len) +
nla_total_size(attrlen);
467 if (tlen > msg->nm_size)
470 nla = (
struct nlattr *) nlmsg_tail(msg->nm_nlh);
471 nla->nla_type = attrtype;
475 memset((
unsigned char *) nla + nla->nla_len, 0,
nla_padlen(attrlen));
476 msg->nm_nlh->nlmsg_len = tlen;
478 NL_DBG(2,
"msg %p: attr <%p> %d: Reserved %d (%d) bytes at offset +%td "
479 "nlmsg_len=%d\n", msg, nla, nla->nla_type,
481 (
char *) nla - (
char *)
nlmsg_data(msg->nm_nlh),
482 msg->nm_nlh->nlmsg_len);
501int nla_put(
struct nl_msg *msg,
int attrtype,
int datalen,
const void *data)
514 memcpy(
nla_data(nla), data, datalen);
515 NL_DBG(2,
"msg %p: attr <%p> %d: Wrote %d bytes at offset +%td\n",
516 msg, nla, nla->nla_type, datalen,
517 (
char *) nla - (
char *)
nlmsg_data(msg->nm_nlh));
535int nla_put_data(
struct nl_msg *msg,
int attrtype,
const struct nl_data *data)
550int nla_put_addr(
struct nl_msg *msg,
int attrtype,
struct nl_addr *addr)
574int nla_put_s8(
struct nl_msg *msg,
int attrtype, int8_t value)
576 return nla_put(msg, attrtype,
sizeof(int8_t), &value);
587 return *(
const int8_t *)
nla_data(nla);
599int nla_put_u8(
struct nl_msg *msg,
int attrtype, uint8_t value)
601 return nla_put(msg, attrtype,
sizeof(uint8_t), &value);
612 return *(
const uint8_t *)
nla_data(nla);
626 return nla_put(msg, attrtype,
sizeof(int16_t), &value);
637 return *(
const int16_t *)
nla_data(nla);
651 return nla_put(msg, attrtype,
sizeof(uint16_t), &value);
662 return *(
const uint16_t *)
nla_data(nla);
676 return nla_put(msg, attrtype,
sizeof(int32_t), &value);
687 return *(
const int32_t *)
nla_data(nla);
701 return nla_put(msg, attrtype,
sizeof(uint32_t), &value);
712 return *(
const uint32_t *)
nla_data(nla);
726 return nla_put(msg, attrtype,
sizeof(int64_t), &value);
739 if (nla &&
nla_len(nla) >=
sizeof(tmp))
740 memcpy(&tmp,
nla_data(nla),
sizeof(tmp));
756 return nla_put(msg, attrtype,
sizeof(uint64_t), &value);
769 if (nla &&
nla_len(nla) >=
sizeof(tmp))
770 memcpy(&tmp,
nla_data(nla),
sizeof(tmp));
792 return nla_put(msg, attrtype, strlen(str) + 1, str);
806char *nla_strdup(
const struct nlattr *nla)
827 return nla_put(msg, attrtype, 0, NULL);
889 const struct nl_msg *nested)
891 NL_DBG(2,
"msg %p: attr <> %d: adding msg %p as nested attribute\n",
892 msg, attrtype, nested);
908 struct nlattr *start = (
struct nlattr *) nlmsg_tail(msg->nm_nlh);
910 if (
nla_put(msg, NLA_F_NESTED | attrtype, 0, NULL) < 0)
913 NL_DBG(2,
"msg %p: attr <%p> %d: starting nesting\n",
914 msg, start, start->nla_type);
919static int _nest_end(
struct nl_msg *msg,
struct nlattr *start,
int keep_empty)
923 len = (
char *) nlmsg_tail(msg->nm_nlh) - (
char *) start;
926 || (!keep_empty && len == NLA_HDRLEN)) {
934 return (len == NLA_HDRLEN) ? 0 : -NLE_ATTRSIZE;
937 start->nla_len = len;
939 pad = NLMSG_ALIGN(msg->nm_nlh->nlmsg_len) - msg->nm_nlh->nlmsg_len;
950 NL_DBG(2,
"msg %p: attr <%p> %d: added %zu bytes of padding\n",
951 msg, start, start->nla_type, pad);
954 NL_DBG(2,
"msg %p: attr <%p> %d: closing nesting, len=%u\n",
955 msg, start, start->nla_type, start->nla_len);
971 return _nest_end (msg, start, 0);
986 return _nest_end (msg, start, 1);
1011 len = (
char *) nlmsg_tail(msg->nm_nlh) - (
char *) attr;
1015 msg->nm_nlh->nlmsg_len -= len;
1016 memset(nlmsg_tail(msg->nm_nlh), 0, len);
1047 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.