1 /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 3 /* 4 * NETLINK Netlink attributes 5 * 6 * Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch> 7 */ 8 9 #ifndef __LIBBPF_NLATTR_H 10 #define __LIBBPF_NLATTR_H 11 12 #include <stdint.h> 13 #include <string.h> 14 #include <errno.h> 15 #include <linux/netlink.h> 16 17 /* avoid multiple definition of netlink features */ 18 #define __LINUX_NETLINK_H 19 20 /** 21 * Standard attribute types to specify validation policy 22 */ 23 enum { 24 LIBBPF_NLA_UNSPEC, /**< Unspecified type, binary data chunk */ 25 LIBBPF_NLA_U8, /**< 8 bit integer */ 26 LIBBPF_NLA_U16, /**< 16 bit integer */ 27 LIBBPF_NLA_U32, /**< 32 bit integer */ 28 LIBBPF_NLA_U64, /**< 64 bit integer */ 29 LIBBPF_NLA_STRING, /**< NUL terminated character string */ 30 LIBBPF_NLA_FLAG, /**< Flag */ 31 LIBBPF_NLA_MSECS, /**< Micro seconds (64bit) */ 32 LIBBPF_NLA_NESTED, /**< Nested attributes */ 33 __LIBBPF_NLA_TYPE_MAX, 34 }; 35 36 #define LIBBPF_NLA_TYPE_MAX (__LIBBPF_NLA_TYPE_MAX - 1) 37 38 /** 39 * @ingroup attr 40 * Attribute validation policy. 41 * 42 * See section @core_doc{core_attr_parse,Attribute Parsing} for more details. 43 */ 44 struct libbpf_nla_policy { 45 /** Type of attribute or LIBBPF_NLA_UNSPEC */ 46 uint16_t type; 47 48 /** Minimal length of payload required */ 49 uint16_t minlen; 50 51 /** Maximal length of payload allowed */ 52 uint16_t maxlen; 53 }; 54 55 /** 56 * @ingroup attr 57 * Iterate over a stream of attributes 58 * @arg pos loop counter, set to current attribute 59 * @arg head head of attribute stream 60 * @arg len length of attribute stream 61 * @arg rem initialized to len, holds bytes currently remaining in stream 62 */ 63 #define libbpf_nla_for_each_attr(pos, head, len, rem) \ 64 for (pos = head, rem = len; \ 65 nla_ok(pos, rem); \ 66 pos = nla_next(pos, &(rem))) 67 68 /** 69 * libbpf_nla_data - head of payload 70 * @nla: netlink attribute 71 */ 72 static inline void *libbpf_nla_data(const struct nlattr *nla) 73 { 74 return (char *) nla + NLA_HDRLEN; 75 } 76 77 static inline uint8_t libbpf_nla_getattr_u8(const struct nlattr *nla) 78 { 79 return *(uint8_t *)libbpf_nla_data(nla); 80 } 81 82 static inline uint32_t libbpf_nla_getattr_u32(const struct nlattr *nla) 83 { 84 return *(uint32_t *)libbpf_nla_data(nla); 85 } 86 87 static inline const char *libbpf_nla_getattr_str(const struct nlattr *nla) 88 { 89 return (const char *)libbpf_nla_data(nla); 90 } 91 92 /** 93 * libbpf_nla_len - length of payload 94 * @nla: netlink attribute 95 */ 96 static inline int libbpf_nla_len(const struct nlattr *nla) 97 { 98 return nla->nla_len - NLA_HDRLEN; 99 } 100 101 int libbpf_nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, 102 int len, struct libbpf_nla_policy *policy); 103 int libbpf_nla_parse_nested(struct nlattr *tb[], int maxtype, 104 struct nlattr *nla, 105 struct libbpf_nla_policy *policy); 106 107 int libbpf_nla_dump_errormsg(struct nlmsghdr *nlh); 108 109 static inline struct nlattr *nla_data(struct nlattr *nla) 110 { 111 return (struct nlattr *)((char *)nla + NLA_HDRLEN); 112 } 113 114 static inline struct nlattr *nh_tail(struct nlmsghdr *nh) 115 { 116 return (struct nlattr *)((char *)nh + NLMSG_ALIGN(nh->nlmsg_len)); 117 } 118 119 static inline int nlattr_add(struct nlmsghdr *nh, size_t maxsz, int type, 120 const void *data, int len) 121 { 122 struct nlattr *nla; 123 124 if (NLMSG_ALIGN(nh->nlmsg_len) + NLA_ALIGN(NLA_HDRLEN + len) > maxsz) 125 return -EMSGSIZE; 126 if (!!data != !!len) 127 return -EINVAL; 128 129 nla = nh_tail(nh); 130 nla->nla_type = type; 131 nla->nla_len = NLA_HDRLEN + len; 132 if (data) 133 memcpy(nla_data(nla), data, len); 134 nh->nlmsg_len = NLMSG_ALIGN(nh->nlmsg_len) + NLA_ALIGN(nla->nla_len); 135 return 0; 136 } 137 138 static inline struct nlattr *nlattr_begin_nested(struct nlmsghdr *nh, 139 size_t maxsz, int type) 140 { 141 struct nlattr *tail; 142 143 tail = nh_tail(nh); 144 if (nlattr_add(nh, maxsz, type | NLA_F_NESTED, NULL, 0)) 145 return NULL; 146 return tail; 147 } 148 149 static inline void nlattr_end_nested(struct nlmsghdr *nh, struct nlattr *tail) 150 { 151 tail->nla_len = (char *)nh_tail(nh) - (char *)tail; 152 } 153 154 #endif /* __LIBBPF_NLATTR_H */ 155