batadv-genl.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. // SPDX-License-Identifier: MIT
  2. /* batman-adv helpers functions library
  3. *
  4. * Copyright (c) 2017, Sven Eckelmann <sven@narfation.org>
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. */
  24. #include "batadv-genl.h"
  25. #include <stdbool.h>
  26. #include <stddef.h>
  27. #include <stdio.h>
  28. #include <string.h>
  29. #include <unistd.h>
  30. #include <errno.h>
  31. #include <net/ethernet.h>
  32. #include <net/if.h>
  33. #include <netlink/netlink.h>
  34. #include <netlink/genl/genl.h>
  35. #include <netlink/genl/ctrl.h>
  36. #include <net/ethernet.h>
  37. #include "batman_adv.h"
  38. __attribute__ ((visibility ("default")))
  39. struct nla_policy batadv_genl_policy[NUM_BATADV_ATTR] = {
  40. [BATADV_ATTR_VERSION] = { .type = NLA_STRING },
  41. [BATADV_ATTR_ALGO_NAME] = { .type = NLA_STRING },
  42. [BATADV_ATTR_MESH_IFINDEX] = { .type = NLA_U32 },
  43. [BATADV_ATTR_MESH_IFNAME] = { .type = NLA_STRING,
  44. .maxlen = IFNAMSIZ },
  45. [BATADV_ATTR_MESH_ADDRESS] = { .type = NLA_UNSPEC,
  46. .minlen = ETH_ALEN,
  47. .maxlen = ETH_ALEN },
  48. [BATADV_ATTR_HARD_IFINDEX] = { .type = NLA_U32 },
  49. [BATADV_ATTR_HARD_IFNAME] = { .type = NLA_STRING,
  50. .maxlen = IFNAMSIZ },
  51. [BATADV_ATTR_HARD_ADDRESS] = { .type = NLA_UNSPEC,
  52. .minlen = ETH_ALEN,
  53. .maxlen = ETH_ALEN },
  54. [BATADV_ATTR_ORIG_ADDRESS] = { .type = NLA_UNSPEC,
  55. .minlen = ETH_ALEN,
  56. .maxlen = ETH_ALEN },
  57. [BATADV_ATTR_TPMETER_RESULT] = { .type = NLA_U8 },
  58. [BATADV_ATTR_TPMETER_TEST_TIME] = { .type = NLA_U32 },
  59. [BATADV_ATTR_TPMETER_BYTES] = { .type = NLA_U64 },
  60. [BATADV_ATTR_TPMETER_COOKIE] = { .type = NLA_U32 },
  61. [BATADV_ATTR_PAD] = { .type = NLA_UNSPEC },
  62. [BATADV_ATTR_ACTIVE] = { .type = NLA_FLAG },
  63. [BATADV_ATTR_TT_ADDRESS] = { .type = NLA_UNSPEC,
  64. .minlen = ETH_ALEN,
  65. .maxlen = ETH_ALEN },
  66. [BATADV_ATTR_TT_TTVN] = { .type = NLA_U8 },
  67. [BATADV_ATTR_TT_LAST_TTVN] = { .type = NLA_U8 },
  68. [BATADV_ATTR_TT_CRC32] = { .type = NLA_U32 },
  69. [BATADV_ATTR_TT_VID] = { .type = NLA_U16 },
  70. [BATADV_ATTR_TT_FLAGS] = { .type = NLA_U32 },
  71. [BATADV_ATTR_FLAG_BEST] = { .type = NLA_FLAG },
  72. [BATADV_ATTR_LAST_SEEN_MSECS] = { .type = NLA_U32 },
  73. [BATADV_ATTR_NEIGH_ADDRESS] = { .type = NLA_UNSPEC,
  74. .minlen = ETH_ALEN,
  75. .maxlen = ETH_ALEN },
  76. [BATADV_ATTR_TQ] = { .type = NLA_U8 },
  77. [BATADV_ATTR_THROUGHPUT] = { .type = NLA_U32 },
  78. [BATADV_ATTR_BANDWIDTH_UP] = { .type = NLA_U32 },
  79. [BATADV_ATTR_BANDWIDTH_DOWN] = { .type = NLA_U32 },
  80. [BATADV_ATTR_ROUTER] = { .type = NLA_UNSPEC,
  81. .minlen = ETH_ALEN,
  82. .maxlen = ETH_ALEN },
  83. [BATADV_ATTR_BLA_OWN] = { .type = NLA_FLAG },
  84. [BATADV_ATTR_BLA_ADDRESS] = { .type = NLA_UNSPEC,
  85. .minlen = ETH_ALEN,
  86. .maxlen = ETH_ALEN },
  87. [BATADV_ATTR_BLA_VID] = { .type = NLA_U16 },
  88. [BATADV_ATTR_BLA_BACKBONE] = { .type = NLA_UNSPEC,
  89. .minlen = ETH_ALEN,
  90. .maxlen = ETH_ALEN },
  91. [BATADV_ATTR_BLA_CRC] = { .type = NLA_U16 },
  92. };
  93. /**
  94. * nlquery_error_cb() - Store error value in &batadv_nlquery_opts->error and
  95. * stop processing
  96. * @nla: netlink address of the peer
  97. * @nlerr: netlink error message being processed
  98. * @arg: &struct batadv_nlquery_opts given to batadv_genl_query()
  99. *
  100. * Return: Always NL_STOP
  101. */
  102. static int nlquery_error_cb(struct sockaddr_nl *nla __attribute__((unused)),
  103. struct nlmsgerr *nlerr, void *arg)
  104. {
  105. struct batadv_nlquery_opts *query_opts = arg;
  106. query_opts->err = nlerr->error;
  107. return NL_STOP;
  108. }
  109. /**
  110. * nlquery_stop_cb() - Store error value in &batadv_nlquery_opts->error and
  111. * stop processing
  112. * @msg: netlink message being processed
  113. * @arg: &struct batadv_nlquery_opts given to batadv_genl_query()
  114. *
  115. * Return: Always NL_STOP
  116. */
  117. static int nlquery_stop_cb(struct nl_msg *msg, void *arg)
  118. {
  119. struct nlmsghdr *nlh = nlmsg_hdr(msg);
  120. struct batadv_nlquery_opts *query_opts = arg;
  121. int *error = nlmsg_data(nlh);
  122. if (*error)
  123. query_opts->err = *error;
  124. return NL_STOP;
  125. }
  126. /**
  127. * batadv_genl_query() - Start a common batman-adv generic netlink query
  128. * @mesh_iface: name of the batman-adv mesh interface
  129. * @nl_cmd: &enum batadv_nl_commands which should be sent to kernel
  130. * @callback: receive callback for valid messages
  131. * @flags: additional netlink message header flags
  132. * @query_opts: pointer to &struct batadv_nlquery_opts which is used to save
  133. * the current processing state. This is given as arg to @callback
  134. *
  135. * Return: 0 on success or negative error value otherwise
  136. */
  137. __attribute__ ((visibility ("default")))
  138. int batadv_genl_query(const char *mesh_iface, enum batadv_nl_commands nl_cmd,
  139. nl_recvmsg_msg_cb_t callback, int flags,
  140. struct batadv_nlquery_opts *query_opts)
  141. {
  142. struct nl_sock *sock;
  143. struct nl_msg *msg;
  144. struct nl_cb *cb;
  145. int ifindex;
  146. int family;
  147. int ret;
  148. query_opts->err = 0;
  149. sock = nl_socket_alloc();
  150. if (!sock)
  151. return -ENOMEM;
  152. ret = genl_connect(sock);
  153. if (ret < 0) {
  154. query_opts->err = ret;
  155. goto err_free_sock;
  156. }
  157. family = genl_ctrl_resolve(sock, BATADV_NL_NAME);
  158. if (family < 0) {
  159. query_opts->err = -EOPNOTSUPP;
  160. goto err_free_sock;
  161. }
  162. ifindex = if_nametoindex(mesh_iface);
  163. if (!ifindex) {
  164. query_opts->err = -ENODEV;
  165. goto err_free_sock;
  166. }
  167. cb = nl_cb_alloc(NL_CB_DEFAULT);
  168. if (!cb) {
  169. query_opts->err = -ENOMEM;
  170. goto err_free_sock;
  171. }
  172. nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, callback, query_opts);
  173. nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, nlquery_stop_cb, query_opts);
  174. nl_cb_err(cb, NL_CB_CUSTOM, nlquery_error_cb, query_opts);
  175. msg = nlmsg_alloc();
  176. if (!msg) {
  177. query_opts->err = -ENOMEM;
  178. goto err_free_cb;
  179. }
  180. genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, flags,
  181. nl_cmd, 1);
  182. nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, ifindex);
  183. nl_send_auto_complete(sock, msg);
  184. nlmsg_free(msg);
  185. nl_recvmsgs(sock, cb);
  186. err_free_cb:
  187. nl_cb_put(cb);
  188. err_free_sock:
  189. nl_socket_free(sock);
  190. return query_opts->err;
  191. }