monitor.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. #include "monitor.h"
  2. #include <linux/nl80211.h>
  3. #include <net/if.h>
  4. #include <netlink/attr.h>
  5. #include <netlink/genl/genl.h>
  6. #include <netlink/handlers.h>
  7. #include <netlink/msg.h>
  8. #include <netlink/netlink.h>
  9. #include <netlink/socket.h>
  10. #include <unistd.h>
  11. #include "log.h"
  12. static int oldval = 0.f;
  13. static monitor_callback *setter = NULL;
  14. static FILE *log_output;
  15. int keep_running = 1;
  16. static int getWifiInfo_callback(struct nl_msg *msg, void *arg) {
  17. struct nlattr *tb[NL80211_ATTR_MAX + 1];
  18. struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
  19. struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
  20. nla_parse(tb,
  21. NL80211_ATTR_MAX,
  22. genlmsg_attrdata(gnlh, 0),
  23. genlmsg_attrlen(gnlh, 0),
  24. NULL);
  25. if (!tb[NL80211_ATTR_STA_INFO]) {
  26. log_err("GET_WIFI_INFO", "sta stats missing!\n");
  27. return NL_SKIP;
  28. }
  29. if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
  30. tb[NL80211_ATTR_STA_INFO], stats_policy)) {
  31. log_err("GET_WIFI_INFO", "failed to parse nested attributes!\n");
  32. return NL_SKIP;
  33. }
  34. if (sinfo[NL80211_STA_INFO_SIGNAL]) {
  35. ((Wifi*)arg)->signal = 100+(int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
  36. }
  37. return NL_OK;
  38. }
  39. static int getWifiStatus(Netlink *nl, Wifi *w) {
  40. nl->result = 1;
  41. struct nl_msg* msg = nlmsg_alloc();
  42. if (!msg) {
  43. log_err("GET_WIFI_STATUS", "Failed to allocate netlink message.\n");
  44. return -2;
  45. }
  46. genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, nl->id, 0, NLM_F_DUMP,
  47. NL80211_CMD_GET_STATION, 0);
  48. nla_put_u32(msg, NL80211_ATTR_IFINDEX, w->ifindex);
  49. nl_send_auto(nl->socket, msg);
  50. while (nl->result > 0) { nl_recvmsgs(nl->socket, nl->cb1); }
  51. nlmsg_free(msg);
  52. return 0;
  53. }
  54. void monitor(const char *ifname, monitor_callback *callback, unsigned long interval) {
  55. setter = callback;
  56. Netlink nl;
  57. Wifi w;
  58. w.ifindex = if_nametoindex(ifname); // todo it’s ioctl -> change to netlink
  59. nl.id = initNl80211(&nl, &w, getWifiInfo_callback);
  60. if (nl.id < 0) {
  61. log_err("MONITOR", "Error initializing netlink 802.11\n");
  62. exit(EXIT_FAILURE);
  63. }
  64. do {
  65. getWifiStatus(&nl, &w);
  66. if (w.signal != oldval) {
  67. int status = setter(oldval, w.signal, &w);
  68. if (status > 0)
  69. oldval=w.signal;
  70. }
  71. sleep(interval);
  72. } while(keep_running);
  73. log_out("MONITOR", "Exiting gracefully...\n");
  74. nl_cb_put(nl.cb1);
  75. nl_close(nl.socket);
  76. nl_socket_free(nl.socket);
  77. }