libnl 1.1
|
00001 /* 00002 * lib/attr.c Netlink Attributes 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation version 2.1 00007 * of the License. 00008 * 00009 * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch> 00010 */ 00011 00012 #include <netlink-local.h> 00013 #include <netlink/netlink.h> 00014 #include <netlink/utils.h> 00015 #include <netlink/addr.h> 00016 #include <netlink/attr.h> 00017 #include <netlink/msg.h> 00018 #include <linux/socket.h> 00019 00020 /** 00021 * @ingroup msg 00022 * @defgroup attr Attributes 00023 * Netlink Attributes Construction/Parsing Interface 00024 * @par 0) Introduction 00025 * Netlink attributes are chained together following each other: 00026 * @code 00027 * <------- nla_total_size(payload) -------> 00028 * <---- nla_attr_size(payload) -----> 00029 * +----------+- - -+- - - - - - - - - +- - -+-------- - - 00030 * | Header | Pad | Payload | Pad | Header 00031 * +----------+- - -+- - - - - - - - - +- - -+-------- - - 00032 * <- nla_len(nla) -> ^ 00033 * nla_data(nla)----^ | 00034 * nla_next(nla)-----------------------------' 00035 * @endcode 00036 * 00037 * @par 00038 * The attribute header and payload must be aligned properly: 00039 * @code 00040 * <------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)--> 00041 * +---------------------+- - -+- - - - - - - - - -+- - -+ 00042 * | Header | Pad | Payload | Pad | 00043 * | (struct nlattr) | ing | | ing | 00044 * +---------------------+- - -+- - - - - - - - - -+- - -+ 00045 * <-------------- nlattr->nla_len --------------> 00046 * @endcode 00047 * 00048 * @par Nested TLVs: 00049 * Nested TLVs are an array of TLVs nested into another TLV. This can be useful 00050 * to allow subsystems to have their own formatting rules without the need to 00051 * make the underlying layer be aware of it. It can also be useful to transfer 00052 * arrays, lists and flattened trees. 00053 * \code 00054 * <-------------------- NLA_ALIGN(...) -------------------> 00055 * +---------------+- - - - - - - - - - - - - - - - - -+- - -+ 00056 * | |+---------+---------+- - -+-------+| | 00057 * | TLV Header || TLV 1 | TLV 2 | | TLV n || Pad | 00058 * | |+---------+---------+- - -+-------+| | 00059 * +---------------+- - - - - - - - - - - - - - - - - -+- - -+ 00060 * <--------- nla_data(nla) ---------> 00061 * \endcode 00062 * 00063 * @par 1) Constructing a message with attributes 00064 * @code 00065 * int param1 = 10; 00066 * char *param2 = "parameter text"; 00067 * 00068 * struct nl_msg *msg = nlmsg_alloc(); 00069 * nla_put_u32(msg, 1, param1); 00070 * nla_put_string(msg, 2, param2); 00071 * 00072 * nl_send_auto_complete(handle, nl_msg_get(msg)); 00073 * nlmsg_free(msg); 00074 * @endcode 00075 * 00076 * @par 2) Constructing nested attributes 00077 * @code 00078 * struct nl_msg * nested_config(void) 00079 * { 00080 * int a = 5, int b = 10; 00081 * struct nl_msg *n = nlmsg_alloc(); 00082 * nla_put_u32(n, 10, a); 00083 * nla_put_u32(n, 20, b); 00084 * return n; 00085 * } 00086 * 00087 * ... 00088 * struct nl_msg *m = nlmsg_alloc(); 00089 * struct nl_msg *nest = nested_config(); 00090 * nla_put_nested(m, 1, nest); 00091 * 00092 * nl_send_auto_complete(handle, nl_msg_get(m)); 00093 * nlmsg_free(nest); 00094 * nlmsg_free(m); 00095 * @endcode 00096 * @{ 00097 */ 00098 00099 /** 00100 * @name Size Calculations 00101 * @{ 00102 */ 00103 00104 /** 00105 * length of attribute not including padding 00106 * @arg payload length of payload 00107 */ 00108 int nla_attr_size(int payload) 00109 { 00110 return NLA_HDRLEN + payload; 00111 } 00112 00113 /** 00114 * total length of attribute including padding 00115 * @arg payload length of payload 00116 */ 00117 int nla_total_size(int payload) 00118 { 00119 return NLA_ALIGN(nla_attr_size(payload)); 00120 } 00121 00122 /** 00123 * length of padding at the tail of the attribute 00124 * @arg payload length of payload 00125 */ 00126 int nla_padlen(int payload) 00127 { 00128 return nla_total_size(payload) - nla_attr_size(payload); 00129 } 00130 00131 /** @} */ 00132 00133 /** 00134 * @name Payload Access 00135 * @{ 00136 */ 00137 00138 /** 00139 * attribute type 00140 * @arg nla netlink attribute 00141 */ 00142 int nla_type(const struct nlattr *nla) 00143 { 00144 return nla->nla_type & NLA_TYPE_MASK; 00145 } 00146 00147 /** 00148 * head of payload 00149 * @arg nla netlink attribute 00150 */ 00151 void *nla_data(const struct nlattr *nla) 00152 { 00153 return (char *) nla + NLA_HDRLEN; 00154 } 00155 00156 /** 00157 * length of payload 00158 * @arg nla netlink attribute 00159 */ 00160 int nla_len(const struct nlattr *nla) 00161 { 00162 return nla->nla_len - NLA_HDRLEN; 00163 } 00164 00165 /** @} */ 00166 00167 /** 00168 * @name Attribute Parsing 00169 * @{ 00170 */ 00171 00172 /** 00173 * check if the netlink attribute fits into the remaining bytes 00174 * @arg nla netlink attribute 00175 * @arg remaining number of bytes remaining in attribute stream 00176 */ 00177 int nla_ok(const struct nlattr *nla, int remaining) 00178 { 00179 return remaining >= sizeof(*nla) && 00180 nla->nla_len >= sizeof(*nla) && 00181 nla->nla_len <= remaining; 00182 } 00183 00184 /** 00185 * next netlink attribte in attribute stream 00186 * @arg nla netlink attribute 00187 * @arg remaining number of bytes remaining in attribute stream 00188 * 00189 * @return the next netlink attribute in the attribute stream and 00190 * decrements remaining by the size of the current attribute. 00191 */ 00192 struct nlattr *nla_next(const struct nlattr *nla, int *remaining) 00193 { 00194 int totlen = NLA_ALIGN(nla->nla_len); 00195 00196 *remaining -= totlen; 00197 return (struct nlattr *) ((char *) nla + totlen); 00198 } 00199 00200 static uint16_t nla_attr_minlen[NLA_TYPE_MAX+1] = { 00201 [NLA_U8] = sizeof(uint8_t), 00202 [NLA_U16] = sizeof(uint16_t), 00203 [NLA_U32] = sizeof(uint32_t), 00204 [NLA_U64] = sizeof(uint64_t), 00205 [NLA_STRING] = 1, 00206 [NLA_NESTED] = NLA_HDRLEN, 00207 }; 00208 00209 static int validate_nla(struct nlattr *nla, int maxtype, 00210 struct nla_policy *policy) 00211 { 00212 struct nla_policy *pt; 00213 int minlen = 0, type = nla_type(nla); 00214 00215 if (type <= 0 || type > maxtype) 00216 return 0; 00217 00218 pt = &policy[type]; 00219 00220 if (pt->type > NLA_TYPE_MAX) 00221 BUG(); 00222 00223 if (pt->minlen) 00224 minlen = pt->minlen; 00225 else if (pt->type != NLA_UNSPEC) 00226 minlen = nla_attr_minlen[pt->type]; 00227 00228 if (pt->type == NLA_FLAG && nla_len(nla) > 0) 00229 return nl_errno(ERANGE); 00230 00231 if (nla_len(nla) < minlen) 00232 return nl_errno(ERANGE); 00233 00234 if (pt->maxlen && nla_len(nla) > pt->maxlen) 00235 return nl_errno(ERANGE); 00236 00237 if (pt->type == NLA_STRING) { 00238 char *data = nla_data(nla); 00239 if (data[nla_len(nla) - 1] != '\0') 00240 return nl_errno(EINVAL); 00241 } 00242 00243 return 0; 00244 } 00245 00246 00247 /** 00248 * Parse a stream of attributes into a tb buffer 00249 * @arg tb destination array with maxtype+1 elements 00250 * @arg maxtype maximum attribute type to be expected 00251 * @arg head head of attribute stream 00252 * @arg len length of attribute stream 00253 * @arg policy validation policy 00254 * 00255 * Parses a stream of attributes and stores a pointer to each attribute in 00256 * the tb array accessable via the attribute type. Attributes with a type 00257 * exceeding maxtype will be silently ignored for backwards compatibility 00258 * reasons. policy may be set to NULL if no validation is required. 00259 * 00260 * @return 0 on success or a negative error code. 00261 */ 00262 int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len, 00263 struct nla_policy *policy) 00264 { 00265 struct nlattr *nla; 00266 int rem, err; 00267 00268 memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1)); 00269 00270 nla_for_each_attr(nla, head, len, rem) { 00271 int type = nla_type(nla); 00272 00273 if (type == 0) { 00274 fprintf(stderr, "Illegal nla->nla_type == 0\n"); 00275 continue; 00276 } 00277 00278 if (type <= maxtype) { 00279 if (policy) { 00280 err = validate_nla(nla, maxtype, policy); 00281 if (err < 0) 00282 goto errout; 00283 } 00284 00285 tb[type] = nla; 00286 } 00287 } 00288 00289 if (rem > 0) 00290 fprintf(stderr, "netlink: %d bytes leftover after parsing " 00291 "attributes.\n", rem); 00292 00293 err = 0; 00294 errout: 00295 return err; 00296 } 00297 00298 00299 /** 00300 * parse nested attributes 00301 * @arg tb destination array with maxtype+1 elements 00302 * @arg maxtype maximum attribute type to be expected 00303 * @arg nla attribute containing the nested attributes 00304 * @arg policy validation policy 00305 * 00306 * @see nla_parse() 00307 */ 00308 int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, 00309 struct nla_policy *policy) 00310 { 00311 return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy); 00312 } 00313 00314 /** 00315 * Validate a stream of attributes 00316 * @arg head head of attribute stream 00317 * @arg len length of attribute stream 00318 * @arg maxtype maximum attribute type to be expected 00319 * @arg policy validation policy 00320 * 00321 * Validates all attributes in the specified attribute stream 00322 * against the specified policy. Attributes with a type exceeding 00323 * maxtype will be ignored. See documenation of struct nla_policy 00324 * for more details. 00325 * 00326 * @return 0 on success or a negative error code. 00327 */ 00328 int nla_validate(struct nlattr *head, int len, int maxtype, 00329 struct nla_policy *policy) 00330 { 00331 struct nlattr *nla; 00332 int rem, err; 00333 00334 nla_for_each_attr(nla, head, len, rem) { 00335 err = validate_nla(nla, maxtype, policy); 00336 if (err < 0) 00337 goto errout; 00338 } 00339 00340 err = 0; 00341 errout: 00342 return err; 00343 } 00344 00345 /** 00346 * Find a specific attribute in a stream of attributes 00347 * @arg head head of attribute stream 00348 * @arg len length of attribute stream 00349 * @arg attrtype type of attribute to look for 00350 * 00351 * @return the first attribute in the stream matching the specified type. 00352 */ 00353 struct nlattr *nla_find(struct nlattr *head, int len, int attrtype) 00354 { 00355 struct nlattr *nla; 00356 int rem; 00357 00358 nla_for_each_attr(nla, head, len, rem) 00359 if (nla_type(nla) == attrtype) 00360 return nla; 00361 00362 return NULL; 00363 } 00364 00365 /** @} */ 00366 00367 /** 00368 * @name Utilities 00369 * @{ 00370 */ 00371 00372 /** 00373 * Copy a netlink attribute into another memory area 00374 * @arg dest where to copy to memcpy 00375 * @arg src netlink attribute to copy from 00376 * @arg count size of the destination area 00377 * 00378 * Note: The number of bytes copied is limited by the length of 00379 * attribute's payload. memcpy 00380 * 00381 * @return the number of bytes copied. 00382 */ 00383 int nla_memcpy(void *dest, struct nlattr *src, int count) 00384 { 00385 int minlen; 00386 00387 if (!src) 00388 return 0; 00389 00390 minlen = min_t(int, count, nla_len(src)); 00391 memcpy(dest, nla_data(src), minlen); 00392 00393 return minlen; 00394 } 00395 00396 /** 00397 * Copy string attribute payload into a sized buffer 00398 * @arg dst where to copy the string to 00399 * @arg nla attribute to copy the string from 00400 * @arg dstsize size of destination buffer 00401 * 00402 * Copies at most dstsize - 1 bytes into the destination buffer. 00403 * The result is always a valid NUL-terminated string. Unlike 00404 * strlcpy the destination buffer is always padded out. 00405 * 00406 * @return the length of the source buffer. 00407 */ 00408 size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize) 00409 { 00410 size_t srclen = nla_len(nla); 00411 char *src = nla_data(nla); 00412 00413 if (srclen > 0 && src[srclen - 1] == '\0') 00414 srclen--; 00415 00416 if (dstsize > 0) { 00417 size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen; 00418 00419 memset(dst, 0, dstsize); 00420 memcpy(dst, src, len); 00421 } 00422 00423 return srclen; 00424 } 00425 00426 /** 00427 * Compare an attribute with sized memory area 00428 * @arg nla netlink attribute 00429 * @arg data memory area 00430 * @arg size size of memory area 00431 */ 00432 int nla_memcmp(const struct nlattr *nla, const void *data, 00433 size_t size) 00434 { 00435 int d = nla_len(nla) - size; 00436 00437 if (d == 0) 00438 d = memcmp(nla_data(nla), data, size); 00439 00440 return d; 00441 } 00442 00443 /** 00444 * Compare a string attribute against a string 00445 * @arg nla netlink string attribute 00446 * @arg str another string 00447 */ 00448 int nla_strcmp(const struct nlattr *nla, const char *str) 00449 { 00450 int len = strlen(str) + 1; 00451 int d = nla_len(nla) - len; 00452 00453 if (d == 0) 00454 d = memcmp(nla_data(nla), str, len); 00455 00456 return d; 00457 } 00458 00459 /** @} */ 00460 00461 /** 00462 * @name Attribute Construction 00463 * @{ 00464 */ 00465 00466 /** 00467 * reserve room for attribute on the skb 00468 * @arg n netlink message 00469 * @arg attrtype attribute type 00470 * @arg attrlen length of attribute payload 00471 * 00472 * Adds a netlink attribute header to a netlink message and reserves 00473 * room for the payload but does not copy it. 00474 */ 00475 struct nlattr *nla_reserve(struct nl_msg *n, int attrtype, int attrlen) 00476 { 00477 struct nlattr *nla; 00478 int tlen; 00479 00480 tlen = NLMSG_ALIGN(n->nm_nlh->nlmsg_len) + nla_total_size(attrlen); 00481 00482 if ((tlen + n->nm_nlh->nlmsg_len) > n->nm_size) { 00483 nl_errno(ENOBUFS); 00484 return NULL; 00485 } 00486 00487 nla = (struct nlattr *) nlmsg_tail(n->nm_nlh); 00488 nla->nla_type = attrtype; 00489 nla->nla_len = nla_attr_size(attrlen); 00490 00491 memset((unsigned char *) nla + nla->nla_len, 0, nla_padlen(attrlen)); 00492 n->nm_nlh->nlmsg_len = tlen; 00493 00494 NL_DBG(2, "msg %p: Reserved %d bytes at offset +%td for attr %d " 00495 "nlmsg_len=%d\n", n, attrlen, 00496 (void *) nla - nlmsg_data(n->nm_nlh), 00497 attrtype, n->nm_nlh->nlmsg_len); 00498 00499 return nla; 00500 } 00501 00502 /** 00503 * Add a netlink attribute to a netlink message 00504 * @arg n netlink message 00505 * @arg attrtype attribute type 00506 * @arg attrlen length of attribute payload 00507 * @arg data head of attribute payload 00508 * 00509 * @return -1 if the tailroom of the skb is insufficient to store 00510 * the attribute header and payload. 00511 */ 00512 int nla_put(struct nl_msg *n, int attrtype, int attrlen, const void *data) 00513 { 00514 struct nlattr *nla; 00515 00516 nla = nla_reserve(n, attrtype, attrlen); 00517 if (!nla) 00518 return nl_errno(ENOMEM); 00519 00520 memcpy(nla_data(nla), data, attrlen); 00521 NL_DBG(2, "msg %p: Wrote %d bytes at offset +%td for attr %d\n", 00522 n, attrlen, (void *) nla - nlmsg_data(n->nm_nlh), attrtype); 00523 00524 return 0; 00525 } 00526 00527 /** 00528 * Add a nested netlink attribute to a netlink message 00529 * @arg n netlink message 00530 * @arg attrtype attribute type 00531 * @arg nested netlink attribute to nest 00532 * 00533 * @return -1 if the tailroom of the skb is insufficient to store 00534 * the attribute header and payload. 00535 */ 00536 int nla_put_nested(struct nl_msg *n, int attrtype, struct nl_msg *nested) 00537 { 00538 return nla_put(n, attrtype, nlmsg_len(nested->nm_nlh), 00539 nlmsg_data(nested->nm_nlh)); 00540 } 00541 00542 /** 00543 * Add a u16 netlink attribute to a netlink message 00544 * @arg n netlink message 00545 * @arg attrtype attribute type 00546 * @arg value numeric value 00547 */ 00548 int nla_put_u8(struct nl_msg *n, int attrtype, uint8_t value) 00549 { 00550 return nla_put(n, attrtype, sizeof(uint8_t), &value); 00551 } 00552 00553 /** 00554 * Add a u16 netlink attribute to a netlink message 00555 * @arg n netlink message 00556 * @arg attrtype attribute type 00557 * @arg value numeric value 00558 */ 00559 int nla_put_u16(struct nl_msg *n, int attrtype, uint16_t value) 00560 { 00561 return nla_put(n, attrtype, sizeof(uint16_t), &value); 00562 } 00563 00564 /** 00565 * Add a u32 netlink attribute to a netlink message 00566 * @arg n netlink message 00567 * @arg attrtype attribute type 00568 * @arg value numeric value 00569 */ 00570 int nla_put_u32(struct nl_msg *n, int attrtype, uint32_t value) 00571 { 00572 return nla_put(n, attrtype, sizeof(uint32_t), &value); 00573 } 00574 00575 /** 00576 * Add a u64 netlink attribute to a netlink message 00577 * @arg n netlink message 00578 * @arg attrtype attribute type 00579 * @arg value numeric value 00580 */ 00581 int nla_put_u64(struct nl_msg *n, int attrtype, uint64_t value) 00582 { 00583 return nla_put(n, attrtype, sizeof(uint64_t), &value); 00584 } 00585 00586 /** 00587 * Add a string netlink attribute to a netlink message 00588 * @arg n netlink message 00589 * @arg attrtype attribute type 00590 * @arg str NUL terminated string 00591 */ 00592 int nla_put_string(struct nl_msg *n, int attrtype, const char *str) 00593 { 00594 return nla_put(n, attrtype, strlen(str) + 1, str); 00595 } 00596 00597 /** 00598 * Add a flag netlink attribute to a netlink message 00599 * @arg n netlink message 00600 * @arg attrtype attribute type 00601 */ 00602 int nla_put_flag(struct nl_msg *n, int attrtype) 00603 { 00604 return nla_put(n, attrtype, 0, NULL); 00605 } 00606 00607 /** 00608 * Add a msecs netlink attribute to a netlink message 00609 * @arg n netlink message 00610 * @arg attrtype attribute type 00611 * @arg msecs number of msecs 00612 */ 00613 int nla_put_msecs(struct nl_msg *n, int attrtype, unsigned long msecs) 00614 { 00615 return nla_put_u64(n, attrtype, msecs); 00616 } 00617 00618 /** 00619 * Add an abstract data netlink attribute to a netlink message 00620 * @arg n netlink message 00621 * @arg attrtype attribute type 00622 * @arg data abstract data 00623 */ 00624 int nla_put_data(struct nl_msg *n, int attrtype, struct nl_data *data) 00625 { 00626 return nla_put(n, attrtype, nl_data_get_size(data), 00627 nl_data_get(data)); 00628 } 00629 00630 /** 00631 * Add an abstract address netlink attribute to a netlink message 00632 * @arg n netlink message 00633 * @arg attrtype attribute type 00634 * @arg addr abstract address 00635 */ 00636 int nla_put_addr(struct nl_msg *n, int attrtype, struct nl_addr *addr) 00637 { 00638 return nla_put(n, attrtype, nl_addr_get_len(addr), 00639 nl_addr_get_binary_addr(addr)); 00640 } 00641 00642 /** @} */ 00643 00644 /** 00645 * @name Attribute Nesting 00646 * @{ 00647 */ 00648 00649 /** 00650 * Start a new level of nested attributes 00651 * @arg n netlink message 00652 * @arg attrtype attribute type of container 00653 * 00654 * @return the container attribute 00655 */ 00656 struct nlattr *nla_nest_start(struct nl_msg *n, int attrtype) 00657 { 00658 struct nlattr *start = (struct nlattr *) nlmsg_tail(n->nm_nlh); 00659 00660 if (nla_put(n, attrtype, 0, NULL) < 0) 00661 return NULL; 00662 00663 return start; 00664 } 00665 00666 /** 00667 * Finalize nesting of attributes 00668 * @arg n netlink message 00669 * @arg start container attribute 00670 * 00671 * Corrects the container attribute header to include the all 00672 * appeneded attributes. 00673 * 00674 * @return the total data length of the skb. 00675 */ 00676 int nla_nest_end(struct nl_msg *n, struct nlattr *start) 00677 { 00678 start->nla_len = (unsigned char *) nlmsg_tail(n->nm_nlh) - 00679 (unsigned char *) start; 00680 return 0; 00681 } 00682 00683 /** @} */ 00684 00685 /** 00686 * @name Attribute Reading 00687 * @{ 00688 */ 00689 00690 /** 00691 * Return payload of u32 attribute 00692 * @arg nla u32 netlink attribute 00693 */ 00694 uint32_t nla_get_u32(struct nlattr *nla) 00695 { 00696 return *(uint32_t *) nla_data(nla); 00697 } 00698 00699 /** 00700 * Return payload of u16 attribute 00701 * @arg nla u16 netlink attribute 00702 */ 00703 uint16_t nla_get_u16(struct nlattr *nla) 00704 { 00705 return *(uint16_t *) nla_data(nla); 00706 } 00707 00708 /** 00709 * Return payload of u8 attribute 00710 * @arg nla u8 netlink attribute 00711 */ 00712 uint8_t nla_get_u8(struct nlattr *nla) 00713 { 00714 return *(uint8_t *) nla_data(nla); 00715 } 00716 00717 /** 00718 * Return payload of u64 attribute 00719 * @arg nla u64 netlink attribute 00720 */ 00721 uint64_t nla_get_u64(struct nlattr *nla) 00722 { 00723 uint64_t tmp; 00724 00725 nla_memcpy(&tmp, nla, sizeof(tmp)); 00726 00727 return tmp; 00728 } 00729 00730 /** 00731 * return payload of string attribute 00732 * @arg nla string netlink attribute 00733 */ 00734 char *nla_get_string(struct nlattr *nla) 00735 { 00736 return (char *) nla_data(nla); 00737 } 00738 00739 /** 00740 * Return payload of flag attribute 00741 * @arg nla flag netlink attribute 00742 */ 00743 int nla_get_flag(struct nlattr *nla) 00744 { 00745 return !!nla; 00746 } 00747 00748 /** 00749 * Return payload of msecs attribute 00750 * @arg nla msecs netlink attribute 00751 * 00752 * @return the number of milliseconds. 00753 */ 00754 unsigned long nla_get_msecs(struct nlattr *nla) 00755 { 00756 return nla_get_u64(nla); 00757 } 00758 00759 /** 00760 * Return payload of address attribute 00761 * @arg nla address netlink attribute 00762 * @arg family address family 00763 * 00764 * @return Newly allocated address handle or NULL 00765 */ 00766 struct nl_addr *nla_get_addr(struct nlattr *nla, int family) 00767 { 00768 return nl_addr_build(family, nla_data(nla), nla_len(nla)); 00769 } 00770 00771 /** 00772 * Return payload of abstract data attribute 00773 * @arg nla abstract data netlink attribute 00774 * 00775 * @return Newly allocated abstract data handle or NULL 00776 */ 00777 struct nl_data *nla_get_data(struct nlattr *nla) 00778 { 00779 return nl_data_alloc(nla_data(nla), nla_len(nla)); 00780 } 00781 00782 /** @} */ 00783 00784 /** @} */