12 #include <netlink-private/netlink.h>
13 #include <netlink/netlink.h>
14 #include <netlink/utils.h>
15 #include <netlink/addr.h>
16 #include <netlink/attr.h>
17 #include <netlink/msg.h>
18 #include <linux/socket.h>
57 return NLA_HDRLEN + payload;
111 return nla->nla_type & NLA_TYPE_MASK;
122 return (
char *) nla + NLA_HDRLEN;
133 return nla->nla_len - NLA_HDRLEN;
148 int nla_ok(
const struct nlattr *nla,
int remaining)
150 return remaining >=
sizeof(*nla) &&
151 nla->nla_len >=
sizeof(*nla) &&
152 nla->nla_len <= remaining;
171 struct nlattr *
nla_next(
const struct nlattr *nla,
int *remaining)
173 int totlen = NLA_ALIGN(nla->nla_len);
175 *remaining -= totlen;
176 return (
struct nlattr *) ((
char *) nla + totlen);
179 static uint16_t nla_attr_minlen[NLA_TYPE_MAX+1] = {
180 [
NLA_U8] =
sizeof(uint8_t),
188 static int validate_nla(
struct nlattr *nla,
int maxtype,
195 if (type <= 0 || type > maxtype)
200 if (pt->
type > NLA_TYPE_MAX)
206 minlen = nla_attr_minlen[pt->
type];
216 if (data[
nla_len(nla) - 1] !=
'\0')
242 int nla_parse(
struct nlattr *tb[],
int maxtype,
struct nlattr *head,
int len,
248 memset(tb, 0,
sizeof(
struct nlattr *) * (maxtype + 1));
261 err = validate_nla(nla, maxtype, policy);
267 NL_DBG(1,
"Attribute of type %#x found multiple times in message, "
268 "previous attribute is being ignored.\n", type);
274 NL_DBG(1,
"netlink: %d bytes leftover after parsing "
275 "attributes.\n", rem);
305 err = validate_nla(nla, maxtype, policy);
327 struct nlattr *
nla_find(
struct nlattr *head,
int len,
int attrtype)
364 minlen = min_t(
int, count,
nla_len(src));
365 memcpy(dest,
nla_data(src), minlen);
382 size_t nla_strlcpy(
char *dst,
const struct nlattr *nla,
size_t dstsize)
387 if (srclen > 0 && src[srclen - 1] ==
'\0')
391 size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen;
393 memset(dst, 0, dstsize);
394 memcpy(dst, src, len);
409 int nla_memcmp(
const struct nlattr *nla,
const void *data,
size_t size)
414 d = memcmp(
nla_data(nla), data, size);
429 int len = strlen(str) + 1;
433 d = memcmp(
nla_data(nla), str, len);
460 struct 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_nlh->nlmsg_len) > 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,
482 msg->nm_nlh->nlmsg_len);
501 int nla_put(
struct nl_msg *msg,
int attrtype,
int datalen,
const void *data)
510 memcpy(
nla_data(nla), data, datalen);
511 NL_DBG(2,
"msg %p: attr <%p> %d: Wrote %d bytes at offset +%td\n",
512 msg, nla, nla->nla_type, datalen,
531 int nla_put_data(
struct nl_msg *msg,
int attrtype,
struct nl_data *data)
546 int nla_put_addr(
struct nl_msg *msg,
int attrtype,
struct nl_addr *addr)
567 int nla_put_u8(
struct nl_msg *msg,
int attrtype, uint8_t value)
569 return nla_put(msg, attrtype,
sizeof(uint8_t), &value);
594 return nla_put(msg, attrtype,
sizeof(uint16_t), &value);
619 return nla_put(msg, attrtype,
sizeof(uint32_t), &value);
644 return nla_put(msg, attrtype,
sizeof(uint64_t), &value);
679 return nla_put(msg, attrtype, strlen(str) + 1, str);
693 char *nla_strdup(
struct nlattr *nla)
714 return nla_put(msg, attrtype, 0, NULL);
777 NL_DBG(2,
"msg %p: attr <> %d: adding msg %p as nested attribute\n",
778 msg, attrtype, nested);
794 struct nlattr *start = (
struct nlattr *) nlmsg_tail(msg->nm_nlh);
796 if (
nla_put(msg, attrtype, 0, NULL) < 0)
799 NL_DBG(2,
"msg %p: attr <%p> %d: starting nesting\n",
800 msg, start, start->nla_type);
818 len = (
void *) nlmsg_tail(msg->nm_nlh) - (
void *) start;
820 if (len == NLA_HDRLEN) {
830 start->nla_len = len;
832 pad = NLMSG_ALIGN(msg->nm_nlh->nlmsg_len) - msg->nm_nlh->nlmsg_len;
843 NL_DBG(2,
"msg %p: attr <%p> %d: added %zu bytes of padding\n",
844 msg, start, start->nla_type, pad);
847 NL_DBG(2,
"msg %p: attr <%p> %d: closing nesting, len=%u\n",
848 msg, start, start->nla_type, start->nla_len);
866 len = (
void *) nlmsg_tail(msg->nm_nlh) - (
void *) attr;
870 msg->nm_nlh->nlmsg_len -= len;
871 memset(nlmsg_tail(msg->nm_nlh), 0, len);
902 return !!(
nla_type(attr) & NLA_F_NESTED);