fst.c revision 289284
1289284Srpaulo/* 2289284Srpaulo * FST module implementation 3289284Srpaulo * Copyright (c) 2014, Qualcomm Atheros, Inc. 4289284Srpaulo * 5289284Srpaulo * This software may be distributed under the terms of the BSD license. 6289284Srpaulo * See README for more details. 7289284Srpaulo */ 8289284Srpaulo 9289284Srpaulo#include "utils/includes.h" 10289284Srpaulo 11289284Srpaulo#include "utils/common.h" 12289284Srpaulo#include "utils/eloop.h" 13289284Srpaulo#include "fst/fst.h" 14289284Srpaulo#include "fst/fst_internal.h" 15289284Srpaulo#include "fst/fst_defs.h" 16289284Srpaulo#include "fst/fst_ctrl_iface.h" 17289284Srpaulo 18289284Srpaulostruct dl_list fst_global_ctrls_list; 19289284Srpaulo 20289284Srpaulo 21289284Srpaulostatic void fst_ctrl_iface_notify_peer_state_change(struct fst_iface *iface, 22289284Srpaulo Boolean connected, 23289284Srpaulo const u8 *peer_addr) 24289284Srpaulo{ 25289284Srpaulo union fst_event_extra extra; 26289284Srpaulo 27289284Srpaulo extra.peer_state.connected = connected; 28289284Srpaulo os_strlcpy(extra.peer_state.ifname, fst_iface_get_name(iface), 29289284Srpaulo sizeof(extra.peer_state.ifname)); 30289284Srpaulo os_memcpy(extra.peer_state.addr, peer_addr, ETH_ALEN); 31289284Srpaulo 32289284Srpaulo foreach_fst_ctrl_call(on_event, EVENT_PEER_STATE_CHANGED, 33289284Srpaulo iface, NULL, &extra); 34289284Srpaulo} 35289284Srpaulo 36289284Srpaulo 37289284Srpaulostruct fst_iface * fst_attach(const char *ifname, const u8 *own_addr, 38289284Srpaulo const struct fst_wpa_obj *iface_obj, 39289284Srpaulo const struct fst_iface_cfg *cfg) 40289284Srpaulo{ 41289284Srpaulo struct fst_group *g; 42289284Srpaulo struct fst_group *group = NULL; 43289284Srpaulo struct fst_iface *iface = NULL; 44289284Srpaulo Boolean new_group = FALSE; 45289284Srpaulo 46289284Srpaulo WPA_ASSERT(ifname != NULL); 47289284Srpaulo WPA_ASSERT(iface_obj != NULL); 48289284Srpaulo WPA_ASSERT(cfg != NULL); 49289284Srpaulo 50289284Srpaulo foreach_fst_group(g) { 51289284Srpaulo if (os_strcmp(cfg->group_id, fst_group_get_id(g)) == 0) { 52289284Srpaulo group = g; 53289284Srpaulo break; 54289284Srpaulo } 55289284Srpaulo } 56289284Srpaulo 57289284Srpaulo if (!group) { 58289284Srpaulo group = fst_group_create(cfg->group_id); 59289284Srpaulo if (!group) { 60289284Srpaulo fst_printf(MSG_ERROR, "%s: FST group cannot be created", 61289284Srpaulo cfg->group_id); 62289284Srpaulo return NULL; 63289284Srpaulo } 64289284Srpaulo new_group = TRUE; 65289284Srpaulo } 66289284Srpaulo 67289284Srpaulo iface = fst_iface_create(group, ifname, own_addr, iface_obj, cfg); 68289284Srpaulo if (!iface) { 69289284Srpaulo fst_printf_group(group, MSG_ERROR, "cannot create iface for %s", 70289284Srpaulo ifname); 71289284Srpaulo if (new_group) 72289284Srpaulo fst_group_delete(group); 73289284Srpaulo return NULL; 74289284Srpaulo } 75289284Srpaulo 76289284Srpaulo fst_group_attach_iface(group, iface); 77289284Srpaulo fst_group_update_ie(group); 78289284Srpaulo 79289284Srpaulo foreach_fst_ctrl_call(on_iface_added, iface); 80289284Srpaulo 81289284Srpaulo fst_printf_iface(iface, MSG_DEBUG, 82289284Srpaulo "iface attached to group %s (prio=%d, llt=%d)", 83289284Srpaulo cfg->group_id, cfg->priority, cfg->llt); 84289284Srpaulo 85289284Srpaulo return iface; 86289284Srpaulo} 87289284Srpaulo 88289284Srpaulo 89289284Srpaulovoid fst_detach(struct fst_iface *iface) 90289284Srpaulo{ 91289284Srpaulo struct fst_group *group = fst_iface_get_group(iface); 92289284Srpaulo 93289284Srpaulo fst_printf_iface(iface, MSG_DEBUG, "iface detached from group %s", 94289284Srpaulo fst_group_get_id(group)); 95289284Srpaulo fst_session_global_on_iface_detached(iface); 96289284Srpaulo foreach_fst_ctrl_call(on_iface_removed, iface); 97289284Srpaulo fst_group_detach_iface(group, iface); 98289284Srpaulo fst_iface_delete(iface); 99289284Srpaulo fst_group_update_ie(group); 100289284Srpaulo fst_group_delete_if_empty(group); 101289284Srpaulo} 102289284Srpaulo 103289284Srpaulo 104289284Srpauloint fst_global_init(void) 105289284Srpaulo{ 106289284Srpaulo dl_list_init(&fst_global_groups_list); 107289284Srpaulo dl_list_init(&fst_global_ctrls_list); 108289284Srpaulo fst_session_global_init(); 109289284Srpaulo return 0; 110289284Srpaulo} 111289284Srpaulo 112289284Srpaulo 113289284Srpaulovoid fst_global_deinit(void) 114289284Srpaulo{ 115289284Srpaulo struct fst_group *group; 116289284Srpaulo struct fst_ctrl_handle *h; 117289284Srpaulo 118289284Srpaulo fst_session_global_deinit(); 119289284Srpaulo while ((group = fst_first_group()) != NULL) 120289284Srpaulo fst_group_delete(group); 121289284Srpaulo while ((h = dl_list_first(&fst_global_ctrls_list, 122289284Srpaulo struct fst_ctrl_handle, 123289284Srpaulo global_ctrls_lentry))) 124289284Srpaulo fst_global_del_ctrl(h); 125289284Srpaulo} 126289284Srpaulo 127289284Srpaulo 128289284Srpaulostruct fst_ctrl_handle * fst_global_add_ctrl(const struct fst_ctrl *ctrl) 129289284Srpaulo{ 130289284Srpaulo struct fst_ctrl_handle *h; 131289284Srpaulo 132289284Srpaulo if (!ctrl) 133289284Srpaulo return NULL; 134289284Srpaulo 135289284Srpaulo h = os_zalloc(sizeof(*h)); 136289284Srpaulo if (!h) 137289284Srpaulo return NULL; 138289284Srpaulo 139289284Srpaulo if (ctrl->init && ctrl->init()) { 140289284Srpaulo os_free(h); 141289284Srpaulo return NULL; 142289284Srpaulo } 143289284Srpaulo 144289284Srpaulo h->ctrl = *ctrl; 145289284Srpaulo dl_list_add_tail(&fst_global_ctrls_list, &h->global_ctrls_lentry); 146289284Srpaulo 147289284Srpaulo return h; 148289284Srpaulo} 149289284Srpaulo 150289284Srpaulo 151289284Srpaulovoid fst_global_del_ctrl(struct fst_ctrl_handle *h) 152289284Srpaulo{ 153289284Srpaulo dl_list_del(&h->global_ctrls_lentry); 154289284Srpaulo if (h->ctrl.deinit) 155289284Srpaulo h->ctrl.deinit(); 156289284Srpaulo os_free(h); 157289284Srpaulo} 158289284Srpaulo 159289284Srpaulo 160289284Srpaulovoid fst_rx_action(struct fst_iface *iface, const struct ieee80211_mgmt *mgmt, 161289284Srpaulo size_t len) 162289284Srpaulo{ 163289284Srpaulo if (fst_iface_is_connected(iface, mgmt->sa)) 164289284Srpaulo fst_session_on_action_rx(iface, mgmt, len); 165289284Srpaulo else 166289284Srpaulo wpa_printf(MSG_DEBUG, 167289284Srpaulo "FST: Ignore FST Action frame - no FST connection with " 168289284Srpaulo MACSTR, MAC2STR(mgmt->sa)); 169289284Srpaulo} 170289284Srpaulo 171289284Srpaulo 172289284Srpaulovoid fst_notify_peer_connected(struct fst_iface *iface, const u8 *addr) 173289284Srpaulo{ 174289284Srpaulo if (is_zero_ether_addr(addr)) 175289284Srpaulo return; 176289284Srpaulo 177289284Srpaulo#ifndef HOSTAPD 178289284Srpaulo fst_group_update_ie(fst_iface_get_group(iface)); 179289284Srpaulo#endif /* HOSTAPD */ 180289284Srpaulo 181289284Srpaulo fst_printf_iface(iface, MSG_DEBUG, MACSTR " became connected", 182289284Srpaulo MAC2STR(addr)); 183289284Srpaulo 184289284Srpaulo fst_ctrl_iface_notify_peer_state_change(iface, TRUE, addr); 185289284Srpaulo} 186289284Srpaulo 187289284Srpaulo 188289284Srpaulovoid fst_notify_peer_disconnected(struct fst_iface *iface, const u8 *addr) 189289284Srpaulo{ 190289284Srpaulo if (is_zero_ether_addr(addr)) 191289284Srpaulo return; 192289284Srpaulo 193289284Srpaulo#ifndef HOSTAPD 194289284Srpaulo fst_group_update_ie(fst_iface_get_group(iface)); 195289284Srpaulo#endif /* HOSTAPD */ 196289284Srpaulo 197289284Srpaulo fst_printf_iface(iface, MSG_DEBUG, MACSTR " became disconnected", 198289284Srpaulo MAC2STR(addr)); 199289284Srpaulo 200289284Srpaulo fst_ctrl_iface_notify_peer_state_change(iface, FALSE, addr); 201289284Srpaulo} 202289284Srpaulo 203289284Srpaulo 204289284SrpauloBoolean fst_are_ifaces_aggregated(struct fst_iface *iface1, 205289284Srpaulo struct fst_iface *iface2) 206289284Srpaulo{ 207289284Srpaulo return fst_iface_get_group(iface1) == fst_iface_get_group(iface2); 208289284Srpaulo} 209289284Srpaulo 210289284Srpaulo 211289284Srpauloenum mb_band_id fst_hw_mode_to_band(enum hostapd_hw_mode mode) 212289284Srpaulo{ 213289284Srpaulo switch (mode) { 214289284Srpaulo case HOSTAPD_MODE_IEEE80211B: 215289284Srpaulo case HOSTAPD_MODE_IEEE80211G: 216289284Srpaulo return MB_BAND_ID_WIFI_2_4GHZ; 217289284Srpaulo case HOSTAPD_MODE_IEEE80211A: 218289284Srpaulo return MB_BAND_ID_WIFI_5GHZ; 219289284Srpaulo case HOSTAPD_MODE_IEEE80211AD: 220289284Srpaulo return MB_BAND_ID_WIFI_60GHZ; 221289284Srpaulo default: 222289284Srpaulo WPA_ASSERT(0); 223289284Srpaulo return MB_BAND_ID_WIFI_2_4GHZ; 224289284Srpaulo } 225289284Srpaulo} 226