1 /* 2 * netlink/attr.h Netlink Attributes 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation version 2.1 7 * of the License. 8 * 9 * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch> 10 */ 11 12 #ifndef NETLINK_ATTR_H_ 13 #define NETLINK_ATTR_H_ 14 15 #include <netlink/netlink.h> 16 #include <netlink/object.h> 17 #include <netlink/addr.h> 18 #include <netlink/data.h> 19 #include <netlink/msg.h> 20 21 #ifdef __cplusplus 22 extern "C" { 23 #endif 24 25 struct nl_msg; 26 27 /** 28 * @name Basic Attribute Data Types 29 * @{ 30 */ 31 32 /** 33 * @ingroup attr 34 * Basic attribute data types 35 * 36 * See \ref attr_datatypes for more details. 37 */ 38 enum { 39 NLA_UNSPEC, /**< Unspecified type, binary data chunk */ 40 NLA_U8, /**< 8 bit integer */ 41 NLA_U16, /**< 16 bit integer */ 42 NLA_U32, /**< 32 bit integer */ 43 NLA_U64, /**< 64 bit integer */ 44 NLA_STRING, /**< NUL terminated character string */ 45 NLA_FLAG, /**< Flag */ 46 NLA_MSECS, /**< Micro seconds (64bit) */ 47 NLA_NESTED, /**< Nested attributes */ 48 __NLA_TYPE_MAX, 49 }; 50 51 #define NLA_TYPE_MAX (__NLA_TYPE_MAX - 1) 52 53 /** @} */ 54 55 /** 56 * @ingroup attr 57 * Attribute validation policy. 58 * 59 * See \ref attr_datatypes for more details. 60 */ 61 struct nla_policy { 62 /** Type of attribute or NLA_UNSPEC */ 63 uint16_t type; 64 65 /** Minimal length of payload required */ 66 uint16_t minlen; 67 68 /** Maximal length of payload allowed */ 69 uint16_t maxlen; 70 }; 71 72 /* Attribute parsing */ 73 extern int nla_ok(const struct nlattr *, int); 74 extern struct nlattr * nla_next(const struct nlattr *, int *); 75 extern int nla_parse(struct nlattr **, int, struct nlattr *, 76 int, struct nla_policy *); 77 extern int nla_validate(struct nlattr *, int, int, 78 struct nla_policy *); 79 extern struct nlattr * nla_find(struct nlattr *, int, int); 80 81 /* Unspecific attribute */ 82 extern struct nlattr * nla_reserve(struct nl_msg *, int, int); 83 extern int nla_put(struct nl_msg *, int, int, const void *); 84 85 /** 86 * nlmsg_find_attr - find a specific attribute in a netlink message 87 * @arg nlh netlink message header 88 * @arg hdrlen length of familiy specific header 89 * @arg attrtype type of attribute to look for 90 * 91 * Returns the first attribute which matches the specified type. 92 */ 93 static inline struct nlattr *nlmsg_find_attr(struct nlmsghdr *nlh, int hdrlen, int attrtype) 94 { 95 return nla_find(nlmsg_attrdata(nlh, hdrlen), 96 nlmsg_attrlen(nlh, hdrlen), attrtype); 97 } 98 99 100 /** 101 * Return size of attribute whithout padding. 102 * @arg payload Payload length of attribute. 103 * 104 * @code 105 * <-------- nla_attr_size(payload) ---------> 106 * +------------------+- - -+- - - - - - - - - +- - -+ 107 * | Attribute Header | Pad | Payload | Pad | 108 * +------------------+- - -+- - - - - - - - - +- - -+ 109 * @endcode 110 * 111 * @return Size of attribute in bytes without padding. 112 */ 113 static inline int nla_attr_size(int payload) 114 { 115 return NLA_HDRLEN + payload; 116 } 117 118 /** 119 * Return size of attribute including padding. 120 * @arg payload Payload length of attribute. 121 * 122 * @code 123 * <----------- nla_total_size(payload) -----------> 124 * +------------------+- - -+- - - - - - - - - +- - -+ 125 * | Attribute Header | Pad | Payload | Pad | 126 * +------------------+- - -+- - - - - - - - - +- - -+ 127 * @endcode 128 * 129 * @return Size of attribute in bytes. 130 */ 131 static inline int nla_total_size(int payload) 132 { 133 return NLA_ALIGN(nla_attr_size(payload)); 134 } 135 136 /** 137 * Return length of padding at the tail of the attribute. 138 * @arg payload Payload length of attribute. 139 * 140 * @code 141 * +------------------+- - -+- - - - - - - - - +- - -+ 142 * | Attribute Header | Pad | Payload | Pad | 143 * +------------------+- - -+- - - - - - - - - +- - -+ 144 * <---> 145 * @endcode 146 * 147 * @return Length of padding in bytes. 148 */ 149 static inline int nla_padlen(int payload) 150 { 151 return nla_total_size(payload) - nla_attr_size(payload); 152 } 153 154 /** 155 * Return type of the attribute. 156 * @arg nla Attribute. 157 * 158 * @return Type of attribute. 159 */ 160 static inline int nla_type(const struct nlattr *nla) 161 { 162 return nla->nla_type & NLA_TYPE_MASK; 163 } 164 165 /** 166 * Return pointer to the payload section. 167 * @arg nla Attribute. 168 * 169 * @return Pointer to start of payload section. 170 */ 171 static inline void *nla_data(const struct nlattr *nla) 172 { 173 return (char *) nla + NLA_HDRLEN; 174 } 175 176 /** 177 * Return length of the payload . 178 * @arg nla Attribute 179 * 180 * @return Length of payload in bytes. 181 */ 182 static inline int nla_len(const struct nlattr *nla) 183 { 184 return nla->nla_len - NLA_HDRLEN; 185 } 186 187 /** 188 * Copy attribute payload to another memory area. 189 * @arg dest Pointer to destination memory area. 190 * @arg src Attribute 191 * @arg count Number of bytes to copy at most. 192 * 193 * Note: The number of bytes copied is limited by the length of 194 * the attribute payload. 195 * 196 * @return The number of bytes copied to dest. 197 */ 198 static inline int nla_memcpy(void *dest, struct nlattr *src, int count) 199 { 200 int minlen; 201 202 if (!src) 203 return 0; 204 205 minlen = min_t(int, count, nla_len(src)); 206 memcpy(dest, nla_data(src), minlen); 207 208 return minlen; 209 } 210 211 212 /** 213 * Add abstract data as unspecific attribute to netlink message. 214 * @arg msg Netlink message. 215 * @arg attrtype Attribute type. 216 * @arg data Abstract data object. 217 * 218 * Equivalent to nla_put() except that the length of the payload is 219 * derived from the abstract data object. 220 * 221 * @see nla_put 222 * @return 0 on success or a negative error code. 223 */ 224 static inline int nla_put_data(struct nl_msg *msg, int attrtype, struct nl_data *data) 225 { 226 return nla_put(msg, attrtype, nl_data_get_size(data), 227 nl_data_get(data)); 228 } 229 230 /** 231 * Add abstract address as unspecific attribute to netlink message. 232 * @arg msg Netlink message. 233 * @arg attrtype Attribute type. 234 * @arg addr Abstract address object. 235 * 236 * @see nla_put 237 * @return 0 on success or a negative error code. 238 */ 239 static inline int nla_put_addr(struct nl_msg *msg, int attrtype, struct nl_addr *addr) 240 { 241 return nla_put(msg, attrtype, nl_addr_get_len(addr), 242 nl_addr_get_binary_addr(addr)); 243 } 244 245 /** @} */ 246 247 /** 248 * @name Integer Attributes 249 */ 250 251 /** 252 * Add 8 bit integer attribute to netlink message. 253 * @arg msg Netlink message. 254 * @arg attrtype Attribute type. 255 * @arg value Numeric value to store as payload. 256 * 257 * @see nla_put 258 * @return 0 on success or a negative error code. 259 */ 260 static inline int nla_put_u8(struct nl_msg *msg, int attrtype, uint8_t value) 261 { 262 return nla_put(msg, attrtype, sizeof(uint8_t), &value); 263 } 264 265 /** 266 * Return value of 8 bit integer attribute. 267 * @arg nla 8 bit integer attribute 268 * 269 * @return Payload as 8 bit integer. 270 */ 271 static inline uint8_t nla_get_u8(struct nlattr *nla) 272 { 273 return *(uint8_t *) nla_data(nla); 274 } 275 276 /** 277 * Add 16 bit integer attribute to netlink message. 278 * @arg msg Netlink message. 279 * @arg attrtype Attribute type. 280 * @arg value Numeric value to store as payload. 281 * 282 * @see nla_put 283 * @return 0 on success or a negative error code. 284 */ 285 static inline int nla_put_u16(struct nl_msg *msg, int attrtype, uint16_t value) 286 { 287 return nla_put(msg, attrtype, sizeof(uint16_t), &value); 288 } 289 290 /** 291 * Return payload of 16 bit integer attribute. 292 * @arg nla 16 bit integer attribute 293 * 294 * @return Payload as 16 bit integer. 295 */ 296 static inline uint16_t nla_get_u16(struct nlattr *nla) 297 { 298 return *(uint16_t *) nla_data(nla); 299 } 300 301 /** 302 * Add 32 bit signed integer attribute to netlink message. 303 * @arg msg Netlink message. 304 * @arg attrtype Attribute type. 305 * @arg value Numeric value to store as payload. 306 * 307 * @see nla_put 308 * @return 0 on success or a negative error code. 309 */ 310 static inline int nla_put_s32(struct nl_msg *msg, int attrtype, int32_t value) 311 { 312 return nla_put(msg, attrtype, sizeof(int32_t), &value); 313 } 314 315 /** 316 * Return payload of 32 bit signed integer attribute. 317 * @arg nla 32 bit integer attribute. 318 * 319 * @return Payload as 32 bit integer. 320 */ 321 static inline int32_t nla_get_s32(struct nlattr *nla) 322 { 323 return *(int32_t *) nla_data(nla); 324 } 325 326 /** 327 * Add 32 bit integer attribute to netlink message. 328 * @arg msg Netlink message. 329 * @arg attrtype Attribute type. 330 * @arg value Numeric value to store as payload. 331 * 332 * @see nla_put 333 * @return 0 on success or a negative error code. 334 */ 335 static inline int nla_put_u32(struct nl_msg *msg, int attrtype, uint32_t value) 336 { 337 return nla_put(msg, attrtype, sizeof(uint32_t), &value); 338 } 339 340 /** 341 * Return payload of 32 bit integer attribute. 342 * @arg nla 32 bit integer attribute. 343 * 344 * @return Payload as 32 bit integer. 345 */ 346 static inline uint32_t nla_get_u32(struct nlattr *nla) 347 { 348 return *(uint32_t *) nla_data(nla); 349 } 350 351 /** 352 * Add 64 bit integer attribute to netlink message. 353 * @arg msg Netlink message. 354 * @arg attrtype Attribute type. 355 * @arg value Numeric value to store as payload. 356 * 357 * @see nla_put 358 * @return 0 on success or a negative error code. 359 */ 360 static inline int nla_put_u64(struct nl_msg *msg, int attrtype, uint64_t value) 361 { 362 return nla_put(msg, attrtype, sizeof(uint64_t), &value); 363 } 364 365 /** 366 * Return payload of u64 attribute 367 * @arg nla u64 netlink attribute 368 * 369 * @return Payload as 64 bit integer. 370 */ 371 static inline uint64_t nla_get_u64(struct nlattr *nla) 372 { 373 uint64_t tmp; 374 375 nla_memcpy(&tmp, nla, sizeof(tmp)); 376 377 return tmp; 378 } 379 380 /** 381 * Add string attribute to netlink message. 382 * @arg msg Netlink message. 383 * @arg attrtype Attribute type. 384 * @arg str NUL terminated string. 385 * 386 * @see nla_put 387 * @return 0 on success or a negative error code. 388 */ 389 static inline int nla_put_string(struct nl_msg *msg, int attrtype, const char *str) 390 { 391 return nla_put(msg, attrtype, strlen(str) + 1, str); 392 } 393 394 /** 395 * Return payload of string attribute. 396 * @arg nla String attribute. 397 * 398 * @return Pointer to attribute payload. 399 */ 400 static inline char *nla_get_string(struct nlattr *nla) 401 { 402 return (char *) nla_data(nla); 403 } 404 405 static inline char *nla_strdup(struct nlattr *nla) 406 { 407 return strdup(nla_get_string(nla)); 408 } 409 410 /** @} */ 411 412 /** 413 * @name Flag Attribute 414 */ 415 416 /** 417 * Add flag netlink attribute to netlink message. 418 * @arg msg Netlink message. 419 * @arg attrtype Attribute type. 420 * 421 * @see nla_put 422 * @return 0 on success or a negative error code. 423 */ 424 static inline int nla_put_flag(struct nl_msg *msg, int attrtype) 425 { 426 return nla_put(msg, attrtype, 0, NULL); 427 } 428 429 /** 430 * Return true if flag attribute is set. 431 * @arg nla Flag netlink attribute. 432 * 433 * @return True if flag is set, otherwise false. 434 */ 435 static inline int nla_get_flag(struct nlattr *nla) 436 { 437 return !!nla; 438 } 439 440 /** @} */ 441 442 /** 443 * @name Microseconds Attribute 444 */ 445 446 /** 447 * Add a msecs netlink attribute to a netlink message 448 * @arg n netlink message 449 * @arg attrtype attribute type 450 * @arg msecs number of msecs 451 */ 452 static inline int nla_put_msecs(struct nl_msg *n, int attrtype, unsigned long msecs) 453 { 454 return nla_put_u64(n, attrtype, msecs); 455 } 456 457 /** 458 * Return payload of msecs attribute 459 * @arg nla msecs netlink attribute 460 * 461 * @return the number of milliseconds. 462 */ 463 static inline unsigned long nla_get_msecs(struct nlattr *nla) 464 { 465 return nla_get_u64(nla); 466 } 467 468 /** 469 * Add nested attributes to netlink message. 470 * @arg msg Netlink message. 471 * @arg attrtype Attribute type. 472 * @arg nested Message containing attributes to be nested. 473 * 474 * Takes the attributes found in the \a nested message and appends them 475 * to the message \a msg nested in a container of the type \a attrtype. 476 * The \a nested message may not have a family specific header. 477 * 478 * @see nla_put 479 * @return 0 on success or a negative error code. 480 */ 481 static inline int nla_put_nested(struct nl_msg *msg, int attrtype, struct nl_msg *nested) 482 { 483 return nla_put(msg, attrtype, nlmsg_len(nested->nm_nlh), 484 nlmsg_data(nested->nm_nlh)); 485 } 486 487 /** 488 * Start a new level of nested attributes. 489 * @arg msg Netlink message. 490 * @arg attrtype Attribute type of container. 491 * 492 * @return Pointer to container attribute. 493 */ 494 static inline struct nlattr *nla_nest_start(struct nl_msg *msg, int attrtype) 495 { 496 struct nlattr *start = (struct nlattr *) nlmsg_tail(msg->nm_nlh); 497 498 if (nla_put(msg, attrtype | NLA_F_NESTED, 0, NULL) < 0) 499 return NULL; 500 501 return start; 502 } 503 504 /** 505 * Finalize nesting of attributes. 506 * @arg msg Netlink message. 507 * @arg start Container attribute as returned from nla_nest_start(). 508 * 509 * Corrects the container attribute header to include the appeneded attributes. 510 * 511 * @return 0 512 */ 513 static inline int nla_nest_end(struct nl_msg *msg, struct nlattr *start) 514 { 515 start->nla_len = (unsigned char *) nlmsg_tail(msg->nm_nlh) - 516 (unsigned char *) start; 517 return 0; 518 } 519 520 /** 521 * Create attribute index based on nested attribute 522 * @arg tb Index array to be filled (maxtype+1 elements). 523 * @arg maxtype Maximum attribute type expected and accepted. 524 * @arg nla Nested Attribute. 525 * @arg policy Attribute validation policy. 526 * 527 * Feeds the stream of attributes nested into the specified attribute 528 * to nla_parse(). 529 * 530 * @see nla_parse 531 * @return 0 on success or a negative error code. 532 */ 533 static inline int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, 534 struct nla_policy *policy) 535 { 536 return nla_parse(tb, maxtype, (struct nlattr *)nla_data(nla), nla_len(nla), policy); 537 } 538 539 /** 540 * Compare attribute payload with memory area. 541 * @arg nla Attribute. 542 * @arg data Memory area to compare to. 543 * @arg size Number of bytes to compare. 544 * 545 * @see memcmp(3) 546 * @return An integer less than, equal to, or greater than zero. 547 */ 548 static inline int nla_memcmp(const struct nlattr *nla, const void *data, size_t size) 549 { 550 int d = nla_len(nla) - size; 551 552 if (d == 0) 553 d = memcmp(nla_data(nla), data, size); 554 555 return d; 556 } 557 558 /** 559 * Compare string attribute payload with string 560 * @arg nla Attribute of type NLA_STRING. 561 * @arg str NUL terminated string. 562 * 563 * @see strcmp(3) 564 * @return An integer less than, equal to, or greater than zero. 565 */ 566 static inline int nla_strcmp(const struct nlattr *nla, const char *str) 567 { 568 int len = strlen(str) + 1; 569 int d = nla_len(nla) - len; 570 571 if (d == 0) 572 d = memcmp(nla_data(nla), str, len); 573 574 return d; 575 } 576 577 /** 578 * Copy string attribute payload to a buffer. 579 * @arg dst Pointer to destination buffer. 580 * @arg nla Attribute of type NLA_STRING. 581 * @arg dstsize Size of destination buffer in bytes. 582 * 583 * Copies at most dstsize - 1 bytes to the destination buffer. 584 * The result is always a valid NUL terminated string. Unlike 585 * strlcpy the destination buffer is always padded out. 586 * 587 * @return The length of string attribute without the terminating NUL. 588 */ 589 static inline size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize) 590 { 591 size_t srclen = (size_t)nla_len(nla); 592 char *src = (char*)nla_data(nla); 593 594 if (srclen > 0 && src[srclen - 1] == '\0') 595 srclen--; 596 597 if (dstsize > 0) { 598 size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen; 599 600 memset(dst, 0, dstsize); 601 memcpy(dst, src, len); 602 } 603 604 return srclen; 605 } 606 607 608 /** 609 * @name Attribute Construction (Exception Based) 610 * @{ 611 */ 612 613 /** 614 * @ingroup attr 615 * Add unspecific attribute to netlink message. 616 * @arg msg Netlink message. 617 * @arg attrtype Attribute type. 618 * @arg attrlen Length of attribute payload. 619 * @arg data Head of attribute payload. 620 */ 621 #define NLA_PUT(msg, attrtype, attrlen, data) \ 622 do { \ 623 if (nla_put(msg, attrtype, attrlen, data) < 0) \ 624 goto nla_put_failure; \ 625 } while(0) 626 627 /** 628 * @ingroup attr 629 * Add atomic type attribute to netlink message. 630 * @arg msg Netlink message. 631 * @arg type Atomic type. 632 * @arg attrtype Attribute type. 633 * @arg value Head of attribute payload. 634 */ 635 #define NLA_PUT_TYPE(msg, type, attrtype, value) \ 636 do { \ 637 type __tmp = value; \ 638 NLA_PUT(msg, attrtype, sizeof(type), &__tmp); \ 639 } while(0) 640 641 /** 642 * Add 8 bit integer attribute to netlink message. 643 * @arg msg Netlink message. 644 * @arg attrtype Attribute type. 645 * @arg value Numeric value. 646 */ 647 #define NLA_PUT_U8(msg, attrtype, value) \ 648 NLA_PUT_TYPE(msg, uint8_t, attrtype, value) 649 650 /** 651 * Add 16 bit integer attribute to netlink message. 652 * @arg msg Netlink message. 653 * @arg attrtype Attribute type. 654 * @arg value Numeric value. 655 */ 656 #define NLA_PUT_U16(msg, attrtype, value) \ 657 NLA_PUT_TYPE(msg, uint16_t, attrtype, value) 658 659 /** 660 * Add 32 bit signed integer attribute to netlink message. 661 * @arg msg Netlink message. 662 * @arg attrtype Attribute type. 663 * @arg value Numeric value. 664 */ 665 #define NLA_PUT_S32(msg, attrtype, value) \ 666 NLA_PUT_TYPE(msg, int32_t, attrtype, value) 667 668 /** 669 * Add 32 bit integer attribute to netlink message. 670 * @arg msg Netlink message. 671 * @arg attrtype Attribute type. 672 * @arg value Numeric value. 673 */ 674 #define NLA_PUT_U32(msg, attrtype, value) \ 675 NLA_PUT_TYPE(msg, uint32_t, attrtype, value) 676 677 /** 678 * Add 64 bit integer attribute to netlink message. 679 * @arg msg Netlink message. 680 * @arg attrtype Attribute type. 681 * @arg value Numeric value. 682 */ 683 #define NLA_PUT_U64(msg, attrtype, value) \ 684 NLA_PUT_TYPE(msg, uint64_t, attrtype, value) 685 686 /** 687 * Add string attribute to netlink message. 688 * @arg msg Netlink message. 689 * @arg attrtype Attribute type. 690 * @arg value NUL terminated character string. 691 */ 692 #define NLA_PUT_STRING(msg, attrtype, value) \ 693 NLA_PUT(msg, attrtype, strlen(value) + 1, value) 694 695 /** 696 * Add flag attribute to netlink message. 697 * @arg msg Netlink message. 698 * @arg attrtype Attribute type. 699 */ 700 #define NLA_PUT_FLAG(msg, attrtype) \ 701 NLA_PUT(msg, attrtype, 0, NULL) 702 703 /** 704 * Add msecs attribute to netlink message. 705 * @arg msg Netlink message. 706 * @arg attrtype Attribute type. 707 * @arg msecs Numeric value in micro seconds. 708 */ 709 #define NLA_PUT_MSECS(msg, attrtype, msecs) \ 710 NLA_PUT_U64(msg, attrtype, msecs) 711 712 /** 713 * Add address attribute to netlink message. 714 * @arg msg Netlink message. 715 * @arg attrtype Attribute type. 716 * @arg addr Abstract address object. 717 */ 718 #define NLA_PUT_ADDR(msg, attrtype, addr) \ 719 NLA_PUT(msg, attrtype, nl_addr_get_len(addr), \ 720 nl_addr_get_binary_addr(addr)) 721 722 /** @} */ 723 724 /** 725 * @name Iterators 726 * @{ 727 */ 728 729 /** 730 * @ingroup attr 731 * Iterate over a stream of attributes 732 * @arg pos loop counter, set to current attribute 733 * @arg head head of attribute stream 734 * @arg len length of attribute stream 735 * @arg rem initialized to len, holds bytes currently remaining in stream 736 */ 737 #define nla_for_each_attr(pos, head, len, rem) \ 738 for (pos = head, rem = len; \ 739 nla_ok(pos, rem); \ 740 pos = nla_next(pos, &(rem))) 741 742 /** 743 * @ingroup attr 744 * Iterate over a stream of nested attributes 745 * @arg pos loop counter, set to current attribute 746 * @arg nla attribute containing the nested attributes 747 * @arg rem initialized to len, holds bytes currently remaining in stream 748 */ 749 #define nla_for_each_nested(pos, nla, rem) \ 750 for (pos = (struct nlattr *)nla_data(nla), rem = nla_len(nla); \ 751 nla_ok(pos, rem); \ 752 pos = nla_next(pos, &(rem))) 753 754 /** @} */ 755 756 #ifdef __cplusplus 757 } 758 #endif 759 760 #endif 761
This page was automatically generated by LXR 0.3.1. • OpenWrt