2 * WPA Supplicant - Basic mesh mode routines
3 * Copyright (c) 2013-2014, cozybit, Inc. All rights reserved.
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"
13 #include "utils/uuid.h"
14 #include "common/ieee802_11_defs.h"
15 #include "common/wpa_ctrl.h"
16 #include "ap/sta_info.h"
17 #include "ap/hostapd.h"
18 #include "ap/ieee802_11.h"
19 #include "config_ssid.h"
21 #include "wpa_supplicant_i.h"
30 static void wpa_supplicant_mesh_deinit(struct wpa_supplicant
*wpa_s
)
32 wpa_supplicant_mesh_iface_deinit(wpa_s
, wpa_s
->ifmsh
);
34 wpa_s
->current_ssid
= NULL
;
35 os_free(wpa_s
->mesh_rsn
);
36 wpa_s
->mesh_rsn
= NULL
;
37 os_free(wpa_s
->mesh_params
);
38 wpa_s
->mesh_params
= NULL
;
39 /* TODO: leave mesh (stop beacon). This will happen on link down
40 * anyway, so it's not urgent */
44 void wpa_supplicant_mesh_iface_deinit(struct wpa_supplicant
*wpa_s
,
45 struct hostapd_iface
*ifmsh
)
51 mesh_mpm_deinit(wpa_s
, ifmsh
);
52 if (ifmsh
->mconf
->rsn_ie
) {
53 ifmsh
->mconf
->rsn_ie
= NULL
;
54 /* We cannot free this struct
55 * because wpa_authenticator on
56 * hostapd side is also using it
57 * for now just set to NULL and
58 * let hostapd code free it.
61 os_free(ifmsh
->mconf
);
65 /* take care of shared data */
66 hostapd_interface_deinit(ifmsh
);
67 hostapd_interface_free(ifmsh
);
71 static struct mesh_conf
* mesh_config_create(struct wpa_supplicant
*wpa_s
,
72 struct wpa_ssid
*ssid
)
74 struct mesh_conf
*conf
;
77 conf
= os_zalloc(sizeof(struct mesh_conf
));
81 os_memcpy(conf
->meshid
, ssid
->ssid
, ssid
->ssid_len
);
82 conf
->meshid_len
= ssid
->ssid_len
;
84 if (ssid
->key_mgmt
& WPA_KEY_MGMT_SAE
)
85 conf
->security
|= MESH_CONF_SEC_AUTH
|
88 conf
->security
|= MESH_CONF_SEC_NONE
;
89 #ifdef CONFIG_IEEE80211W
90 conf
->ieee80211w
= ssid
->ieee80211w
;
91 if (conf
->ieee80211w
== MGMT_FRAME_PROTECTION_DEFAULT
) {
92 if (wpa_s
->drv_enc
& WPA_DRIVER_CAPA_ENC_BIP
)
93 conf
->ieee80211w
= wpa_s
->conf
->pmf
;
95 conf
->ieee80211w
= NO_MGMT_FRAME_PROTECTION
;
97 #endif /* CONFIG_IEEE80211W */
99 conf
->ocv
= ssid
->ocv
;
100 #endif /* CONFIG_OCV */
102 cipher
= wpa_pick_pairwise_cipher(ssid
->pairwise_cipher
, 0);
103 if (cipher
< 0 || cipher
== WPA_CIPHER_TKIP
) {
104 wpa_msg(wpa_s
, MSG_INFO
, "mesh: Invalid pairwise cipher");
108 conf
->pairwise_cipher
= cipher
;
110 cipher
= wpa_pick_group_cipher(ssid
->group_cipher
);
111 if (cipher
< 0 || cipher
== WPA_CIPHER_TKIP
||
112 cipher
== WPA_CIPHER_GTK_NOT_USED
) {
113 wpa_msg(wpa_s
, MSG_INFO
, "mesh: Invalid group cipher");
118 conf
->group_cipher
= cipher
;
119 if (conf
->ieee80211w
!= NO_MGMT_FRAME_PROTECTION
)
120 conf
->mgmt_group_cipher
= WPA_CIPHER_AES_128_CMAC
;
123 conf
->mesh_pp_id
= MESH_PATH_PROTOCOL_HWMP
;
124 conf
->mesh_pm_id
= MESH_PATH_METRIC_AIRTIME
;
125 conf
->mesh_cc_id
= 0;
126 conf
->mesh_sp_id
= MESH_SYNC_METHOD_NEIGHBOR_OFFSET
;
127 conf
->mesh_auth_id
= (conf
->security
& MESH_CONF_SEC_AUTH
) ? 1 : 0;
128 conf
->dot11MeshMaxRetries
= ssid
->dot11MeshMaxRetries
;
129 conf
->dot11MeshRetryTimeout
= ssid
->dot11MeshRetryTimeout
;
130 conf
->dot11MeshConfirmTimeout
= ssid
->dot11MeshConfirmTimeout
;
131 conf
->dot11MeshHoldingTimeout
= ssid
->dot11MeshHoldingTimeout
;
137 static void wpas_mesh_copy_groups(struct hostapd_data
*bss
,
138 struct wpa_supplicant
*wpa_s
)
143 for (num_groups
= 0; wpa_s
->conf
->sae_groups
[num_groups
] > 0;
147 groups_size
= (num_groups
+ 1) * sizeof(wpa_s
->conf
->sae_groups
[0]);
148 bss
->conf
->sae_groups
= os_malloc(groups_size
);
149 if (bss
->conf
->sae_groups
)
150 os_memcpy(bss
->conf
->sae_groups
, wpa_s
->conf
->sae_groups
,
155 static int wpas_mesh_init_rsn(struct wpa_supplicant
*wpa_s
)
157 struct hostapd_iface
*ifmsh
= wpa_s
->ifmsh
;
158 struct wpa_ssid
*ssid
= wpa_s
->current_ssid
;
159 struct hostapd_data
*bss
= ifmsh
->bss
[0];
160 static int default_groups
[] = { 19, 20, 21, 25, 26, -1 };
161 const char *password
;
164 password
= ssid
->sae_password
;
166 password
= ssid
->passphrase
;
168 wpa_printf(MSG_ERROR
,
169 "mesh: Passphrase for SAE not configured");
173 bss
->conf
->wpa
= ssid
->proto
;
174 bss
->conf
->wpa_key_mgmt
= ssid
->key_mgmt
;
176 if (wpa_s
->conf
->sae_groups
&& wpa_s
->conf
->sae_groups
[0] > 0) {
177 wpas_mesh_copy_groups(bss
, wpa_s
);
179 bss
->conf
->sae_groups
= os_memdup(default_groups
,
180 sizeof(default_groups
));
181 if (!bss
->conf
->sae_groups
)
185 len
= os_strlen(password
);
186 bss
->conf
->ssid
.wpa_passphrase
= dup_binstr(password
, len
);
188 wpa_s
->mesh_rsn
= mesh_rsn_auth_init(wpa_s
, ifmsh
->mconf
);
189 return !wpa_s
->mesh_rsn
? -1 : 0;
193 static int wpas_mesh_complete(struct wpa_supplicant
*wpa_s
)
195 struct hostapd_iface
*ifmsh
= wpa_s
->ifmsh
;
196 struct wpa_driver_mesh_join_params
*params
= wpa_s
->mesh_params
;
197 struct wpa_ssid
*ssid
= wpa_s
->current_ssid
;
200 if (!params
|| !ssid
|| !ifmsh
) {
201 wpa_printf(MSG_ERROR
, "mesh: %s called without active mesh",
206 if (ifmsh
->mconf
->security
!= MESH_CONF_SEC_NONE
&&
207 wpas_mesh_init_rsn(wpa_s
)) {
208 wpa_printf(MSG_ERROR
,
209 "mesh: RSN initialization failed - deinit mesh");
210 wpa_supplicant_mesh_deinit(wpa_s
);
211 wpa_drv_leave_mesh(wpa_s
);
215 if (ssid
->key_mgmt
& WPA_KEY_MGMT_SAE
) {
216 wpa_s
->pairwise_cipher
= wpa_s
->mesh_rsn
->pairwise_cipher
;
217 wpa_s
->group_cipher
= wpa_s
->mesh_rsn
->group_cipher
;
218 wpa_s
->mgmt_group_cipher
= wpa_s
->mesh_rsn
->mgmt_group_cipher
;
221 params
->ies
= ifmsh
->mconf
->rsn_ie
;
222 params
->ie_len
= ifmsh
->mconf
->rsn_ie_len
;
223 params
->basic_rates
= ifmsh
->basic_rates
;
224 params
->conf
.flags
|= WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE
;
225 params
->conf
.ht_opmode
= ifmsh
->bss
[0]->iface
->ht_op_mode
;
227 wpa_msg(wpa_s
, MSG_INFO
, "joining mesh %s",
228 wpa_ssid_txt(ssid
->ssid
, ssid
->ssid_len
));
229 ret
= wpa_drv_join_mesh(wpa_s
, params
);
231 wpa_msg(wpa_s
, MSG_ERROR
, "mesh join error=%d", ret
);
233 /* hostapd sets the interface down until we associate */
234 wpa_drv_set_operstate(wpa_s
, 1);
237 wpa_supplicant_set_state(wpa_s
, WPA_COMPLETED
);
243 static int wpa_supplicant_mesh_init(struct wpa_supplicant
*wpa_s
,
244 struct wpa_ssid
*ssid
,
245 struct hostapd_freq_params
*freq
)
247 struct hostapd_iface
*ifmsh
;
248 struct hostapd_data
*bss
;
249 struct hostapd_config
*conf
;
250 struct mesh_conf
*mconf
;
251 int basic_rates_erp
[] = { 10, 20, 55, 60, 110, 120, 240, -1 };
255 if (!wpa_s
->conf
->user_mpm
) {
256 /* not much for us to do here */
257 wpa_msg(wpa_s
, MSG_WARNING
,
258 "user_mpm is not enabled in configuration");
262 wpa_s
->ifmsh
= ifmsh
= hostapd_alloc_iface();
266 ifmsh
->drv_flags
= wpa_s
->drv_flags
;
268 ifmsh
->bss
= os_calloc(wpa_s
->ifmsh
->num_bss
,
269 sizeof(struct hostapd_data
*));
273 ifmsh
->bss
[0] = bss
= hostapd_alloc_bss_data(NULL
, NULL
, NULL
);
277 ifmsh
->bss
[0]->msg_ctx
= wpa_s
;
278 os_memcpy(bss
->own_addr
, wpa_s
->own_addr
, ETH_ALEN
);
279 bss
->driver
= wpa_s
->driver
;
280 bss
->drv_priv
= wpa_s
->drv_priv
;
282 bss
->mesh_sta_free_cb
= mesh_mpm_free_sta
;
283 frequency
= ssid
->frequency
;
284 if (frequency
!= freq
->freq
&&
285 frequency
== freq
->freq
+ freq
->sec_channel_offset
* 20) {
286 wpa_printf(MSG_DEBUG
, "mesh: pri/sec channels switched");
287 frequency
= freq
->freq
;
289 wpa_s
->assoc_freq
= frequency
;
290 wpa_s
->current_ssid
= ssid
;
292 /* setup an AP config for auth processing */
293 conf
= hostapd_config_defaults();
297 bss
->conf
= *conf
->bss
;
298 bss
->conf
->start_disabled
= 1;
299 bss
->conf
->mesh
= MESH_ENABLED
;
300 bss
->conf
->ap_max_inactivity
= wpa_s
->conf
->mesh_max_inactivity
;
302 if (ieee80211_is_dfs(ssid
->frequency
, wpa_s
->hw
.modes
,
303 wpa_s
->hw
.num_modes
) && wpa_s
->conf
->country
[0]) {
304 conf
->ieee80211h
= 1;
305 conf
->ieee80211d
= 1;
306 conf
->country
[0] = wpa_s
->conf
->country
[0];
307 conf
->country
[1] = wpa_s
->conf
->country
[1];
308 conf
->country
[2] = ' ';
314 ifmsh
->bss
[0]->max_plinks
= wpa_s
->conf
->max_peer_links
;
315 ifmsh
->bss
[0]->dot11RSNASAERetransPeriod
=
316 wpa_s
->conf
->dot11RSNASAERetransPeriod
;
317 os_strlcpy(bss
->conf
->iface
, wpa_s
->ifname
, sizeof(bss
->conf
->iface
));
319 mconf
= mesh_config_create(wpa_s
, ssid
);
322 ifmsh
->mconf
= mconf
;
324 /* need conf->hw_mode for supported rates. */
325 conf
->hw_mode
= ieee80211_freq_to_chan(frequency
, &conf
->channel
);
326 if (conf
->hw_mode
== NUM_HOSTAPD_MODES
) {
327 wpa_printf(MSG_ERROR
, "Unsupported mesh mode frequency: %d MHz",
332 conf
->secondary_channel
= ssid
->ht40
;
333 if (conf
->hw_mode
== HOSTAPD_MODE_IEEE80211A
&& ssid
->vht
) {
334 if (ssid
->max_oper_chwidth
!= DEFAULT_MAX_OPER_CHWIDTH
)
335 conf
->vht_oper_chwidth
= ssid
->max_oper_chwidth
;
336 switch (conf
->vht_oper_chwidth
) {
337 case CHANWIDTH_80MHZ
:
338 case CHANWIDTH_80P80MHZ
:
339 ieee80211_freq_to_chan(
341 &conf
->vht_oper_centr_freq_seg0_idx
);
342 conf
->vht_oper_centr_freq_seg0_idx
+= ssid
->ht40
* 2;
344 case CHANWIDTH_160MHZ
:
345 ieee80211_freq_to_chan(
347 &conf
->vht_oper_centr_freq_seg0_idx
);
348 conf
->vht_oper_centr_freq_seg0_idx
+= ssid
->ht40
* 2;
349 conf
->vht_oper_centr_freq_seg0_idx
+= 40 / 5;
352 ieee80211_freq_to_chan(ssid
->vht_center_freq2
,
353 &conf
->vht_oper_centr_freq_seg1_idx
);
356 if (ssid
->mesh_basic_rates
== NULL
) {
358 * XXX: Hack! This is so an MPM which correctly sets the ERP
359 * mandatory rates as BSSBasicRateSet doesn't reject us. We
360 * could add a new hw_mode HOSTAPD_MODE_IEEE80211G_ERP, but
361 * this is way easier. This also makes our BSSBasicRateSet
362 * advertised in beacons match the one in peering frames, sigh.
364 if (conf
->hw_mode
== HOSTAPD_MODE_IEEE80211G
) {
365 conf
->basic_rates
= os_memdup(basic_rates_erp
,
366 sizeof(basic_rates_erp
));
367 if (!conf
->basic_rates
)
373 if (ssid
->mesh_basic_rates
[rate_len
] < 1)
377 conf
->basic_rates
= os_calloc(rate_len
+ 1, sizeof(int));
378 if (conf
->basic_rates
== NULL
)
380 os_memcpy(conf
->basic_rates
, ssid
->mesh_basic_rates
,
381 rate_len
* sizeof(int));
382 conf
->basic_rates
[rate_len
] = -1;
385 if (wpa_drv_init_mesh(wpa_s
)) {
386 wpa_msg(wpa_s
, MSG_ERROR
, "Failed to init mesh in driver");
390 if (hostapd_setup_interface(ifmsh
)) {
391 wpa_printf(MSG_ERROR
,
392 "Failed to initialize hostapd interface for mesh");
396 wpa_supplicant_conf_ap_ht(wpa_s
, ssid
, conf
);
400 wpa_supplicant_mesh_deinit(wpa_s
);
405 void wpa_mesh_notify_peer(struct wpa_supplicant
*wpa_s
, const u8
*addr
,
406 const u8
*ies
, size_t ie_len
)
408 struct ieee802_11_elems elems
;
410 wpa_msg(wpa_s
, MSG_INFO
,
411 "new peer notification for " MACSTR
, MAC2STR(addr
));
413 if (ieee802_11_parse_elems(ies
, ie_len
, &elems
, 0) == ParseFailed
) {
414 wpa_msg(wpa_s
, MSG_INFO
, "Could not parse beacon from " MACSTR
,
418 wpa_mesh_new_mesh_peer(wpa_s
, addr
, &elems
);
422 void wpa_supplicant_mesh_add_scan_ie(struct wpa_supplicant
*wpa_s
,
423 struct wpabuf
**extra_ie
)
425 /* EID + 0-length (wildcard) mesh-id */
428 if (wpabuf_resize(extra_ie
, ielen
) == 0) {
429 wpabuf_put_u8(*extra_ie
, WLAN_EID_MESH_ID
);
430 wpabuf_put_u8(*extra_ie
, 0);
435 int wpa_supplicant_join_mesh(struct wpa_supplicant
*wpa_s
,
436 struct wpa_ssid
*ssid
)
438 struct wpa_driver_mesh_join_params
*params
= os_zalloc(sizeof(*params
));
441 if (!ssid
|| !ssid
->ssid
|| !ssid
->ssid_len
|| !ssid
->frequency
||
448 wpa_supplicant_mesh_deinit(wpa_s
);
450 wpa_s
->pairwise_cipher
= WPA_CIPHER_NONE
;
451 wpa_s
->group_cipher
= WPA_CIPHER_NONE
;
452 wpa_s
->mgmt_group_cipher
= 0;
454 params
->meshid
= ssid
->ssid
;
455 params
->meshid_len
= ssid
->ssid_len
;
456 ibss_mesh_setup_freq(wpa_s
, ssid
, ¶ms
->freq
);
457 wpa_s
->mesh_ht_enabled
= !!params
->freq
.ht_enabled
;
458 wpa_s
->mesh_vht_enabled
= !!params
->freq
.vht_enabled
;
459 wpa_s
->mesh_he_enabled
= !!params
->freq
.he_enabled
;
460 if (params
->freq
.ht_enabled
&& params
->freq
.sec_channel_offset
)
461 ssid
->ht40
= params
->freq
.sec_channel_offset
;
463 if (wpa_s
->mesh_vht_enabled
) {
465 ssid
->vht_center_freq1
= params
->freq
.center_freq1
;
466 switch (params
->freq
.bandwidth
) {
468 if (params
->freq
.center_freq2
) {
469 ssid
->max_oper_chwidth
= CHANWIDTH_80P80MHZ
;
470 ssid
->vht_center_freq2
=
471 params
->freq
.center_freq2
;
473 ssid
->max_oper_chwidth
= CHANWIDTH_80MHZ
;
477 ssid
->max_oper_chwidth
= CHANWIDTH_160MHZ
;
480 ssid
->max_oper_chwidth
= CHANWIDTH_USE_HT
;
484 if (wpa_s
->mesh_he_enabled
)
486 if (ssid
->beacon_int
> 0)
487 params
->beacon_int
= ssid
->beacon_int
;
488 else if (wpa_s
->conf
->beacon_int
> 0)
489 params
->beacon_int
= wpa_s
->conf
->beacon_int
;
490 if (ssid
->dtim_period
> 0)
491 params
->dtim_period
= ssid
->dtim_period
;
492 else if (wpa_s
->conf
->dtim_period
> 0)
493 params
->dtim_period
= wpa_s
->conf
->dtim_period
;
494 params
->conf
.max_peer_links
= wpa_s
->conf
->max_peer_links
;
495 if (ssid
->mesh_rssi_threshold
< DEFAULT_MESH_RSSI_THRESHOLD
) {
496 params
->conf
.rssi_threshold
= ssid
->mesh_rssi_threshold
;
497 params
->conf
.flags
|= WPA_DRIVER_MESH_CONF_FLAG_RSSI_THRESHOLD
;
500 if (ssid
->key_mgmt
& WPA_KEY_MGMT_SAE
) {
501 params
->flags
|= WPA_DRIVER_MESH_FLAG_SAE_AUTH
;
502 params
->flags
|= WPA_DRIVER_MESH_FLAG_AMPE
;
503 wpa_s
->conf
->user_mpm
= 1;
506 if (wpa_s
->conf
->user_mpm
) {
507 params
->flags
|= WPA_DRIVER_MESH_FLAG_USER_MPM
;
508 params
->conf
.auto_plinks
= 0;
510 params
->flags
|= WPA_DRIVER_MESH_FLAG_DRIVER_MPM
;
511 params
->conf
.auto_plinks
= 1;
513 params
->conf
.peer_link_timeout
= wpa_s
->conf
->mesh_max_inactivity
;
515 os_free(wpa_s
->mesh_params
);
516 wpa_s
->mesh_params
= params
;
517 if (wpa_supplicant_mesh_init(wpa_s
, ssid
, ¶ms
->freq
)) {
518 wpa_msg(wpa_s
, MSG_ERROR
, "Failed to init mesh");
519 wpa_drv_leave_mesh(wpa_s
);
524 ret
= wpas_mesh_complete(wpa_s
);
530 int wpa_supplicant_leave_mesh(struct wpa_supplicant
*wpa_s
)
534 wpa_msg(wpa_s
, MSG_INFO
, "leaving mesh");
536 /* Need to send peering close messages first */
537 wpa_supplicant_mesh_deinit(wpa_s
);
539 ret
= wpa_drv_leave_mesh(wpa_s
);
541 wpa_msg(wpa_s
, MSG_ERROR
, "mesh leave error=%d", ret
);
543 wpa_drv_set_operstate(wpa_s
, 1);
549 static int mesh_attr_text(const u8
*ies
, size_t ies_len
, char *buf
, char *end
)
551 struct ieee802_11_elems elems
;
552 char *mesh_id
, *pos
= buf
;
553 u8
*bss_basic_rate_set
;
554 int bss_basic_rate_set_len
, ret
, i
;
556 if (ieee802_11_parse_elems(ies
, ies_len
, &elems
, 0) == ParseFailed
)
559 if (elems
.mesh_id_len
< 1)
562 mesh_id
= os_malloc(elems
.mesh_id_len
+ 1);
566 os_memcpy(mesh_id
, elems
.mesh_id
, elems
.mesh_id_len
);
567 mesh_id
[elems
.mesh_id_len
] = '\0';
568 ret
= os_snprintf(pos
, end
- pos
, "mesh_id=%s\n", mesh_id
);
570 if (os_snprintf_error(end
- pos
, ret
))
574 if (elems
.mesh_config_len
> 6) {
575 ret
= os_snprintf(pos
, end
- pos
,
576 "active_path_selection_protocol_id=0x%02x\n"
577 "active_path_selection_metric_id=0x%02x\n"
578 "congestion_control_mode_id=0x%02x\n"
579 "synchronization_method_id=0x%02x\n"
580 "authentication_protocol_id=0x%02x\n"
581 "mesh_formation_info=0x%02x\n"
582 "mesh_capability=0x%02x\n",
583 elems
.mesh_config
[0], elems
.mesh_config
[1],
584 elems
.mesh_config
[2], elems
.mesh_config
[3],
585 elems
.mesh_config
[4], elems
.mesh_config
[5],
586 elems
.mesh_config
[6]);
587 if (os_snprintf_error(end
- pos
, ret
))
592 bss_basic_rate_set
= os_malloc(elems
.supp_rates_len
+
593 elems
.ext_supp_rates_len
);
594 if (bss_basic_rate_set
== NULL
)
597 bss_basic_rate_set_len
= 0;
598 for (i
= 0; i
< elems
.supp_rates_len
; i
++) {
599 if (elems
.supp_rates
[i
] & 0x80) {
600 bss_basic_rate_set
[bss_basic_rate_set_len
++] =
601 (elems
.supp_rates
[i
] & 0x7f) * 5;
604 for (i
= 0; i
< elems
.ext_supp_rates_len
; i
++) {
605 if (elems
.ext_supp_rates
[i
] & 0x80) {
606 bss_basic_rate_set
[bss_basic_rate_set_len
++] =
607 (elems
.ext_supp_rates
[i
] & 0x7f) * 5;
610 if (bss_basic_rate_set_len
> 0) {
611 ret
= os_snprintf(pos
, end
- pos
, "bss_basic_rate_set=%d",
612 bss_basic_rate_set
[0]);
613 if (os_snprintf_error(end
- pos
, ret
))
617 for (i
= 1; i
< bss_basic_rate_set_len
; i
++) {
618 ret
= os_snprintf(pos
, end
- pos
, " %d",
619 bss_basic_rate_set
[i
]);
620 if (os_snprintf_error(end
- pos
, ret
))
625 ret
= os_snprintf(pos
, end
- pos
, "\n");
626 if (os_snprintf_error(end
- pos
, ret
))
631 os_free(bss_basic_rate_set
);
637 int wpas_mesh_scan_result_text(const u8
*ies
, size_t ies_len
, char *buf
,
640 return mesh_attr_text(ies
, ies_len
, buf
, end
);
644 static int wpas_mesh_get_ifname(struct wpa_supplicant
*wpa_s
, char *ifname
,
647 char *ifname_ptr
= wpa_s
->ifname
;
650 res
= os_snprintf(ifname
, len
, "mesh-%s-%d", ifname_ptr
,
652 if (os_snprintf_error(len
, res
) ||
653 (os_strlen(ifname
) >= IFNAMSIZ
&&
654 os_strlen(wpa_s
->ifname
) < IFNAMSIZ
)) {
655 /* Try to avoid going over the IFNAMSIZ length limit */
656 res
= os_snprintf(ifname
, len
, "mesh-%d", wpa_s
->mesh_if_idx
);
657 if (os_snprintf_error(len
, res
))
660 wpa_s
->mesh_if_idx
++;
665 int wpas_mesh_add_interface(struct wpa_supplicant
*wpa_s
, char *ifname
,
668 struct wpa_interface iface
;
669 struct wpa_supplicant
*mesh_wpa_s
;
672 if (ifname
[0] == '\0' && wpas_mesh_get_ifname(wpa_s
, ifname
, len
) < 0)
675 if (wpa_drv_if_add(wpa_s
, WPA_IF_MESH
, ifname
, NULL
, NULL
, NULL
, addr
,
677 wpa_printf(MSG_ERROR
,
678 "mesh: Failed to create new mesh interface");
681 wpa_printf(MSG_INFO
, "mesh: Created virtual interface %s addr "
682 MACSTR
, ifname
, MAC2STR(addr
));
684 os_memset(&iface
, 0, sizeof(iface
));
685 iface
.ifname
= ifname
;
686 iface
.driver
= wpa_s
->driver
->name
;
687 iface
.driver_param
= wpa_s
->conf
->driver_param
;
688 iface
.ctrl_interface
= wpa_s
->conf
->ctrl_interface
;
690 mesh_wpa_s
= wpa_supplicant_add_iface(wpa_s
->global
, &iface
, wpa_s
);
692 wpa_printf(MSG_ERROR
,
693 "mesh: Failed to create new wpa_supplicant interface");
694 wpa_drv_if_remove(wpa_s
, WPA_IF_MESH
, ifname
);
697 mesh_wpa_s
->mesh_if_created
= 1;
702 int wpas_mesh_peer_remove(struct wpa_supplicant
*wpa_s
, const u8
*addr
)
704 return mesh_mpm_close_peer(wpa_s
, addr
);
708 int wpas_mesh_peer_add(struct wpa_supplicant
*wpa_s
, const u8
*addr
,
711 return mesh_mpm_connect_peer(wpa_s
, addr
, duration
);