Exemple #1
0
/********************************************************************
* FUNCTION mgr_not_init
*
* Initialize the mgr_not module
* call once to init module
* Adds the mgr_not_dispatch function as the handler
* for the NETCONF <rpc> top-level element.
*
* INPUTS:
*   none
* RETURNS:
*   NO_ERR if all okay, the minimum spare requests will be malloced
*********************************************************************/
status_t 
    mgr_not_init (void)
{
    if (mgr_not_init_done) {
        return ERR_INTERNAL_INIT_SEQ;
    }

    /* get the notification template */
    notification_obj = NULL;
    callbackfn = NULL;

    ncx_module_t *mod = ncx_find_module(NCN_MODULE, NULL);
    if (mod == NULL) {
        return ERR_NCX_MOD_NOT_FOUND;
    }
    notification_obj = ncx_find_object(mod, NCX_EL_NOTIFICATION);
    if (notification_obj == NULL) {
        return ERR_NCX_DEF_NOT_FOUND;
    }

    status_t res = 
        top_register_node(NCN_MODULE, NCX_EL_NOTIFICATION, 
                          mgr_not_dispatch);
    if (res != NO_ERR) {
        return res;
    }

    mgr_not_init_done = TRUE;
    return NO_ERR;

} /* mgr_not_init */
Exemple #2
0
/********************************************************************
* FUNCTION agt_cap_set_modules
*
* Initialize the NETCONF agent capabilities modules list
* MUST call after agt_cap_set_caps
*
* INPUTS:
*   profile == agent profile control block to use
*
* RETURNS:
*    status
*********************************************************************/
status_t 
    agt_cap_set_modules (agt_profile_t *profile)
{
    if (!agt_caps || !my_agt_caps) {
        return SET_ERROR(ERR_INTERNAL_INIT_SEQ);
    }

    /* add the ietf-netconf module first */
    status_t res = cap_add_netconf_modval(agt_caps);
    if (res != NO_ERR) {
        log_error("\nError: could not add ietf-netconf "
                  "capability val (%s)\n", get_error_string(res));
        return res;
    }

    ncx_module_t *mod = ncx_get_first_module();

    /* add capability for each module loaded in ncxmod */
    while (mod && res == NO_ERR) {
        /* keep internal modules out of the capabilities */
        if (agt_advertise_module_needed(mod->name)) {
            res = cap_add_modval(agt_caps, mod);
            if (res == NO_ERR) {
                res = cap_add_mod(my_agt_caps, mod);
            }
        }
        mod = (ncx_module_t *)dlq_nextEntry(mod);
    }

    /* add capability for each deviation module, not already
     * listed in the module capabilities so far
     */
    ncx_save_deviations_t *savedev;
    for (savedev = (ncx_save_deviations_t *)
             dlq_firstEntry(&profile->agt_savedevQ);
         savedev != NULL && res == NO_ERR;
         savedev = (ncx_save_deviations_t *)
             dlq_nextEntry(savedev)) {

        if (agt_advertise_module_needed(savedev->devmodule)) {

            /* make sure this is not a hard-wired internal module 
             * or a duplicate already loaded as a regular module
             */
            mod = ncx_find_module(savedev->devmodule,
                                  savedev->devrevision);
            if (mod == NULL) {
                /* not already announced in the capabilities */
                res = cap_add_devmodval(agt_caps, savedev);
            }
        }
    }
         
    return res;

} /* agt_cap_set_modules */
Exemple #3
0
/********************************************************************
* FUNCTION ncx_feature_enabled_str
* 
* Check if the specified feature and any referenced
* if-features are enabled
*
* INPUTS:
*    modname == name of module to search
*    revision == module revision string (may be NULL)
*    name == feature name to find
* RETURNS:
*   TRUE if feature is completely enabled
*   FALSE if feature is not enabled, or partially enabled
*********************************************************************/
boolean
    ncx_feature_enabled_str (const xmlChar *modname,
                             const xmlChar *revision,
                             const xmlChar *name)
{
#ifdef DEBUG
    if (!modname || !name) {
        SET_ERROR(ERR_INTERNAL_PTR);
        return FALSE;
    }
#endif
    ncx_module_t *mod = ncx_find_module(modname, revision);
    if (mod == NULL) {
        return FALSE;
    }

    const ncx_feature_t *feature = ncx_find_feature(mod, name);
    if (feature == NULL) {
        return FALSE;
    }
    return ncx_feature_enabled(feature);

} /* ncx_feature_enabled_str */
Exemple #4
0
/********************************************************************
* FUNCTION help_program_module
*
* Print the full help text for an entire program module to STDOUT
*
* INPUTS:
*    modname == module name without file suffix
*    cliname == name of CLI parmset within the modname module
*
*********************************************************************/
void
    help_program_module (const xmlChar *modname,
                         const xmlChar *cliname,
                         help_mode_t mode)
{
    ncx_module_t         *mod;
    obj_template_t       *cli;
    uint32                nestlevel;
    help_mode_t           usemode;

#ifdef DEBUG
    if (!modname) {
        SET_ERROR(ERR_INTERNAL_PTR);
        return;
    }
    if (mode == HELP_MODE_NONE || mode > HELP_MODE_FULL) {
        SET_ERROR(ERR_INTERNAL_VAL);
        return;
    }
#endif

    nestlevel = get_nestlevel(mode);

    mod = ncx_find_module(modname, NULL);
    if (!mod) {
        log_error("\nhelp: Module '%s' not found", modname);
        SET_ERROR(ERR_NCX_MOD_NOT_FOUND);
        return;
    }

    log_stdout("\n\n  Program %s", mod->name);
    log_stdout("\n\n  Usage:");
    log_stdout("\n\n    %s [parameters]", mod->name);
    if (mode != HELP_MODE_BRIEF) {
        log_stdout("\n\n  Parameters can be entered in any order, and have ");
        log_stdout("the form:");
        log_stdout("\n\n    [start] name separator [value]");
        log_stdout("\n\n  where:");
        log_stdout("\n\n    start == 0, 1, or 2 dashes (foo, -foo, --foo)");
        log_stdout("\n\n    name == parameter name (foo)"
                   "\n\n  Parameter name completion "
                   "will be attempted "
                   "\n  if a partial name is entered.");
        log_stdout("\n\n    separator == whitespace or equals sign "
                   "(foo=bar, foo bar)");
        log_stdout("\n\n    value == string value for the parameter");
        log_stdout("\n\n Strings with whitespace need to be "
                   "double quoted."
                   "\n    (--foo=\"some string\")");
    }

    if (mode == HELP_MODE_FULL && mod->descr) {
        log_stdout("\n\n  Description:");
        help_write_lines(mod->descr, 4, TRUE);
    }

    if (cliname) {
        cli = ncx_find_object(mod, cliname);
        if (!cli) {
            log_error("\nhelp: CLI Object %s not found", cliname);
            SET_ERROR(ERR_NCX_DEF_NOT_FOUND);
            return;
        } else if (cli->objtype == OBJ_TYP_CONTAINER) {
            log_stdout("\n\n Command Line Parameters");
            log_stdout("\n\n Key:  parm-name [built-in-type] [d:default]\n");


            if (mode == HELP_MODE_BRIEF) {
                usemode = HELP_MODE_NORMAL;
            } else {
                usemode = HELP_MODE_FULL;
            }
                
            obj_dump_datadefQ(obj_get_datadefQ(cli), 
                              usemode, 
                              nestlevel, 
                              4);
            log_stdout("\n");
        }
    }

    if (obj_any_rpcs(&mod->datadefQ) && mode == HELP_MODE_FULL) {
        log_stdout("\n\n  Local Commands\n");
        dump_rpcQ(&mod->datadefQ, mode, 4);
    }

}  /* help_program_module */
Exemple #5
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 */
/********************************************************************
* FUNCTION agt_hello_dispatch
*
* Handle an incoming <hello> message from the client
*
* INPUTS:
*   scb == session control block
*   top == top element descriptor
*********************************************************************/
void 
    agt_hello_dispatch (ses_cb_t *scb,
                        xml_node_t *top)
{
    assert( scb && "scb is NULL!" );
    assert( top && "top is NULL!" );

    if (LOGDEBUG2) {
        log_debug2("\nagt_hello: got node");
        if (LOGDEBUG3) {
            xml_dump_node(top);
        }
    }

    /* only process this message in hello wait state */
    if (scb->state != SES_ST_HELLO_WAIT) {
        log_info("\nagt_hello dropped, wrong state "
                 "(%d) for session %d", scb->state, scb->sid);
        mytotals->inBadHellos++;
        mytotals->droppedSessions++;
        agt_ses_request_close(scb, scb->sid, SES_TR_BAD_HELLO);
        return;
    }

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

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

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

    /* parse a manager hello message */
    if (res == NO_ERR) {
        res = agt_val_parse_nc(scb, &msg, obj, top, NCX_DC_STATE, val);
    }
    
    /* check that the NETCONF base capability is included
     * and it matches the server protocol version
     */
    if (res == NO_ERR) {
        res = check_manager_hello(scb, val);
    }

    /* report first error and close session */
    if (res != NO_ERR) {
        if (LOGINFO) {
            log_info("\nagt_connect error (%s), dropping session %d",
                     get_error_string(res), scb->sid);
        }
        mytotals->inBadHellos++;
        mytotals->droppedSessions++;
        agt_ses_request_close(scb, scb->sid, SES_TR_BAD_HELLO);

    } else {
        scb->state = SES_ST_IDLE;
        scb->active = TRUE;
        /* start the timer for the first rpc request */
        (void)time(&scb->last_rpc_time);

        if (LOGDEBUG) {
            log_debug("\nSession %d for %s@%s now active", 
                      scb->sid, scb->username, scb->peeraddr);
            if (ses_get_protocol(scb) == NCX_PROTO_NETCONF11) {
                log_debug_append(" (base:1.1)");
            } else {
                log_debug_append(" (base:1.0)");
            }
        }
    }

    if (val) {
        val_free_value(val);
    }

} /* agt_hello_dispatch */
Exemple #7
0
/********************************************************************
* FUNCTION agt_cli_process_input
*
* Process the param line parameters against the hardwired
* parmset for the netconfd program
*
* INPUTS:
*    argc == argument count
*    argv == array of command line argument strings
*    agt_profile == agent profile struct to fill in
*    showver == address of version return quick-exit status
*    showhelpmode == address of help return quick-exit status
*
* OUTPUTS:
*    *agt_profile is filled in, with parms gathered or defaults
*    *showver == TRUE if user requsted version quick-exit mode
*    *showhelpmode == requested help mode 
*                     (none, breief, normal, full)
*
* RETURNS:
*    NO_ERR if all goes well
*********************************************************************/
status_t
    agt_cli_process_input (int argc,
                           char *argv[],
                           agt_profile_t *agt_profile,
                           boolean *showver,
                           help_mode_t *showhelpmode)
{
    ncx_module_t          *mod;
    obj_template_t        *obj;
    val_value_t           *valset, *val;
    FILE                  *fp;
    status_t               res;
    boolean                test;

#ifdef DEBUG
    if (!argv || !agt_profile || !showver || !showhelpmode) {
        return SET_ERROR(ERR_INTERNAL_PTR);
    }
#endif

    *showver = FALSE;
    *showhelpmode = HELP_MODE_NONE;

    /* find the parmset definition in the registry */
    obj = NULL;
    mod = ncx_find_module(AGT_CLI_MODULE, NULL);
    if (mod) {
        obj = ncx_find_object(mod, AGT_CLI_CONTAINER);
    }
    if (!obj) {
        log_error("\nError: netconfd module with CLI definitions not loaded");
        return ERR_NCX_NOT_FOUND;
    }

    /* parse the command line against the object template */
    res = NO_ERR;
    valset = NULL;
    if (argc > 0) {
        valset = cli_parse(NULL,
                           argc, 
                           argv, 
                           obj,
                           FULLTEST, 
                           PLAINMODE, 
                           TRUE, 
                           CLI_MODE_PROGRAM,
                           &res);
        if (res != NO_ERR) {
            if (valset) {
                val_free_value(valset);
            }
            return res;
        }
    }

    if (valset != NULL) {
        /* transfer the parmset values */
        set_server_profile(valset, agt_profile);

        /* next get any params from the conf file */
        val = val_find_child(valset, 
                             AGT_CLI_MODULE, 
                             NCX_EL_CONFIG);
        if (val) {
            if (val->res == NO_ERR) {
                /* try the specified config location */
                agt_profile->agt_conffile = VAL_STR(val);
                res = conf_parse_val_from_filespec(VAL_STR(val), 
                                                   valset, 
                                                   TRUE, 
                                                   TRUE);
                if (res != NO_ERR) {
                    val_free_value(valset);
                    return res;
                } else {
                    /* transfer the parmset values again */
                    set_server_profile(valset, agt_profile);
                }
            }
        } else {
            fp = fopen((const char *)AGT_DEF_CONF_FILE, "r");
            if (fp != NULL) {
                fclose(fp);

                /* use default config location */
                res = conf_parse_val_from_filespec(AGT_DEF_CONF_FILE, 
                                                   valset, 
                                                   TRUE, 
                                                   TRUE);
                if (res != NO_ERR) {
                    val_free_value(valset);
                    return res;
                } else {
                    /* transfer the parmset values again */
                    set_server_profile(valset, agt_profile);
                }
            }
        }

        /* set the logging control parameters */
        val_set_logging_parms(valset);

        /* audit-log-append param */
        val = val_find_child(valset, 
                             AGT_CLI_MODULE, 
                             NCX_EL_AUDIT_LOG_APPEND);
        if (val && val->res == NO_ERR) {
            test = TRUE;
        } else {
            test = FALSE;
        }

        /* audit-log param */
        val = val_find_child(valset, AGT_CLI_MODULE, NCX_EL_AUDIT_LOG);
        if (val && val->res == NO_ERR) {
            xmlChar *filespec = ncx_get_source(VAL_STR(val), &res);
            if (filespec == NULL) {
                log_error("\nError: get source for audit log failed");
                return res;
            }
            res = log_audit_open((const char *)filespec, test, TRUE);
            if (res == NO_ERR) {
                if (LOGDEBUG) {
                    log_debug("\nAudit log '%s' opened for %s",
                              filespec,
                              (test) ? "append" : "write");
                }
            } else {
                log_error("\nError: open audit log '%s' failed",
                          filespec);
            }
            m__free(filespec);
            if (res != NO_ERR) {
                return res;
            }
        }

        /* set the file search path parms */
        res = val_set_path_parms(valset);
        if (res != NO_ERR) {
            return res;
        }

        /* set the warning control parameters */
        res = val_set_warning_parms(valset);
        if (res != NO_ERR) {
            return res;
        }

        /* set the feature code generation parameters */
        res = val_set_feature_parms(valset);
        if (res != NO_ERR) {
            return res;
        }

        /* check the subdirs parameter */
        res = val_set_subdirs_parm(valset);
        if (res != NO_ERR) {
            return res;
        }

        /* check the protocols parameter */
        res = val_set_protocols_parm(valset);
        if (res != NO_ERR) {
            return res;
        }

        /* check the system-sorted param */
        val = val_find_child(valset, AGT_CLI_MODULE, NCX_EL_SYSTEM_SORTED);
        if (val && val->res == NO_ERR) {
            agt_profile->agt_system_sorted = VAL_BOOL(val);
        }

        /* version param handled externally */

        /* check if version mode requested */
        val = val_find_child(valset, AGT_CLI_MODULE, NCX_EL_VERSION);
        *showver = (val) ? TRUE : FALSE;

        /* check if help mode requested */
        val = val_find_child(valset, AGT_CLI_MODULE, NCX_EL_HELP);
        if (val) {
            *showhelpmode = HELP_MODE_NORMAL;

            /* help submode parameter (brief/normal/full) */
            val = val_find_child(valset, AGT_CLI_MODULE, NCX_EL_BRIEF);
            if (val) {
                *showhelpmode = HELP_MODE_BRIEF;
            } else {
                /* full parameter */
                val = val_find_child(valset, AGT_CLI_MODULE, NCX_EL_FULL);
                if (val) {
                    *showhelpmode = HELP_MODE_FULL;
                }
            }
        }
    }

    /* cleanup and exit
     * handoff the malloced 'valset' memory here 
     */
    cli_val = valset;

    return res;

} /* agt_cli_process_input */
Exemple #8
0
/********************************************************************
* FUNCTION mgr_rpc_dispatch
*
* Dispatch an incoming <rpc-reply> response
* handle the <rpc-reply> element
* called by mgr_top.c: 
* This function is registered with top_register_node
* for the module 'netconf', top-node 'rpc-reply'
*
* INPUTS:
*   scb == session control block
*   top == top element descriptor
*********************************************************************/
void 
    mgr_rpc_dispatch (ses_cb_t *scb,
                      xml_node_t *top)
{
    obj_template_t          *rpyobj;
    mgr_rpc_rpy_t           *rpy;
    mgr_rpc_req_t           *req;
    xml_attr_t              *attr;
    xmlChar                 *msg_id;
    ncx_module_t            *mod;
    mgr_rpc_cbfn_t           handler;
    ncx_num_t                num;
    status_t                 res;

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

    /* init local vars */
    res = NO_ERR;
    msg_id = NULL;
    req = NULL;

    /* make sure any real session has been properly established */
    if (scb->type != SES_TYP_DUMMY && scb->state != SES_ST_IDLE) {
        log_error("\nError: mgr_rpc: skipping incoming message '%s'",
                  top->qname);
        mgr_xml_skip_subtree(scb->reader, top);
        return;
    }

    /* check if the reply template is already cached */
    rpyobj = NULL;
    mod = ncx_find_module(NC_MODULE, NULL);
    if (mod != NULL) {
        rpyobj = ncx_find_object(mod, NC_RPC_REPLY_TYPE);
    }
    if (rpyobj == NULL) {
        SET_ERROR(ERR_NCX_DEF_NOT_FOUND);
        mgr_xml_skip_subtree(scb->reader, top);
        return;
    }

    /* get the NC RPC message-id attribute; should be present
     * because the send-rpc function put a message-id in <rpc>
     */
    attr = xml_find_attr(top, 0, NCX_EL_MESSAGE_ID);
    if (attr && attr->attr_val) {
        msg_id = xml_strdup(attr->attr_val);
    }
    if (msg_id == NULL) {
        mgr_xml_skip_subtree(scb->reader, top);
        log_info("\nmgr_rpc: incoming message with no message-id");
        return;
    }       

    /* the current node is 'rpc-reply' in the netconf namespace
     * First get a new RPC reply struct
     */
    rpy = new_reply();
    if (rpy == NULL) {
        m__free(msg_id);
        log_error("\nError: mgr_rpc: skipping incoming message");
        mgr_xml_skip_subtree(scb->reader, top);
        return;
    } else {
        rpy->msg_id = msg_id;
    }
    
    /* get the NCX RPC group-id attribute if present */
    attr = xml_find_attr(top, xmlns_ncx_id(), NCX_EL_GROUP_ID);
    if (attr && attr->attr_val) {
        res = ncx_decode_num(attr->attr_val, NCX_BT_UINT32, &num);
        if (res == NO_ERR) {
            rpy->group_id = num.u;
        }
    }

    /* find the request that goes with this reply */
    if (rpy->msg_id != NULL) {
        req = find_request(scb, rpy->msg_id);
        if (req == NULL) {
#ifdef MGR_RPC_DEBUG
            log_debug("\nmgr_rpc: got request found for msg (%s) "
                      "on session %d", 
                      rpy->msg_id, 
                      scb->sid);
#endif
            mgr_xml_skip_subtree(scb->reader, top);
            mgr_rpc_free_reply(rpy);
            return;
        } else {
            dlq_remove(req);
        }
    }

    /* have a request/reply pair, so parse the reply 
     * as a val_value_t tree, stored in rpy->reply
     */
    rpy->res = mgr_val_parse_reply(scb, 
                                   rpyobj, 
                                   (req != NULL) ?
                                   req->rpc : ncx_get_gen_anyxml(),
                                   top, 
                                   rpy->reply);
    if (rpy->res != NO_ERR && LOGINFO) {
        log_info("\nmgr_rpc: got invalid reply on session %d (%s)",
                 scb->sid, get_error_string(rpy->res));
    }

    /* check that there is nothing after the <rpc-reply> element */
    if (rpy->res==NO_ERR && 
        !xml_docdone(scb->reader) && LOGINFO) {
        log_info("\nmgr_rpc: got extra nodes in reply on session %d",
                 scb->sid);
    }

    /* invoke the reply handler */
    if (req != NULL) { 
        handler = (mgr_rpc_cbfn_t)req->replycb;
        (*handler)(scb, req, rpy);
    }

    /* only reset the session state to idle if was not changed
     * to SES_ST_SHUTDOWN_REQ during this RPC call
     */
    if (scb->state == SES_ST_IN_MSG) {
        scb->state = SES_ST_IDLE;
    }

#ifdef MGR_RPC_DEBUG
    print_errors();
    clear_errors();
#endif

} /* mgr_rpc_dispatch */