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.

167 lines
5.1 KiB

2 years ago
  1. /*
  2. * (C) 2008-2010 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 <errno.h>
  10. #include "libmnl.h"
  11. static int mnl_cb_noop(const struct nlmsghdr *nlh, void *data)
  12. {
  13. return MNL_CB_OK;
  14. }
  15. static int mnl_cb_error(const struct nlmsghdr *nlh, void *data)
  16. {
  17. const struct nlmsgerr *err = mnl_nlmsg_get_payload(nlh);
  18. if (nlh->nlmsg_len < mnl_nlmsg_size(sizeof(struct nlmsgerr))) {
  19. errno = EBADMSG;
  20. return MNL_CB_ERROR;
  21. }
  22. /* Netlink subsystems returns the errno value with different signess */
  23. if (err->error < 0)
  24. errno = -err->error;
  25. else
  26. errno = err->error;
  27. return err->error == 0 ? MNL_CB_STOP : MNL_CB_ERROR;
  28. }
  29. static int mnl_cb_stop(const struct nlmsghdr *nlh, void *data)
  30. {
  31. return MNL_CB_STOP;
  32. }
  33. static const mnl_cb_t default_cb_array[NLMSG_MIN_TYPE] = {
  34. [NLMSG_NOOP] = mnl_cb_noop,
  35. [NLMSG_ERROR] = mnl_cb_error,
  36. [NLMSG_DONE] = mnl_cb_stop,
  37. [NLMSG_OVERRUN] = mnl_cb_noop,
  38. };
  39. static inline int __mnl_cb_run(const void *buf, size_t numbytes,
  40. unsigned int seq, unsigned int portid,
  41. mnl_cb_t cb_data, void *data,
  42. const mnl_cb_t *cb_ctl_array,
  43. unsigned int cb_ctl_array_len)
  44. {
  45. int ret = MNL_CB_OK, len = numbytes;
  46. const struct nlmsghdr *nlh = buf;
  47. while (mnl_nlmsg_ok(nlh, len)) {
  48. /* check message source */
  49. if (!mnl_nlmsg_portid_ok(nlh, portid)) {
  50. errno = ESRCH;
  51. return -1;
  52. }
  53. /* perform sequence tracking */
  54. if (!mnl_nlmsg_seq_ok(nlh, seq)) {
  55. errno = EPROTO;
  56. return -1;
  57. }
  58. /* dump was interrupted */
  59. if (nlh->nlmsg_flags & NLM_F_DUMP_INTR) {
  60. errno = EINTR;
  61. return -1;
  62. }
  63. /* netlink data message handling */
  64. if (nlh->nlmsg_type >= NLMSG_MIN_TYPE) {
  65. if (cb_data){
  66. ret = cb_data(nlh, data);
  67. if (ret <= MNL_CB_STOP)
  68. goto out;
  69. }
  70. } else if (nlh->nlmsg_type < cb_ctl_array_len) {
  71. if (cb_ctl_array && cb_ctl_array[nlh->nlmsg_type]) {
  72. ret = cb_ctl_array[nlh->nlmsg_type](nlh, data);
  73. if (ret <= MNL_CB_STOP)
  74. goto out;
  75. }
  76. } else if (default_cb_array[nlh->nlmsg_type]) {
  77. ret = default_cb_array[nlh->nlmsg_type](nlh, data);
  78. if (ret <= MNL_CB_STOP)
  79. goto out;
  80. }
  81. nlh = mnl_nlmsg_next(nlh, &len);
  82. }
  83. out:
  84. return ret;
  85. }
  86. /**
  87. * \defgroup callback Callback helpers
  88. * @{
  89. */
  90. /**
  91. * mnl_cb_run2 - callback runqueue for netlink messages
  92. * \param buf buffer that contains the netlink messages
  93. * \param numbytes number of bytes stored in the buffer
  94. * \param seq sequence number that we expect to receive
  95. * \param portid Netlink PortID that we expect to receive
  96. * \param cb_data callback handler for data messages
  97. * \param data pointer to data that will be passed to the data callback handler
  98. * \param cb_ctl_array array of custom callback handlers from control messages
  99. * \param cb_ctl_array_len array length of custom control callback handlers
  100. *
  101. * You can set the cb_ctl_array to NULL if you want to use the default control
  102. * callback handlers, in that case, the parameter cb_ctl_array_len is not
  103. * checked.
  104. *
  105. * Your callback may return three possible values:
  106. * - MNL_CB_ERROR (<=-1): an error has occurred. Stop callback runqueue.
  107. * - MNL_CB_STOP (=0): stop callback runqueue.
  108. * - MNL_CB_OK (>=1): no problem has occurred.
  109. *
  110. * This function propagates the callback return value. On error, it returns
  111. * -1 and errno is explicitly set. If the portID is not the expected, errno
  112. * is set to ESRCH. If the sequence number is not the expected, errno is set
  113. * to EPROTO. If the dump was interrupted, errno is set to EINTR and you should
  114. * request a new fresh dump again.
  115. */
  116. int mnl_cb_run2(const void *buf, size_t numbytes,
  117. unsigned int seq, unsigned int portid,
  118. mnl_cb_t cb_data, void *data,
  119. const mnl_cb_t *cb_ctl_array,
  120. unsigned int cb_ctl_array_len)
  121. {
  122. return __mnl_cb_run(buf, numbytes, seq, portid, cb_data, data,
  123. cb_ctl_array, cb_ctl_array_len);
  124. }
  125. /**
  126. * mnl_cb_run - callback runqueue for netlink messages (simplified version)
  127. * \param buf buffer that contains the netlink messages
  128. * \param numbytes number of bytes stored in the buffer
  129. * \param seq sequence number that we expect to receive
  130. * \param portid Netlink PortID that we expect to receive
  131. * \param cb_data callback handler for data messages
  132. * \param data pointer to data that will be passed to the data callback handler
  133. *
  134. * This function is like mnl_cb_run2() but it does not allow you to set
  135. * the control callback handlers.
  136. *
  137. * Your callback may return three possible values:
  138. * - MNL_CB_ERROR (<=-1): an error has occurred. Stop callback runqueue.
  139. * - MNL_CB_STOP (=0): stop callback runqueue.
  140. * - MNL_CB_OK (>=1): no problems has occurred.
  141. *
  142. * This function propagates the callback return value.
  143. */
  144. int mnl_cb_run(const void *buf, size_t numbytes, unsigned int seq,
  145. unsigned int portid, mnl_cb_t cb_data, void *data)
  146. {
  147. return __mnl_cb_run(buf, numbytes, seq, portid, cb_data, data, NULL, 0);
  148. }
  149. /**
  150. * @}
  151. */