ctrl_iface_ap.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /*
  2. * Control interface for shared AP commands
  3. * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
  4. *
  5. * This software may be distributed under the terms of the BSD license.
  6. * See README for more details.
  7. */
  8. #include "utils/includes.h"
  9. #include "utils/common.h"
  10. #include "common/ieee802_11_defs.h"
  11. #include "hostapd.h"
  12. #include "ieee802_1x.h"
  13. #include "wpa_auth.h"
  14. #include "ieee802_11.h"
  15. #include "sta_info.h"
  16. #include "wps_hostapd.h"
  17. #include "p2p_hostapd.h"
  18. #include "ctrl_iface_ap.h"
  19. #include "ap_drv_ops.h"
  20. static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
  21. struct sta_info *sta,
  22. char *buf, size_t buflen)
  23. {
  24. int len, res, ret;
  25. if (sta == NULL) {
  26. ret = os_snprintf(buf, buflen, "FAIL\n");
  27. if (ret < 0 || (size_t) ret >= buflen)
  28. return 0;
  29. return ret;
  30. }
  31. len = 0;
  32. ret = os_snprintf(buf + len, buflen - len, MACSTR "\n",
  33. MAC2STR(sta->addr));
  34. if (ret < 0 || (size_t) ret >= buflen - len)
  35. return len;
  36. len += ret;
  37. res = ieee802_11_get_mib_sta(hapd, sta, buf + len, buflen - len);
  38. if (res >= 0)
  39. len += res;
  40. res = wpa_get_mib_sta(sta->wpa_sm, buf + len, buflen - len);
  41. if (res >= 0)
  42. len += res;
  43. res = ieee802_1x_get_mib_sta(hapd, sta, buf + len, buflen - len);
  44. if (res >= 0)
  45. len += res;
  46. res = hostapd_wps_get_mib_sta(hapd, sta->addr, buf + len,
  47. buflen - len);
  48. if (res >= 0)
  49. len += res;
  50. res = hostapd_p2p_get_mib_sta(hapd, sta, buf + len, buflen - len);
  51. if (res >= 0)
  52. len += res;
  53. return len;
  54. }
  55. int hostapd_ctrl_iface_sta_first(struct hostapd_data *hapd,
  56. char *buf, size_t buflen)
  57. {
  58. return hostapd_ctrl_iface_sta_mib(hapd, hapd->sta_list, buf, buflen);
  59. }
  60. int hostapd_ctrl_iface_sta(struct hostapd_data *hapd, const char *txtaddr,
  61. char *buf, size_t buflen)
  62. {
  63. u8 addr[ETH_ALEN];
  64. int ret;
  65. if (hwaddr_aton(txtaddr, addr)) {
  66. ret = os_snprintf(buf, buflen, "FAIL\n");
  67. if (ret < 0 || (size_t) ret >= buflen)
  68. return 0;
  69. return ret;
  70. }
  71. return hostapd_ctrl_iface_sta_mib(hapd, ap_get_sta(hapd, addr),
  72. buf, buflen);
  73. }
  74. int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd, const char *txtaddr,
  75. char *buf, size_t buflen)
  76. {
  77. u8 addr[ETH_ALEN];
  78. struct sta_info *sta;
  79. int ret;
  80. if (hwaddr_aton(txtaddr, addr) ||
  81. (sta = ap_get_sta(hapd, addr)) == NULL) {
  82. ret = os_snprintf(buf, buflen, "FAIL\n");
  83. if (ret < 0 || (size_t) ret >= buflen)
  84. return 0;
  85. return ret;
  86. }
  87. return hostapd_ctrl_iface_sta_mib(hapd, sta->next, buf, buflen);
  88. }
  89. #ifdef CONFIG_P2P_MANAGER
  90. static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype,
  91. u8 minor_reason_code, const u8 *addr)
  92. {
  93. struct ieee80211_mgmt *mgmt;
  94. int ret;
  95. u8 *pos;
  96. if (hapd->driver->send_frame == NULL)
  97. return -1;
  98. mgmt = os_zalloc(sizeof(*mgmt) + 100);
  99. if (mgmt == NULL)
  100. return -1;
  101. wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "P2P: Disconnect STA " MACSTR
  102. " with minor reason code %u (stype=%u)",
  103. MAC2STR(addr), minor_reason_code, stype);
  104. mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, stype);
  105. os_memcpy(mgmt->da, addr, ETH_ALEN);
  106. os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
  107. os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
  108. if (stype == WLAN_FC_STYPE_DEAUTH) {
  109. mgmt->u.deauth.reason_code =
  110. host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
  111. pos = (u8 *) (&mgmt->u.deauth.reason_code + 1);
  112. } else {
  113. mgmt->u.disassoc.reason_code =
  114. host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
  115. pos = (u8 *) (&mgmt->u.disassoc.reason_code + 1);
  116. }
  117. *pos++ = WLAN_EID_VENDOR_SPECIFIC;
  118. *pos++ = 4 + 3 + 1;
  119. WPA_PUT_BE24(pos, OUI_WFA);
  120. pos += 3;
  121. *pos++ = P2P_OUI_TYPE;
  122. *pos++ = P2P_ATTR_MINOR_REASON_CODE;
  123. WPA_PUT_LE16(pos, 1);
  124. pos += 2;
  125. *pos++ = minor_reason_code;
  126. ret = hapd->driver->send_frame(hapd->drv_priv, (u8 *) mgmt,
  127. pos - (u8 *) mgmt, 1);
  128. os_free(mgmt);
  129. return ret < 0 ? -1 : 0;
  130. }
  131. #endif /* CONFIG_P2P_MANAGER */
  132. int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd,
  133. const char *txtaddr)
  134. {
  135. u8 addr[ETH_ALEN];
  136. struct sta_info *sta;
  137. const char *pos;
  138. wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE DEAUTHENTICATE %s",
  139. txtaddr);
  140. if (hwaddr_aton(txtaddr, addr))
  141. return -1;
  142. pos = os_strstr(txtaddr, " test=");
  143. if (pos) {
  144. struct ieee80211_mgmt mgmt;
  145. int encrypt;
  146. if (hapd->driver->send_frame == NULL)
  147. return -1;
  148. pos += 6;
  149. encrypt = atoi(pos);
  150. os_memset(&mgmt, 0, sizeof(mgmt));
  151. mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
  152. WLAN_FC_STYPE_DEAUTH);
  153. os_memcpy(mgmt.da, addr, ETH_ALEN);
  154. os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
  155. os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
  156. mgmt.u.deauth.reason_code =
  157. host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
  158. if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
  159. IEEE80211_HDRLEN +
  160. sizeof(mgmt.u.deauth),
  161. encrypt) < 0)
  162. return -1;
  163. return 0;
  164. }
  165. #ifdef CONFIG_P2P_MANAGER
  166. pos = os_strstr(txtaddr, " p2p=");
  167. if (pos) {
  168. return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DEAUTH,
  169. atoi(pos + 5), addr);
  170. }
  171. #endif /* CONFIG_P2P_MANAGER */
  172. hostapd_drv_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
  173. sta = ap_get_sta(hapd, addr);
  174. if (sta)
  175. ap_sta_deauthenticate(hapd, sta,
  176. WLAN_REASON_PREV_AUTH_NOT_VALID);
  177. else if (addr[0] == 0xff)
  178. hostapd_free_stas(hapd);
  179. return 0;
  180. }
  181. int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd,
  182. const char *txtaddr)
  183. {
  184. u8 addr[ETH_ALEN];
  185. struct sta_info *sta;
  186. const char *pos;
  187. wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE DISASSOCIATE %s",
  188. txtaddr);
  189. if (hwaddr_aton(txtaddr, addr))
  190. return -1;
  191. pos = os_strstr(txtaddr, " test=");
  192. if (pos) {
  193. struct ieee80211_mgmt mgmt;
  194. int encrypt;
  195. if (hapd->driver->send_frame == NULL)
  196. return -1;
  197. pos += 6;
  198. encrypt = atoi(pos);
  199. os_memset(&mgmt, 0, sizeof(mgmt));
  200. mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
  201. WLAN_FC_STYPE_DISASSOC);
  202. os_memcpy(mgmt.da, addr, ETH_ALEN);
  203. os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
  204. os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
  205. mgmt.u.disassoc.reason_code =
  206. host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
  207. if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
  208. IEEE80211_HDRLEN +
  209. sizeof(mgmt.u.deauth),
  210. encrypt) < 0)
  211. return -1;
  212. return 0;
  213. }
  214. #ifdef CONFIG_P2P_MANAGER
  215. pos = os_strstr(txtaddr, " p2p=");
  216. if (pos) {
  217. return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DISASSOC,
  218. atoi(pos + 5), addr);
  219. }
  220. #endif /* CONFIG_P2P_MANAGER */
  221. hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
  222. sta = ap_get_sta(hapd, addr);
  223. if (sta)
  224. ap_sta_disassociate(hapd, sta,
  225. WLAN_REASON_PREV_AUTH_NOT_VALID);
  226. else if (addr[0] == 0xff)
  227. hostapd_free_stas(hapd);
  228. return 0;
  229. }