/********************************************************************
 * 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 */
void agt_not_queue_notification_cb_unregister( const xmlChar *modname )
{
    assert( modname );

    agt_cb_queue_notification_set_t* cbSet = find_callback_set( modname );

    if ( cbSet )
    {
        dlq_remove( cbSet );
        free_callback_set( cbSet );
    }
}
示例#3
0
void agt_commit_complete_unregister( const xmlChar *modname )
{
    assert( modname );

    agt_cb_commit_complete_set_t* cbSet = find_callback_set( modname );

    if ( cbSet )
    {
        dlq_remove( cbSet );
        free_callback_set( cbSet );
    }
}
/********************************************************************
 * FUNCTION unregister_notif_event_handler
 * 
 * Unregister an event callback function
 * This is optional -- data structures will get cleaned up
 * when the program terminates
 * Assumes function is registered once!!!
 * Caller must make sure to register each callback only once
 * or call this function multiple times
 *
 * INPUTS:
 *   modname == module defining the notification
 *   event == notification event name
 *   cbfn == function to unregister
 *********************************************************************/
void
    unregister_notif_event_handler (const xmlChar *modname,
                                    const xmlChar *event,
                                    yangcli_notif_cbfn_t cbfn)
{
    event_cb_t *cb = find_event_cb(modname, event, NULL);
    while (cb) {
        if (cb->cbfn == cbfn) {
            dlq_remove(cb);
            free_event_cb(cb);
            return;
        }
        cb = find_event_cb(modname, event, cb);
    }

}  /* unregister_notif_event_handler */
示例#5
0
/********************************************************************
* FUNCTION mgr_rpc_timeout_requestQ
*
* Clean the request Q of mgr_rpc_req_t entries
* Only remove the entries that have timed out
*
* returning number of msgs timed out
* need a callback-based cleanup later on
* to support N concurrent requests per agent
*
* INPUTS:
*   reqQ == Q of entries to check
*
* RETURNS:
*   number of request timed out
*********************************************************************/
uint32
    mgr_rpc_timeout_requestQ (dlq_hdr_t *reqQ)
{
    mgr_rpc_req_t *req, *nextreq;
    time_t         timenow;
    double         timediff;
    uint32         deletecount;

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

    deletecount = 0;
    (void)uptime(&timenow);

    for (req = (mgr_rpc_req_t *)dlq_firstEntry(reqQ);
         req != NULL;
         req = nextreq) {

        nextreq = (mgr_rpc_req_t *)dlq_nextEntry(req);

        if (!req->timeout) {
            continue;
        }

        timediff = difftime(timenow, req->starttime);
        if (timediff >= (double)req->timeout) {
            log_info("\nmgr_rpc: deleting timed out request '%s'",
                     req->msg_id);
            deletecount++;
            dlq_remove(req);
            mgr_rpc_free_request(req);
        }
    }

    return deletecount;

} /* mgr_rpc_timeout_requestQ */
示例#6
0
/********************************************************************
* FUNCTION xml_msg_clean_defns_attr
*
* Get rid of an xmlns=foo default attribute
*
* INPUTS:
*    attrs == xmlns_attrs_t Q to process
*
* OUTPUTS:
*   *attrs will be cleaned as needed,
*
* RETURNS:
*   status
*********************************************************************/
status_t
xml_msg_clean_defns_attr (xml_attrs_t *attrs)
{
    xml_attr_t  *attr, *nextattr;
    uint32       len, len2;

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

    len = xml_strlen(XMLNS);

    for (attr = (xml_attr_t *)xml_first_attr(attrs);
            attr != NULL;
            attr = nextattr) {


        nextattr = (xml_attr_t *)xml_next_attr(attr);

        len2 = xml_strlen(attr->attr_qname);
        if (len2 >= len) {
            if (!xml_strncmp(attr->attr_qname, XMLNS, len)) {
                if (len == len2) {
                    /* this xmlns=foo is getting toosed so
                     * the netconf NSID can be the default
                     */
                    dlq_remove(attr);
                    xml_free_attr(attr);
                    return NO_ERR;
                } /* else xmlns:foo=bar found */
            }  /* else not xmlns */
        }  /* else not 'xmlns' */
    }

    return NO_ERR;

}  /* xml_msg_clean_defns_attr */
示例#7
0
文件: conf.c 项目: 0xDEC0DE8/OpenYuma
/********************************************************************
* FUNCTION parse_parm
* 
* Parse, and fill one val_value_t struct during
* processing of a parmset
*
* Error messages are printed by this function!!
* Do not duplicate error messages upon error return
*
*
* INPUTS:
*   tkc == token chain
*   val == container val to fill in
*   keepvals == TRUE to save existing parms in 'ps', as needed
*               FALSE to overwrite old parms in 'ps', as needed
*
* RETURNS:
*   status of the operation
*********************************************************************/
static status_t 
    parse_parm (tk_chain_t  *tkc,
                val_value_t *val,
                boolean keepvals)
{
    obj_template_t         *obj;
    const xmlChar          *modname;
    val_value_t            *curparm, *newparm;
    status_t                res;
    ncx_iqual_t             iqual;
    boolean                 match, usewarning, isdefault;

    
    /* get the next token, which must be a TSTRING
     * representing the parameter name 
     */
    if (TK_CUR_TYP(tkc) != TK_TT_TSTRING) {
        res = ERR_NCX_WRONG_TKTYPE;
        ncx_conf_exp_err(tkc, res, "parameter name");
        return res;
    }

    curparm = NULL;
    usewarning = ncx_warning_enabled(ERR_NCX_CONF_PARM_EXISTS);

    /* check if this TSTRING is a parameter in this parmset
     * make sure to always check for prefix:identifier
     * This is automatically processed in tk.c
     */
    if (TK_CUR_MOD(tkc)) {
        modname = xmlns_get_module
            (xmlns_find_ns_by_prefix(TK_CUR_MOD(tkc)));
        if (modname) {
            curparm = val_find_child(val, 
                                     modname,
                                     TK_CUR_VAL(tkc));
        }
    }  else {
        curparm = val_find_child(val, 
                                 val_get_mod_name(val),
                                 TK_CUR_VAL(tkc));
    }
        
    if (curparm) {
        obj = curparm->obj;
    } else {
        obj = obj_find_child(val->obj, 
                             TK_CUR_MOD(tkc),
                             TK_CUR_VAL(tkc));
    }
    if (!obj) {
        res = ERR_NCX_UNKNOWN_PARM;
        if (TK_CUR_MOD(tkc)) {
            log_error("\nError: parameter '%s:%s' not found",
                      TK_CUR_MOD(tkc),
                      TK_CUR_VAL(tkc));
        } else {
            log_error("\nError: parameter '%s' not found",
                      TK_CUR_VAL(tkc));
        }
        ncx_conf_exp_err(tkc, res, "parameter name");
        return res;
    }

    /* got a valid parameter name, now create a new parm
     * even if it may not be kept.  There are corner-cases
     * that require the new value be parsed before knowing
     * if a parm value is a duplicate or not
     */
    newparm = val_new_value();
    if (!newparm) {
        res = ERR_INTERNAL_MEM;
        ncx_print_errormsg(tkc, NULL, res);
        return res;
    }
    val_init_from_template(newparm, obj);

    /* parse the parameter value */
    res = parse_val(tkc, obj, newparm);
    if (res != NO_ERR) {
        val_free_value(newparm);
        return res;
    }

    /* check if a potential current value exists, or just
     * add the newparm to the parmset
     */
    if (curparm) {
        isdefault = val_set_by_default(curparm);
        iqual = obj_get_iqualval(obj);
        if (iqual == NCX_IQUAL_ONE || iqual == NCX_IQUAL_OPT) {
            /* only one allowed, check really a match */
            match = TRUE;
            if (val_has_index(curparm) &&
                !val_index_match(newparm, curparm)) {
                match = FALSE;
            }

            if (!match) {
                val_add_child(newparm, val);
            } else if (isdefault) {
                dlq_remove(curparm);
                val_free_value(curparm);
                val_add_child(newparm, val);
            } else if (keepvals) {
                if (usewarning) {
                    /* keep current value and toss new value */
                    log_warn("\nWarning: Parameter '%s' already exists. "
                             "Not using new value\n", 
                             curparm->name);
                    if (LOGDEBUG2) {
                        val_dump_value(newparm, NCX_DEF_INDENT);
                        log_debug2("\n");
                    }
                }
                val_free_value(newparm);
            } else {
                if (usewarning) {
                    /* replace current value and warn old value tossed */
                    log_warn("\nconf: Parameter '%s' already exists. "
                             "Overwriting with new value\n",
                             curparm->name);
                    if (LOGDEBUG2) {
                        val_dump_value(newparm, NCX_DEF_INDENT);
                        log_debug2("\n");
                    }
                }
                dlq_remove(curparm);
                val_free_value(curparm);
                val_add_child(newparm, val);
            }
        } else {
            /* mutliple instances allowed */
            val_add_child(newparm, val);
        }
    } else {
        val_add_child(newparm, val);
    }

    return NO_ERR;

}  /* parse_parm */
示例#8
0
/********************************************************************
* FUNCTION agt_ses_process_first_ready
*
* Check the readyQ and process the first message, if any
*
* RETURNS:
*     TRUE if a message was processed
*     FALSE if the readyQ was empty
*********************************************************************/
boolean
    agt_ses_process_first_ready (void)
{
    ses_cb_t     *scb;
    ses_ready_t  *rdy;
    ses_msg_t    *msg;
    status_t      res;
    uint32        cnt;
    xmlChar       buff[32];

    rdy = ses_msg_get_first_inready();
    if (!rdy) {
        return FALSE;
    }

    /* get the session control block that rdy is embedded into */
    scb = agtses[rdy->sid];

    if (scb == NULL) {
        log_debug("\nagt_ses: session %d gone", rdy->sid);
        return FALSE;
    }

    log_debug2("\nagt_ses msg ready for session %d", scb->sid);

    /* check the session control block state */
    if (scb->state >= SES_ST_SHUTDOWN_REQ) {
        /* don't process the message or even it mark it
         * It will be cleaned up when the session is freed
         */
        log_debug("\nagt_ses drop input, session %d shutting down", 
                  scb->sid);
        return TRUE;
    }

    /* make sure a message is really there */
    msg = (ses_msg_t *)dlq_firstEntry(&scb->msgQ);
    if (!msg || !msg->ready) {
        SET_ERROR(ERR_INTERNAL_PTR);
        log_error("\nagt_ses ready Q message not correct");
        if (msg && scb->state != SES_ST_INIT) {
            /* do not echo the ncx-connect message */
            cnt = xml_strcpy(buff, 
                             (const xmlChar *)"Incoming msg for session ");
            snprintf((char *)(&buff[cnt]), sizeof(buff) - cnt, "%u", scb->sid);
            ses_msg_dump(msg, buff);
        }
            
        return FALSE;
    } else if (LOGDEBUG2 && scb->state != SES_ST_INIT) {
        cnt = xml_strcpy(buff, 
                         (const xmlChar *)"Incoming msg for session ");
        snprintf((char *)(&buff[cnt]), sizeof(buff) - cnt, "%u", scb->sid);
        ses_msg_dump(msg, buff);
    }

    /* setup the XML parser */
    if (scb->reader) {
            /* reset the xmlreader */
        res = xml_reset_reader_for_session(ses_read_cb,
                                           NULL, 
                                           scb, 
                                           scb->reader);
    } else {
        res = xml_get_reader_for_session(ses_read_cb,
                                         NULL, 
                                         scb, 
                                         &scb->reader);
    }

    /* process the message */
    if (res == NO_ERR) {
        /* process the message 
         * the scb pointer may get deleted !!!
         */
        agt_top_dispatch_msg(&scb);
    } else {
        if (LOGINFO) {
            log_info("\nReset xmlreader failed for session %d (%s)",
                     scb->sid, 
                     get_error_string(res));
        }
        agt_ses_kill_session(scb, 0, SES_TR_OTHER);
        scb = NULL;
    }

    if (scb) {
        /* free the message that was just processed */
        dlq_remove(msg);
        ses_msg_free_msg(scb, msg);


        /* check if any messages left for this session */
        msg = (ses_msg_t *)dlq_firstEntry(&scb->msgQ);
        if (msg && msg->ready) {
            ses_msg_make_inready(scb);
        }
    }

    return TRUE;
    
}  /* agt_ses_process_first_ready */
示例#9
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 */
示例#10
0
/********************************************************************
* FUNCTION mgr_rpc_send_request
*
* Send an <rpc> request to the agent on the specified session
* non-blocking send, reply function will be called when
* one is received or a timeout occurs
*
* INPUTS:
*   scb == session control block
*   req == request to send
*   rpyfn == reply callback function
*
* RETURNS:
*   status
*********************************************************************/
status_t
    mgr_rpc_send_request (ses_cb_t *scb,
                          mgr_rpc_req_t *req,
                          mgr_rpc_cbfn_t rpyfn)
{
    xml_msg_hdr_t msg;
    xml_attr_t   *attr;
    status_t      res;
    boolean       anyout;
    xmlns_id_t    nc_id;

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

#ifdef MGR_HELLO_DEBUG
    log_debug2("\nmgr sending RPC request %s on session %d", 
               req->msg_id, scb->sid);
#endif

    anyout = FALSE;
    xml_msg_init_hdr(&msg);
    nc_id = xmlns_nc_id();

    /* make sure the message-id attribute is not already present */
    attr = xml_find_attr_q(&req->attrs, 0, NCX_EL_MESSAGE_ID);
    if (attr) {
        dlq_remove(attr);
        xml_free_attr(attr);
    }

    /* setup the prefix map with the NETCONF (and maybe NCX) namespace */
    res = xml_msg_build_prefix_map(&msg, 
                                   &req->attrs, 
                                   FALSE, 
                                   (req->data->nsid == xmlns_ncx_id()));

    /* add the message-id attribute */
    if (res == NO_ERR) {
        res = xml_add_attr(&req->attrs, 
                           0, 
                           NCX_EL_MESSAGE_ID,
                           req->msg_id);
    }

    /* set perf timestamp in case response timing active */
    gettimeofday(&req->perfstarttime, NULL);     

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

    /* start the <rpc> element */
    if (res == NO_ERR) {
        anyout = TRUE;
        xml_wr_begin_elem_ex(scb, 
                             &msg, 
                             0, 
                             nc_id, 
                             NCX_EL_RPC, 
                             &req->attrs, 
                             ATTRQ, 
                             0, 
                             START);
    }
    
    /* send the method and parameters */
    if (res == NO_ERR) {
        xml_wr_full_val(scb, &msg, req->data, NCX_DEF_INDENT);
    }

    /* finish the <rpc> element */
    if (res == NO_ERR) {
        xml_wr_end_elem(scb, &msg, nc_id, NCX_EL_RPC, 0);
    }

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

    if (res == NO_ERR) {
        req->replycb = rpyfn;
        add_request(scb, req);
    }

    xml_msg_clean_hdr(&msg);
    return res;

}  /* mgr_rpc_send_request */