/******************************************************************** * FUNCTION mgr_cap_set_caps * * Initialize the NETCONF manager capabilities * * TEMP !!! JUST SET EVERYTHING, WILL REALLY GET FROM MGR STARTUP * * INPUTS: * none * RETURNS: * NO_ERR if all goes well *********************************************************************/ status_t mgr_cap_set_caps (void) { val_value_t *oldcaps, *newcaps; cap_list_t *oldmycaps,*newmycaps; xmlns_id_t nc_id; status_t res; res = NO_ERR; newcaps = NULL; nc_id = xmlns_nc_id(); oldcaps = mgr_caps; oldmycaps = my_mgr_caps; /* get a new cap_list */ newmycaps = cap_new_caplist(); if (!newmycaps) { res = ERR_INTERNAL_MEM; } /* get a new val_value_t cap list for manager <hello> messages */ if (res == NO_ERR) { newcaps = xml_val_new_struct(NCX_EL_CAPABILITIES, nc_id); if (!newcaps) { res = ERR_INTERNAL_MEM; } } /* add capability for NETCONF version 1.0 support */ if (res == NO_ERR) { res = cap_add_std(newmycaps, CAP_STDID_V1); if (res == NO_ERR) { res = cap_add_stdval(newcaps, CAP_STDID_V1); } } /* check the return value */ if (res != NO_ERR) { /* toss the new, put back the old */ cap_free_caplist(newmycaps); val_free_value(newcaps); my_mgr_caps = oldmycaps; mgr_caps = oldcaps; } else { /* toss the old, install the new */ if (oldmycaps) { cap_free_caplist(oldmycaps); } if (oldcaps) { val_free_value(oldcaps); } my_mgr_caps = newmycaps; mgr_caps = newcaps; } return res; } /* mgr_cap_set_caps */
/******************************************************************** * FUNCTION mgr_cap_get_ses_capsval * * Get the NETCONF manager capabilities ain val_value_t format * for a specific session, v2 supports base1.0 and/or base1.1 * INPUTS: * scb == session control block to use * RETURNS: * MALLOCED pointer to the manager caps list to use * and then discard with val_free_value *********************************************************************/ val_value_t * mgr_cap_get_ses_capsval (ses_cb_t *scb) { val_value_t *newcaps; xmlns_id_t nc_id; status_t res; nc_id = xmlns_nc_id(); res = NO_ERR; /* get a new val_value_t cap list for manager <hello> messages */ newcaps = xml_val_new_struct(NCX_EL_CAPABILITIES, nc_id); if (newcaps == NULL) { return NULL; } /* add capability for NETCONF version 1.0 support */ if (ses_protocol_requested(scb, NCX_PROTO_NETCONF10)) { res = cap_add_stdval(newcaps, CAP_STDID_V1); } /* add capability for NETCONF version 1.1 support */ if (res == NO_ERR && ses_protocol_requested(scb, NCX_PROTO_NETCONF11)) { res = cap_add_stdval(newcaps, CAP_STDID_V11); } /* check the return value */ if (res != NO_ERR) { val_free_value(newcaps); newcaps = NULL; } return newcaps;; } /* mgr_cap_get_ses_capsval */
/******************************************************************** * 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 */
/******************************************************************** * FUNCTION agt_cap_set_caps * * Initialize the NETCONF agent capabilities * * INPUTS: * agttarg == the target of edit-config for this agent * agtstart == the type of startup configuration for this agent * defstyle == default with-defaults style for the entire agent * * RETURNS: * NO_ERR if all goes well *********************************************************************/ status_t agt_cap_set_caps (ncx_agttarg_t agttarg, ncx_agtstart_t agtstart, const xmlChar *defstyle) { xmlns_id_t nc_id = xmlns_nc_id(); status_t res = NO_ERR; val_value_t *newcaps = NULL; val_value_t *oldcaps = agt_caps; cap_list_t *oldmycaps = my_agt_caps; const agt_profile_t *agt_profile = agt_get_profile(); /* get a new cap_list */ cap_list_t *newmycaps = cap_new_caplist(); if (!newmycaps) { res = ERR_INTERNAL_MEM; } /* get a new val_value_t cap list for agent <hello> messages */ if (res == NO_ERR) { newcaps = xml_val_new_struct(NCX_EL_CAPABILITIES, nc_id); if (!newcaps) { res = ERR_INTERNAL_MEM; } } /* add capability for NETCONF version 1.0 and/or 1.1 support */ if (res == NO_ERR) { if (ncx_protocol_enabled(NCX_PROTO_NETCONF10)) { res = cap_add_std(newmycaps, CAP_STDID_V1); if (res == NO_ERR) { res = cap_add_stdval(newcaps, CAP_STDID_V1); } } if (ncx_protocol_enabled(NCX_PROTO_NETCONF11)) { res = cap_add_std(newmycaps, CAP_STDID_V11); if (res == NO_ERR) { res = cap_add_stdval(newcaps, CAP_STDID_V11); } } } if (res == NO_ERR) { /* set the capabilities based on the native target */ switch (agttarg) { case NCX_AGT_TARG_RUNNING: res = cap_add_std(newmycaps, CAP_STDID_WRITE_RUNNING); if (res == NO_ERR) { res = cap_add_stdval(newcaps, CAP_STDID_WRITE_RUNNING); } break; case NCX_AGT_TARG_CANDIDATE: res = cap_add_std(newmycaps, CAP_STDID_CANDIDATE); if (res == NO_ERR) { res = cap_add_stdval(newcaps, CAP_STDID_CANDIDATE); } if (res == NO_ERR) { if (ncx_protocol_enabled(NCX_PROTO_NETCONF10)) { res = cap_add_std(newmycaps, CAP_STDID_CONF_COMMIT); if (res == NO_ERR) { res = cap_add_stdval(newcaps, CAP_STDID_CONF_COMMIT); } } if (ncx_protocol_enabled(NCX_PROTO_NETCONF11)) { res = cap_add_std(newmycaps, CAP_STDID_CONF_COMMIT11); if (res == NO_ERR) { res = cap_add_stdval(newcaps, CAP_STDID_CONF_COMMIT11); } } } break; default: res = SET_ERROR(ERR_INTERNAL_VAL); break; } } if (res == NO_ERR) { /* set the rollback-on-error capability */ res = cap_add_std(newmycaps, CAP_STDID_ROLLBACK_ERR); if (res == NO_ERR) { res = cap_add_stdval(newcaps, CAP_STDID_ROLLBACK_ERR); } } if (res == NO_ERR) { if (agt_profile->agt_usevalidate) { /* set the validate capability */ if (ncx_protocol_enabled(NCX_PROTO_NETCONF10)) { res = cap_add_std(newmycaps, CAP_STDID_VALIDATE); if (res == NO_ERR) { res = cap_add_stdval(newcaps, CAP_STDID_VALIDATE); } } if (ncx_protocol_enabled(NCX_PROTO_NETCONF11)) { res = cap_add_std(newmycaps, CAP_STDID_VALIDATE11); if (res == NO_ERR) { res = cap_add_stdval(newcaps, CAP_STDID_VALIDATE11); } } } } /* check the startup type for distinct-startup capability */ if (res == NO_ERR) { if (agtstart==NCX_AGT_START_DISTINCT) { res = cap_add_std(newmycaps, CAP_STDID_STARTUP); if (res == NO_ERR) { res = cap_add_stdval(newcaps, CAP_STDID_STARTUP); } } } /* set the url capability */ if (res == NO_ERR) { if (agt_profile->agt_useurl) { res = cap_add_url(newmycaps, AGT_URL_SCHEME_LIST); if (res == NO_ERR) { res = cap_add_urlval(newcaps, AGT_URL_SCHEME_LIST); } } } /* set the xpath capability */ if (res == NO_ERR) { res = cap_add_std(newmycaps, CAP_STDID_XPATH); if (res == NO_ERR) { res = cap_add_stdval(newcaps, CAP_STDID_XPATH); } } /* set the notification capability if enabled */ if (agt_profile->agt_use_notifications) { if (res == NO_ERR) { res = cap_add_std(newmycaps, CAP_STDID_NOTIFICATION); if (res == NO_ERR) { res = cap_add_stdval(newcaps, CAP_STDID_NOTIFICATION); } } /* set the interleave capability */ if (res == NO_ERR) { res = cap_add_std(newmycaps, CAP_STDID_INTERLEAVE); if (res == NO_ERR) { res = cap_add_stdval(newcaps, CAP_STDID_INTERLEAVE); } } } /* set the partial-lock capability */ if (res == NO_ERR) { res = cap_add_std(newmycaps, CAP_STDID_PARTIAL_LOCK); if (res == NO_ERR) { res = cap_add_stdval(newcaps, CAP_STDID_PARTIAL_LOCK); } } /* set the with-defaults capability */ if (res == NO_ERR) { res = cap_add_withdef(newmycaps, defstyle); if (res == NO_ERR) { res = cap_add_withdefval(newcaps, defstyle); } } /* check the return value */ if (res != NO_ERR) { /* toss the new, put back the old */ cap_free_caplist(newmycaps); val_free_value(newcaps); my_agt_caps = oldmycaps; agt_caps = oldcaps; } else { /* toss the old, install the new */ if (oldmycaps) { cap_free_caplist(oldmycaps); } if (oldcaps) { val_free_value(oldcaps); } my_agt_caps = newmycaps; agt_caps = newcaps; } return res; } /* agt_cap_set_caps */
/******************************************************************** * FUNCTION do_while (local RPC) * * Handle the while command; start a new loopcb context * * while expr='xpath-str' [docroot=$foo] * * INPUTS: * server_cb == server control block to use * rpc == RPC method for the show command * line == CLI input in progress * len == offset into line buffer to start parsing * * RETURNS: * status *********************************************************************/ status_t do_while (server_cb_t *server_cb, obj_template_t *rpc, const xmlChar *line, uint32 len) { val_value_t *valset, *docroot, *expr, *dummydoc, *maxloops; xpath_pcb_t *pcb; status_t res; uint32 maxloopsval; docroot = NULL; expr = NULL; pcb = NULL; dummydoc = NULL; res = NO_ERR; maxloopsval = YANGCLI_DEF_MAXLOOPS; valset = get_valset(server_cb, rpc, &line[len], &res); if (valset == NULL) { return res; } if (res != NO_ERR) { val_free_value(valset); return res; } if (valset->res != NO_ERR) { res = valset->res; val_free_value(valset); return res; } /* get the expr parameter */ expr = val_find_child(valset, YANGCLI_MOD, YANGCLI_EXPR); if (expr == NULL) { res = ERR_NCX_MISSING_PARM; } else if (expr->res != NO_ERR) { res = expr->res; } if (res == NO_ERR) { /* get the optional docroot parameter */ docroot = val_find_child(valset, YANGCLI_MOD, YANGCLI_DOCROOT); if (docroot != NULL) { if (docroot->res != NO_ERR) { res = docroot->res; } else { val_remove_child(docroot); } } } if (res == NO_ERR && docroot == NULL) { dummydoc = xml_val_new_struct(NCX_EL_DATA, xmlns_nc_id()); if (dummydoc == NULL) { res = ERR_INTERNAL_MEM; } else { docroot = dummydoc; } } if (res == NO_ERR) { /* get the optional maxloops parameter */ maxloops = val_find_child(valset, YANGCLI_MOD, YANGCLI_MAXLOOPS); if (maxloops != NULL) { if (maxloops->res != NO_ERR) { res = maxloops->res; } else { maxloopsval = VAL_UINT(maxloops); } } } if (res == NO_ERR) { /* got all the parameters, and setup the XPath control block */ pcb = xpath_new_pcb_ex(VAL_STR(expr), xpath_getvar_fn, server_cb->runstack_context); if (pcb == NULL) { res = ERR_INTERNAL_MEM; } else { /* save these parameter and start a new while context block */ res = runstack_handle_while(server_cb->runstack_context, maxloopsval, pcb, /* hand off memory here */ docroot); /* hand off memory here */ if (res == NO_ERR) { /* hand off the pcb and docroot memory above */ pcb = NULL; docroot = NULL; } } } /* cleanup and exit */ if (valset) { val_free_value(valset); } if (pcb) { xpath_free_pcb(pcb); } if (docroot) { val_free_value(docroot); } return res; } /* do_while */
/******************************************************************** * FUNCTION do_elif (local RPC) * * Handle the if command; start a new ifcb context * * elif expr='xpath-str' [docroot=$foo] * * INPUTS: * server_cb == server control block to use * rpc == RPC method for the show command * line == CLI input in progress * len == offset into line buffer to start parsing * isif == TRUE for if, FALSE for elif * RETURNS: * status *********************************************************************/ static status_t do_if_elif (server_cb_t *server_cb, obj_template_t *rpc, const xmlChar *line, uint32 len, boolean isif) { val_value_t *valset, *docroot, *expr, *dummydoc; xpath_pcb_t *pcb; xpath_result_t *result; status_t res; boolean cond; docroot = NULL; expr = NULL; pcb = NULL; dummydoc = NULL; cond = FALSE; res = NO_ERR; valset = get_valset(server_cb, rpc, &line[len], &res); if (valset == NULL) { return res; } if (res != NO_ERR) { val_free_value(valset); return res; } if (valset->res != NO_ERR) { res = valset->res; val_free_value(valset); return res; } /* get the expr parameter */ expr = val_find_child(valset, YANGCLI_MOD, YANGCLI_EXPR); if (expr == NULL) { res = ERR_NCX_MISSING_PARM; } else if (expr->res != NO_ERR) { res = expr->res; } if (res == NO_ERR) { /* get the optional docroot parameter */ docroot = val_find_child(valset, YANGCLI_MOD, YANGCLI_DOCROOT); if (docroot && docroot->res != NO_ERR) { res = docroot->res; } } if (res == NO_ERR && docroot == NULL) { dummydoc = xml_val_new_struct(NCX_EL_DATA, xmlns_nc_id()); if (dummydoc == NULL) { res = ERR_INTERNAL_MEM; } else { docroot = dummydoc; } } if (res == NO_ERR) { /* got all the parameters, and setup the XPath control block */ pcb = xpath_new_pcb_ex(VAL_STR(expr), xpath_getvar_fn, server_cb->runstack_context); if (pcb == NULL) { res = ERR_INTERNAL_MEM; } else if ((isif && runstack_get_cond_state(server_cb->runstack_context)) || (!isif && !runstack_get_if_used(server_cb->runstack_context))) { /* figure out if this if or elif block is enabled or not */ result = xpath1_eval_expr(pcb, docroot, /* context */ docroot, TRUE, FALSE, &res); if (result != NULL && res == NO_ERR) { /* get new condition state for this loop */ cond = xpath_cvt_boolean(result); } xpath_free_result(result); } if (res == NO_ERR) { if (isif) { res = runstack_handle_if(server_cb->runstack_context, cond); } else { res = runstack_handle_elif(server_cb->runstack_context, cond); } } } /* cleanup and exit */ if (valset) { val_free_value(valset); } if (pcb) { xpath_free_pcb(pcb); } if (dummydoc) { val_free_value(dummydoc); } return res; } /* do_if_elif */