Exemplo n.º 1
0
/********************************************************************
 * FUNCTION do_show_cli (sub-mode of local RPC)
 * 
 * show CLI parms
 *
 * INPUTS:
 *  server_cb == server control block to use
 *********************************************************************/
static void
    do_show_cli (server_cb_t *server_cb)
{
    session_cb_t *session_cb = server_cb->cur_session_cb;
    val_value_t  *mgrset;
    logfn_t       logfn;
    boolean imode = interactive_mode();
    if (imode) {
        logfn = log_stdout;
    } else {
        logfn = log_write;
    }

    mgrset = get_mgr_cli_valset();

    /* CLI Parameters */
    if (mgrset && val_child_cnt(mgrset)) {
        (*logfn)("\nCLI Variables\n");
        val_dump_value_max(mgrset, 0,session_cb->defindent,
                           (imode) ? DUMP_VAL_STDOUT : DUMP_VAL_LOG,
                           session_cb->display_mode, FALSE, FALSE);
        (*logfn)("\n");
    } else {
        (*logfn)("\nNo CLI variables\n");
    }

}  /* do_show_cli */
Exemplo n.º 2
0
/********************************************************************
 * FUNCTION yangcli_notification_handler
 * 
 * matches callback template mgr_not_cbfn_t
 *
 * INPUTS:
 *   scb == session receiving RPC reply
 *   msg == notification msg that was parsed
 *   consumed == address of return consumed message flag
 *
 *  OUTPUTS:
 *     *consumed == TRUE if msg has been consumed so
 *                  it will not be freed by mgr_not_dispatch
 *               == FALSE if msg has been not consumed so
 *                  it will be freed by mgr_not_dispatch
 *********************************************************************/
void
    yangcli_notification_handler (ses_cb_t *scb,
                                  mgr_not_msg_t *msg,
                                  boolean *consumed)
{
    assert(scb && "scb is NULL!");
    assert(msg && "msg is NULL!");
    assert(consumed && "consumed is NULL!");

    *consumed = FALSE;

    mgr_scb_t *mgrcb = scb->mgrcb;
    server_cb_t *server_cb = get_cur_server_cb();
    session_cb_t *save_session_cb = server_cb->cur_session_cb;
    session_cb_t *session_cb = NULL;

    if (mgrcb) {
        session_cb = mgrcb->session_cb;
    }

    if (session_cb == NULL) {
        log_error("\nError: session no longer valid; dropping notification");
        return;
    }

    const xmlChar *sesname = get_session_name(session_cb);
    if (session_cb != save_session_cb) {
        set_cur_session_cb(server_cb, session_cb);
    }

    /* check the contents of the notification */
    if (msg && msg->notification) {

        /* dispatch this event to any handler registered for
         * this event;  !!! not session-specific !!!     */
        uint32 retcnt = dispatch_notif_event(session_cb, msg);
         
        /* display only unhandled notifications, and only if
         * the session is configured to show them         */
        log_debug_t loglevel = log_get_debug_level();
        log_debug_t base_loglevel = loglevel + 1;
        if (loglevel == LOG_DEBUG_INFO) {
            base_loglevel++;
        }
        if (retcnt == 0 && session_cb->echo_notifs &&
            base_loglevel >= session_cb->echo_notif_loglevel) {

            gl_normal_io(server_cb->cli_gl);
            if (loglevel >= session_cb->echo_notif_loglevel) {
                log_write("\n\nIncoming notification for session %u [%s]:",
                          scb->sid, sesname);
                val_dump_value_max(msg->notification, 
                                   0, session_cb->defindent,
                                   DUMP_VAL_LOG,
                                   session_cb->display_mode,
                                   FALSE, FALSE);
                log_write_append("\n\n");
            } else if (msg->eventType) {
                log_write("\n\nIncoming <%s> notification for session "
                          "%u [%s]\n\n", msg->eventType->name,
                          scb->sid, sesname);
            }
        }

        /* store msg in the session notification log */
        dlq_enque(msg, &session_cb->notificationQ);
        *consumed = TRUE;
    }
    
    if (session_cb != save_session_cb) {
        set_cur_session_cb(server_cb, save_session_cb);
    }

}  /* yangcli_notification_handler */
Exemplo n.º 3
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 */
Exemplo n.º 4
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 */
Exemplo n.º 5
0
/********************************************************************
* FUNCTION agt_init2
* 
* Initialize the Server Library
* The agt_profile is set and the object database is
* ready to have YANG modules loaded
*
* RPC and data node callbacks should be installed
* after the module is loaded, and before the running config
* is loaded.
*
* RETURNS:
*   status
*********************************************************************/
status_t 
    agt_init2 (void)
{
    val_value_t        *clivalset;
    ncx_module_t       *retmod;
    val_value_t        *val;
    agt_dynlib_cb_t    *dynlib;
    xmlChar            *savestr, *revision, savechar;
    cfg_template_t     *cfg;
    status_t            res;
    uint32              modlen;
    boolean             startup_loaded;

    log_debug3("\nServer Init-2 Starting...");

    startup_loaded = FALSE;

    /* init user callback support */
    agt_cb_init();
    agt_commit_complete_init();
    agt_commit_validate_init();
    agt_not_queue_notification_cb_init();

    /* initial signal handler first to allow clean exit */
    agt_signal_init();

    /* initialize the server timer service */
    agt_timer_init();
    
    /* initialize the RPC server callback structures */
    res = agt_rpc_init();
    if (res != NO_ERR) {
        log_debug3("\nError in rpc_init");
        return res;
    }

    /* initialize the NCX connect handler */
    res = agt_connect_init();
    if (res != NO_ERR) {
        log_debug3("\nError in agt_connect_init");
        return res;
    }

    /* initialize the NCX hello handler */
    res = agt_hello_init();
    if (res != NO_ERR) {
        log_debug3("\nError in agt_hello_init");
        return res;
    }

    /* setup an empty <running> config 
     * The config state is still CFG_ST_INIT
     * so no user access can occur yet (except OP_LOAD by root)
     */
    res = cfg_init_static_db(NCX_CFGID_RUNNING);
    if (res != NO_ERR) {
        return res;
    }

    /* set the 'ordered-by system' sorted/not-sorted flag */
    ncx_set_system_sorted(agt_profile.agt_system_sorted);

    /* set the 'top-level mandatory objects allowed' flag */
    ncx_set_top_mandatory_allowed(!agt_profile.agt_running_error);

    /*** All Server profile parameters should be set by now ***/

    /* must set the server capabilities after the profile is set */
    res = agt_cap_set_caps(agt_profile.agt_targ, 
                           agt_profile.agt_start,
                           agt_profile.agt_defaultStyle);
    if (res != NO_ERR) {
        return res;
    }

    /* setup the candidate config if it is used */
    if (agt_profile.agt_targ==NCX_AGT_TARG_CANDIDATE) {
        res = cfg_init_static_db(NCX_CFGID_CANDIDATE);
        if (res != NO_ERR) {
            return res;
        }
    }

    /* setup the startup config if it is used */
    if (agt_profile.agt_start==NCX_AGT_START_DISTINCT) {
        res = cfg_init_static_db(NCX_CFGID_STARTUP);
        if (res != NO_ERR) {
            return res;
        }
    }

    /* initialize the server access control model */
    res = agt_acm_init();
    if (res != NO_ERR) {
        return res;
    }

    /* initialize the session handler data structures */
    agt_ses_init();

    /* load the system module */
    res = agt_sys_init();
    if (res != NO_ERR) {
        return res;
    }

    /* load the NETCONF state monitoring data model module */
    res = agt_state_init();
    if (res != NO_ERR) {
        return res;
    }

    /* load the NETCONF Notifications data model module */
    res = agt_not_init();
    if (res != NO_ERR) {
        return res;
    }

    /* load the NETCONF /proc monitoring data model module */
    res = agt_proc_init();
    if (res != NO_ERR) {
        return res;
    }

    /* load the partial lock module */
    res = y_ietf_netconf_partial_lock_init
        (y_ietf_netconf_partial_lock_M_ietf_netconf_partial_lock,
         NULL);
    if (res != NO_ERR) {
        return res;
    }
#if 0  // OpenClovis: we do not want this by default
    /* load the NETCONF interface monitoring data model module */
    res = agt_if_init();
    if (res != NO_ERR) {
        return res;
    }
#endif
    /* initialize the NCX server core callback functions.
     * the schema (yuma-netconf.yang) for these callbacks was 
     * already loaded in the common ncx_init
     * */
    res = agt_ncx_init();
    if (res != NO_ERR) {
        return res;
    }

    /* load the yuma-time-filter module */
    res = y_yuma_time_filter_init
        (y_yuma_time_filter_M_yuma_time_filter, NULL);
    if (res != NO_ERR) {
        return res;
    }

    /* load the yuma-arp module */
    res = y_yuma_arp_init(y_yuma_arp_M_yuma_arp, NULL);
    if (res != NO_ERR) {
        return res;
    }

    /* check the module parameter set from CLI or conf file
     * for any modules to pre-load
     */
    res = NO_ERR;
    clivalset = agt_cli_get_valset();
    if (clivalset) {

        if (LOGDEBUG) {
            log_debug("\n\nnetconfd final CLI + .conf parameters:\n");
            val_dump_value_max(clivalset, 0, NCX_DEF_INDENT, DUMP_VAL_LOG,
                               NCX_DISPLAY_MODE_PLAIN, FALSE, /* withmeta */
                               TRUE /* config only */);
            log_debug("\n");
        }

        /* first check if there are any deviations to load */
        val = val_find_child(clivalset, NCXMOD_NETCONFD, NCX_EL_DEVIATION);
        while (val) {
            res = ncxmod_load_deviation(VAL_STR(val), 
                                        &agt_profile.agt_savedevQ);
            if (res != NO_ERR) {
                return res;
            } else {
                val = val_find_next_child(clivalset,
                                          NCXMOD_NETCONFD,
                                          NCX_EL_DEVIATION,
                                          val);
            }
        }

        val = val_find_child(clivalset, NCXMOD_NETCONFD, NCX_EL_MODULE);

        /* attempt all dynamically loaded modules */
        while (val && res == NO_ERR) {
            /* see if the revision is present in the
             * module parameter or not
             */
            modlen = 0;
            revision = NULL;
            savestr = NULL;
            savechar = '\0';

            if (yang_split_filename(VAL_STR(val), &modlen)) {
                savestr = &(VAL_STR(val)[modlen]);
                savechar = *savestr;
                *savestr = '\0';
                revision = savestr + 1;
            }

#ifdef STATIC_SERVER
            /* load just the module
             * SIL initialization is assumed to be
             * handled elsewhere
             */
             res = ncxmod_load_module(VAL_STR(val),
                                     revision,
                                     &agt_profile.agt_savedevQ,
                                     &retmod);
            }
            
#else
            /* load the SIL and it will load its own module */
            res = agt_load_sil_code(VAL_STR(val), revision, FALSE);
            if (res == ERR_NCX_SKIPPED) {
                log_warn("\nWarning: SIL code for module '%s' not found",
                         VAL_STR(val));
                res = ncxmod_load_module(VAL_STR(val),
                                         revision,
                                         &agt_profile.agt_savedevQ,
                                         &retmod);
            }
#endif

            if (savestr != NULL) {
                *savestr = savechar;
            }

            if (res == NO_ERR) {
                val = val_find_next_child(clivalset,
                                          NCXMOD_NETCONFD,
                                          NCX_EL_MODULE,
                                          val);
            }
        }
    }
Exemplo n.º 6
0
/********************************************************************
 * FUNCTION show_user_var
 * 
 * generate the output for a global or local variable
 *
 * INPUTS:
 *   server_cb == server control block to use
 *   varname == variable name to show
 *   vartype == type of user variable
 *   val == value associated with this variable
 *   mode == help mode in use
 *
 * RETURNS:
 *   status
 *********************************************************************/
static status_t
    show_user_var (server_cb_t *server_cb,
                   const xmlChar *varname,
                   var_type_t vartype,
                   val_value_t *val,
                   help_mode_t mode)
{
    session_cb_t *session_cb = server_cb->cur_session_cb;
    xmlChar      *objbuff;
    logfn_t       logfn;
    boolean imode = interactive_mode();
    int32 doubleindent = 1;
    status_t res = NO_ERR;


    if (imode) {
        logfn = log_stdout;
    } else {
        logfn = log_write;
    }

    switch (vartype) {
    case VAR_TYP_GLOBAL:
    case VAR_TYP_LOCAL:
    case VAR_TYP_SESSION:
    case VAR_TYP_SYSTEM:
    case VAR_TYP_CONFIG:
        if (xml_strcmp(varname, val->name)) {
            doubleindent = 2;

            (*logfn)("\n   %s ", varname);

            if (val->obj && obj_is_data_db(val->obj)) {
                res = obj_gen_object_id(val->obj, &objbuff);
                if (res != NO_ERR) {
                    (*logfn)("[no object id]\n   ");
                } else {
                    (*logfn)("[%s]\n   ", objbuff);
                    m__free(objbuff);
                }
            }
        } else if (session_cb->display_mode == NCX_DISPLAY_MODE_JSON) {
            (*logfn)("\n   %s: ", varname);
            if (!typ_is_simple(val->btyp)) {
                (*logfn)("\n");
            }
        }
        break;
    default:
        ;
    }

    if (!typ_is_simple(val->btyp) && mode == HELP_MODE_BRIEF) {
        if (doubleindent == 1) {
            (*logfn)("\n   %s (%s)",
                     varname, tk_get_btype_sym(val->btyp));
        } else {
            (*logfn)("\n      (%s)", 
                     tk_get_btype_sym(val->btyp));
        }
    } else {
        val_dump_value_max(val, 
                           session_cb->defindent * doubleindent,
                           session_cb->defindent,
                           (imode) ? DUMP_VAL_STDOUT : DUMP_VAL_LOG,
                           session_cb->display_mode,
                           FALSE, FALSE);
    }

    return res;

}  /* show_user_var */