Generic map_str2int generic mapping tables; Removed vector return values from xmldb_get()
This commit is contained in:
parent
bf30e6f66a
commit
abd3eee17d
29 changed files with 381 additions and 280 deletions
|
|
@ -230,12 +230,14 @@ clicon_rpc_generate_error(cxobj *xerr)
|
|||
* @param[in] h CLICON handle
|
||||
* @param[in] db Name of database
|
||||
* @param[in] xpath XPath (or "")
|
||||
* @param[in] errmode 0 if xml errors are returned as clicon_err
|
||||
* 1 if xml errors are in xt and return 0.
|
||||
* @param[out] xt XML tree. must be freed by caller with xml_free
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error, fatal or xml
|
||||
* @code
|
||||
* cxobj *xt = NULL;
|
||||
* if (clicon_rpc_get_config(h, "running", "/", &xt) < 0)
|
||||
* if (clicon_rpc_get_config(h, "running", "/", 0, &xt) < 0)
|
||||
* err;
|
||||
* if (xt)
|
||||
* xml_free(xt);
|
||||
|
|
@ -245,6 +247,7 @@ int
|
|||
clicon_rpc_get_config(clicon_handle h,
|
||||
char *db,
|
||||
char *xpath,
|
||||
int errmode,
|
||||
cxobj **xt)
|
||||
{
|
||||
int retval = -1;
|
||||
|
|
@ -264,13 +267,22 @@ clicon_rpc_get_config(clicon_handle h,
|
|||
goto done;
|
||||
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
||||
goto done;
|
||||
if ((xerr = xpath_first(xret, "//rpc-error")) != NULL){
|
||||
clicon_rpc_generate_error(xerr);
|
||||
goto done;
|
||||
}
|
||||
if ((xd = xpath_first(xret, "//data/config")) == NULL)
|
||||
if ((xd = xml_new("config", NULL)) == NULL)
|
||||
if (errmode == 0){ /* Move this to caller */
|
||||
if ((xerr = xpath_first(xret, "//rpc-error")) != NULL){
|
||||
clicon_rpc_generate_error(xerr);
|
||||
goto done;
|
||||
}
|
||||
if ((xd = xpath_first(xret, "//data/config")) == NULL)
|
||||
if ((xd = xml_new("config", NULL)) == NULL)
|
||||
goto done;
|
||||
}
|
||||
else{ /* Send xml error back (this should be default behaviour) */
|
||||
if ((xd = xpath_first(xret, "//rpc-error")) == NULL){
|
||||
if ((xd = xpath_first(xret, "//data/config")) == NULL)
|
||||
if ((xd = xml_new("config", NULL)) == NULL)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if (xt){
|
||||
if (xml_rm(xd) < 0)
|
||||
goto done;
|
||||
|
|
|
|||
|
|
@ -333,6 +333,43 @@ str2cvec(char *string,
|
|||
goto done;
|
||||
}
|
||||
|
||||
/*! Map from int to string using str2int map
|
||||
* @param[in] ms String, integer map
|
||||
* @param[in] i Input integer
|
||||
* @retval str String value
|
||||
* @retval NULL Error, not found
|
||||
* @note linear search
|
||||
*/
|
||||
const char *
|
||||
clicon_int2str(const map_str2int *mstab,
|
||||
int i)
|
||||
{
|
||||
const struct map_str2int *ms;
|
||||
|
||||
for (ms = &mstab[0]; ms->ms_str; ms++)
|
||||
if (ms->ms_int == i)
|
||||
return ms->ms_str;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*! Map from string to int using str2int map
|
||||
* @param[in] ms String, integer map
|
||||
* @param[in] str Input string
|
||||
* @retval int Value
|
||||
* @retval -1 Error, not found
|
||||
* @note linear search
|
||||
*/
|
||||
int
|
||||
clicon_str2int(const map_str2int *mstab,
|
||||
char *str)
|
||||
{
|
||||
const struct map_str2int *ms;
|
||||
|
||||
for (ms = &mstab[0]; ms->ms_str; ms++)
|
||||
if (strcmp(ms->ms_str, str) == 0)
|
||||
return ms->ms_int;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*! strndup() for systems without it, such as xBSD
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@
|
|||
/* clixon */
|
||||
#include "clixon_err.h"
|
||||
#include "clixon_log.h"
|
||||
#include "clixon_string.h"
|
||||
#include "clixon_queue.h"
|
||||
#include "clixon_xml.h"
|
||||
#include "clixon_xml_parse.h"
|
||||
|
|
@ -82,14 +83,8 @@ struct xml{
|
|||
cg_var *x_cv; /* If body this contains the typed value */
|
||||
};
|
||||
|
||||
/* Type to string conversion */
|
||||
struct map_str2int{
|
||||
char *ms_str;
|
||||
enum cxobj_type ms_type;
|
||||
};
|
||||
|
||||
/* Mapping between xml type <--> string */
|
||||
static const struct map_str2int xsmap[] = {
|
||||
static const map_str2int xsmap[] = {
|
||||
{"error", CX_ERROR},
|
||||
{"element", CX_ELMNT},
|
||||
{"attr", CX_ATTR},
|
||||
|
|
@ -104,12 +99,7 @@ static const struct map_str2int xsmap[] = {
|
|||
char *
|
||||
xml_type2str(enum cxobj_type type)
|
||||
{
|
||||
const struct map_str2int *xs;
|
||||
|
||||
for (xs = &xsmap[0]; xs->ms_str; xs++)
|
||||
if (xs->ms_type == type)
|
||||
return xs->ms_str;
|
||||
return NULL;
|
||||
return (char*)clicon_int2str(xsmap, type);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -169,6 +169,23 @@ xmldb_plugin_unload(clicon_handle h)
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*! Validate database name
|
||||
* @param[in] db Name of database
|
||||
* @param[out] xret Return value as cligen buffer containing xml netconf return
|
||||
* @retval 0 OK
|
||||
* @retval -1 Failed validate, xret set to error
|
||||
*/
|
||||
int
|
||||
xmldb_validate_db(char *db)
|
||||
{
|
||||
if (strcmp(db, "running") != 0 &&
|
||||
strcmp(db, "candidate") != 0 &&
|
||||
strcmp(db, "startup") != 0 &&
|
||||
strcmp(db, "tmp") != 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! Connect to a datastore plugin, allocate handle to be used in API calls
|
||||
* @param[in] h Clicon handle
|
||||
* @retval 0 OK
|
||||
|
|
@ -306,23 +323,17 @@ xmldb_setopt(clicon_handle h,
|
|||
* @param[in] dbname Name of database to search in (filename including dir path
|
||||
* @param[in] xpath String with XPATH syntax. or NULL for all
|
||||
* @param[out] xtop Single XML tree which xvec points to. Free with xml_free()
|
||||
* @param[out] xvec Vector of xml trees. Free after use.
|
||||
* @param[out] xlen Length of vector.
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
* @code
|
||||
* cxobj *xt;
|
||||
* cxobj **xvec;
|
||||
* size_t xlen;
|
||||
* if (xmldb_get(xh, "running", "/interfaces/interface[name="eth"]",
|
||||
* &xt, &xvec, &xlen) < 0)
|
||||
* if (xmldb_get(xh, "running", "/interfaces/interface[name="eth"]", &xt) < 0)
|
||||
* err;
|
||||
* for (i=0; i<xlen; i++){
|
||||
* xn = xv[i];
|
||||
* ...
|
||||
* }
|
||||
* xml_free(xt);
|
||||
* free(xvec);
|
||||
* @endcode
|
||||
* @note if xvec is given, then purge tree, if not return whole tree.
|
||||
* @see xpath_vec
|
||||
|
|
@ -332,9 +343,7 @@ int
|
|||
xmldb_get(clicon_handle h,
|
||||
char *db,
|
||||
char *xpath,
|
||||
cxobj **xtop,
|
||||
cxobj ***xvec,
|
||||
size_t *xlen)
|
||||
cxobj **xtop)
|
||||
{
|
||||
int retval = -1;
|
||||
xmldb_handle xh;
|
||||
|
|
@ -352,7 +361,7 @@ xmldb_get(clicon_handle h,
|
|||
clicon_err(OE_DB, 0, "Not connected to datastore plugin");
|
||||
goto done;
|
||||
}
|
||||
retval = xa->xa_get_fn(xh, db, xpath, xtop, xvec, xlen);
|
||||
retval = xa->xa_get_fn(xh, db, xpath, xtop);
|
||||
#if DEBUG
|
||||
if (retval == 0) {
|
||||
cbuf *cb = cbuf_new();
|
||||
|
|
@ -366,14 +375,12 @@ xmldb_get(clicon_handle h,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*! Modify database provided an xml tree and an operation
|
||||
/*! Modify database given an xml tree and an operation
|
||||
*
|
||||
* @param[in] h CLICON handle
|
||||
* @param[in] db running or candidate
|
||||
* @param[in] op Top-level operation, can be superceded by other op in tree
|
||||
* @param[in] xt xml-tree. Top-level symbol is dummy
|
||||
* @param[in] op OP_MERGE: just add it.
|
||||
* OP_REPLACE: first delete whole database
|
||||
* OP_NONE: operation attribute in xml determines operation
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
* The xml may contain the "operation" attribute which defines the operation.
|
||||
|
|
@ -581,7 +588,7 @@ xmldb_islocked(clicon_handle h,
|
|||
clicon_err(OE_DB, 0, "Not connected to datastore plugin");
|
||||
goto done;
|
||||
}
|
||||
retval =xa->xa_islocked_fn(xh, db);
|
||||
retval = xa->xa_islocked_fn(xh, db);
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1617,3 +1617,84 @@ api_path2xml(char *api_path,
|
|||
free(vec);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* See RFC 8040 Section 7: Mapping from NETCONF<error-tag> to Status Code
|
||||
* and RFC 6241 Appendix A. NETCONF Error list
|
||||
*/
|
||||
const map_str2int netconf_restconf_map[] = {
|
||||
{"in-use", 409},
|
||||
{"invalid-value", 400},
|
||||
{"invalid-value", 404},
|
||||
{"invalid-value", 406},
|
||||
{"too-big", 413}, /* request */
|
||||
{"too-big", 400}, /* response */
|
||||
{"missing-attribute", 400},
|
||||
{"bad-attribute", 400},
|
||||
{"unknown-attribute", 400},
|
||||
{"bad-element", 400},
|
||||
{"unknown-element", 400},
|
||||
{"unknown-namespace", 400},
|
||||
{"access-denied", 401},
|
||||
{"access-denied", 403},
|
||||
{"lock-denied", 409},
|
||||
{"resource-denied", 409},
|
||||
{"rollback-failed", 500},
|
||||
{"data-exists", 409},
|
||||
{"data-missing", 409},
|
||||
{"operation-not-supported",405},
|
||||
{"operation-not-supported",501},
|
||||
{"operation-failed", 412},
|
||||
{"operation-failed", 500},
|
||||
{"partial-operation", 500},
|
||||
{"malformed-message", 400},
|
||||
{NULL, -1}
|
||||
};
|
||||
|
||||
/* See 7231 Section 6.1
|
||||
*/
|
||||
const map_str2int http_reason_phrase_map[] = {
|
||||
{"Continue", 100},
|
||||
{"Switching Protocols", 101},
|
||||
{"OK", 200},
|
||||
{"Created", 201},
|
||||
{"Accepted", 202},
|
||||
{"Non-Authoritative Information", 203},
|
||||
{"No Content", 204},
|
||||
{"Reset Content", 205},
|
||||
{"Partial Content", 206},
|
||||
{"Multiple Choices", 300},
|
||||
{"Moved Permanently", 301},
|
||||
{"Found", 302},
|
||||
{"See Other", 303},
|
||||
{"Not Modified", 304},
|
||||
{"Use Proxy", 305},
|
||||
{"Temporary Redirect", 307},
|
||||
{"Bad Request", 400},
|
||||
{"Unauthorized", 401},
|
||||
{"Payment Required", 402},
|
||||
{"Forbidden", 403},
|
||||
{"Not Found", 404},
|
||||
{"Method Not Allowed", 405},
|
||||
{"Not Acceptable", 406},
|
||||
{"Proxy Authentication Required", 407},
|
||||
{"Request Timeout", 408},
|
||||
{"Conflict", 409},
|
||||
{"Gone", 410},
|
||||
{"Length Required", 411},
|
||||
{"Precondition Failed", 412},
|
||||
{"Payload Too Large", 413},
|
||||
{"URI Too Long", 414},
|
||||
{"Unsupported Media Type", 415},
|
||||
{"Range Not Satisfiable", 416},
|
||||
{"Expectation Failed", 417},
|
||||
{"Upgrade Required", 426},
|
||||
{"Internal Server Error", 500},
|
||||
{"Not Implemented", 501},
|
||||
{"Bad Gateway", 502},
|
||||
{"Service Unavailable", 503},
|
||||
{"Gateway Timeout", 504},
|
||||
{"HTTP Version Not Supported", 505},
|
||||
{NULL, -1}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ in
|
|||
/* clicon */
|
||||
#include "clixon_err.h"
|
||||
#include "clixon_log.h"
|
||||
#include "clixon_string.h"
|
||||
#include "clixon_xml.h"
|
||||
#include "clixon_xsl.h"
|
||||
|
||||
|
|
@ -130,13 +131,8 @@ enum axis_type{
|
|||
A_DESCENDANT_OR_SELF, /* actually descendant-or-self */
|
||||
};
|
||||
|
||||
struct map_str2int{
|
||||
char *ms_str; /* string as in 4.2.4 in RFC 6020 */
|
||||
int ms_int;
|
||||
};
|
||||
|
||||
/* Mapping between axis type string <--> int */
|
||||
static const struct map_str2int atmap[] = {
|
||||
static const map_str2int atmap[] = {
|
||||
{"self", A_SELF},
|
||||
{"child", A_CHILD},
|
||||
{"parent", A_PARENT},
|
||||
|
|
@ -160,19 +156,6 @@ struct xpath_element{
|
|||
|
||||
static int xpath_split(char *xpathstr, char **pathexpr);
|
||||
|
||||
static char *axis_type2str(enum axis_type type) __attribute__ ((unused));
|
||||
|
||||
static char *
|
||||
axis_type2str(enum axis_type type)
|
||||
{
|
||||
const struct map_str2int *at;
|
||||
|
||||
for (at = &atmap[0]; at->ms_str; at++)
|
||||
if (at->ms_int == type)
|
||||
return at->ms_str;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
xpath_print(FILE *f, struct xpath_element *xplist)
|
||||
{
|
||||
|
|
@ -180,7 +163,7 @@ xpath_print(FILE *f, struct xpath_element *xplist)
|
|||
struct xpath_predicate *xp;
|
||||
|
||||
for (xe=xplist; xe; xe=xe->xe_next){
|
||||
fprintf(f, "\t:%s %s ", axis_type2str(xe->xe_type),
|
||||
fprintf(f, "\t:%s %s ", clicon_int2str(atmap, xe->xe_type),
|
||||
xe->xe_str?xe->xe_str:"");
|
||||
for (xp=xe->xe_predicate; xp; xp=xp->xp_next)
|
||||
fprintf(f, "[%s]", xp->xp_expr);
|
||||
|
|
@ -598,7 +581,7 @@ xpath_find(struct xpath_element *xe,
|
|||
}
|
||||
#if 0
|
||||
fprintf(stderr, "%s: %s: \"%s\"\n", __FUNCTION__,
|
||||
axis_type2str(xe->xe_type), xe->xe_str?xe->xe_str:"");
|
||||
clicon_int2str(atmap, xe->xe_type), xe->xe_str?xe->xe_str:"");
|
||||
#endif
|
||||
switch (xe->xe_type){
|
||||
case A_SELF:
|
||||
|
|
|
|||
|
|
@ -75,21 +75,9 @@
|
|||
for static scope type binding */
|
||||
#define YANG_TYPE_CACHE 1
|
||||
|
||||
/*
|
||||
* Private data types
|
||||
*/
|
||||
/* Struct used to map between int and strings. Used for:
|
||||
* - mapping yang types/typedefs (strings) and cligen types (ints).
|
||||
* - mapping yang keywords (strings) and enum (clicon)
|
||||
*/
|
||||
struct map_str2int{
|
||||
char *ms_str; /* string as in 4.2.4 in RFC 6020 */
|
||||
int ms_int;
|
||||
};
|
||||
|
||||
|
||||
/* Mapping between yang keyword string <--> clicon constants */
|
||||
static const struct map_str2int ykmap[] = {
|
||||
static const map_str2int ykmap[] = {
|
||||
{"anyxml", Y_ANYXML},
|
||||
{"argument", Y_ARGUMENT},
|
||||
{"augment", Y_AUGMENT},
|
||||
|
|
@ -545,18 +533,10 @@ ys_flag_reset(yang_stmt *ys,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*! Translate from RFC 6020 keywords to printable string.
|
||||
linear search,...
|
||||
*/
|
||||
char *
|
||||
yang_key2str(int keyword)
|
||||
{
|
||||
const struct map_str2int *yk;
|
||||
|
||||
for (yk = &ykmap[0]; yk->ms_str; yk++)
|
||||
if (yk->ms_int == keyword)
|
||||
return yk->ms_str;
|
||||
return NULL;
|
||||
return (char*)clicon_int2str(ykmap, keyword);
|
||||
}
|
||||
|
||||
/*! Find top module or sub-module. Note that ultimate top is yang spec
|
||||
|
|
|
|||
|
|
@ -71,19 +71,10 @@
|
|||
/*
|
||||
* Local types and variables
|
||||
*/
|
||||
/* Struct used to map between int and strings. Used for:
|
||||
* - mapping yang types/typedefs (strings) and cligen types (ints).
|
||||
* - mapping yang keywords (strings) and enum (clicon)
|
||||
* (same struct in clicon_yang.c)
|
||||
*/
|
||||
struct map_str2int{
|
||||
char *ms_str; /* string as in 4.2.4 in RFC 6020 */
|
||||
int ms_int;
|
||||
};
|
||||
|
||||
/* Mapping between yang types <--> cligen types
|
||||
Note, first match used wne translating from cv to yang --> order is significant */
|
||||
static const struct map_str2int ytmap[] = {
|
||||
static const map_str2int ytmap[] = {
|
||||
{"int32", CGV_INT32}, /* NOTE, first match on right is significant, dont move */
|
||||
{"string", CGV_STRING}, /* NOTE, first match on right is significant, dont move */
|
||||
{"string", CGV_REST}, /* For cv -> yang translation of rest */
|
||||
|
|
@ -105,9 +96,22 @@ static const struct map_str2int ytmap[] = {
|
|||
{"uint32", CGV_UINT32},
|
||||
{"uint64", CGV_UINT64},
|
||||
{"union", CGV_REST}, /* Is replaced by actual type */
|
||||
{NULL, -1}
|
||||
{NULL, -1}
|
||||
};
|
||||
|
||||
/* return 1 if built-in, 0 if not */
|
||||
static int
|
||||
yang_builtin(char *type)
|
||||
{
|
||||
const struct map_str2int *yt;
|
||||
|
||||
/* built-in types */
|
||||
for (yt = &ytmap[0]; yt->ms_str; yt++)
|
||||
if (strcmp(yt->ms_str, type) == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
yang_type_cache_set(yang_type_cache **ycache0,
|
||||
yang_stmt *resolved,
|
||||
|
|
@ -229,20 +233,6 @@ ys_resolve_type(yang_stmt *ys, void *arg)
|
|||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/* return 1 if built-in, 0 if not */
|
||||
static int
|
||||
yang_builtin(char *type)
|
||||
{
|
||||
const struct map_str2int *yt;
|
||||
|
||||
/* built-in types */
|
||||
for (yt = &ytmap[0]; yt->ms_str; yt++)
|
||||
if (strcmp(yt->ms_str, type) == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! Translate from a yang type to a cligen variable type
|
||||
*
|
||||
* Currently many built-in types from RFC6020 and some RFC6991 types.
|
||||
|
|
@ -252,17 +242,17 @@ yang_builtin(char *type)
|
|||
* Return 0 if no match but set cv_type to CGV_ERR
|
||||
*/
|
||||
int
|
||||
yang2cv_type(char *ytype, enum cv_type *cv_type)
|
||||
yang2cv_type(char *ytype,
|
||||
enum cv_type *cv_type)
|
||||
{
|
||||
const struct map_str2int *yt;
|
||||
int ret;
|
||||
|
||||
*cv_type = CGV_ERR;
|
||||
/* built-in types */
|
||||
for (yt = &ytmap[0]; yt->ms_str; yt++)
|
||||
if (strcmp(yt->ms_str, ytype) == 0){
|
||||
*cv_type = yt->ms_int;
|
||||
return 0;
|
||||
}
|
||||
if ((ret = clicon_str2int(ytmap, ytype)) != -1){
|
||||
*cv_type = ret;
|
||||
return 0;
|
||||
}
|
||||
/* special derived types */
|
||||
if (strcmp("ipv4-address", ytype) == 0){ /* RFC6991 */
|
||||
*cv_type = CGV_IPV4ADDR;
|
||||
|
|
@ -300,14 +290,13 @@ yang2cv_type(char *ytype, enum cv_type *cv_type)
|
|||
char *
|
||||
cv2yang_type(enum cv_type cv_type)
|
||||
{
|
||||
const struct map_str2int *yt;
|
||||
char *ytype;
|
||||
const char *str;
|
||||
|
||||
ytype = "empty";
|
||||
/* built-in types */
|
||||
for (yt = &ytmap[0]; yt->ms_str; yt++)
|
||||
if (yt->ms_int == cv_type)
|
||||
return yt->ms_str;
|
||||
if ((str = clicon_int2str(ytmap, cv_type)) != NULL)
|
||||
return (char*)str;
|
||||
|
||||
/* special derived types */
|
||||
if (cv_type == CGV_IPV4ADDR) /* RFC6991 */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue