ctrl.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*
  2. * wlantest control interface
  3. * Copyright (c) 2010, Jouni Malinen <j@w1.fi>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * Alternatively, this software may be distributed under the terms of BSD
  10. * license.
  11. *
  12. * See README and COPYING for more details.
  13. */
  14. #include "utils/includes.h"
  15. #include <sys/un.h>
  16. #include "utils/common.h"
  17. #include "utils/eloop.h"
  18. #include "wlantest.h"
  19. #include "wlantest_ctrl.h"
  20. static void ctrl_disconnect(struct wlantest *wt, int sock)
  21. {
  22. int i;
  23. wpa_printf(MSG_DEBUG, "Disconnect control interface connection %d",
  24. sock);
  25. for (i = 0; i < MAX_CTRL_CONNECTIONS; i++) {
  26. if (wt->ctrl_socks[i] == sock) {
  27. close(wt->ctrl_socks[i]);
  28. eloop_unregister_read_sock(wt->ctrl_socks[i]);
  29. wt->ctrl_socks[i] = -1;
  30. break;
  31. }
  32. }
  33. }
  34. static void ctrl_send_simple(struct wlantest *wt, int sock,
  35. enum wlantest_ctrl_cmd cmd)
  36. {
  37. u8 buf[4];
  38. WPA_PUT_BE32(buf, cmd);
  39. if (send(sock, buf, sizeof(buf), 0) < 0) {
  40. wpa_printf(MSG_INFO, "send(ctrl): %s", strerror(errno));
  41. ctrl_disconnect(wt, sock);
  42. }
  43. }
  44. static void ctrl_read(int sock, void *eloop_ctx, void *sock_ctx)
  45. {
  46. struct wlantest *wt = eloop_ctx;
  47. u8 buf[WLANTEST_CTRL_MAX_CMD_LEN];
  48. int len;
  49. enum wlantest_ctrl_cmd cmd;
  50. wpa_printf(MSG_EXCESSIVE, "New control interface message from %d",
  51. sock);
  52. len = recv(sock, buf, sizeof(buf), 0);
  53. if (len < 0) {
  54. wpa_printf(MSG_INFO, "recv(ctrl): %s", strerror(errno));
  55. ctrl_disconnect(wt, sock);
  56. return;
  57. }
  58. if (len == 0) {
  59. ctrl_disconnect(wt, sock);
  60. return;
  61. }
  62. if (len < 4) {
  63. wpa_printf(MSG_INFO, "Too short control interface command "
  64. "from %d", sock);
  65. ctrl_disconnect(wt, sock);
  66. return;
  67. }
  68. cmd = WPA_GET_BE32(buf);
  69. wpa_printf(MSG_EXCESSIVE, "Control interface command %d from %d",
  70. cmd, sock);
  71. switch (cmd) {
  72. case WLANTEST_CTRL_PING:
  73. ctrl_send_simple(wt, sock, WLANTEST_CTRL_SUCCESS);
  74. break;
  75. case WLANTEST_CTRL_TERMINATE:
  76. ctrl_send_simple(wt, sock, WLANTEST_CTRL_SUCCESS);
  77. eloop_terminate();
  78. break;
  79. default:
  80. ctrl_send_simple(wt, sock, WLANTEST_CTRL_UNKNOWN_CMD);
  81. break;
  82. }
  83. }
  84. static void ctrl_connect(int sock, void *eloop_ctx, void *sock_ctx)
  85. {
  86. struct wlantest *wt = eloop_ctx;
  87. int conn, i;
  88. conn = accept(sock, NULL, NULL);
  89. if (conn < 0) {
  90. wpa_printf(MSG_INFO, "accept(ctrl): %s", strerror(errno));
  91. return;
  92. }
  93. wpa_printf(MSG_MSGDUMP, "New control interface connection %d", conn);
  94. for (i = 0; i < MAX_CTRL_CONNECTIONS; i++) {
  95. if (wt->ctrl_socks[i] < 0)
  96. break;
  97. }
  98. if (i == MAX_CTRL_CONNECTIONS) {
  99. wpa_printf(MSG_INFO, "No room for new control connection");
  100. close(conn);
  101. return;
  102. }
  103. wt->ctrl_socks[i] = conn;
  104. eloop_register_read_sock(conn, ctrl_read, wt, NULL);
  105. }
  106. int ctrl_init(struct wlantest *wt)
  107. {
  108. struct sockaddr_un addr;
  109. wt->ctrl_sock = socket(AF_UNIX, SOCK_SEQPACKET, 0);
  110. if (wt->ctrl_sock < 0) {
  111. wpa_printf(MSG_ERROR, "socket: %s", strerror(errno));
  112. return -1;
  113. }
  114. os_memset(&addr, 0, sizeof(addr));
  115. addr.sun_family = AF_UNIX;
  116. os_strlcpy(addr.sun_path + 1, WLANTEST_SOCK_NAME,
  117. sizeof(addr.sun_path) - 1);
  118. if (bind(wt->ctrl_sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
  119. wpa_printf(MSG_ERROR, "bind: %s", strerror(errno));
  120. close(wt->ctrl_sock);
  121. wt->ctrl_sock = -1;
  122. return -1;
  123. }
  124. if (listen(wt->ctrl_sock, 5) < 0) {
  125. wpa_printf(MSG_ERROR, "listen: %s", strerror(errno));
  126. close(wt->ctrl_sock);
  127. wt->ctrl_sock = -1;
  128. return -1;
  129. }
  130. if (eloop_register_read_sock(wt->ctrl_sock, ctrl_connect, wt, NULL)) {
  131. close(wt->ctrl_sock);
  132. wt->ctrl_sock = -1;
  133. return -1;
  134. }
  135. return 0;
  136. }
  137. void ctrl_deinit(struct wlantest *wt)
  138. {
  139. int i;
  140. if (wt->ctrl_sock < 0)
  141. return;
  142. for (i = 0; i < MAX_CTRL_CONNECTIONS; i++) {
  143. if (wt->ctrl_socks[i] >= 0) {
  144. close(wt->ctrl_socks[i]);
  145. eloop_unregister_read_sock(wt->ctrl_socks[i]);
  146. wt->ctrl_socks[i] = -1;
  147. }
  148. }
  149. eloop_unregister_read_sock(wt->ctrl_sock);
  150. close(wt->ctrl_sock);
  151. wt->ctrl_sock = -1;
  152. }