wifi.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. #include <err.h>
  2. #include <string.h>
  3. #include <sys/ioctl.h>
  4. #include <sys/socket.h>
  5. #include <linux/wireless.h>
  6. #include "wifi.h"
  7. #include "../lib/util.h"
  8. #include "../aslstatus.h"
  9. #define CLEANUP(X) \
  10. static inline void wifi_##X##_cleanup(void *ptr) \
  11. { \
  12. eclose(((struct wifi_##X##_data *)ptr)->common.sock); \
  13. } \
  14. struct trailing_semicolon
  15. #define eioctl(fd, req, arg) _eioctl(__func__, (fd), (req), #req, arg)
  16. static uint8_t _eioctl(const char *func,
  17. int fd,
  18. unsigned long int req,
  19. const char *str_req,
  20. void *arg);
  21. #define esocket(socket, ...) \
  22. ((socket = _esocket(__func__, #__VA_ARGS__, __VA_ARGS__)) != -1)
  23. static int
  24. _esocket(const char *func, const char *args, int domain, int type, int proto);
  25. #define SOCKET_INIT(DATA, OUT) \
  26. do { \
  27. if (!esocket((DATA)->common.sock, AF_INET, SOCK_DGRAM, 0)) \
  28. ERRRET(OUT); \
  29. } while (0)
  30. static void wifi_perc_cleanup(void *ptr);
  31. static void wifi_essid_cleanup(void *ptr);
  32. void
  33. wifi_perc(char *out,
  34. const char *interface,
  35. uint32_t __unused _i,
  36. static_data_t *static_data)
  37. {
  38. struct wifi_perc_data *data = static_data->data;
  39. if (!static_data->cleanup) static_data->cleanup = wifi_perc_cleanup;
  40. if (data->common.sock <= 0) {
  41. SOCKET_INIT(data, out);
  42. strncpy(data->common.req.ifr_name,
  43. interface,
  44. sizeof(data->common.req.ifr_name));
  45. data->common.req.u.data.pointer = &data->stat;
  46. data->common.req.u.data.length = sizeof(data->stat);
  47. }
  48. if (!eioctl(data->common.sock, SIOCGIWSTATS, &data->common.req)) {
  49. close(data->common.sock);
  50. data->common.sock = -1;
  51. ERRRET(out);
  52. }
  53. bprintf(out,
  54. "%" PRIperc,
  55. (percent_t)((float)data->stat.qual.qual / (70 /* max RSSI */)
  56. * 100));
  57. }
  58. void
  59. wifi_essid(char *out,
  60. const char *interface,
  61. uint32_t __unused _i,
  62. static_data_t *static_data)
  63. {
  64. struct wifi_essid_data *data = static_data->data;
  65. if (!static_data->cleanup) static_data->cleanup = wifi_essid_cleanup;
  66. if (data->common.sock <= 0) {
  67. SOCKET_INIT(data, out);
  68. strncpy(data->common.req.ifr_name,
  69. interface,
  70. sizeof(data->common.req.ifr_name));
  71. data->common.req.u.essid.pointer = data->id;
  72. data->common.req.u.essid.length = sizeof(data->id);
  73. }
  74. if (!eioctl(data->common.sock, SIOCGIWESSID, &data->common.req)) {
  75. close(data->common.sock);
  76. data->common.sock = -1;
  77. ERRRET(out);
  78. }
  79. if (!*data->id) ERRRET(out);
  80. bprintf(out, "%s", data->id);
  81. }
  82. static inline uint8_t
  83. _eioctl(const char *func,
  84. int fd,
  85. unsigned long int req,
  86. const char *str_req,
  87. void *arg)
  88. {
  89. uint8_t ret;
  90. static const char msg[] = "you are probably not connected to wifi";
  91. if (!(ret = (ioctl(fd, req, arg) != -1)))
  92. warn("%s: %s: ioctl(%d, %s, %p)", func, msg, fd, str_req, arg);
  93. return ret;
  94. }
  95. static inline int
  96. _esocket(const char *func, const char *args, int domain, int type, int proto)
  97. {
  98. int ret;
  99. if ((ret = socket(domain, type, proto)) == -1)
  100. warn("%s: socket(%s)", func, args);
  101. return ret;
  102. }
  103. CLEANUP(perc);
  104. CLEANUP(essid);