You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

722 lines
24 KiB

2 years ago
  1. /*
  2. * (C) 2008-2012 by Pablo Neira Ayuso <pablo@netfilter.org>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU Lesser General Public License as published
  6. * by the Free Software Foundation; either version 2.1 of the License, or
  7. * (at your option) any later version.
  8. */
  9. #include <limits.h> /* for INT_MAX */
  10. #include <string.h>
  11. #include <errno.h>
  12. #include "libmnl.h"
  13. /**
  14. * \defgroup attr Netlink attribute helpers
  15. *
  16. * Netlink Type-Length-Value (TLV) attribute:
  17. * \verbatim
  18. |<-- 2 bytes -->|<-- 2 bytes -->|<-- variable -->|
  19. -------------------------------------------------
  20. | length | type | value |
  21. -------------------------------------------------
  22. |<--------- header ------------>|<-- payload --->|
  23. \endverbatim
  24. * The payload of the Netlink message contains sequences of attributes that are
  25. * expressed in TLV format.
  26. *
  27. * @{
  28. */
  29. /**
  30. * mnl_attr_get_type - get type of netlink attribute
  31. * \param attr pointer to netlink attribute
  32. *
  33. * This function returns the attribute type.
  34. */
  35. uint16_t mnl_attr_get_type(const struct nlattr *attr)
  36. {
  37. return attr->nla_type & NLA_TYPE_MASK;
  38. }
  39. /**
  40. * mnl_attr_get_len - get length of netlink attribute
  41. * \param attr pointer to netlink attribute
  42. *
  43. * This function returns the attribute length that is the attribute header
  44. * plus the attribute payload.
  45. */
  46. uint16_t mnl_attr_get_len(const struct nlattr *attr)
  47. {
  48. return attr->nla_len;
  49. }
  50. /**
  51. * mnl_attr_get_payload_len - get the attribute payload-value length
  52. * \param attr pointer to netlink attribute
  53. *
  54. * This function returns the attribute payload-value length.
  55. */
  56. uint16_t mnl_attr_get_payload_len(const struct nlattr *attr)
  57. {
  58. return attr->nla_len - MNL_ATTR_HDRLEN;
  59. }
  60. /**
  61. * mnl_attr_get_payload - get pointer to the attribute payload
  62. * \param attr pointer to netlink attribute
  63. *
  64. * This function return a pointer to the attribute payload.
  65. */
  66. void *mnl_attr_get_payload(const struct nlattr *attr)
  67. {
  68. return (void *)attr + MNL_ATTR_HDRLEN;
  69. }
  70. /**
  71. * mnl_attr_ok - check if there is room for an attribute in a buffer
  72. * \param attr attribute that we want to check if there is room for
  73. * \param len remaining bytes in a buffer that contains the attribute
  74. *
  75. * This function is used to check that a buffer, which is supposed to contain
  76. * an attribute, has enough room for the attribute that it stores, i.e. this
  77. * function can be used to verify that an attribute is neither malformed nor
  78. * truncated.
  79. *
  80. * This function does not set errno in case of error since it is intended
  81. * for iterations. Thus, it returns true on success and false on error.
  82. *
  83. * The len parameter may be negative in the case of malformed messages during
  84. * attribute iteration, that is why we use a signed integer.
  85. */
  86. bool mnl_attr_ok(const struct nlattr *attr, int len)
  87. {
  88. return len >= (int)sizeof(struct nlattr) &&
  89. attr->nla_len >= sizeof(struct nlattr) &&
  90. (int)attr->nla_len <= len;
  91. }
  92. /**
  93. * mnl_attr_next - get the next attribute in the payload of a netlink message
  94. * \param attr pointer to the current attribute
  95. *
  96. * This function returns a pointer to the next attribute after the one passed
  97. * as parameter. You have to use mnl_attr_ok() to ensure that the next
  98. * attribute is valid.
  99. */
  100. struct nlattr *mnl_attr_next(const struct nlattr *attr)
  101. {
  102. return (struct nlattr *)((void *)attr + MNL_ALIGN(attr->nla_len));
  103. }
  104. /**
  105. * mnl_attr_type_valid - check if the attribute type is valid
  106. * \param attr pointer to attribute to be checked
  107. * \param max maximum attribute type
  108. *
  109. * This function allows to check if the attribute type is higher than the
  110. * maximum supported type. If the attribute type is invalid, this function
  111. * returns -1 and errno is explicitly set. On success, this function returns 1.
  112. *
  113. * Strict attribute checking in user-space is not a good idea since you may
  114. * run an old application with a newer kernel that supports new attributes.
  115. * This leads to backward compatibility breakages in user-space. Better check
  116. * if you support an attribute, if not, skip it.
  117. */
  118. int mnl_attr_type_valid(const struct nlattr *attr, uint16_t max)
  119. {
  120. if (mnl_attr_get_type(attr) > max) {
  121. errno = EOPNOTSUPP;
  122. return -1;
  123. }
  124. return 1;
  125. }
  126. static int __mnl_attr_validate(const struct nlattr *attr,
  127. enum mnl_attr_data_type type, size_t exp_len)
  128. {
  129. uint16_t attr_len = mnl_attr_get_payload_len(attr);
  130. const char *attr_data = mnl_attr_get_payload(attr);
  131. if (attr_len < exp_len) {
  132. errno = ERANGE;
  133. return -1;
  134. }
  135. switch(type) {
  136. case MNL_TYPE_FLAG:
  137. if (attr_len > 0) {
  138. errno = ERANGE;
  139. return -1;
  140. }
  141. break;
  142. case MNL_TYPE_NUL_STRING:
  143. if (attr_len == 0) {
  144. errno = ERANGE;
  145. return -1;
  146. }
  147. if (attr_data[attr_len-1] != '\0') {
  148. errno = EINVAL;
  149. return -1;
  150. }
  151. break;
  152. case MNL_TYPE_STRING:
  153. if (attr_len == 0) {
  154. errno = ERANGE;
  155. return -1;
  156. }
  157. break;
  158. case MNL_TYPE_NESTED:
  159. /* empty nested attributes are OK. */
  160. if (attr_len == 0)
  161. break;
  162. /* if not empty, they must contain one header, eg. flag */
  163. if (attr_len < MNL_ATTR_HDRLEN) {
  164. errno = ERANGE;
  165. return -1;
  166. }
  167. break;
  168. default:
  169. /* make gcc happy. */
  170. break;
  171. }
  172. if (exp_len && attr_len > exp_len) {
  173. errno = ERANGE;
  174. return -1;
  175. }
  176. return 0;
  177. }
  178. static const size_t mnl_attr_data_type_len[MNL_TYPE_MAX] = {
  179. [MNL_TYPE_U8] = sizeof(uint8_t),
  180. [MNL_TYPE_U16] = sizeof(uint16_t),
  181. [MNL_TYPE_U32] = sizeof(uint32_t),
  182. [MNL_TYPE_U64] = sizeof(uint64_t),
  183. [MNL_TYPE_MSECS] = sizeof(uint64_t),
  184. };
  185. /**
  186. * mnl_attr_validate - validate netlink attribute (simplified version)
  187. * \param attr pointer to netlink attribute that we want to validate
  188. * \param type data type (see enum mnl_attr_data_type)
  189. *
  190. * The validation is based on the data type. Specifically, it checks that
  191. * integers (u8, u16, u32 and u64) have enough room for them. This function
  192. * returns -1 in case of error, and errno is explicitly set.
  193. */
  194. int mnl_attr_validate(const struct nlattr *attr, enum mnl_attr_data_type type)
  195. {
  196. int exp_len;
  197. if (type >= MNL_TYPE_MAX) {
  198. errno = EINVAL;
  199. return -1;
  200. }
  201. exp_len = mnl_attr_data_type_len[type];
  202. return __mnl_attr_validate(attr, type, exp_len);
  203. }
  204. /**
  205. * mnl_attr_validate2 - validate netlink attribute (extended version)
  206. * \param attr pointer to netlink attribute that we want to validate
  207. * \param type attribute type (see enum mnl_attr_data_type)
  208. * \param exp_len expected attribute data size
  209. *
  210. * This function allows to perform a more accurate validation for attributes
  211. * whose size is variable. If the size of the attribute is not what we expect,
  212. * this functions returns -1 and errno is explicitly set.
  213. */
  214. int mnl_attr_validate2(const struct nlattr *attr,
  215. enum mnl_attr_data_type type,
  216. size_t exp_len)
  217. {
  218. if (type >= MNL_TYPE_MAX) {
  219. errno = EINVAL;
  220. return -1;
  221. }
  222. return __mnl_attr_validate(attr, type, exp_len);
  223. }
  224. /**
  225. * mnl_attr_parse - parse attributes
  226. * \param nlh pointer to netlink message
  227. * \param offset offset to start parsing from (if payload is after any header)
  228. * \param cb callback function that is called for each attribute
  229. * \param data pointer to data that is passed to the callback function
  230. *
  231. * This function allows to iterate over the sequence of attributes that compose
  232. * the Netlink message. You can then put the attribute in an array as it
  233. * usually happens at this stage or you can use any other data structure (such
  234. * as lists or trees).
  235. *
  236. * This function propagates the return value of the callback, which can be
  237. * MNL_CB_ERROR, MNL_CB_OK or MNL_CB_STOP.
  238. */
  239. int mnl_attr_parse(const struct nlmsghdr *nlh,
  240. unsigned int offset, mnl_attr_cb_t cb,
  241. void *data)
  242. {
  243. int ret = MNL_CB_OK;
  244. const struct nlattr *attr;
  245. mnl_attr_for_each(attr, nlh, offset)
  246. if ((ret = cb(attr, data)) <= MNL_CB_STOP)
  247. return ret;
  248. return ret;
  249. }
  250. /**
  251. * mnl_attr_parse_nested - parse attributes inside a nest
  252. * \param nested pointer to netlink attribute that contains a nest
  253. * \param cb callback function that is called for each attribute in the nest
  254. * \param data pointer to data passed to the callback function
  255. *
  256. * This function allows to iterate over the sequence of attributes that compose
  257. * the Netlink message. You can then put the attribute in an array as it
  258. * usually happens at this stage or you can use any other data structure (such
  259. * as lists or trees).
  260. *
  261. * This function propagates the return value of the callback, which can be
  262. * MNL_CB_ERROR, MNL_CB_OK or MNL_CB_STOP.
  263. */
  264. int mnl_attr_parse_nested(const struct nlattr *nested,
  265. mnl_attr_cb_t cb, void *data)
  266. {
  267. int ret = MNL_CB_OK;
  268. const struct nlattr *attr;
  269. mnl_attr_for_each_nested(attr, nested)
  270. if ((ret = cb(attr, data)) <= MNL_CB_STOP)
  271. return ret;
  272. return ret;
  273. }
  274. /**
  275. * mnl_attr_parse_payload - parse attributes in payload of Netlink message
  276. * \param payload pointer to payload of the Netlink message
  277. * \param payload_len payload length that contains the attributes
  278. * \param cb callback function that is called for each attribute
  279. * \param data pointer to data that is passed to the callback function
  280. *
  281. * This function takes a pointer to the area that contains the attributes,
  282. * commonly known as the payload of the Netlink message. Thus, you have to
  283. * pass a pointer to the Netlink message payload, instead of the entire
  284. * message.
  285. *
  286. * This function allows you to iterate over the sequence of attributes that are
  287. * located at some payload offset. You can then put the attributes in one array
  288. * as usual, or you can use any other data structure (such as lists or trees).
  289. *
  290. * This function propagates the return value of the callback, which can be
  291. * MNL_CB_ERROR, MNL_CB_OK or MNL_CB_STOP.
  292. */
  293. int mnl_attr_parse_payload(const void *payload,
  294. size_t payload_len,
  295. mnl_attr_cb_t cb, void *data)
  296. {
  297. int ret = MNL_CB_OK;
  298. const struct nlattr *attr;
  299. mnl_attr_for_each_payload(payload, payload_len)
  300. if ((ret = cb(attr, data)) <= MNL_CB_STOP)
  301. return ret;
  302. return ret;
  303. }
  304. /**
  305. * mnl_attr_get_u8 - returns 8-bit unsigned integer attribute payload
  306. * \param attr pointer to netlink attribute
  307. *
  308. * This function returns the 8-bit value of the attribute payload.
  309. */
  310. uint8_t mnl_attr_get_u8(const struct nlattr *attr)
  311. {
  312. return *((uint8_t *)mnl_attr_get_payload(attr));
  313. }
  314. /**
  315. * mnl_attr_get_u16 - returns 16-bit unsigned integer attribute payload
  316. * \param attr pointer to netlink attribute
  317. *
  318. * This function returns the 16-bit value of the attribute payload.
  319. */
  320. uint16_t mnl_attr_get_u16(const struct nlattr *attr)
  321. {
  322. return *((uint16_t *)mnl_attr_get_payload(attr));
  323. }
  324. /**
  325. * mnl_attr_get_u32 - returns 32-bit unsigned integer attribute payload
  326. * \param attr pointer to netlink attribute
  327. *
  328. * This function returns the 32-bit value of the attribute payload.
  329. */
  330. uint32_t mnl_attr_get_u32(const struct nlattr *attr)
  331. {
  332. return *((uint32_t *)mnl_attr_get_payload(attr));
  333. }
  334. /**
  335. * mnl_attr_get_u64 - returns 64-bit unsigned integer attribute.
  336. * \param attr pointer to netlink attribute
  337. *
  338. * This function returns the 64-bit value of the attribute payload. This
  339. * function is align-safe, since accessing 64-bit Netlink attributes is a
  340. * common source of alignment issues.
  341. */
  342. uint64_t mnl_attr_get_u64(const struct nlattr *attr)
  343. {
  344. uint64_t tmp;
  345. memcpy(&tmp, mnl_attr_get_payload(attr), sizeof(tmp));
  346. return tmp;
  347. }
  348. /**
  349. * mnl_attr_get_str - returns pointer to string attribute.
  350. * \param attr pointer to netlink attribute
  351. *
  352. * This function returns the payload of string attribute value.
  353. */
  354. const char *mnl_attr_get_str(const struct nlattr *attr)
  355. {
  356. return mnl_attr_get_payload(attr);
  357. }
  358. /**
  359. * mnl_attr_put - add an attribute to netlink message
  360. * \param nlh pointer to the netlink message
  361. * \param type netlink attribute type that you want to add
  362. * \param len netlink attribute payload length
  363. * \param data pointer to the data that will be stored by the new attribute
  364. *
  365. * This function updates the length field of the Netlink message (nlmsg_len)
  366. * by adding the size (header + payload) of the new attribute.
  367. */
  368. void mnl_attr_put(struct nlmsghdr *nlh, uint16_t type,
  369. size_t len, const void *data)
  370. {
  371. struct nlattr *attr = mnl_nlmsg_get_payload_tail(nlh);
  372. uint16_t payload_len = MNL_ALIGN(sizeof(struct nlattr)) + len;
  373. int pad;
  374. attr->nla_type = type;
  375. attr->nla_len = payload_len;
  376. memcpy(mnl_attr_get_payload(attr), data, len);
  377. pad = MNL_ALIGN(len) - len;
  378. if (pad > 0)
  379. memset(mnl_attr_get_payload(attr) + len, 0, pad);
  380. nlh->nlmsg_len += MNL_ALIGN(payload_len);
  381. }
  382. /**
  383. * mnl_attr_put_u8 - add 8-bit unsigned integer attribute to netlink message
  384. * \param nlh pointer to the netlink message
  385. * \param type netlink attribute type
  386. * \param data 8-bit unsigned integer data that is stored by the new attribute
  387. *
  388. * This function updates the length field of the Netlink message (nlmsg_len)
  389. * by adding the size (header + payload) of the new attribute.
  390. */
  391. void mnl_attr_put_u8(struct nlmsghdr *nlh, uint16_t type,
  392. uint8_t data)
  393. {
  394. mnl_attr_put(nlh, type, sizeof(uint8_t), &data);
  395. }
  396. /**
  397. * mnl_attr_put_u16 - add 16-bit unsigned integer attribute to netlink message
  398. * \param nlh pointer to the netlink message
  399. * \param type netlink attribute type
  400. * \param data 16-bit unsigned integer data that is stored by the new attribute
  401. *
  402. * This function updates the length field of the Netlink message (nlmsg_len)
  403. * by adding the size (header + payload) of the new attribute.
  404. */
  405. void mnl_attr_put_u16(struct nlmsghdr *nlh, uint16_t type,
  406. uint16_t data)
  407. {
  408. mnl_attr_put(nlh, type, sizeof(uint16_t), &data);
  409. }
  410. /**
  411. * mnl_attr_put_u32 - add 32-bit unsigned integer attribute to netlink message
  412. * \param nlh pointer to the netlink message
  413. * \param type netlink attribute type
  414. * \param data 32-bit unsigned integer data that is stored by the new attribute
  415. *
  416. * This function updates the length field of the Netlink message (nlmsg_len)
  417. * by adding the size (header + payload) of the new attribute.
  418. */
  419. void mnl_attr_put_u32(struct nlmsghdr *nlh, uint16_t type,
  420. uint32_t data)
  421. {
  422. mnl_attr_put(nlh, type, sizeof(uint32_t), &data);
  423. }
  424. /**
  425. * mnl_attr_put_u64 - add 64-bit unsigned integer attribute to netlink message
  426. * \param nlh pointer to the netlink message
  427. * \param type netlink attribute type
  428. * \param data 64-bit unsigned integer data that is stored by the new attribute
  429. *
  430. * This function updates the length field of the Netlink message (nlmsg_len)
  431. * by adding the size (header + payload) of the new attribute.
  432. */
  433. void mnl_attr_put_u64(struct nlmsghdr *nlh, uint16_t type,
  434. uint64_t data)
  435. {
  436. mnl_attr_put(nlh, type, sizeof(uint64_t), &data);
  437. }
  438. /**
  439. * mnl_attr_put_str - add string attribute to netlink message
  440. * \param nlh pointer to the netlink message
  441. * \param type netlink attribute type
  442. * \param data pointer to string data that is stored by the new attribute
  443. *
  444. * This function updates the length field of the Netlink message (nlmsg_len)
  445. * by adding the size (header + payload) of the new attribute.
  446. */
  447. void mnl_attr_put_str(struct nlmsghdr *nlh, uint16_t type,
  448. const char *data)
  449. {
  450. mnl_attr_put(nlh, type, strlen(data), data);
  451. }
  452. /**
  453. * mnl_attr_put_strz - add string attribute to netlink message
  454. * \param nlh pointer to the netlink message
  455. * \param type netlink attribute type
  456. * \param data pointer to string data that is stored by the new attribute
  457. *
  458. * This function is similar to mnl_attr_put_str, but it includes the
  459. * NUL/zero ('\0') terminator at the end of the string.
  460. *
  461. * This function updates the length field of the Netlink message (nlmsg_len)
  462. * by adding the size (header + payload) of the new attribute.
  463. */
  464. void mnl_attr_put_strz(struct nlmsghdr *nlh, uint16_t type,
  465. const char *data)
  466. {
  467. mnl_attr_put(nlh, type, strlen(data)+1, data);
  468. }
  469. /**
  470. * mnl_attr_nest_start - start an attribute nest
  471. * \param nlh pointer to the netlink message
  472. * \param type netlink attribute type
  473. *
  474. * This function adds the attribute header that identifies the beginning of
  475. * an attribute nest. This function always returns a valid pointer to the
  476. * beginning of the nest.
  477. */
  478. struct nlattr *mnl_attr_nest_start(struct nlmsghdr *nlh,
  479. uint16_t type)
  480. {
  481. struct nlattr *start = mnl_nlmsg_get_payload_tail(nlh);
  482. /* set start->nla_len in mnl_attr_nest_end() */
  483. start->nla_type = NLA_F_NESTED | type;
  484. nlh->nlmsg_len += MNL_ALIGN(sizeof(struct nlattr));
  485. return start;
  486. }
  487. /**
  488. * mnl_attr_put_check - add an attribute to netlink message
  489. * \param nlh pointer to the netlink message
  490. * \param buflen size of buffer which stores the message
  491. * \param type netlink attribute type that you want to add
  492. * \param len netlink attribute payload length
  493. * \param data pointer to the data that will be stored by the new attribute
  494. *
  495. * This function first checks that the data can be added to the message
  496. * (fits into the buffer) and then updates the length field of the Netlink
  497. * message (nlmsg_len) by adding the size (header + payload) of the new
  498. * attribute. The function returns true if the attribute could be added
  499. * to the message, otherwise false is returned.
  500. */
  501. bool mnl_attr_put_check(struct nlmsghdr *nlh, size_t buflen,
  502. uint16_t type, size_t len,
  503. const void *data)
  504. {
  505. if (nlh->nlmsg_len + MNL_ATTR_HDRLEN + MNL_ALIGN(len) > buflen)
  506. return false;
  507. mnl_attr_put(nlh, type, len, data);
  508. return true;
  509. }
  510. /**
  511. * mnl_attr_put_u8_check - add 8-bit unsigned int attribute to netlink message
  512. * \param nlh pointer to the netlink message
  513. * \param buflen size of buffer which stores the message
  514. * \param type netlink attribute type
  515. * \param data 8-bit unsigned integer data that is stored by the new attribute
  516. *
  517. * This function first checks that the data can be added to the message
  518. * (fits into the buffer) and then updates the length field of the Netlink
  519. * message (nlmsg_len) by adding the size (header + payload) of the new
  520. * attribute. The function returns true if the attribute could be added
  521. * to the message, otherwise false is returned.
  522. */
  523. bool mnl_attr_put_u8_check(struct nlmsghdr *nlh, size_t buflen,
  524. uint16_t type, uint8_t data)
  525. {
  526. return mnl_attr_put_check(nlh, buflen, type, sizeof(uint8_t), &data);
  527. }
  528. /**
  529. * mnl_attr_put_u16_check - add 16-bit unsigned int attribute to netlink message
  530. * \param nlh pointer to the netlink message
  531. * \param buflen size of buffer which stores the message
  532. * \param type netlink attribute type
  533. * \param data 16-bit unsigned integer data that is stored by the new attribute
  534. *
  535. * This function first checks that the data can be added to the message
  536. * (fits into the buffer) and then updates the length field of the Netlink
  537. * message (nlmsg_len) by adding the size (header + payload) of the new
  538. * attribute. The function returns true if the attribute could be added
  539. * to the message, otherwise false is returned.
  540. * This function updates the length field of the Netlink message (nlmsg_len)
  541. * by adding the size (header + payload) of the new attribute.
  542. */
  543. bool mnl_attr_put_u16_check(struct nlmsghdr *nlh, size_t buflen,
  544. uint16_t type, uint16_t data)
  545. {
  546. return mnl_attr_put_check(nlh, buflen, type, sizeof(uint16_t), &data);
  547. }
  548. /**
  549. * mnl_attr_put_u32_check - add 32-bit unsigned int attribute to netlink message
  550. * \param nlh pointer to the netlink message
  551. * \param buflen size of buffer which stores the message
  552. * \param type netlink attribute type
  553. * \param data 32-bit unsigned integer data that is stored by the new attribute
  554. *
  555. * This function first checks that the data can be added to the message
  556. * (fits into the buffer) and then updates the length field of the Netlink
  557. * message (nlmsg_len) by adding the size (header + payload) of the new
  558. * attribute. The function returns true if the attribute could be added
  559. * to the message, otherwise false is returned.
  560. * This function updates the length field of the Netlink message (nlmsg_len)
  561. * by adding the size (header + payload) of the new attribute.
  562. */
  563. bool mnl_attr_put_u32_check(struct nlmsghdr *nlh, size_t buflen,
  564. uint16_t type, uint32_t data)
  565. {
  566. return mnl_attr_put_check(nlh, buflen, type, sizeof(uint32_t), &data);
  567. }
  568. /**
  569. * mnl_attr_put_u64_check - add 64-bit unsigned int attribute to netlink message
  570. * \param nlh pointer to the netlink message
  571. * \param buflen size of buffer which stores the message
  572. * \param type netlink attribute type
  573. * \param data 64-bit unsigned integer data that is stored by the new attribute
  574. *
  575. * This function first checks that the data can be added to the message
  576. * (fits into the buffer) and then updates the length field of the Netlink
  577. * message (nlmsg_len) by adding the size (header + payload) of the new
  578. * attribute. The function returns true if the attribute could be added
  579. * to the message, otherwise false is returned.
  580. * This function updates the length field of the Netlink message (nlmsg_len)
  581. * by adding the size (header + payload) of the new attribute.
  582. */
  583. bool mnl_attr_put_u64_check(struct nlmsghdr *nlh, size_t buflen,
  584. uint16_t type, uint64_t data)
  585. {
  586. return mnl_attr_put_check(nlh, buflen, type, sizeof(uint64_t), &data);
  587. }
  588. /**
  589. * mnl_attr_put_str_check - add string attribute to netlink message
  590. * \param nlh pointer to the netlink message
  591. * \param buflen size of buffer which stores the message
  592. * \param type netlink attribute type
  593. * \param data pointer to string data that is stored by the new attribute
  594. *
  595. * This function first checks that the data can be added to the message
  596. * (fits into the buffer) and then updates the length field of the Netlink
  597. * message (nlmsg_len) by adding the size (header + payload) of the new
  598. * attribute. The function returns true if the attribute could be added
  599. * to the message, otherwise false is returned.
  600. * This function updates the length field of the Netlink message (nlmsg_len)
  601. * by adding the size (header + payload) of the new attribute.
  602. */
  603. bool mnl_attr_put_str_check(struct nlmsghdr *nlh, size_t buflen,
  604. uint16_t type, const char *data)
  605. {
  606. return mnl_attr_put_check(nlh, buflen, type, strlen(data), data);
  607. }
  608. /**
  609. * mnl_attr_put_strz_check - add string attribute to netlink message
  610. * \param nlh pointer to the netlink message
  611. * \param buflen size of buffer which stores the message
  612. * \param type netlink attribute type
  613. * \param data pointer to string data that is stored by the new attribute
  614. *
  615. * This function is similar to mnl_attr_put_str, but it includes the
  616. * NUL/zero ('\0') terminator at the end of the string.
  617. *
  618. * This function first checks that the data can be added to the message
  619. * (fits into the buffer) and then updates the length field of the Netlink
  620. * message (nlmsg_len) by adding the size (header + payload) of the new
  621. * attribute. The function returns true if the attribute could be added
  622. * to the message, otherwise false is returned.
  623. */
  624. bool mnl_attr_put_strz_check(struct nlmsghdr *nlh, size_t buflen,
  625. uint16_t type, const char *data)
  626. {
  627. return mnl_attr_put_check(nlh, buflen, type, strlen(data)+1, data);
  628. }
  629. /**
  630. * mnl_attr_nest_start_check - start an attribute nest
  631. * \param buflen size of buffer which stores the message
  632. * \param nlh pointer to the netlink message
  633. * \param type netlink attribute type
  634. *
  635. * This function adds the attribute header that identifies the beginning of
  636. * an attribute nest. If the nested attribute cannot be added then NULL,
  637. * otherwise valid pointer to the beginning of the nest is returned.
  638. */
  639. struct nlattr *mnl_attr_nest_start_check(struct nlmsghdr *nlh,
  640. size_t buflen,
  641. uint16_t type)
  642. {
  643. if (nlh->nlmsg_len + MNL_ATTR_HDRLEN > buflen)
  644. return NULL;
  645. return mnl_attr_nest_start(nlh, type);
  646. }
  647. /**
  648. * mnl_attr_nest_end - end an attribute nest
  649. * \param nlh pointer to the netlink message
  650. * \param start pointer to the attribute nest returned by mnl_attr_nest_start()
  651. *
  652. * This function updates the attribute header that identifies the nest.
  653. */
  654. void mnl_attr_nest_end(struct nlmsghdr *nlh,
  655. struct nlattr *start)
  656. {
  657. start->nla_len = mnl_nlmsg_get_payload_tail(nlh) - (void *)start;
  658. }
  659. /**
  660. * mnl_attr_nest_cancel - cancel an attribute nest
  661. * \param nlh pointer to the netlink message
  662. * \param start pointer to the attribute nest returned by mnl_attr_nest_start()
  663. *
  664. * This function updates the attribute header that identifies the nest.
  665. */
  666. void mnl_attr_nest_cancel(struct nlmsghdr *nlh,
  667. struct nlattr *start)
  668. {
  669. nlh->nlmsg_len -= mnl_nlmsg_get_payload_tail(nlh) - (void *)start;
  670. }
  671. /**
  672. * @}
  673. */