Beispiel #1
0
/********************************************************************
* FUNCTION parse_index
* 
* Parse, and fill the indexQ for one val_value_t struct during
* processing of a text config file
*
* Error messages are printed by this function!!
* Do not duplicate error messages upon error return
*
* The value name is the current token.
* Based on the value typdef, the res of the tokens
* comprising the value statement will be processed
*
* INPUTS:
*   tkc == token chain
*   obj == the object template to use for filling in 'val'
*   val == initialized value struct, without any value,
*          which will be filled in by this function
*   nsid == namespace ID to use for this value
*
* OUTPUTS:
*   indexQ filled in as tokens representing the index components
*   are parsed.  NEWLINE tokens are skipped as needed
*
* RETURNS:
*   status of the operation
*********************************************************************/
static status_t 
    parse_index (tk_chain_t  *tkc,
                 obj_template_t *obj,
                 val_value_t *val,
                 xmlns_id_t  nsid)
{
    obj_key_t     *indef, *infirst;
    val_value_t   *inval;
    status_t       res;

    infirst = obj_first_key(obj);

    /* first make value nodes for all the index values */
    for (indef = infirst; 
         indef != NULL; 
         indef = obj_next_key(indef)) {

        /* advance to the next non-NEWLINE token */
        res = get_tk(tkc);
        if (res != NO_ERR) {
            ncx_conf_exp_err(tkc, res, "index value");
            return res;
        }

        /* check if a valid token is given for the index value */
        if (TK_CUR_TEXT(tkc)) {
            inval = val_make_simval_obj(indef->keyobj,
                                        TK_CUR_VAL(tkc), 
                                        &res);
            if (!inval) {
                ncx_conf_exp_err(tkc, res, "index value");
                return res;
            } else {
                val_change_nsid(inval, nsid);
                val_add_child(inval, val);
            }
        } else {
            res = ERR_NCX_WRONG_TKTYPE;
            ncx_conf_exp_err(tkc, res, "index value");
            return res;
        }
    }

    /* generate the index chain in the indexQ */
    res = val_gen_index_chain(obj, val);
    if (res != NO_ERR) {
        ncx_print_errormsg(tkc, NULL, res);
    }

    return res;
        
} /* parse_index */
Beispiel #2
0
static status_t
    add_interfaces_state_entry(char* buf, val_value_t* interfaces_state_val)
{
    /*objs*/
    obj_template_t* interface_obj;
    obj_template_t* name_obj;
    obj_template_t* statistics_obj;
    obj_template_t* obj;

    /*vals*/
    val_value_t* interface_val;
    val_value_t* name_val;
    val_value_t* statistics_val;
    val_value_t* val;

    status_t res=NO_ERR;
    boolean done;
    char* name;
    char* str;
    char* endptr;
    unsigned int i;
    uint64_t counter;
    int ret;

    char* counter_names_array[] = {
        "in-octets",
        "in-unicast-pkts",
        "in-errors",
        "in-discards",
        NULL/*"in-fifo"*/,
        NULL/*"in-frames"*/,
        NULL/*in-compressed*/,
        "in-multicast-pkts",
        "out-octets",
        "out-unicast-pkts",
        "out-errors",
        "out-discards",
        NULL/*"out-fifo"*/,
        NULL/*out-collisions*/,
        NULL/*out-carrier*/,
        NULL/*out-compressed*/
    };

    /* get the start of the interface name */
    str = buf;
    while (*str && isspace(*str)) {
        str++;
    }
    if (*str == '\0') {
        /* not expecting a line with just whitespace on it */
        return ERR_NCX_SKIPPED;
    } else {
        name = str++;
    }

    /* get the end of the interface name */
    while (*str && *str != ':') {
        str++;
    }

    if (*str != ':') {
        /* expected e.g. eth0: ...*/
        return ERR_NCX_SKIPPED;
    } else {
    	*str=0;
    	str++;
    }

    /* /interfaces-state/interface */
    interface_obj = obj_find_child(interfaces_state_val->obj,
                                   "ietf-interfaces",
                                   "interface");
    assert(interface_obj != NULL);

    interface_val = val_new_value();
    if (interface_val == NULL) {
        return ERR_INTERNAL_MEM;
    }

    val_init_from_template(interface_val, interface_obj);

    val_add_child(interface_val, interfaces_state_val);

    /* /interfaces-state/interface/name */
    name_obj = obj_find_child(interface_obj,
                              "ietf-interfaces",
                              "name");
    assert(name_obj != NULL);


    name_val = val_new_value();
    if (name_val == NULL) {
                return ERR_INTERNAL_MEM;
    }       
    
    val_init_from_template(name_val, name_obj);

    res = val_set_simval_obj(name_val, name_obj, name);

    val_add_child(name_val, interface_val);

    res = val_gen_index_chain(interface_obj, interface_val);
    assert(res == NO_ERR);

    /* /interfaces-state/interface/statistics */
    statistics_obj = obj_find_child(interface_obj,
                                   "ietf-interfaces",
                                   "statistics");
    assert(statistics_obj != NULL);
    statistics_val = val_new_value();
    if (statistics_val == NULL) {
        return ERR_INTERNAL_MEM;
    }

    val_init_from_template(statistics_val, statistics_obj);

    val_add_child(statistics_val, interface_val);

    done = FALSE;
    for(i=0;i<(sizeof(counter_names_array)/sizeof(char*));i++) {
        endptr = NULL;
        counter = strtoull((const char *)str, &endptr, 10);
        if (counter == 0 && str == endptr) {
            /* number conversion failed */
            log_error("Error: /proc/net/dev number conversion failed.");
            return ERR_NCX_OPERATION_FAILED;
        }

        if(counter_names_array[i]!=NULL) {
            obj = obj_find_child(statistics_obj,
                                 "ietf-interfaces",
                                 counter_names_array[i]);
    	    assert(obj != NULL);

            val = val_new_value();
            if (val == NULL) {
                return ERR_INTERNAL_MEM;
            }
            val_init_from_template(val, obj);
            VAL_UINT64(val) = counter;
            val_add_child(val, statistics_val);
        }

        str = (xmlChar *)endptr;
        if (*str == '\0' || *str == '\n') {
            break;
        }
    }
    return res;
}
/********************************************************************
 * FUNCTION parse_node
 * (config mode input received)
 *  Parse the next word using the comstate and session_cb state
 *  Expecting this word to represent a datastore node, not a key or value
 *
 * e.g.,
 *  interface eth0 mtu 1500
 *      ^      ^    ^    ^
 *    node    key node  value
 *
 * INPUTS:
 *    tkc == token chain in progress
 *    session_cb == session control block to use
 *    done == address of return done flag
 *    gotexit == address of return gotexit flag
 *    gotapply == address of return gotapply flag
 *    gotdo == address of return do command flag
 *
 * OUTPUTS:
 *    *done == TRUE if parsing done; no more tokens;
 *             ignore unless return NO_ERR
 *    *gotexit == TRUE if got 'exit' command
 *             ignore unless return NO_ERR and *done == TRUE
 *    *gotapply == TRUE if got 'apply' command
 *             ignore unless return NO_ERR and *done == TRUE
 *    *gotdo == TRUE if got 'do' command
 * RETURNS:
 *   status
 *********************************************************************/
static status_t
    parse_node (tk_chain_t *tkc,
                session_cb_t *session_cb,
                boolean *done,
                boolean *gotexit,
                boolean *gotapply,
                boolean *gotdo)
{
    *done = FALSE;
    *gotexit = FALSE;
    *gotapply = FALSE;
    *gotdo = FALSE;

    /* get the next token to use */
    status_t res = TK_ADV(tkc);
    if (res != NO_ERR) {
        if (res == ERR_NCX_EOF) {
            *done = TRUE;
            return NO_ERR;
        } else {
            log_error("\nError: Expecting node identifier\n");
            return res;
        }
    }

    boolean first = tk_cur_is_first(tkc);

    /* check if the 'do' form of command was given */
    if (first && TK_CUR_TYP(tkc) == TK_TT_TSTRING &&
        !xml_strcmp(TK_CUR_VAL(tkc), NCX_EL_DO) &&
        tk_next_typ(tkc) != TK_TT_NONE) {

        *gotdo = TRUE;
        *done = TRUE;
        return NO_ERR;
    }

    /* check if the 'no' form of command was given */
    if (first && TK_CUR_TYP(tkc) == TK_TT_TSTRING &&
        !xml_strcmp(TK_CUR_VAL(tkc), NCX_EL_NO) &&
        tk_next_typ(tkc) != TK_TT_NONE) {

        /* get the next token to use as the first identifier */
        res = TK_ADV(tkc);
        if (res != NO_ERR) {
            log_error("\nError: Expecting identifier token after "
                      "'no' keyword\n");
            return res;
        }
        first = FALSE;
        session_cb->config_no_active = TRUE;
    }

    /* check if the current token is an identifier */
    if (!TK_CUR_ID(tkc)) {
        log_error("\nError: expecting a node identifier\n");
        res = ERR_NCX_WRONG_TKTYPE;
        return res;
    }

    /* check if the exit command was given */
    if (first && TK_CUR_TYP(tkc) == TK_TT_TSTRING &&
        !xml_strcmp(TK_CUR_VAL(tkc), NCX_EL_EXIT) &&
        tk_next_typ(tkc) == TK_TT_NONE) {
        *done = TRUE;
        *gotexit = TRUE;
        return NO_ERR;
    }

    /* check if the apply command was given */
    if (first && TK_CUR_TYP(tkc) == TK_TT_TSTRING &&
        !xml_strcmp(TK_CUR_VAL(tkc), NCX_EL_APPLY) &&
        tk_next_typ(tkc) == TK_TT_NONE) {
        *done = TRUE;
        *gotapply = TRUE;
        return NO_ERR;
    }

    obj_template_t *startobj = session_cb->config_curobj;
    obj_template_t *topobj = NULL;

    if (startobj == NULL) {
        /* getting top-level config object */
        topobj = find_top_obj(session_cb, TK_CUR_VAL(tkc));
        if (topobj && !(obj_is_data_db(topobj) && obj_is_config(topobj))) {
            topobj = NULL;
        }
    } else {
        /* getting child node config object */
        topobj = find_child_obj(session_cb, startobj, TK_CUR_VAL(tkc));
        if (topobj && !obj_is_config(topobj)) {
            topobj = NULL;
        }
    }
    
    if (topobj == NULL) {
        log_error("\nError: No config object found matching '%s'\n",
                  TK_CUR_VAL(tkc));
        return ERR_NCX_UNKNOWN_OBJECT;
    }

    /* got a top object (relative to the current context) */
    session_cb->config_curobj = topobj;

    /* make a template object for the edit operation for non-terminals */
    val_value_t *newval = NULL;
    if (!obj_is_leafy(topobj)) {
        newval = val_new_value();
        if (newval == NULL) {
            log_error("\nError: malloc failed for new value\n");
            return ERR_INTERNAL_MEM;
        }
        val_init_from_template(newval, topobj);
        add_enode(session_cb, newval);
    } else if (session_cb->config_no_active && obj_is_leaf(topobj)) {
        /* no ... foo-leaf */
        newval = xml_val_new_flag(obj_get_name(topobj), obj_get_nsid(topobj));
        if (newval == NULL) {
            log_error("\nError: malloc failed for new value\n");
            return ERR_INTERNAL_MEM;
        }
        add_enode(session_cb, newval);
    }

    if (obj_is_list(topobj)) {
        boolean anykeys = FALSE;
        obj_key_t *newkey = obj_first_key(topobj);
        while (newkey) {
            anykeys = TRUE;

            /* get the next token to use as the key value */
            res = TK_ADV(tkc);
            if (res != NO_ERR) {
                log_error("\nError: Expecting value for '%s' key leaf\n",
                          obj_get_name(newkey->keyobj));
                return res;
            }

            /* parse the value as a key value */
            /*** do something different if TK_CUR_MOD(tkc) is not NULL ***/
            val_value_t *keyval =
                val_make_simval_obj(newkey->keyobj, TK_CUR_VAL(tkc), &res);
            if (res != NO_ERR) {
                log_error("\nError: Invalid value for '%s' key leaf\n",
                          obj_get_name(newkey->keyobj));
                val_free_value(keyval);
                return res;
            }

            /* save keyval */
            if (newval) {
                val_add_child(keyval, newval);
            } else {
                val_free_value(keyval);
            }

            /* set up the next key in the list */
            newkey = obj_next_key(newkey);
        }
        if (anykeys) {
            res = val_gen_index_chain(topobj, newval);
        }
    }

    if (res == NO_ERR && obj_is_leafy(topobj)) {
        /* expecting a value node to follow or done if 'no' command */
        *done = TRUE;
    }

    return res;

}  /* parse_node */