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 #include <errno.h> 10 #include <string.h> 11 #include <stdio.h> 12 #include <linux/rtnetlink.h> 13 #include "nlattr.h" 14 #include "libbpf_internal.h" 15 16 static uint16_t nla_attr_minlen[LIBBPF_NLA_TYPE_MAX+1] = { 17 [LIBBPF_NLA_U8] = sizeof(uint8_t), 18 [LIBBPF_NLA_U16] = sizeof(uint16_t), 19 [LIBBPF_NLA_U32] = sizeof(uint32_t), 20 [LIBBPF_NLA_U64] = sizeof(uint64_t), 21 [LIBBPF_NLA_STRING] = 1, 22 [LIBBPF_NLA_FLAG] = 0, 23 }; 24 25 static struct nlattr *nla_next(const struct nlattr *nla, int *remaining) 26 { 27 int totlen = NLA_ALIGN(nla->nla_len); 28 29 *remaining -= totlen; 30 return (struct nlattr *)((void *)nla + totlen); 31 } 32 33 static int nla_ok(const struct nlattr *nla, int remaining) 34 { 35 return remaining >= (int)sizeof(*nla) && 36 nla->nla_len >= sizeof(*nla) && 37 nla->nla_len <= remaining; 38 } 39 40 static int nla_type(const struct nlattr *nla) 41 { 42 return nla->nla_type & NLA_TYPE_MASK; 43 } 44 45 static int validate_nla(struct nlattr *nla, int maxtype, 46 struct libbpf_nla_policy *policy) 47 { 48 struct libbpf_nla_policy *pt; 49 unsigned int minlen = 0; 50 int type = nla_type(nla); 51 52 if (type < 0 || type > maxtype) 53 return 0; 54 55 pt = &policy[type]; 56 57 if (pt->type > LIBBPF_NLA_TYPE_MAX) 58 return 0; 59 60 if (pt->minlen) 61 minlen = pt->minlen; 62 else if (pt->type != LIBBPF_NLA_UNSPEC) 63 minlen = nla_attr_minlen[pt->type]; 64 65 if (libbpf_nla_len(nla) < minlen) 66 return -1; 67 68 if (pt->maxlen && libbpf_nla_len(nla) > pt->maxlen) 69 return -1; 70 71 if (pt->type == LIBBPF_NLA_STRING) { 72 char *data = libbpf_nla_data(nla); 73 74 if (data[libbpf_nla_len(nla) - 1] != '\0') 75 return -1; 76 } 77 78 return 0; 79 } 80 81 static inline int nlmsg_len(const struct nlmsghdr *nlh) 82 { 83 return nlh->nlmsg_len - NLMSG_HDRLEN; 84 } 85 86 /** 87 * Create attribute index based on a stream of attributes. 88 * @arg tb Index array to be filled (maxtype+1 elements). 89 * @arg maxtype Maximum attribute type expected and accepted. 90 * @arg head Head of attribute stream. 91 * @arg len Length of attribute stream. 92 * @arg policy Attribute validation policy. 93 * 94 * Iterates over the stream of attributes and stores a pointer to each 95 * attribute in the index array using the attribute type as index to 96 * the array. Attribute with a type greater than the maximum type 97 * specified will be silently ignored in order to maintain backwards 98 * compatibility. If \a policy is not NULL, the attribute will be 99 * validated using the specified policy. 100 * 101 * @see nla_validate 102 * @return 0 on success or a negative error code. 103 */ 104 int libbpf_nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, 105 int len, struct libbpf_nla_policy *policy) 106 { 107 struct nlattr *nla; 108 int rem, err; 109 110 memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1)); 111 112 libbpf_nla_for_each_attr(nla, head, len, rem) { 113 int type = nla_type(nla); 114 115 if (type > maxtype) 116 continue; 117 118 if (policy) { 119 err = validate_nla(nla, maxtype, policy); 120 if (err < 0) 121 goto errout; 122 } 123 124 if (tb[type]) 125 pr_warn("Attribute of type %#x found multiple times in message, " 126 "previous attribute is being ignored.\n", type); 127 128 tb[type] = nla; 129 } 130 131 err = 0; 132 errout: 133 return err; 134 } 135 136 /** 137 * Create attribute index based on nested attribute 138 * @arg tb Index array to be filled (maxtype+1 elements). 139 * @arg maxtype Maximum attribute type expected and accepted. 140 * @arg nla Nested Attribute. 141 * @arg policy Attribute validation policy. 142 * 143 * Feeds the stream of attributes nested into the specified attribute 144 * to libbpf_nla_parse(). 145 * 146 * @see libbpf_nla_parse 147 * @return 0 on success or a negative error code. 148 */ 149 int libbpf_nla_parse_nested(struct nlattr *tb[], int maxtype, 150 struct nlattr *nla, 151 struct libbpf_nla_policy *policy) 152 { 153 return libbpf_nla_parse(tb, maxtype, libbpf_nla_data(nla), 154 libbpf_nla_len(nla), policy); 155 } 156 157 /* dump netlink extended ack error message */ 158 int libbpf_nla_dump_errormsg(struct nlmsghdr *nlh) 159 { 160 struct libbpf_nla_policy extack_policy[NLMSGERR_ATTR_MAX + 1] = { 161 [NLMSGERR_ATTR_MSG] = { .type = LIBBPF_NLA_STRING }, 162 [NLMSGERR_ATTR_OFFS] = { .type = LIBBPF_NLA_U32 }, 163 }; 164 struct nlattr *tb[NLMSGERR_ATTR_MAX + 1], *attr; 165 struct nlmsgerr *err; 166 char *errmsg = NULL; 167 int hlen, alen; 168 169 /* no TLVs, nothing to do here */ 170 if (!(nlh->nlmsg_flags & NLM_F_ACK_TLVS)) 171 return 0; 172 173 err = (struct nlmsgerr *)NLMSG_DATA(nlh); 174 hlen = sizeof(*err); 175 176 /* if NLM_F_CAPPED is set then the inner err msg was capped */ 177 if (!(nlh->nlmsg_flags & NLM_F_CAPPED)) 178 hlen += nlmsg_len(&err->msg); 179 180 attr = (struct nlattr *) ((void *) err + hlen); 181 alen = (void *)nlh + nlh->nlmsg_len - (void *)attr; 182 183 if (libbpf_nla_parse(tb, NLMSGERR_ATTR_MAX, attr, alen, 184 extack_policy) != 0) { 185 pr_warn("Failed to parse extended error attributes\n"); 186 return 0; 187 } 188 189 if (tb[NLMSGERR_ATTR_MSG]) 190 errmsg = (char *) libbpf_nla_data(tb[NLMSGERR_ATTR_MSG]); 191 192 pr_warn("Kernel error message: %s\n", errmsg); 193 194 return 0; 195 } 196
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.