fst.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. /*
  2. * FST module implementation
  3. * Copyright (c) 2014, Qualcomm Atheros, Inc.
  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 "utils/eloop.h"
  11. #include "fst/fst.h"
  12. #include "fst/fst_internal.h"
  13. #include "fst/fst_defs.h"
  14. #include "fst/fst_ctrl_iface.h"
  15. static int fst_global_initialized = 0;
  16. struct dl_list fst_global_ctrls_list;
  17. static void fst_ctrl_iface_notify_peer_state_change(struct fst_iface *iface,
  18. Boolean connected,
  19. const u8 *peer_addr)
  20. {
  21. union fst_event_extra extra;
  22. extra.peer_state.connected = connected;
  23. os_strlcpy(extra.peer_state.ifname, fst_iface_get_name(iface),
  24. sizeof(extra.peer_state.ifname));
  25. os_memcpy(extra.peer_state.addr, peer_addr, ETH_ALEN);
  26. foreach_fst_ctrl_call(on_event, EVENT_PEER_STATE_CHANGED,
  27. iface, NULL, &extra);
  28. }
  29. struct fst_iface * fst_attach(const char *ifname, const u8 *own_addr,
  30. const struct fst_wpa_obj *iface_obj,
  31. const struct fst_iface_cfg *cfg)
  32. {
  33. struct fst_group *g;
  34. struct fst_group *group = NULL;
  35. struct fst_iface *iface = NULL;
  36. Boolean new_group = FALSE;
  37. WPA_ASSERT(ifname != NULL);
  38. WPA_ASSERT(iface_obj != NULL);
  39. WPA_ASSERT(cfg != NULL);
  40. foreach_fst_group(g) {
  41. if (os_strcmp(cfg->group_id, fst_group_get_id(g)) == 0) {
  42. group = g;
  43. break;
  44. }
  45. }
  46. if (!group) {
  47. group = fst_group_create(cfg->group_id);
  48. if (!group) {
  49. fst_printf(MSG_ERROR, "%s: FST group cannot be created",
  50. cfg->group_id);
  51. return NULL;
  52. }
  53. new_group = TRUE;
  54. }
  55. iface = fst_iface_create(group, ifname, own_addr, iface_obj, cfg);
  56. if (!iface) {
  57. fst_printf_group(group, MSG_ERROR, "cannot create iface for %s",
  58. ifname);
  59. if (new_group)
  60. fst_group_delete(group);
  61. return NULL;
  62. }
  63. fst_group_attach_iface(group, iface);
  64. fst_group_update_ie(group);
  65. foreach_fst_ctrl_call(on_iface_added, iface);
  66. fst_printf_iface(iface, MSG_DEBUG,
  67. "iface attached to group %s (prio=%d, llt=%d)",
  68. cfg->group_id, cfg->priority, cfg->llt);
  69. return iface;
  70. }
  71. void fst_detach(struct fst_iface *iface)
  72. {
  73. struct fst_group *group = fst_iface_get_group(iface);
  74. fst_printf_iface(iface, MSG_DEBUG, "iface detached from group %s",
  75. fst_group_get_id(group));
  76. fst_session_global_on_iface_detached(iface);
  77. foreach_fst_ctrl_call(on_iface_removed, iface);
  78. fst_group_detach_iface(group, iface);
  79. fst_iface_delete(iface);
  80. fst_group_update_ie(group);
  81. fst_group_delete_if_empty(group);
  82. }
  83. int fst_global_init(void)
  84. {
  85. dl_list_init(&fst_global_groups_list);
  86. dl_list_init(&fst_global_ctrls_list);
  87. fst_session_global_init();
  88. fst_global_initialized = 1;
  89. return 0;
  90. }
  91. void fst_global_deinit(void)
  92. {
  93. struct fst_group *group;
  94. struct fst_ctrl_handle *h;
  95. if (!fst_global_initialized)
  96. return;
  97. fst_session_global_deinit();
  98. while ((group = fst_first_group()) != NULL)
  99. fst_group_delete(group);
  100. while ((h = dl_list_first(&fst_global_ctrls_list,
  101. struct fst_ctrl_handle,
  102. global_ctrls_lentry)))
  103. fst_global_del_ctrl(h);
  104. fst_global_initialized = 0;
  105. }
  106. struct fst_ctrl_handle * fst_global_add_ctrl(const struct fst_ctrl *ctrl)
  107. {
  108. struct fst_ctrl_handle *h;
  109. if (!ctrl)
  110. return NULL;
  111. h = os_zalloc(sizeof(*h));
  112. if (!h)
  113. return NULL;
  114. if (ctrl->init && ctrl->init()) {
  115. os_free(h);
  116. return NULL;
  117. }
  118. h->ctrl = *ctrl;
  119. dl_list_add_tail(&fst_global_ctrls_list, &h->global_ctrls_lentry);
  120. return h;
  121. }
  122. void fst_global_del_ctrl(struct fst_ctrl_handle *h)
  123. {
  124. dl_list_del(&h->global_ctrls_lentry);
  125. if (h->ctrl.deinit)
  126. h->ctrl.deinit();
  127. os_free(h);
  128. }
  129. void fst_rx_action(struct fst_iface *iface, const struct ieee80211_mgmt *mgmt,
  130. size_t len)
  131. {
  132. if (fst_iface_is_connected(iface, mgmt->sa, FALSE))
  133. fst_session_on_action_rx(iface, mgmt, len);
  134. else
  135. wpa_printf(MSG_DEBUG,
  136. "FST: Ignore FST Action frame - no FST connection with "
  137. MACSTR, MAC2STR(mgmt->sa));
  138. }
  139. void fst_notify_peer_connected(struct fst_iface *iface, const u8 *addr)
  140. {
  141. if (is_zero_ether_addr(addr))
  142. return;
  143. #ifndef HOSTAPD
  144. fst_group_update_ie(fst_iface_get_group(iface));
  145. #endif /* HOSTAPD */
  146. fst_printf_iface(iface, MSG_DEBUG, MACSTR " became connected",
  147. MAC2STR(addr));
  148. fst_ctrl_iface_notify_peer_state_change(iface, TRUE, addr);
  149. }
  150. void fst_notify_peer_disconnected(struct fst_iface *iface, const u8 *addr)
  151. {
  152. if (is_zero_ether_addr(addr))
  153. return;
  154. #ifndef HOSTAPD
  155. fst_group_update_ie(fst_iface_get_group(iface));
  156. #endif /* HOSTAPD */
  157. fst_printf_iface(iface, MSG_DEBUG, MACSTR " became disconnected",
  158. MAC2STR(addr));
  159. fst_ctrl_iface_notify_peer_state_change(iface, FALSE, addr);
  160. }
  161. Boolean fst_are_ifaces_aggregated(struct fst_iface *iface1,
  162. struct fst_iface *iface2)
  163. {
  164. return fst_iface_get_group(iface1) == fst_iface_get_group(iface2);
  165. }
  166. enum mb_band_id fst_hw_mode_to_band(enum hostapd_hw_mode mode)
  167. {
  168. switch (mode) {
  169. case HOSTAPD_MODE_IEEE80211B:
  170. case HOSTAPD_MODE_IEEE80211G:
  171. return MB_BAND_ID_WIFI_2_4GHZ;
  172. case HOSTAPD_MODE_IEEE80211A:
  173. return MB_BAND_ID_WIFI_5GHZ;
  174. case HOSTAPD_MODE_IEEE80211AD:
  175. return MB_BAND_ID_WIFI_60GHZ;
  176. default:
  177. WPA_ASSERT(0);
  178. return MB_BAND_ID_WIFI_2_4GHZ;
  179. }
  180. }