Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.18-rc5 327 lines 8.1 kB view raw
1/* 2 * NETLINK Netlink attributes 3 * 4 * Authors: Thomas Graf <tgraf@suug.ch> 5 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> 6 */ 7 8#include <linux/module.h> 9#include <linux/kernel.h> 10#include <linux/errno.h> 11#include <linux/jiffies.h> 12#include <linux/netdevice.h> 13#include <linux/skbuff.h> 14#include <linux/string.h> 15#include <linux/types.h> 16#include <net/netlink.h> 17 18static u16 nla_attr_minlen[NLA_TYPE_MAX+1] __read_mostly = { 19 [NLA_U8] = sizeof(u8), 20 [NLA_U16] = sizeof(u16), 21 [NLA_U32] = sizeof(u32), 22 [NLA_U64] = sizeof(u64), 23 [NLA_STRING] = 1, 24 [NLA_NESTED] = NLA_HDRLEN, 25}; 26 27static int validate_nla(struct nlattr *nla, int maxtype, 28 struct nla_policy *policy) 29{ 30 struct nla_policy *pt; 31 int minlen = 0; 32 33 if (nla->nla_type <= 0 || nla->nla_type > maxtype) 34 return 0; 35 36 pt = &policy[nla->nla_type]; 37 38 BUG_ON(pt->type > NLA_TYPE_MAX); 39 40 if (pt->minlen) 41 minlen = pt->minlen; 42 else if (pt->type != NLA_UNSPEC) 43 minlen = nla_attr_minlen[pt->type]; 44 45 if (pt->type == NLA_FLAG && nla_len(nla) > 0) 46 return -ERANGE; 47 48 if (nla_len(nla) < minlen) 49 return -ERANGE; 50 51 return 0; 52} 53 54/** 55 * nla_validate - Validate a stream of attributes 56 * @head: head of attribute stream 57 * @len: length of attribute stream 58 * @maxtype: maximum attribute type to be expected 59 * @policy: validation policy 60 * 61 * Validates all attributes in the specified attribute stream against the 62 * specified policy. Attributes with a type exceeding maxtype will be 63 * ignored. See documenation of struct nla_policy for more details. 64 * 65 * Returns 0 on success or a negative error code. 66 */ 67int nla_validate(struct nlattr *head, int len, int maxtype, 68 struct nla_policy *policy) 69{ 70 struct nlattr *nla; 71 int rem, err; 72 73 nla_for_each_attr(nla, head, len, rem) { 74 err = validate_nla(nla, maxtype, policy); 75 if (err < 0) 76 goto errout; 77 } 78 79 err = 0; 80errout: 81 return err; 82} 83 84/** 85 * nla_parse - Parse a stream of attributes into a tb buffer 86 * @tb: destination array with maxtype+1 elements 87 * @maxtype: maximum attribute type to be expected 88 * @head: head of attribute stream 89 * @len: length of attribute stream 90 * 91 * Parses a stream of attributes and stores a pointer to each attribute in 92 * the tb array accessable via the attribute type. Attributes with a type 93 * exceeding maxtype will be silently ignored for backwards compatibility 94 * reasons. policy may be set to NULL if no validation is required. 95 * 96 * Returns 0 on success or a negative error code. 97 */ 98int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len, 99 struct nla_policy *policy) 100{ 101 struct nlattr *nla; 102 int rem, err; 103 104 memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1)); 105 106 nla_for_each_attr(nla, head, len, rem) { 107 u16 type = nla->nla_type; 108 109 if (type > 0 && type <= maxtype) { 110 if (policy) { 111 err = validate_nla(nla, maxtype, policy); 112 if (err < 0) 113 goto errout; 114 } 115 116 tb[type] = nla; 117 } 118 } 119 120 if (unlikely(rem > 0)) 121 printk(KERN_WARNING "netlink: %d bytes leftover after parsing " 122 "attributes.\n", rem); 123 124 err = 0; 125errout: 126 return err; 127} 128 129/** 130 * nla_find - Find a specific attribute in a stream of attributes 131 * @head: head of attribute stream 132 * @len: length of attribute stream 133 * @attrtype: type of attribute to look for 134 * 135 * Returns the first attribute in the stream matching the specified type. 136 */ 137struct nlattr *nla_find(struct nlattr *head, int len, int attrtype) 138{ 139 struct nlattr *nla; 140 int rem; 141 142 nla_for_each_attr(nla, head, len, rem) 143 if (nla->nla_type == attrtype) 144 return nla; 145 146 return NULL; 147} 148 149/** 150 * nla_strlcpy - Copy string attribute payload into a sized buffer 151 * @dst: where to copy the string to 152 * @src: attribute to copy the string from 153 * @dstsize: size of destination buffer 154 * 155 * Copies at most dstsize - 1 bytes into the destination buffer. 156 * The result is always a valid NUL-terminated string. Unlike 157 * strlcpy the destination buffer is always padded out. 158 * 159 * Returns the length of the source buffer. 160 */ 161size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize) 162{ 163 size_t srclen = nla_len(nla); 164 char *src = nla_data(nla); 165 166 if (srclen > 0 && src[srclen - 1] == '\0') 167 srclen--; 168 169 if (dstsize > 0) { 170 size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen; 171 172 memset(dst, 0, dstsize); 173 memcpy(dst, src, len); 174 } 175 176 return srclen; 177} 178 179/** 180 * nla_memcpy - Copy a netlink attribute into another memory area 181 * @dest: where to copy to memcpy 182 * @src: netlink attribute to copy from 183 * @count: size of the destination area 184 * 185 * Note: The number of bytes copied is limited by the length of 186 * attribute's payload. memcpy 187 * 188 * Returns the number of bytes copied. 189 */ 190int nla_memcpy(void *dest, struct nlattr *src, int count) 191{ 192 int minlen = min_t(int, count, nla_len(src)); 193 194 memcpy(dest, nla_data(src), minlen); 195 196 return minlen; 197} 198 199/** 200 * nla_memcmp - Compare an attribute with sized memory area 201 * @nla: netlink attribute 202 * @data: memory area 203 * @size: size of memory area 204 */ 205int nla_memcmp(const struct nlattr *nla, const void *data, 206 size_t size) 207{ 208 int d = nla_len(nla) - size; 209 210 if (d == 0) 211 d = memcmp(nla_data(nla), data, size); 212 213 return d; 214} 215 216/** 217 * nla_strcmp - Compare a string attribute against a string 218 * @nla: netlink string attribute 219 * @str: another string 220 */ 221int nla_strcmp(const struct nlattr *nla, const char *str) 222{ 223 int len = strlen(str) + 1; 224 int d = nla_len(nla) - len; 225 226 if (d == 0) 227 d = memcmp(nla_data(nla), str, len); 228 229 return d; 230} 231 232/** 233 * __nla_reserve - reserve room for attribute on the skb 234 * @skb: socket buffer to reserve room on 235 * @attrtype: attribute type 236 * @attrlen: length of attribute payload 237 * 238 * Adds a netlink attribute header to a socket buffer and reserves 239 * room for the payload but does not copy it. 240 * 241 * The caller is responsible to ensure that the skb provides enough 242 * tailroom for the attribute header and payload. 243 */ 244struct nlattr *__nla_reserve(struct sk_buff *skb, int attrtype, int attrlen) 245{ 246 struct nlattr *nla; 247 248 nla = (struct nlattr *) skb_put(skb, nla_total_size(attrlen)); 249 nla->nla_type = attrtype; 250 nla->nla_len = nla_attr_size(attrlen); 251 252 memset((unsigned char *) nla + nla->nla_len, 0, nla_padlen(attrlen)); 253 254 return nla; 255} 256 257/** 258 * nla_reserve - reserve room for attribute on the skb 259 * @skb: socket buffer to reserve room on 260 * @attrtype: attribute type 261 * @attrlen: length of attribute payload 262 * 263 * Adds a netlink attribute header to a socket buffer and reserves 264 * room for the payload but does not copy it. 265 * 266 * Returns NULL if the tailroom of the skb is insufficient to store 267 * the attribute header and payload. 268 */ 269struct nlattr *nla_reserve(struct sk_buff *skb, int attrtype, int attrlen) 270{ 271 if (unlikely(skb_tailroom(skb) < nla_total_size(attrlen))) 272 return NULL; 273 274 return __nla_reserve(skb, attrtype, attrlen); 275} 276 277/** 278 * __nla_put - Add a netlink attribute to a socket buffer 279 * @skb: socket buffer to add attribute to 280 * @attrtype: attribute type 281 * @attrlen: length of attribute payload 282 * @data: head of attribute payload 283 * 284 * The caller is responsible to ensure that the skb provides enough 285 * tailroom for the attribute header and payload. 286 */ 287void __nla_put(struct sk_buff *skb, int attrtype, int attrlen, 288 const void *data) 289{ 290 struct nlattr *nla; 291 292 nla = __nla_reserve(skb, attrtype, attrlen); 293 memcpy(nla_data(nla), data, attrlen); 294} 295 296 297/** 298 * nla_put - Add a netlink attribute to a socket buffer 299 * @skb: socket buffer to add attribute to 300 * @attrtype: attribute type 301 * @attrlen: length of attribute payload 302 * @data: head of attribute payload 303 * 304 * Returns -1 if the tailroom of the skb is insufficient to store 305 * the attribute header and payload. 306 */ 307int nla_put(struct sk_buff *skb, int attrtype, int attrlen, const void *data) 308{ 309 if (unlikely(skb_tailroom(skb) < nla_total_size(attrlen))) 310 return -1; 311 312 __nla_put(skb, attrtype, attrlen, data); 313 return 0; 314} 315 316 317EXPORT_SYMBOL(nla_validate); 318EXPORT_SYMBOL(nla_parse); 319EXPORT_SYMBOL(nla_find); 320EXPORT_SYMBOL(nla_strlcpy); 321EXPORT_SYMBOL(__nla_reserve); 322EXPORT_SYMBOL(nla_reserve); 323EXPORT_SYMBOL(__nla_put); 324EXPORT_SYMBOL(nla_put); 325EXPORT_SYMBOL(nla_memcpy); 326EXPORT_SYMBOL(nla_memcmp); 327EXPORT_SYMBOL(nla_strcmp);