Пример #1
0
/********************************************************************
* FUNCTION y_starter_starter_kill_vnf_validate
* 
* RPC validation phase
* All YANG constraints have passed at this point.
* Add description-stmt checks in this function.
* 
* INPUTS:
*     see agt/agt_rpc.h for details
* 
* RETURNS:
*     error status
********************************************************************/
static status_t y_starter_starter_kill_vnf_validate (
    ses_cb_t *scb,
    rpc_msg_t *msg,
    xml_node_t *methnode)
{
    status_t res = NO_ERR;
    val_value_t *errorval = NULL;

    val_value_t *vnfID_val;
    const xmlChar *vnfID;

    vnfID_val = val_find_child(
        msg->rpc_input,
        y_starter_M_starter,
        y_starter_N_vnfID);
    if (vnfID_val != NULL && vnfID_val->res == NO_ERR) {
        vnfID = VAL_STRING(vnfID_val);
    }

    if (res != NO_ERR) {
        agt_record_error(
            scb,
            &msg->mhdr,
            NCX_LAYER_OPERATION,
            res,
            methnode,
            (errorval) ? NCX_NT_VAL : NCX_NT_NONE,
            errorval,
            (errorval) ? NCX_NT_VAL : NCX_NT_NONE,
            errorval);
    }
    return res;

} /* y_starter_starter_kill_vnf_validate */
Пример #2
0
/********************************************************************
* FUNCTION y_ietf_netconf_partial_lock_partial_unlock_validate
* 
* RPC validation phase
* All YANG constraints have passed at this point.
* Add description-stmt checks in this function.
* 
* INPUTS:
*     see agt/agt_rpc.h for details
* 
* RETURNS:
*     error status
********************************************************************/
static status_t
    y_ietf_netconf_partial_lock_partial_unlock_validate (
        ses_cb_t *scb,
        rpc_msg_t *msg,
        xml_node_t *methnode)
{
    val_value_t *lock_id_val;
    cfg_template_t *running;
    plock_cb_t *plcb;
    uint32 lock_id;
    status_t res;

    res = NO_ERR;

    lock_id_val = val_find_child(
        msg->rpc_input,
        y_ietf_netconf_partial_lock_M_ietf_netconf_partial_lock,
        y_ietf_netconf_partial_lock_N_lock_id);
    if (lock_id_val == NULL || lock_id_val->res != NO_ERR) {
        return ERR_NCX_INVALID_VALUE;
    }

    lock_id = VAL_UINT(lock_id_val);

    running = cfg_get_config_id(NCX_CFGID_RUNNING);

    plcb = cfg_find_partial_lock(running, lock_id);

    if (plcb == NULL || (plock_get_sid(plcb) != SES_MY_SID(scb))) {
        res = ERR_NCX_INVALID_VALUE;
        agt_record_error(
            scb,
            &msg->mhdr,
            NCX_LAYER_OPERATION,
            res,
            methnode,
            NCX_NT_NONE,
            NULL,
            NCX_NT_VAL,
            lock_id_val);
    } else {
        msg->rpc_user1 = plcb;
    }
    
    return res;

} /* y_ietf_netconf_partial_lock_partial_unlock_validate */
Пример #3
0
/********************************************************************
* FUNCTION y_starter_starter_start_vnf_validate
* 
* RPC validation phase
* All YANG constraints have passed at this point.
* Add description-stmt checks in this function.
* 
* INPUTS:
*     see agt/agt_rpc.h for details
* 
* RETURNS:
*     error status
********************************************************************/
static status_t y_starter_starter_start_vnf_validate (
    ses_cb_t *scb,
    rpc_msg_t *msg,
    xml_node_t *methnode)
{
    status_t res = NO_ERR;
    val_value_t *errorval = NULL;

    val_value_t *port_val;
    const xmlChar *port;
    val_value_t *clickDescription_val;
    const xmlChar *clickDescription;

    port_val = val_find_child(
        msg->rpc_input,
        y_starter_M_starter,
        y_starter_N_port);
    if (port_val != NULL && port_val->res == NO_ERR) {
        port = VAL_STRING(port_val);
    }

    clickDescription_val = val_find_child(
        msg->rpc_input,
        y_starter_M_starter,
        y_starter_N_clickDescription);
    if (clickDescription_val != NULL && clickDescription_val->res == NO_ERR) {
        clickDescription = VAL_STRING(clickDescription_val);
    }

    if (res != NO_ERR) {
        agt_record_error(
            scb,
            &msg->mhdr,
            NCX_LAYER_OPERATION,
            res,
            methnode,
            (errorval) ? NCX_NT_VAL : NCX_NT_NONE,
            errorval,
            (errorval) ? NCX_NT_VAL : NCX_NT_NONE,
            errorval);
    }
    return res;

} /* y_starter_starter_start_vnf_validate */
Пример #4
0
/********************************************************************
* FUNCTION y_toaster_cancel_toast_validate
* 
* RPC validation phase
* All YANG constriants have passed at this point.
* Add description-stmt checks in this function.
* 
* INPUTS:
*     see agt/agt_rpc.h for details
* 
* RETURNS:
*     error status
********************************************************************/
static status_t
    y_toaster_cancel_toast_validate (
        ses_cb_t *scb,
        rpc_msg_t *msg,
        xml_node_t *methnode)
{
    status_t res;
    val_value_t *errorval;
    const xmlChar *errorstr;

    res = NO_ERR;
    errorval = NULL;
    errorstr = NULL;

    /* added code starts here */
    if (toaster_enabled) {
        /* toaster service enabled, check if not in use */
        if (!toaster_toasting) {
            res = ERR_NCX_OPERATION_FAILED;
        }
    } else {
        /* toaster service disabled */
        res = ERR_NCX_RESOURCE_DENIED;
    }
    /* added code ends here */

    /* if error: set the res, errorstr, and errorval parms */
    if (res != NO_ERR) {
        agt_record_error(
            scb,
            &msg->mhdr,
            NCX_LAYER_OPERATION,
            res,
            methnode,
            NCX_NT_STRING,
            errorstr,
            NCX_NT_VAL,
            errorval);
    }
    
    return res;

} /* y_toaster_cancel_toast_validate */
Пример #5
0
/********************************************************************
* FUNCTION y_starter_starter_get_processes_validate
* 
* RPC validation phase
* All YANG constraints have passed at this point.
* Add description-stmt checks in this function.
* 
* INPUTS:
*     see agt/agt_rpc.h for details
* 
* RETURNS:
*     error status
********************************************************************/
static status_t y_starter_starter_get_processes_validate (
    ses_cb_t *scb,
    rpc_msg_t *msg,
    xml_node_t *methnode)
{
    status_t res = NO_ERR;
    val_value_t *errorval = NULL;


    if (res != NO_ERR) {
        agt_record_error(
            scb,
            &msg->mhdr,
            NCX_LAYER_OPERATION,
            res,
            methnode,
            (errorval) ? NCX_NT_VAL : NCX_NT_NONE,
            errorval,
            (errorval) ? NCX_NT_VAL : NCX_NT_NONE,
            errorval);
    }
    return res;

} /* y_starter_starter_get_processes_validate */
Пример #6
0
/********************************************************************
* FUNCTION starter_starter_edit
* 
* Edit database object callback
* Path: /starter
* Add object instrumentation in COMMIT phase.
* 
* INPUTS:
*     see agt/agt_cb.h for details
* 
* RETURNS:
*     error status
********************************************************************/
static status_t starter_starter_edit (
    ses_cb_t *scb,
    rpc_msg_t *msg,
    agt_cbtyp_t cbtyp,
    op_editop_t editop,
    val_value_t *newval,
    val_value_t *curval)
{
    status_t res = NO_ERR;
    val_value_t *errorval = (curval) ? curval : newval;

    if (LOGDEBUG) {
        log_debug("\nEnter starter_starter_edit callback for %s phase",
            agt_cbtype_name(cbtyp));
    }

    switch (cbtyp) {
    case AGT_CB_VALIDATE:
        /* description-stmt validation here */
        break;
    case AGT_CB_APPLY:
        /* database manipulation done here */
        break;
    case AGT_CB_COMMIT:
        /* device instrumentation done here */
        switch (editop) {
        case OP_EDITOP_LOAD:
            break;
        case OP_EDITOP_MERGE:
            break;
        case OP_EDITOP_REPLACE:
            break;
        case OP_EDITOP_CREATE:
            break;
        case OP_EDITOP_DELETE:
            break;
        default:
            res = SET_ERROR(ERR_INTERNAL_VAL);
        }

        if (res == NO_ERR) {
            res = agt_check_cache(&starter_val, newval, curval, editop);
        }
        
        break;
    case AGT_CB_ROLLBACK:
        /* undo device instrumentation here */
        break;
    default:
        res = SET_ERROR(ERR_INTERNAL_VAL);
    }

    if (res != NO_ERR) {
        agt_record_error(
            scb,
            &msg->mhdr,
            NCX_LAYER_CONTENT,
            res,
            NULL,
            (errorval) ? NCX_NT_VAL : NCX_NT_NONE,
            errorval,
            (errorval) ? NCX_NT_VAL : NCX_NT_NONE,
            errorval);
    }
    return res;

} /* starter_starter_edit */
Пример #7
0
/********************************************************************
* FUNCTION get_all_attrs
* 
*  Copy all the attributes from the current node to
*  the xml_attrs_t queue
*
* INPUTS:
*    scb == session control block
*    errnode == element node to use for reporting errors
*    msghdr  == msg hdr w/ Q to get any rpc-errors as found, 
*               NULL if not used
*    nserr == TRUE if unknown namespace should cause the
*             function to fail and the attr not to be saved 
*             This is the normal mode.
*          == FALSE and the namespace will be marked INVALID
*             but an error will not be returned
*
* OUTPUTS:
*   attrs Q contains 0 or more entries
*   *msghdr.errQ may have rpc-errors added to it
*
* RETURNS:
*   status of the operation
*   returns NO_ERR if all copied okay or even zero copied
*********************************************************************/
static status_t
    get_all_attrs (ses_cb_t *scb,
                   xml_node_t *errnode,
                   xml_attrs_t *attrs,
                   ncx_layer_t layer,
                   xml_msg_hdr_t *msghdr,
                   boolean nserr)
{
    /* check the attribute count first */
    int cnt = xmlTextReaderAttributeCount(scb->reader);
    if (cnt==0) {
        return NO_ERR;
    }

    const xmlChar *name = NULL;
    status_t res = NO_ERR;
    boolean xpatherror = FALSE;
    int ret = 0;

    /* move through the list of attributes */
    int i = 0;
    boolean done = FALSE;
    for (; i < cnt && !done; i++) {

        xmlChar *value = NULL;
        const xmlChar *badns = NULL;
        uint32 plen = 0;
        xmlns_id_t nsid = 0;

        res = NO_ERR;
        name = NULL;

        /* get the next attribute */
        if (i==0) {
            ret = xmlTextReaderMoveToFirstAttribute(scb->reader);
        } else {
            ret = xmlTextReaderMoveToNextAttribute(scb->reader);
        }
        if (ret != 1) {
            res = ERR_XML_READER_INTERNAL;
            done = TRUE;
        } else {
            /* get the attribute name */
            name = xmlTextReaderConstName(scb->reader);
            if (!name) {
                res = ERR_XML_READER_NULLNAME;
            } else {
                res = xml_check_ns(scb->reader, name, &nsid, &plen, &badns);
                if (!nserr && res != NO_ERR) {
                    /* mask invalid namespace as requested */
                    nsid = xmlns_inv_id();
                    plen = 0;
                    res = NO_ERR;
                }

                /* get the attribute value even if a NS error */
                value = xmlTextReaderValue(scb->reader);
                if (!value) {
                    res = ERR_XML_READER_NULLVAL;
                } else {
                    /* save the values as received, may be QName 
                     * only error that can occur is a malloc fail
                     */
                    xml_attr_t *attr =
                        xml_add_qattr(attrs, nsid, name, plen, value, &res);
                    if (!attr) {
                        res = ERR_INTERNAL_MEM;
                    } else {
                        /* special hack: do not know which
                         * attributes within an XML node
                         * are tagged as XPath strings at this point
                         * To save resources, only the 'select' and
                         * 'key' attributes are supported at this time.
                         */
                        if (!xml_strcmp(&name[plen], NCX_EL_SELECT)) {
                            res = NO_ERR;
                            attr->attr_xpcb = agt_new_xpath_pcb(scb, value, 
                                                                &res);
                            if (!attr->attr_xpcb) {
                                ;  /* res already set */
                            } else {
                                /* do a first pass parsing to resolve all
                                 * the prefixes and check well-formed XPath
                                 */
                                xpath_result_t *result =
                                    xpath1_eval_xmlexpr(scb->reader,
                                                        attr->attr_xpcb,
                                                        NULL, NULL,
                                                        FALSE, FALSE, &res);
                                if (res != NO_ERR) {
                                    xpatherror = TRUE;
                                }
                                xpath_free_result(result);
                            }
                        } else if (!xml_strcmp(&name[plen], NCX_EL_KEY)) {
                            res = NO_ERR;
                            attr->attr_xpcb =
                                agt_new_xpath_pcb(scb, value, &res);
                            if (!attr->attr_xpcb) {
                                ;  /* res already set */
                            } else {
                                res = xpath_yang_validate_xmlkey
                                    (scb->reader,
                                     attr->attr_xpcb,
                                     NULL,
                                     FALSE);
                                if (res != NO_ERR) {
                                    xpatherror = TRUE;
                                }
                            }
                        }
                    }
                }
            }
        }

        /* check the result */
        if (res != NO_ERR && msghdr) {

            /* need a dummy attribute struct to report this error */
            xml_attr_t errattr;
            memset(&errattr, 0x0, sizeof(xml_attr_t));
            errattr.attr_ns = xmlns_nc_id();
            errattr.attr_qname = name;
            errattr.attr_name = name;
            errattr.attr_val = value;

            /* save the error info */
            if (xpatherror) {
                res = ERR_NCX_INVALID_XPATH_EXPR;

                /* generate an invalid-value error */
                agt_record_attr_error(scb, 
                                      msghdr, 
                                      layer, 
                                      res,
                                      &errattr, 
                                      errnode, 
                                      NULL, 
                                      NCX_NT_NONE, 
                                      NULL);
            } else if (res==ERR_XML_READER_NULLVAL ||
                res==ERR_NCX_UNKNOWN_NAMESPACE) {
                /* generate a bad namespace error */
                agt_record_attr_error(scb, 
                                      msghdr, 
                                      layer, 
                                      res, 
                                      &errattr, 
                                      errnode, 
                                      badns,
                                      NCX_NT_NONE,
                                      NULL);
            } else {
                /* generate a generic error */
                agt_record_attr_error(scb, 
                                      msghdr, 
                                      layer, 
                                      res, 
                                      &errattr,
                                      errnode,
                                      NULL,
                                      NCX_NT_NONE, 
                                      NULL);
            }
        }

        if (value) {
            xmlFree(value);
        }
    }

    /* reset the current node to where we started */
    ret = xmlTextReaderMoveToElement(scb->reader);
    if (ret != 1) {
        if (msghdr) {
            res = ERR_XML_READER_INTERNAL;
            agt_record_error(scb, 
                             msghdr, 
                             layer, 
                             res, 
                             errnode, 
                             NCX_NT_STRING, 
                             name, 
                             NCX_NT_NONE, 
                             NULL);
        }
    }   

    return res;

}  /* get_all_attrs */
Пример #8
0
/********************************************************************
* FUNCTION consume_node
* 
* Internal consume XML node function
* see agt_xml_consume_node for details.
*
* EXTRA INPUTS:
*   eoferr == TRUE if an End of File error should be generated
*          == FALSE if not
*    nserr == TRUE if bad namespace should be checked
*          == FALSE if not
*    clean == TRUE is a string should be cleaned before returned 
*          == FALSE if a string node should be returned as-is
*
* RETURNS:
*   status of the operation
*   Try to fail on fatal errors only
*********************************************************************/
static status_t 
    consume_node (ses_cb_t *scb,
                  boolean advance,
                  xml_node_t *node,
                  ncx_layer_t layer,
                  xml_msg_hdr_t *msghdr,
                  boolean eoferr,
                  boolean nserr,
                  boolean clean)
{
    int             ret, nodetyp;
    const xmlChar  *badns;
    xmlChar        *valstr, *namestr;
    uint32          len;
    status_t        res, res2;
    boolean         done;

    /* init local vars */
    done = FALSE;
    res = NO_ERR;
    res2 = NO_ERR;
    badns = NULL;

    /* loop past any unused xmlTextReader node types */
    while (!done) {
        /* check if a new node should be read */
        if (advance) {
            /* advance the node pointer */
            ret = xmlTextReaderRead(scb->reader);
            if (ret != 1) {
                /* do not treat this as an internal error */
                res = ERR_XML_READER_EOF;
                if (msghdr && eoferr) {
                    /* generate an operation-failed error */
                    agt_record_error(scb, 
                                     msghdr, 
                                     layer, 
                                     res, 
                                     NULL, 
                                     NCX_NT_NONE,
                                     NULL, 
                                     NCX_NT_NONE,
                                     NULL);
                }
                return res;
            }
        }

        /* get the node depth to match the end node correctly */
        node->depth = xmlTextReaderDepth(scb->reader);
        if (node->depth == -1) {
            /* this never actaully happens */
            SET_ERROR(ERR_XML_READER_INTERNAL);
            node->depth = 0;
        }

        /* get the internal nodetype, check it and convert it */
        nodetyp = xmlTextReaderNodeType(scb->reader);
        switch (nodetyp) {
        case XML_ELEMENT_NODE:
            /* classify element as empty or start */
            if (xmlTextReaderIsEmptyElement(scb->reader)) {
                node->nodetyp = XML_NT_EMPTY;
            } else {
                node->nodetyp = XML_NT_START;
            }
            done = TRUE;
            break;
        case XML_ELEMENT_DECL:
            node->nodetyp = XML_NT_END;
            done = TRUE;
            break;
        case XML_TEXT_NODE:
     /* case XML_DTD_NODE: */
            node->nodetyp = XML_NT_STRING;
            done = TRUE;
            break;
        default:
            /* unused node type -- keep trying */
            if (LOGDEBUG3) {
                log_debug3("\nxml_consume_node: skip unused node (%s)",
                           xml_get_node_name(nodetyp));
            }
            advance = TRUE;
        }
    }

    /* finish the node, depending on its type */
    switch (node->nodetyp) {
    case XML_NT_START:
    case XML_NT_END:
    case XML_NT_EMPTY:
        /* get the element QName */
        namestr = xml_strdup(xmlTextReaderConstName(scb->reader));
        if (!namestr) {
            res = ERR_INTERNAL_MEM;
        } else {
            node->qname = namestr;

            /* check for namespace prefix in the name 
             * only error returned is unknown-namespace 
             */
            len = 0;
            res = xml_check_ns(scb->reader, 
                               namestr, 
                               &node->nsid, 
                               &len, 
                               &badns);
            if (!nserr && res != NO_ERR) {
                node->nsid = xmlns_inv_id();
                len = 0;
                res = NO_ERR;
            }
            
            /* set the element name to the char after the prefix, if any */
            node->elname = (const xmlChar *)(namestr+len);
        
            /* get all the attributes, except for XML_NT_END */
            if (res == NO_ERR && node->nodetyp != XML_NT_END) {
                res2 = get_all_attrs(scb, 
                                     node,
                                     &node->attrs, 
                                     layer, 
                                     msghdr, 
                                     nserr);
            }

            /* Set the node module */
            if (res == NO_ERR) {
                if (node->nsid) {
                    node->module = xmlns_get_module(node->nsid);
                } else {
                    /* no entry, use the default module (ncx) */
                    node->module = NCX_DEF_MODULE;
                }
            }
        }
        break;
    case XML_NT_STRING:
        /* get the text value -- this is a malloced string */
        node->simval = NULL;
        valstr = xmlTextReaderValue(scb->reader);
        if (valstr) {
            if (clean) {
                node->simfree = xml_copy_clean_string(valstr);
            } else {
                node->simfree = xml_strdup(valstr);
            }
            if (node->simfree) {
                node->simlen = xml_strlen(node->simfree);
                node->simval = (const xmlChar *)node->simfree;
            }

            /* see if this is a QName string; if so save the NSID */
            xml_check_qname_content(scb->reader, node);

            xmlFree(valstr);
        }
        if (!node->simval) {
            /* prevent a NULL ptr reference */
            node->simval = EMPTY_STRING;
            node->simlen = 0;
            node->simfree = NULL;
        }
        break;
    default:
        break;
    }

    if ((res != NO_ERR) && msghdr) {
        if (badns) {
            /* generate an operation-failed error */
            agt_record_error(scb,
                             msghdr,
                             layer, 
                             res, 
                             node,
                             NCX_NT_STRING, 
                             badns, 
                             NCX_NT_NONE, 
                             NULL);
        } else {
            agt_record_error(scb,
                             msghdr,
                             layer,
                             res, 
                             node,
                             NCX_NT_NONE,
                             NULL, 
                             NCX_NT_NONE, 
                             NULL);
        }
    }

    if (LOGDEBUG4) {
        log_debug4("\nxml_consume_node: return (%d)", 
                   (res==NO_ERR) ? res2 : res);
        if (scb->state != SES_ST_INIT) {
            xml_dump_node(node);
        }
    }

    /* return general error first, then attribute error 
     * It doesn't really matter since the caller will 
     * assume all error reports have been queued upon return
     */
    return (res==NO_ERR) ? res2 : res;

}  /* consume_node */
Пример #9
0
static status_t
    y_interfaces_alarms_alarms_edit (
        ses_cb_t *scb,
        rpc_msg_t *msg,
        agt_cbtyp_t cbtyp,
        op_editop_t editop,
        val_value_t *newval,
        val_value_t *curval)
{
    status_t res;
    val_value_t *errorval;
    const xmlChar *errorstr;

    res = NO_ERR;
    errorval = NULL;
    errorstr = NULL;

    switch (cbtyp) {
    case AGT_CB_VALIDATE:
        /* description-stmt validation here */
        break;
    case AGT_CB_APPLY:
        /* database manipulation done here */
        break;
    case AGT_CB_COMMIT:
        /* device instrumentation done here */
        switch (editop) {
        case OP_EDITOP_LOAD:
        case OP_EDITOP_MERGE:
        case OP_EDITOP_REPLACE:
        case OP_EDITOP_CREATE:
        case OP_EDITOP_DELETE:
            /* device instrumentation here */
            break;
        default:
            assert(0);
        }

        break;
    case AGT_CB_ROLLBACK:
        /* undo device instrumentation here */
        break;
    default:
        res = SET_ERROR(ERR_INTERNAL_VAL);
    }

    /* if error: set the res, errorstr, and errorval parms */
    if (res != NO_ERR) {
        agt_record_error(
            scb,
            &msg->mhdr,
            NCX_LAYER_CONTENT,
            res,
            NULL,
            NCX_NT_STRING,
            errorstr,
            NCX_NT_VAL,
            errorval);
    }

    return res;
}
Пример #10
0
/********************************************************************
* FUNCTION y_ietf_netconf_partial_lock_partial_lock_validate
* 
* RPC validation phase
* All YANG constraints have passed at this point.
* Add description-stmt checks in this function.
* 
* INPUTS:
*     see agt/agt_rpc.h for details
* 
* RETURNS:
*     error status
********************************************************************/
static status_t
    y_ietf_netconf_partial_lock_partial_lock_validate (
        ses_cb_t *scb,
        rpc_msg_t *msg,
        xml_node_t *methnode)
{
    plock_cb_t *plcb;
    cfg_template_t *running;
    val_value_t *select_val, *testval;
    xpath_result_t *result;
    xpath_resnode_t *resnode;
    status_t res, retres;
    ses_id_t lockowner;

    res = NO_ERR;
    retres = NO_ERR;
    plcb = NULL;
    result = NULL;

    running = cfg_get_config_id(NCX_CFGID_RUNNING);

    /* make sure the running config state is READY */
    res = cfg_ok_to_partial_lock(running);
    if (res != NO_ERR) {
        agt_record_error(scb,
                         &msg->mhdr,
                         NCX_LAYER_OPERATION,
                         res,
                         methnode,
                         NCX_NT_NONE,
                         NULL,
                         NCX_NT_NONE,
                         NULL);
        return res;
    }

    /* the stack has already made sure at least 1 of these
     * is present because min-elements=1
     */
    select_val = val_find_child
        (msg->rpc_input,
         y_ietf_netconf_partial_lock_M_ietf_netconf_partial_lock,
         y_ietf_netconf_partial_lock_N_select);
    if (select_val == NULL || select_val->res != NO_ERR) {
        /* should not happen */
        return SET_ERROR(ERR_INTERNAL_VAL);
    }

    /* allocate a new lock cb
     * the plcb pointer will be NULL if the result is not NO_ERR
     */
    res = NO_ERR;
    plcb = plock_cb_new(SES_MY_SID(scb), &res);
    if (res == ERR_NCX_RESOURCE_DENIED && !plcb &&
        !cfg_is_partial_locked(running)) {
        /* no partial locks so it is safe to reset the lock index */
        plock_cb_reset_id();
        res = NO_ERR;
        plcb = plock_cb_new(SES_MY_SID(scb), &res);
    }

    if (res != NO_ERR || !plcb ) {
        if ( res==NO_ERR && !plcb ) {
            res = ERR_INTERNAL_MEM;
        }
        agt_record_error(scb,
                         &msg->mhdr,
                         NCX_LAYER_OPERATION,
                         res,
                         methnode,
                         NCX_NT_NONE,
                         NULL,
                         NCX_NT_NONE,
                         NULL);
        if ( plcb ) {
            plock_cb_free(plcb);
        }
        return res;
    }

    /* get all the select parm instances and save them
     * in the partial lock cb
     */
    while (select_val != NULL) {
        result = xpath1_eval_xmlexpr(scb->reader,
                                     select_val->xpathpcb,
                                     running->root,
                                     running->root,
                                     FALSE,  /* logerrors */
                                     TRUE,   /* config-only */
                                     &res);

        if (result == NULL || res != NO_ERR) {
            /* should not get invalid XPath expression
             * but maybe something was valid in the
             * object tree but not in the value tree
             */
            agt_record_error(scb,
                             &msg->mhdr,
                             NCX_LAYER_OPERATION,
                             res,
                             methnode,
                             NCX_NT_STRING,
                             VAL_STRING(select_val),
                             NCX_NT_VAL,
                             select_val);
            retres = res;
            xpath_free_result(result);
        } else if (result->restype != XP_RT_NODESET) {
            res = ERR_NCX_XPATH_NOT_NODESET;
            agt_record_error(scb,
                             &msg->mhdr,
                             NCX_LAYER_OPERATION,
                             res,
                             methnode,
                             NCX_NT_STRING,
                             VAL_STRING(select_val),
                             NCX_NT_VAL,
                             select_val);
            retres = res;
            xpath_free_result(result);
        } else {
            /* save these pointers; the result will be
             * pruned for redundant nodes after all the
             * select expressions have been processed;
             * transfer the memory straight across
             */
            plock_add_select(plcb, 
                             select_val->xpathpcb,
                             result);
            select_val->xpathpcb = NULL;
            result = NULL;
        }

        /* set up the next select value even if errors so far */
        select_val = val_find_next_child
            (msg->rpc_input,
             y_ietf_netconf_partial_lock_M_ietf_netconf_partial_lock,
             y_ietf_netconf_partial_lock_N_select,
             select_val);
    }

    /* check the result for non-empty only if all
     * the select stmts were valid
     */
    if (retres == NO_ERR) {
        res = plock_make_final_result(plcb);
        if (res != NO_ERR) {
            agt_record_error(scb,
                             &msg->mhdr,
                             NCX_LAYER_OPERATION,
                             res,
                             methnode,
                             NCX_NT_NONE,
                             NULL,
                             NCX_NT_VAL,
                             select_val);
            retres = res;
        }
    }

    /* make sure all the nodeptrs identify subtrees in the
     * running config that can really be locked right now
     * only if the final result is a non-empty nodeset
     */
    if (retres == NO_ERR) {
        result = plock_get_final_result(plcb);

        for (resnode = xpath_get_first_resnode(result);
             resnode != NULL;
             resnode = xpath_get_next_resnode(resnode)) {

            testval = xpath_get_resnode_valptr(resnode);

            /* !!! Update 2011-09-27
             * Just talked to the RFC author; Martin and I
             * agree RFC 5717 does not specify that write 
             * access be required to create a partial lock
             * In fact -- a user may want to lock a node
             * to do a stable read
             **** deleted agt_acm check ***/

            /* make sure there is a plock slot available
             * and no part of this subtree is already locked
             * do not check lock conflicts if this subtree
             * is unauthorized for writing
             */
            lockowner = 0;
            res = val_ok_to_partial_lock(testval, SES_MY_SID(scb),
                                         &lockowner);
            if (res != NO_ERR) {
                if (res == ERR_NCX_LOCK_DENIED) {
                    agt_record_error(scb,
                                     &msg->mhdr,
                                     NCX_LAYER_OPERATION,
                                     res,
                                     methnode,
                                     NCX_NT_UINT32_PTR,
                                     &lockowner,
                                     NCX_NT_VAL,
                                     testval);
                } else {
                    agt_record_error(scb,
                                     &msg->mhdr,
                                     NCX_LAYER_OPERATION,
                                     res,
                                     methnode,
                                     NCX_NT_NONE,
                                     NULL,
                                     NCX_NT_VAL,
                                     testval);
                }
                retres = res;
            }
        }  // for loop
    }  // if retres == NO_ERR

    /* make sure there is no partial commit in progress */
    if (agt_ncx_cc_active()) {
        res = ERR_NCX_IN_USE_COMMIT;
        agt_record_error(scb,
                         &msg->mhdr,
                         NCX_LAYER_OPERATION,
                         res,
                         methnode,
                         NCX_NT_NONE,
                         NULL,
                         NCX_NT_NONE,
                         NULL);
        retres = res;
    }

    /* save the plock CB only if there were no errors;
     * otherwise the invoke function will not get called
     */
    if (retres == NO_ERR) {
        /* the invoke function must free this pointer */
        msg->rpc_user1 = plcb;
    } else {
        plock_cb_free(plcb);
    }

    return retres;

} /* y_ietf_netconf_partial_lock_partial_lock_validate */
Пример #11
0
/********************************************************************
* FUNCTION y_ietf_netconf_partial_lock_partial_lock_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_ietf_netconf_partial_lock_partial_lock_invoke (
        ses_cb_t *scb,
        rpc_msg_t *msg,
        xml_node_t *methnode)
{
    plock_cb_t *plcb;
    val_value_t *testval, *newval;
    xpath_result_t *result;
    xpath_resnode_t *resnode, *clearnode;
    xmlChar *pathbuff;
    cfg_template_t *running;
    status_t res;
    ncx_num_t num;

    res = NO_ERR;

    plcb = (plock_cb_t *)msg->rpc_user1;
    result = plock_get_final_result(plcb);
    running = cfg_get_config_id(NCX_CFGID_RUNNING);

    /* try to lock all the target nodes */
    for (resnode = xpath_get_first_resnode(result);
         resnode != NULL && res == NO_ERR;
         resnode = xpath_get_next_resnode(resnode)) {

        testval = xpath_get_resnode_valptr(resnode);

        res = val_set_partial_lock(testval, plcb);
        if (res != NO_ERR) {
            agt_record_error(scb,
                             &msg->mhdr,
                             NCX_LAYER_OPERATION,
                             res,
                             methnode,
                             NCX_NT_NONE,
                             NULL,
                             NCX_NT_VAL,
                             testval);
        }
    }

    /* unlock any nodes already attempted if any fail */
    if (res != NO_ERR) {
        for (clearnode = xpath_get_first_resnode(result);
             clearnode != NULL;
             clearnode = xpath_get_next_resnode(clearnode)) {

            testval = xpath_get_resnode_valptr(clearnode);

            val_clear_partial_lock(testval, plcb);
            if (clearnode == resnode) {
                return res;
            }
        }
        return res;
    }

    /* add this partial lock to the running config */
    res = cfg_add_partial_lock(running, plcb);
    if (res != NO_ERR) {
        /* should not happen since config lock state could
         * not have changed since validate callback
         */
        agt_record_error(scb,
                         &msg->mhdr,
                         NCX_LAYER_OPERATION,
                         res,
                         methnode,
                         NCX_NT_NONE,
                         NULL,
                         NCX_NT_NONE,
                         NULL);
        for (clearnode = xpath_get_first_resnode(result);
             clearnode != NULL;
             clearnode = xpath_get_next_resnode(clearnode)) {

            testval = xpath_get_resnode_valptr(clearnode);
            val_clear_partial_lock(testval, plcb);
        }
        plock_cb_free(plcb);
        return res;
    }

    /* setup return data only if lock successful
     * cache the reply instead of stream the reply
     * in case there is any error; if so; the partial
     * lock will be backed out and the dataQ cleaned
     * for an error exit; add lock-id leaf first 
     */
    msg->rpc_data_type = RPC_DATA_YANG;
    
    ncx_init_num(&num);
    num.u = plock_get_id(plcb);
    newval = xml_val_new_number
        (y_ietf_netconf_partial_lock_N_lock_id,
         val_get_nsid(msg->rpc_input),
         &num,
         NCX_BT_UINT32);
    ncx_clean_num(NCX_BT_UINT32, &num);

    if (newval == NULL) {
        res = ERR_INTERNAL_MEM;
        agt_record_error(scb, 
                         &msg->mhdr, 
                         NCX_LAYER_OPERATION, 
                         res,
                         methnode, 
                         NCX_NT_NONE, 
                         NULL, 
                         NCX_NT_NONE, 
                         NULL);
    } else {
        dlq_enque(newval, &msg->rpc_dataQ);
    }

    /* add lock-node leaf-list instance for each resnode */
    for (resnode = xpath_get_first_resnode(result);
         resnode != NULL && res == NO_ERR;
         resnode = xpath_get_next_resnode(resnode)) {

        /* Q&D method: generate the i-i string as a plain
         * string and add any needed prefixes to the global
         * prefix map for the reply message (in mhdr)
         */
        pathbuff = NULL;
        testval = xpath_get_resnode_valptr(resnode);
        res = val_gen_instance_id(&msg->mhdr, 
                                  testval,
                                  NCX_IFMT_XPATH1, 
                                  &pathbuff);
        if (res == NO_ERR) {
            /* make leaf; pass off pathbuff malloced memory */
            newval = xml_val_new_string
                (y_ietf_netconf_partial_lock_N_locked_node,
                 val_get_nsid(msg->rpc_input),
                 pathbuff);
            if (newval == NULL) {
                res = ERR_INTERNAL_MEM;
                m__free(pathbuff);
                pathbuff = NULL;
            }
        }

        if (res == NO_ERR) {
            dlq_enque(newval, &msg->rpc_dataQ);
        } else {
            agt_record_error(scb, 
                             &msg->mhdr, 
                             NCX_LAYER_OPERATION, 
                             res,
                             methnode, 
                             NCX_NT_NONE, 
                             NULL, 
                             NCX_NT_NONE, 
                             NULL);
        }
    }

    if (res != NO_ERR) {
        /* back out everything, except waste the lock ID */
        for (clearnode = xpath_get_first_resnode(result);
             clearnode != NULL;
             clearnode = xpath_get_next_resnode(clearnode)) {

            testval = xpath_get_resnode_valptr(clearnode);
            val_clear_partial_lock(testval, plcb);
        }
        cfg_delete_partial_lock(running, plock_get_id(plcb));

        /* clear any data already queued */
        while (!dlq_empty(&msg->rpc_dataQ)) {
            testval = (val_value_t *)
                dlq_deque(&msg->rpc_dataQ);
            val_free_value(testval);
        }
        msg->rpc_data_type = RPC_DATA_NONE;
    }

    return res;

} /* y_ietf_netconf_partial_lock_partial_lock_invoke */
Пример #12
0
/********************************************************************
* FUNCTION y_toaster_make_toast_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_toaster_make_toast_invoke (
        ses_cb_t *scb,
        rpc_msg_t *msg,
        xml_node_t *methnode)
{
    status_t res;
    val_value_t *toasterDoneness_val;
    val_value_t *toasterToastType_val;
    uint32 toasterDoneness;
    //val_idref_t *toasterToastType;

    res = NO_ERR;
    toasterDoneness = 0;

    toasterDoneness_val = val_find_child(
        msg->rpc_input,
        y_toaster_M_toaster,
        y_toaster_N_toasterDoneness);
    if (toasterDoneness_val != NULL && toasterDoneness_val->res == NO_ERR) {
        toasterDoneness = VAL_UINT(toasterDoneness_val);
    }

    toasterToastType_val = val_find_child(
        msg->rpc_input,
        y_toaster_M_toaster,
        y_toaster_N_toasterToastType);
    if (toasterToastType_val != NULL && toasterToastType_val->res == NO_ERR) {
        //toasterToastType = VAL_IDREF(toasterToastType_val);
        // invoke instrumentation with this toast type
    }

    /* invoke your device instrumentation code here */

    /* make sure the toasterDoneness value is set */
    if (toasterDoneness_val == NULL) {
        toasterDoneness = 5;   /* set the default */
    }
    

    /* arbitrary formula to convert toaster doneness to the
     * number of seconds the toaster should be on
     */
    toaster_duration = toasterDoneness * 12;

    /* this is where the code would go to adjust the duration
     * based on the bread type
     */

    if (LOGDEBUG) {
        log_debug("\ntoaster: starting toaster for %u seconds",
                  toaster_duration);
    }

    /* this is where the code would go to start the toaster
     * heater element
     */

    /* start a timer to toast for the specified time interval */
    res = agt_timer_create(toaster_duration,
                           FALSE,
                           toaster_timer_fn,
                           NULL,
                           &toaster_timer_id);
    if (res == NO_ERR) {
        toaster_toasting = TRUE;
    } else {
        agt_record_error(
            scb,
            &msg->mhdr,
            NCX_LAYER_OPERATION,
            res,
            methnode,
            NCX_NT_NONE,
            NULL,
            NCX_NT_NONE,
            NULL);
    }
    /* added code ends here */
    
    return res;

} /* y_toaster_make_toast_invoke */
Пример #13
0
/********************************************************************
* FUNCTION y_toaster_make_toast_validate
* 
* RPC validation phase
* All YANG constriants have passed at this point.
* Add description-stmt checks in this function.
* 
* INPUTS:
*     see agt/agt_rpc.h for details
* 
* RETURNS:
*     error status
********************************************************************/
static status_t
    y_toaster_make_toast_validate (
        ses_cb_t *scb,
        rpc_msg_t *msg,
        xml_node_t *methnode)
{
    status_t res;
    val_value_t *errorval;
    const xmlChar *errorstr;
    val_value_t *toasterDoneness_val;
    val_value_t *toasterToastType_val;
    //uint32 toasterDoneness;
    //val_idref_t *toasterToastType;

    res = NO_ERR;
    errorval = NULL;
    errorstr = NULL;

    toasterDoneness_val = val_find_child(
        msg->rpc_input,
        y_toaster_M_toaster,
        y_toaster_N_toasterDoneness);
    if (toasterDoneness_val != NULL && toasterDoneness_val->res == NO_ERR) {
        //toasterDoneness = VAL_UINT(toasterDoneness_val);
        // validate toast doneness within instrumentation if needed
    }

    toasterToastType_val = val_find_child(
        msg->rpc_input,
        y_toaster_M_toaster,
        y_toaster_N_toasterToastType);
    if (toasterToastType_val != NULL && toasterToastType_val->res == NO_ERR) {
        //toasterToastType = VAL_IDREF(toasterToastType_val);
        // validate toast-type within instrumentation if needed
    }

    /* added code starts here */
    if (toaster_enabled) {
        /* toaster service enabled, check if in use */
        if (toaster_toasting) {
            res = ERR_NCX_IN_USE;
        } else {
            /* this is where a check on bread inventory would go */

            /* this is where a check on toaster HW ready would go */
        }
    } else {
        /* toaster service disabled */
        res = ERR_NCX_RESOURCE_DENIED;

    }
    /* added code ends here */

    /* if error: set the res, errorstr, and errorval parms */
    if (res != NO_ERR) {
        agt_record_error(
            scb,
            &msg->mhdr,
            NCX_LAYER_OPERATION,
            res,
            methnode,
            NCX_NT_STRING,
            errorstr,
            NCX_NT_VAL,
            errorval);
    }
    
    return res;

} /* y_toaster_make_toast_validate */
Пример #14
0
/********************************************************************
* FUNCTION y_toaster_toaster_edit
* 
* Edit database object callback
* Path: /toaster
* Add object instrumentation in COMMIT phase.
* 
* INPUTS:
*     see agt/agt_cb.h for details
* 
* RETURNS:
*     error status
********************************************************************/
static status_t
    y_toaster_toaster_edit (
        ses_cb_t *scb,
        rpc_msg_t *msg,
        agt_cbtyp_t cbtyp,
        op_editop_t editop,
        val_value_t *newval,
        val_value_t *curval)
{
    status_t res;
    val_value_t *errorval;
    const xmlChar *errorstr;

    res = NO_ERR;
    errorval = NULL;
    errorstr = NULL;

    switch (cbtyp) {
    case AGT_CB_VALIDATE:
        /* description-stmt validation here */
        break;
    case AGT_CB_APPLY:
        /* database manipulation done here */
        break;
    case AGT_CB_COMMIT:
        /* device instrumentation done here */
        switch (editop) {
        case OP_EDITOP_LOAD:
            toaster_enabled = TRUE;
            toaster_toasting = FALSE;
            break;
        case OP_EDITOP_MERGE:
            break;
        case OP_EDITOP_REPLACE:
            break;
        case OP_EDITOP_CREATE:
            toaster_enabled = TRUE;
            toaster_toasting = FALSE;
            break;
        case OP_EDITOP_DELETE:
            toaster_enabled = FALSE;
            if (toaster_toasting) {
                agt_timer_delete(toaster_timer_id);
                toaster_timer_id = 0;
                toaster_toasting = FALSE;
                y_toaster_toastDone_send((const xmlChar *)"error");
            }
            break;
        default:
            res = SET_ERROR(ERR_INTERNAL_VAL);
        }

        if (res == NO_ERR) {
            res = agt_check_cache(
                &toaster_val,
                newval,
                curval,
                editop);
        }
        
        if (res == NO_ERR &&
            (editop == OP_EDITOP_LOAD || editop == OP_EDITOP_CREATE)) {
            res = y_toaster_toaster_mro(newval);
        }
        break;
    case AGT_CB_ROLLBACK:
        /* undo device instrumentation here */
        break;
    default:
        res = SET_ERROR(ERR_INTERNAL_VAL);
    }

    /* if error: set the res, errorstr, and errorval parms */
    if (res != NO_ERR) {
        agt_record_error(
            scb,
            &msg->mhdr,
            NCX_LAYER_CONTENT,
            res,
            NULL,
            NCX_NT_STRING,
            errorstr,
            NCX_NT_VAL,
            errorval);
    }
    
    return res;

} /* y_toaster_toaster_edit */