1*03f9172cSAndroid Build Coastguard Worker /*
2*03f9172cSAndroid Build Coastguard Worker * FST module implementation
3*03f9172cSAndroid Build Coastguard Worker * Copyright (c) 2014, Qualcomm Atheros, Inc.
4*03f9172cSAndroid Build Coastguard Worker *
5*03f9172cSAndroid Build Coastguard Worker * This software may be distributed under the terms of the BSD license.
6*03f9172cSAndroid Build Coastguard Worker * See README for more details.
7*03f9172cSAndroid Build Coastguard Worker */
8*03f9172cSAndroid Build Coastguard Worker
9*03f9172cSAndroid Build Coastguard Worker #include "utils/includes.h"
10*03f9172cSAndroid Build Coastguard Worker
11*03f9172cSAndroid Build Coastguard Worker #include "utils/common.h"
12*03f9172cSAndroid Build Coastguard Worker #include "utils/eloop.h"
13*03f9172cSAndroid Build Coastguard Worker #include "fst/fst.h"
14*03f9172cSAndroid Build Coastguard Worker #include "fst/fst_internal.h"
15*03f9172cSAndroid Build Coastguard Worker #include "fst/fst_defs.h"
16*03f9172cSAndroid Build Coastguard Worker #include "fst/fst_ctrl_iface.h"
17*03f9172cSAndroid Build Coastguard Worker
18*03f9172cSAndroid Build Coastguard Worker static int fst_global_initialized = 0;
19*03f9172cSAndroid Build Coastguard Worker struct dl_list fst_global_ctrls_list;
20*03f9172cSAndroid Build Coastguard Worker
21*03f9172cSAndroid Build Coastguard Worker
fst_ctrl_iface_notify_peer_state_change(struct fst_iface * iface,bool connected,const u8 * peer_addr)22*03f9172cSAndroid Build Coastguard Worker static void fst_ctrl_iface_notify_peer_state_change(struct fst_iface *iface,
23*03f9172cSAndroid Build Coastguard Worker bool connected,
24*03f9172cSAndroid Build Coastguard Worker const u8 *peer_addr)
25*03f9172cSAndroid Build Coastguard Worker {
26*03f9172cSAndroid Build Coastguard Worker union fst_event_extra extra;
27*03f9172cSAndroid Build Coastguard Worker
28*03f9172cSAndroid Build Coastguard Worker extra.peer_state.connected = connected;
29*03f9172cSAndroid Build Coastguard Worker os_strlcpy(extra.peer_state.ifname, fst_iface_get_name(iface),
30*03f9172cSAndroid Build Coastguard Worker sizeof(extra.peer_state.ifname));
31*03f9172cSAndroid Build Coastguard Worker os_memcpy(extra.peer_state.addr, peer_addr, ETH_ALEN);
32*03f9172cSAndroid Build Coastguard Worker
33*03f9172cSAndroid Build Coastguard Worker foreach_fst_ctrl_call(on_event, EVENT_PEER_STATE_CHANGED,
34*03f9172cSAndroid Build Coastguard Worker iface, NULL, &extra);
35*03f9172cSAndroid Build Coastguard Worker }
36*03f9172cSAndroid Build Coastguard Worker
37*03f9172cSAndroid Build Coastguard Worker
fst_attach(const char * ifname,const u8 * own_addr,const struct fst_wpa_obj * iface_obj,const struct fst_iface_cfg * cfg)38*03f9172cSAndroid Build Coastguard Worker struct fst_iface * fst_attach(const char *ifname, const u8 *own_addr,
39*03f9172cSAndroid Build Coastguard Worker const struct fst_wpa_obj *iface_obj,
40*03f9172cSAndroid Build Coastguard Worker const struct fst_iface_cfg *cfg)
41*03f9172cSAndroid Build Coastguard Worker {
42*03f9172cSAndroid Build Coastguard Worker struct fst_group *g;
43*03f9172cSAndroid Build Coastguard Worker struct fst_group *group = NULL;
44*03f9172cSAndroid Build Coastguard Worker struct fst_iface *iface = NULL;
45*03f9172cSAndroid Build Coastguard Worker bool new_group = false;
46*03f9172cSAndroid Build Coastguard Worker
47*03f9172cSAndroid Build Coastguard Worker WPA_ASSERT(ifname != NULL);
48*03f9172cSAndroid Build Coastguard Worker WPA_ASSERT(iface_obj != NULL);
49*03f9172cSAndroid Build Coastguard Worker WPA_ASSERT(cfg != NULL);
50*03f9172cSAndroid Build Coastguard Worker
51*03f9172cSAndroid Build Coastguard Worker foreach_fst_group(g) {
52*03f9172cSAndroid Build Coastguard Worker if (os_strcmp(cfg->group_id, fst_group_get_id(g)) == 0) {
53*03f9172cSAndroid Build Coastguard Worker group = g;
54*03f9172cSAndroid Build Coastguard Worker break;
55*03f9172cSAndroid Build Coastguard Worker }
56*03f9172cSAndroid Build Coastguard Worker }
57*03f9172cSAndroid Build Coastguard Worker
58*03f9172cSAndroid Build Coastguard Worker if (!group) {
59*03f9172cSAndroid Build Coastguard Worker group = fst_group_create(cfg->group_id);
60*03f9172cSAndroid Build Coastguard Worker if (!group) {
61*03f9172cSAndroid Build Coastguard Worker fst_printf(MSG_ERROR, "%s: FST group cannot be created",
62*03f9172cSAndroid Build Coastguard Worker cfg->group_id);
63*03f9172cSAndroid Build Coastguard Worker return NULL;
64*03f9172cSAndroid Build Coastguard Worker }
65*03f9172cSAndroid Build Coastguard Worker new_group = true;
66*03f9172cSAndroid Build Coastguard Worker }
67*03f9172cSAndroid Build Coastguard Worker
68*03f9172cSAndroid Build Coastguard Worker iface = fst_iface_create(group, ifname, own_addr, iface_obj, cfg);
69*03f9172cSAndroid Build Coastguard Worker if (!iface) {
70*03f9172cSAndroid Build Coastguard Worker fst_printf_group(group, MSG_ERROR, "cannot create iface for %s",
71*03f9172cSAndroid Build Coastguard Worker ifname);
72*03f9172cSAndroid Build Coastguard Worker if (new_group)
73*03f9172cSAndroid Build Coastguard Worker fst_group_delete(group);
74*03f9172cSAndroid Build Coastguard Worker return NULL;
75*03f9172cSAndroid Build Coastguard Worker }
76*03f9172cSAndroid Build Coastguard Worker
77*03f9172cSAndroid Build Coastguard Worker fst_group_attach_iface(group, iface);
78*03f9172cSAndroid Build Coastguard Worker fst_group_update_ie(group);
79*03f9172cSAndroid Build Coastguard Worker
80*03f9172cSAndroid Build Coastguard Worker foreach_fst_ctrl_call(on_iface_added, iface);
81*03f9172cSAndroid Build Coastguard Worker
82*03f9172cSAndroid Build Coastguard Worker fst_printf_iface(iface, MSG_DEBUG,
83*03f9172cSAndroid Build Coastguard Worker "iface attached to group %s (prio=%d, llt=%d)",
84*03f9172cSAndroid Build Coastguard Worker cfg->group_id, cfg->priority, cfg->llt);
85*03f9172cSAndroid Build Coastguard Worker
86*03f9172cSAndroid Build Coastguard Worker return iface;
87*03f9172cSAndroid Build Coastguard Worker }
88*03f9172cSAndroid Build Coastguard Worker
89*03f9172cSAndroid Build Coastguard Worker
fst_detach(struct fst_iface * iface)90*03f9172cSAndroid Build Coastguard Worker void fst_detach(struct fst_iface *iface)
91*03f9172cSAndroid Build Coastguard Worker {
92*03f9172cSAndroid Build Coastguard Worker struct fst_group *group = fst_iface_get_group(iface);
93*03f9172cSAndroid Build Coastguard Worker
94*03f9172cSAndroid Build Coastguard Worker fst_printf_iface(iface, MSG_DEBUG, "iface detached from group %s",
95*03f9172cSAndroid Build Coastguard Worker fst_group_get_id(group));
96*03f9172cSAndroid Build Coastguard Worker fst_session_global_on_iface_detached(iface);
97*03f9172cSAndroid Build Coastguard Worker foreach_fst_ctrl_call(on_iface_removed, iface);
98*03f9172cSAndroid Build Coastguard Worker fst_group_detach_iface(group, iface);
99*03f9172cSAndroid Build Coastguard Worker fst_iface_delete(iface);
100*03f9172cSAndroid Build Coastguard Worker fst_group_update_ie(group);
101*03f9172cSAndroid Build Coastguard Worker fst_group_delete_if_empty(group);
102*03f9172cSAndroid Build Coastguard Worker }
103*03f9172cSAndroid Build Coastguard Worker
104*03f9172cSAndroid Build Coastguard Worker
fst_global_init(void)105*03f9172cSAndroid Build Coastguard Worker int fst_global_init(void)
106*03f9172cSAndroid Build Coastguard Worker {
107*03f9172cSAndroid Build Coastguard Worker dl_list_init(&fst_global_groups_list);
108*03f9172cSAndroid Build Coastguard Worker dl_list_init(&fst_global_ctrls_list);
109*03f9172cSAndroid Build Coastguard Worker fst_session_global_init();
110*03f9172cSAndroid Build Coastguard Worker fst_global_initialized = 1;
111*03f9172cSAndroid Build Coastguard Worker return 0;
112*03f9172cSAndroid Build Coastguard Worker }
113*03f9172cSAndroid Build Coastguard Worker
114*03f9172cSAndroid Build Coastguard Worker
fst_global_deinit(void)115*03f9172cSAndroid Build Coastguard Worker void fst_global_deinit(void)
116*03f9172cSAndroid Build Coastguard Worker {
117*03f9172cSAndroid Build Coastguard Worker struct fst_group *group;
118*03f9172cSAndroid Build Coastguard Worker struct fst_ctrl_handle *h;
119*03f9172cSAndroid Build Coastguard Worker
120*03f9172cSAndroid Build Coastguard Worker if (!fst_global_initialized)
121*03f9172cSAndroid Build Coastguard Worker return;
122*03f9172cSAndroid Build Coastguard Worker
123*03f9172cSAndroid Build Coastguard Worker fst_session_global_deinit();
124*03f9172cSAndroid Build Coastguard Worker while ((group = fst_first_group()) != NULL)
125*03f9172cSAndroid Build Coastguard Worker fst_group_delete(group);
126*03f9172cSAndroid Build Coastguard Worker while ((h = dl_list_first(&fst_global_ctrls_list,
127*03f9172cSAndroid Build Coastguard Worker struct fst_ctrl_handle,
128*03f9172cSAndroid Build Coastguard Worker global_ctrls_lentry)))
129*03f9172cSAndroid Build Coastguard Worker fst_global_del_ctrl(h);
130*03f9172cSAndroid Build Coastguard Worker fst_global_initialized = 0;
131*03f9172cSAndroid Build Coastguard Worker }
132*03f9172cSAndroid Build Coastguard Worker
133*03f9172cSAndroid Build Coastguard Worker
fst_global_add_ctrl(const struct fst_ctrl * ctrl)134*03f9172cSAndroid Build Coastguard Worker struct fst_ctrl_handle * fst_global_add_ctrl(const struct fst_ctrl *ctrl)
135*03f9172cSAndroid Build Coastguard Worker {
136*03f9172cSAndroid Build Coastguard Worker struct fst_ctrl_handle *h;
137*03f9172cSAndroid Build Coastguard Worker
138*03f9172cSAndroid Build Coastguard Worker if (!ctrl)
139*03f9172cSAndroid Build Coastguard Worker return NULL;
140*03f9172cSAndroid Build Coastguard Worker
141*03f9172cSAndroid Build Coastguard Worker h = os_zalloc(sizeof(*h));
142*03f9172cSAndroid Build Coastguard Worker if (!h)
143*03f9172cSAndroid Build Coastguard Worker return NULL;
144*03f9172cSAndroid Build Coastguard Worker
145*03f9172cSAndroid Build Coastguard Worker if (ctrl->init && ctrl->init()) {
146*03f9172cSAndroid Build Coastguard Worker os_free(h);
147*03f9172cSAndroid Build Coastguard Worker return NULL;
148*03f9172cSAndroid Build Coastguard Worker }
149*03f9172cSAndroid Build Coastguard Worker
150*03f9172cSAndroid Build Coastguard Worker h->ctrl = *ctrl;
151*03f9172cSAndroid Build Coastguard Worker dl_list_add_tail(&fst_global_ctrls_list, &h->global_ctrls_lentry);
152*03f9172cSAndroid Build Coastguard Worker
153*03f9172cSAndroid Build Coastguard Worker return h;
154*03f9172cSAndroid Build Coastguard Worker }
155*03f9172cSAndroid Build Coastguard Worker
156*03f9172cSAndroid Build Coastguard Worker
fst_global_del_ctrl(struct fst_ctrl_handle * h)157*03f9172cSAndroid Build Coastguard Worker void fst_global_del_ctrl(struct fst_ctrl_handle *h)
158*03f9172cSAndroid Build Coastguard Worker {
159*03f9172cSAndroid Build Coastguard Worker dl_list_del(&h->global_ctrls_lentry);
160*03f9172cSAndroid Build Coastguard Worker if (h->ctrl.deinit)
161*03f9172cSAndroid Build Coastguard Worker h->ctrl.deinit();
162*03f9172cSAndroid Build Coastguard Worker os_free(h);
163*03f9172cSAndroid Build Coastguard Worker }
164*03f9172cSAndroid Build Coastguard Worker
165*03f9172cSAndroid Build Coastguard Worker
fst_rx_action(struct fst_iface * iface,const struct ieee80211_mgmt * mgmt,size_t len)166*03f9172cSAndroid Build Coastguard Worker void fst_rx_action(struct fst_iface *iface, const struct ieee80211_mgmt *mgmt,
167*03f9172cSAndroid Build Coastguard Worker size_t len)
168*03f9172cSAndroid Build Coastguard Worker {
169*03f9172cSAndroid Build Coastguard Worker if (fst_iface_is_connected(iface, mgmt->sa, false))
170*03f9172cSAndroid Build Coastguard Worker fst_session_on_action_rx(iface, mgmt, len);
171*03f9172cSAndroid Build Coastguard Worker else
172*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG,
173*03f9172cSAndroid Build Coastguard Worker "FST: Ignore FST Action frame - no FST connection with "
174*03f9172cSAndroid Build Coastguard Worker MACSTR, MAC2STR(mgmt->sa));
175*03f9172cSAndroid Build Coastguard Worker }
176*03f9172cSAndroid Build Coastguard Worker
177*03f9172cSAndroid Build Coastguard Worker
fst_notify_peer_connected(struct fst_iface * iface,const u8 * addr)178*03f9172cSAndroid Build Coastguard Worker void fst_notify_peer_connected(struct fst_iface *iface, const u8 *addr)
179*03f9172cSAndroid Build Coastguard Worker {
180*03f9172cSAndroid Build Coastguard Worker if (is_zero_ether_addr(addr))
181*03f9172cSAndroid Build Coastguard Worker return;
182*03f9172cSAndroid Build Coastguard Worker
183*03f9172cSAndroid Build Coastguard Worker #ifndef HOSTAPD
184*03f9172cSAndroid Build Coastguard Worker fst_group_update_ie(fst_iface_get_group(iface));
185*03f9172cSAndroid Build Coastguard Worker #endif /* HOSTAPD */
186*03f9172cSAndroid Build Coastguard Worker
187*03f9172cSAndroid Build Coastguard Worker fst_printf_iface(iface, MSG_DEBUG, MACSTR " became connected",
188*03f9172cSAndroid Build Coastguard Worker MAC2STR(addr));
189*03f9172cSAndroid Build Coastguard Worker
190*03f9172cSAndroid Build Coastguard Worker fst_ctrl_iface_notify_peer_state_change(iface, true, addr);
191*03f9172cSAndroid Build Coastguard Worker }
192*03f9172cSAndroid Build Coastguard Worker
193*03f9172cSAndroid Build Coastguard Worker
fst_notify_peer_disconnected(struct fst_iface * iface,const u8 * addr)194*03f9172cSAndroid Build Coastguard Worker void fst_notify_peer_disconnected(struct fst_iface *iface, const u8 *addr)
195*03f9172cSAndroid Build Coastguard Worker {
196*03f9172cSAndroid Build Coastguard Worker if (is_zero_ether_addr(addr))
197*03f9172cSAndroid Build Coastguard Worker return;
198*03f9172cSAndroid Build Coastguard Worker
199*03f9172cSAndroid Build Coastguard Worker #ifndef HOSTAPD
200*03f9172cSAndroid Build Coastguard Worker fst_group_update_ie(fst_iface_get_group(iface));
201*03f9172cSAndroid Build Coastguard Worker #endif /* HOSTAPD */
202*03f9172cSAndroid Build Coastguard Worker
203*03f9172cSAndroid Build Coastguard Worker fst_printf_iface(iface, MSG_DEBUG, MACSTR " became disconnected",
204*03f9172cSAndroid Build Coastguard Worker MAC2STR(addr));
205*03f9172cSAndroid Build Coastguard Worker
206*03f9172cSAndroid Build Coastguard Worker fst_ctrl_iface_notify_peer_state_change(iface, false, addr);
207*03f9172cSAndroid Build Coastguard Worker }
208*03f9172cSAndroid Build Coastguard Worker
209*03f9172cSAndroid Build Coastguard Worker
fst_are_ifaces_aggregated(struct fst_iface * iface1,struct fst_iface * iface2)210*03f9172cSAndroid Build Coastguard Worker bool fst_are_ifaces_aggregated(struct fst_iface *iface1,
211*03f9172cSAndroid Build Coastguard Worker struct fst_iface *iface2)
212*03f9172cSAndroid Build Coastguard Worker {
213*03f9172cSAndroid Build Coastguard Worker return fst_iface_get_group(iface1) == fst_iface_get_group(iface2);
214*03f9172cSAndroid Build Coastguard Worker }
215*03f9172cSAndroid Build Coastguard Worker
216*03f9172cSAndroid Build Coastguard Worker
fst_update_mac_addr(struct fst_iface * iface,const u8 * addr)217*03f9172cSAndroid Build Coastguard Worker void fst_update_mac_addr(struct fst_iface *iface, const u8 *addr)
218*03f9172cSAndroid Build Coastguard Worker {
219*03f9172cSAndroid Build Coastguard Worker fst_printf_iface(iface, MSG_DEBUG, "new MAC address " MACSTR,
220*03f9172cSAndroid Build Coastguard Worker MAC2STR(addr));
221*03f9172cSAndroid Build Coastguard Worker os_memcpy(iface->own_addr, addr, sizeof(iface->own_addr));
222*03f9172cSAndroid Build Coastguard Worker fst_group_update_ie(fst_iface_get_group(iface));
223*03f9172cSAndroid Build Coastguard Worker }
224*03f9172cSAndroid Build Coastguard Worker
225*03f9172cSAndroid Build Coastguard Worker
fst_hw_mode_to_band(enum hostapd_hw_mode mode)226*03f9172cSAndroid Build Coastguard Worker enum mb_band_id fst_hw_mode_to_band(enum hostapd_hw_mode mode)
227*03f9172cSAndroid Build Coastguard Worker {
228*03f9172cSAndroid Build Coastguard Worker switch (mode) {
229*03f9172cSAndroid Build Coastguard Worker case HOSTAPD_MODE_IEEE80211B:
230*03f9172cSAndroid Build Coastguard Worker case HOSTAPD_MODE_IEEE80211G:
231*03f9172cSAndroid Build Coastguard Worker return MB_BAND_ID_WIFI_2_4GHZ;
232*03f9172cSAndroid Build Coastguard Worker case HOSTAPD_MODE_IEEE80211A:
233*03f9172cSAndroid Build Coastguard Worker return MB_BAND_ID_WIFI_5GHZ;
234*03f9172cSAndroid Build Coastguard Worker case HOSTAPD_MODE_IEEE80211AD:
235*03f9172cSAndroid Build Coastguard Worker return MB_BAND_ID_WIFI_60GHZ;
236*03f9172cSAndroid Build Coastguard Worker default:
237*03f9172cSAndroid Build Coastguard Worker WPA_ASSERT(0);
238*03f9172cSAndroid Build Coastguard Worker return MB_BAND_ID_WIFI_2_4GHZ;
239*03f9172cSAndroid Build Coastguard Worker }
240*03f9172cSAndroid Build Coastguard Worker }
241