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
|
|
@ -1,5 +1,8 @@
|
|||
# Clixon CHANGELOG
|
||||
|
||||
- Generic map_str2int generic mapping tables
|
||||
|
||||
- Removed vector return values from xmldb_get()
|
||||
|
||||
## 3.3.1 June 7 2017
|
||||
|
||||
|
|
|
|||
|
|
@ -219,10 +219,20 @@ from_client_get_config(clicon_handle h,
|
|||
clicon_err(OE_XML, 0, "db not found");
|
||||
goto done;
|
||||
}
|
||||
if (xmldb_validate_db(db) < 0){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>invalid-value</error-tag>"
|
||||
"<error-type>protocol</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-message>No such database: %s</error-message>"
|
||||
"</rpc-error></rpc-reply>", db);
|
||||
goto ok;
|
||||
}
|
||||
|
||||
if ((xfilter = xml_find(xe, "filter")) != NULL)
|
||||
if ((selector = xml_find_value(xfilter, "select"))==NULL)
|
||||
selector="/";
|
||||
if (xmldb_get(h, db, selector, &xret, NULL, NULL) < 0){
|
||||
if (xmldb_get(h, db, selector, &xret) < 0){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>operation-failed</error-tag>"
|
||||
"<error-type>application</error-type>"
|
||||
|
|
@ -276,6 +286,16 @@ from_client_edit_config(clicon_handle h,
|
|||
clicon_err(OE_XML, 0, "db not found");
|
||||
goto done;
|
||||
}
|
||||
if (xmldb_validate_db(target) < 0){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>invalid-value</error-tag>"
|
||||
"<error-type>protocol</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-message>No such database: %s</error-message>"
|
||||
"</rpc-error></rpc-reply>", target);
|
||||
goto ok;
|
||||
}
|
||||
|
||||
/* Check if target locked by other client */
|
||||
piddb = xmldb_islocked(h, target);
|
||||
if (piddb && mypid != piddb){
|
||||
|
|
@ -356,6 +376,16 @@ from_client_lock(clicon_handle h,
|
|||
"</rpc-error></rpc-reply>");
|
||||
goto ok;
|
||||
}
|
||||
if (xmldb_validate_db(db) < 0){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>invalid-value</error-tag>"
|
||||
"<error-type>protocol</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-message>No such database: %s</error-message>"
|
||||
"</rpc-error></rpc-reply>", db);
|
||||
goto ok;
|
||||
}
|
||||
|
||||
/*
|
||||
* A lock MUST not be granted if either of the following conditions is true:
|
||||
* 1) A lock is already held by any NETCONF session or another entity.
|
||||
|
|
@ -410,6 +440,15 @@ from_client_unlock(clicon_handle h,
|
|||
"</rpc-error></rpc-reply>");
|
||||
goto ok;
|
||||
}
|
||||
if (xmldb_validate_db(db) < 0){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>invalid-value</error-tag>"
|
||||
"<error-type>protocol</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-message>No such database: %s</error-message>"
|
||||
"</rpc-error></rpc-reply>", db);
|
||||
goto ok;
|
||||
}
|
||||
piddb = xmldb_islocked(h, db);
|
||||
/*
|
||||
* An unlock operation will not succeed if any of the following
|
||||
|
|
@ -534,6 +573,16 @@ from_client_copy_config(clicon_handle h,
|
|||
"</rpc-error></rpc-reply>");
|
||||
goto ok;
|
||||
}
|
||||
if (xmldb_validate_db(source) < 0){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>invalid-value</error-tag>"
|
||||
"<error-type>protocol</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-message>No such database: %s</error-message>"
|
||||
"</rpc-error></rpc-reply>", source);
|
||||
goto ok;
|
||||
}
|
||||
|
||||
if ((target = netconf_db_find(xe, "target")) == NULL){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>missing-element</error-tag>"
|
||||
|
|
@ -543,6 +592,15 @@ from_client_copy_config(clicon_handle h,
|
|||
"</rpc-error></rpc-reply>");
|
||||
goto ok;
|
||||
}
|
||||
if (xmldb_validate_db(target) < 0){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>invalid-value</error-tag>"
|
||||
"<error-type>protocol</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-message>No such database: %s</error-message>"
|
||||
"</rpc-error></rpc-reply>", target);
|
||||
goto ok;
|
||||
}
|
||||
/* Check if target locked by other client */
|
||||
piddb = xmldb_islocked(h, target);
|
||||
if (piddb && mypid != piddb){
|
||||
|
|
@ -556,7 +614,6 @@ from_client_copy_config(clicon_handle h,
|
|||
piddb);
|
||||
goto ok;
|
||||
}
|
||||
|
||||
if (xmldb_copy(h, source, target) < 0){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>operation-failed</error-tag>"
|
||||
|
|
@ -601,6 +658,16 @@ from_client_delete_config(clicon_handle h,
|
|||
"</rpc-error></rpc-reply>");
|
||||
goto ok;
|
||||
}
|
||||
if (xmldb_validate_db(target) < 0){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>invalid-value</error-tag>"
|
||||
"<error-type>protocol</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-message>No such database: %s</error-message>"
|
||||
"</rpc-error></rpc-reply>", target);
|
||||
goto ok;
|
||||
}
|
||||
|
||||
/* Check if target locked by other client */
|
||||
piddb = xmldb_islocked(h, target);
|
||||
if (piddb && mypid != piddb){
|
||||
|
|
|
|||
|
|
@ -146,9 +146,9 @@ validate_common(clicon_handle h,
|
|||
goto done;
|
||||
}
|
||||
/* 2. Parse xml trees */
|
||||
if (xmldb_get(h, "running", "/", &td->td_src, NULL, NULL) < 0)
|
||||
if (xmldb_get(h, "running", "/", &td->td_src) < 0)
|
||||
goto done;
|
||||
if (xmldb_get(h, candidate, "/", &td->td_target, NULL, NULL) < 0)
|
||||
if (xmldb_get(h, candidate, "/", &td->td_target) < 0)
|
||||
goto done;
|
||||
|
||||
/* 3. Compute differences */
|
||||
|
|
@ -212,7 +212,8 @@ validate_common(clicon_handle h,
|
|||
* The code reverts changes if the commit fails. But if the revert
|
||||
* fails, we just ignore the errors and proceed. Maybe we should
|
||||
* do something more drastic?
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] candidate A candidate database, not necessarily "candidate"
|
||||
*/
|
||||
int
|
||||
candidate_commit(clicon_handle h,
|
||||
|
|
@ -283,17 +284,17 @@ from_client_commit(clicon_handle h,
|
|||
piddb);
|
||||
goto ok;
|
||||
}
|
||||
|
||||
if (candidate_commit(h, "candidate") < 0){
|
||||
clicon_debug(1, "Commit candidate failed");
|
||||
/* XXX: candidate_validate should have proper error handling */
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>missing-attribute</error-tag>"
|
||||
"<error-tag>invalid-value</error-tag>"
|
||||
"<error-type>protocol</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-message>%s</error-message>"
|
||||
"</rpc-error></rpc-reply>",
|
||||
clicon_err_reason);
|
||||
goto ok;
|
||||
|
||||
goto ok;
|
||||
}
|
||||
cprintf(cbret, "<rpc-reply><ok/></rpc-reply>");
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ done:
|
|||
static int
|
||||
candb_reset(clicon_handle h)
|
||||
{
|
||||
int retval = -1;
|
||||
int retval = -1;
|
||||
|
||||
if (xmldb_copy(h, "running", "tmp") < 0){
|
||||
clicon_err(OE_UNIX, errno, "file copy");
|
||||
|
|
@ -590,7 +590,7 @@ main(int argc, char **argv)
|
|||
*(argv-1) = tmp;
|
||||
|
||||
if (reload_running){
|
||||
/* This could be afailed validation, and we should not fail for that */
|
||||
/* This could be a failed validation, and we should not fail for that */
|
||||
(void)candidate_commit(h, "candidate");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -655,9 +655,9 @@ compare_dbs(clicon_handle h,
|
|||
astext = cv_int32_get(cvec_i(argv, 0));
|
||||
else
|
||||
astext = 0;
|
||||
if (clicon_rpc_get_config(h, "running", "/", &xc1) < 0)
|
||||
if (clicon_rpc_get_config(h, "running", "/", 0, &xc1) < 0)
|
||||
goto done;
|
||||
if (clicon_rpc_get_config(h, "candidate", "/", &xc2) < 0)
|
||||
if (clicon_rpc_get_config(h, "candidate", "/", 0, &xc2) < 0)
|
||||
goto done;
|
||||
if (compare_xmls(xc1, xc2, astext) < 0) /* astext? */
|
||||
goto done;
|
||||
|
|
@ -823,7 +823,7 @@ save_config_file(clicon_handle h,
|
|||
goto done;
|
||||
}
|
||||
filename = cv_string_get(cv);
|
||||
if (clicon_rpc_get_config(h, dbstr,"/", &xt) < 0)
|
||||
if (clicon_rpc_get_config(h, dbstr,"/", 0, &xt) < 0)
|
||||
goto done;
|
||||
if ((f = fopen(filename, "wb")) == NULL){
|
||||
clicon_err(OE_CFG, errno, "Creating file %s", filename);
|
||||
|
|
@ -1162,7 +1162,7 @@ cli_copy_config(clicon_handle h,
|
|||
cprintf(cb, xpath, keyname, fromname);
|
||||
|
||||
/* Get from object configuration and store in x1 */
|
||||
if (clicon_rpc_get_config(h, db, cbuf_get(cb), &x1) < 0)
|
||||
if (clicon_rpc_get_config(h, db, cbuf_get(cb), 0, &x1) < 0)
|
||||
goto done;
|
||||
|
||||
/* Get to variable -> cv -> to name */
|
||||
|
|
|
|||
|
|
@ -657,7 +657,7 @@ clicon_parse(clicon_handle h,
|
|||
}
|
||||
res = cliread_parse(cli_cligen(h), cmd, pt, &match_obj, cvv);
|
||||
if (res != CG_MATCH)
|
||||
pt_expand_cleanup_1(pt);
|
||||
pt_expand_cleanup_1(pt); /* XXX change to pt_expand_treeref_cleanup */
|
||||
if (msav){
|
||||
cli_tree_active_set(h, msav);
|
||||
free(msav);
|
||||
|
|
@ -689,7 +689,7 @@ clicon_parse(clicon_handle h,
|
|||
}
|
||||
if ((r = clicon_eval(h, cmd, match_obj, cvv)) < 0)
|
||||
cli_handler_err(stdout);
|
||||
pt_expand_cleanup_1(pt);
|
||||
pt_expand_cleanup_1(pt); /* XXX change to pt_expand_treeref_cleanup */
|
||||
if (result)
|
||||
*result = r;
|
||||
goto done;
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ expand_dbvar(void *h,
|
|||
if (api_path_fmt2xpath(api_path, cvv, &xpath) < 0)
|
||||
goto done;
|
||||
/* XXX read whole configuration, why not send xpath? */
|
||||
if (clicon_rpc_get_config(h, dbstr, "/", &xt) < 0)
|
||||
if (clicon_rpc_get_config(h, dbstr, "/", 0, &xt) < 0)
|
||||
goto done;
|
||||
/* One round to detect duplicates
|
||||
* XXX The code below would benefit from some cleanup
|
||||
|
|
@ -426,7 +426,7 @@ cli_show_config(clicon_handle h,
|
|||
else
|
||||
cprintf(cbxpath, "%s", xpath);
|
||||
/* Get configuration from database */
|
||||
if (clicon_rpc_get_config(h, db, cbuf_get(cbxpath), &xt) < 0)
|
||||
if (clicon_rpc_get_config(h, db, cbuf_get(cbxpath), 0, &xt) < 0)
|
||||
goto done;
|
||||
/* Print configuration according to format */
|
||||
switch (format){
|
||||
|
|
@ -505,7 +505,7 @@ show_conf_xpath(clicon_handle h,
|
|||
}
|
||||
cv = cvec_find_var(cvv, "xpath");
|
||||
xpath = cv_string_get(cv);
|
||||
if (clicon_rpc_get_config(h, str, xpath, &xt) < 0)
|
||||
if (clicon_rpc_get_config(h, str, xpath, 0, &xt) < 0)
|
||||
goto done;
|
||||
if (xpath_vec(xt, xpath, &xv, &xlen) < 0)
|
||||
goto done;
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ olof@vandal> curl -G http://127.0.0.1/restconf/data/interfaces/interface/name=et
|
|||
}
|
||||
]
|
||||
|
||||
curl -sX POST -d '{"clicon":{"interfaces":{"interface":{"name":"eth1","type":"eth","enabled":"true"}}}}' http://localhost/restconf/data
|
||||
curl -sX POST -d '{"interfaces":{"interface":{"name":"eth1","type":"eth","enabled":"true"}}}' http://localhost/restconf/data
|
||||
```
|
||||
|
||||
### Debugging
|
||||
|
|
|
|||
|
|
@ -156,6 +156,10 @@ api_data_get_gen(clicon_handle h,
|
|||
cxobj **vec = NULL;
|
||||
yang_spec *yspec;
|
||||
cxobj *xret = NULL;
|
||||
cxobj *xerr;
|
||||
cbuf *cbj = NULL;;
|
||||
int code;
|
||||
char *reason_phrase;
|
||||
|
||||
clicon_debug(1, "%s", __FUNCTION__);
|
||||
yspec = clicon_dbspec_yang(h);
|
||||
|
|
@ -166,16 +170,45 @@ api_data_get_gen(clicon_handle h,
|
|||
goto done;
|
||||
}
|
||||
clicon_debug(1, "%s path:%s", __FUNCTION__, cbuf_get(path));
|
||||
if (clicon_rpc_get_config(h, "running", cbuf_get(path), &xret) < 0){
|
||||
if (clicon_rpc_get_config(h, "running", cbuf_get(path), 1, &xret) < 0){
|
||||
notfound(r);
|
||||
goto done;
|
||||
}
|
||||
#if 0 /* DEBUG */
|
||||
{
|
||||
cbuf *cb = cbuf_new();
|
||||
clicon_xml2cbuf(cb, xret, 0, 0);
|
||||
xml2json_cbuf(cb, xret, 1);
|
||||
clicon_debug(1, "%s xret:%s", __FUNCTION__, cbuf_get(cb));
|
||||
cbuf_free(cb);
|
||||
}
|
||||
#endif
|
||||
if (strcmp(xml_name(xret), "rpc-error") == 0){
|
||||
if ((cbj = cbuf_new()) == NULL)
|
||||
goto done;
|
||||
if ((xerr = xpath_first(xret, "/error-tag")) == NULL){
|
||||
notfound(r); /* bad reply? */
|
||||
goto done;
|
||||
}
|
||||
code = clicon_str2int(netconf_restconf_map, xml_body(xerr));
|
||||
if ((reason_phrase = clicon_int2str(http_reason_phrase_map, code)) == NULL)
|
||||
reason_phrase="";
|
||||
clicon_debug(1, "%s code:%d reason phrase:%s",
|
||||
__FUNCTION__, code, reason_phrase);
|
||||
|
||||
if (xml_name_set(xret, "error") < 0)
|
||||
goto done;
|
||||
if (xml2json_cbuf(cbj, xret, 1) < 0)
|
||||
goto done;
|
||||
FCGX_FPrintF(r->out, "Status: %d %s\r\n", code, reason_phrase);
|
||||
FCGX_FPrintF(r->out, "Content-Type: application/yang-data+json\r\n\r\n");
|
||||
FCGX_FPrintF(r->out, "\r\n");
|
||||
FCGX_FPrintF(r->out, "{\r\n");
|
||||
FCGX_FPrintF(r->out, " \"ietf-restconf:errors\" : {\r\n");
|
||||
FCGX_FPrintF(r->out, " %s", cbuf_get(cbj));
|
||||
FCGX_FPrintF(r->out, " }\r\n");
|
||||
FCGX_FPrintF(r->out, "}\r\n");
|
||||
goto ok;
|
||||
}
|
||||
if ((cbx = cbuf_new()) == NULL)
|
||||
goto done;
|
||||
FCGX_SetExitStatus(200, r->out); /* OK */
|
||||
|
|
@ -197,6 +230,8 @@ api_data_get_gen(clicon_handle h,
|
|||
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
|
||||
if (cbx)
|
||||
cbuf_free(cbx);
|
||||
if (cbj)
|
||||
cbuf_free(cbj);
|
||||
if (path)
|
||||
cbuf_free(path);
|
||||
if (xret)
|
||||
|
|
@ -555,6 +590,7 @@ api_data_delete(clicon_handle h,
|
|||
goto done;
|
||||
if ((cbx = cbuf_new()) == NULL)
|
||||
goto done;
|
||||
|
||||
if (clicon_xml2cbuf(cbx, xtop, 0, 0) < 0)
|
||||
goto done;
|
||||
if (clicon_rpc_edit_config(h, "candidate",
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ main(int argc, char **argv)
|
|||
if (strcmp(cmd, "get")==0){
|
||||
if (argc != 1 && argc != 2)
|
||||
usage(argv0);
|
||||
if (xmldb_get(h, db, argc==2?argv[1]:"/", &xt, NULL, 0) < 0)
|
||||
if (xmldb_get(h, db, argc==2?argv[1]:"/", &xt) < 0)
|
||||
goto done;
|
||||
clicon_xml2file(stdout, xt, 0, 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -571,38 +571,14 @@ kv_setopt(xmldb_handle xh,
|
|||
/*! Get content of database using xpath. return a set of matching sub-trees
|
||||
* The function returns a minimal tree that includes all sub-trees that match
|
||||
* xpath.
|
||||
* @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)
|
||||
* 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
|
||||
* This is a clixon datastore plugin of the the xmldb api
|
||||
* @see xmldb_get
|
||||
*/
|
||||
int
|
||||
kv_get(xmldb_handle xh,
|
||||
char *db,
|
||||
char *xpath,
|
||||
cxobj **xtop,
|
||||
cxobj ***xvec0,
|
||||
size_t *xlen0)
|
||||
cxobj **xtop)
|
||||
{
|
||||
int retval = -1;
|
||||
struct kv_handle *kh = handle(xh);
|
||||
|
|
@ -655,12 +631,6 @@ kv_get(xmldb_handle xh,
|
|||
goto done;
|
||||
if (xml_apply(xt, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset, (void*)XML_FLAG_MARK) < 0)
|
||||
goto done;
|
||||
if (xvec0 && xlen0){
|
||||
*xvec0 = xvec;
|
||||
xvec = NULL;
|
||||
*xlen0 = xlen;
|
||||
xlen = 0;
|
||||
}
|
||||
if (xml_apply(xt, CX_ELMNT, xml_default, NULL) < 0)
|
||||
goto done;
|
||||
/* XXX does not work for top-level */
|
||||
|
|
@ -816,33 +786,15 @@ put(char *dbfile,
|
|||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*! Modify database provided an xml tree and an operation
|
||||
*
|
||||
* @param[in] xh XMLDB handle
|
||||
* @param[in] db running or candidate
|
||||
* @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
|
||||
* @param[in] api_path According to restconf (Sec 3.5.1.1 in [restconf-draft 13])
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
* The xml may contain the "operation" attribute which defines the operation.
|
||||
* @code
|
||||
* cxobj *xt;
|
||||
* if (clicon_xml_parse_str("<a>17</a>", &xt) < 0)
|
||||
* err;
|
||||
* if (xmldb_put(h, "running", OP_MERGE, NULL, xt) < 0)
|
||||
* err;
|
||||
* @endcode
|
||||
* @see xmldb_put_xkey for single key
|
||||
* This is a clixon datastore plugin of the the xmldb api
|
||||
* @see xmldb_put
|
||||
*/
|
||||
int
|
||||
kv_put(xmldb_handle xh,
|
||||
char *db,
|
||||
enum operation_type op,
|
||||
cxobj *xt)
|
||||
cxobj *xt)
|
||||
{
|
||||
int retval = -1;
|
||||
struct kv_handle *kh = handle(xh);
|
||||
|
|
|
|||
|
|
@ -39,8 +39,7 @@
|
|||
/*
|
||||
* Prototypes
|
||||
*/
|
||||
int kv_get(xmldb_handle h, char *db, char *xpath,
|
||||
cxobj **xtop, cxobj ***xvec, size_t *xlen);
|
||||
int kv_get(xmldb_handle h, char *db, char *xpath, cxobj **xtop);
|
||||
int kv_put(xmldb_handle h, char *db, enum operation_type op, cxobj *xt);
|
||||
int kv_dump(FILE *f, char *dbfilename, char *rxkey);
|
||||
int kv_copy(xmldb_handle h, char *from, char *to);
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ static int _running_locked = 0;
|
|||
static int _candidate_locked = 0;
|
||||
static int _startup_locked = 0;
|
||||
|
||||
|
||||
/*! Translate from symbolic database name to actual filename in file-system
|
||||
* @param[in] th text handle handle
|
||||
* @param[in] db Symbolic database name, eg "candidate", "running"
|
||||
|
|
@ -107,8 +108,8 @@ static int _startup_locked = 0;
|
|||
*/
|
||||
static int
|
||||
text_db2file(struct text_handle *th,
|
||||
char *db,
|
||||
char **filename)
|
||||
char *db,
|
||||
char **filename)
|
||||
{
|
||||
int retval = -1;
|
||||
cbuf *cb;
|
||||
|
|
@ -122,13 +123,6 @@ text_db2file(struct text_handle *th,
|
|||
clicon_err(OE_XML, errno, "dbdir not set");
|
||||
goto done;
|
||||
}
|
||||
if (strcmp(db, "running") != 0 &&
|
||||
strcmp(db, "candidate") != 0 &&
|
||||
strcmp(db, "startup") != 0 &&
|
||||
strcmp(db, "tmp") != 0){
|
||||
clicon_err(OE_XML, 0, "No such database: %s", db);
|
||||
goto done;
|
||||
}
|
||||
cprintf(cb, "%s/%s_db", dir, db);
|
||||
if ((*filename = strdup4(cbuf_get(cb))) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "strdup");
|
||||
|
|
@ -318,39 +312,14 @@ singleconfigroot(cxobj *xt,
|
|||
/*! Get content of database using xpath. return a set of matching sub-trees
|
||||
* The function returns a minimal tree that includes all sub-trees that match
|
||||
* xpath.
|
||||
* @param[in] xh XMLDB handle
|
||||
* @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)
|
||||
* 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
|
||||
* This is a clixon datastore plugin of the the xmldb api
|
||||
* @see xmldb_get
|
||||
*/
|
||||
int
|
||||
text_get(xmldb_handle xh,
|
||||
char *db,
|
||||
char *xpath,
|
||||
cxobj **xtop,
|
||||
cxobj ***xvec0,
|
||||
size_t *xlen0)
|
||||
cxobj **xtop)
|
||||
{
|
||||
int retval = -1;
|
||||
char *dbfile = NULL;
|
||||
|
|
@ -426,12 +395,6 @@ text_get(xmldb_handle xh,
|
|||
|
||||
if (debug>1)
|
||||
clicon_xml2file(stderr, xt, 0, 1);
|
||||
if (xvec0 && xlen0){
|
||||
*xvec0 = xvec;
|
||||
xvec = NULL;
|
||||
*xlen0 = xlen;
|
||||
xlen = 0;
|
||||
}
|
||||
*xtop = xt;
|
||||
xt = NULL;
|
||||
retval = 0;
|
||||
|
|
@ -735,30 +698,14 @@ text_modify_top(cxobj *x0,
|
|||
|
||||
|
||||
/*! Modify database provided an xml tree and an operation
|
||||
*
|
||||
* @param[in] xh XMLDB handle
|
||||
* @param[in] db running or candidate
|
||||
* @param[in] op OP_MERGE: just add it.
|
||||
* OP_REPLACE: first delete whole database
|
||||
* OP_NONE: operation attribute in xml determines operation
|
||||
* @param[in] x1 xml-tree to merge/replace. Top-level symbol is 'config'.
|
||||
* Should be empty or '<config/>' if delete?
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
* The xml may contain the "operation" attribute which defines the operation.
|
||||
* @code
|
||||
* cxobj *xt;
|
||||
* if (clicon_xml_parse_str("<a>17</a>", &xt) < 0)
|
||||
* err;
|
||||
* if (xmldb_put(h, "running", OP_MERGE, "/", xt) < 0)
|
||||
* err;
|
||||
* @endcode
|
||||
y */
|
||||
* This is a clixon datastore plugin of the the xmldb api
|
||||
* @see xmldb_put
|
||||
*/
|
||||
int
|
||||
text_put(xmldb_handle xh,
|
||||
char *db,
|
||||
enum operation_type op,
|
||||
cxobj *x1)
|
||||
cxobj *x1)
|
||||
{
|
||||
int retval = -1;
|
||||
struct text_handle *th = handle(xh);
|
||||
|
|
@ -799,7 +746,6 @@ text_put(xmldb_handle xh,
|
|||
}
|
||||
/* 2. File is not empty <top><config>...</config></top> -> replace root */
|
||||
else{
|
||||
|
||||
/* There should only be one element and called config */
|
||||
if (singleconfigroot(x0, &x0) < 0)
|
||||
goto done;
|
||||
|
|
@ -871,8 +817,8 @@ text_put(xmldb_handle xh,
|
|||
*/
|
||||
int
|
||||
text_copy(xmldb_handle xh,
|
||||
char *from,
|
||||
char *to)
|
||||
char *from,
|
||||
char *to)
|
||||
{
|
||||
int retval = -1;
|
||||
struct text_handle *th = handle(xh);
|
||||
|
|
@ -904,11 +850,10 @@ text_copy(xmldb_handle xh,
|
|||
*/
|
||||
int
|
||||
text_lock(xmldb_handle xh,
|
||||
char *db,
|
||||
int pid)
|
||||
char *db,
|
||||
int pid)
|
||||
{
|
||||
// struct text_handle *th = handle(xh);
|
||||
|
||||
if (strcmp("running", db) == 0)
|
||||
_running_locked = pid;
|
||||
else if (strcmp("candidate", db) == 0)
|
||||
|
|
@ -929,10 +874,9 @@ text_lock(xmldb_handle xh,
|
|||
*/
|
||||
int
|
||||
text_unlock(xmldb_handle xh,
|
||||
char *db)
|
||||
char *db)
|
||||
{
|
||||
// struct text_handle *th = handle(xh);
|
||||
|
||||
if (strcmp("running", db) == 0)
|
||||
_running_locked = 0;
|
||||
else if (strcmp("candidate", db) == 0)
|
||||
|
|
@ -993,8 +937,8 @@ text_islocked(xmldb_handle xh,
|
|||
* @retval 1 Yes it exists
|
||||
*/
|
||||
int
|
||||
text_exists(xmldb_handle xh,
|
||||
char *db)
|
||||
text_exists(xmldb_handle xh,
|
||||
char *db)
|
||||
{
|
||||
|
||||
int retval = -1;
|
||||
|
|
@ -1022,7 +966,7 @@ text_exists(xmldb_handle xh,
|
|||
*/
|
||||
int
|
||||
text_delete(xmldb_handle xh,
|
||||
char *db)
|
||||
char *db)
|
||||
{
|
||||
int retval = -1;
|
||||
char *filename = NULL;
|
||||
|
|
@ -1049,7 +993,7 @@ text_delete(xmldb_handle xh,
|
|||
*/
|
||||
int
|
||||
text_create(xmldb_handle xh,
|
||||
char *db)
|
||||
char *db)
|
||||
{
|
||||
int retval = -1;
|
||||
struct text_handle *th = handle(xh);
|
||||
|
|
|
|||
|
|
@ -39,8 +39,7 @@
|
|||
/*
|
||||
* Prototypes
|
||||
*/
|
||||
int text_get(xmldb_handle h, char *db, char *xpath,
|
||||
cxobj **xtop, cxobj ***xvec, size_t *xlen);
|
||||
int text_get(xmldb_handle h, char *db, char *xpath, cxobj **xtop);
|
||||
int text_put(xmldb_handle h, char *db, enum operation_type op, cxobj *xt);
|
||||
int text_dump(FILE *f, char *dbfilename, char *rxkey);
|
||||
int text_copy(xmldb_handle h, char *from, char *to);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
module ietf-ip {
|
||||
module ietf-ip {
|
||||
|
||||
namespace "urn:ietf:params:xml:ns:yang:ietf-ip";
|
||||
prefix ip;
|
||||
|
|
|
|||
|
|
@ -81,8 +81,9 @@ mycallback(clicon_handle h, cvec *cvv, cvec *argv)
|
|||
|
||||
/* Show eth0 interfaces config using XPATH */
|
||||
if (clicon_rpc_get_config(h, "running","/interfaces/interface[name=eth0]",
|
||||
&xret) < 0)
|
||||
0, &xret) < 0)
|
||||
goto done;
|
||||
|
||||
xml_print(stdout, xret);
|
||||
retval = 0;
|
||||
done:
|
||||
|
|
|
|||
|
|
@ -45,7 +45,8 @@ int clicon_rpc_msg(clicon_handle h, struct clicon_msg *msg, cxobj **xret0,
|
|||
int clicon_rpc_netconf(clicon_handle h, char *xmlst, cxobj **xret, int *sp);
|
||||
int clicon_rpc_netconf_xml(clicon_handle h, cxobj *xml, cxobj **xret, int *sp);
|
||||
int clicon_rpc_generate_error(cxobj *xerr);
|
||||
int clicon_rpc_get_config(clicon_handle h, char *db, char *xpath, cxobj **xret);
|
||||
int clicon_rpc_get_config(clicon_handle h, char *db, char *xpath,
|
||||
int errmode, cxobj **xret);
|
||||
int clicon_rpc_edit_config(clicon_handle h, char *db, enum operation_type op,
|
||||
char *xml);
|
||||
int clicon_rpc_copy_config(clicon_handle h, char *db1, char *db2);
|
||||
|
|
|
|||
|
|
@ -36,6 +36,23 @@
|
|||
#ifndef _CLIXON_STRING_H_
|
||||
#define _CLIXON_STRING_H_
|
||||
|
||||
/* Struct used to map between int and strings. Typically used to map between
|
||||
* values and their names. Note NULL terminated
|
||||
* Example:
|
||||
* @code
|
||||
static const map_str2int atmap[] = {
|
||||
{"One", 1},
|
||||
{"Two", 2},
|
||||
{NULL, -1}
|
||||
};
|
||||
* @endcode
|
||||
*/
|
||||
struct map_str2int{
|
||||
char *ms_str;
|
||||
int ms_int;
|
||||
};
|
||||
typedef struct map_str2int map_str2int;
|
||||
|
||||
/*! A malloc version that aligns on 4 bytes. To avoid warning from valgrind */
|
||||
#define align4(s) (((s)/4)*4 + 4)
|
||||
|
||||
|
|
@ -59,6 +76,9 @@ char *clicon_strjoin (int argc, char **argv, char *delim);
|
|||
int str2cvec(char *string, char delim1, char delim2, cvec **cvp);
|
||||
int percent_encode(char *str, char **escp);
|
||||
int percent_decode(char *esc, char **str);
|
||||
const char *clicon_int2str(const map_str2int *mstab, int i);
|
||||
int clicon_str2int(const map_str2int *mstab, char *str);
|
||||
|
||||
#ifndef HAVE_STRNDUP
|
||||
char *clicon_strndup (const char *, size_t);
|
||||
#endif /* ! HAVE_STRNDUP */
|
||||
|
|
|
|||
|
|
@ -75,12 +75,10 @@ typedef int (xmldb_getopt_t)(xmldb_handle xh, char *optname, void **value);
|
|||
typedef int (xmldb_setopt_t)(xmldb_handle xh, char *optname, void *value);
|
||||
|
||||
/* Type of xmldb get function */
|
||||
typedef int (xmldb_get_t)(xmldb_handle xh, char *db, char *xpath,
|
||||
cxobj **xtop, cxobj ***xvec, size_t *xlen);
|
||||
typedef int (xmldb_get_t)(xmldb_handle xh, char *db, char *xpath, cxobj **xtop);
|
||||
|
||||
/* Type of xmldb put function */
|
||||
typedef int (xmldb_put_t)(xmldb_handle xh, char *db, enum operation_type op,
|
||||
cxobj *xt);
|
||||
typedef int (xmldb_put_t)(xmldb_handle xh, char *db, enum operation_type op, cxobj *xt);
|
||||
|
||||
/* Type of xmldb copy function */
|
||||
typedef int (xmldb_copy_t)(xmldb_handle xh, char *from, char *to);
|
||||
|
|
@ -135,12 +133,12 @@ struct xmldb_api{
|
|||
int xmldb_plugin_load(clicon_handle h, char *filename);
|
||||
int xmldb_plugin_unload(clicon_handle h);
|
||||
|
||||
int xmldb_validate_db(char *db);
|
||||
int xmldb_connect(clicon_handle h);
|
||||
int xmldb_disconnect(clicon_handle h);
|
||||
int xmldb_getopt(clicon_handle h, char *optname, void **value);
|
||||
int xmldb_setopt(clicon_handle h, char *optname, void *value);
|
||||
int xmldb_get(clicon_handle h, char *db, char *xpath,
|
||||
cxobj **xtop, cxobj ***xvec, size_t *xlen);
|
||||
int xmldb_get(clicon_handle h, char *db, char *xpath, cxobj **xtop);
|
||||
int xmldb_put(clicon_handle h, char *db, enum operation_type op, cxobj *xt);
|
||||
int xmldb_copy(clicon_handle h, char *from, char *to);
|
||||
int xmldb_lock(clicon_handle h, char *db, int pid);
|
||||
|
|
|
|||
|
|
@ -47,7 +47,8 @@ enum {
|
|||
LVXML_VECVAL, /* key: a.b.0{x=1} -> <a><b><x>1</x></b></a> och */
|
||||
LVXML_VECVAL2, /* key: a.b.0{x=1} -> <a><x>1</x></a> och */
|
||||
};
|
||||
|
||||
extern const map_str2int netconf_restconf_map[];
|
||||
extern const map_str2int http_reason_phrase_map[];
|
||||
|
||||
/*
|
||||
* Prototypes
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ expectfn(){
|
|||
# echo "expect:\"$expect\""
|
||||
# echo "match:\"$match\""
|
||||
if [ -z "$match" ]; then
|
||||
err $expect "$ret"
|
||||
err "$expect" "$ret"
|
||||
fi
|
||||
if [ -n "$expect2" ]; then
|
||||
match=`echo "$ret" | grep -EZo "$expect2"`
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue