1 1.1 christos /* 2 1.1 christos * WPA Supplicant - Basic mesh peer management 3 1.1 christos * Copyright (c) 2013-2014, cozybit, Inc. All rights reserved. 4 1.1 christos * 5 1.1 christos * This software may be distributed under the terms of the BSD license. 6 1.1 christos * See README for more details. 7 1.1 christos */ 8 1.1 christos 9 1.1 christos #include "utils/includes.h" 10 1.1 christos 11 1.1 christos #include "utils/common.h" 12 1.1 christos #include "utils/eloop.h" 13 1.1 christos #include "common/ieee802_11_defs.h" 14 1.1.1.3 christos #include "common/hw_features_common.h" 15 1.1.1.4 christos #include "common/ocv.h" 16 1.1 christos #include "ap/hostapd.h" 17 1.1 christos #include "ap/sta_info.h" 18 1.1 christos #include "ap/ieee802_11.h" 19 1.1.1.5 christos #include "ap/beacon.h" 20 1.1.1.2 christos #include "ap/wpa_auth.h" 21 1.1 christos #include "wpa_supplicant_i.h" 22 1.1 christos #include "driver_i.h" 23 1.1 christos #include "mesh_mpm.h" 24 1.1 christos #include "mesh_rsn.h" 25 1.1.1.3 christos #include "notify.h" 26 1.1 christos 27 1.1 christos struct mesh_peer_mgmt_ie { 28 1.1.1.2 christos const u8 *proto_id; /* Mesh Peering Protocol Identifier (2 octets) */ 29 1.1.1.2 christos const u8 *llid; /* Local Link ID (2 octets) */ 30 1.1.1.2 christos const u8 *plid; /* Peer Link ID (conditional, 2 octets) */ 31 1.1.1.2 christos const u8 *reason; /* Reason Code (conditional, 2 octets) */ 32 1.1.1.2 christos const u8 *chosen_pmk; /* Chosen PMK (optional, 16 octets) */ 33 1.1 christos }; 34 1.1 christos 35 1.1 christos static void plink_timer(void *eloop_ctx, void *user_data); 36 1.1 christos 37 1.1 christos 38 1.1 christos enum plink_event { 39 1.1 christos PLINK_UNDEFINED, 40 1.1 christos OPN_ACPT, 41 1.1 christos OPN_RJCT, 42 1.1 christos CNF_ACPT, 43 1.1 christos CNF_RJCT, 44 1.1 christos CLS_ACPT, 45 1.1.1.2 christos REQ_RJCT 46 1.1 christos }; 47 1.1 christos 48 1.1 christos static const char * const mplstate[] = { 49 1.1.1.2 christos [0] = "UNINITIALIZED", 50 1.1.1.2 christos [PLINK_IDLE] = "IDLE", 51 1.1.1.2 christos [PLINK_OPN_SNT] = "OPN_SNT", 52 1.1.1.2 christos [PLINK_OPN_RCVD] = "OPN_RCVD", 53 1.1 christos [PLINK_CNF_RCVD] = "CNF_RCVD", 54 1.1 christos [PLINK_ESTAB] = "ESTAB", 55 1.1 christos [PLINK_HOLDING] = "HOLDING", 56 1.1 christos [PLINK_BLOCKED] = "BLOCKED" 57 1.1 christos }; 58 1.1 christos 59 1.1 christos static const char * const mplevent[] = { 60 1.1 christos [PLINK_UNDEFINED] = "UNDEFINED", 61 1.1 christos [OPN_ACPT] = "OPN_ACPT", 62 1.1 christos [OPN_RJCT] = "OPN_RJCT", 63 1.1 christos [CNF_ACPT] = "CNF_ACPT", 64 1.1 christos [CNF_RJCT] = "CNF_RJCT", 65 1.1 christos [CLS_ACPT] = "CLS_ACPT", 66 1.1.1.2 christos [REQ_RJCT] = "REQ_RJCT", 67 1.1 christos }; 68 1.1 christos 69 1.1 christos 70 1.1 christos static int mesh_mpm_parse_peer_mgmt(struct wpa_supplicant *wpa_s, 71 1.1 christos u8 action_field, 72 1.1 christos const u8 *ie, size_t len, 73 1.1 christos struct mesh_peer_mgmt_ie *mpm_ie) 74 1.1 christos { 75 1.1 christos os_memset(mpm_ie, 0, sizeof(*mpm_ie)); 76 1.1 christos 77 1.1.1.2 christos /* Remove optional Chosen PMK field at end */ 78 1.1.1.2 christos if (len >= SAE_PMKID_LEN) { 79 1.1.1.2 christos mpm_ie->chosen_pmk = ie + len - SAE_PMKID_LEN; 80 1.1.1.2 christos len -= SAE_PMKID_LEN; 81 1.1 christos } 82 1.1 christos 83 1.1 christos if ((action_field == PLINK_OPEN && len != 4) || 84 1.1 christos (action_field == PLINK_CONFIRM && len != 6) || 85 1.1 christos (action_field == PLINK_CLOSE && len != 6 && len != 8)) { 86 1.1 christos wpa_msg(wpa_s, MSG_DEBUG, "MPM: Invalid peer mgmt ie"); 87 1.1 christos return -1; 88 1.1 christos } 89 1.1 christos 90 1.1 christos /* required fields */ 91 1.1 christos if (len < 4) 92 1.1 christos return -1; 93 1.1 christos mpm_ie->proto_id = ie; 94 1.1 christos mpm_ie->llid = ie + 2; 95 1.1 christos ie += 4; 96 1.1 christos len -= 4; 97 1.1 christos 98 1.1 christos /* close reason is always present at end for close */ 99 1.1 christos if (action_field == PLINK_CLOSE) { 100 1.1 christos if (len < 2) 101 1.1 christos return -1; 102 1.1 christos mpm_ie->reason = ie + len - 2; 103 1.1 christos len -= 2; 104 1.1 christos } 105 1.1 christos 106 1.1.1.2 christos /* Peer Link ID, present for confirm, and possibly close */ 107 1.1.1.2 christos if (len >= 2) 108 1.1 christos mpm_ie->plid = ie; 109 1.1 christos 110 1.1 christos return 0; 111 1.1 christos } 112 1.1 christos 113 1.1 christos 114 1.1 christos static int plink_free_count(struct hostapd_data *hapd) 115 1.1 christos { 116 1.1 christos if (hapd->max_plinks > hapd->num_plinks) 117 1.1 christos return hapd->max_plinks - hapd->num_plinks; 118 1.1 christos return 0; 119 1.1 christos } 120 1.1 christos 121 1.1 christos 122 1.1 christos static u16 copy_supp_rates(struct wpa_supplicant *wpa_s, 123 1.1 christos struct sta_info *sta, 124 1.1 christos struct ieee802_11_elems *elems) 125 1.1 christos { 126 1.1 christos if (!elems->supp_rates) { 127 1.1 christos wpa_msg(wpa_s, MSG_ERROR, "no supported rates from " MACSTR, 128 1.1 christos MAC2STR(sta->addr)); 129 1.1 christos return WLAN_STATUS_UNSPECIFIED_FAILURE; 130 1.1 christos } 131 1.1 christos 132 1.1 christos if (elems->supp_rates_len + elems->ext_supp_rates_len > 133 1.1 christos sizeof(sta->supported_rates)) { 134 1.1 christos wpa_msg(wpa_s, MSG_ERROR, 135 1.1 christos "Invalid supported rates element length " MACSTR 136 1.1 christos " %d+%d", MAC2STR(sta->addr), elems->supp_rates_len, 137 1.1 christos elems->ext_supp_rates_len); 138 1.1 christos return WLAN_STATUS_UNSPECIFIED_FAILURE; 139 1.1 christos } 140 1.1 christos 141 1.1 christos sta->supported_rates_len = merge_byte_arrays( 142 1.1 christos sta->supported_rates, sizeof(sta->supported_rates), 143 1.1 christos elems->supp_rates, elems->supp_rates_len, 144 1.1 christos elems->ext_supp_rates, elems->ext_supp_rates_len); 145 1.1 christos 146 1.1 christos return WLAN_STATUS_SUCCESS; 147 1.1 christos } 148 1.1 christos 149 1.1 christos 150 1.1 christos /* return true if elems from a neighbor match this MBSS */ 151 1.1.1.5 christos static bool matches_local(struct wpa_supplicant *wpa_s, 152 1.1.1.5 christos struct ieee802_11_elems *elems) 153 1.1 christos { 154 1.1 christos struct mesh_conf *mconf = wpa_s->ifmsh->mconf; 155 1.1 christos 156 1.1 christos if (elems->mesh_config_len < 5) 157 1.1.1.5 christos return false; 158 1.1 christos 159 1.1 christos return (mconf->meshid_len == elems->mesh_id_len && 160 1.1 christos os_memcmp(mconf->meshid, elems->mesh_id, 161 1.1 christos elems->mesh_id_len) == 0 && 162 1.1 christos mconf->mesh_pp_id == elems->mesh_config[0] && 163 1.1 christos mconf->mesh_pm_id == elems->mesh_config[1] && 164 1.1 christos mconf->mesh_cc_id == elems->mesh_config[2] && 165 1.1 christos mconf->mesh_sp_id == elems->mesh_config[3] && 166 1.1 christos mconf->mesh_auth_id == elems->mesh_config[4]); 167 1.1 christos } 168 1.1 christos 169 1.1 christos 170 1.1 christos /* check if local link id is already used with another peer */ 171 1.1.1.5 christos static bool llid_in_use(struct wpa_supplicant *wpa_s, u16 llid) 172 1.1 christos { 173 1.1 christos struct sta_info *sta; 174 1.1 christos struct hostapd_data *hapd = wpa_s->ifmsh->bss[0]; 175 1.1 christos 176 1.1 christos for (sta = hapd->sta_list; sta; sta = sta->next) { 177 1.1 christos if (sta->my_lid == llid) 178 1.1.1.5 christos return true; 179 1.1 christos } 180 1.1 christos 181 1.1.1.5 christos return false; 182 1.1 christos } 183 1.1 christos 184 1.1 christos 185 1.1 christos /* generate an llid for a link and set to initial state */ 186 1.1 christos static void mesh_mpm_init_link(struct wpa_supplicant *wpa_s, 187 1.1 christos struct sta_info *sta) 188 1.1 christos { 189 1.1 christos u16 llid; 190 1.1 christos 191 1.1 christos do { 192 1.1 christos if (os_get_random((u8 *) &llid, sizeof(llid)) < 0) 193 1.1.1.4 christos llid = 0; /* continue */ 194 1.1 christos } while (!llid || llid_in_use(wpa_s, llid)); 195 1.1 christos 196 1.1 christos sta->my_lid = llid; 197 1.1 christos sta->peer_lid = 0; 198 1.1.1.2 christos sta->peer_aid = 0; 199 1.1 christos 200 1.1 christos /* 201 1.1 christos * We do not use wpa_mesh_set_plink_state() here because there is no 202 1.1 christos * entry in kernel yet. 203 1.1 christos */ 204 1.1.1.2 christos sta->plink_state = PLINK_IDLE; 205 1.1 christos } 206 1.1 christos 207 1.1 christos 208 1.1 christos static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s, 209 1.1 christos struct sta_info *sta, 210 1.1 christos enum plink_action_field type, 211 1.1 christos u16 close_reason) 212 1.1 christos { 213 1.1 christos struct wpabuf *buf; 214 1.1 christos struct hostapd_iface *ifmsh = wpa_s->ifmsh; 215 1.1 christos struct hostapd_data *bss = ifmsh->bss[0]; 216 1.1 christos struct mesh_conf *conf = ifmsh->mconf; 217 1.1 christos u8 supp_rates[2 + 2 + 32]; 218 1.1 christos u8 *pos, *cat; 219 1.1 christos u8 ie_len, add_plid = 0; 220 1.1 christos int ret; 221 1.1 christos int ampe = conf->security & MESH_CONF_SEC_AMPE; 222 1.1 christos size_t buf_len; 223 1.1 christos 224 1.1 christos if (!sta) 225 1.1 christos return; 226 1.1 christos 227 1.1.1.3 christos buf_len = 2 + /* Category and Action */ 228 1.1.1.3 christos 2 + /* capability info */ 229 1.1 christos 2 + /* AID */ 230 1.1 christos 2 + 8 + /* supported rates */ 231 1.1 christos 2 + (32 - 8) + 232 1.1 christos 2 + 32 + /* mesh ID */ 233 1.1 christos 2 + 7 + /* mesh config */ 234 1.1.1.3 christos 2 + 24 + /* peering management */ 235 1.1.1.5 christos 2 + 96 + 32 + 32 + /* AMPE (96 + max GTKlen + max IGTKlen) */ 236 1.1 christos 2 + 16; /* MIC */ 237 1.1 christos if (type != PLINK_CLOSE && wpa_s->mesh_ht_enabled) { 238 1.1 christos buf_len += 2 + 26 + /* HT capabilities */ 239 1.1 christos 2 + 22; /* HT operation */ 240 1.1 christos } 241 1.1.1.2 christos #ifdef CONFIG_IEEE80211AC 242 1.1.1.2 christos if (type != PLINK_CLOSE && wpa_s->mesh_vht_enabled) { 243 1.1.1.2 christos buf_len += 2 + 12 + /* VHT Capabilities */ 244 1.1.1.2 christos 2 + 5; /* VHT Operation */ 245 1.1.1.2 christos } 246 1.1.1.2 christos #endif /* CONFIG_IEEE80211AC */ 247 1.1.1.4 christos #ifdef CONFIG_IEEE80211AX 248 1.1.1.4 christos if (type != PLINK_CLOSE && wpa_s->mesh_he_enabled) { 249 1.1.1.4 christos buf_len += 3 + 250 1.1.1.4 christos HE_MAX_MAC_CAPAB_SIZE + 251 1.1.1.4 christos HE_MAX_PHY_CAPAB_SIZE + 252 1.1.1.4 christos HE_MAX_MCS_CAPAB_SIZE + 253 1.1.1.4 christos HE_MAX_PPET_CAPAB_SIZE; 254 1.1.1.4 christos buf_len += 3 + sizeof(struct ieee80211_he_operation); 255 1.1.1.5 christos if (is_6ghz_op_class(bss->iconf->op_class)) 256 1.1.1.5 christos buf_len += sizeof(struct ieee80211_he_6ghz_oper_info) + 257 1.1.1.5 christos 3 + sizeof(struct ieee80211_he_6ghz_band_cap); 258 1.1.1.4 christos } 259 1.1.1.4 christos #endif /* CONFIG_IEEE80211AX */ 260 1.1.1.2 christos if (type != PLINK_CLOSE) 261 1.1.1.2 christos buf_len += conf->rsn_ie_len; /* RSN IE */ 262 1.1.1.4 christos #ifdef CONFIG_OCV 263 1.1.1.4 christos /* OCI is included even when the other STA doesn't support OCV */ 264 1.1.1.4 christos if (type != PLINK_CLOSE && conf->ocv) 265 1.1.1.4 christos buf_len += OCV_OCI_EXTENDED_LEN; 266 1.1.1.4 christos #endif /* CONFIG_OCV */ 267 1.1.1.5 christos #ifdef CONFIG_IEEE80211BE 268 1.1.1.5 christos if (type != PLINK_CLOSE && wpa_s->mesh_eht_enabled) { 269 1.1.1.5 christos buf_len += 3 + 2 + EHT_PHY_CAPAB_LEN + EHT_MCS_NSS_CAPAB_LEN + 270 1.1.1.5 christos EHT_PPE_THRESH_CAPAB_LEN; 271 1.1.1.5 christos buf_len += 3 + sizeof(struct ieee80211_eht_operation); 272 1.1.1.5 christos } 273 1.1.1.5 christos #endif /* CONFIG_IEEE80211BE */ 274 1.1.1.2 christos 275 1.1 christos buf = wpabuf_alloc(buf_len); 276 1.1 christos if (!buf) 277 1.1 christos return; 278 1.1 christos 279 1.1 christos cat = wpabuf_mhead_u8(buf); 280 1.1 christos wpabuf_put_u8(buf, WLAN_ACTION_SELF_PROTECTED); 281 1.1 christos wpabuf_put_u8(buf, type); 282 1.1 christos 283 1.1 christos if (type != PLINK_CLOSE) { 284 1.1 christos u8 info; 285 1.1 christos 286 1.1 christos /* capability info */ 287 1.1 christos wpabuf_put_le16(buf, ampe ? IEEE80211_CAP_PRIVACY : 0); 288 1.1 christos 289 1.1 christos /* aid */ 290 1.1 christos if (type == PLINK_CONFIRM) 291 1.1.1.2 christos wpabuf_put_le16(buf, sta->aid); 292 1.1 christos 293 1.1 christos /* IE: supp + ext. supp rates */ 294 1.1 christos pos = hostapd_eid_supp_rates(bss, supp_rates); 295 1.1 christos pos = hostapd_eid_ext_supp_rates(bss, pos); 296 1.1 christos wpabuf_put_data(buf, supp_rates, pos - supp_rates); 297 1.1 christos 298 1.1.1.2 christos /* IE: RSN IE */ 299 1.1.1.2 christos wpabuf_put_data(buf, conf->rsn_ie, conf->rsn_ie_len); 300 1.1.1.2 christos 301 1.1 christos /* IE: Mesh ID */ 302 1.1 christos wpabuf_put_u8(buf, WLAN_EID_MESH_ID); 303 1.1 christos wpabuf_put_u8(buf, conf->meshid_len); 304 1.1 christos wpabuf_put_data(buf, conf->meshid, conf->meshid_len); 305 1.1 christos 306 1.1 christos /* IE: mesh conf */ 307 1.1 christos wpabuf_put_u8(buf, WLAN_EID_MESH_CONFIG); 308 1.1 christos wpabuf_put_u8(buf, 7); 309 1.1 christos wpabuf_put_u8(buf, conf->mesh_pp_id); 310 1.1 christos wpabuf_put_u8(buf, conf->mesh_pm_id); 311 1.1 christos wpabuf_put_u8(buf, conf->mesh_cc_id); 312 1.1 christos wpabuf_put_u8(buf, conf->mesh_sp_id); 313 1.1 christos wpabuf_put_u8(buf, conf->mesh_auth_id); 314 1.1 christos info = (bss->num_plinks > 63 ? 63 : bss->num_plinks) << 1; 315 1.1 christos /* TODO: Add Connected to Mesh Gate/AS subfields */ 316 1.1 christos wpabuf_put_u8(buf, info); 317 1.1.1.5 christos /* Set forwarding based on configuration and always accept 318 1.1.1.5 christos * plinks for now */ 319 1.1.1.2 christos wpabuf_put_u8(buf, MESH_CAP_ACCEPT_ADDITIONAL_PEER | 320 1.1.1.5 christos (conf->mesh_fwding ? MESH_CAP_FORWARDING : 0)); 321 1.1 christos } else { /* Peer closing frame */ 322 1.1 christos /* IE: Mesh ID */ 323 1.1 christos wpabuf_put_u8(buf, WLAN_EID_MESH_ID); 324 1.1 christos wpabuf_put_u8(buf, conf->meshid_len); 325 1.1 christos wpabuf_put_data(buf, conf->meshid, conf->meshid_len); 326 1.1 christos } 327 1.1 christos 328 1.1 christos /* IE: Mesh Peering Management element */ 329 1.1 christos ie_len = 4; 330 1.1 christos if (ampe) 331 1.1 christos ie_len += PMKID_LEN; 332 1.1 christos switch (type) { 333 1.1 christos case PLINK_OPEN: 334 1.1 christos break; 335 1.1 christos case PLINK_CONFIRM: 336 1.1 christos ie_len += 2; 337 1.1 christos add_plid = 1; 338 1.1 christos break; 339 1.1 christos case PLINK_CLOSE: 340 1.1 christos ie_len += 2; 341 1.1 christos add_plid = 1; 342 1.1 christos ie_len += 2; /* reason code */ 343 1.1 christos break; 344 1.1 christos } 345 1.1 christos 346 1.1 christos wpabuf_put_u8(buf, WLAN_EID_PEER_MGMT); 347 1.1 christos wpabuf_put_u8(buf, ie_len); 348 1.1 christos /* peering protocol */ 349 1.1 christos if (ampe) 350 1.1 christos wpabuf_put_le16(buf, 1); 351 1.1 christos else 352 1.1 christos wpabuf_put_le16(buf, 0); 353 1.1 christos wpabuf_put_le16(buf, sta->my_lid); 354 1.1 christos if (add_plid) 355 1.1 christos wpabuf_put_le16(buf, sta->peer_lid); 356 1.1 christos if (type == PLINK_CLOSE) 357 1.1 christos wpabuf_put_le16(buf, close_reason); 358 1.1 christos if (ampe) { 359 1.1 christos if (sta->sae == NULL) { 360 1.1 christos wpa_msg(wpa_s, MSG_INFO, "Mesh MPM: no SAE session"); 361 1.1 christos goto fail; 362 1.1 christos } 363 1.1 christos mesh_rsn_get_pmkid(wpa_s->mesh_rsn, sta, 364 1.1 christos wpabuf_put(buf, PMKID_LEN)); 365 1.1 christos } 366 1.1 christos 367 1.1 christos if (type != PLINK_CLOSE && wpa_s->mesh_ht_enabled) { 368 1.1.1.2 christos u8 ht_capa_oper[2 + 26 + 2 + 22]; 369 1.1.1.2 christos 370 1.1 christos pos = hostapd_eid_ht_capabilities(bss, ht_capa_oper); 371 1.1 christos pos = hostapd_eid_ht_operation(bss, pos); 372 1.1 christos wpabuf_put_data(buf, ht_capa_oper, pos - ht_capa_oper); 373 1.1 christos } 374 1.1.1.2 christos #ifdef CONFIG_IEEE80211AC 375 1.1.1.2 christos if (type != PLINK_CLOSE && wpa_s->mesh_vht_enabled) { 376 1.1.1.2 christos u8 vht_capa_oper[2 + 12 + 2 + 5]; 377 1.1.1.2 christos 378 1.1.1.2 christos pos = hostapd_eid_vht_capabilities(bss, vht_capa_oper, 0); 379 1.1.1.2 christos pos = hostapd_eid_vht_operation(bss, pos); 380 1.1.1.2 christos wpabuf_put_data(buf, vht_capa_oper, pos - vht_capa_oper); 381 1.1.1.2 christos } 382 1.1.1.2 christos #endif /* CONFIG_IEEE80211AC */ 383 1.1.1.4 christos #ifdef CONFIG_IEEE80211AX 384 1.1.1.4 christos if (type != PLINK_CLOSE && wpa_s->mesh_he_enabled) { 385 1.1.1.4 christos u8 he_capa_oper[3 + 386 1.1.1.4 christos HE_MAX_MAC_CAPAB_SIZE + 387 1.1.1.4 christos HE_MAX_PHY_CAPAB_SIZE + 388 1.1.1.4 christos HE_MAX_MCS_CAPAB_SIZE + 389 1.1.1.4 christos HE_MAX_PPET_CAPAB_SIZE + 390 1.1.1.5 christos 3 + sizeof(struct ieee80211_he_operation) + 391 1.1.1.5 christos sizeof(struct ieee80211_he_6ghz_oper_info) + 392 1.1.1.5 christos 3 + sizeof(struct ieee80211_he_6ghz_band_cap)]; 393 1.1.1.4 christos 394 1.1.1.4 christos pos = hostapd_eid_he_capab(bss, he_capa_oper, 395 1.1.1.4 christos IEEE80211_MODE_MESH); 396 1.1.1.4 christos pos = hostapd_eid_he_operation(bss, pos); 397 1.1.1.5 christos pos = hostapd_eid_he_6ghz_band_cap(bss, pos); 398 1.1.1.4 christos wpabuf_put_data(buf, he_capa_oper, pos - he_capa_oper); 399 1.1.1.4 christos } 400 1.1.1.4 christos #endif /* CONFIG_IEEE80211AX */ 401 1.1.1.4 christos #ifdef CONFIG_OCV 402 1.1.1.4 christos if (type != PLINK_CLOSE && conf->ocv) { 403 1.1.1.4 christos struct wpa_channel_info ci; 404 1.1.1.4 christos 405 1.1.1.4 christos if (wpa_drv_channel_info(wpa_s, &ci) != 0) { 406 1.1.1.4 christos wpa_printf(MSG_WARNING, 407 1.1.1.4 christos "Mesh MPM: Failed to get channel info for OCI element"); 408 1.1.1.4 christos goto fail; 409 1.1.1.4 christos } 410 1.1.1.4 christos 411 1.1.1.4 christos pos = wpabuf_put(buf, OCV_OCI_EXTENDED_LEN); 412 1.1.1.4 christos if (ocv_insert_extended_oci(&ci, pos) < 0) 413 1.1.1.4 christos goto fail; 414 1.1.1.4 christos } 415 1.1.1.4 christos #endif /* CONFIG_OCV */ 416 1.1 christos 417 1.1.1.5 christos #ifdef CONFIG_IEEE80211BE 418 1.1.1.5 christos if (type != PLINK_CLOSE && wpa_s->mesh_eht_enabled) { 419 1.1.1.5 christos u8 eht_capa_oper[3 + 420 1.1.1.5 christos 2 + 421 1.1.1.5 christos EHT_PHY_CAPAB_LEN + 422 1.1.1.5 christos EHT_MCS_NSS_CAPAB_LEN + 423 1.1.1.5 christos EHT_PPE_THRESH_CAPAB_LEN + 424 1.1.1.5 christos 3 + sizeof(struct ieee80211_eht_operation)]; 425 1.1.1.5 christos pos = hostapd_eid_eht_capab(bss, eht_capa_oper, 426 1.1.1.5 christos IEEE80211_MODE_MESH); 427 1.1.1.5 christos pos = hostapd_eid_eht_operation(bss, pos); 428 1.1.1.5 christos wpabuf_put_data(buf, eht_capa_oper, pos - eht_capa_oper); 429 1.1.1.5 christos } 430 1.1.1.5 christos #endif /* CONFIG_IEEE80211BE */ 431 1.1.1.5 christos 432 1.1 christos if (ampe && mesh_rsn_protect_frame(wpa_s->mesh_rsn, sta, cat, buf)) { 433 1.1 christos wpa_msg(wpa_s, MSG_INFO, 434 1.1 christos "Mesh MPM: failed to add AMPE and MIC IE"); 435 1.1 christos goto fail; 436 1.1 christos } 437 1.1 christos 438 1.1.1.2 christos wpa_msg(wpa_s, MSG_DEBUG, "Mesh MPM: Sending peering frame type %d to " 439 1.1.1.2 christos MACSTR " (my_lid=0x%x peer_lid=0x%x)", 440 1.1.1.2 christos type, MAC2STR(sta->addr), sta->my_lid, sta->peer_lid); 441 1.1 christos ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, 442 1.1 christos sta->addr, wpa_s->own_addr, wpa_s->own_addr, 443 1.1 christos wpabuf_head(buf), wpabuf_len(buf), 0); 444 1.1 christos if (ret < 0) 445 1.1 christos wpa_msg(wpa_s, MSG_INFO, 446 1.1 christos "Mesh MPM: failed to send peering frame"); 447 1.1 christos 448 1.1 christos fail: 449 1.1 christos wpabuf_free(buf); 450 1.1 christos } 451 1.1 christos 452 1.1 christos 453 1.1 christos /* configure peering state in ours and driver's station entry */ 454 1.1 christos void wpa_mesh_set_plink_state(struct wpa_supplicant *wpa_s, 455 1.1 christos struct sta_info *sta, 456 1.1 christos enum mesh_plink_state state) 457 1.1 christos { 458 1.1 christos struct hostapd_sta_add_params params; 459 1.1 christos int ret; 460 1.1 christos 461 1.1.1.2 christos wpa_msg(wpa_s, MSG_DEBUG, "MPM set " MACSTR " from %s into %s", 462 1.1.1.2 christos MAC2STR(sta->addr), mplstate[sta->plink_state], 463 1.1.1.2 christos mplstate[state]); 464 1.1 christos sta->plink_state = state; 465 1.1 christos 466 1.1 christos os_memset(¶ms, 0, sizeof(params)); 467 1.1 christos params.addr = sta->addr; 468 1.1 christos params.plink_state = state; 469 1.1.1.2 christos params.peer_aid = sta->peer_aid; 470 1.1 christos params.set = 1; 471 1.1.1.5 christos params.mld_link_id = -1; 472 1.1 christos 473 1.1 christos ret = wpa_drv_sta_add(wpa_s, ¶ms); 474 1.1 christos if (ret) { 475 1.1 christos wpa_msg(wpa_s, MSG_ERROR, "Driver failed to set " MACSTR 476 1.1 christos ": %d", MAC2STR(sta->addr), ret); 477 1.1 christos } 478 1.1 christos } 479 1.1 christos 480 1.1 christos 481 1.1 christos static void mesh_mpm_fsm_restart(struct wpa_supplicant *wpa_s, 482 1.1 christos struct sta_info *sta) 483 1.1 christos { 484 1.1 christos struct hostapd_data *hapd = wpa_s->ifmsh->bss[0]; 485 1.1 christos 486 1.1 christos eloop_cancel_timeout(plink_timer, wpa_s, sta); 487 1.1 christos 488 1.1 christos ap_free_sta(hapd, sta); 489 1.1 christos } 490 1.1 christos 491 1.1 christos 492 1.1 christos static void plink_timer(void *eloop_ctx, void *user_data) 493 1.1 christos { 494 1.1 christos struct wpa_supplicant *wpa_s = eloop_ctx; 495 1.1 christos struct sta_info *sta = user_data; 496 1.1 christos u16 reason = 0; 497 1.1 christos struct mesh_conf *conf = wpa_s->ifmsh->mconf; 498 1.1.1.2 christos struct hostapd_data *hapd = wpa_s->ifmsh->bss[0]; 499 1.1 christos 500 1.1 christos switch (sta->plink_state) { 501 1.1.1.2 christos case PLINK_OPN_RCVD: 502 1.1.1.2 christos case PLINK_OPN_SNT: 503 1.1 christos /* retry timer */ 504 1.1 christos if (sta->mpm_retries < conf->dot11MeshMaxRetries) { 505 1.1 christos eloop_register_timeout( 506 1.1 christos conf->dot11MeshRetryTimeout / 1000, 507 1.1 christos (conf->dot11MeshRetryTimeout % 1000) * 1000, 508 1.1 christos plink_timer, wpa_s, sta); 509 1.1 christos mesh_mpm_send_plink_action(wpa_s, sta, PLINK_OPEN, 0); 510 1.1 christos sta->mpm_retries++; 511 1.1 christos break; 512 1.1 christos } 513 1.1 christos reason = WLAN_REASON_MESH_MAX_RETRIES; 514 1.1.1.3 christos /* fall through */ 515 1.1 christos 516 1.1 christos case PLINK_CNF_RCVD: 517 1.1 christos /* confirm timer */ 518 1.1 christos if (!reason) 519 1.1 christos reason = WLAN_REASON_MESH_CONFIRM_TIMEOUT; 520 1.1 christos wpa_mesh_set_plink_state(wpa_s, sta, PLINK_HOLDING); 521 1.1 christos eloop_register_timeout(conf->dot11MeshHoldingTimeout / 1000, 522 1.1 christos (conf->dot11MeshHoldingTimeout % 1000) * 1000, 523 1.1 christos plink_timer, wpa_s, sta); 524 1.1 christos mesh_mpm_send_plink_action(wpa_s, sta, PLINK_CLOSE, reason); 525 1.1 christos break; 526 1.1 christos case PLINK_HOLDING: 527 1.1 christos /* holding timer */ 528 1.1.1.2 christos 529 1.1.1.2 christos if (sta->mesh_sae_pmksa_caching) { 530 1.1.1.2 christos wpa_printf(MSG_DEBUG, "MPM: Peer " MACSTR 531 1.1.1.2 christos " looks like it does not support mesh SAE PMKSA caching, so remove the cached entry for it", 532 1.1.1.2 christos MAC2STR(sta->addr)); 533 1.1.1.2 christos wpa_auth_pmksa_remove(hapd->wpa_auth, sta->addr); 534 1.1.1.2 christos } 535 1.1 christos mesh_mpm_fsm_restart(wpa_s, sta); 536 1.1 christos break; 537 1.1 christos default: 538 1.1 christos break; 539 1.1 christos } 540 1.1 christos } 541 1.1 christos 542 1.1 christos 543 1.1 christos /* initiate peering with station */ 544 1.1 christos static void 545 1.1 christos mesh_mpm_plink_open(struct wpa_supplicant *wpa_s, struct sta_info *sta, 546 1.1 christos enum mesh_plink_state next_state) 547 1.1 christos { 548 1.1 christos struct mesh_conf *conf = wpa_s->ifmsh->mconf; 549 1.1 christos 550 1.1 christos eloop_cancel_timeout(plink_timer, wpa_s, sta); 551 1.1 christos eloop_register_timeout(conf->dot11MeshRetryTimeout / 1000, 552 1.1 christos (conf->dot11MeshRetryTimeout % 1000) * 1000, 553 1.1 christos plink_timer, wpa_s, sta); 554 1.1 christos mesh_mpm_send_plink_action(wpa_s, sta, PLINK_OPEN, 0); 555 1.1 christos wpa_mesh_set_plink_state(wpa_s, sta, next_state); 556 1.1 christos } 557 1.1 christos 558 1.1 christos 559 1.1.1.2 christos static int mesh_mpm_plink_close(struct hostapd_data *hapd, struct sta_info *sta, 560 1.1.1.2 christos void *ctx) 561 1.1 christos { 562 1.1 christos struct wpa_supplicant *wpa_s = ctx; 563 1.1 christos int reason = WLAN_REASON_MESH_PEERING_CANCELLED; 564 1.1 christos 565 1.1 christos if (sta) { 566 1.1.1.5 christos if (sta->plink_state == PLINK_ESTAB) { 567 1.1.1.5 christos hapd->num_plinks--; 568 1.1.1.5 christos wpas_notify_mesh_peer_disconnected( 569 1.1.1.5 christos wpa_s, sta->addr, WLAN_REASON_UNSPECIFIED); 570 1.1.1.5 christos } 571 1.1 christos wpa_mesh_set_plink_state(wpa_s, sta, PLINK_HOLDING); 572 1.1 christos mesh_mpm_send_plink_action(wpa_s, sta, PLINK_CLOSE, reason); 573 1.1 christos wpa_printf(MSG_DEBUG, "MPM closing plink sta=" MACSTR, 574 1.1 christos MAC2STR(sta->addr)); 575 1.1 christos eloop_cancel_timeout(plink_timer, wpa_s, sta); 576 1.1.1.5 christos eloop_cancel_timeout(mesh_auth_timer, wpa_s, sta); 577 1.1 christos return 0; 578 1.1 christos } 579 1.1 christos 580 1.1 christos return 1; 581 1.1 christos } 582 1.1 christos 583 1.1 christos 584 1.1.1.2 christos int mesh_mpm_close_peer(struct wpa_supplicant *wpa_s, const u8 *addr) 585 1.1.1.2 christos { 586 1.1.1.2 christos struct hostapd_data *hapd; 587 1.1.1.2 christos struct sta_info *sta; 588 1.1.1.2 christos 589 1.1.1.2 christos if (!wpa_s->ifmsh) { 590 1.1.1.2 christos wpa_msg(wpa_s, MSG_INFO, "Mesh is not prepared yet"); 591 1.1.1.2 christos return -1; 592 1.1.1.2 christos } 593 1.1.1.2 christos 594 1.1.1.2 christos hapd = wpa_s->ifmsh->bss[0]; 595 1.1.1.2 christos sta = ap_get_sta(hapd, addr); 596 1.1.1.2 christos if (!sta) { 597 1.1.1.2 christos wpa_msg(wpa_s, MSG_INFO, "No such mesh peer"); 598 1.1.1.2 christos return -1; 599 1.1.1.2 christos } 600 1.1.1.2 christos 601 1.1.1.2 christos return mesh_mpm_plink_close(hapd, sta, wpa_s) == 0 ? 0 : -1; 602 1.1.1.2 christos } 603 1.1.1.2 christos 604 1.1.1.2 christos 605 1.1.1.2 christos static void peer_add_timer(void *eloop_ctx, void *user_data) 606 1.1.1.2 christos { 607 1.1.1.2 christos struct wpa_supplicant *wpa_s = eloop_ctx; 608 1.1.1.2 christos struct hostapd_data *hapd = wpa_s->ifmsh->bss[0]; 609 1.1.1.2 christos 610 1.1.1.2 christos os_memset(hapd->mesh_required_peer, 0, ETH_ALEN); 611 1.1.1.2 christos } 612 1.1.1.2 christos 613 1.1.1.2 christos 614 1.1.1.2 christos int mesh_mpm_connect_peer(struct wpa_supplicant *wpa_s, const u8 *addr, 615 1.1.1.2 christos int duration) 616 1.1.1.2 christos { 617 1.1.1.2 christos struct wpa_ssid *ssid = wpa_s->current_ssid; 618 1.1.1.2 christos struct hostapd_data *hapd; 619 1.1.1.2 christos struct sta_info *sta; 620 1.1.1.2 christos struct mesh_conf *conf; 621 1.1.1.2 christos 622 1.1.1.2 christos if (!wpa_s->ifmsh) { 623 1.1.1.2 christos wpa_msg(wpa_s, MSG_INFO, "Mesh is not prepared yet"); 624 1.1.1.2 christos return -1; 625 1.1.1.2 christos } 626 1.1.1.2 christos 627 1.1.1.2 christos if (!ssid || !ssid->no_auto_peer) { 628 1.1.1.2 christos wpa_msg(wpa_s, MSG_INFO, 629 1.1.1.2 christos "This command is available only with no_auto_peer mesh network"); 630 1.1.1.2 christos return -1; 631 1.1.1.2 christos } 632 1.1.1.2 christos 633 1.1.1.2 christos hapd = wpa_s->ifmsh->bss[0]; 634 1.1.1.2 christos conf = wpa_s->ifmsh->mconf; 635 1.1.1.2 christos 636 1.1.1.2 christos sta = ap_get_sta(hapd, addr); 637 1.1.1.2 christos if (!sta) { 638 1.1.1.2 christos wpa_msg(wpa_s, MSG_INFO, "No such mesh peer"); 639 1.1.1.2 christos return -1; 640 1.1.1.2 christos } 641 1.1.1.2 christos 642 1.1.1.2 christos if ((PLINK_OPN_SNT <= sta->plink_state && 643 1.1.1.2 christos sta->plink_state <= PLINK_ESTAB) || 644 1.1.1.2 christos (sta->sae && sta->sae->state > SAE_NOTHING)) { 645 1.1.1.2 christos wpa_msg(wpa_s, MSG_INFO, 646 1.1.1.2 christos "Specified peer is connecting/connected"); 647 1.1.1.2 christos return -1; 648 1.1.1.2 christos } 649 1.1.1.2 christos 650 1.1.1.2 christos if (conf->security == MESH_CONF_SEC_NONE) { 651 1.1.1.2 christos mesh_mpm_plink_open(wpa_s, sta, PLINK_OPN_SNT); 652 1.1.1.2 christos } else { 653 1.1.1.2 christos mesh_rsn_auth_sae_sta(wpa_s, sta); 654 1.1.1.2 christos os_memcpy(hapd->mesh_required_peer, addr, ETH_ALEN); 655 1.1.1.2 christos eloop_register_timeout(duration == -1 ? 10 : duration, 0, 656 1.1.1.2 christos peer_add_timer, wpa_s, NULL); 657 1.1.1.2 christos } 658 1.1.1.2 christos 659 1.1.1.2 christos return 0; 660 1.1.1.2 christos } 661 1.1.1.2 christos 662 1.1.1.2 christos 663 1.1 christos void mesh_mpm_deinit(struct wpa_supplicant *wpa_s, struct hostapd_iface *ifmsh) 664 1.1 christos { 665 1.1 christos struct hostapd_data *hapd = ifmsh->bss[0]; 666 1.1 christos 667 1.1 christos /* notify peers we're leaving */ 668 1.1 christos ap_for_each_sta(hapd, mesh_mpm_plink_close, wpa_s); 669 1.1 christos 670 1.1 christos hapd->num_plinks = 0; 671 1.1 christos hostapd_free_stas(hapd); 672 1.1.1.2 christos eloop_cancel_timeout(peer_add_timer, wpa_s, NULL); 673 1.1 christos } 674 1.1 christos 675 1.1 christos 676 1.1 christos /* for mesh_rsn to indicate this peer has completed authentication, and we're 677 1.1 christos * ready to start AMPE */ 678 1.1 christos void mesh_mpm_auth_peer(struct wpa_supplicant *wpa_s, const u8 *addr) 679 1.1 christos { 680 1.1 christos struct hostapd_data *data = wpa_s->ifmsh->bss[0]; 681 1.1 christos struct hostapd_sta_add_params params; 682 1.1 christos struct sta_info *sta; 683 1.1 christos int ret; 684 1.1 christos 685 1.1 christos sta = ap_get_sta(data, addr); 686 1.1 christos if (!sta) { 687 1.1 christos wpa_msg(wpa_s, MSG_DEBUG, "no such mesh peer"); 688 1.1 christos return; 689 1.1 christos } 690 1.1 christos 691 1.1 christos /* TODO: Should do nothing if this STA is already authenticated, but 692 1.1 christos * the AP code already sets this flag. */ 693 1.1 christos sta->flags |= WLAN_STA_AUTH; 694 1.1 christos 695 1.1 christos mesh_rsn_init_ampe_sta(wpa_s, sta); 696 1.1 christos 697 1.1 christos os_memset(¶ms, 0, sizeof(params)); 698 1.1 christos params.addr = sta->addr; 699 1.1 christos params.flags = WPA_STA_AUTHENTICATED | WPA_STA_AUTHORIZED; 700 1.1 christos params.set = 1; 701 1.1.1.5 christos params.mld_link_id = -1; 702 1.1 christos 703 1.1 christos wpa_msg(wpa_s, MSG_DEBUG, "MPM authenticating " MACSTR, 704 1.1 christos MAC2STR(sta->addr)); 705 1.1 christos ret = wpa_drv_sta_add(wpa_s, ¶ms); 706 1.1 christos if (ret) { 707 1.1 christos wpa_msg(wpa_s, MSG_ERROR, 708 1.1 christos "Driver failed to set " MACSTR ": %d", 709 1.1 christos MAC2STR(sta->addr), ret); 710 1.1 christos } 711 1.1 christos 712 1.1 christos if (!sta->my_lid) 713 1.1 christos mesh_mpm_init_link(wpa_s, sta); 714 1.1 christos 715 1.1.1.2 christos mesh_mpm_plink_open(wpa_s, sta, PLINK_OPN_SNT); 716 1.1 christos } 717 1.1 christos 718 1.1 christos /* 719 1.1 christos * Initialize a sta_info structure for a peer and upload it into the driver 720 1.1 christos * in preparation for beginning authentication or peering. This is done when a 721 1.1 christos * Beacon (secure or open mesh) or a peering open frame (for open mesh) is 722 1.1 christos * received from the peer for the first time. 723 1.1 christos */ 724 1.1 christos static struct sta_info * mesh_mpm_add_peer(struct wpa_supplicant *wpa_s, 725 1.1 christos const u8 *addr, 726 1.1 christos struct ieee802_11_elems *elems) 727 1.1 christos { 728 1.1 christos struct hostapd_sta_add_params params; 729 1.1 christos struct mesh_conf *conf = wpa_s->ifmsh->mconf; 730 1.1 christos struct hostapd_data *data = wpa_s->ifmsh->bss[0]; 731 1.1 christos struct sta_info *sta; 732 1.1.1.3 christos struct ieee80211_ht_operation *oper; 733 1.1 christos int ret; 734 1.1 christos 735 1.1.1.2 christos if (elems->mesh_config_len >= 7 && 736 1.1.1.2 christos !(elems->mesh_config[6] & MESH_CAP_ACCEPT_ADDITIONAL_PEER)) { 737 1.1.1.2 christos wpa_msg(wpa_s, MSG_DEBUG, 738 1.1.1.2 christos "mesh: Ignore a crowded peer " MACSTR, 739 1.1.1.2 christos MAC2STR(addr)); 740 1.1.1.2 christos return NULL; 741 1.1.1.2 christos } 742 1.1.1.2 christos 743 1.1 christos sta = ap_get_sta(data, addr); 744 1.1.1.5 christos if (sta) 745 1.1.1.5 christos return NULL; 746 1.1.1.5 christos 747 1.1.1.5 christos sta = ap_sta_add(data, addr); 748 1.1.1.5 christos if (!sta) 749 1.1.1.5 christos return NULL; 750 1.1 christos 751 1.1.1.2 christos /* Set WMM by default since Mesh STAs are QoS STAs */ 752 1.1.1.2 christos sta->flags |= WLAN_STA_WMM; 753 1.1.1.2 christos 754 1.1 christos /* initialize sta */ 755 1.1 christos if (copy_supp_rates(wpa_s, sta, elems)) { 756 1.1 christos ap_free_sta(data, sta); 757 1.1 christos return NULL; 758 1.1 christos } 759 1.1 christos 760 1.1.1.2 christos if (!sta->my_lid) 761 1.1.1.2 christos mesh_mpm_init_link(wpa_s, sta); 762 1.1 christos 763 1.1.1.2 christos copy_sta_ht_capab(data, sta, elems->ht_capabilities); 764 1.1.1.3 christos 765 1.1.1.3 christos oper = (struct ieee80211_ht_operation *) elems->ht_operation; 766 1.1.1.3 christos if (oper && 767 1.1.1.3 christos !(oper->ht_param & HT_INFO_HT_PARAM_STA_CHNL_WIDTH) && 768 1.1.1.3 christos sta->ht_capabilities) { 769 1.1.1.3 christos wpa_msg(wpa_s, MSG_DEBUG, MACSTR 770 1.1.1.3 christos " does not support 40 MHz bandwidth", 771 1.1.1.3 christos MAC2STR(sta->addr)); 772 1.1.1.3 christos set_disable_ht40(sta->ht_capabilities, 1); 773 1.1.1.3 christos } 774 1.1.1.3 christos 775 1.1.1.5 christos if (update_ht_state(data, sta) > 0) 776 1.1.1.5 christos ieee802_11_update_beacons(data->iface); 777 1.1 christos 778 1.1.1.2 christos #ifdef CONFIG_IEEE80211AC 779 1.1.1.2 christos copy_sta_vht_capab(data, sta, elems->vht_capabilities); 780 1.1.1.4 christos copy_sta_vht_oper(data, sta, elems->vht_operation); 781 1.1.1.5 christos set_sta_vht_opmode(data, sta, elems->opmode_notif); 782 1.1.1.2 christos #endif /* CONFIG_IEEE80211AC */ 783 1.1.1.2 christos 784 1.1.1.4 christos #ifdef CONFIG_IEEE80211AX 785 1.1.1.4 christos copy_sta_he_capab(data, sta, IEEE80211_MODE_MESH, 786 1.1.1.4 christos elems->he_capabilities, elems->he_capabilities_len); 787 1.1.1.5 christos copy_sta_he_6ghz_capab(data, sta, elems->he_6ghz_band_cap); 788 1.1.1.4 christos #endif /* CONFIG_IEEE80211AX */ 789 1.1.1.5 christos #ifdef CONFIG_IEEE80211BE 790 1.1.1.5 christos copy_sta_eht_capab(data, sta, IEEE80211_MODE_MESH, 791 1.1.1.5 christos elems->he_capabilities, 792 1.1.1.5 christos elems->he_capabilities_len, 793 1.1.1.5 christos elems->eht_capabilities, 794 1.1.1.5 christos elems->eht_capabilities_len); 795 1.1.1.5 christos #endif /*CONFIG_IEEE80211BE */ 796 1.1.1.4 christos 797 1.1.1.2 christos if (hostapd_get_aid(data, sta) < 0) { 798 1.1.1.2 christos wpa_msg(wpa_s, MSG_ERROR, "No AIDs available"); 799 1.1.1.2 christos ap_free_sta(data, sta); 800 1.1.1.2 christos return NULL; 801 1.1.1.2 christos } 802 1.1.1.2 christos 803 1.1 christos /* insert into driver */ 804 1.1 christos os_memset(¶ms, 0, sizeof(params)); 805 1.1 christos params.supp_rates = sta->supported_rates; 806 1.1 christos params.supp_rates_len = sta->supported_rates_len; 807 1.1 christos params.addr = addr; 808 1.1 christos params.plink_state = sta->plink_state; 809 1.1.1.2 christos params.aid = sta->aid; 810 1.1.1.2 christos params.peer_aid = sta->peer_aid; 811 1.1 christos params.listen_interval = 100; 812 1.1 christos params.ht_capabilities = sta->ht_capabilities; 813 1.1.1.2 christos params.vht_capabilities = sta->vht_capabilities; 814 1.1.1.4 christos params.he_capab = sta->he_capab; 815 1.1.1.4 christos params.he_capab_len = sta->he_capab_len; 816 1.1.1.5 christos params.he_6ghz_capab = sta->he_6ghz_capab; 817 1.1.1.5 christos params.eht_capab = sta->eht_capab; 818 1.1.1.5 christos params.eht_capab_len = sta->eht_capab_len; 819 1.1 christos params.flags |= WPA_STA_WMM; 820 1.1 christos params.flags_mask |= WPA_STA_AUTHENTICATED; 821 1.1.1.5 christos params.mld_link_id = -1; 822 1.1 christos if (conf->security == MESH_CONF_SEC_NONE) { 823 1.1 christos params.flags |= WPA_STA_AUTHORIZED; 824 1.1 christos params.flags |= WPA_STA_AUTHENTICATED; 825 1.1 christos } else { 826 1.1 christos sta->flags |= WLAN_STA_MFP; 827 1.1 christos params.flags |= WPA_STA_MFP; 828 1.1 christos } 829 1.1 christos 830 1.1 christos ret = wpa_drv_sta_add(wpa_s, ¶ms); 831 1.1 christos if (ret) { 832 1.1 christos wpa_msg(wpa_s, MSG_ERROR, 833 1.1 christos "Driver failed to insert " MACSTR ": %d", 834 1.1 christos MAC2STR(addr), ret); 835 1.1 christos ap_free_sta(data, sta); 836 1.1 christos return NULL; 837 1.1 christos } 838 1.1 christos 839 1.1 christos return sta; 840 1.1 christos } 841 1.1 christos 842 1.1 christos 843 1.1 christos void wpa_mesh_new_mesh_peer(struct wpa_supplicant *wpa_s, const u8 *addr, 844 1.1 christos struct ieee802_11_elems *elems) 845 1.1 christos { 846 1.1 christos struct mesh_conf *conf = wpa_s->ifmsh->mconf; 847 1.1 christos struct hostapd_data *data = wpa_s->ifmsh->bss[0]; 848 1.1 christos struct sta_info *sta; 849 1.1 christos struct wpa_ssid *ssid = wpa_s->current_ssid; 850 1.1 christos 851 1.1 christos sta = mesh_mpm_add_peer(wpa_s, addr, elems); 852 1.1 christos if (!sta) 853 1.1 christos return; 854 1.1 christos 855 1.1.1.2 christos if (ssid && ssid->no_auto_peer && 856 1.1.1.2 christos (is_zero_ether_addr(data->mesh_required_peer) || 857 1.1.1.5 christos !ether_addr_equal(data->mesh_required_peer, addr))) { 858 1.1 christos wpa_msg(wpa_s, MSG_INFO, "will not initiate new peer link with " 859 1.1 christos MACSTR " because of no_auto_peer", MAC2STR(addr)); 860 1.1 christos if (data->mesh_pending_auth) { 861 1.1 christos struct os_reltime age; 862 1.1 christos const struct ieee80211_mgmt *mgmt; 863 1.1 christos struct hostapd_frame_info fi; 864 1.1 christos 865 1.1 christos mgmt = wpabuf_head(data->mesh_pending_auth); 866 1.1 christos os_reltime_age(&data->mesh_pending_auth_time, &age); 867 1.1 christos if (age.sec < 2 && 868 1.1.1.5 christos ether_addr_equal(mgmt->sa, addr)) { 869 1.1 christos wpa_printf(MSG_DEBUG, 870 1.1 christos "mesh: Process pending Authentication frame from %u.%06u seconds ago", 871 1.1 christos (unsigned int) age.sec, 872 1.1 christos (unsigned int) age.usec); 873 1.1 christos os_memset(&fi, 0, sizeof(fi)); 874 1.1 christos ieee802_11_mgmt( 875 1.1 christos data, 876 1.1 christos wpabuf_head(data->mesh_pending_auth), 877 1.1 christos wpabuf_len(data->mesh_pending_auth), 878 1.1 christos &fi); 879 1.1 christos } 880 1.1 christos wpabuf_free(data->mesh_pending_auth); 881 1.1 christos data->mesh_pending_auth = NULL; 882 1.1 christos } 883 1.1 christos return; 884 1.1 christos } 885 1.1 christos 886 1.1.1.2 christos if (conf->security == MESH_CONF_SEC_NONE) { 887 1.1.1.2 christos if (sta->plink_state < PLINK_OPN_SNT || 888 1.1.1.2 christos sta->plink_state > PLINK_ESTAB) 889 1.1.1.2 christos mesh_mpm_plink_open(wpa_s, sta, PLINK_OPN_SNT); 890 1.1.1.2 christos } else { 891 1.1 christos mesh_rsn_auth_sae_sta(wpa_s, sta); 892 1.1.1.2 christos } 893 1.1 christos } 894 1.1 christos 895 1.1 christos 896 1.1 christos void mesh_mpm_mgmt_rx(struct wpa_supplicant *wpa_s, struct rx_mgmt *rx_mgmt) 897 1.1 christos { 898 1.1 christos struct hostapd_frame_info fi; 899 1.1 christos 900 1.1 christos os_memset(&fi, 0, sizeof(fi)); 901 1.1 christos fi.datarate = rx_mgmt->datarate; 902 1.1 christos fi.ssi_signal = rx_mgmt->ssi_signal; 903 1.1 christos ieee802_11_mgmt(wpa_s->ifmsh->bss[0], rx_mgmt->frame, 904 1.1 christos rx_mgmt->frame_len, &fi); 905 1.1 christos } 906 1.1 christos 907 1.1 christos 908 1.1 christos static void mesh_mpm_plink_estab(struct wpa_supplicant *wpa_s, 909 1.1 christos struct sta_info *sta) 910 1.1 christos { 911 1.1 christos struct hostapd_data *hapd = wpa_s->ifmsh->bss[0]; 912 1.1 christos struct mesh_conf *conf = wpa_s->ifmsh->mconf; 913 1.1 christos u8 seq[6] = {}; 914 1.1 christos 915 1.1 christos wpa_msg(wpa_s, MSG_INFO, "mesh plink with " MACSTR " established", 916 1.1 christos MAC2STR(sta->addr)); 917 1.1 christos 918 1.1 christos if (conf->security & MESH_CONF_SEC_AMPE) { 919 1.1.1.2 christos wpa_hexdump_key(MSG_DEBUG, "mesh: MTK", sta->mtk, sta->mtk_len); 920 1.1.1.5 christos wpa_drv_set_key(wpa_s, -1, 921 1.1.1.5 christos wpa_cipher_to_alg(conf->pairwise_cipher), 922 1.1.1.2 christos sta->addr, 0, 0, seq, sizeof(seq), 923 1.1.1.5 christos sta->mtk, sta->mtk_len, 924 1.1.1.5 christos KEY_FLAG_PAIRWISE_RX_TX); 925 1.1.1.2 christos 926 1.1.1.2 christos wpa_hexdump_key(MSG_DEBUG, "mesh: RX MGTK Key RSC", 927 1.1.1.2 christos sta->mgtk_rsc, sizeof(sta->mgtk_rsc)); 928 1.1.1.2 christos wpa_hexdump_key(MSG_DEBUG, "mesh: RX MGTK", 929 1.1.1.2 christos sta->mgtk, sta->mgtk_len); 930 1.1.1.5 christos wpa_drv_set_key(wpa_s, -1, 931 1.1.1.5 christos wpa_cipher_to_alg(conf->group_cipher), 932 1.1.1.2 christos sta->addr, sta->mgtk_key_id, 0, 933 1.1.1.2 christos sta->mgtk_rsc, sizeof(sta->mgtk_rsc), 934 1.1.1.5 christos sta->mgtk, sta->mgtk_len, 935 1.1.1.5 christos KEY_FLAG_GROUP_RX); 936 1.1.1.2 christos 937 1.1.1.2 christos if (sta->igtk_len) { 938 1.1.1.2 christos wpa_hexdump_key(MSG_DEBUG, "mesh: RX IGTK Key RSC", 939 1.1.1.2 christos sta->igtk_rsc, sizeof(sta->igtk_rsc)); 940 1.1.1.2 christos wpa_hexdump_key(MSG_DEBUG, "mesh: RX IGTK", 941 1.1.1.2 christos sta->igtk, sta->igtk_len); 942 1.1.1.2 christos wpa_drv_set_key( 943 1.1.1.5 christos wpa_s, -1, 944 1.1.1.2 christos wpa_cipher_to_alg(conf->mgmt_group_cipher), 945 1.1.1.2 christos sta->addr, sta->igtk_key_id, 0, 946 1.1.1.2 christos sta->igtk_rsc, sizeof(sta->igtk_rsc), 947 1.1.1.5 christos sta->igtk, sta->igtk_len, 948 1.1.1.5 christos KEY_FLAG_GROUP_RX); 949 1.1.1.2 christos } 950 1.1 christos } 951 1.1 christos 952 1.1 christos wpa_mesh_set_plink_state(wpa_s, sta, PLINK_ESTAB); 953 1.1 christos hapd->num_plinks++; 954 1.1 christos 955 1.1 christos sta->flags |= WLAN_STA_ASSOC; 956 1.1.1.2 christos sta->mesh_sae_pmksa_caching = 0; 957 1.1 christos 958 1.1.1.2 christos eloop_cancel_timeout(peer_add_timer, wpa_s, NULL); 959 1.1.1.2 christos peer_add_timer(wpa_s, NULL); 960 1.1 christos eloop_cancel_timeout(plink_timer, wpa_s, sta); 961 1.1 christos 962 1.1.1.3 christos wpas_notify_mesh_peer_connected(wpa_s, sta->addr); 963 1.1 christos } 964 1.1 christos 965 1.1 christos 966 1.1 christos static void mesh_mpm_fsm(struct wpa_supplicant *wpa_s, struct sta_info *sta, 967 1.1.1.2 christos enum plink_event event, u16 reason) 968 1.1 christos { 969 1.1 christos struct hostapd_data *hapd = wpa_s->ifmsh->bss[0]; 970 1.1 christos struct mesh_conf *conf = wpa_s->ifmsh->mconf; 971 1.1 christos 972 1.1 christos wpa_msg(wpa_s, MSG_DEBUG, "MPM " MACSTR " state %s event %s", 973 1.1 christos MAC2STR(sta->addr), mplstate[sta->plink_state], 974 1.1 christos mplevent[event]); 975 1.1 christos 976 1.1 christos switch (sta->plink_state) { 977 1.1.1.2 christos case PLINK_IDLE: 978 1.1 christos switch (event) { 979 1.1 christos case CLS_ACPT: 980 1.1 christos mesh_mpm_fsm_restart(wpa_s, sta); 981 1.1 christos break; 982 1.1 christos case OPN_ACPT: 983 1.1.1.2 christos mesh_mpm_plink_open(wpa_s, sta, PLINK_OPN_RCVD); 984 1.1 christos mesh_mpm_send_plink_action(wpa_s, sta, PLINK_CONFIRM, 985 1.1 christos 0); 986 1.1 christos break; 987 1.1.1.2 christos case REQ_RJCT: 988 1.1.1.2 christos mesh_mpm_send_plink_action(wpa_s, sta, 989 1.1.1.2 christos PLINK_CLOSE, reason); 990 1.1.1.2 christos break; 991 1.1 christos default: 992 1.1 christos break; 993 1.1 christos } 994 1.1 christos break; 995 1.1.1.2 christos case PLINK_OPN_SNT: 996 1.1 christos switch (event) { 997 1.1 christos case OPN_RJCT: 998 1.1 christos case CNF_RJCT: 999 1.1.1.2 christos if (!reason) 1000 1.1.1.2 christos reason = WLAN_REASON_MESH_CONFIG_POLICY_VIOLATION; 1001 1.1 christos /* fall-through */ 1002 1.1 christos case CLS_ACPT: 1003 1.1 christos wpa_mesh_set_plink_state(wpa_s, sta, PLINK_HOLDING); 1004 1.1 christos if (!reason) 1005 1.1 christos reason = WLAN_REASON_MESH_CLOSE_RCVD; 1006 1.1 christos eloop_register_timeout( 1007 1.1 christos conf->dot11MeshHoldingTimeout / 1000, 1008 1.1 christos (conf->dot11MeshHoldingTimeout % 1000) * 1000, 1009 1.1 christos plink_timer, wpa_s, sta); 1010 1.1 christos mesh_mpm_send_plink_action(wpa_s, sta, 1011 1.1 christos PLINK_CLOSE, reason); 1012 1.1 christos break; 1013 1.1 christos case OPN_ACPT: 1014 1.1 christos /* retry timer is left untouched */ 1015 1.1.1.2 christos wpa_mesh_set_plink_state(wpa_s, sta, PLINK_OPN_RCVD); 1016 1.1 christos mesh_mpm_send_plink_action(wpa_s, sta, 1017 1.1 christos PLINK_CONFIRM, 0); 1018 1.1 christos break; 1019 1.1 christos case CNF_ACPT: 1020 1.1 christos wpa_mesh_set_plink_state(wpa_s, sta, PLINK_CNF_RCVD); 1021 1.1.1.2 christos eloop_cancel_timeout(plink_timer, wpa_s, sta); 1022 1.1 christos eloop_register_timeout( 1023 1.1 christos conf->dot11MeshConfirmTimeout / 1000, 1024 1.1 christos (conf->dot11MeshConfirmTimeout % 1000) * 1000, 1025 1.1 christos plink_timer, wpa_s, sta); 1026 1.1 christos break; 1027 1.1 christos default: 1028 1.1 christos break; 1029 1.1 christos } 1030 1.1 christos break; 1031 1.1.1.2 christos case PLINK_OPN_RCVD: 1032 1.1 christos switch (event) { 1033 1.1 christos case OPN_RJCT: 1034 1.1 christos case CNF_RJCT: 1035 1.1.1.2 christos if (!reason) 1036 1.1.1.2 christos reason = WLAN_REASON_MESH_CONFIG_POLICY_VIOLATION; 1037 1.1 christos /* fall-through */ 1038 1.1 christos case CLS_ACPT: 1039 1.1 christos wpa_mesh_set_plink_state(wpa_s, sta, PLINK_HOLDING); 1040 1.1 christos if (!reason) 1041 1.1 christos reason = WLAN_REASON_MESH_CLOSE_RCVD; 1042 1.1 christos eloop_register_timeout( 1043 1.1 christos conf->dot11MeshHoldingTimeout / 1000, 1044 1.1 christos (conf->dot11MeshHoldingTimeout % 1000) * 1000, 1045 1.1 christos plink_timer, wpa_s, sta); 1046 1.1 christos sta->mpm_close_reason = reason; 1047 1.1 christos mesh_mpm_send_plink_action(wpa_s, sta, 1048 1.1 christos PLINK_CLOSE, reason); 1049 1.1 christos break; 1050 1.1 christos case OPN_ACPT: 1051 1.1 christos mesh_mpm_send_plink_action(wpa_s, sta, 1052 1.1 christos PLINK_CONFIRM, 0); 1053 1.1 christos break; 1054 1.1 christos case CNF_ACPT: 1055 1.1 christos if (conf->security & MESH_CONF_SEC_AMPE) 1056 1.1 christos mesh_rsn_derive_mtk(wpa_s, sta); 1057 1.1 christos mesh_mpm_plink_estab(wpa_s, sta); 1058 1.1 christos break; 1059 1.1 christos default: 1060 1.1 christos break; 1061 1.1 christos } 1062 1.1 christos break; 1063 1.1 christos case PLINK_CNF_RCVD: 1064 1.1 christos switch (event) { 1065 1.1 christos case OPN_RJCT: 1066 1.1 christos case CNF_RJCT: 1067 1.1.1.2 christos if (!reason) 1068 1.1.1.2 christos reason = WLAN_REASON_MESH_CONFIG_POLICY_VIOLATION; 1069 1.1 christos /* fall-through */ 1070 1.1 christos case CLS_ACPT: 1071 1.1 christos wpa_mesh_set_plink_state(wpa_s, sta, PLINK_HOLDING); 1072 1.1 christos if (!reason) 1073 1.1 christos reason = WLAN_REASON_MESH_CLOSE_RCVD; 1074 1.1 christos eloop_register_timeout( 1075 1.1 christos conf->dot11MeshHoldingTimeout / 1000, 1076 1.1 christos (conf->dot11MeshHoldingTimeout % 1000) * 1000, 1077 1.1 christos plink_timer, wpa_s, sta); 1078 1.1 christos sta->mpm_close_reason = reason; 1079 1.1 christos mesh_mpm_send_plink_action(wpa_s, sta, 1080 1.1 christos PLINK_CLOSE, reason); 1081 1.1 christos break; 1082 1.1 christos case OPN_ACPT: 1083 1.1.1.2 christos if (conf->security & MESH_CONF_SEC_AMPE) 1084 1.1.1.2 christos mesh_rsn_derive_mtk(wpa_s, sta); 1085 1.1 christos mesh_mpm_plink_estab(wpa_s, sta); 1086 1.1 christos mesh_mpm_send_plink_action(wpa_s, sta, 1087 1.1 christos PLINK_CONFIRM, 0); 1088 1.1 christos break; 1089 1.1 christos default: 1090 1.1 christos break; 1091 1.1 christos } 1092 1.1 christos break; 1093 1.1 christos case PLINK_ESTAB: 1094 1.1 christos switch (event) { 1095 1.1.1.2 christos case OPN_RJCT: 1096 1.1.1.2 christos case CNF_RJCT: 1097 1.1 christos case CLS_ACPT: 1098 1.1 christos wpa_mesh_set_plink_state(wpa_s, sta, PLINK_HOLDING); 1099 1.1.1.2 christos if (!reason) 1100 1.1.1.2 christos reason = WLAN_REASON_MESH_CLOSE_RCVD; 1101 1.1 christos 1102 1.1 christos eloop_register_timeout( 1103 1.1 christos conf->dot11MeshHoldingTimeout / 1000, 1104 1.1 christos (conf->dot11MeshHoldingTimeout % 1000) * 1000, 1105 1.1 christos plink_timer, wpa_s, sta); 1106 1.1 christos sta->mpm_close_reason = reason; 1107 1.1 christos 1108 1.1 christos wpa_msg(wpa_s, MSG_INFO, "mesh plink with " MACSTR 1109 1.1 christos " closed with reason %d", 1110 1.1 christos MAC2STR(sta->addr), reason); 1111 1.1 christos 1112 1.1.1.3 christos wpas_notify_mesh_peer_disconnected(wpa_s, sta->addr, 1113 1.1.1.3 christos reason); 1114 1.1.1.3 christos 1115 1.1 christos hapd->num_plinks--; 1116 1.1 christos 1117 1.1 christos mesh_mpm_send_plink_action(wpa_s, sta, 1118 1.1 christos PLINK_CLOSE, reason); 1119 1.1 christos break; 1120 1.1 christos case OPN_ACPT: 1121 1.1 christos mesh_mpm_send_plink_action(wpa_s, sta, 1122 1.1 christos PLINK_CONFIRM, 0); 1123 1.1 christos break; 1124 1.1 christos default: 1125 1.1 christos break; 1126 1.1 christos } 1127 1.1 christos break; 1128 1.1 christos case PLINK_HOLDING: 1129 1.1 christos switch (event) { 1130 1.1 christos case CLS_ACPT: 1131 1.1 christos mesh_mpm_fsm_restart(wpa_s, sta); 1132 1.1 christos break; 1133 1.1 christos case OPN_ACPT: 1134 1.1 christos case CNF_ACPT: 1135 1.1 christos case OPN_RJCT: 1136 1.1 christos case CNF_RJCT: 1137 1.1 christos reason = sta->mpm_close_reason; 1138 1.1 christos mesh_mpm_send_plink_action(wpa_s, sta, 1139 1.1 christos PLINK_CLOSE, reason); 1140 1.1 christos break; 1141 1.1 christos default: 1142 1.1 christos break; 1143 1.1 christos } 1144 1.1 christos break; 1145 1.1 christos default: 1146 1.1 christos wpa_msg(wpa_s, MSG_DEBUG, 1147 1.1 christos "Unsupported MPM event %s for state %s", 1148 1.1 christos mplevent[event], mplstate[sta->plink_state]); 1149 1.1 christos break; 1150 1.1 christos } 1151 1.1 christos } 1152 1.1 christos 1153 1.1 christos 1154 1.1 christos void mesh_mpm_action_rx(struct wpa_supplicant *wpa_s, 1155 1.1 christos const struct ieee80211_mgmt *mgmt, size_t len) 1156 1.1 christos { 1157 1.1 christos u8 action_field; 1158 1.1 christos struct hostapd_data *hapd = wpa_s->ifmsh->bss[0]; 1159 1.1 christos struct mesh_conf *mconf = wpa_s->ifmsh->mconf; 1160 1.1 christos struct sta_info *sta; 1161 1.1.1.2 christos u16 plid = 0, llid = 0, aid = 0; 1162 1.1 christos enum plink_event event; 1163 1.1 christos struct ieee802_11_elems elems; 1164 1.1 christos struct mesh_peer_mgmt_ie peer_mgmt_ie; 1165 1.1 christos const u8 *ies; 1166 1.1 christos size_t ie_len; 1167 1.1 christos int ret; 1168 1.1.1.2 christos u16 reason = 0; 1169 1.1 christos 1170 1.1 christos if (mgmt->u.action.category != WLAN_ACTION_SELF_PROTECTED) 1171 1.1 christos return; 1172 1.1 christos 1173 1.1 christos action_field = mgmt->u.action.u.slf_prot_action.action; 1174 1.1 christos if (action_field != PLINK_OPEN && 1175 1.1 christos action_field != PLINK_CONFIRM && 1176 1.1 christos action_field != PLINK_CLOSE) 1177 1.1 christos return; 1178 1.1 christos 1179 1.1 christos ies = mgmt->u.action.u.slf_prot_action.variable; 1180 1.1 christos ie_len = (const u8 *) mgmt + len - 1181 1.1 christos mgmt->u.action.u.slf_prot_action.variable; 1182 1.1 christos 1183 1.1 christos /* at least expect mesh id and peering mgmt */ 1184 1.1 christos if (ie_len < 2 + 2) { 1185 1.1 christos wpa_printf(MSG_DEBUG, 1186 1.1 christos "MPM: Ignore too short action frame %u ie_len %u", 1187 1.1 christos action_field, (unsigned int) ie_len); 1188 1.1 christos return; 1189 1.1 christos } 1190 1.1 christos wpa_printf(MSG_DEBUG, "MPM: Received PLINK action %u", action_field); 1191 1.1 christos 1192 1.1 christos if (action_field == PLINK_OPEN || action_field == PLINK_CONFIRM) { 1193 1.1 christos wpa_printf(MSG_DEBUG, "MPM: Capability 0x%x", 1194 1.1 christos WPA_GET_LE16(ies)); 1195 1.1 christos ies += 2; /* capability */ 1196 1.1 christos ie_len -= 2; 1197 1.1 christos } 1198 1.1 christos if (action_field == PLINK_CONFIRM) { 1199 1.1.1.2 christos aid = WPA_GET_LE16(ies); 1200 1.1.1.2 christos wpa_printf(MSG_DEBUG, "MPM: AID 0x%x", aid); 1201 1.1 christos ies += 2; /* aid */ 1202 1.1 christos ie_len -= 2; 1203 1.1 christos } 1204 1.1 christos 1205 1.1 christos /* check for mesh peering, mesh id and mesh config IEs */ 1206 1.1 christos if (ieee802_11_parse_elems(ies, ie_len, &elems, 0) == ParseFailed) { 1207 1.1 christos wpa_printf(MSG_DEBUG, "MPM: Failed to parse PLINK IEs"); 1208 1.1 christos return; 1209 1.1 christos } 1210 1.1 christos if (!elems.peer_mgmt) { 1211 1.1 christos wpa_printf(MSG_DEBUG, 1212 1.1 christos "MPM: No Mesh Peering Management element"); 1213 1.1 christos return; 1214 1.1 christos } 1215 1.1 christos if (action_field != PLINK_CLOSE) { 1216 1.1 christos if (!elems.mesh_id || !elems.mesh_config) { 1217 1.1 christos wpa_printf(MSG_DEBUG, 1218 1.1 christos "MPM: No Mesh ID or Mesh Configuration element"); 1219 1.1 christos return; 1220 1.1 christos } 1221 1.1 christos 1222 1.1 christos if (!matches_local(wpa_s, &elems)) { 1223 1.1 christos wpa_printf(MSG_DEBUG, 1224 1.1 christos "MPM: Mesh ID or Mesh Configuration element do not match local MBSS"); 1225 1.1 christos return; 1226 1.1 christos } 1227 1.1 christos } 1228 1.1 christos 1229 1.1 christos ret = mesh_mpm_parse_peer_mgmt(wpa_s, action_field, 1230 1.1 christos elems.peer_mgmt, 1231 1.1 christos elems.peer_mgmt_len, 1232 1.1 christos &peer_mgmt_ie); 1233 1.1 christos if (ret) { 1234 1.1 christos wpa_printf(MSG_DEBUG, "MPM: Mesh parsing rejected frame"); 1235 1.1 christos return; 1236 1.1 christos } 1237 1.1 christos 1238 1.1 christos /* the sender's llid is our plid and vice-versa */ 1239 1.1 christos plid = WPA_GET_LE16(peer_mgmt_ie.llid); 1240 1.1 christos if (peer_mgmt_ie.plid) 1241 1.1 christos llid = WPA_GET_LE16(peer_mgmt_ie.plid); 1242 1.1 christos wpa_printf(MSG_DEBUG, "MPM: plid=0x%x llid=0x%x", plid, llid); 1243 1.1 christos 1244 1.1.1.2 christos if (action_field == PLINK_CLOSE) 1245 1.1.1.2 christos wpa_printf(MSG_DEBUG, "MPM: close reason=%u", 1246 1.1.1.2 christos WPA_GET_LE16(peer_mgmt_ie.reason)); 1247 1.1.1.2 christos 1248 1.1 christos sta = ap_get_sta(hapd, mgmt->sa); 1249 1.1 christos 1250 1.1 christos /* 1251 1.1 christos * If this is an open frame from an unknown STA, and this is an 1252 1.1 christos * open mesh, then go ahead and add the peer before proceeding. 1253 1.1 christos */ 1254 1.1 christos if (!sta && action_field == PLINK_OPEN && 1255 1.1.1.2 christos (!(mconf->security & MESH_CONF_SEC_AMPE) || 1256 1.1.1.3 christos wpa_auth_pmksa_get(hapd->wpa_auth, mgmt->sa, NULL))) 1257 1.1 christos sta = mesh_mpm_add_peer(wpa_s, mgmt->sa, &elems); 1258 1.1 christos 1259 1.1 christos if (!sta) { 1260 1.1 christos wpa_printf(MSG_DEBUG, "MPM: No STA entry for peer"); 1261 1.1 christos return; 1262 1.1 christos } 1263 1.1 christos 1264 1.1 christos #ifdef CONFIG_SAE 1265 1.1 christos /* peer is in sae_accepted? */ 1266 1.1 christos if (sta->sae && sta->sae->state != SAE_ACCEPTED) { 1267 1.1 christos wpa_printf(MSG_DEBUG, "MPM: SAE not yet accepted for peer"); 1268 1.1 christos return; 1269 1.1 christos } 1270 1.1 christos #endif /* CONFIG_SAE */ 1271 1.1 christos 1272 1.1 christos if (!sta->my_lid) 1273 1.1 christos mesh_mpm_init_link(wpa_s, sta); 1274 1.1 christos 1275 1.1.1.2 christos if (mconf->security & MESH_CONF_SEC_AMPE) { 1276 1.1.1.2 christos int res; 1277 1.1.1.2 christos 1278 1.1.1.2 christos res = mesh_rsn_process_ampe(wpa_s, sta, &elems, 1279 1.1.1.2 christos &mgmt->u.action.category, 1280 1.1.1.2 christos peer_mgmt_ie.chosen_pmk, 1281 1.1.1.2 christos ies, ie_len); 1282 1.1.1.2 christos if (res) { 1283 1.1.1.2 christos wpa_printf(MSG_DEBUG, 1284 1.1.1.2 christos "MPM: RSN process rejected frame (res=%d)", 1285 1.1.1.2 christos res); 1286 1.1.1.2 christos if (action_field == PLINK_OPEN && res == -2) { 1287 1.1.1.2 christos /* AES-SIV decryption failed */ 1288 1.1.1.2 christos mesh_mpm_fsm(wpa_s, sta, OPN_RJCT, 1289 1.1.1.2 christos WLAN_REASON_MESH_INVALID_GTK); 1290 1.1.1.2 christos } 1291 1.1.1.2 christos return; 1292 1.1.1.2 christos } 1293 1.1.1.4 christos 1294 1.1.1.4 christos #ifdef CONFIG_OCV 1295 1.1.1.4 christos if (action_field == PLINK_OPEN && elems.rsn_ie) { 1296 1.1.1.4 christos struct wpa_state_machine *sm = sta->wpa_sm; 1297 1.1.1.4 christos struct wpa_ie_data data; 1298 1.1.1.4 christos 1299 1.1.1.4 christos res = wpa_parse_wpa_ie_rsn(elems.rsn_ie - 2, 1300 1.1.1.4 christos elems.rsn_ie_len + 2, 1301 1.1.1.4 christos &data); 1302 1.1.1.4 christos if (res) { 1303 1.1.1.4 christos wpa_printf(MSG_DEBUG, 1304 1.1.1.4 christos "Failed to parse RSN IE (res=%d)", 1305 1.1.1.4 christos res); 1306 1.1.1.4 christos wpa_hexdump(MSG_DEBUG, "RSN IE", elems.rsn_ie, 1307 1.1.1.4 christos elems.rsn_ie_len); 1308 1.1.1.4 christos return; 1309 1.1.1.4 christos } 1310 1.1.1.4 christos 1311 1.1.1.4 christos wpa_auth_set_ocv(sm, mconf->ocv && 1312 1.1.1.4 christos (data.capabilities & 1313 1.1.1.4 christos WPA_CAPABILITY_OCVC)); 1314 1.1.1.4 christos } 1315 1.1.1.4 christos 1316 1.1.1.4 christos if (action_field != PLINK_CLOSE && 1317 1.1.1.4 christos wpa_auth_uses_ocv(sta->wpa_sm)) { 1318 1.1.1.4 christos struct wpa_channel_info ci; 1319 1.1.1.4 christos int tx_chanwidth; 1320 1.1.1.4 christos int tx_seg1_idx; 1321 1.1.1.4 christos 1322 1.1.1.4 christos if (wpa_drv_channel_info(wpa_s, &ci) != 0) { 1323 1.1.1.4 christos wpa_printf(MSG_WARNING, 1324 1.1.1.4 christos "MPM: Failed to get channel info to validate received OCI in MPM Confirm"); 1325 1.1.1.4 christos return; 1326 1.1.1.4 christos } 1327 1.1.1.4 christos 1328 1.1.1.4 christos if (get_tx_parameters( 1329 1.1.1.4 christos sta, channel_width_to_int(ci.chanwidth), 1330 1.1.1.4 christos ci.seg1_idx, &tx_chanwidth, 1331 1.1.1.4 christos &tx_seg1_idx) < 0) 1332 1.1.1.4 christos return; 1333 1.1.1.4 christos 1334 1.1.1.4 christos if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci, 1335 1.1.1.4 christos tx_chanwidth, tx_seg1_idx) != 1336 1.1.1.5 christos OCI_SUCCESS) { 1337 1.1.1.5 christos wpa_printf(MSG_WARNING, "MPM: OCV failed: %s", 1338 1.1.1.4 christos ocv_errorstr); 1339 1.1.1.4 christos return; 1340 1.1.1.4 christos } 1341 1.1.1.4 christos } 1342 1.1.1.4 christos #endif /* CONFIG_OCV */ 1343 1.1 christos } 1344 1.1 christos 1345 1.1 christos if (sta->plink_state == PLINK_BLOCKED) { 1346 1.1 christos wpa_printf(MSG_DEBUG, "MPM: PLINK_BLOCKED"); 1347 1.1 christos return; 1348 1.1 christos } 1349 1.1 christos 1350 1.1 christos /* Now we will figure out the appropriate event... */ 1351 1.1 christos switch (action_field) { 1352 1.1 christos case PLINK_OPEN: 1353 1.1 christos if (plink_free_count(hapd) == 0) { 1354 1.1.1.2 christos event = REQ_RJCT; 1355 1.1.1.2 christos reason = WLAN_REASON_MESH_MAX_PEERS; 1356 1.1 christos wpa_printf(MSG_INFO, 1357 1.1 christos "MPM: Peer link num over quota(%d)", 1358 1.1 christos hapd->max_plinks); 1359 1.1 christos } else if (sta->peer_lid && sta->peer_lid != plid) { 1360 1.1.1.2 christos wpa_printf(MSG_DEBUG, 1361 1.1.1.2 christos "MPM: peer_lid mismatch: 0x%x != 0x%x", 1362 1.1.1.2 christos sta->peer_lid, plid); 1363 1.1.1.2 christos return; /* no FSM event */ 1364 1.1 christos } else { 1365 1.1 christos sta->peer_lid = plid; 1366 1.1 christos event = OPN_ACPT; 1367 1.1 christos } 1368 1.1 christos break; 1369 1.1 christos case PLINK_CONFIRM: 1370 1.1 christos if (plink_free_count(hapd) == 0) { 1371 1.1.1.2 christos event = REQ_RJCT; 1372 1.1.1.2 christos reason = WLAN_REASON_MESH_MAX_PEERS; 1373 1.1 christos wpa_printf(MSG_INFO, 1374 1.1 christos "MPM: Peer link num over quota(%d)", 1375 1.1 christos hapd->max_plinks); 1376 1.1 christos } else if (sta->my_lid != llid || 1377 1.1 christos (sta->peer_lid && sta->peer_lid != plid)) { 1378 1.1.1.2 christos wpa_printf(MSG_DEBUG, 1379 1.1.1.2 christos "MPM: lid mismatch: my_lid: 0x%x != 0x%x or peer_lid: 0x%x != 0x%x", 1380 1.1.1.2 christos sta->my_lid, llid, sta->peer_lid, plid); 1381 1.1.1.2 christos return; /* no FSM event */ 1382 1.1 christos } else { 1383 1.1 christos if (!sta->peer_lid) 1384 1.1 christos sta->peer_lid = plid; 1385 1.1.1.2 christos sta->peer_aid = aid; 1386 1.1 christos event = CNF_ACPT; 1387 1.1 christos } 1388 1.1 christos break; 1389 1.1 christos case PLINK_CLOSE: 1390 1.1 christos if (sta->plink_state == PLINK_ESTAB) 1391 1.1 christos /* Do not check for llid or plid. This does not 1392 1.1 christos * follow the standard but since multiple plinks 1393 1.1 christos * per cand are not supported, it is necessary in 1394 1.1 christos * order to avoid a livelock when MP A sees an 1395 1.1 christos * establish peer link to MP B but MP B does not 1396 1.1 christos * see it. This can be caused by a timeout in 1397 1.1 christos * B's peer link establishment or B being 1398 1.1 christos * restarted. 1399 1.1 christos */ 1400 1.1 christos event = CLS_ACPT; 1401 1.1.1.2 christos else if (sta->peer_lid != plid) { 1402 1.1.1.2 christos wpa_printf(MSG_DEBUG, 1403 1.1.1.2 christos "MPM: peer_lid mismatch: 0x%x != 0x%x", 1404 1.1.1.2 christos sta->peer_lid, plid); 1405 1.1.1.2 christos return; /* no FSM event */ 1406 1.1.1.2 christos } else if (peer_mgmt_ie.plid && sta->my_lid != llid) { 1407 1.1.1.2 christos wpa_printf(MSG_DEBUG, 1408 1.1.1.2 christos "MPM: my_lid mismatch: 0x%x != 0x%x", 1409 1.1.1.2 christos sta->my_lid, llid); 1410 1.1.1.2 christos return; /* no FSM event */ 1411 1.1.1.2 christos } else { 1412 1.1 christos event = CLS_ACPT; 1413 1.1.1.2 christos } 1414 1.1 christos break; 1415 1.1 christos default: 1416 1.1 christos /* 1417 1.1 christos * This cannot be hit due to the action_field check above, but 1418 1.1 christos * compilers may not be able to figure that out and can warn 1419 1.1 christos * about uninitialized event below. 1420 1.1 christos */ 1421 1.1 christos return; 1422 1.1 christos } 1423 1.1.1.2 christos mesh_mpm_fsm(wpa_s, sta, event, reason); 1424 1.1 christos } 1425 1.1 christos 1426 1.1 christos 1427 1.1 christos /* called by ap_free_sta */ 1428 1.1.1.2 christos void mesh_mpm_free_sta(struct hostapd_data *hapd, struct sta_info *sta) 1429 1.1 christos { 1430 1.1.1.5 christos struct wpa_supplicant *wpa_s = hapd->iface->owner; 1431 1.1.1.5 christos 1432 1.1.1.5 christos if (sta->plink_state == PLINK_ESTAB) { 1433 1.1.1.2 christos hapd->num_plinks--; 1434 1.1.1.5 christos wpas_notify_mesh_peer_disconnected( 1435 1.1.1.5 christos wpa_s, sta->addr, WLAN_REASON_UNSPECIFIED); 1436 1.1.1.5 christos } 1437 1.1 christos eloop_cancel_timeout(plink_timer, ELOOP_ALL_CTX, sta); 1438 1.1 christos eloop_cancel_timeout(mesh_auth_timer, ELOOP_ALL_CTX, sta); 1439 1.1 christos } 1440