1 /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
4 * NETLINK Netlink attributes
6 * Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
9 #ifndef __LIBBPF_NLATTR_H
10 #define __LIBBPF_NLATTR_H
15 #include <linux/netlink.h>
16 #include <linux/rtnetlink.h>
17 #include <linux/genetlink.h>
19 /* avoid multiple definition of netlink features */
20 #define __LINUX_NETLINK_H
23 * Standard attribute types to specify validation policy
26 LIBBPF_NLA_UNSPEC
, /**< Unspecified type, binary data chunk */
27 LIBBPF_NLA_U8
, /**< 8 bit integer */
28 LIBBPF_NLA_U16
, /**< 16 bit integer */
29 LIBBPF_NLA_U32
, /**< 32 bit integer */
30 LIBBPF_NLA_U64
, /**< 64 bit integer */
31 LIBBPF_NLA_STRING
, /**< NUL terminated character string */
32 LIBBPF_NLA_FLAG
, /**< Flag */
33 LIBBPF_NLA_MSECS
, /**< Micro seconds (64bit) */
34 LIBBPF_NLA_NESTED
, /**< Nested attributes */
35 __LIBBPF_NLA_TYPE_MAX
,
38 #define LIBBPF_NLA_TYPE_MAX (__LIBBPF_NLA_TYPE_MAX - 1)
42 * Attribute validation policy.
44 * See section @core_doc{core_attr_parse,Attribute Parsing} for more details.
46 struct libbpf_nla_policy
{
47 /** Type of attribute or LIBBPF_NLA_UNSPEC */
50 /** Minimal length of payload required */
53 /** Maximal length of payload allowed */
57 struct libbpf_nla_req
{
60 struct ifinfomsg ifinfo
;
62 struct genlmsghdr gnl
;
69 * Iterate over a stream of attributes
70 * @arg pos loop counter, set to current attribute
71 * @arg head head of attribute stream
72 * @arg len length of attribute stream
73 * @arg rem initialized to len, holds bytes currently remaining in stream
75 #define libbpf_nla_for_each_attr(pos, head, len, rem) \
76 for (pos = head, rem = len; \
78 pos = nla_next(pos, &(rem)))
81 * libbpf_nla_data - head of payload
82 * @nla: netlink attribute
84 static inline void *libbpf_nla_data(const struct nlattr
*nla
)
86 return (void *)nla
+ NLA_HDRLEN
;
89 static inline uint8_t libbpf_nla_getattr_u8(const struct nlattr
*nla
)
91 return *(uint8_t *)libbpf_nla_data(nla
);
94 static inline uint16_t libbpf_nla_getattr_u16(const struct nlattr
*nla
)
96 return *(uint16_t *)libbpf_nla_data(nla
);
99 static inline uint32_t libbpf_nla_getattr_u32(const struct nlattr
*nla
)
101 return *(uint32_t *)libbpf_nla_data(nla
);
104 static inline uint64_t libbpf_nla_getattr_u64(const struct nlattr
*nla
)
106 return *(uint64_t *)libbpf_nla_data(nla
);
109 static inline const char *libbpf_nla_getattr_str(const struct nlattr
*nla
)
111 return (const char *)libbpf_nla_data(nla
);
115 * libbpf_nla_len - length of payload
116 * @nla: netlink attribute
118 static inline int libbpf_nla_len(const struct nlattr
*nla
)
120 return nla
->nla_len
- NLA_HDRLEN
;
123 int libbpf_nla_parse(struct nlattr
*tb
[], int maxtype
, struct nlattr
*head
,
124 int len
, struct libbpf_nla_policy
*policy
);
125 int libbpf_nla_parse_nested(struct nlattr
*tb
[], int maxtype
,
127 struct libbpf_nla_policy
*policy
);
129 int libbpf_nla_dump_errormsg(struct nlmsghdr
*nlh
);
131 static inline struct nlattr
*nla_data(struct nlattr
*nla
)
133 return (struct nlattr
*)((void *)nla
+ NLA_HDRLEN
);
136 static inline struct nlattr
*req_tail(struct libbpf_nla_req
*req
)
138 return (struct nlattr
*)((void *)req
+ NLMSG_ALIGN(req
->nh
.nlmsg_len
));
141 static inline int nlattr_add(struct libbpf_nla_req
*req
, int type
,
142 const void *data
, int len
)
146 if (NLMSG_ALIGN(req
->nh
.nlmsg_len
) + NLA_ALIGN(NLA_HDRLEN
+ len
) > sizeof(*req
))
152 nla
->nla_type
= type
;
153 nla
->nla_len
= NLA_HDRLEN
+ len
;
155 memcpy(nla_data(nla
), data
, len
);
156 req
->nh
.nlmsg_len
= NLMSG_ALIGN(req
->nh
.nlmsg_len
) + NLA_ALIGN(nla
->nla_len
);
160 static inline struct nlattr
*nlattr_begin_nested(struct libbpf_nla_req
*req
, int type
)
164 tail
= req_tail(req
);
165 if (nlattr_add(req
, type
| NLA_F_NESTED
, NULL
, 0))
170 static inline void nlattr_end_nested(struct libbpf_nla_req
*req
,
173 tail
->nla_len
= (void *)req_tail(req
) - (void *)tail
;
176 #endif /* __LIBBPF_NLATTR_H */