batadv-netlink.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  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_FLAG_BEST] = { .type = NLA_FLAG },
  44. [BATADV_ATTR_LAST_SEEN_MSECS] = { .type = NLA_U32 },
  45. [BATADV_ATTR_NEIGH_ADDRESS] = { .type = NLA_UNSPEC,
  46. .minlen = ETH_ALEN,
  47. .maxlen = ETH_ALEN },
  48. [BATADV_ATTR_TQ] = { .type = NLA_U8 },
  49. };
  50. static int nlquery_error_cb(struct sockaddr_nl *nla __maybe_unused,
  51. struct nlmsgerr *nlerr, void *arg)
  52. {
  53. struct batadv_nlquery_opts *query_opts = arg;
  54. query_opts->err = nlerr->error;
  55. return NL_STOP;
  56. }
  57. static int nlquery_stop_cb(struct nl_msg *msg, void *arg)
  58. {
  59. struct nlmsghdr *nlh = nlmsg_hdr(msg);
  60. struct batadv_nlquery_opts *query_opts = arg;
  61. int *error = nlmsg_data(nlh);
  62. if (*error)
  63. query_opts->err = *error;
  64. return NL_STOP;
  65. }
  66. int batadv_nl_query_common(const char *mesh_iface,
  67. enum batadv_nl_commands nl_cmd,
  68. nl_recvmsg_msg_cb_t callback, int flags,
  69. struct batadv_nlquery_opts *query_opts)
  70. {
  71. struct nl_sock *sock;
  72. struct nl_msg *msg;
  73. struct nl_cb *cb;
  74. int ifindex;
  75. int family;
  76. int ret;
  77. query_opts->err = 0;
  78. sock = nl_socket_alloc();
  79. if (!sock)
  80. return -ENOMEM;
  81. ret = genl_connect(sock);
  82. if (ret < 0) {
  83. query_opts->err = ret;
  84. goto err_free_sock;
  85. }
  86. family = genl_ctrl_resolve(sock, BATADV_NL_NAME);
  87. if (family < 0) {
  88. query_opts->err = -EOPNOTSUPP;
  89. goto err_free_sock;
  90. }
  91. ifindex = if_nametoindex(mesh_iface);
  92. if (!ifindex) {
  93. query_opts->err = -ENODEV;
  94. goto err_free_sock;
  95. }
  96. cb = nl_cb_alloc(NL_CB_DEFAULT);
  97. if (!cb) {
  98. query_opts->err = -ENOMEM;
  99. goto err_free_sock;
  100. }
  101. nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, callback, query_opts);
  102. nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, nlquery_stop_cb, query_opts);
  103. nl_cb_err(cb, NL_CB_CUSTOM, nlquery_error_cb, query_opts);
  104. msg = nlmsg_alloc();
  105. if (!msg) {
  106. query_opts->err = -ENOMEM;
  107. goto err_free_cb;
  108. }
  109. genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, flags,
  110. nl_cmd, 1);
  111. nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, ifindex);
  112. nl_send_auto_complete(sock, msg);
  113. nlmsg_free(msg);
  114. nl_recvmsgs(sock, cb);
  115. err_free_cb:
  116. nl_cb_put(cb);
  117. err_free_sock:
  118. nl_socket_free(sock);
  119. return query_opts->err;
  120. }