1 From d017f5d98a143c46c3c3fcb0e6507ca0b2bebdb0 Mon Sep 17 00:00:00 2001
2 From: Markus Theil <markus.theil@tu-ilmenau.de>
3 Date: Tue, 30 Jun 2020 14:19:03 +0200
4 Subject: [PATCH 15/19] mesh: fix DFS deinit/init
6 The hostapd DFS code deinitializes and initializes the
7 AP interface, if a clean channel switch is not possible.
8 In this case the AP code paths would deinit the driver, for
9 example nl80211, without wpa_supplicant code paths getting
12 Therefore add callbacks for wpa_supplicant mesh methods,
13 which are called on init/deinit of the AP bss. These
14 callbacks are then used to handle the reset in the mesh
17 Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>
20 src/ap/hostapd.c | 17 ++++++--
21 src/ap/hostapd.h | 6 +++
22 wpa_supplicant/mesh.c | 90 +++++++++++++++++++++++++++++++++++++------
23 4 files changed, 100 insertions(+), 15 deletions(-)
27 @@ -1112,7 +1112,7 @@ static int hostapd_dfs_start_channel_swi
28 oper_centr_freq_seg0_idx,
29 oper_centr_freq_seg1_idx,
31 - &cmode->he_capab[IEEE80211_MODE_AP]);
32 + &cmode->he_capab[iface->conf->hw_mode]);
35 wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params");
36 --- a/src/ap/hostapd.c
37 +++ b/src/ap/hostapd.c
38 @@ -354,7 +354,7 @@ static int hostapd_broadcast_wep_set(str
39 #endif /* CONFIG_WEP */
42 -static void hostapd_free_hapd_data(struct hostapd_data *hapd)
43 +void hostapd_free_hapd_data(struct hostapd_data *hapd)
45 os_free(hapd->probereq_cb);
46 hapd->probereq_cb = NULL;
47 @@ -498,7 +498,7 @@ static void sta_track_deinit(struct host
51 -static void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
52 +void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
54 wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
56 @@ -626,7 +626,7 @@ static int hostapd_flush_old_stations(st
60 -static void hostapd_bss_deinit_no_free(struct hostapd_data *hapd)
61 +void hostapd_bss_deinit_no_free(struct hostapd_data *hapd)
63 hostapd_free_stas(hapd);
64 hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING);
65 @@ -2690,6 +2690,13 @@ int hostapd_enable_iface(struct hostapd_
69 + if (hapd_iface == NULL)
72 + if (hapd_iface->enable_iface_cb != NULL) {
73 + return hapd_iface->enable_iface_cb(hapd_iface);
76 if (hapd_iface->bss[0]->drv_priv != NULL) {
77 wpa_printf(MSG_ERROR, "Interface %s already enabled",
78 hapd_iface->conf->bss[0]->iface);
79 @@ -2751,6 +2758,10 @@ int hostapd_disable_iface(struct hostapd
80 if (hapd_iface == NULL)
83 + if (hapd_iface->disable_iface_cb != NULL) {
84 + return hapd_iface->disable_iface_cb(hapd_iface);
87 if (hapd_iface->bss[0]->drv_priv == NULL) {
88 wpa_printf(MSG_INFO, "Interface %s already disabled",
89 hapd_iface->conf->bss[0]->iface);
90 --- a/src/ap/hostapd.h
91 +++ b/src/ap/hostapd.h
92 @@ -589,6 +589,9 @@ struct hostapd_iface {
94 /* Previous WMM element information */
95 struct hostapd_wmm_ac_params prev_wmm[WMM_AC_NUM];
97 + int (*enable_iface_cb)(struct hostapd_iface *iface);
98 + int (*disable_iface_cb)(struct hostapd_iface *iface);
102 @@ -617,6 +620,9 @@ void hostapd_interface_deinit_free(struc
103 int hostapd_enable_iface(struct hostapd_iface *hapd_iface);
104 int hostapd_reload_iface(struct hostapd_iface *hapd_iface);
105 int hostapd_disable_iface(struct hostapd_iface *hapd_iface);
106 +void hostapd_bss_deinit_no_free(struct hostapd_data *hapd);
107 +void hostapd_free_hapd_data(struct hostapd_data *hapd);
108 +void hostapd_cleanup_iface_partial(struct hostapd_iface *iface);
109 int hostapd_add_iface(struct hapd_interfaces *ifaces, char *buf);
110 int hostapd_remove_iface(struct hapd_interfaces *ifaces, char *buf);
111 void hostapd_channel_list_updated(struct hostapd_iface *iface, int initiator);
112 --- a/wpa_supplicant/mesh.c
113 +++ b/wpa_supplicant/mesh.c
118 -static void wpa_supplicant_mesh_deinit(struct wpa_supplicant *wpa_s)
119 +static void wpa_supplicant_mesh_deinit(struct wpa_supplicant *wpa_s, bool also_clear_hostapd)
121 - wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
122 - wpa_s->ifmsh = NULL;
123 - wpa_s->current_ssid = NULL;
124 + wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, also_clear_hostapd);
126 + if (also_clear_hostapd) {
127 + wpa_s->ifmsh = NULL;
128 + wpa_s->current_ssid = NULL;
129 + os_free(wpa_s->mesh_params);
130 + wpa_s->mesh_params = NULL;
133 os_free(wpa_s->mesh_rsn);
134 wpa_s->mesh_rsn = NULL;
135 - os_free(wpa_s->mesh_params);
136 - wpa_s->mesh_params = NULL;
138 wpa_supplicant_leave_mesh(wpa_s, false);
141 @@ -237,7 +242,7 @@ static int wpas_mesh_complete(struct wpa
142 ifmsh->conf->vht_capab,
144 wpa_printf(MSG_ERROR, "Error updating mesh frequency params.");
145 - wpa_supplicant_mesh_deinit(wpa_s);
146 + wpa_supplicant_mesh_deinit(wpa_s, true);
150 @@ -246,7 +251,7 @@ static int wpas_mesh_complete(struct wpa
151 wpas_mesh_init_rsn(wpa_s)) {
152 wpa_printf(MSG_ERROR,
153 "mesh: RSN initialization failed - deinit mesh");
154 - wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, false);
155 + wpa_supplicant_mesh_deinit(wpa_s, false);
159 @@ -291,6 +296,67 @@ static void wpas_mesh_complete_cb(void *
163 +static int wpa_supplicant_mesh_enable_iface_cb(struct hostapd_iface *ifmsh)
165 + struct wpa_supplicant *wpa_s = ifmsh->owner;
166 + struct hostapd_data *bss;
168 + ifmsh->mconf = mesh_config_create(wpa_s, wpa_s->current_ssid);
170 + bss = ifmsh->bss[0];
171 + bss->msg_ctx = wpa_s;
172 + os_memcpy(bss->own_addr, wpa_s->own_addr, ETH_ALEN);
173 + bss->driver = wpa_s->driver;
174 + bss->drv_priv = wpa_s->drv_priv;
175 + bss->iface = ifmsh;
176 + bss->mesh_sta_free_cb = mesh_mpm_free_sta;
177 + bss->setup_complete_cb = wpas_mesh_complete_cb;
178 + bss->setup_complete_cb_ctx = wpa_s;
180 + bss->conf->start_disabled = 1;
181 + bss->conf->mesh = MESH_ENABLED;
182 + bss->conf->ap_max_inactivity = wpa_s->conf->mesh_max_inactivity;
184 + if (wpa_drv_init_mesh(wpa_s)) {
185 + wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh in driver");
189 + if (hostapd_setup_interface(ifmsh)) {
190 + wpa_printf(MSG_ERROR,
191 + "Failed to initialize hostapd interface for mesh");
199 +static int wpa_supplicant_mesh_disable_iface_cb(struct hostapd_iface *ifmsh)
201 + struct wpa_supplicant *wpa_s = ifmsh->owner;
204 + wpa_supplicant_mesh_deinit(wpa_s, false);
207 + for (j = 0; j < ifmsh->num_bss; j++)
208 + hostapd_cleanup_cs_params(ifmsh->bss[j]);
209 +#endif /* NEED_AP_MLME */
211 + /* same as hostapd_interface_deinit without deinitializing ctrl-iface */
212 + for (j = 0; j < ifmsh->num_bss; j++) {
213 + struct hostapd_data *hapd = ifmsh->bss[j];
214 + hostapd_bss_deinit_no_free(hapd);
215 + hostapd_free_hapd_data(hapd);
218 + hostapd_cleanup_iface_partial(ifmsh);
224 static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
225 struct wpa_ssid *ssid,
226 struct hostapd_freq_params *freq)
227 @@ -318,6 +384,8 @@ static int wpa_supplicant_mesh_init(stru
228 ifmsh->drv_flags = wpa_s->drv_flags;
229 ifmsh->drv_flags2 = wpa_s->drv_flags2;
231 + ifmsh->enable_iface_cb = wpa_supplicant_mesh_enable_iface_cb;
232 + ifmsh->disable_iface_cb = wpa_supplicant_mesh_disable_iface_cb;
233 ifmsh->bss = os_calloc(wpa_s->ifmsh->num_bss,
234 sizeof(struct hostapd_data *));
236 @@ -451,7 +519,7 @@ static int wpa_supplicant_mesh_init(stru
240 - wpa_supplicant_mesh_deinit(wpa_s);
241 + wpa_supplicant_mesh_deinit(wpa_s, true);
245 @@ -499,7 +567,7 @@ int wpa_supplicant_join_mesh(struct wpa_
249 - wpa_supplicant_mesh_deinit(wpa_s);
250 + wpa_supplicant_mesh_deinit(wpa_s, true);
252 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
253 wpa_s->group_cipher = WPA_CIPHER_NONE;
254 @@ -588,7 +656,7 @@ int wpa_supplicant_leave_mesh(struct wpa
256 /* Need to send peering close messages first */
258 - wpa_supplicant_mesh_deinit(wpa_s);
259 + wpa_supplicant_mesh_deinit(wpa_s, true);
261 ret = wpa_drv_leave_mesh(wpa_s);