0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef __LIBBPF_NLATTR_H
0010 #define __LIBBPF_NLATTR_H
0011
0012 #include <stdint.h>
0013 #include <string.h>
0014 #include <errno.h>
0015 #include <linux/netlink.h>
0016 #include <linux/rtnetlink.h>
0017
0018
0019 #define __LINUX_NETLINK_H
0020
0021
0022
0023
0024 enum {
0025 LIBBPF_NLA_UNSPEC,
0026 LIBBPF_NLA_U8,
0027 LIBBPF_NLA_U16,
0028 LIBBPF_NLA_U32,
0029 LIBBPF_NLA_U64,
0030 LIBBPF_NLA_STRING,
0031 LIBBPF_NLA_FLAG,
0032 LIBBPF_NLA_MSECS,
0033 LIBBPF_NLA_NESTED,
0034 __LIBBPF_NLA_TYPE_MAX,
0035 };
0036
0037 #define LIBBPF_NLA_TYPE_MAX (__LIBBPF_NLA_TYPE_MAX - 1)
0038
0039
0040
0041
0042
0043
0044
0045 struct libbpf_nla_policy {
0046
0047 uint16_t type;
0048
0049
0050 uint16_t minlen;
0051
0052
0053 uint16_t maxlen;
0054 };
0055
0056 struct libbpf_nla_req {
0057 struct nlmsghdr nh;
0058 union {
0059 struct ifinfomsg ifinfo;
0060 struct tcmsg tc;
0061 };
0062 char buf[128];
0063 };
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073 #define libbpf_nla_for_each_attr(pos, head, len, rem) \
0074 for (pos = head, rem = len; \
0075 nla_ok(pos, rem); \
0076 pos = nla_next(pos, &(rem)))
0077
0078
0079
0080
0081
0082 static inline void *libbpf_nla_data(const struct nlattr *nla)
0083 {
0084 return (void *)nla + NLA_HDRLEN;
0085 }
0086
0087 static inline uint8_t libbpf_nla_getattr_u8(const struct nlattr *nla)
0088 {
0089 return *(uint8_t *)libbpf_nla_data(nla);
0090 }
0091
0092 static inline uint32_t libbpf_nla_getattr_u32(const struct nlattr *nla)
0093 {
0094 return *(uint32_t *)libbpf_nla_data(nla);
0095 }
0096
0097 static inline const char *libbpf_nla_getattr_str(const struct nlattr *nla)
0098 {
0099 return (const char *)libbpf_nla_data(nla);
0100 }
0101
0102
0103
0104
0105
0106 static inline int libbpf_nla_len(const struct nlattr *nla)
0107 {
0108 return nla->nla_len - NLA_HDRLEN;
0109 }
0110
0111 int libbpf_nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head,
0112 int len, struct libbpf_nla_policy *policy);
0113 int libbpf_nla_parse_nested(struct nlattr *tb[], int maxtype,
0114 struct nlattr *nla,
0115 struct libbpf_nla_policy *policy);
0116
0117 int libbpf_nla_dump_errormsg(struct nlmsghdr *nlh);
0118
0119 static inline struct nlattr *nla_data(struct nlattr *nla)
0120 {
0121 return (struct nlattr *)((void *)nla + NLA_HDRLEN);
0122 }
0123
0124 static inline struct nlattr *req_tail(struct libbpf_nla_req *req)
0125 {
0126 return (struct nlattr *)((void *)req + NLMSG_ALIGN(req->nh.nlmsg_len));
0127 }
0128
0129 static inline int nlattr_add(struct libbpf_nla_req *req, int type,
0130 const void *data, int len)
0131 {
0132 struct nlattr *nla;
0133
0134 if (NLMSG_ALIGN(req->nh.nlmsg_len) + NLA_ALIGN(NLA_HDRLEN + len) > sizeof(*req))
0135 return -EMSGSIZE;
0136 if (!!data != !!len)
0137 return -EINVAL;
0138
0139 nla = req_tail(req);
0140 nla->nla_type = type;
0141 nla->nla_len = NLA_HDRLEN + len;
0142 if (data)
0143 memcpy(nla_data(nla), data, len);
0144 req->nh.nlmsg_len = NLMSG_ALIGN(req->nh.nlmsg_len) + NLA_ALIGN(nla->nla_len);
0145 return 0;
0146 }
0147
0148 static inline struct nlattr *nlattr_begin_nested(struct libbpf_nla_req *req, int type)
0149 {
0150 struct nlattr *tail;
0151
0152 tail = req_tail(req);
0153 if (nlattr_add(req, type | NLA_F_NESTED, NULL, 0))
0154 return NULL;
0155 return tail;
0156 }
0157
0158 static inline void nlattr_end_nested(struct libbpf_nla_req *req,
0159 struct nlattr *tail)
0160 {
0161 tail->nla_len = (void *)req_tail(req) - (void *)tail;
0162 }
0163
0164 #endif