/******************************************************************** * FUNCTION do_release_locks (local RPC) * * release all the locks on the server * * INPUTS: * server_cb == server control block to use * rpc == RPC method for the history command * line == CLI input in progress * len == offset into line buffer to start parsing * * RETURNS: * status *********************************************************************/ status_t do_release_locks (server_cb_t *server_cb, obj_template_t *rpc, const xmlChar *line, uint32 len) { ses_cb_t *scb; val_value_t *valset; uint32 locks_timeout, retry_interval; boolean cleanup, done, needed; status_t res; if (!server_cb->locks_active) { log_error("\nError: locks are not active"); return ERR_NCX_OPERATION_FAILED; } scb = mgr_ses_get_scb(server_cb->mysid); if (scb == NULL) { log_error("\nError: active session dropped, cannot lock"); return ERR_NCX_OPERATION_FAILED; } locks_timeout = server_cb->locks_timeout; retry_interval = server_cb->locks_retry_interval; cleanup = TRUE; res = NO_ERR; valset = get_valset(server_cb, rpc, &line[len], &res); if (res == NO_ERR || res == ERR_NCX_SKIPPED) { /* start the auto-unlock procedure */ server_cb->locks_timeout = locks_timeout; server_cb->locks_retry_interval = retry_interval; server_cb->locks_cleanup = cleanup; needed = setup_unlock_cbs(server_cb); if (LOGINFO && needed) { log_info("\nSending <unlock> operations for release-locks...\n"); } if (needed) { done = FALSE; res = handle_release_locks_request_to_server(server_cb, TRUE, &done); if (done) { /* need to close the session or report fatal error */ clear_lock_cbs(server_cb); } } } if (valset != NULL) { val_free_value(valset); } return res; } /* do_release_locks */
/******************************************************************** * FUNCTION do_show_session (sub-mode of local RPC) * * show session startup screen * * INPUTS: * server_cb == server control block to use * mode == help mode *********************************************************************/ static void do_show_session (server_cb_t *server_cb, help_mode_t mode) { session_cb_t *session_cb = server_cb->cur_session_cb; ses_cb_t *scb = mgr_ses_get_scb(session_cb->mysid); if (scb == NULL) { /* session was dropped */ log_write("\nError: No session available." " Not connected to any server.\n"); return; } report_capabilities(server_cb, session_cb, scb, FALSE, mode); log_write("\n"); } /* do_show_session */
/******************************************************************** * FUNCTION get_del_op * * Check if remove operation allowed, or just delete * * INPUTS: * session_cb == session control block to use * RETURNS: * delete operation to use (OP_EDITOP_DELETE or OP_EDITOP_REMOVE) *********************************************************************/ static op_editop_t get_del_op (session_cb_t *session_cb) { ses_cb_t *scb = mgr_ses_get_scb(session_cb->mysid); if (scb == NULL) { return OP_EDITOP_DELETE; } switch (ses_get_protocol(scb)) { case NCX_PROTO_NETCONF10: return OP_EDITOP_DELETE; case NCX_PROTO_NETCONF11: return OP_EDITOP_REMOVE; default: return OP_EDITOP_DELETE; } } /* get_del_op */
/******************************************************************** * FUNCTION setup_lock_cbs * * Setup the lock state info in all the lock control blocks * in the specified server_cb; call when a new sesion is started * * INPUTS: * server_cb == server control block to use *********************************************************************/ static void setup_lock_cbs (server_cb_t *server_cb) { ses_cb_t *scb; mgr_scb_t *mscb; ncx_cfg_t cfg_id; scb = mgr_ses_get_scb(server_cb->mysid); if (scb == NULL) { log_error("\nError: active session dropped, cannot lock"); return; } mscb = (mgr_scb_t *)scb->mgrcb; server_cb->locks_active = TRUE; server_cb->locks_waiting = FALSE; server_cb->locks_cur_cfg = NCX_CFGID_RUNNING; for (cfg_id = NCX_CFGID_RUNNING; cfg_id <= NCX_CFGID_STARTUP; cfg_id++) { server_cb->lock_cb[cfg_id].lock_state = LOCK_STATE_IDLE; server_cb->lock_cb[cfg_id].lock_used = FALSE; server_cb->lock_cb[cfg_id].start_time = (time_t)0; server_cb->lock_cb[cfg_id].last_msg_time = (time_t)0; } /* always request the lock on running */ server_cb->lock_cb[NCX_CFGID_RUNNING].lock_used = TRUE; server_cb->lock_cb[NCX_CFGID_CANDIDATE].lock_used = (cap_std_set(&mscb->caplist, CAP_STDID_CANDIDATE)) ? TRUE : FALSE; server_cb->lock_cb[NCX_CFGID_STARTUP].lock_used = (cap_std_set(&mscb->caplist, CAP_STDID_STARTUP)) ? TRUE : FALSE; } /* setup_lock_cbs */
/******************************************************************** * FUNCTION send_discard_changes_pdu_to_server * * Send a <discard-changes> operation to the server * * INPUTS: * server_cb == server control block to use * * RETURNS: * status *********************************************************************/ status_t send_discard_changes_pdu_to_server (server_cb_t *server_cb) { obj_template_t *rpc; mgr_rpc_req_t *req; val_value_t *reqdata; ses_cb_t *scb; status_t res; xmlns_id_t obj_nsid; req = NULL; reqdata = NULL; res = NO_ERR; if (LOGDEBUG) { log_debug("\nSending <discard-changes> request"); } rpc = ncx_find_object(get_netconf_mod(server_cb), NCX_EL_DISCARD_CHANGES); if (!rpc) { return SET_ERROR(ERR_NCX_DEF_NOT_FOUND); } obj_nsid = obj_get_nsid(rpc); /* construct a method node */ reqdata = xml_val_new_flag(obj_get_name(rpc), obj_nsid); if (!reqdata) { log_error("\nError allocating a new RPC request"); return ERR_INTERNAL_MEM; } scb = mgr_ses_get_scb(server_cb->mysid); if (!scb) { res = SET_ERROR(ERR_INTERNAL_PTR); } else { req = mgr_rpc_new_request(scb); if (!req) { res = ERR_INTERNAL_MEM; log_error("\nError allocating a new RPC request"); } else { req->data = reqdata; req->rpc = rpc; req->timeout = server_cb->timeout; } } /* if all OK, send the RPC request */ if (res == NO_ERR) { if (LOGDEBUG2) { log_debug2("\nabout to send RPC request with reqdata:"); val_dump_value_max(reqdata, 0, server_cb->defindent, DUMP_VAL_LOG, server_cb->display_mode, FALSE, FALSE); } /* the request will be stored if this returns NO_ERR */ res = mgr_rpc_send_request(scb, req, yangcli_reply_handler); if (res == NO_ERR) { server_cb->command_mode = CMD_MODE_AUTODISCARD; } } /* cleanup and set next state */ if (res != NO_ERR) { if (req) { mgr_rpc_free_request(req); } else if (reqdata) { val_free_value(reqdata); } } else { server_cb->state = MGR_IO_ST_CONN_RPYWAIT; } return res; } /* send_discard_changes_pdu_to_server */
/******************************************************************** * FUNCTION do_get_locks (local RPC) * * get all the locks on the server * * INPUTS: * server_cb == server control block to use * rpc == RPC method for the history command * line == CLI input in progress * len == offset into line buffer to start parsing * * RETURNS: * status *********************************************************************/ status_t do_get_locks (server_cb_t *server_cb, obj_template_t *rpc, const xmlChar *line, uint32 len) { ses_cb_t *scb; val_value_t *valset, *parm; uint32 locks_timeout, retry_interval; boolean cleanup, done; status_t res; if (server_cb->locks_active) { log_error("\nError: locks are already active"); return ERR_NCX_OPERATION_FAILED; } if (server_cb->state != MGR_IO_ST_CONN_IDLE) { log_error("\nError: no active session to lock"); return ERR_NCX_OPERATION_FAILED; } scb = mgr_ses_get_scb(server_cb->mysid); if (scb == NULL) { log_error("\nError: active session dropped, cannot lock"); return ERR_NCX_OPERATION_FAILED; } locks_timeout = server_cb->locks_timeout; retry_interval = server_cb->locks_retry_interval; cleanup = TRUE; res = NO_ERR; valset = get_valset(server_cb, rpc, &line[len], &res); if (valset && res == NO_ERR) { /* get the overall lock timeout */ parm = val_find_child(valset, YANGCLI_MOD, YANGCLI_LOCK_TIMEOUT); if (parm && parm->res == NO_ERR) { locks_timeout = VAL_UINT(parm); } /* get the retry interval between failed locks */ parm = val_find_child(valset, YANGCLI_MOD, YANGCLI_RETRY_INTERVAL); if (parm && parm->res == NO_ERR) { retry_interval = VAL_UINT(parm); } /* get the auto-cleanup flag */ parm = val_find_child(valset, YANGCLI_MOD, YANGCLI_CLEANUP); if (parm && parm->res == NO_ERR) { cleanup = VAL_BOOL(parm); } } /* start the auto-lock procedure */ setup_lock_cbs(server_cb); server_cb->locks_timeout = locks_timeout; server_cb->locks_retry_interval = retry_interval; server_cb->locks_cleanup = cleanup; done = FALSE; if (LOGINFO) { log_info("\nSending <lock> operations for get-locks...\n"); } res = handle_get_locks_request_to_server(server_cb, TRUE, &done); if (res != NO_ERR && done) { /* need to undo the whole thing; whatever got done */ } if (valset != NULL) { val_free_value(valset); } return res; } /* do_get_locks */
/******************************************************************** * FUNCTION send_lock_pdu_to_server * * Send a <lock> or <unlock> operation to the server * * INPUTS: * server_cb == server control block to use * lockcb == lock control block to use within server_cb * islock == TRUE for lock; FALSE for unlock * * RETURNS: * status *********************************************************************/ static status_t send_lock_pdu_to_server (server_cb_t *server_cb, lock_cb_t *lockcb, boolean islock) { obj_template_t *rpc, *input; mgr_rpc_req_t *req; val_value_t *reqdata, *targetval, *parmval; ses_cb_t *scb; status_t res; xmlns_id_t obj_nsid; req = NULL; reqdata = NULL; res = NO_ERR; if (LOGDEBUG) { log_debug("\nSending <%s> request", (islock) ? NCX_EL_LOCK : NCX_EL_UNLOCK); } if (islock) { rpc = ncx_find_object(get_netconf_mod(server_cb), NCX_EL_LOCK); } else { rpc = ncx_find_object(get_netconf_mod(server_cb), NCX_EL_UNLOCK); } if (!rpc) { return SET_ERROR(ERR_NCX_DEF_NOT_FOUND); } obj_nsid = obj_get_nsid(rpc); /* get the 'input' section container */ input = obj_find_child(rpc, NULL, YANG_K_INPUT); if (!input) { return SET_ERROR(ERR_NCX_DEF_NOT_FOUND); } /* construct a method + parameter tree */ reqdata = xml_val_new_struct(obj_get_name(rpc), obj_nsid); if (!reqdata) { log_error("\nError allocating a new RPC request"); return ERR_INTERNAL_MEM; } /* set the [un]lock/input/target node XML namespace */ targetval = xml_val_new_struct(NCX_EL_TARGET, obj_nsid); if (!targetval) { log_error("\nError allocating a new RPC request"); val_free_value(reqdata); return ERR_INTERNAL_MEM; } else { val_add_child(targetval, reqdata); } parmval = xml_val_new_flag(lockcb->config_name, obj_nsid); if (!parmval) { val_free_value(reqdata); return ERR_INTERNAL_MEM; } else { val_add_child(parmval, targetval); } scb = mgr_ses_get_scb(server_cb->mysid); if (!scb) { res = SET_ERROR(ERR_INTERNAL_PTR); } else { req = mgr_rpc_new_request(scb); if (!req) { res = ERR_INTERNAL_MEM; log_error("\nError allocating a new RPC request"); } else { req->data = reqdata; req->rpc = rpc; req->timeout = server_cb->timeout; } } /* if all OK, send the RPC request */ if (res == NO_ERR) { if (LOGDEBUG2) { log_debug2("\nabout to send RPC request with reqdata:"); val_dump_value_max(reqdata, 0, server_cb->defindent, DUMP_VAL_LOG, server_cb->display_mode, FALSE, FALSE); } /* the request will be stored if this returns NO_ERR */ res = mgr_rpc_send_request(scb, req, yangcli_reply_handler); if (res == NO_ERR) { if (islock) { lockcb->lock_state = LOCK_STATE_REQUEST_SENT; } else { lockcb->lock_state = LOCK_STATE_RELEASE_SENT; } (void)uptime(&lockcb->last_msg_time); server_cb->locks_cur_cfg = lockcb->config_id; } } /* cleanup and set next state */ if (res != NO_ERR) { if (req) { mgr_rpc_free_request(req); } else if (reqdata) { val_free_value(reqdata); } } else { server_cb->state = MGR_IO_ST_CONN_RPYWAIT; } return res; } /* send_lock_pdu_to_server */