1 /* 2 * WPA Supplicant - Basic mesh mode routines 3 * Copyright (c) 2013-2014, cozybit, Inc. All rights reserved. 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 "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" 20 #include "config.h" 21 #include "wpa_supplicant_i.h" 22 #include "driver_i.h" 23 #include "notify.h" 24 #include "ap.h" 25 #include "mesh_mpm.h" 26 #include "mesh_rsn.h" 27 #include "mesh.h" 28 29 30 static void wpa_supplicant_mesh_deinit(struct wpa_supplicant *wpa_s) 31 { 32 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh); 33 wpa_s->ifmsh = NULL; 34 wpa_s->current_ssid = NULL; 35 os_free(wpa_s->mesh_rsn); 36 wpa_s->mesh_rsn = NULL; 37 /* TODO: leave mesh (stop beacon). This will happen on link down 38 * anyway, so it's not urgent */ 39 } 40 41 42 void wpa_supplicant_mesh_iface_deinit(struct wpa_supplicant *wpa_s, 43 struct hostapd_iface *ifmsh) 44 { 45 if (!ifmsh) 46 return; 47 48 if (ifmsh->mconf) { 49 mesh_mpm_deinit(wpa_s, ifmsh); 50 if (ifmsh->mconf->rsn_ie) { 51 ifmsh->mconf->rsn_ie = NULL; 52 /* We cannot free this struct 53 * because wpa_authenticator on 54 * hostapd side is also using it 55 * for now just set to NULL and 56 * let hostapd code free it. 57 */ 58 } 59 os_free(ifmsh->mconf); 60 ifmsh->mconf = NULL; 61 } 62 63 /* take care of shared data */ 64 hostapd_interface_deinit(ifmsh); 65 hostapd_interface_free(ifmsh); 66 } 67 68 69 static struct mesh_conf * mesh_config_create(struct wpa_supplicant *wpa_s, 70 struct wpa_ssid *ssid) 71 { 72 struct mesh_conf *conf; 73 int cipher; 74 75 conf = os_zalloc(sizeof(struct mesh_conf)); 76 if (!conf) 77 return NULL; 78 79 os_memcpy(conf->meshid, ssid->ssid, ssid->ssid_len); 80 conf->meshid_len = ssid->ssid_len; 81 82 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) 83 conf->security |= MESH_CONF_SEC_AUTH | 84 MESH_CONF_SEC_AMPE; 85 else 86 conf->security |= MESH_CONF_SEC_NONE; 87 #ifdef CONFIG_IEEE80211W 88 conf->ieee80211w = ssid->ieee80211w; 89 if (conf->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) { 90 if (wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP) 91 conf->ieee80211w = wpa_s->conf->pmf; 92 else 93 conf->ieee80211w = NO_MGMT_FRAME_PROTECTION; 94 } 95 #endif /* CONFIG_IEEE80211W */ 96 97 cipher = wpa_pick_pairwise_cipher(ssid->pairwise_cipher, 0); 98 if (cipher < 0 || cipher == WPA_CIPHER_TKIP) { 99 wpa_msg(wpa_s, MSG_INFO, "mesh: Invalid pairwise cipher"); 100 os_free(conf); 101 return NULL; 102 } 103 conf->pairwise_cipher = cipher; 104 105 cipher = wpa_pick_group_cipher(ssid->group_cipher); 106 if (cipher < 0 || cipher == WPA_CIPHER_TKIP || 107 cipher == WPA_CIPHER_GTK_NOT_USED) { 108 wpa_msg(wpa_s, MSG_INFO, "mesh: Invalid group cipher"); 109 os_free(conf); 110 return NULL; 111 } 112 113 conf->group_cipher = cipher; 114 if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) 115 conf->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC; 116 117 /* defaults */ 118 conf->mesh_pp_id = MESH_PATH_PROTOCOL_HWMP; 119 conf->mesh_pm_id = MESH_PATH_METRIC_AIRTIME; 120 conf->mesh_cc_id = 0; 121 conf->mesh_sp_id = MESH_SYNC_METHOD_NEIGHBOR_OFFSET; 122 conf->mesh_auth_id = (conf->security & MESH_CONF_SEC_AUTH) ? 1 : 0; 123 conf->dot11MeshMaxRetries = ssid->dot11MeshMaxRetries; 124 conf->dot11MeshRetryTimeout = ssid->dot11MeshRetryTimeout; 125 conf->dot11MeshConfirmTimeout = ssid->dot11MeshConfirmTimeout; 126 conf->dot11MeshHoldingTimeout = ssid->dot11MeshHoldingTimeout; 127 128 return conf; 129 } 130 131 132 static void wpas_mesh_copy_groups(struct hostapd_data *bss, 133 struct wpa_supplicant *wpa_s) 134 { 135 int num_groups; 136 size_t groups_size; 137 138 for (num_groups = 0; wpa_s->conf->sae_groups[num_groups] > 0; 139 num_groups++) 140 ; 141 142 groups_size = (num_groups + 1) * sizeof(wpa_s->conf->sae_groups[0]); 143 bss->conf->sae_groups = os_malloc(groups_size); 144 if (bss->conf->sae_groups) 145 os_memcpy(bss->conf->sae_groups, wpa_s->conf->sae_groups, 146 groups_size); 147 } 148 149 150 static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, 151 struct wpa_ssid *ssid, 152 struct hostapd_freq_params *freq) 153 { 154 struct hostapd_iface *ifmsh; 155 struct hostapd_data *bss; 156 struct hostapd_config *conf; 157 struct mesh_conf *mconf; 158 int basic_rates_erp[] = { 10, 20, 55, 60, 110, 120, 240, -1 }; 159 static int default_groups[] = { 19, 20, 21, 25, 26, -1 }; 160 const char *password; 161 size_t len; 162 int rate_len; 163 int frequency; 164 165 if (!wpa_s->conf->user_mpm) { 166 /* not much for us to do here */ 167 wpa_msg(wpa_s, MSG_WARNING, 168 "user_mpm is not enabled in configuration"); 169 return 0; 170 } 171 172 wpa_s->ifmsh = ifmsh = hostapd_alloc_iface(); 173 if (!ifmsh) 174 return -ENOMEM; 175 176 ifmsh->drv_flags = wpa_s->drv_flags; 177 ifmsh->num_bss = 1; 178 ifmsh->bss = os_calloc(wpa_s->ifmsh->num_bss, 179 sizeof(struct hostapd_data *)); 180 if (!ifmsh->bss) 181 goto out_free; 182 183 ifmsh->bss[0] = bss = hostapd_alloc_bss_data(NULL, NULL, NULL); 184 if (!bss) 185 goto out_free; 186 187 ifmsh->bss[0]->msg_ctx = wpa_s; 188 os_memcpy(bss->own_addr, wpa_s->own_addr, ETH_ALEN); 189 bss->driver = wpa_s->driver; 190 bss->drv_priv = wpa_s->drv_priv; 191 bss->iface = ifmsh; 192 bss->mesh_sta_free_cb = mesh_mpm_free_sta; 193 frequency = ssid->frequency; 194 if (frequency != freq->freq && 195 frequency == freq->freq + freq->sec_channel_offset * 20) { 196 wpa_printf(MSG_DEBUG, "mesh: pri/sec channels switched"); 197 frequency = freq->freq; 198 } 199 wpa_s->assoc_freq = frequency; 200 wpa_s->current_ssid = ssid; 201 202 /* setup an AP config for auth processing */ 203 conf = hostapd_config_defaults(); 204 if (!conf) 205 goto out_free; 206 207 bss->conf = *conf->bss; 208 bss->conf->start_disabled = 1; 209 bss->conf->mesh = MESH_ENABLED; 210 bss->conf->ap_max_inactivity = wpa_s->conf->mesh_max_inactivity; 211 bss->iconf = conf; 212 ifmsh->conf = conf; 213 214 ifmsh->bss[0]->max_plinks = wpa_s->conf->max_peer_links; 215 ifmsh->bss[0]->dot11RSNASAERetransPeriod = 216 wpa_s->conf->dot11RSNASAERetransPeriod; 217 os_strlcpy(bss->conf->iface, wpa_s->ifname, sizeof(bss->conf->iface)); 218 219 mconf = mesh_config_create(wpa_s, ssid); 220 if (!mconf) 221 goto out_free; 222 ifmsh->mconf = mconf; 223 224 /* need conf->hw_mode for supported rates. */ 225 conf->hw_mode = ieee80211_freq_to_chan(frequency, &conf->channel); 226 if (conf->hw_mode == NUM_HOSTAPD_MODES) { 227 wpa_printf(MSG_ERROR, "Unsupported mesh mode frequency: %d MHz", 228 frequency); 229 goto out_free; 230 } 231 if (ssid->ht40) 232 conf->secondary_channel = ssid->ht40; 233 if (conf->hw_mode == HOSTAPD_MODE_IEEE80211A && ssid->vht) { 234 conf->vht_oper_chwidth = ssid->max_oper_chwidth; 235 switch (conf->vht_oper_chwidth) { 236 case VHT_CHANWIDTH_80MHZ: 237 case VHT_CHANWIDTH_80P80MHZ: 238 ieee80211_freq_to_chan( 239 frequency, 240 &conf->vht_oper_centr_freq_seg0_idx); 241 conf->vht_oper_centr_freq_seg0_idx += ssid->ht40 * 2; 242 break; 243 case VHT_CHANWIDTH_160MHZ: 244 ieee80211_freq_to_chan( 245 frequency, 246 &conf->vht_oper_centr_freq_seg0_idx); 247 conf->vht_oper_centr_freq_seg0_idx += ssid->ht40 * 2; 248 conf->vht_oper_centr_freq_seg0_idx += 40 / 5; 249 break; 250 } 251 ieee80211_freq_to_chan(ssid->vht_center_freq2, 252 &conf->vht_oper_centr_freq_seg1_idx); 253 } 254 255 if (ssid->mesh_basic_rates == NULL) { 256 /* 257 * XXX: Hack! This is so an MPM which correctly sets the ERP 258 * mandatory rates as BSSBasicRateSet doesn't reject us. We 259 * could add a new hw_mode HOSTAPD_MODE_IEEE80211G_ERP, but 260 * this is way easier. This also makes our BSSBasicRateSet 261 * advertised in beacons match the one in peering frames, sigh. 262 */ 263 if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G) { 264 conf->basic_rates = os_memdup(basic_rates_erp, 265 sizeof(basic_rates_erp)); 266 if (!conf->basic_rates) 267 goto out_free; 268 } 269 } else { 270 rate_len = 0; 271 while (1) { 272 if (ssid->mesh_basic_rates[rate_len] < 1) 273 break; 274 rate_len++; 275 } 276 conf->basic_rates = os_calloc(rate_len + 1, sizeof(int)); 277 if (conf->basic_rates == NULL) 278 goto out_free; 279 os_memcpy(conf->basic_rates, ssid->mesh_basic_rates, 280 rate_len * sizeof(int)); 281 conf->basic_rates[rate_len] = -1; 282 } 283 284 if (hostapd_setup_interface(ifmsh)) { 285 wpa_printf(MSG_ERROR, 286 "Failed to initialize hostapd interface for mesh"); 287 return -1; 288 } 289 290 if (wpa_drv_init_mesh(wpa_s)) { 291 wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh in driver"); 292 return -1; 293 } 294 295 if (mconf->security != MESH_CONF_SEC_NONE) { 296 password = ssid->sae_password; 297 if (!password) 298 password = ssid->passphrase; 299 if (!password) { 300 wpa_printf(MSG_ERROR, 301 "mesh: Passphrase for SAE not configured"); 302 goto out_free; 303 } 304 305 bss->conf->wpa = ssid->proto; 306 bss->conf->wpa_key_mgmt = ssid->key_mgmt; 307 308 if (wpa_s->conf->sae_groups && 309 wpa_s->conf->sae_groups[0] > 0) { 310 wpas_mesh_copy_groups(bss, wpa_s); 311 } else { 312 bss->conf->sae_groups = 313 os_memdup(default_groups, 314 sizeof(default_groups)); 315 if (!bss->conf->sae_groups) 316 goto out_free; 317 } 318 319 len = os_strlen(password); 320 bss->conf->ssid.wpa_passphrase = 321 dup_binstr(password, len); 322 323 wpa_s->mesh_rsn = mesh_rsn_auth_init(wpa_s, mconf); 324 if (!wpa_s->mesh_rsn) 325 goto out_free; 326 } 327 328 wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf); 329 330 return 0; 331 out_free: 332 wpa_supplicant_mesh_deinit(wpa_s); 333 return -ENOMEM; 334 } 335 336 337 void wpa_mesh_notify_peer(struct wpa_supplicant *wpa_s, const u8 *addr, 338 const u8 *ies, size_t ie_len) 339 { 340 struct ieee802_11_elems elems; 341 342 wpa_msg(wpa_s, MSG_INFO, 343 "new peer notification for " MACSTR, MAC2STR(addr)); 344 345 if (ieee802_11_parse_elems(ies, ie_len, &elems, 0) == ParseFailed) { 346 wpa_msg(wpa_s, MSG_INFO, "Could not parse beacon from " MACSTR, 347 MAC2STR(addr)); 348 return; 349 } 350 wpa_mesh_new_mesh_peer(wpa_s, addr, &elems); 351 } 352 353 354 void wpa_supplicant_mesh_add_scan_ie(struct wpa_supplicant *wpa_s, 355 struct wpabuf **extra_ie) 356 { 357 /* EID + 0-length (wildcard) mesh-id */ 358 size_t ielen = 2; 359 360 if (wpabuf_resize(extra_ie, ielen) == 0) { 361 wpabuf_put_u8(*extra_ie, WLAN_EID_MESH_ID); 362 wpabuf_put_u8(*extra_ie, 0); 363 } 364 } 365 366 367 int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s, 368 struct wpa_ssid *ssid) 369 { 370 struct wpa_driver_mesh_join_params params; 371 int ret = 0; 372 373 if (!ssid || !ssid->ssid || !ssid->ssid_len || !ssid->frequency) { 374 ret = -ENOENT; 375 goto out; 376 } 377 378 wpa_supplicant_mesh_deinit(wpa_s); 379 380 wpa_s->pairwise_cipher = WPA_CIPHER_NONE; 381 wpa_s->group_cipher = WPA_CIPHER_NONE; 382 wpa_s->mgmt_group_cipher = 0; 383 384 os_memset(¶ms, 0, sizeof(params)); 385 params.meshid = ssid->ssid; 386 params.meshid_len = ssid->ssid_len; 387 ibss_mesh_setup_freq(wpa_s, ssid, ¶ms.freq); 388 wpa_s->mesh_ht_enabled = !!params.freq.ht_enabled; 389 wpa_s->mesh_vht_enabled = !!params.freq.vht_enabled; 390 if (params.freq.ht_enabled && params.freq.sec_channel_offset) 391 ssid->ht40 = params.freq.sec_channel_offset; 392 if (wpa_s->mesh_vht_enabled) { 393 ssid->vht = 1; 394 switch (params.freq.bandwidth) { 395 case 80: 396 if (params.freq.center_freq2) { 397 ssid->max_oper_chwidth = VHT_CHANWIDTH_80P80MHZ; 398 ssid->vht_center_freq2 = 399 params.freq.center_freq2; 400 } else { 401 ssid->max_oper_chwidth = VHT_CHANWIDTH_80MHZ; 402 } 403 break; 404 case 160: 405 ssid->max_oper_chwidth = VHT_CHANWIDTH_160MHZ; 406 break; 407 default: 408 ssid->max_oper_chwidth = VHT_CHANWIDTH_USE_HT; 409 break; 410 } 411 } 412 if (ssid->beacon_int > 0) 413 params.beacon_int = ssid->beacon_int; 414 else if (wpa_s->conf->beacon_int > 0) 415 params.beacon_int = wpa_s->conf->beacon_int; 416 if (ssid->dtim_period > 0) 417 params.dtim_period = ssid->dtim_period; 418 else if (wpa_s->conf->dtim_period > 0) 419 params.dtim_period = wpa_s->conf->dtim_period; 420 params.conf.max_peer_links = wpa_s->conf->max_peer_links; 421 if (ssid->mesh_rssi_threshold < DEFAULT_MESH_RSSI_THRESHOLD) { 422 params.conf.rssi_threshold = ssid->mesh_rssi_threshold; 423 params.conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_RSSI_THRESHOLD; 424 } 425 426 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) { 427 params.flags |= WPA_DRIVER_MESH_FLAG_SAE_AUTH; 428 params.flags |= WPA_DRIVER_MESH_FLAG_AMPE; 429 wpa_s->conf->user_mpm = 1; 430 } 431 432 if (wpa_s->conf->user_mpm) { 433 params.flags |= WPA_DRIVER_MESH_FLAG_USER_MPM; 434 params.conf.auto_plinks = 0; 435 } else { 436 params.flags |= WPA_DRIVER_MESH_FLAG_DRIVER_MPM; 437 params.conf.auto_plinks = 1; 438 } 439 params.conf.peer_link_timeout = wpa_s->conf->mesh_max_inactivity; 440 441 if (wpa_supplicant_mesh_init(wpa_s, ssid, ¶ms.freq)) { 442 wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh"); 443 wpa_drv_leave_mesh(wpa_s); 444 ret = -1; 445 goto out; 446 } 447 448 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) { 449 wpa_s->pairwise_cipher = wpa_s->mesh_rsn->pairwise_cipher; 450 wpa_s->group_cipher = wpa_s->mesh_rsn->group_cipher; 451 wpa_s->mgmt_group_cipher = wpa_s->mesh_rsn->mgmt_group_cipher; 452 } 453 454 if (wpa_s->ifmsh) { 455 params.ies = wpa_s->ifmsh->mconf->rsn_ie; 456 params.ie_len = wpa_s->ifmsh->mconf->rsn_ie_len; 457 params.basic_rates = wpa_s->ifmsh->basic_rates; 458 params.conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE; 459 params.conf.ht_opmode = wpa_s->ifmsh->bss[0]->iface->ht_op_mode; 460 } 461 462 wpa_msg(wpa_s, MSG_INFO, "joining mesh %s", 463 wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); 464 ret = wpa_drv_join_mesh(wpa_s, ¶ms); 465 if (ret) 466 wpa_msg(wpa_s, MSG_ERROR, "mesh join error=%d", ret); 467 468 /* hostapd sets the interface down until we associate */ 469 wpa_drv_set_operstate(wpa_s, 1); 470 471 if (!ret) 472 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); 473 474 out: 475 return ret; 476 } 477 478 479 int wpa_supplicant_leave_mesh(struct wpa_supplicant *wpa_s) 480 { 481 int ret = 0; 482 483 wpa_msg(wpa_s, MSG_INFO, "leaving mesh"); 484 485 /* Need to send peering close messages first */ 486 wpa_supplicant_mesh_deinit(wpa_s); 487 488 ret = wpa_drv_leave_mesh(wpa_s); 489 if (ret) 490 wpa_msg(wpa_s, MSG_ERROR, "mesh leave error=%d", ret); 491 492 wpa_drv_set_operstate(wpa_s, 1); 493 494 return ret; 495 } 496 497 498 static int mesh_attr_text(const u8 *ies, size_t ies_len, char *buf, char *end) 499 { 500 struct ieee802_11_elems elems; 501 char *mesh_id, *pos = buf; 502 u8 *bss_basic_rate_set; 503 int bss_basic_rate_set_len, ret, i; 504 505 if (ieee802_11_parse_elems(ies, ies_len, &elems, 0) == ParseFailed) 506 return -1; 507 508 if (elems.mesh_id_len < 1) 509 return 0; 510 511 mesh_id = os_malloc(elems.mesh_id_len + 1); 512 if (mesh_id == NULL) 513 return -1; 514 515 os_memcpy(mesh_id, elems.mesh_id, elems.mesh_id_len); 516 mesh_id[elems.mesh_id_len] = '\0'; 517 ret = os_snprintf(pos, end - pos, "mesh_id=%s\n", mesh_id); 518 os_free(mesh_id); 519 if (os_snprintf_error(end - pos, ret)) 520 return pos - buf; 521 pos += ret; 522 523 if (elems.mesh_config_len > 6) { 524 ret = os_snprintf(pos, end - pos, 525 "active_path_selection_protocol_id=0x%02x\n" 526 "active_path_selection_metric_id=0x%02x\n" 527 "congestion_control_mode_id=0x%02x\n" 528 "synchronization_method_id=0x%02x\n" 529 "authentication_protocol_id=0x%02x\n" 530 "mesh_formation_info=0x%02x\n" 531 "mesh_capability=0x%02x\n", 532 elems.mesh_config[0], elems.mesh_config[1], 533 elems.mesh_config[2], elems.mesh_config[3], 534 elems.mesh_config[4], elems.mesh_config[5], 535 elems.mesh_config[6]); 536 if (os_snprintf_error(end - pos, ret)) 537 return pos - buf; 538 pos += ret; 539 } 540 541 bss_basic_rate_set = os_malloc(elems.supp_rates_len + 542 elems.ext_supp_rates_len); 543 if (bss_basic_rate_set == NULL) 544 return -1; 545 546 bss_basic_rate_set_len = 0; 547 for (i = 0; i < elems.supp_rates_len; i++) { 548 if (elems.supp_rates[i] & 0x80) { 549 bss_basic_rate_set[bss_basic_rate_set_len++] = 550 (elems.supp_rates[i] & 0x7f) * 5; 551 } 552 } 553 for (i = 0; i < elems.ext_supp_rates_len; i++) { 554 if (elems.ext_supp_rates[i] & 0x80) { 555 bss_basic_rate_set[bss_basic_rate_set_len++] = 556 (elems.ext_supp_rates[i] & 0x7f) * 5; 557 } 558 } 559 if (bss_basic_rate_set_len > 0) { 560 ret = os_snprintf(pos, end - pos, "bss_basic_rate_set=%d", 561 bss_basic_rate_set[0]); 562 if (os_snprintf_error(end - pos, ret)) 563 goto fail; 564 pos += ret; 565 566 for (i = 1; i < bss_basic_rate_set_len; i++) { 567 ret = os_snprintf(pos, end - pos, " %d", 568 bss_basic_rate_set[i]); 569 if (os_snprintf_error(end - pos, ret)) 570 goto fail; 571 pos += ret; 572 } 573 574 ret = os_snprintf(pos, end - pos, "\n"); 575 if (os_snprintf_error(end - pos, ret)) 576 goto fail; 577 pos += ret; 578 } 579 fail: 580 os_free(bss_basic_rate_set); 581 582 return pos - buf; 583 } 584 585 586 int wpas_mesh_scan_result_text(const u8 *ies, size_t ies_len, char *buf, 587 char *end) 588 { 589 return mesh_attr_text(ies, ies_len, buf, end); 590 } 591 592 593 static int wpas_mesh_get_ifname(struct wpa_supplicant *wpa_s, char *ifname, 594 size_t len) 595 { 596 char *ifname_ptr = wpa_s->ifname; 597 int res; 598 599 res = os_snprintf(ifname, len, "mesh-%s-%d", ifname_ptr, 600 wpa_s->mesh_if_idx); 601 if (os_snprintf_error(len, res) || 602 (os_strlen(ifname) >= IFNAMSIZ && 603 os_strlen(wpa_s->ifname) < IFNAMSIZ)) { 604 /* Try to avoid going over the IFNAMSIZ length limit */ 605 res = os_snprintf(ifname, len, "mesh-%d", wpa_s->mesh_if_idx); 606 if (os_snprintf_error(len, res)) 607 return -1; 608 } 609 wpa_s->mesh_if_idx++; 610 return 0; 611 } 612 613 614 int wpas_mesh_add_interface(struct wpa_supplicant *wpa_s, char *ifname, 615 size_t len) 616 { 617 struct wpa_interface iface; 618 struct wpa_supplicant *mesh_wpa_s; 619 u8 addr[ETH_ALEN]; 620 621 if (ifname[0] == '\0' && wpas_mesh_get_ifname(wpa_s, ifname, len) < 0) 622 return -1; 623 624 if (wpa_drv_if_add(wpa_s, WPA_IF_MESH, ifname, NULL, NULL, NULL, addr, 625 NULL) < 0) { 626 wpa_printf(MSG_ERROR, 627 "mesh: Failed to create new mesh interface"); 628 return -1; 629 } 630 wpa_printf(MSG_INFO, "mesh: Created virtual interface %s addr " 631 MACSTR, ifname, MAC2STR(addr)); 632 633 os_memset(&iface, 0, sizeof(iface)); 634 iface.ifname = ifname; 635 iface.driver = wpa_s->driver->name; 636 iface.driver_param = wpa_s->conf->driver_param; 637 iface.ctrl_interface = wpa_s->conf->ctrl_interface; 638 639 mesh_wpa_s = wpa_supplicant_add_iface(wpa_s->global, &iface, wpa_s); 640 if (!mesh_wpa_s) { 641 wpa_printf(MSG_ERROR, 642 "mesh: Failed to create new wpa_supplicant interface"); 643 wpa_drv_if_remove(wpa_s, WPA_IF_MESH, ifname); 644 return -1; 645 } 646 mesh_wpa_s->mesh_if_created = 1; 647 return 0; 648 } 649 650 651 int wpas_mesh_peer_remove(struct wpa_supplicant *wpa_s, const u8 *addr) 652 { 653 return mesh_mpm_close_peer(wpa_s, addr); 654 } 655 656 657 int wpas_mesh_peer_add(struct wpa_supplicant *wpa_s, const u8 *addr, 658 int duration) 659 { 660 return mesh_mpm_connect_peer(wpa_s, addr, duration); 661 } 662