2 * FST module implementation
3 * Copyright (c) 2014, Qualcomm Atheros, Inc.
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
9 #include "utils/includes.h"
11 #include "utils/common.h"
12 #include "utils/eloop.h"
14 #include "fst/fst_internal.h"
15 #include "fst/fst_defs.h"
16 #include "fst/fst_ctrl_iface.h"
18 struct dl_list fst_global_ctrls_list;
21 static void fst_ctrl_iface_notify_peer_state_change(struct fst_iface *iface,
25 union fst_event_extra extra;
27 extra.peer_state.connected = connected;
28 os_strlcpy(extra.peer_state.ifname, fst_iface_get_name(iface),
29 sizeof(extra.peer_state.ifname));
30 os_memcpy(extra.peer_state.addr, peer_addr, ETH_ALEN);
32 foreach_fst_ctrl_call(on_event, EVENT_PEER_STATE_CHANGED,
37 static struct fst_group * fst_find_group_by_iface(const char *ifname)
41 foreach_fst_group(g) {
42 if (fst_group_get_iface_by_name(g, ifname))
50 struct fst_iface * fst_attach(const char *ifname, const u8 *own_addr,
51 const struct fst_wpa_obj *iface_obj,
52 const struct fst_iface_cfg *cfg)
55 struct fst_group *group = NULL;
56 struct fst_iface *iface = NULL;
57 Boolean new_group = FALSE;
59 WPA_ASSERT(ifname != NULL);
60 WPA_ASSERT(iface_obj != NULL);
61 WPA_ASSERT(cfg != NULL);
63 g = fst_find_group_by_iface(ifname);
66 "%s: iface is already part of an FST group: %s",
71 foreach_fst_group(g) {
72 if (os_strcmp(cfg->group_id, fst_group_get_id(g)) == 0) {
79 group = fst_group_create(cfg->group_id);
81 fst_printf(MSG_ERROR, "%s: FST group cannot be created",
88 iface = fst_iface_create(group, ifname, own_addr, iface_obj, cfg);
90 fst_printf_group(group, MSG_ERROR, "cannot create iface for %s",
93 fst_group_delete(group);
97 fst_group_attach_iface(group, iface);
98 fst_group_update_ie(group);
100 foreach_fst_ctrl_call(on_iface_added, iface);
102 fst_printf_iface(iface, MSG_DEBUG,
103 "iface attached to group %s (prio=%d, llt=%d)",
104 cfg->group_id, cfg->priority, cfg->llt);
110 void fst_detach(struct fst_iface *iface)
112 struct fst_group *group = fst_iface_get_group(iface);
114 fst_printf_iface(iface, MSG_DEBUG, "iface detached from group %s",
115 fst_group_get_id(group));
116 fst_session_global_on_iface_detached(iface);
117 foreach_fst_ctrl_call(on_iface_removed, iface);
118 fst_group_detach_iface(group, iface);
119 fst_iface_delete(iface);
120 fst_group_update_ie(group);
121 fst_group_delete_if_empty(group);
125 int fst_global_init(void)
127 dl_list_init(&fst_global_groups_list);
128 dl_list_init(&fst_global_ctrls_list);
129 fst_session_global_init();
134 void fst_global_deinit(void)
136 struct fst_group *group;
138 fst_session_global_deinit();
139 while ((group = fst_first_group()) != NULL)
140 fst_group_delete(group);
141 while (!dl_list_empty(&fst_global_ctrls_list)) {
142 struct fst_ctrl_handle *h;
144 h = dl_list_first(&fst_global_ctrls_list,
145 struct fst_ctrl_handle, global_ctrls_lentry);
146 fst_global_del_ctrl(h);
151 struct fst_ctrl_handle * fst_global_add_ctrl(const struct fst_ctrl *ctrl)
153 struct fst_ctrl_handle *h;
158 h = os_zalloc(sizeof(*h));
162 if (ctrl->init && ctrl->init()) {
168 dl_list_add_tail(&fst_global_ctrls_list, &h->global_ctrls_lentry);
174 void fst_global_del_ctrl(struct fst_ctrl_handle *h)
176 dl_list_del(&h->global_ctrls_lentry);
183 void fst_rx_action(struct fst_iface *iface, const struct ieee80211_mgmt *mgmt,
186 if (fst_iface_is_connected(iface, mgmt->sa))
187 fst_session_on_action_rx(iface, mgmt, len);
191 void fst_notify_peer_connected(struct fst_iface *iface, const u8 *addr)
193 if (is_zero_ether_addr(addr))
197 fst_group_update_ie(fst_iface_get_group(iface));
200 fst_printf_iface(iface, MSG_DEBUG, MACSTR " became connected",
203 fst_ctrl_iface_notify_peer_state_change(iface, TRUE, addr);
207 void fst_notify_peer_disconnected(struct fst_iface *iface, const u8 *addr)
209 if (is_zero_ether_addr(addr))
213 fst_group_update_ie(fst_iface_get_group(iface));
216 fst_printf_iface(iface, MSG_DEBUG, MACSTR " became disconnected",
219 fst_ctrl_iface_notify_peer_state_change(iface, FALSE, addr);
223 Boolean fst_are_ifaces_aggregated(struct fst_iface *iface1,
224 struct fst_iface *iface2)
226 return fst_iface_get_group(iface1) == fst_iface_get_group(iface2);