xref: /aosp_15_r20/external/wpa_supplicant_8/src/fst/fst.c (revision 03f9172ca588f91df233974f4258bab95191f931)
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