attr.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783
  1. /*
  2. * lib/attr.c 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-2006 Thomas Graf <tgraf@suug.ch>
  10. */
  11. #include <netlink-local.h>
  12. #include <netlink/netlink.h>
  13. #include <netlink/utils.h>
  14. #include <netlink/addr.h>
  15. #include <netlink/attr.h>
  16. #include <netlink/msg.h>
  17. #include <linux/socket.h>
  18. /**
  19. * @ingroup msg
  20. * @defgroup attr Attributes
  21. * Netlink Attributes Construction/Parsing Interface
  22. * @par 0) Introduction
  23. * Netlink attributes are chained together following each other:
  24. * @code
  25. * <------- nla_total_size(payload) ------->
  26. * <---- nla_attr_size(payload) ----->
  27. * +----------+- - -+- - - - - - - - - +- - -+-------- - -
  28. * | Header | Pad | Payload | Pad | Header
  29. * +----------+- - -+- - - - - - - - - +- - -+-------- - -
  30. * <- nla_len(nla) -> ^
  31. * nla_data(nla)----^ |
  32. * nla_next(nla)-----------------------------'
  33. * @endcode
  34. *
  35. * @par
  36. * The attribute header and payload must be aligned properly:
  37. * @code
  38. * <------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)-->
  39. * +---------------------+- - -+- - - - - - - - - -+- - -+
  40. * | Header | Pad | Payload | Pad |
  41. * | (struct nlattr) | ing | | ing |
  42. * +---------------------+- - -+- - - - - - - - - -+- - -+
  43. * <-------------- nlattr->nla_len -------------->
  44. * @endcode
  45. *
  46. * @par Nested TLVs:
  47. * Nested TLVs are an array of TLVs nested into another TLV. This can be useful
  48. * to allow subsystems to have their own formatting rules without the need to
  49. * make the underlying layer be aware of it. It can also be useful to transfer
  50. * arrays, lists and flattened trees.
  51. * \code
  52. * <-------------------- NLA_ALIGN(...) ------------------->
  53. * +---------------+- - - - - - - - - - - - - - - - - -+- - -+
  54. * | |+---------+---------+- - -+-------+| |
  55. * | TLV Header || TLV 1 | TLV 2 | | TLV n || Pad |
  56. * | |+---------+---------+- - -+-------+| |
  57. * +---------------+- - - - - - - - - - - - - - - - - -+- - -+
  58. * <--------- nla_data(nla) --------->
  59. * \endcode
  60. *
  61. * @par 1) Constructing a message with attributes
  62. * @code
  63. * int param1 = 10;
  64. * char *param2 = "parameter text";
  65. *
  66. * struct nl_msg *msg = nlmsg_alloc();
  67. * nla_put_u32(msg, 1, param1);
  68. * nla_put_string(msg, 2, param2);
  69. *
  70. * nl_send_auto_complete(handle, nl_msg_get(msg));
  71. * nlmsg_free(msg);
  72. * @endcode
  73. *
  74. * @par 2) Constructing nested attributes
  75. * @code
  76. * struct nl_msg * nested_config(void)
  77. * {
  78. * int a = 5, int b = 10;
  79. * struct nl_msg *n = nlmsg_alloc();
  80. * nla_put_u32(n, 10, a);
  81. * nla_put_u32(n, 20, b);
  82. * return n;
  83. * }
  84. *
  85. * ...
  86. * struct nl_msg *m = nlmsg_alloc();
  87. * struct nl_msg *nest = nested_config();
  88. * nla_put_nested(m, 1, nest);
  89. *
  90. * nl_send_auto_complete(handle, nl_msg_get(m));
  91. * nlmsg_free(nest);
  92. * nlmsg_free(m);
  93. * @endcode
  94. * @{
  95. */
  96. /**
  97. * @name Size Calculations
  98. * @{
  99. */
  100. /**
  101. * length of attribute not including padding
  102. * @arg payload length of payload
  103. */
  104. int nla_attr_size(int payload)
  105. {
  106. return NLA_HDRLEN + payload;
  107. }
  108. /**
  109. * total length of attribute including padding
  110. * @arg payload length of payload
  111. */
  112. int nla_total_size(int payload)
  113. {
  114. return NLA_ALIGN(nla_attr_size(payload));
  115. }
  116. /**
  117. * length of padding at the tail of the attribute
  118. * @arg payload length of payload
  119. */
  120. int nla_padlen(int payload)
  121. {
  122. return nla_total_size(payload) - nla_attr_size(payload);
  123. }
  124. /** @} */
  125. /**
  126. * @name Payload Access
  127. * @{
  128. */
  129. /**
  130. * attribute type
  131. * @arg nla netlink attribute
  132. */
  133. int nla_type(const struct nlattr *nla)
  134. {
  135. return nla->nla_type & NLA_TYPE_MASK;
  136. }
  137. /**
  138. * head of payload
  139. * @arg nla netlink attribute
  140. */
  141. void *nla_data(const struct nlattr *nla)
  142. {
  143. return (char *) nla + NLA_HDRLEN;
  144. }
  145. /**
  146. * length of payload
  147. * @arg nla netlink attribute
  148. */
  149. int nla_len(const struct nlattr *nla)
  150. {
  151. return nla->nla_len - NLA_HDRLEN;
  152. }
  153. /** @} */
  154. /**
  155. * @name Attribute Parsing
  156. * @{
  157. */
  158. /**
  159. * check if the netlink attribute fits into the remaining bytes
  160. * @arg nla netlink attribute
  161. * @arg remaining number of bytes remaining in attribute stream
  162. */
  163. int nla_ok(const struct nlattr *nla, int remaining)
  164. {
  165. return remaining >= sizeof(*nla) &&
  166. nla->nla_len >= sizeof(*nla) &&
  167. nla->nla_len <= remaining;
  168. }
  169. /**
  170. * next netlink attribte in attribute stream
  171. * @arg nla netlink attribute
  172. * @arg remaining number of bytes remaining in attribute stream
  173. *
  174. * @return the next netlink attribute in the attribute stream and
  175. * decrements remaining by the size of the current attribute.
  176. */
  177. struct nlattr *nla_next(const struct nlattr *nla, int *remaining)
  178. {
  179. int totlen = NLA_ALIGN(nla->nla_len);
  180. *remaining -= totlen;
  181. return (struct nlattr *) ((char *) nla + totlen);
  182. }
  183. static uint16_t nla_attr_minlen[NLA_TYPE_MAX+1] = {
  184. [NLA_U8] = sizeof(uint8_t),
  185. [NLA_U16] = sizeof(uint16_t),
  186. [NLA_U32] = sizeof(uint32_t),
  187. [NLA_U64] = sizeof(uint64_t),
  188. [NLA_STRING] = 1,
  189. [NLA_NESTED] = NLA_HDRLEN,
  190. };
  191. static int validate_nla(struct nlattr *nla, int maxtype,
  192. struct nla_policy *policy)
  193. {
  194. struct nla_policy *pt;
  195. int minlen = 0, type = nla_type(nla);
  196. if (type <= 0 || type > maxtype)
  197. return 0;
  198. pt = &policy[type];
  199. if (pt->type > NLA_TYPE_MAX)
  200. BUG();
  201. if (pt->minlen)
  202. minlen = pt->minlen;
  203. else if (pt->type != NLA_UNSPEC)
  204. minlen = nla_attr_minlen[pt->type];
  205. if (pt->type == NLA_FLAG && nla_len(nla) > 0)
  206. return nl_errno(ERANGE);
  207. if (nla_len(nla) < minlen)
  208. return nl_errno(ERANGE);
  209. if (pt->maxlen && nla_len(nla) > pt->maxlen)
  210. return nl_errno(ERANGE);
  211. if (pt->type == NLA_STRING) {
  212. char *data = nla_data(nla);
  213. if (data[nla_len(nla) - 1] != '\0')
  214. return nl_errno(EINVAL);
  215. }
  216. return 0;
  217. }
  218. /**
  219. * Parse a stream of attributes into a tb buffer
  220. * @arg tb destination array with maxtype+1 elements
  221. * @arg maxtype maximum attribute type to be expected
  222. * @arg head head of attribute stream
  223. * @arg len length of attribute stream
  224. * @arg policy validation policy
  225. *
  226. * Parses a stream of attributes and stores a pointer to each attribute in
  227. * the tb array accessable via the attribute type. Attributes with a type
  228. * exceeding maxtype will be silently ignored for backwards compatibility
  229. * reasons. policy may be set to NULL if no validation is required.
  230. *
  231. * @return 0 on success or a negative error code.
  232. */
  233. int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len,
  234. struct nla_policy *policy)
  235. {
  236. struct nlattr *nla;
  237. int rem, err;
  238. memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
  239. nla_for_each_attr(nla, head, len, rem) {
  240. int type = nla_type(nla);
  241. /* Padding attributes */
  242. if (type == 0)
  243. continue;
  244. if (type <= maxtype) {
  245. if (policy) {
  246. err = validate_nla(nla, maxtype, policy);
  247. if (err < 0)
  248. goto errout;
  249. }
  250. tb[type] = nla;
  251. }
  252. }
  253. if (rem > 0)
  254. fprintf(stderr, "netlink: %d bytes leftover after parsing "
  255. "attributes.\n", rem);
  256. err = 0;
  257. errout:
  258. return err;
  259. }
  260. /**
  261. * parse nested attributes
  262. * @arg tb destination array with maxtype+1 elements
  263. * @arg maxtype maximum attribute type to be expected
  264. * @arg nla attribute containing the nested attributes
  265. * @arg policy validation policy
  266. *
  267. * @see nla_parse()
  268. */
  269. int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla,
  270. struct nla_policy *policy)
  271. {
  272. return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy);
  273. }
  274. /**
  275. * Validate a stream of attributes
  276. * @arg head head of attribute stream
  277. * @arg len length of attribute stream
  278. * @arg maxtype maximum attribute type to be expected
  279. * @arg policy validation policy
  280. *
  281. * Validates all attributes in the specified attribute stream
  282. * against the specified policy. Attributes with a type exceeding
  283. * maxtype will be ignored. See documenation of struct nla_policy
  284. * for more details.
  285. *
  286. * @return 0 on success or a negative error code.
  287. */
  288. int nla_validate(struct nlattr *head, int len, int maxtype,
  289. struct nla_policy *policy)
  290. {
  291. struct nlattr *nla;
  292. int rem, err;
  293. nla_for_each_attr(nla, head, len, rem) {
  294. err = validate_nla(nla, maxtype, policy);
  295. if (err < 0)
  296. goto errout;
  297. }
  298. err = 0;
  299. errout:
  300. return err;
  301. }
  302. /**
  303. * Find a specific attribute in a stream of attributes
  304. * @arg head head of attribute stream
  305. * @arg len length of attribute stream
  306. * @arg attrtype type of attribute to look for
  307. *
  308. * @return the first attribute in the stream matching the specified type.
  309. */
  310. struct nlattr *nla_find(struct nlattr *head, int len, int attrtype)
  311. {
  312. struct nlattr *nla;
  313. int rem;
  314. nla_for_each_attr(nla, head, len, rem)
  315. if (nla_type(nla) == attrtype)
  316. return nla;
  317. return NULL;
  318. }
  319. /** @} */
  320. /**
  321. * @name Utilities
  322. * @{
  323. */
  324. /**
  325. * Copy a netlink attribute into another memory area
  326. * @arg dest where to copy to memcpy
  327. * @arg src netlink attribute to copy from
  328. * @arg count size of the destination area
  329. *
  330. * Note: The number of bytes copied is limited by the length of
  331. * attribute's payload. memcpy
  332. *
  333. * @return the number of bytes copied.
  334. */
  335. int nla_memcpy(void *dest, struct nlattr *src, int count)
  336. {
  337. int minlen;
  338. if (!src)
  339. return 0;
  340. minlen = min_t(int, count, nla_len(src));
  341. memcpy(dest, nla_data(src), minlen);
  342. return minlen;
  343. }
  344. /**
  345. * Copy string attribute payload into a sized buffer
  346. * @arg dst where to copy the string to
  347. * @arg nla attribute to copy the string from
  348. * @arg dstsize size of destination buffer
  349. *
  350. * Copies at most dstsize - 1 bytes into the destination buffer.
  351. * The result is always a valid NUL-terminated string. Unlike
  352. * strlcpy the destination buffer is always padded out.
  353. *
  354. * @return the length of the source buffer.
  355. */
  356. size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize)
  357. {
  358. size_t srclen = nla_len(nla);
  359. char *src = nla_data(nla);
  360. if (srclen > 0 && src[srclen - 1] == '\0')
  361. srclen--;
  362. if (dstsize > 0) {
  363. size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen;
  364. memset(dst, 0, dstsize);
  365. memcpy(dst, src, len);
  366. }
  367. return srclen;
  368. }
  369. /**
  370. * Compare an attribute with sized memory area
  371. * @arg nla netlink attribute
  372. * @arg data memory area
  373. * @arg size size of memory area
  374. */
  375. int nla_memcmp(const struct nlattr *nla, const void *data,
  376. size_t size)
  377. {
  378. int d = nla_len(nla) - size;
  379. if (d == 0)
  380. d = memcmp(nla_data(nla), data, size);
  381. return d;
  382. }
  383. /**
  384. * Compare a string attribute against a string
  385. * @arg nla netlink string attribute
  386. * @arg str another string
  387. */
  388. int nla_strcmp(const struct nlattr *nla, const char *str)
  389. {
  390. int len = strlen(str) + 1;
  391. int d = nla_len(nla) - len;
  392. if (d == 0)
  393. d = memcmp(nla_data(nla), str, len);
  394. return d;
  395. }
  396. /** @} */
  397. /**
  398. * @name Attribute Construction
  399. * @{
  400. */
  401. /**
  402. * reserve room for attribute on the skb
  403. * @arg n netlink message
  404. * @arg attrtype attribute type
  405. * @arg attrlen length of attribute payload
  406. *
  407. * Adds a netlink attribute header to a netlink message and reserves
  408. * room for the payload but does not copy it.
  409. */
  410. struct nlattr *nla_reserve(struct nl_msg *n, int attrtype, int attrlen)
  411. {
  412. struct nlattr *nla;
  413. int tlen;
  414. tlen = NLMSG_ALIGN(n->nm_nlh->nlmsg_len) + nla_total_size(attrlen);
  415. if (tlen > n->nm_size) {
  416. nl_errno(ENOBUFS);
  417. return NULL;
  418. }
  419. nla = (struct nlattr *) nlmsg_tail(n->nm_nlh);
  420. nla->nla_type = attrtype;
  421. nla->nla_len = nla_attr_size(attrlen);
  422. memset((unsigned char *) nla + nla->nla_len, 0, nla_padlen(attrlen));
  423. n->nm_nlh->nlmsg_len = tlen;
  424. NL_DBG(2, "msg %p: Reserved %d bytes at offset +%td for attr %d "
  425. "nlmsg_len=%d\n", n, attrlen,
  426. (void *) nla - nlmsg_data(n->nm_nlh),
  427. attrtype, n->nm_nlh->nlmsg_len);
  428. return nla;
  429. }
  430. /**
  431. * Add a netlink attribute to a netlink message
  432. * @arg n netlink message
  433. * @arg attrtype attribute type
  434. * @arg attrlen length of attribute payload
  435. * @arg data head of attribute payload
  436. *
  437. * @return -1 if the tailroom of the skb is insufficient to store
  438. * the attribute header and payload.
  439. */
  440. int nla_put(struct nl_msg *n, int attrtype, int attrlen, const void *data)
  441. {
  442. struct nlattr *nla;
  443. nla = nla_reserve(n, attrtype, attrlen);
  444. if (!nla)
  445. return nl_errno(ENOMEM);
  446. memcpy(nla_data(nla), data, attrlen);
  447. NL_DBG(2, "msg %p: Wrote %d bytes at offset +%td for attr %d\n",
  448. n, attrlen, (void *) nla - nlmsg_data(n->nm_nlh), attrtype);
  449. return 0;
  450. }
  451. /**
  452. * Add a nested netlink attribute to a netlink message
  453. * @arg n netlink message
  454. * @arg attrtype attribute type
  455. * @arg nested netlink attribute to nest
  456. *
  457. * @return -1 if the tailroom of the skb is insufficient to store
  458. * the attribute header and payload.
  459. */
  460. int nla_put_nested(struct nl_msg *n, int attrtype, struct nl_msg *nested)
  461. {
  462. return nla_put(n, attrtype, nlmsg_len(nested->nm_nlh),
  463. nlmsg_data(nested->nm_nlh));
  464. }
  465. /**
  466. * Add a u16 netlink attribute to a netlink message
  467. * @arg n netlink message
  468. * @arg attrtype attribute type
  469. * @arg value numeric value
  470. */
  471. int nla_put_u8(struct nl_msg *n, int attrtype, uint8_t value)
  472. {
  473. return nla_put(n, attrtype, sizeof(uint8_t), &value);
  474. }
  475. /**
  476. * Add a u16 netlink attribute to a netlink message
  477. * @arg n netlink message
  478. * @arg attrtype attribute type
  479. * @arg value numeric value
  480. */
  481. int nla_put_u16(struct nl_msg *n, int attrtype, uint16_t value)
  482. {
  483. return nla_put(n, attrtype, sizeof(uint16_t), &value);
  484. }
  485. /**
  486. * Add a u32 netlink attribute to a netlink message
  487. * @arg n netlink message
  488. * @arg attrtype attribute type
  489. * @arg value numeric value
  490. */
  491. int nla_put_u32(struct nl_msg *n, int attrtype, uint32_t value)
  492. {
  493. return nla_put(n, attrtype, sizeof(uint32_t), &value);
  494. }
  495. /**
  496. * Add a u64 netlink attribute to a netlink message
  497. * @arg n netlink message
  498. * @arg attrtype attribute type
  499. * @arg value numeric value
  500. */
  501. int nla_put_u64(struct nl_msg *n, int attrtype, uint64_t value)
  502. {
  503. return nla_put(n, attrtype, sizeof(uint64_t), &value);
  504. }
  505. /**
  506. * Add a string netlink attribute to a netlink message
  507. * @arg n netlink message
  508. * @arg attrtype attribute type
  509. * @arg str NUL terminated string
  510. */
  511. int nla_put_string(struct nl_msg *n, int attrtype, const char *str)
  512. {
  513. return nla_put(n, attrtype, strlen(str) + 1, str);
  514. }
  515. /**
  516. * Add a flag netlink attribute to a netlink message
  517. * @arg n netlink message
  518. * @arg attrtype attribute type
  519. */
  520. int nla_put_flag(struct nl_msg *n, int attrtype)
  521. {
  522. return nla_put(n, attrtype, 0, NULL);
  523. }
  524. /**
  525. * Add a msecs netlink attribute to a netlink message
  526. * @arg n netlink message
  527. * @arg attrtype attribute type
  528. * @arg msecs number of msecs
  529. */
  530. int nla_put_msecs(struct nl_msg *n, int attrtype, unsigned long msecs)
  531. {
  532. return nla_put_u64(n, attrtype, msecs);
  533. }
  534. /**
  535. * Add an abstract data netlink attribute to a netlink message
  536. * @arg n netlink message
  537. * @arg attrtype attribute type
  538. * @arg data abstract data
  539. */
  540. int nla_put_data(struct nl_msg *n, int attrtype, struct nl_data *data)
  541. {
  542. return nla_put(n, attrtype, nl_data_get_size(data),
  543. nl_data_get(data));
  544. }
  545. /**
  546. * Add an abstract address netlink attribute to a netlink message
  547. * @arg n netlink message
  548. * @arg attrtype attribute type
  549. * @arg addr abstract address
  550. */
  551. int nla_put_addr(struct nl_msg *n, int attrtype, struct nl_addr *addr)
  552. {
  553. return nla_put(n, attrtype, nl_addr_get_len(addr),
  554. nl_addr_get_binary_addr(addr));
  555. }
  556. /** @} */
  557. /**
  558. * @name Attribute Nesting
  559. * @{
  560. */
  561. /**
  562. * Start a new level of nested attributes
  563. * @arg n netlink message
  564. * @arg attrtype attribute type of container
  565. *
  566. * @return the container attribute
  567. */
  568. struct nlattr *nla_nest_start(struct nl_msg *n, int attrtype)
  569. {
  570. struct nlattr *start = (struct nlattr *) nlmsg_tail(n->nm_nlh);
  571. if (nla_put(n, attrtype, 0, NULL) < 0)
  572. return NULL;
  573. return start;
  574. }
  575. /**
  576. * Finalize nesting of attributes
  577. * @arg n netlink message
  578. * @arg start container attribute
  579. *
  580. * Corrects the container attribute header to include the all
  581. * appeneded attributes.
  582. *
  583. * @return the total data length of the skb.
  584. */
  585. int nla_nest_end(struct nl_msg *n, struct nlattr *start)
  586. {
  587. start->nla_len = (unsigned char *) nlmsg_tail(n->nm_nlh) -
  588. (unsigned char *) start;
  589. return 0;
  590. }
  591. /** @} */
  592. /**
  593. * @name Attribute Reading
  594. * @{
  595. */
  596. /**
  597. * Return payload of u32 attribute
  598. * @arg nla u32 netlink attribute
  599. */
  600. uint32_t nla_get_u32(struct nlattr *nla)
  601. {
  602. return *(uint32_t *) nla_data(nla);
  603. }
  604. /**
  605. * Return payload of u16 attribute
  606. * @arg nla u16 netlink attribute
  607. */
  608. uint16_t nla_get_u16(struct nlattr *nla)
  609. {
  610. return *(uint16_t *) nla_data(nla);
  611. }
  612. /**
  613. * Return payload of u8 attribute
  614. * @arg nla u8 netlink attribute
  615. */
  616. uint8_t nla_get_u8(struct nlattr *nla)
  617. {
  618. return *(uint8_t *) nla_data(nla);
  619. }
  620. /**
  621. * Return payload of u64 attribute
  622. * @arg nla u64 netlink attribute
  623. */
  624. uint64_t nla_get_u64(struct nlattr *nla)
  625. {
  626. uint64_t tmp;
  627. nla_memcpy(&tmp, nla, sizeof(tmp));
  628. return tmp;
  629. }
  630. /**
  631. * return payload of string attribute
  632. * @arg nla string netlink attribute
  633. */
  634. char *nla_get_string(struct nlattr *nla)
  635. {
  636. return (char *) nla_data(nla);
  637. }
  638. /**
  639. * Return payload of flag attribute
  640. * @arg nla flag netlink attribute
  641. */
  642. int nla_get_flag(struct nlattr *nla)
  643. {
  644. return !!nla;
  645. }
  646. /**
  647. * Return payload of msecs attribute
  648. * @arg nla msecs netlink attribute
  649. *
  650. * @return the number of milliseconds.
  651. */
  652. unsigned long nla_get_msecs(struct nlattr *nla)
  653. {
  654. return nla_get_u64(nla);
  655. }
  656. /**
  657. * Return payload of address attribute
  658. * @arg nla address netlink attribute
  659. * @arg family address family
  660. *
  661. * @return Newly allocated address handle or NULL
  662. */
  663. struct nl_addr *nla_get_addr(struct nlattr *nla, int family)
  664. {
  665. return nl_addr_build(family, nla_data(nla), nla_len(nla));
  666. }
  667. /**
  668. * Return payload of abstract data attribute
  669. * @arg nla abstract data netlink attribute
  670. *
  671. * @return Newly allocated abstract data handle or NULL
  672. */
  673. struct nl_data *nla_get_data(struct nlattr *nla)
  674. {
  675. return nl_data_alloc(nla_data(nla), nla_len(nla));
  676. }
  677. /** @} */
  678. /** @} */