static uns32 avnd_node_oper_req(AVND_CB *cb, AVSV_PARAM_INFO *param) { uns32 rc = NCSCC_RC_FAILURE; TRACE_ENTER2("'%s'", param->name.value); switch (param->act) { case AVSV_OBJ_OPR_MOD: switch (param->attr_id) { case saAmfNodeSuFailoverProb_ID: assert(sizeof(SaTimeT) == param->value_len); cb->su_failover_prob = m_NCS_OS_NTOHLL_P(param->value); break; case saAmfNodeSuFailoverMax_ID: assert(sizeof(uns32) == param->value_len); cb->su_failover_max = m_NCS_OS_NTOHL(*(uns32 *)(param->value)); break; default: LOG_NO("%s: Unsupported attribute %u", __FUNCTION__, param->attr_id); goto done; } break; default: LOG_NO("%s: Unsupported action %u", __FUNCTION__, param->act); goto done; } rc = NCSCC_RC_SUCCESS; done: TRACE_LEAVE(); return rc; }
/*************************************************************************** @brief : MDS svc evt callback. In this context called for SMFND UP/DOWN events. @param[in] : svc_evt - MDS svc event callback info. @return : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE *****************************************************************************/ uint32_t smfa_mds_svc_evt_cbk(MDS_CALLBACK_SVC_EVENT_INFO *svc_evt) { SMFA_CB *cb = &_smfa_cb; /* Agent subscribes for only local ND UP/DOWN.*/ if (NCSMDS_SVC_ID_SMFND != svc_evt->i_svc_id){ LOG_NO("SMFA: Got svc evt for: %d",svc_evt->i_svc_id); return NCSCC_RC_SUCCESS; } switch(svc_evt->i_change){ case NCSMDS_UP: /* Catch the adest of SMFND*/ if (!m_MDS_DEST_IS_AN_ADEST(svc_evt->i_dest)) return NCSCC_RC_SUCCESS; /* TODO: No lock is taken. This might be dangerous.*/ cb->is_smfnd_up = true; cb->smfnd_adest = svc_evt->i_dest; break; case NCSMDS_DOWN: if (!m_MDS_DEST_IS_AN_ADEST(svc_evt->i_dest)) return NCSCC_RC_SUCCESS; /* TODO: No lock is taken. This might be dangerous.*/ cb->is_smfnd_up = false; cb->smfnd_adest = 0; break; default: LOG_NO("SMFA: Got the svc evt: %d for SMFND",svc_evt->i_change); } return NCSCC_RC_SUCCESS; }
static uns32 avnd_sg_oper_req(AVND_CB *cb, AVSV_PARAM_INFO *param) { uns32 rc = NCSCC_RC_FAILURE; TRACE_ENTER2("'%s'", param->name.value); switch (param->act) { case AVSV_OBJ_OPR_MOD: { AVND_SU *su; su = m_AVND_SUDB_REC_GET(cb->sudb, param->name); if (!su) { LOG_ER("%s: failed to get %s", __FUNCTION__, param->name.value); goto done; } switch (param->attr_id) { case saAmfSGCompRestartProb_ID: assert(sizeof(SaTimeT) == param->value_len); su->comp_restart_prob = m_NCS_OS_NTOHLL_P(param->value); m_AVND_SEND_CKPT_UPDT_ASYNC_UPDT(cb, su, AVND_CKPT_SU_COMP_RESTART_PROB); break; case saAmfSGCompRestartMax_ID: assert(sizeof(uns32) == param->value_len); su->comp_restart_max = m_NCS_OS_NTOHL(*(uns32 *)(param->value)); m_AVND_SEND_CKPT_UPDT_ASYNC_UPDT(cb, su, AVND_CKPT_SU_COMP_RESTART_MAX); break; case saAmfSGSuRestartProb_ID: assert(sizeof(SaTimeT) == param->value_len); su->su_restart_prob = m_NCS_OS_NTOHLL_P(param->value); m_AVND_SEND_CKPT_UPDT_ASYNC_UPDT(cb, su, AVND_CKPT_SU_RESTART_PROB); break; case saAmfSGSuRestartMax_ID: assert(sizeof(uns32) == param->value_len); su->su_restart_max = m_NCS_OS_NTOHL(*(uns32 *)(param->value)); m_AVND_SEND_CKPT_UPDT_ASYNC_UPDT(cb, su, AVND_CKPT_SU_RESTART_MAX); break; default: LOG_NO("%s: Unsupported attribute %u", __FUNCTION__, param->attr_id); goto done; } break; } default: LOG_NO("%s: Unsupported action %u", __FUNCTION__, param->act); goto done; } rc = NCSCC_RC_SUCCESS; done: TRACE_LEAVE(); return rc; }
/**************************************************************************** * Name : fm_mbx_msg_handler * * Description : Processes Mail box messages between FM. * * Arguments : Pointer to Control block and Mail box event * * Return Values : None. * * Notes : None. *****************************************************************************/ static void fm_mbx_msg_handler(FM_CB *fm_cb, FM_EVT *fm_mbx_evt) { switch (fm_mbx_evt->evt_code) { case FM_EVT_NODE_DOWN: LOG_NO("Role: %s, Node Down for node id: %x", role_string[fm_cb->role], fm_mbx_evt->node_id); if ((fm_cb->role == PCS_RDA_STANDBY)||(fm_cb->role == PCS_RDA_QUIESCED)) { if ((fm_mbx_evt->node_id == fm_cb->peer_node_id)) { /* Start Promote active timer */ if ((fm_cb->peer_node_name.length != 0) && (fm_cb->role != PCS_RDA_QUIESCED)) { LOG_NO("Promote active timer started"); fm_tmr_start(&fm_cb->promote_active_tmr, fm_cb->active_promote_tmr_val); } else { fm_cb->role = PCS_RDA_ACTIVE; opensaf_reboot(fm_cb->peer_node_id, (char *)fm_cb->peer_node_name.value, "Received Node Down for Active peer"); fm_rda_set_role(fm_cb, PCS_RDA_ACTIVE); } } } else if (fm_cb->role == PCS_RDA_ACTIVE) { opensaf_reboot(fm_cb->peer_node_id, (char *)fm_cb->peer_node_name.value, "Received Node Down for standby peer"); } break; case FM_EVT_PEER_UP: /* Peer fm came up so sending ee_id of this node */ if (fm_cb->node_name.length != 0) fms_fms_exchange_node_info(fm_cb); break; case FM_EVT_TMR_EXP: /* Timer Expiry event posted */ if (fm_mbx_evt->info.fm_tmr->type == FM_TMR_PROMOTE_ACTIVE) { /* Now. Try resetting other blade */ fm_cb->role = PCS_RDA_ACTIVE; LOG_NO("Reseting peer controller node id: %x", fm_cb->peer_node_id); opensaf_reboot(fm_cb->peer_node_id, (char *)fm_cb->peer_node_name.value, "Received Node Down for Active peer"); fm_rda_set_role(fm_cb, PCS_RDA_ACTIVE); } break; default: break; } /* Free the event. */ if (fm_mbx_evt != NULL) { m_MMGR_FREE_FM_EVT(fm_mbx_evt); fm_mbx_evt = NULL; } return; }
/*************************************************************************** @brief : MDS rcv callback. In this context called if any MDS msg is received by SMFA. @param[in] : rcv_evt - MDS rcv callback info. @return : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE *****************************************************************************/ uint32_t smfa_mds_rcv_cbk(MDS_CALLBACK_RECEIVE_INFO *rcv_evt) { SMFSV_EVT *smfsv_evt = rcv_evt->i_msg; SMF_EVT *evt = &smfsv_evt->info.smfa.event.cbk_req_rsp; SMFA_CLIENT_INFO *client_info = NULL; SMFA_CB *cb = &_smfa_cb; uint32_t filter_match = false; SMFSV_EVT resp_evt; if (NULL == evt){ LOG_NO("SMFA: evt is NULL in rcv_cbk"); return NCSCC_RC_SUCCESS; } if (SMF_CLBK_EVT != evt->evt_type){ LOG_NO("SMFA: evt_type is : %d",evt->evt_type); return NCSCC_RC_SUCCESS; } /* TODO: I need to take READ LOCK here. But in MDS thread ???*/ client_info = cb->smfa_client_info_list; while (NULL != client_info){ /* If filter matches, post the evt to the corresponding MBX.*/ if (NCSCC_RC_SUCCESS == smfa_cbk_filter_match(client_info,&evt->evt.cbk_evt)) filter_match = true; client_info = client_info->next_client; } /* If filters dont match, respond to ND as SA_AIS_OK*/ if (false == filter_match){ memset(&resp_evt,0,sizeof(SMFSV_EVT)); resp_evt.type = SMFSV_EVT_TYPE_SMFND; resp_evt.info.smfnd.type = SMFND_EVT_CBK_RSP; resp_evt.info.smfnd.event.cbk_req_rsp.evt_type = SMF_RSP_EVT; resp_evt.info.smfnd.event.cbk_req_rsp.evt.resp_evt.inv_id = evt->evt.cbk_evt.inv_id; resp_evt.info.smfnd.event.cbk_req_rsp.evt.resp_evt.err = SA_AIS_OK; if (NCSCC_RC_SUCCESS != smfa_to_smfnd_mds_async_send((NCSCONTEXT)&resp_evt)){ LOG_ER("SMFA: MDS send to SMFND FAILED."); /* TODO: What should I do?? ND is waiting for my response.*/ } } /* This is not the same evt we are putting in client MBX, so free it.*/ free(evt->evt.cbk_evt.params); free(evt->evt.cbk_evt.cbk_label.label); free(smfsv_evt); return NCSCC_RC_SUCCESS; }
/** * Dispatch admin operation requests to the real handler * @param cb * @param evt * * @return uns32 */ uns32 avnd_evt_avd_admin_op_req_evh(AVND_CB *cb, AVND_EVT *evt) { uns32 rc = NCSCC_RC_FAILURE; AVSV_D2N_ADMIN_OP_REQ_MSG_INFO *info = &evt->info.avd->msg_info.d2n_admin_op_req_info; TRACE_ENTER2("%u", info->class_id); switch (info->class_id) { case AVSV_SA_AMF_NODE: rc = avnd_evt_node_admin_op_req(cb, evt); break; case AVSV_SA_AMF_COMP: rc = avnd_evt_comp_admin_op_req(cb, evt); break; case AVSV_SA_AMF_SU: rc = avnd_evt_su_admin_op_req(cb, evt); break; default: LOG_NO("%s: unsupported adm op for class %u", __FUNCTION__, info->class_id); break; } TRACE_LEAVE(); return rc; }
/***************************************************************************** PROCEDURE NAME : eds_start_tmr DESCRIPTION : Starts the EDS timer. If the timer is already active, it is restarted (ie. stopped & started without reallocating the tmr block). ARGUMENTS : cb - ptr to the EDS control block tmr - ptr to the EDS timer block type - timer type period - timer period uarg - opaque handle that is returned on timer expiry RETURNS : NCSCC_RC_SUCCESS - Success NCSCC_RC_FAILURE - Failure NOTES : None *****************************************************************************/ uint32_t eds_start_tmr(EDS_CB *cb, EDS_TMR *tmr, EDS_TMR_TYPE type, SaTimeT period, uint32_t uarg) { uint32_t tmr_period = (uint32_t)(period / EDSV_NANOSEC_TO_LEAPTM); if (EDS_TMR_MAX <= tmr->type) { LOG_WA("Unsupported timer type"); TRACE_LEAVE(); return NCSCC_RC_FAILURE; } if (tmr->tmr_id == TMR_T_NULL) { tmr->type = type; m_NCS_TMR_CREATE(tmr->tmr_id, (uint32_t)tmr_period, eds_tmr_exp, (void *)tmr); } if (tmr->is_active == true) { m_NCS_TMR_STOP(tmr->tmr_id); tmr->is_active = false; } tmr->opq_hdl = uarg; tmr->cb_hdl = cb->my_hdl; m_NCS_TMR_START(tmr->tmr_id, (uint32_t)tmr_period, eds_tmr_exp, (void *)tmr); tmr->is_active = true; if (TMR_T_NULL == tmr->tmr_id) { LOG_NO("Timer start failed: type: %u, Id: %p, period: %u", type, tmr->tmr_id, tmr_period); TRACE_LEAVE(); return NCSCC_RC_FAILURE; } TRACE_LEAVE(); return NCSCC_RC_SUCCESS; }
/**************************************************************************** * Name : amf_quiesced_state_handler * * Description : This function is called upon receving an Quiesced state * assignment from AMF. * * Arguments : invocation - Designates a particular invocation. * cb - A pointer to the SMFD control block. * * Return Values : None * * Notes : None *****************************************************************************/ static SaAisErrorT amf_quiesced_state_handler(smfd_cb_t * cb, SaInvocationT invocation) { TRACE_ENTER(); V_DEST_RL mds_role; SaAisErrorT rc = SA_AIS_OK; /* Terminate threads and finalize the OI handle */ if (campaign_oi_deactivate(cb) != NCSCC_RC_SUCCESS) { LOG_NO("amf_quiesced_state_handler oi deactivate FAILED, continue"); } /* ** Change the MDS VDSET role to Quiesced. Wait for MDS callback with type ** MDS_CALLBACK_QUIESCED_ACK. Don't change cb->ha_state now. */ mds_role = cb->mds_role; cb->mds_role = V_DEST_RL_QUIESCED; if ((rc = smfd_mds_change_role(cb)) != NCSCC_RC_SUCCESS) { LOG_ER("smfd_mds_change_role [V_DEST_RL_QUIESCED] FAILED"); rc = SA_AIS_ERR_FAILED_OPERATION; cb->mds_role = mds_role; goto done; } cb->amf_invocation_id = invocation; cb->is_quiesced_set = true; done: TRACE_LEAVE(); return rc; }
static uint32_t mds_quiesced_ack(struct ncsmds_callback_info *mds_info) { SMFSV_EVT *smfsv_evt; if (smfd_cb->is_quiesced_set == true) { /** allocate an SMFSV_EVT **/ if (NULL == (smfsv_evt = calloc(1, sizeof(SMFSV_EVT)))) { LOG_NO("calloc FAILED"); goto err; } /** Initialize the Event **/ smfsv_evt->type = SMFSV_EVT_TYPE_SMFD; smfsv_evt->info.smfd.type = SMFD_EVT_QUIESCED_ACK; smfsv_evt->cb_hdl = (uint32_t)mds_info->i_yr_svc_hdl; /* Push the event and we are done */ if (NCSCC_RC_FAILURE == m_NCS_IPC_SEND(&smfd_cb->mbx, smfsv_evt, NCS_IPC_PRIORITY_VERY_HIGH)) { TRACE("ipc send failed"); smfsv_evt_destroy(smfsv_evt); goto err; } } return NCSCC_RC_SUCCESS; err: return NCSCC_RC_FAILURE; }
/**************************************************************************** * Name : fm_mds_node_evt * * Description : Function to process MDS NODE/control events. * * Arguments : pointer to FM CB & MDS_CALLBACK_NODE_EVENT_INFO * * Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE * * Notes : None. *****************************************************************************/ static uint32_t fm_mds_node_evt(FM_CB *cb, MDS_CALLBACK_NODE_EVENT_INFO * node_evt) { uint32_t return_val = NCSCC_RC_SUCCESS; TRACE_ENTER(); switch (node_evt->node_chg) { case NCSMDS_NODE_DOWN: if (node_evt->node_id == cb->peer_node_id && cb->control_tipc) { /* Process NODE_DOWN only if OpenSAF is controling TIPC */ LOG_NO("Node Down event for node id %x:", node_evt->node_id); return_val = fm_send_node_down_to_mbx(cb, node_evt->node_id); } break; case NCSMDS_NODE_UP: break; default: LOG_IN("Wrong MDS event from GFM."); break; } TRACE_LEAVE(); return return_val; }
uns32 amfd_switch_qsd_stdby(AVD_CL_CB *cb) { AVD_AVND *avnd = NULL; uns32 node_id = 0; uns32 status = NCSCC_RC_SUCCESS; TRACE_ENTER(); LOG_NO("Switching Quiesced --> StandBy"); cb->swap_switch = SA_FALSE; if (NCSCC_RC_SUCCESS != (status = avd_mds_set_vdest_role(cb, SA_AMF_HA_STANDBY))) { LOG_ER("Switch Quiesced --> StandBy, Vdest set role failed"); return NCSCC_RC_FAILURE; } /* Change MBCSv role to Standby */ if (NCSCC_RC_SUCCESS != (status = avsv_set_ckpt_role(cb, SA_AMF_HA_STANDBY))) { LOG_ER("Switch Quiesced --> StandBy, MBCSv set role failed"); return NCSCC_RC_FAILURE; } /* Now Dispatch all the messages from the MBCSv mail-box */ if (NCSCC_RC_SUCCESS != (status = avsv_mbcsv_dispatch(cb, SA_DISPATCH_ALL))) { LOG_ER("Switch Quiesced --> StandBy, MBCSv dispatch failed"); return NCSCC_RC_FAILURE; } if (NCSCC_RC_SUCCESS != avd_rde_set_role(SA_AMF_HA_STANDBY)) { LOG_ER("rde role change failed from qsd -> stdby"); } node_id = 0; /* Walk through all the nodes and free PG records. */ while (NULL != (avnd = avd_node_getnext_nodeid(node_id))) { node_id = avnd->node_info.nodeId; avd_pg_node_csi_del_all(cb, avnd); } cb->avail_state_avd = SA_AMF_HA_STANDBY; LOG_NO("Controller switch over done"); saflog(LOG_NOTICE, amfSvcUsrName, "Controller switch over done at %x", cb->node_id_avd); TRACE_LEAVE(); return NCSCC_RC_SUCCESS; }
uns32 amfd_switch_qsd_actv (AVD_CL_CB *cb) { LOG_NO("ROLE SWITCH Quiesced --> Active"); cb->swap_switch = SA_FALSE; if (NCSCC_RC_SUCCESS != avd_rde_set_role(SA_AMF_HA_ACTIVE)) { LOG_ER("rde role change failed from qsd -> actv"); } return amfd_switch_stdby_actv(cb); }
uint32_t rde_set_role(PCS_RDA_ROLE role) { LOG_NO("RDE role set to %s", role_string[role]); rde_cb->ha_role = role; /* Send new role to all RDA client */ rde_rda_send_role(rde_cb->ha_role); return NCSCC_RC_SUCCESS; }
/**************************************************************************** * Name : amf_comp_terminate_callback * * Description : This is the callback function which will be called * when the AMF framework want to terminate SMFND. This does * all required to destroy SMFND(except to unregister from AMF) * * Arguments : invocation - This parameter designated a particular * invocation of this callback function. The * invoke process return invocation when it * responds to the Avilability Management * FrameWork using the saAmfResponse() * function. * compName - A pointer to the name of the component * whose readiness stae the Availability * Management Framework is setting. * * Return Values : None * * Notes : None *****************************************************************************/ static void amf_comp_terminate_callback(SaInvocationT invocation, const SaNameT * compName) { TRACE_ENTER(); saAmfResponse(smfnd_cb->amf_hdl, invocation, SA_AIS_OK); LOG_NO("Received AMF component terminate callback, exiting"); TRACE_LEAVE(); _Exit(EXIT_SUCCESS); }
/**************************************************************************** * Name : immd_amf_comp_terminate_callback * * Description : This function SAF callback function which will be called * when the AMF framework needs to terminate GLSV. This does * all required to destroy GLSV(except to unregister from AMF) * * Arguments : invocation - This parameter designated a particular * invocation of this callback function. The * invoke process return invocation when it * responds to the Avilability Management * FrameWork using the saAmfResponse() * function. * compName - A pointer to the name of the component * whose readiness stae the Availability * Management Framework is setting. * * Return Values : None * * Notes : At present we are just support a simple liveness check. *****************************************************************************/ static void immd_amf_comp_terminate_callback(SaInvocationT invocation, const SaNameT *compName) { IMMD_CB *cb = immd_cb; SaAisErrorT saErr = SA_AIS_OK; LOG_IN("IMMD - AMF Component Termination Callback Invoked, exiting..."); saAmfResponse(cb->amf_hdl, invocation, saErr); immd_mds_unregister(cb); /* unreg with mbcp also ?? */ sleep(1); LOG_NO("Received AMF component terminate callback, exiting"); exit(0); }
static void app_ccb_apply_cb(CcbUtilOperationData_t *opdata) { AVD_APP *app; int i = 0; TRACE_ENTER2("CCB ID %llu, '%s'", opdata->ccbId, opdata->objectName.value); switch (opdata->operationType) { case CCBUTIL_CREATE: app = avd_app_create(&opdata->objectName, opdata->param.create.attrValues); assert(app); app_add_to_model(app); break; case CCBUTIL_MODIFY: { const SaImmAttrModificationT_2 *attr_mod; app = avd_app_get(&opdata->objectName); while ((attr_mod = opdata->param.modify.attrMods[i++]) != NULL) { const SaImmAttrValuesT_2 *attribute = &attr_mod->modAttr; if (!strcmp(attribute->attrName, "saAmfAppType")) { avd_apptype_remove_app(app); app->saAmfAppType = *((SaNameT*)attribute->attrValues[0]); app->app_type = avd_apptype_get(&app->saAmfAppType); avd_apptype_add_app(app); LOG_NO("Changed saAmfAppType to '%s' for '%s'", app->saAmfAppType.value, app->name.value); break; } else assert(0); } break; } case CCBUTIL_DELETE: app = avd_app_get(&opdata->objectName); /* by this time all the SGs and SIs under this * app object should have been *DELETED* just * do a sanity check here */ assert(app->list_of_sg == NULL); assert(app->list_of_si == NULL); avd_app_delete(app); break; default: assert(0); } TRACE_LEAVE(); }
/**************************************************************************** * Name : cpd_amf_comp_terminate_callback * * Description : This function SAF callback function which will be called * when the AMF framework needs to terminate GLSV. This does * all required to destroy GLSV(except to unregister from AMF) * * Arguments : invocation - This parameter designated a particular * invocation of this callback function. The * invoke process return invocation when it * responds to the Avilability Management * FrameWork using the saAmfResponse() * function. * compName - A pointer to the name of the component * whose readiness stae the Availability * Management Framework is setting. * * Return Values : None * * Notes : At present we are just support a simple liveness check. *****************************************************************************/ void cpd_amf_comp_terminate_callback(SaInvocationT invocation, const SaNameT *compName) { CPD_CB *cb = 0; SaAisErrorT saErr = SA_AIS_OK; TRACE_ENTER(); cb = ncshm_take_hdl(NCS_SERVICE_ID_CPD, gl_cpd_cb_hdl); if (cb) { saAmfResponse(cb->amf_hdl, invocation, saErr); ncshm_give_hdl(cb->cpd_hdl); } LOG_NO("Received AMF component terminate callback, exiting"); TRACE_LEAVE(); exit(0); }
/**************************************************************************** * Name : amf_comp_terminate_callback * * Description : This is the callback function which will be called * when the AMF framework needs to terminate LGS. This does * all required to destroy LGS(except to unregister from AMF) * * Arguments : invocation - This parameter designated a particular * invocation of this callback function. The * invoke process return invocation when it * responds to the Availability Management * FrameWork using the saAmfResponse() * function. * compName - A pointer to the name of the component * whose readiness state the Availability * Management Framework is setting. * * Return Values : None * * Notes : None *****************************************************************************/ static void amf_comp_terminate_callback(SaInvocationT invocation, const SaNameT *compName) { TRACE_ENTER(); saAmfResponse(lgs_cb->amf_hdl, invocation, SA_AIS_OK); /* Detach from IPC */ m_NCS_IPC_DETACH(&lgs_mbx, NULL, lgs_cb); /* Disconnect from MDS */ lgs_mds_finalize(lgs_cb); sleep(1); LOG_NO("Received AMF component terminate callback, exiting"); exit(0); }
/** * Check if path is a writeable directory * * @param indata[in] path[] * @param outdata[out] Not used * @param max_outsize[in] Must be 0 * @return 0 if not writable, 1 if writable */ int path_is_writeable_dir_hdl(void *indata, void *outdata, size_t max_outsize) { int is_writeable_dir = 0; struct stat pathstat; char *pathname = (char *) indata; TRACE_ENTER(); TRACE("%s - pathname \"%s\"",__FUNCTION__,pathname); /* Check if the pathname violates security rules e.g. contains ../ */ if (lgs_relative_path_check_ts(pathname) || stat(pathname, &pathstat) != 0) { LOG_NO("Path %s not allowed", pathname); goto done; } /* Check if the path points to a directory */ if (!S_ISDIR(pathstat.st_mode)) { LOG_NO("%s is not a directory", pathname); goto done; } /* Check if we have correct permissions. Note that we check permissions for * real UID */ if (access(pathname, (R_OK | W_OK | X_OK)) != 0) { LOG_NO("permission denied for %s, error %s", pathname, strerror(errno)); goto done; } is_writeable_dir = 1; done: TRACE_LEAVE2("is_writeable_dir = %d",is_writeable_dir); return is_writeable_dir; }
/** * Rename a file * * @param indata[in] old_path[], new_path[] * @param outdata[out] Not used * @param max_outsize[in] Must be 0 * @return (-1) on error, errno is logged */ int rename_file_hdl(void *indata, void *outdata, size_t max_outsize) { int rc = 0; TRACE_ENTER(); size_t old_path_size = *((size_t *) indata); char *old_path = (char *) indata + sizeof(size_t); char *new_path = old_path + old_path_size; if ((rc = rename(old_path, new_path)) == -1) LOG_NO("rename: FAILED - %s", strerror(errno)); TRACE_LEAVE(); return rc; }
/** * USR2 signal handler to enable/disable trace (toggle) * @param sig[in] */ static void sigusr2_handler(int sig) { if (category_mask == 0) { category_mask = CATEGORY_ALL; } else { category_mask = 0; } if (trace_category_set(category_mask) == -1) LOG_ER("trace_category_set failed"); if (category_mask != 0) { LOG_NO("osafntfimcn trace enabled"); } }
/** * Delete config file. * @param indata[in], pathname string * @param outdata[out], always NULL * @param max_outsize[in], must be set to 0 * @return (-1) if error */ int delete_file_hdl(void *indata, void *outdata, size_t max_outsize) { int rc = 0; char *pathname = (char *) indata; TRACE_ENTER(); if ((rc = unlink(pathname)) == -1) { if (errno == ENOENT) rc = 0; else LOG_NO("could not unlink: %s - %s", pathname, strerror(errno)); } TRACE_LEAVE(); return rc; }
/** * Process Node admin operation request from director * * @param cb * @param evt */ static uns32 avnd_evt_node_admin_op_req(AVND_CB *cb, AVND_EVT *evt) { AVSV_D2N_ADMIN_OP_REQ_MSG_INFO *info = &evt->info.avd->msg_info.d2n_admin_op_req_info; uns32 rc = NCSCC_RC_SUCCESS; TRACE_ENTER2("%s op=%u", info->dn.value, info->oper_id); assert( info->msg_id == cb->rcv_msg_id+1 ); cb->rcv_msg_id = info->msg_id; switch(info->oper_id) { default: LOG_NO("%s: unsupported adm op %u", __FUNCTION__, info->oper_id); rc = NCSCC_RC_FAILURE; break; } TRACE_LEAVE(); return rc; }
/**************************************************************************** * Name : fm_get_args * * Description : Parses configuration and store the values in Data str. * * Arguments : Pointer to Control block * * Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE. * * Notes : None. *****************************************************************************/ static uns32 fm_get_args(FM_CB *fm_cb) { char *value; value = getenv("EE_ID"); if (value != NULL) { fm_cb->node_name.length = strlen(value); memcpy(fm_cb->node_name.value, value, fm_cb->node_name.length); LOG_NO("EE_ID : %s", fm_cb->node_name.value); } else fm_cb->node_name.length = 0; /* Update fm_cb configuration fields */ fm_cb->node_id = m_NCS_GET_NODE_ID; fm_cb->active_promote_tmr_val = atoi(getenv("FMS_PROMOTE_ACTIVE_TIMER")); /* Set timer variables */ fm_cb->promote_active_tmr.type = FM_TMR_PROMOTE_ACTIVE; return NCSCC_RC_SUCCESS; }
/**************************************************************************** * Name : plms_amf_comp_terminate_callback * * Description : This is the callback function which will be called * when the AMF framework needs to terminate PLMS. This does * all required operations to destroy PLMS(except to * unregister from AMF) * * Arguments : invocation - This parameter designated a particular * invocation of this callback function. The * invoke process return invocation when it * responds to the Avilability Management * FrameWork using the saAmfResponse() * function. * compName - A pointer to the name of the component * whose readiness stae the Availability * Management Framework is setting. * * Return Values : None * * Notes : At present we are just support a simple liveness check. *****************************************************************************/ void plms_amf_comp_terminate_callback(SaInvocationT invocation, const SaNameT *compName) { PLMS_CB *cb = plms_cb; SaAisErrorT error = SA_AIS_OK; TRACE_ENTER(); m_NCS_LOCK(&cb->cb_lock,NCS_LOCK_WRITE); saAmfResponse(cb->amf_hdl, invocation, error); /* FIXME : Clean up all internal structures */ /* Detach from IPC */ m_NCS_IPC_DETACH(&cb->mbx, NULL, cb); /* Disconnect from MDS */ plms_mds_unregister(); m_NCS_UNLOCK(&cb->cb_lock,NCS_LOCK_WRITE); /* Destroy the cb */ sleep(1); LOG_NO("Received AMF component terminate callback, exiting"); exit(0); }
/****************************************************************************\ * Function: avsv_mbcsv_process_dec_cb * * Purpose: AVSV MBCSV decode call back function. * * Input: arg - MBCSV callback argument pointer. * * Returns: NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE. * * NOTES: * * \**************************************************************************/ static uns32 avsv_mbcsv_process_dec_cb(AVD_CL_CB *cb, NCS_MBCSV_CB_ARG *arg) { uns32 status = NCSCC_RC_SUCCESS; switch (arg->info.decode.i_msg_type) { case NCS_MBCSV_MSG_ASYNC_UPDATE: { if ((arg->info.decode.i_peer_version < AVD_MBCSV_SUB_PART_VERSION_3) && (arg->info.decode.i_reo_type >= AVSV_CKPT_AVD_SI_TRANS)) arg->info.decode.i_reo_type ++; /* Decode Async update message */ if (AVD_STBY_IN_SYNC == cb->stby_sync_state) { if (AVSV_SYNC_COMMIT != arg->info.decode.i_reo_type) { /* * Enqueue async update message till sync commit message is * received from the Active. */ avsv_enqueue_async_update_msgs(cb, &arg->info.decode); } else { /* * we have received sync commit message. So process all async * ckpt updates received till now. */ avsv_dequeue_async_update_msgs(cb, TRUE); } } else { /* Nothing is there to decode in this case */ if (AVSV_SYNC_COMMIT == arg->info.decode.i_reo_type) return status; /* * Cold sync is in progress, then drop the async update for which * cold sync response are yet to come. */ if (NCSCC_RC_SUCCESS != avsv_validate_reo_type_in_csync(cb, arg->info.decode.i_reo_type)) { /* Free userbuff and return without decoding */ ncs_reset_uba(&arg->info.decode.i_uba); break; } /* * During cold sync operation or in case of warm sync failure * and standby require to be sync-up, process the async updates as and * when they received. Dont enqueue them. */ if (arg->info.decode.i_reo_type < AVSV_CKPT_MSG_MAX) { status = avsv_dec_ckpt_data_func_list[arg->info.decode.i_reo_type] (cb, &arg->info.decode); } else { LOG_ER("%s: invalid type %u", __FUNCTION__, arg->info.encode.io_reo_type); status = NCSCC_RC_FAILURE; } } } break; case NCS_MBCSV_MSG_COLD_SYNC_REQ: { /* * Decode Cold Sync request message * Nothing is there to decode. */ TRACE("COLD_SYNC_REQ"); if (cb->init_state < AVD_INIT_DONE) { TRACE("invalid init state (%u) for cold sync req", cb->init_state); status = NCSCC_RC_FAILURE; } } break; case NCS_MBCSV_MSG_COLD_SYNC_RESP: case NCS_MBCSV_MSG_COLD_SYNC_RESP_COMPLETE: { if ((arg->info.decode.i_peer_version < AVD_MBCSV_SUB_PART_VERSION_3) && (arg->info.decode.i_reo_type >= AVSV_CKPT_AVD_SI_TRANS)) arg->info.decode.i_reo_type ++; /* Decode Cold Sync Response message */ status = avsv_decode_cold_sync_rsp(cb, &arg->info.decode); if (NCSCC_RC_SUCCESS != status) { LOG_ER("%s: cold sync decode failed %u", __FUNCTION__, status); (void) avd_data_clean_up(cb); status = NCSCC_RC_FAILURE; break; } /* * If we have received cold sync complete message then mark standby * as in sync. */ if ((NCS_MBCSV_MSG_COLD_SYNC_RESP_COMPLETE == arg->info.decode.i_msg_type) && (NCSCC_RC_SUCCESS == status)) { LOG_NO("Cold sync complete!"); cb->stby_sync_state = AVD_STBY_IN_SYNC; } cb->synced_reo_type = arg->info.decode.i_reo_type; } break; case NCS_MBCSV_MSG_WARM_SYNC_REQ: { /* * Decode Warm Sync Request message * Nothing is there to decode. */ TRACE("warm sync req"); } break; case NCS_MBCSV_MSG_WARM_SYNC_RESP: case NCS_MBCSV_MSG_WARM_SYNC_RESP_COMPLETE: { if ((arg->info.decode.i_peer_version < AVD_MBCSV_SUB_PART_VERSION_3) && (arg->info.decode.i_reo_type >= AVSV_CKPT_AVD_SI_TRANS)) arg->info.decode.i_reo_type ++; /* Decode Warm Sync Response message */ status = avsv_decode_warm_sync_rsp(cb, &arg->info.decode); /* If we find mismatch in data or warm sync fails set in_sync to FALSE */ if (NCSCC_RC_FAILURE == status) { LOG_ER("%s: warm sync decode failed %u", __FUNCTION__, status); cb->stby_sync_state = AVD_STBY_OUT_OF_SYNC; } } break; case NCS_MBCSV_MSG_DATA_REQ: { /* Decode Data request message */ status = avsv_decode_data_req(cb, &arg->info.decode); } break; case NCS_MBCSV_MSG_DATA_RESP: case NCS_MBCSV_MSG_DATA_RESP_COMPLETE: { if ((arg->info.decode.i_peer_version < AVD_MBCSV_SUB_PART_VERSION_3) && (arg->info.decode.i_reo_type >= AVSV_CKPT_AVD_SI_TRANS)) arg->info.decode.i_reo_type ++; /* Decode Data response and data response complete message */ status = avsv_decode_data_sync_rsp(cb, &arg->info.decode); if (NCSCC_RC_SUCCESS != status) { LOG_ER("%s: data resp decode failed %u", __FUNCTION__, status); avd_data_clean_up(cb); /* * Now send data request, which will sync Standby with Active. */ if (NCSCC_RC_SUCCESS != avsv_send_data_req(cb)) break; break; } if (NCS_MBCSV_MSG_DATA_RESP_COMPLETE == arg->info.decode.i_msg_type) { cb->stby_sync_state = AVD_STBY_IN_SYNC; LOG_IN("Standby in sync"); } } break; default: LOG_ER("%s: invalid msg type %u", __FUNCTION__, arg->info.decode.i_msg_type); status = NCSCC_RC_FAILURE; break; } return status; }
/** * Make directory. Handles creation of directory path. * Creates the relative directory in the directory given by the root path. * If the root path does not exist/is not available a root path is created * based on the default path. * * TBD (Separate ticket): * Default path taken from the configuration define PKGLOGDIR. * Settings: Read, Write, Exec for User, Group, Other * * @param indata[in], Type mld_in_t * @param outdata[out], char *, new root dir if changed otherwise '\0' * @param max_outsize[in] * @return (-1) if error */ int make_log_dir_hdl(void *indata, void *outdata, size_t max_outsize) { int rc = 0; int mldh_rc = 0; mld_in_t *params_in = (mld_in_t *) indata; char *out_path = (char *) outdata; char *relpath = params_in->rel_path; char *rootpath = params_in->root_dir; char dir_to_make[PATH_MAX]; char mpath[PATH_MAX]; char *spath_p; char *epath_p; struct stat statbuf; int n; TRACE_ENTER(); TRACE("rootpath \"%s\"",rootpath); TRACE("relpath \"%s\"",relpath); /* * Create root directory if it does not exists. * TBD. Handle via separate ticket * (Create the default root path regardless of what is set in the * configuration object.) */ out_path[0] = '\0'; if (lstat(rootpath, &statbuf) != 0) { #if 0 rootpath = PKGLOGDIR; #endif strncpy(out_path, rootpath, max_outsize); n = snprintf(out_path, max_outsize, "%s", rootpath); if (n >= max_outsize) { LOG_WA("Invalid root path > max_outsize"); mldh_rc = -1; goto done; } LOG_NO("LOG Root path does not exist. Will be created"); TRACE("%s - create rootpath \"%s\"",__FUNCTION__,rootpath); } /* * Create root path without preceding '/' and ending '/' * Example: ro1/ro2/ro3 * Check that not > PATH_MAX */ n = snprintf(mpath, PATH_MAX, "%s", rootpath); if (n >= PATH_MAX) { LOG_WA("Could not create path, rootpath > PATH_MAX"); mldh_rc = -1; goto done; } char *rootpp = mpath; while (*rootpp == '/') rootpp++; /* Remove preceding '/' */ while (mpath[strlen(mpath)-1] == '/') { /* Remove trailing '/' if needed */ mpath[strlen(mpath)-1] = '\0'; } /* * Add relative path. Shall end with '/' * Example: ro1/ro2/ro3/re1/re2/re3/ * Check that not > PATH_MAX */ if (relpath[strlen(relpath)-1] != '/') { n = snprintf(dir_to_make, PATH_MAX, "/%s/%s/", rootpp, relpath); } else { n = snprintf(dir_to_make, PATH_MAX, "/%s/%s", rootpp, relpath); } if (n >= PATH_MAX) { LOG_WA("Could not create path > PATH_MAX"); mldh_rc = -1; goto done; } TRACE("%s - Path to create \"%s\"",__FUNCTION__,dir_to_make); /* Create the path */ int path_len = 0; spath_p = epath_p = dir_to_make; while ((epath_p = strchr(epath_p, '/')) != NULL) { if (epath_p == spath_p) { epath_p++; continue; /* Don't try to create path "/" */ } epath_p++; path_len = epath_p - spath_p; strncpy(mpath, spath_p, path_len); mpath[path_len] = '\0'; rc = mkdir(mpath, S_IRWXU | S_IRWXG | S_IRWXO); if ((rc != 0) && (errno != EEXIST)) { LOG_ER("Making directory error %s",strerror(errno)); mldh_rc = -1; goto done; } } TRACE("%s - Dir \"%s\" created",__FUNCTION__, mpath); done: TRACE_LEAVE2("mldh_rc = %u", mldh_rc); return mldh_rc; }
/** * Create a configuration file. * Creates the file, write its content and close the file * * @param indata[in] ccfh_t, logFileFormat string, file_path string * @param outdata[out] Not used * @param max_outsize[in] Must be 0 * @return (-1) on error, errno is logged */ int create_config_file_hdl(void *indata, void *outdata, size_t max_outsize) { int rc = 0; FILE *filp; ccfh_t *params_in = (ccfh_t *) indata; char *logFileFormat = (char *) (indata + sizeof(ccfh_t)); char *file_path = (logFileFormat + params_in->logFileFormat_size); TRACE_ENTER(); TRACE("%s - file_path \"%s\"",__FUNCTION__,file_path); fopen_retry: if ((filp = fopen(file_path, "w")) == NULL) { if (errno == EINTR) goto fopen_retry; LOG_NO("Could not open '%s' - %s", file_path, strerror(errno)); rc = -1; goto done; } /* version */ if ((rc = fprintf(filp, "%s %c.%d.%d\n", LOG_VER_EXP, params_in->version.releaseCode, params_in->version.majorVersion, params_in->version.minorVersion)) == -1) { TRACE("%s - Print version failed",__FUNCTION__); goto fprintf_done; } /* Format expression */ if ((rc = fprintf(filp, "%s%s\n", FMAT_EXP, logFileFormat)) == -1) { TRACE("%s - Print Format expression failed",__FUNCTION__); goto fprintf_done; } /* Max logfile size */ if ((rc = fprintf(filp, "%s %llu\n", CFG_EXP_MAX_FILE_SIZE, params_in->maxLogFileSize)) == -1) { TRACE("%s - Print Max logfile size failed",__FUNCTION__); goto fprintf_done; } /* Fixed log record size */ if ((rc = fprintf(filp, "%s %d\n", CFG_EXP_FIXED_LOG_REC_SIZE, params_in->fixedLogRecordSize)) == -1) { TRACE("%s - Print Fixed log record size failed",__FUNCTION__); goto fprintf_done; } /* Log file full action */ rc = fprintf(filp, "%s %s %d\n", CFG_EXP_LOG_FULL_ACTION, DEFAULT_ALM_ACTION, params_in->maxFilesRotated); if (rc == -1) { TRACE("%s - Print version failed",__FUNCTION__); } fprintf_done: if (rc == -1) LOG_NO("Could not write to \"%s\"", file_path); fclose_retry: if ((rc = fclose(filp)) == -1) { if (errno == EINTR) goto fclose_retry; LOG_NO("Could not close \"%s\" - \"%s\"", file_path, strerror(errno)); } done: TRACE_LEAVE2("rc = %d", rc); return rc; }
/** * Handler for mds register requests * Note: executed by and in context of the auth thread! * Communicates with the main thread (where the * real work is done) to get outcome of initialization request which is then * sent back to the client. * @param fd * @param creds credentials for client */ static void mds_register_callback(int fd, const struct ucred *creds) { uint8_t buf[32]; uint8_t *p = buf; TRACE_ENTER2("fd:%d, pid:%u", fd, creds->pid); int n = recv(fd, buf, sizeof(buf), 0); if (n == -1) { syslog(LOG_ERR, "%s: recv failed - %s", __FUNCTION__, strerror(errno)); goto done; } if (n != 16) { syslog(LOG_ERR, "%s: recv failed - %d bytes", __FUNCTION__, n); goto done; } int type = ncs_decode_32bit(&p); NCSMDS_SVC_ID svc_id = ncs_decode_32bit(&p); MDS_DEST mds_dest = ncs_decode_64bit(&p); TRACE("mds: received %d from %"PRIx64", pid %d", type, mds_dest, creds->pid); if (type == MDS_REGISTER_REQ) { osaf_mutex_lock_ordie(&gl_mds_library_mutex); MDS_PROCESS_INFO *info = mds_process_info_get(mds_dest, svc_id); if (info == NULL) { MDS_PROCESS_INFO *info = calloc(1, sizeof(MDS_PROCESS_INFO)); osafassert(info); info->mds_dest = mds_dest; info->svc_id = svc_id; info->uid = creds->uid; info->pid = creds->pid; info->gid = creds->gid; int rc = mds_process_info_add(info); osafassert(rc == NCSCC_RC_SUCCESS); } else { /* when can this happen? */ LOG_NO("%s: dest %"PRIx64" already exist", __FUNCTION__, mds_dest); // just update credentials info->uid = creds->uid; info->pid = creds->pid; info->gid = creds->gid; } osaf_mutex_unlock_ordie(&gl_mds_library_mutex); p = buf; uint32_t sz = ncs_encode_32bit(&p, MDS_REGISTER_RESP); sz += ncs_encode_32bit(&p, 0); // result OK if ((n = send(fd, buf, sz, 0)) == -1) syslog(LOG_ERR, "%s: send to pid %d failed - %s", __FUNCTION__, creds->pid, strerror(errno)); } else if (type == MDS_UNREGISTER_REQ) { osaf_mutex_lock_ordie(&gl_mds_library_mutex); MDS_PROCESS_INFO *info = mds_process_info_get(mds_dest, svc_id); if (info != NULL) { (void)mds_process_info_del(info); } osaf_mutex_unlock_ordie(&gl_mds_library_mutex); p = buf; uint32_t sz = ncs_encode_32bit(&p, MDS_UNREGISTER_RESP); sz += ncs_encode_32bit(&p, 0); // result OK if ((n = send(fd, buf, sz, 0)) == -1) syslog(LOG_ERR, "%s: send to pid %d failed - %s", __FUNCTION__, creds->pid, strerror(errno)); } else { syslog(LOG_ERR, "%s: recv failed - wrong type %d", __FUNCTION__, type); goto done; } done: TRACE_LEAVE(); }
/**************************************************************************** Name : avnd_evt_avd_operation_request_msg Description : This routine processes the operation request message from AvD. These messages are generated in response to configuration requests to AvD that modify a single object. Arguments : cb - ptr to the AvND control block evt - ptr to the AvND event Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE Notes : None. ******************************************************************************/ uns32 avnd_evt_avd_operation_request_evh(AVND_CB *cb, AVND_EVT *evt) { AVSV_D2N_OPERATION_REQUEST_MSG_INFO *info; AVSV_PARAM_INFO *param; AVND_MSG msg; uns32 rc = NCSCC_RC_SUCCESS; info = &evt->info.avd->msg_info.d2n_op_req; param = &info->param_info; TRACE_ENTER2("Class=%u, action=%u", param->class_id, param->act); /* dont process unless AvD is up */ if (!m_AVND_CB_IS_AVD_UP(cb)) goto done; assert(info->msg_id == (cb->rcv_msg_id + 1)); cb->rcv_msg_id = info->msg_id; switch (param->class_id) { case AVSV_SA_AMF_NODE: rc = avnd_node_oper_req(cb, param); break; case AVSV_SA_AMF_SG: rc = avnd_sg_oper_req(cb, param); break; case AVSV_SA_AMF_SU: rc = avnd_su_oper_req(cb, param); break; case AVSV_SA_AMF_COMP: rc = avnd_comp_oper_req(cb, param); break; case AVSV_SA_AMF_HEALTH_CHECK: rc = avnd_hc_oper_req(cb, param); break; default: LOG_NO("%s: Unknown class ID %u", __FUNCTION__, param->class_id); rc = NCSCC_RC_FAILURE; break; } /* Send the response to avd. */ if (info->node_id == cb->node_info.nodeId) { memset(&msg, 0, sizeof(AVND_MSG)); msg.info.avd = calloc(1, sizeof(AVSV_DND_MSG)); if (!msg.info.avd) { LOG_ER("calloc FAILED"); assert(0); } msg.type = AVND_MSG_AVD; msg.info.avd->msg_type = AVSV_N2D_OPERATION_REQUEST_MSG; msg.info.avd->msg_info.n2d_op_req.msg_id = ++(cb->snd_msg_id); msg.info.avd->msg_info.n2d_op_req.node_id = cb->node_info.nodeId; msg.info.avd->msg_info.n2d_op_req.param_info = *param; msg.info.avd->msg_info.n2d_op_req.error = rc; rc = avnd_di_msg_send(cb, &msg); if (NCSCC_RC_SUCCESS == rc) msg.info.avd = 0; // TODO Mem leak? else LOG_ER("avnd_di_msg_send FAILED"); avnd_msg_content_free(cb, &msg); } done: TRACE_LEAVE(); return rc; }