Exemple #1
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 */
Exemple #2
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 */
Exemple #3
0
/********************************************************************
* FUNCTION agt_top_dispatch_msg
* 
* Find the appropriate top node handler and call it
* called by the transport manager (through the session manager)
* when a new message is detected
*
* INPUTS:
*   scb == session control block containing the xmlreader
*          set at the start of an incoming message.
*
* RETURNS:
*  none
*********************************************************************/
void
    agt_top_dispatch_msg (ses_cb_t **ppscb)
{
    ses_total_stats_t  *myagttotals;
    agt_profile_t      *profile;
    xml_node_t          top;
    status_t            res;
    top_handler_t       handler;
    ses_cb_t           *scb = *ppscb;
    
#ifdef DEBUG
    if (!scb) {
        SET_ERROR(ERR_INTERNAL_PTR);
        return;
    }
#endif

    myagttotals = ses_get_total_stats();
    profile = agt_get_profile();

    xml_init_node(&top);

    /* get the first node */
    res = agt_xml_consume_node(scb, 
                               &top, 
                               NCX_LAYER_TRANSPORT, 
                               NULL);
    if (res != NO_ERR) {
        scb->stats.inBadRpcs++;
        myagttotals->stats.inBadRpcs++;
        myagttotals->droppedSessions++;

        if (LOGINFO) {
            log_info("\nagt_top: bad msg for session %d (%s)",
                     scb->sid, 
                     get_error_string(res));
        }

        xml_clean_node(&top);
        agt_ses_free_session(scb);

        /* set the supplied ptr to ptr to scb to NULL so that the 
         * caller of this function knows that it was deallotcated */
        *ppscb=NULL;
        return;
    }

    log_debug3("\nagt_top: got node");
    if (LOGDEBUG4 && scb->state != SES_ST_INIT) {
        xml_dump_node(&top);
    }

    /* check node type and if handler exists, then call it */
    if (top.nodetyp==XML_NT_START || top.nodetyp==XML_NT_EMPTY) {
        /* find the owner, elname tuple in the topQ */
        handler = top_find_handler(top.module, top.elname);
        if (handler) {
            /* call the handler */
            (*handler)(scb, &top);
        } else {
            res = ERR_NCX_DEF_NOT_FOUND;
        }
    } else {
        res = ERR_NCX_WRONG_NODETYP;
    }

    /* check any error trying to invoke the top handler */
    if (res != NO_ERR) {
        scb->stats.inBadRpcs++;
        myagttotals->stats.inBadRpcs++;
        myagttotals->droppedSessions++;
        
        if (LOGINFO) {
            log_info("\nagt_top: bad msg for session %d (%s)",
                     scb->sid, 
                     get_error_string(res));
        }

        agt_ses_free_session(scb);

        /* set the supplied ptr to ptr to scb to NULL so that the 
         * caller of this function knows that it was deallotcated */
        *ppscb=NULL;

    } else if (profile->agt_stream_output &&
               scb->state == SES_ST_SHUTDOWN_REQ) {
        /* session was closed */
        agt_ses_kill_session(scb,
                             scb->killedbysid,
                             scb->termreason);
        /* set the supplied ptr to ptr to scb to NULL so that the 
         * caller of this function knows that it was deallotcated */
        *ppscb=NULL;
    }

    xml_clean_node(&top);

} /* agt_top_dispatch_msg */
/********************************************************************
* 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 */