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