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));
257 err = validate_nla(nla, maxtype, policy);
263 NL_DBG(1,
"Attribute of type %#x found multiple times in message, "
264 "previous attribute is being ignored.\n", type);
270 NL_DBG(1,
"netlink: %d bytes leftover after parsing "
271 "attributes.\n", rem);
301 err = validate_nla(nla, maxtype, policy);
323 struct nlattr *
nla_find(
struct nlattr *head,
int len,
int attrtype)
360 minlen = min_t(
int, count,
nla_len(src));
361 memcpy(dest,
nla_data(src), minlen);
378 size_t nla_strlcpy(
char *dst,
const struct nlattr *nla,
size_t dstsize)
383 if (srclen > 0 && src[srclen - 1] ==
'\0')
387 size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen;
389 memset(dst, 0, dstsize);
390 memcpy(dst, src, len);
405 int nla_memcmp(
const struct nlattr *nla,
const void *data,
size_t size)
410 d = memcmp(
nla_data(nla), data, size);
425 int len = strlen(str) + 1;
429 d = memcmp(
nla_data(nla), str, len);
456 struct nlattr *
nla_reserve(
struct nl_msg *msg,
int attrtype,
int attrlen)
461 tlen = NLMSG_ALIGN(msg->nm_nlh->nlmsg_len) +
nla_total_size(attrlen);
463 if (tlen > msg->nm_size)
466 nla = (
struct nlattr *) nlmsg_tail(msg->nm_nlh);
467 nla->nla_type = attrtype;
471 memset((
unsigned char *) nla + nla->nla_len, 0,
nla_padlen(attrlen));
472 msg->nm_nlh->nlmsg_len = tlen;
474 NL_DBG(2,
"msg %p: attr <%p> %d: Reserved %d (%d) bytes at offset +%td "
475 "nlmsg_len=%d\n", msg, nla, nla->nla_type,
478 msg->nm_nlh->nlmsg_len);
497 int 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,
527 int nla_put_data(
struct nl_msg *msg,
int attrtype,
struct nl_data *data)
542 int nla_put_addr(
struct nl_msg *msg,
int attrtype,
struct nl_addr *addr)
563 int nla_put_u8(
struct nl_msg *msg,
int attrtype, uint8_t value)
565 return nla_put(msg, attrtype,
sizeof(uint8_t), &value);
590 return nla_put(msg, attrtype,
sizeof(uint16_t), &value);
615 return nla_put(msg, attrtype,
sizeof(uint32_t), &value);
640 return nla_put(msg, attrtype,
sizeof(uint64_t), &value);
675 return nla_put(msg, attrtype, strlen(str) + 1, str);
689 char *nla_strdup(
struct nlattr *nla)
710 return nla_put(msg, attrtype, 0, NULL);
773 NL_DBG(2,
"msg %p: attr <> %d: adding msg %p as nested attribute\n",
774 msg, attrtype, nested);
790 struct nlattr *start = (
struct nlattr *) nlmsg_tail(msg->nm_nlh);
792 if (
nla_put(msg, attrtype, 0, NULL) < 0)
795 NL_DBG(2,
"msg %p: attr <%p> %d: starting nesting\n",
796 msg, start, start->nla_type);
814 len = (
void *) nlmsg_tail(msg->nm_nlh) - (
void *) start;
816 if (len == NLA_HDRLEN) {
826 start->nla_len = len;
828 pad = NLMSG_ALIGN(msg->nm_nlh->nlmsg_len) - msg->nm_nlh->nlmsg_len;
839 NL_DBG(2,
"msg %p: attr <%p> %d: added %zu bytes of padding\n",
840 msg, start, start->nla_type, pad);
843 NL_DBG(2,
"msg %p: attr <%p> %d: closing nesting, len=%u\n",
844 msg, start, start->nla_type, start->nla_len);
862 len = (
void *) nlmsg_tail(msg->nm_nlh) - (
void *) attr;
866 msg->nm_nlh->nlmsg_len -= len;
867 memset(nlmsg_tail(msg->nm_nlh), 0, len);
898 return !!(attr->nla_type & NLA_F_NESTED);