xref: /openbmc/linux/tools/lib/bpf/nlattr.h (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
11bc38b8fSAlexei Starovoitov /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
2bbf48c18SEric Leblond 
3bbf48c18SEric Leblond /*
4bbf48c18SEric Leblond  * NETLINK      Netlink attributes
5bbf48c18SEric Leblond  *
6bbf48c18SEric Leblond  * Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
7bbf48c18SEric Leblond  */
8bbf48c18SEric Leblond 
9eff81908SAndrey Ignatov #ifndef __LIBBPF_NLATTR_H
10eff81908SAndrey Ignatov #define __LIBBPF_NLATTR_H
11bbf48c18SEric Leblond 
12bbf48c18SEric Leblond #include <stdint.h>
138bbb77b7SKumar Kartikeya Dwivedi #include <string.h>
148bbb77b7SKumar Kartikeya Dwivedi #include <errno.h>
15bbf48c18SEric Leblond #include <linux/netlink.h>
160ae64fb6SKumar Kartikeya Dwivedi #include <linux/rtnetlink.h>
17*04d58f1bSLorenzo Bianconi #include <linux/genetlink.h>
188bbb77b7SKumar Kartikeya Dwivedi 
19bbf48c18SEric Leblond /* avoid multiple definition of netlink features */
20bbf48c18SEric Leblond #define __LINUX_NETLINK_H
21bbf48c18SEric Leblond 
22bbf48c18SEric Leblond /**
23bbf48c18SEric Leblond  * Standard attribute types to specify validation policy
24bbf48c18SEric Leblond  */
25bbf48c18SEric Leblond enum {
26f04bc8a4SAndrey Ignatov 	LIBBPF_NLA_UNSPEC,	/**< Unspecified type, binary data chunk */
27f04bc8a4SAndrey Ignatov 	LIBBPF_NLA_U8,		/**< 8 bit integer */
28f04bc8a4SAndrey Ignatov 	LIBBPF_NLA_U16,		/**< 16 bit integer */
29f04bc8a4SAndrey Ignatov 	LIBBPF_NLA_U32,		/**< 32 bit integer */
30f04bc8a4SAndrey Ignatov 	LIBBPF_NLA_U64,		/**< 64 bit integer */
31f04bc8a4SAndrey Ignatov 	LIBBPF_NLA_STRING,	/**< NUL terminated character string */
32f04bc8a4SAndrey Ignatov 	LIBBPF_NLA_FLAG,	/**< Flag */
33f04bc8a4SAndrey Ignatov 	LIBBPF_NLA_MSECS,	/**< Micro seconds (64bit) */
34f04bc8a4SAndrey Ignatov 	LIBBPF_NLA_NESTED,	/**< Nested attributes */
35f04bc8a4SAndrey Ignatov 	__LIBBPF_NLA_TYPE_MAX,
36bbf48c18SEric Leblond };
37bbf48c18SEric Leblond 
38f04bc8a4SAndrey Ignatov #define LIBBPF_NLA_TYPE_MAX (__LIBBPF_NLA_TYPE_MAX - 1)
39bbf48c18SEric Leblond 
40bbf48c18SEric Leblond /**
41bbf48c18SEric Leblond  * @ingroup attr
42bbf48c18SEric Leblond  * Attribute validation policy.
43bbf48c18SEric Leblond  *
44bbf48c18SEric Leblond  * See section @core_doc{core_attr_parse,Attribute Parsing} for more details.
45bbf48c18SEric Leblond  */
46f04bc8a4SAndrey Ignatov struct libbpf_nla_policy {
47f04bc8a4SAndrey Ignatov 	/** Type of attribute or LIBBPF_NLA_UNSPEC */
48bbf48c18SEric Leblond 	uint16_t	type;
49bbf48c18SEric Leblond 
50bbf48c18SEric Leblond 	/** Minimal length of payload required */
51bbf48c18SEric Leblond 	uint16_t	minlen;
52bbf48c18SEric Leblond 
53bbf48c18SEric Leblond 	/** Maximal length of payload allowed */
54bbf48c18SEric Leblond 	uint16_t	maxlen;
55bbf48c18SEric Leblond };
56bbf48c18SEric Leblond 
570ae64fb6SKumar Kartikeya Dwivedi struct libbpf_nla_req {
580ae64fb6SKumar Kartikeya Dwivedi 	struct nlmsghdr nh;
590ae64fb6SKumar Kartikeya Dwivedi 	union {
600ae64fb6SKumar Kartikeya Dwivedi 		struct ifinfomsg ifinfo;
610ae64fb6SKumar Kartikeya Dwivedi 		struct tcmsg tc;
62*04d58f1bSLorenzo Bianconi 		struct genlmsghdr gnl;
630ae64fb6SKumar Kartikeya Dwivedi 	};
640ae64fb6SKumar Kartikeya Dwivedi 	char buf[128];
650ae64fb6SKumar Kartikeya Dwivedi };
660ae64fb6SKumar Kartikeya Dwivedi 
67bbf48c18SEric Leblond /**
68bbf48c18SEric Leblond  * @ingroup attr
69bbf48c18SEric Leblond  * Iterate over a stream of attributes
70bbf48c18SEric Leblond  * @arg pos	loop counter, set to current attribute
71bbf48c18SEric Leblond  * @arg head	head of attribute stream
72bbf48c18SEric Leblond  * @arg len	length of attribute stream
73bbf48c18SEric Leblond  * @arg rem	initialized to len, holds bytes currently remaining in stream
74bbf48c18SEric Leblond  */
75f04bc8a4SAndrey Ignatov #define libbpf_nla_for_each_attr(pos, head, len, rem) \
76bbf48c18SEric Leblond 	for (pos = head, rem = len; \
77bbf48c18SEric Leblond 	     nla_ok(pos, rem); \
78bbf48c18SEric Leblond 	     pos = nla_next(pos, &(rem)))
79bbf48c18SEric Leblond 
8036f1678dSYonghong Song /**
81f04bc8a4SAndrey Ignatov  * libbpf_nla_data - head of payload
8236f1678dSYonghong Song  * @nla: netlink attribute
8336f1678dSYonghong Song  */
libbpf_nla_data(const struct nlattr * nla)84f04bc8a4SAndrey Ignatov static inline void *libbpf_nla_data(const struct nlattr *nla)
8536f1678dSYonghong Song {
86ee62a5c6SKumar Kartikeya Dwivedi 	return (void *)nla + NLA_HDRLEN;
8736f1678dSYonghong Song }
8836f1678dSYonghong Song 
libbpf_nla_getattr_u8(const struct nlattr * nla)89f04bc8a4SAndrey Ignatov static inline uint8_t libbpf_nla_getattr_u8(const struct nlattr *nla)
9036f1678dSYonghong Song {
91f04bc8a4SAndrey Ignatov 	return *(uint8_t *)libbpf_nla_data(nla);
9236f1678dSYonghong Song }
9336f1678dSYonghong Song 
libbpf_nla_getattr_u16(const struct nlattr * nla)94*04d58f1bSLorenzo Bianconi static inline uint16_t libbpf_nla_getattr_u16(const struct nlattr *nla)
95*04d58f1bSLorenzo Bianconi {
96*04d58f1bSLorenzo Bianconi 	return *(uint16_t *)libbpf_nla_data(nla);
97*04d58f1bSLorenzo Bianconi }
98*04d58f1bSLorenzo Bianconi 
libbpf_nla_getattr_u32(const struct nlattr * nla)99f04bc8a4SAndrey Ignatov static inline uint32_t libbpf_nla_getattr_u32(const struct nlattr *nla)
10036f1678dSYonghong Song {
101f04bc8a4SAndrey Ignatov 	return *(uint32_t *)libbpf_nla_data(nla);
10236f1678dSYonghong Song }
10336f1678dSYonghong Song 
libbpf_nla_getattr_u64(const struct nlattr * nla)104*04d58f1bSLorenzo Bianconi static inline uint64_t libbpf_nla_getattr_u64(const struct nlattr *nla)
105*04d58f1bSLorenzo Bianconi {
106*04d58f1bSLorenzo Bianconi 	return *(uint64_t *)libbpf_nla_data(nla);
107*04d58f1bSLorenzo Bianconi }
108*04d58f1bSLorenzo Bianconi 
libbpf_nla_getattr_str(const struct nlattr * nla)109f04bc8a4SAndrey Ignatov static inline const char *libbpf_nla_getattr_str(const struct nlattr *nla)
11036f1678dSYonghong Song {
111f04bc8a4SAndrey Ignatov 	return (const char *)libbpf_nla_data(nla);
11236f1678dSYonghong Song }
11336f1678dSYonghong Song 
11436f1678dSYonghong Song /**
115f04bc8a4SAndrey Ignatov  * libbpf_nla_len - length of payload
11636f1678dSYonghong Song  * @nla: netlink attribute
11736f1678dSYonghong Song  */
libbpf_nla_len(const struct nlattr * nla)118f04bc8a4SAndrey Ignatov static inline int libbpf_nla_len(const struct nlattr *nla)
11936f1678dSYonghong Song {
12036f1678dSYonghong Song 	return nla->nla_len - NLA_HDRLEN;
12136f1678dSYonghong Song }
12236f1678dSYonghong Song 
123f04bc8a4SAndrey Ignatov int libbpf_nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head,
124f04bc8a4SAndrey Ignatov 		     int len, struct libbpf_nla_policy *policy);
125f04bc8a4SAndrey Ignatov int libbpf_nla_parse_nested(struct nlattr *tb[], int maxtype,
126f04bc8a4SAndrey Ignatov 			    struct nlattr *nla,
127f04bc8a4SAndrey Ignatov 			    struct libbpf_nla_policy *policy);
12836f1678dSYonghong Song 
129f04bc8a4SAndrey Ignatov int libbpf_nla_dump_errormsg(struct nlmsghdr *nlh);
130bbf48c18SEric Leblond 
nla_data(struct nlattr * nla)1318bbb77b7SKumar Kartikeya Dwivedi static inline struct nlattr *nla_data(struct nlattr *nla)
1328bbb77b7SKumar Kartikeya Dwivedi {
133ee62a5c6SKumar Kartikeya Dwivedi 	return (struct nlattr *)((void *)nla + NLA_HDRLEN);
1348bbb77b7SKumar Kartikeya Dwivedi }
1358bbb77b7SKumar Kartikeya Dwivedi 
req_tail(struct libbpf_nla_req * req)1360ae64fb6SKumar Kartikeya Dwivedi static inline struct nlattr *req_tail(struct libbpf_nla_req *req)
1378bbb77b7SKumar Kartikeya Dwivedi {
138ee62a5c6SKumar Kartikeya Dwivedi 	return (struct nlattr *)((void *)req + NLMSG_ALIGN(req->nh.nlmsg_len));
1398bbb77b7SKumar Kartikeya Dwivedi }
1408bbb77b7SKumar Kartikeya Dwivedi 
nlattr_add(struct libbpf_nla_req * req,int type,const void * data,int len)1410ae64fb6SKumar Kartikeya Dwivedi static inline int nlattr_add(struct libbpf_nla_req *req, int type,
1428bbb77b7SKumar Kartikeya Dwivedi 			     const void *data, int len)
1438bbb77b7SKumar Kartikeya Dwivedi {
1448bbb77b7SKumar Kartikeya Dwivedi 	struct nlattr *nla;
1458bbb77b7SKumar Kartikeya Dwivedi 
1460ae64fb6SKumar Kartikeya Dwivedi 	if (NLMSG_ALIGN(req->nh.nlmsg_len) + NLA_ALIGN(NLA_HDRLEN + len) > sizeof(*req))
1478bbb77b7SKumar Kartikeya Dwivedi 		return -EMSGSIZE;
1488bbb77b7SKumar Kartikeya Dwivedi 	if (!!data != !!len)
1498bbb77b7SKumar Kartikeya Dwivedi 		return -EINVAL;
1508bbb77b7SKumar Kartikeya Dwivedi 
1510ae64fb6SKumar Kartikeya Dwivedi 	nla = req_tail(req);
1528bbb77b7SKumar Kartikeya Dwivedi 	nla->nla_type = type;
1538bbb77b7SKumar Kartikeya Dwivedi 	nla->nla_len = NLA_HDRLEN + len;
1548bbb77b7SKumar Kartikeya Dwivedi 	if (data)
1558bbb77b7SKumar Kartikeya Dwivedi 		memcpy(nla_data(nla), data, len);
1560ae64fb6SKumar Kartikeya Dwivedi 	req->nh.nlmsg_len = NLMSG_ALIGN(req->nh.nlmsg_len) + NLA_ALIGN(nla->nla_len);
1578bbb77b7SKumar Kartikeya Dwivedi 	return 0;
1588bbb77b7SKumar Kartikeya Dwivedi }
1598bbb77b7SKumar Kartikeya Dwivedi 
nlattr_begin_nested(struct libbpf_nla_req * req,int type)1600ae64fb6SKumar Kartikeya Dwivedi static inline struct nlattr *nlattr_begin_nested(struct libbpf_nla_req *req, int type)
1618bbb77b7SKumar Kartikeya Dwivedi {
1628bbb77b7SKumar Kartikeya Dwivedi 	struct nlattr *tail;
1638bbb77b7SKumar Kartikeya Dwivedi 
1640ae64fb6SKumar Kartikeya Dwivedi 	tail = req_tail(req);
1650ae64fb6SKumar Kartikeya Dwivedi 	if (nlattr_add(req, type | NLA_F_NESTED, NULL, 0))
1668bbb77b7SKumar Kartikeya Dwivedi 		return NULL;
1678bbb77b7SKumar Kartikeya Dwivedi 	return tail;
1688bbb77b7SKumar Kartikeya Dwivedi }
1698bbb77b7SKumar Kartikeya Dwivedi 
nlattr_end_nested(struct libbpf_nla_req * req,struct nlattr * tail)1700ae64fb6SKumar Kartikeya Dwivedi static inline void nlattr_end_nested(struct libbpf_nla_req *req,
1710ae64fb6SKumar Kartikeya Dwivedi 				     struct nlattr *tail)
1728bbb77b7SKumar Kartikeya Dwivedi {
173ee62a5c6SKumar Kartikeya Dwivedi 	tail->nla_len = (void *)req_tail(req) - (void *)tail;
1748bbb77b7SKumar Kartikeya Dwivedi }
1758bbb77b7SKumar Kartikeya Dwivedi 
176eff81908SAndrey Ignatov #endif /* __LIBBPF_NLATTR_H */
177