예제 #1
0
/********************************************************************
 * FUNCTION clear_current_level
 * Clear the current level without changing it
 *
 * INPUTS:
 *    session_cb == session control block to use
 *********************************************************************/
static void
    clear_current_level (session_cb_t *session_cb)
{
    val_value_t *target = session_cb->config_ecurval;
    if (target == NULL) {
        return;
    }

    if (session_cb->config_estartval == NULL) {
        /* clear everything out */
        val_free_value(session_cb->config_etree);
        session_cb->config_etree = NULL;
        session_cb->config_ecurval = NULL;
        return;
    }

    boolean islist = obj_is_list(target->obj);
    val_value_t *chval = val_get_first_child(target);
    val_value_t *nextval = NULL;
    for (; chval; chval = nextval) {
        nextval = val_get_next_child(chval);
        if (islist && obj_is_key(chval->obj)) {
            continue;
        }
        val_remove_child(chval);
        val_free_value(chval);
    }

}  /* clear_current_level */
예제 #2
0
파일: rpc.c 프로젝트: 0xDEC0DE8/OpenYuma
/********************************************************************
* FUNCTION rpc_free_msg
*
* Free all the memory used by the specified rpc_msg_t
*
* INPUTS:
*   msg == rpc_msg_t to clean and delete
* RETURNS:
*   none
*********************************************************************/
void rpc_free_msg (rpc_msg_t *msg)
{
    if (!msg) {
        return;
    }

    xml_msg_clean_hdr(&msg->mhdr);

    //msg->rpc_in_attrs = NULL;
    //msg->rpc_method = NULL;
    //msg->rpc_agt_state = 0;

    /* clean input parameter set */
    if (msg->rpc_input) {
        val_free_value(msg->rpc_input);
    }
    //msg->rpc_user1 = NULL;
    //msg->rpc_user2 = NULL;

    //msg->rpc_filter.op_filtyp = OP_FILTER_NONE;
    //msg->rpc_filter.op_filter = NULL;
    //msg->rpc_datacb = NULL;

    /* clean data queue */
    while (!dlq_empty(&msg->rpc_dataQ)) {
        val_value_t *val = (val_value_t *)dlq_deque(&msg->rpc_dataQ);
        val_free_value(val);
    }

    m__free(msg);

} /* rpc_free_msg */
예제 #3
0
/********************************************************************
* 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 */
예제 #4
0
/********************************************************************
 * FUNCTION do_alias (local RPC)
 * 
 * alias
 * alias def
 * alias def=def-value
 *
 * Handle the alias command, based on the parameter
 *
 * INPUTS:
 *    server_cb == server control block to use
 *    rpc == RPC method for the alias command
 *    line == CLI input in progress
 *    len == offset into line buffer to start parsing
 *
 * RETURNS:
 *   status
 *********************************************************************/
status_t
    do_alias (server_cb_t *server_cb,
              obj_template_t *rpc,
              const xmlChar *line,
              uint32  len)
{
    val_value_t        *valset, *parm;
    status_t            res = NO_ERR;

    valset = get_valset(server_cb, rpc, &line[len], &res);

    if (res == NO_ERR && valset) {
        parm = val_find_child(valset, YANGCLI_MOD, YANGCLI_VAR);
        if (parm) {
            const xmlChar *varstr = VAL_STR(parm);
            res = handle_alias_parm(varstr, FALSE, TRUE);

            if (res == NO_ERR) {
               update_yangcli_param_change_flag (ALIASES_FILE, TRUE);
            }

        } else {
            /* no parameter; show all aliases */
            show_aliases();
        }
    }

    if (valset) {
        val_free_value(valset);
    }

    return res;

}  /* do_alias */
예제 #5
0
/********************************************************************
 * FUNCTION do_unset (local RPC)
 * 
 * unset def
 *
 * Handle the unset command; remove the specified alias
 *
 * INPUTS:
 *    server_cb == server control block to use
 *    rpc == RPC method for the unset command
 *    line == CLI input in progress
 *    len == offset into line buffer to start parsing
 *
 * RETURNS:
 *   status
 *********************************************************************/
extern status_t
    do_unset (server_cb_t *server_cb,
              obj_template_t *rpc,
              const xmlChar *line,
              uint32  len)
{
    val_value_t        *valset, *parm;
    status_t            res = NO_ERR;

    valset = get_valset(server_cb, rpc, &line[len], &res);

    if (res == NO_ERR && valset) {
        parm = val_find_child(valset, YANGCLI_MOD, NCX_EL_NAME);
        if (parm) {
            const xmlChar *varstr = VAL_STR(parm);
            alias_cb_t *alias = find_alias(varstr, xml_strlen(varstr));
            if (alias) {
                dlq_remove(alias);
                free_alias(alias);
                log_info("\nDeleted alias '%s'\n", varstr);
            } else {
                res = ERR_NCX_INVALID_VALUE;
                log_error("\nError: unknown alias '%s'\n", varstr);
            }
        }  /* else missing parameter already reported */
    } /* else no valset already reported */

    if (valset) {
        val_free_value(valset);
    }

    return res;

}  /* do_unset */
예제 #6
0
/********************************************************************
 * FUNCTION do_end (local RPC)
 * 
 * Handle the end command; end an if or while block
 *
 *   end
 *
 * 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_end (server_cb_t *server_cb,
            obj_template_t *rpc,
            const xmlChar *line,
            uint32  len)
{
    val_value_t        *valset;
    status_t            res;

    res = NO_ERR;
    valset = get_valset(server_cb, rpc, &line[len], &res);
    if (valset == NULL) {
        if (res != ERR_NCX_SKIPPED) {
            return res;
        }
    } else {
        val_free_value(valset);
        return ERR_NCX_INVALID_VALUE;
    }

    res = runstack_handle_end(server_cb->runstack_context);

    return res;

}  /* do_end */
예제 #7
0
/********************************************************************
* FUNCTION rpc_err_free_info
*
* Clean and free an rpc_err_info_t struct
*
* INPUTS:
*   errinfo == rpc_err_info_t struct to clean and free
* RETURNS:
*   none
*********************************************************************/
void
    rpc_err_free_info (rpc_err_info_t *errinfo)
{
#ifdef DEBUG
    if (!errinfo) {
        SET_ERROR(ERR_INTERNAL_PTR);
        return;
    }
#endif

    if (errinfo->badns) {
        m__free(errinfo->badns);
    }
    if (errinfo->dname) {
        m__free(errinfo->dname);
    }
    if (errinfo->dval) {
        m__free(errinfo->dval);
    }
    switch (errinfo->val_btype) {
    case NCX_BT_ANY:
    case NCX_BT_CONTAINER:
    case NCX_BT_CHOICE:
    case NCX_BT_LIST:
        if (errinfo->v.cpxval) {
            val_free_value((val_value_t *)errinfo->v.cpxval);
        }
        break;
    default:
        ;
    }
    m__free(errinfo);

} /* rpc_err_free_info */
예제 #8
0
/********************************************************************
 * FUNCTION do_exit (local RPC)
 * 
 * exit
 *
 * Exit the configuration mode
 *
 * 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_exit (server_cb_t *server_cb,
             obj_template_t *rpc,
             const xmlChar *line,
             uint32  len)
{
    status_t res = NO_ERR;
    val_value_t *valset = get_valset(server_cb, rpc, &line[len], &res);

    if (valset && res == NO_ERR) {

        ;
    }

    if (res == NO_ERR || res == ERR_NCX_SKIPPED) {
        session_cb_t *session_cb = server_cb->cur_session_cb;
        if (!session_cb->config_mode) {
            log_error("\nError: configure mode is not active\n");
            res = ERR_NCX_OPERATION_FAILED;
        } else {
            exit_config_mode(session_cb);
        }
    }

    if (valset) {
        val_free_value(valset);
    }

    return res;

}  /* do_exit */
예제 #9
0
/********************************************************************
 * FUNCTION clear_one_level
 * Clear the current level for the ecurptr
 * The exit command was given so backing up top the
 * parent of the config_ecurptr
 *
 * INPUTS:
 *    session_cb == session control block to use
 *********************************************************************/
static void
    clear_one_level (session_cb_t *session_cb)
{
    val_value_t *target = session_cb->config_ecurval;
    if (target == NULL) {
        return;
    }

    val_value_t *parent = target->parent;

    if (session_cb->config_estartval == target) {
        session_cb->config_estartval = NULL;
    }

    if (parent) {
        val_remove_child(target);
    }
    val_free_value(target);

    session_cb->config_ecurval = parent;
    if (parent == NULL) {
        session_cb->config_etree = NULL;
        session_cb->config_estartval = NULL;
    }

}  /* clear_one_level */
예제 #10
0
/********************************************************************
* FUNCTION y_simple_list_test_get_counter_invoke
* 
* RPC invocation phase
* All constraints have passed at this point.
* Call device instrumentation code in this function.
* 
* INPUTS:
*     see agt/agt_rpc.h for details
* 
* RETURNS:
*     error status
********************************************************************/
static status_t y_simple_list_test_get_counter_invoke (
    ses_cb_t *scb,
    rpc_msg_t *msg,
    xml_node_t *methnode)
{
    status_t res = NO_ERR;
    val_value_t     *countVal;
    xmlChar          countBuff[100];

    /* remove the next line if scb is used */
    (void)scb;

    /* remove the next line if msg is used */
    (void)msg;

    /* remove the next line if methnode is used */
    (void)methnode;

    /* invoke your device instrumentation code here */
    snprintf((char *)countBuff, sizeof(countBuff), "%u", count_static);
    countVal = val_make_string(0,
                               (xmlChar*)"count",
                               countBuff);
    if (countVal == NULL) {
        val_free_value(countVal);
        return ERR_INTERNAL_MEM;
    }

    dlq_enque(countVal, &msg->rpc_dataQ);
    msg->rpc_data_type = RPC_DATA_STD;

    return res;

} /* y_simple_list_test_get_counter_invoke */
예제 #11
0
/********************************************************************
 * 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 */
예제 #12
0
/********************************************************************
* FUNCTION agt_cli_cleanup
*
*   Cleanup the module static data
*
*********************************************************************/
void
    agt_cli_cleanup (void)
{
    if (cli_val) {
        val_free_value(cli_val);
        cli_val = NULL;
    }

} /* agt_cli_cleanup */
예제 #13
0
/********************************************************************
* FUNCTION get_my_session_invoke
*
* get-my-session : invoke params callback
*
* INPUTS:
*    see rpc/agt_rpc.h
* RETURNS:
*    status
*********************************************************************/
static status_t 
    get_my_session_invoke (ses_cb_t *scb,
                           rpc_msg_t *msg,
                           xml_node_t *methnode)
{
    val_value_t     *indentval, *linesizeval, *withdefval;
    xmlChar          numbuff[NCX_MAX_NUMLEN];

    (void)methnode;

    snprintf((char *)numbuff, sizeof(numbuff), "%u", scb->indent);
    indentval = val_make_string(mysesmod->nsid,
                                NCX_EL_INDENT,
                                numbuff);
    if (indentval == NULL) {
        return ERR_INTERNAL_MEM;
    }

    snprintf((char *)numbuff, sizeof(numbuff), "%u", scb->linesize);
    linesizeval = val_make_string(mysesmod->nsid,
                                  NCX_EL_LINESIZE,
                                  numbuff);
    if (linesizeval == NULL) {
        val_free_value(indentval);
        return ERR_INTERNAL_MEM;
    }

    withdefval = 
        val_make_string(mysesmod->nsid,
                        NCX_EL_WITH_DEFAULTS,
                        ncx_get_withdefaults_string(scb->withdef));
    if (withdefval == NULL) {
        val_free_value(indentval);
        val_free_value(linesizeval);
        return ERR_INTERNAL_MEM;
    }

    dlq_enque(indentval, &msg->rpc_dataQ);
    dlq_enque(linesizeval, &msg->rpc_dataQ);
    dlq_enque(withdefval, &msg->rpc_dataQ);
    msg->rpc_data_type = RPC_DATA_YANG;
    return NO_ERR;

} /* get_my_session_invoke */
예제 #14
0
/********************************************************************
 * FUNCTION process_exit
 * (config mode input received)
 *  Handle the exit command based on the current mode
 *
 * INPUTS:
 *    server_cb == server control block to use
 *    session_cb == session control block to use
 * RETURNS:
 *   status
 *********************************************************************/
static status_t
    process_exit (server_cb_t *server_cb,
                  session_cb_t *session_cb)
{
    /*** TBD: add warning about edits pending ***/

    status_t res = NO_ERR;

    /* exit to previous level or root or out of config mode */
    if (session_cb->config_curobj) {
        /* check if edits are applied when the mode is exited */
        if (session_cb->config_edit_mode == CFG_EDITMODE_LEVEL) {
            if (session_cb->config_etree) {
                /* there may be an edit to apply */
                if (!session_cb->config_edit_dirty ||
                    dlq_count(&session_cb->config_editQ) == 0) {
                    
                    /* entered mode and then exited without adding any
                     * edits so try adding the container or list    */
                    res = add_edit(session_cb);
                }
                //clear_one_level(session_cb);
            }
            if (res == NO_ERR) {
                res = process_apply(server_cb, session_cb);
            }
        }

        /* get parent of current object */
        session_cb->config_curobj = 
            obj_get_real_parent(session_cb->config_curobj);

        if (!session_cb->config_curobj || 
            obj_is_root(session_cb->config_curobj)) {

            /* exit to root-level, stay in config mode */
            session_cb->config_curobj = NULL;
            session_cb->config_ecurval = NULL;
            val_free_value(session_cb->config_etree);
            session_cb->config_etree = NULL;
        } else if (session_cb->config_ecurval) {
            clear_one_level(session_cb);
        }
    } else {
        /* no current object so exit config mode */
        exit_config_mode(session_cb);
    }

    return res;

}  /* process_exit */
예제 #15
0
/********************************************************************
* FUNCTION clean_undorec
*
* Clean all the memory used by the specified agt_cfg_undo_rec_t
* but do not free the struct itself
*
*  !!! The caller must free internal pointers that were malloced
*  !!! instead of copied.  This function does not check them!!!
*  
* INPUTS:
*   undo == agt_cfg_undo_rec_t to clean
*   reuse == TRUE if possible reuse
*            FALSE if this node is being freed right now
*
* RETURNS:
*   none
*********************************************************************/
static void 
    clean_undorec (agt_cfg_undo_rec_t *undo,
                   boolean reuse)
{
    if (undo->free_curnode && undo->curnode) {
        val_free_value(undo->curnode);
    }

    if (undo->curnode_clone) {
        val_free_value(undo->curnode_clone);
    }

    if (undo->newnode_marker) {
        val_free_value(undo->newnode_marker);
    }

    if (undo->curnode_marker) {
        val_free_value(undo->curnode_marker);
    }

    /* really expecting the extra_deleteQ to be empty at this point */
    while (!dlq_empty(&undo->extra_deleteQ)) {
        agt_cfg_nodeptr_t *nodeptr = (agt_cfg_nodeptr_t *)
            dlq_deque(&undo->extra_deleteQ);
        if (nodeptr && nodeptr->node) {
            val_remove_child(nodeptr->node);
            val_free_value(nodeptr->node);
        } else {
            SET_ERROR(ERR_INTERNAL_VAL);
        }
        agt_cfg_free_nodeptr(nodeptr);
    }

    if (reuse) {
        agt_cfg_init_undorec(undo);
    }

} /* clean_undorec */
예제 #16
0
/********************************************************************
* FUNCTION agt_cap_cleanup
*
* Clean the NETCONF agent capabilities
*
* INPUTS:
*    none
* RETURNS:
*    none
*********************************************************************/
void 
    agt_cap_cleanup (void)
{
    if (agt_caps) {
        val_free_value(agt_caps);
        agt_caps = NULL;
    }

    if (my_agt_caps) {
        cap_clean_caplist(my_agt_caps);
        m__free(my_agt_caps);
        my_agt_caps = NULL;
    }

} /* agt_cap_cleanup */
예제 #17
0
/********************************************************************
* FUNCTION mgr_cap_cleanup
*
* Clean the NETCONF manager capabilities
*
* INPUTS:
*    none
* RETURNS:
*    none
*********************************************************************/
void 
    mgr_cap_cleanup (void)
{
    if (mgr_caps) {
        val_free_value(mgr_caps);
        mgr_caps = NULL;
    }

    if (my_mgr_caps) {
        cap_clean_caplist(my_mgr_caps);
        m__free(my_mgr_caps);
        my_mgr_caps = NULL;
    }

} /* mgr_cap_cleanup */
예제 #18
0
/********************************************************************
* FUNCTION mgr_not_free_msg
*
* Free a mgr_not_msg_t struct
*
* INPUTS:
*   msg == struct to free
*
* RETURNS:
*   none
*********************************************************************/
void
    mgr_not_free_msg (mgr_not_msg_t *msg)
{
#ifdef DEBUG
    if (!msg) {
        SET_ERROR(ERR_INTERNAL_PTR);
        return;
    }
#endif

    if (msg->notification) {
        val_free_value(msg->notification);
    }

    m__free(msg);

} /* mgr_not_free_msg */
예제 #19
0
/********************************************************************
* FUNCTION mgr_rpc_free_reply
*
* Free a mgr_rpc_rpy_t struct
*
* INPUTS:
*   rpy == struct to free
*
* RETURNS:
*   none
*********************************************************************/
void
    mgr_rpc_free_reply (mgr_rpc_rpy_t *rpy)
{
#ifdef DEBUG
    if (!rpy) {
        SET_ERROR(ERR_INTERNAL_PTR);
        return;
    }
#endif

    if (rpy->msg_id) {
        m__free(rpy->msg_id);
    }
    if (rpy->reply) {
        val_free_value(rpy->reply);
    }
    m__free(rpy);

} /* mgr_rpc_free_reply */
예제 #20
0
/********************************************************************
* FUNCTION mgr_rpc_free_request
*
* Free a mgr_rpc_req_t struct
*
* INPUTS:
*   req == struct to free
*
* RETURNS:
*   none
*********************************************************************/
void
    mgr_rpc_free_request (mgr_rpc_req_t *req)
{
#ifdef DEBUG
    if (!req) {
        SET_ERROR(ERR_INTERNAL_PTR);
        return;
    }
#endif

    if (req->msg_id) {
        m__free(req->msg_id);
    }
    xml_clean_attrs(&req->attrs);
    if (req->data) {
        val_free_value(req->data);
    }
    m__free(req);

} /* mgr_rpc_free_request */
예제 #21
0
/********************************************************************
 * FUNCTION add_edit
 * (config mode input received)
 *  Add an edit to the server config_editQ
 *
 * INPUTS:
 *    session_cb == session control block to use
 *
 * RETURNS:
 *   status
 *********************************************************************/
static status_t
    add_edit (session_cb_t *session_cb)
{
    if (session_cb->config_etree) {
        op_editop_t delop = get_del_op(session_cb);
        op_editop_t op = (session_cb->config_no_active) ?
            delop : OP_EDITOP_MERGE;
        val_value_t *clone = val_clone(session_cb->config_etree);
        if (clone == NULL) {
            return ERR_INTERNAL_MEM;
        }
        config_edit_t *edit = new_config_edit(op, clone);
        if (edit == NULL) {
            val_free_value(clone);
            return ERR_INTERNAL_MEM;
        }
        session_cb->config_edit_dirty = TRUE;
        dlq_enque(edit, &session_cb->config_editQ);
    }
    return NO_ERR;

}  /* add_edit */
예제 #22
0
/********************************************************************
 * FUNCTION do_config (local RPC)
 * 
 * config term
 *
 * Enter the configuration mode
 *
 * 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_config (server_cb_t *server_cb,
               obj_template_t *rpc,
               const xmlChar *line,
               uint32  len)
{
    status_t res = NO_ERR;
    val_value_t *valset = get_valset(server_cb, rpc, &line[len], &res);

    if (valset && res == NO_ERR) {
        /* check if the 'brief' flag is set first */
        val_value_t *parm = 
            val_find_child(valset, YANGCLI_MOD, YANGCLI_TERM);
        if (!parm || parm->res != NO_ERR) {
            log_error("\nError: 'terminal' parameter invalid\n");
            if (parm) {
                res = parm->res;
            } else {
                res = ERR_NCX_MISSING_PARM;
            }
        } else {
            session_cb_t *session_cb = server_cb->cur_session_cb;
            if (session_cb->config_mode) {
                log_error("\nError: configure mode already active\n");
                res = ERR_NCX_IN_USE;
            } else {
                res = start_config_mode(server_cb, session_cb);
            }
        }
    }

    if (valset) {
        val_free_value(valset);
    }

    return res;

}  /* do_config */
예제 #23
0
/********************************************************************
 * FUNCTION exit_config_mode
 * 
 * Exit the configuration mode
 *
 * INPUTS:
 *    session_cb == session control block to use
 *
 *********************************************************************/
static void
    exit_config_mode (session_cb_t *session_cb)
{
    session_cb->config_mode = FALSE;
    session_cb->config_no_active = FALSE;
    session_cb->config_edit_dirty = FALSE;
    session_cb->alt_names = session_cb->config_alt_names;
    session_cb->match_names = session_cb->config_match_names;
    m__free(session_cb->config_path);
    session_cb->config_path = NULL;
    session_cb->config_curval = NULL;
    session_cb->config_curobj = NULL;
    session_cb->config_curkey = NULL;
    val_free_value(session_cb->config_etree);
    session_cb->config_etree = NULL;
    session_cb->config_ecurval = NULL;
    while (!dlq_empty(&session_cb->config_editQ)) {
        config_edit_t *edit = (config_edit_t *)
            dlq_deque(&session_cb->config_editQ);
        free_config_edit(edit);
    }

} /* exit_config_mode */
예제 #24
0
/********************************************************************
* 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 */
예제 #25
0
/********************************************************************
* 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 */
예제 #26
0
/********************************************************************
 * 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 */
예제 #27
0
/********************************************************************
* 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 */
예제 #28
0
/********************************************************************
* FUNCTION mgr_hello_send
*
* Send the manager <hello> message to the server on the 
* specified session
*
* INPUTS:
*   scb == session control block
*
* RETURNS:
*   status
*********************************************************************/
status_t
    mgr_hello_send (ses_cb_t *scb)
{
    val_value_t  *mycaps;
    xml_msg_hdr_t msg;
    status_t      res;
    xml_attrs_t   attrs;
    boolean       anyout;
    xmlns_id_t    nc_id;

#ifdef DEBUG
    if (!scb) {
        return SET_ERROR(ERR_INTERNAL_PTR);
    }
#endif

#ifdef MGR_HELLO_DEBUG
    if (LOGDEBUG2) {
        log_debug2("\nmgr sending hello on session %d", scb->sid);
    }
#endif

    res = NO_ERR;
    anyout = FALSE;
    xml_msg_init_hdr(&msg);
    xml_init_attrs(&attrs);
    nc_id = xmlns_nc_id();

    /* get my client caps, custom made for this session */
    mycaps = mgr_cap_get_ses_capsval(scb);
    if (!mycaps) {
        res = SET_ERROR(ERR_INTERNAL_PTR);
    }

    /* setup the prefix map with the NETCONF namespace */
    if (res == NO_ERR) {
        res = xml_msg_build_prefix_map(&msg, &attrs, TRUE, FALSE);
    }

    /* send the <?xml?> directive */
    if (res == NO_ERR) {
        res = ses_start_msg(scb);
    }

    /* start the hello element */
    if (res == NO_ERR) {
        anyout = TRUE;
        xml_wr_begin_elem_ex(scb, 
                             &msg, 
                             0, 
                             nc_id, 
                             NCX_EL_HELLO, 
                             &attrs, 
                             ATTRQ, 
                             0, 
                             START);
    }
    
    /* send the capabilities list */
    if (res == NO_ERR) {
        xml_wr_full_val(scb, &msg, mycaps, NCX_DEF_INDENT);
    }

    /* finish the hello element */
    if (res == NO_ERR) {
        xml_wr_end_elem(scb, &msg, nc_id, NCX_EL_HELLO, 0);
    }

    /* finish the message */
    if (anyout) {
        ses_finish_msg(scb);
    }

    xml_clean_attrs(&attrs);
    xml_msg_clean_hdr(&msg);
    if (mycaps != NULL) {
        val_free_value(mycaps);
    }
    return res;

} /* mgr_hello_send */
예제 #29
0
/********************************************************************
* FUNCTION mgr_hello_dispatch
*
* Handle an incoming <hello> message from the client
*
* INPUTS:
*   scb == session control block
*   top == top element descriptor
*********************************************************************/
void 
    mgr_hello_dispatch (ses_cb_t *scb,
                        xml_node_t *top)
{
    val_value_t           *val;
    ncx_module_t          *mod;
    obj_template_t        *obj;
    mgr_scb_t             *mscb;
    xml_msg_hdr_t          msg;
    status_t               res;

#ifdef DEBUG
    if (!scb || !top) {
        SET_ERROR(ERR_INTERNAL_PTR);
        return;
    }
#endif

#ifdef MGR_HELLO_DEBUG
    if (LOGDEBUG) {
        log_debug("\nmgr_hello got node");
    }
    if (LOGDEBUG2) {
        xml_dump_node(top);
    }
#endif

    mscb = mgr_ses_get_mscb(scb);

    /* only process this message in hello wait state */
    if (scb->state != SES_ST_HELLO_WAIT) {
        /* TBD: stats update */
        if (LOGINFO) {
            log_info("\nmgr_hello dropped, wrong state for session %d",
                     scb->sid);
        }
        return;
    }

    /* init local vars */
    res = NO_ERR;
    val = NULL;
    obj = NULL;
    xml_msg_init_hdr(&msg);

    /* get a value struct to hold the server hello msg */
    val = val_new_value();
    if (!val) {
        res = ERR_INTERNAL_MEM;
    }

    /* get the type definition from the registry */
    if (res == NO_ERR) {
        mod = ncx_find_module(NC_MODULE, NULL);
        if (mod) {
            obj = ncx_find_object(mod, MGR_SERVER_HELLO_OBJ);
        }
        if (!obj) {
            /* netconf module should have loaded this definition */
            res = SET_ERROR(ERR_INTERNAL_PTR);
        }
    }

    /* parse an server hello message */
    if (res == NO_ERR) {
        res = mgr_val_parse(scb, obj, top, val);
    }
    
    /* examine the server capability list
     * and it matches the server protocol version
     */
    if (res == NO_ERR) {
        res = process_server_hello(scb, val);
    }

    /* report first error and close session */
    if (res != NO_ERR) {
        if (LOGINFO) {
            log_info("\nmgr_connect error (%s)\n  dropping session %u (a:%u)",
                     get_error_string(res), 
                     scb->sid, 
                     mscb->agtsid,
                     res);
        }
    } else {
        scb->state = SES_ST_IDLE;
        if (LOGDEBUG) {
            log_debug("\nmgr_hello manager hello ok");
        }
    }
    if (val) {
        val_free_value(val);
    }

} /* mgr_hello_dispatch */
예제 #30
0
/********************************************************************
 * FUNCTION do_aliases (local RPC)
 * 
 * aliases
 * aliases clear
 * aliases show
 * aliases load[=filespec]
 * aliases save[=filespec]
 *
 * Handle the aliases command, based on the parameter
 *
 * INPUTS:
 *    server_cb == server control block to use
 *    rpc == RPC method for the aliases command
 *    line == CLI input in progress
 *    len == offset into line buffer to start parsing
 *
 * RETURNS:
 *   status
 *********************************************************************/
status_t
    do_aliases (server_cb_t *server_cb,
              obj_template_t *rpc,
              const xmlChar *line,
              uint32  len)
{
    val_value_t   *valset;
    status_t       res = NO_ERR;

    valset = get_valset(server_cb, rpc, &line[len], &res);

    if (res == NO_ERR && valset) {
        /* get the 1 of N 'alias-action' choice */
        val_value_t *parm;
        const xmlChar *parmval = NULL;
        boolean done = FALSE;
        
        /* aliases show */
        parm = val_find_child(valset, YANGCLI_MOD, YANGCLI_SHOW);
        if (parm) {
            show_aliases();
            done = TRUE;
        }

        /* aliases clear */
        if (!done) {
            parm = val_find_child(valset, YANGCLI_MOD, YANGCLI_CLEAR);
            if (parm) {
                dlq_hdr_t *aliasQ = get_aliasQ();
                if (!dlq_empty(aliasQ)) {
                    free_aliases();
                    log_info("\nDeleted all aliases from memory\n");
                    update_yangcli_param_change_flag (ALIASES_FILE, TRUE);
                }else {
                    log_info("\nNo aliases found\n");
                }
                done = TRUE;
            }
        }

        /* aliases load */
        if (!done) {
            parm = val_find_child(valset, YANGCLI_MOD, YANGCLI_LOAD);
            if (parm) {
                if (xml_strlen(VAL_STR(parm))) {
                    parmval = VAL_STR(parm);
                } else {
                    parmval = get_aliases_file();
                }
                res = load_aliases(parmval, !val_set_by_default(parm));
                if (res == NO_ERR) {
                    log_info("\nLoaded aliases OK from '%s'\n", parmval);
                } else {
                    log_error("\nLoad aliases from '%s' failed (%s)\n", 
                              parmval, get_error_string(res));
                }
                done = TRUE;
            }
        }

        /* aliases save */
        if (!done) {
            parm = val_find_child(valset, YANGCLI_MOD, YANGCLI_SAVE);
            if (parm) {
                if (xml_strlen(VAL_STR(parm))) {
                    parmval = VAL_STR(parm);
                } else {
                    parmval = get_aliases_file();
                }
                res = save_aliases(parmval);
                if (res == NO_ERR) {
                    log_info("\nSaved aliases OK to '%s'\n", parmval);
                } else if (res != ERR_NCX_CANCELED) {
                    log_error("\nSave aliases to '%s' failed (%s)\n", 
                              parmval, get_error_string(res));
                }
                done = TRUE;
            }
        }

        if (!done) {
            /* no parameters; show all aliases */
            show_aliases();
        }
    }

    if (valset) {
        val_free_value(valset);
    }

    return res;

}  /* do_aliases */