batadv-netlink.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /*
  2. * Copyright (C) 2009-2016 B.A.T.M.A.N. contributors:
  3. *
  4. * Marek Lindner <mareklindner@neomailbox.ch>, Andrew Lunn <andrew@lunn.ch>
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of version 2 of the GNU General Public
  8. * License as published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  18. * 02110-1301, USA
  19. *
  20. */
  21. #include "batadv-netlink.h"
  22. #include <stdbool.h>
  23. #include <stddef.h>
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include <unistd.h>
  27. #include <errno.h>
  28. #include <net/ethernet.h>
  29. #include <net/if.h>
  30. #include <netlink/netlink.h>
  31. #include <netlink/genl/genl.h>
  32. #include <netlink/genl/ctrl.h>
  33. #include <net/ethernet.h>
  34. #include "batman_adv.h"
  35. #ifndef __maybe_unused
  36. #define __maybe_unused __attribute__((unused))
  37. #endif
  38. struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = {
  39. [BATADV_ATTR_HARD_IFINDEX] = { .type = NLA_U32 },
  40. [BATADV_ATTR_ORIG_ADDRESS] = { .type = NLA_UNSPEC,
  41. .minlen = ETH_ALEN,
  42. .maxlen = ETH_ALEN },
  43. [BATADV_ATTR_TT_FLAGS] = { .type = NLA_U32 },
  44. [BATADV_ATTR_FLAG_BEST] = { .type = NLA_FLAG },
  45. [BATADV_ATTR_LAST_SEEN_MSECS] = { .type = NLA_U32 },
  46. [BATADV_ATTR_NEIGH_ADDRESS] = { .type = NLA_UNSPEC,
  47. .minlen = ETH_ALEN,
  48. .maxlen = ETH_ALEN },
  49. [BATADV_ATTR_TQ] = { .type = NLA_U8 },
  50. [BATADV_ATTR_ROUTER] = { .type = NLA_UNSPEC,
  51. .minlen = ETH_ALEN,
  52. .maxlen = ETH_ALEN },
  53. };
  54. static int nlquery_error_cb(struct sockaddr_nl *nla __maybe_unused,
  55. struct nlmsgerr *nlerr, void *arg)
  56. {
  57. struct batadv_nlquery_opts *query_opts = arg;
  58. query_opts->err = nlerr->error;
  59. return NL_STOP;
  60. }
  61. static int nlquery_stop_cb(struct nl_msg *msg, void *arg)
  62. {
  63. struct nlmsghdr *nlh = nlmsg_hdr(msg);
  64. struct batadv_nlquery_opts *query_opts = arg;
  65. int *error = nlmsg_data(nlh);
  66. if (*error)
  67. query_opts->err = *error;
  68. return NL_STOP;
  69. }
  70. int batadv_nl_query_common(const char *mesh_iface,
  71. enum batadv_nl_commands nl_cmd,
  72. nl_recvmsg_msg_cb_t callback, int flags,
  73. struct batadv_nlquery_opts *query_opts)
  74. {
  75. struct nl_sock *sock;
  76. struct nl_msg *msg;
  77. struct nl_cb *cb;
  78. int ifindex;
  79. int family;
  80. int ret;
  81. query_opts->err = 0;
  82. sock = nl_socket_alloc();
  83. if (!sock)
  84. return -ENOMEM;
  85. ret = genl_connect(sock);
  86. if (ret < 0) {
  87. query_opts->err = ret;
  88. goto err_free_sock;
  89. }
  90. family = genl_ctrl_resolve(sock, BATADV_NL_NAME);
  91. if (family < 0) {
  92. query_opts->err = -EOPNOTSUPP;
  93. goto err_free_sock;
  94. }
  95. ifindex = if_nametoindex(mesh_iface);
  96. if (!ifindex) {
  97. query_opts->err = -ENODEV;
  98. goto err_free_sock;
  99. }
  100. cb = nl_cb_alloc(NL_CB_DEFAULT);
  101. if (!cb) {
  102. query_opts->err = -ENOMEM;
  103. goto err_free_sock;
  104. }
  105. nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, callback, query_opts);
  106. nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, nlquery_stop_cb, query_opts);
  107. nl_cb_err(cb, NL_CB_CUSTOM, nlquery_error_cb, query_opts);
  108. msg = nlmsg_alloc();
  109. if (!msg) {
  110. query_opts->err = -ENOMEM;
  111. goto err_free_cb;
  112. }
  113. genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, flags,
  114. nl_cmd, 1);
  115. nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, ifindex);
  116. nl_send_auto_complete(sock, msg);
  117. nlmsg_free(msg);
  118. nl_recvmsgs(sock, cb);
  119. err_free_cb:
  120. nl_cb_put(cb);
  121. err_free_sock:
  122. nl_socket_free(sock);
  123. return query_opts->err;
  124. }