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.28-rc3 467 lines 12 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_NESTED] = NLA_HDRLEN, 24}; 25 26static int validate_nla(struct nlattr *nla, int maxtype, 27 const struct nla_policy *policy) 28{ 29 const struct nla_policy *pt; 30 int minlen = 0, attrlen = nla_len(nla), type = nla_type(nla); 31 32 if (type <= 0 || type > maxtype) 33 return 0; 34 35 pt = &policy[type]; 36 37 BUG_ON(pt->type > NLA_TYPE_MAX); 38 39 switch (pt->type) { 40 case NLA_FLAG: 41 if (attrlen > 0) 42 return -ERANGE; 43 break; 44 45 case NLA_NUL_STRING: 46 if (pt->len) 47 minlen = min_t(int, attrlen, pt->len + 1); 48 else 49 minlen = attrlen; 50 51 if (!minlen || memchr(nla_data(nla), '\0', minlen) == NULL) 52 return -EINVAL; 53 /* fall through */ 54 55 case NLA_STRING: 56 if (attrlen < 1) 57 return -ERANGE; 58 59 if (pt->len) { 60 char *buf = nla_data(nla); 61 62 if (buf[attrlen - 1] == '\0') 63 attrlen--; 64 65 if (attrlen > pt->len) 66 return -ERANGE; 67 } 68 break; 69 70 case NLA_BINARY: 71 if (pt->len && attrlen > pt->len) 72 return -ERANGE; 73 break; 74 75 case NLA_NESTED_COMPAT: 76 if (attrlen < pt->len) 77 return -ERANGE; 78 if (attrlen < NLA_ALIGN(pt->len)) 79 break; 80 if (attrlen < NLA_ALIGN(pt->len) + NLA_HDRLEN) 81 return -ERANGE; 82 nla = nla_data(nla) + NLA_ALIGN(pt->len); 83 if (attrlen < NLA_ALIGN(pt->len) + NLA_HDRLEN + nla_len(nla)) 84 return -ERANGE; 85 break; 86 default: 87 if (pt->len) 88 minlen = pt->len; 89 else if (pt->type != NLA_UNSPEC) 90 minlen = nla_attr_minlen[pt->type]; 91 92 if (attrlen < minlen) 93 return -ERANGE; 94 } 95 96 return 0; 97} 98 99/** 100 * nla_validate - Validate a stream of attributes 101 * @head: head of attribute stream 102 * @len: length of attribute stream 103 * @maxtype: maximum attribute type to be expected 104 * @policy: validation policy 105 * 106 * Validates all attributes in the specified attribute stream against the 107 * specified policy. Attributes with a type exceeding maxtype will be 108 * ignored. See documenation of struct nla_policy for more details. 109 * 110 * Returns 0 on success or a negative error code. 111 */ 112int nla_validate(struct nlattr *head, int len, int maxtype, 113 const struct nla_policy *policy) 114{ 115 struct nlattr *nla; 116 int rem, err; 117 118 nla_for_each_attr(nla, head, len, rem) { 119 err = validate_nla(nla, maxtype, policy); 120 if (err < 0) 121 goto errout; 122 } 123 124 err = 0; 125errout: 126 return err; 127} 128 129/** 130 * nla_parse - Parse a stream of attributes into a tb buffer 131 * @tb: destination array with maxtype+1 elements 132 * @maxtype: maximum attribute type to be expected 133 * @head: head of attribute stream 134 * @len: length of attribute stream 135 * @policy: validation policy 136 * 137 * Parses a stream of attributes and stores a pointer to each attribute in 138 * the tb array accessable via the attribute type. Attributes with a type 139 * exceeding maxtype will be silently ignored for backwards compatibility 140 * reasons. policy may be set to NULL if no validation is required. 141 * 142 * Returns 0 on success or a negative error code. 143 */ 144int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len, 145 const struct nla_policy *policy) 146{ 147 struct nlattr *nla; 148 int rem, err; 149 150 memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1)); 151 152 nla_for_each_attr(nla, head, len, rem) { 153 u16 type = nla_type(nla); 154 155 if (type > 0 && type <= maxtype) { 156 if (policy) { 157 err = validate_nla(nla, maxtype, policy); 158 if (err < 0) 159 goto errout; 160 } 161 162 tb[type] = nla; 163 } 164 } 165 166 if (unlikely(rem > 0)) 167 printk(KERN_WARNING "netlink: %d bytes leftover after parsing " 168 "attributes.\n", rem); 169 170 err = 0; 171errout: 172 return err; 173} 174 175/** 176 * nla_find - Find a specific attribute in a stream of attributes 177 * @head: head of attribute stream 178 * @len: length of attribute stream 179 * @attrtype: type of attribute to look for 180 * 181 * Returns the first attribute in the stream matching the specified type. 182 */ 183struct nlattr *nla_find(struct nlattr *head, int len, int attrtype) 184{ 185 struct nlattr *nla; 186 int rem; 187 188 nla_for_each_attr(nla, head, len, rem) 189 if (nla_type(nla) == attrtype) 190 return nla; 191 192 return NULL; 193} 194 195/** 196 * nla_strlcpy - Copy string attribute payload into a sized buffer 197 * @dst: where to copy the string to 198 * @nla: attribute to copy the string from 199 * @dstsize: size of destination buffer 200 * 201 * Copies at most dstsize - 1 bytes into the destination buffer. 202 * The result is always a valid NUL-terminated string. Unlike 203 * strlcpy the destination buffer is always padded out. 204 * 205 * Returns the length of the source buffer. 206 */ 207size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize) 208{ 209 size_t srclen = nla_len(nla); 210 char *src = nla_data(nla); 211 212 if (srclen > 0 && src[srclen - 1] == '\0') 213 srclen--; 214 215 if (dstsize > 0) { 216 size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen; 217 218 memset(dst, 0, dstsize); 219 memcpy(dst, src, len); 220 } 221 222 return srclen; 223} 224 225/** 226 * nla_memcpy - Copy a netlink attribute into another memory area 227 * @dest: where to copy to memcpy 228 * @src: netlink attribute to copy from 229 * @count: size of the destination area 230 * 231 * Note: The number of bytes copied is limited by the length of 232 * attribute's payload. memcpy 233 * 234 * Returns the number of bytes copied. 235 */ 236int nla_memcpy(void *dest, struct nlattr *src, int count) 237{ 238 int minlen = min_t(int, count, nla_len(src)); 239 240 memcpy(dest, nla_data(src), minlen); 241 242 return minlen; 243} 244 245/** 246 * nla_memcmp - Compare an attribute with sized memory area 247 * @nla: netlink attribute 248 * @data: memory area 249 * @size: size of memory area 250 */ 251int nla_memcmp(const struct nlattr *nla, const void *data, 252 size_t size) 253{ 254 int d = nla_len(nla) - size; 255 256 if (d == 0) 257 d = memcmp(nla_data(nla), data, size); 258 259 return d; 260} 261 262/** 263 * nla_strcmp - Compare a string attribute against a string 264 * @nla: netlink string attribute 265 * @str: another string 266 */ 267int nla_strcmp(const struct nlattr *nla, const char *str) 268{ 269 int len = strlen(str) + 1; 270 int d = nla_len(nla) - len; 271 272 if (d == 0) 273 d = memcmp(nla_data(nla), str, len); 274 275 return d; 276} 277 278/** 279 * __nla_reserve - reserve room for attribute on the skb 280 * @skb: socket buffer to reserve room on 281 * @attrtype: attribute type 282 * @attrlen: length of attribute payload 283 * 284 * Adds a netlink attribute header to a socket buffer and reserves 285 * room for the payload but does not copy it. 286 * 287 * The caller is responsible to ensure that the skb provides enough 288 * tailroom for the attribute header and payload. 289 */ 290struct nlattr *__nla_reserve(struct sk_buff *skb, int attrtype, int attrlen) 291{ 292 struct nlattr *nla; 293 294 nla = (struct nlattr *) skb_put(skb, nla_total_size(attrlen)); 295 nla->nla_type = attrtype; 296 nla->nla_len = nla_attr_size(attrlen); 297 298 memset((unsigned char *) nla + nla->nla_len, 0, nla_padlen(attrlen)); 299 300 return nla; 301} 302 303/** 304 * __nla_reserve_nohdr - reserve room for attribute without header 305 * @skb: socket buffer to reserve room on 306 * @attrlen: length of attribute payload 307 * 308 * Reserves room for attribute payload without a header. 309 * 310 * The caller is responsible to ensure that the skb provides enough 311 * tailroom for the payload. 312 */ 313void *__nla_reserve_nohdr(struct sk_buff *skb, int attrlen) 314{ 315 void *start; 316 317 start = skb_put(skb, NLA_ALIGN(attrlen)); 318 memset(start, 0, NLA_ALIGN(attrlen)); 319 320 return start; 321} 322 323/** 324 * nla_reserve - reserve room for attribute on the skb 325 * @skb: socket buffer to reserve room on 326 * @attrtype: attribute type 327 * @attrlen: length of attribute payload 328 * 329 * Adds a netlink attribute header to a socket buffer and reserves 330 * room for the payload but does not copy it. 331 * 332 * Returns NULL if the tailroom of the skb is insufficient to store 333 * the attribute header and payload. 334 */ 335struct nlattr *nla_reserve(struct sk_buff *skb, int attrtype, int attrlen) 336{ 337 if (unlikely(skb_tailroom(skb) < nla_total_size(attrlen))) 338 return NULL; 339 340 return __nla_reserve(skb, attrtype, attrlen); 341} 342 343/** 344 * nla_reserve_nohdr - reserve room for attribute without header 345 * @skb: socket buffer to reserve room on 346 * @attrlen: length of attribute payload 347 * 348 * Reserves room for attribute payload without a header. 349 * 350 * Returns NULL if the tailroom of the skb is insufficient to store 351 * the attribute payload. 352 */ 353void *nla_reserve_nohdr(struct sk_buff *skb, int attrlen) 354{ 355 if (unlikely(skb_tailroom(skb) < NLA_ALIGN(attrlen))) 356 return NULL; 357 358 return __nla_reserve_nohdr(skb, attrlen); 359} 360 361/** 362 * __nla_put - Add a netlink attribute to a socket buffer 363 * @skb: socket buffer to add attribute to 364 * @attrtype: attribute type 365 * @attrlen: length of attribute payload 366 * @data: head of attribute payload 367 * 368 * The caller is responsible to ensure that the skb provides enough 369 * tailroom for the attribute header and payload. 370 */ 371void __nla_put(struct sk_buff *skb, int attrtype, int attrlen, 372 const void *data) 373{ 374 struct nlattr *nla; 375 376 nla = __nla_reserve(skb, attrtype, attrlen); 377 memcpy(nla_data(nla), data, attrlen); 378} 379 380/** 381 * __nla_put_nohdr - Add a netlink attribute without header 382 * @skb: socket buffer to add attribute to 383 * @attrlen: length of attribute payload 384 * @data: head of attribute payload 385 * 386 * The caller is responsible to ensure that the skb provides enough 387 * tailroom for the attribute payload. 388 */ 389void __nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data) 390{ 391 void *start; 392 393 start = __nla_reserve_nohdr(skb, attrlen); 394 memcpy(start, data, attrlen); 395} 396 397/** 398 * nla_put - Add a netlink attribute to a socket buffer 399 * @skb: socket buffer to add attribute to 400 * @attrtype: attribute type 401 * @attrlen: length of attribute payload 402 * @data: head of attribute payload 403 * 404 * Returns -EMSGSIZE if the tailroom of the skb is insufficient to store 405 * the attribute header and payload. 406 */ 407int nla_put(struct sk_buff *skb, int attrtype, int attrlen, const void *data) 408{ 409 if (unlikely(skb_tailroom(skb) < nla_total_size(attrlen))) 410 return -EMSGSIZE; 411 412 __nla_put(skb, attrtype, attrlen, data); 413 return 0; 414} 415 416/** 417 * nla_put_nohdr - Add a netlink attribute without header 418 * @skb: socket buffer to add attribute to 419 * @attrlen: length of attribute payload 420 * @data: head of attribute payload 421 * 422 * Returns -EMSGSIZE if the tailroom of the skb is insufficient to store 423 * the attribute payload. 424 */ 425int nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data) 426{ 427 if (unlikely(skb_tailroom(skb) < NLA_ALIGN(attrlen))) 428 return -EMSGSIZE; 429 430 __nla_put_nohdr(skb, attrlen, data); 431 return 0; 432} 433 434/** 435 * nla_append - Add a netlink attribute without header or padding 436 * @skb: socket buffer to add attribute to 437 * @attrlen: length of attribute payload 438 * @data: head of attribute payload 439 * 440 * Returns -EMSGSIZE if the tailroom of the skb is insufficient to store 441 * the attribute payload. 442 */ 443int nla_append(struct sk_buff *skb, int attrlen, const void *data) 444{ 445 if (unlikely(skb_tailroom(skb) < NLA_ALIGN(attrlen))) 446 return -EMSGSIZE; 447 448 memcpy(skb_put(skb, attrlen), data, attrlen); 449 return 0; 450} 451 452EXPORT_SYMBOL(nla_validate); 453EXPORT_SYMBOL(nla_parse); 454EXPORT_SYMBOL(nla_find); 455EXPORT_SYMBOL(nla_strlcpy); 456EXPORT_SYMBOL(__nla_reserve); 457EXPORT_SYMBOL(__nla_reserve_nohdr); 458EXPORT_SYMBOL(nla_reserve); 459EXPORT_SYMBOL(nla_reserve_nohdr); 460EXPORT_SYMBOL(__nla_put); 461EXPORT_SYMBOL(__nla_put_nohdr); 462EXPORT_SYMBOL(nla_put); 463EXPORT_SYMBOL(nla_put_nohdr); 464EXPORT_SYMBOL(nla_memcpy); 465EXPORT_SYMBOL(nla_memcmp); 466EXPORT_SYMBOL(nla_strcmp); 467EXPORT_SYMBOL(nla_append);