static uint32_t do_estab_peer_link(struct candidate *cand) { uint32_t changed; derive_mtk(cand); cb->estab_peer_link( cand->peer_mac, cand->mtk, sizeof(cand->mtk), cand->mgtk, sizeof(cand->mgtk), cand->mgtk_expiration, (cand->has_igtk) ? cand->igtk : NULL, (cand->has_igtk) ? sizeof(cand->igtk) : 0, cand->igtk_keyid, cand->sup_rates, cand->sup_rates_len, cand->cookie); set_link_state(cand, PLINK_ESTAB); changed = mesh_set_ht_op_mode(cand->conf->mesh); sae_debug( AMPE_DEBUG_FSM, "Mesh plink with " MACSTR " ESTABLISHED\n", MAC2STR(cand->peer_mac)); rekey_verify_peer(cand); return changed; }
static void fsm_step(struct candidate *cand, enum plink_event event) { struct ampe_config *aconf = cand->conf; unsigned short reason = 0; uint32_t changed = 0; switch (cand->link_state) { case PLINK_LISTEN: switch (event) { case CLS_ACPT: fsm_restart(cand); break; case OPN_ACPT: cand->timeout = aconf->retry_timeout_ms; cand->t2 = srv_add_timeout(srvctx, SRV_MSEC(cand->timeout), plink_timer, cand); plink_frame_tx(cand, PLINK_OPEN, 0); plink_frame_tx(cand, PLINK_CONFIRM, 0); break; default: break; } break; case PLINK_OPN_SNT: switch (event) { case OPN_RJCT: case CNF_RJCT: reason = htole16(MESH_CAPABILITY_POLICY_VIOLATION); case CLS_ACPT: if (!reason) reason = htole16(MESH_CLOSE_RCVD); cand->reason = reason; set_link_state(cand, PLINK_HOLDING); cand->timeout = aconf->holding_timeout_ms; cand->t2 = srv_add_timeout(srvctx, SRV_MSEC(cand->timeout), plink_timer, cand); plink_frame_tx(cand, PLINK_CLOSE, reason); break; case OPN_ACPT: /* retry timer is left untouched */ set_link_state(cand, PLINK_OPN_RCVD); plink_frame_tx(cand, PLINK_CONFIRM, 0); break; case CNF_ACPT: set_link_state(cand, PLINK_CNF_RCVD); cand->timeout = aconf->confirm_timeout_ms; cand->t2 = srv_add_timeout(srvctx, SRV_MSEC(cand->timeout), plink_timer, cand); break; default: break; } break; case PLINK_OPN_RCVD: switch (event) { case OPN_RJCT: case CNF_RJCT: reason = htole16(MESH_CAPABILITY_POLICY_VIOLATION); case CLS_ACPT: if (!reason) reason = htole16(MESH_CLOSE_RCVD); cand->reason = reason; set_link_state(cand, PLINK_HOLDING); cand->timeout = aconf->holding_timeout_ms; cand->t2 = srv_add_timeout(srvctx, SRV_MSEC(cand->timeout), plink_timer, cand); plink_frame_tx(cand, PLINK_CLOSE, reason); break; case OPN_ACPT: plink_frame_tx(cand, PLINK_CONFIRM, 0); break; case CNF_ACPT: //del_timer(&cand->plink_timer); set_link_state(cand, PLINK_ESTAB); //mesh_plink_inc_estab_count(sdata); //ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); derive_mtk(cand); estab_peer_link(cand->peer_mac, cand->mtk, sizeof(cand->mtk), cand->mgtk, sizeof(cand->mgtk), cand->mgtk_expiration, cand->sup_rates, cand->sup_rates_len, cand->cookie); changed |= mesh_set_ht_op_mode(cand->conf->mesh); sae_debug(AMPE_DEBUG_FSM, "mesh plink with " MACSTR " established\n", MAC2STR(cand->peer_mac)); break; default: break; } break; case PLINK_CNF_RCVD: switch (event) { case OPN_RJCT: case CNF_RJCT: reason = htole16(MESH_CAPABILITY_POLICY_VIOLATION); case CLS_ACPT: if (!reason) reason = htole16(MESH_CLOSE_RCVD); cand->reason = reason; set_link_state(cand, PLINK_HOLDING); cand->timeout = aconf->holding_timeout_ms; cand->t2 = srv_add_timeout(srvctx, SRV_MSEC(cand->timeout), plink_timer, cand); plink_frame_tx(cand, PLINK_CLOSE, reason); break; case OPN_ACPT: set_link_state(cand, PLINK_ESTAB); estab_peer_link(cand->peer_mac, cand->mtk, sizeof(cand->mtk), cand->mgtk, sizeof(cand->mgtk), cand->mgtk_expiration, cand->sup_rates, cand->sup_rates_len, cand->cookie); changed |= mesh_set_ht_op_mode(cand->conf->mesh); //TODO: update the number of available peer "slots" in mesh config //mesh_plink_inc_estab_count(sdata); //ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); sae_debug(AMPE_DEBUG_FSM, "Mesh plink with " MACSTR " ESTABLISHED\n", MAC2STR(cand->peer_mac)); plink_frame_tx(cand, PLINK_CONFIRM, 0); break; default: break; } break; case PLINK_ESTAB: switch (event) { case CLS_ACPT: reason = htole16(MESH_CLOSE_RCVD); cand->reason = reason; set_link_state(cand, PLINK_HOLDING); cand->timeout = aconf->holding_timeout_ms; cand->t2 = srv_add_timeout(srvctx, SRV_MSEC(cand->timeout), plink_timer, cand); changed |= mesh_set_ht_op_mode(cand->conf->mesh); //TODO: update the number of available peer "slots" in mesh config //if (deactivated) // ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); plink_frame_tx(cand, PLINK_CLOSE, reason); break; case OPN_ACPT: plink_frame_tx(cand, PLINK_CONFIRM, 0); break; default: break; } break; case PLINK_HOLDING: switch (event) { case CLS_ACPT: //if (del_timer(&cand->plink_timer)) // cand->ignore_plink_timer = 1; fsm_restart(cand); break; case OPN_ACPT: case CNF_ACPT: case OPN_RJCT: case CNF_RJCT: reason = cand->reason; plink_frame_tx(cand, PLINK_CLOSE, reason); break; default: break; } break; default: sae_debug(AMPE_DEBUG_FSM, "Unsupported event transition %d", event); break; } if (changed) meshd_set_mesh_conf(cand->conf->mesh, changed); }