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