* Proper RFC 6241 Netconf error handling
* New functions added in clixon_netconf_lib.[ch] * Datastore code modified for RFC 6241 * Remaining: validate, generic restconf and netconf code
This commit is contained in:
parent
52e510cfdf
commit
efa72e9e6f
26 changed files with 1196 additions and 475 deletions
|
|
@ -180,7 +180,7 @@ backend_client_rm(clicon_handle h,
|
|||
return backend_client_delete(h, ce); /* actually purge it */
|
||||
}
|
||||
|
||||
/*! FInd target/source in netconf request. Assume sanity made so not finding is error */
|
||||
/*! Find target/source in netconf request. Assume sanity- not finding is error */
|
||||
static char*
|
||||
netconf_db_find(cxobj *xn,
|
||||
char *name)
|
||||
|
|
@ -214,31 +214,28 @@ from_client_get_config(clicon_handle h,
|
|||
cxobj *xfilter;
|
||||
char *selector = "/";
|
||||
cxobj *xret = NULL;
|
||||
cbuf *cbx = NULL; /* Assist cbuf */
|
||||
|
||||
if ((db = netconf_db_find(xe, "source")) == NULL){
|
||||
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);
|
||||
if ((cbx = cbuf_new()) == NULL){
|
||||
clicon_err(OE_XML, errno, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
cprintf(cbx, "No such database: %s", db);
|
||||
if (netconf_invalid_value(cbret, "protocol", cbuf_get(cbx))< 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
|
||||
if ((xfilter = xml_find(xe, "filter")) != NULL)
|
||||
if ((selector = xml_find_value(xfilter, "select"))==NULL)
|
||||
selector="/";
|
||||
if (xmldb_get(h, db, selector, 1, &xret) < 0){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>operation-failed</error-tag>"
|
||||
"<error-type>application</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-info>read-registry</error-info>"
|
||||
"</rpc-error></rpc-reply>");
|
||||
if (netconf_operation_failed(cbret, "application", "read registry")< 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
cprintf(cbret, "<rpc-reply>");
|
||||
|
|
@ -254,6 +251,8 @@ from_client_get_config(clicon_handle h,
|
|||
ok:
|
||||
retval = 0;
|
||||
done:
|
||||
if (cbx)
|
||||
cbuf_free(cbx);
|
||||
if (xret)
|
||||
xml_free(xret);
|
||||
return retval;
|
||||
|
|
@ -276,18 +275,15 @@ from_client_get(clicon_handle h,
|
|||
char *selector = "/";
|
||||
cxobj *xret = NULL;
|
||||
int ret;
|
||||
cbuf *cbx = NULL; /* Assist cbuf */
|
||||
|
||||
if ((xfilter = xml_find(xe, "filter")) != NULL)
|
||||
if ((selector = xml_find_value(xfilter, "select"))==NULL)
|
||||
selector="/";
|
||||
/* Get config */
|
||||
if (xmldb_get(h, "running", selector, 0, &xret) < 0){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>operation-failed</error-tag>"
|
||||
"<error-type>application</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-info>read-registry</error-info>"
|
||||
"</rpc-error></rpc-reply>");
|
||||
if (netconf_operation_failed(cbret, "application", "read registry")< 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
/* Get state data from plugins as defined by plugin_statedata(), if any */
|
||||
|
|
@ -308,23 +304,25 @@ from_client_get(clicon_handle h,
|
|||
cprintf(cbret, "</rpc-reply>");
|
||||
}
|
||||
else { /* 1 Error from callback */
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>operation-failed</error-tag>"
|
||||
"<error-type>rpc</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-message>Internal error:%s</error-message>"
|
||||
"</rpc-error></rpc-reply>", clicon_err_reason);
|
||||
if ((cbx = cbuf_new()) == NULL){
|
||||
clicon_err(OE_XML, errno, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
cprintf(cbx, "Internal error:%s", clicon_err_reason);
|
||||
if (netconf_operation_failed(cbret, "rpc", cbuf_get(cbx))< 0)
|
||||
goto done;
|
||||
clicon_log(LOG_NOTICE, "%s Error in backend_statedata_call:%s", __FUNCTION__, xml_name(xe));
|
||||
}
|
||||
ok:
|
||||
retval = 0;
|
||||
done:
|
||||
if (cbx)
|
||||
cbuf_free(cbx);
|
||||
if (xret)
|
||||
xml_free(xret);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*! Internal message: edit-config
|
||||
*
|
||||
* @param[in] h Clicon handle
|
||||
|
|
@ -340,14 +338,13 @@ from_client_edit_config(clicon_handle h,
|
|||
{
|
||||
int retval = -1;
|
||||
char *target;
|
||||
cbuf *cb = NULL;
|
||||
cxobj *xret = NULL;
|
||||
cxobj *xc;
|
||||
cxobj *x;
|
||||
enum operation_type operation = OP_MERGE;
|
||||
int piddb;
|
||||
int non_config = 0;
|
||||
yang_spec *yspec;
|
||||
cbuf *cbx = NULL; /* Assist cbuf */
|
||||
|
||||
if ((yspec = clicon_dbspec_yang(h)) == NULL){
|
||||
clicon_err(OE_YANG, ENOENT, "No yang spec");
|
||||
|
|
@ -357,50 +354,44 @@ from_client_edit_config(clicon_handle h,
|
|||
clicon_err(OE_XML, 0, "db not found");
|
||||
goto done;
|
||||
}
|
||||
if ((cbx = cbuf_new()) == NULL){
|
||||
clicon_err(OE_XML, errno, "cbuf_new");
|
||||
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);
|
||||
cprintf(cbx, "No such database: %s", target);
|
||||
if (netconf_invalid_value(cbret, "protocol", cbuf_get(cbx))< 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
/* Check if target locked by other client */
|
||||
piddb = xmldb_islocked(h, target);
|
||||
if (piddb && mypid != piddb){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>lock-denied</error-tag>"
|
||||
"<error-type>protocol</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-message>Operation failed, lock is already held</error-message>"
|
||||
"<error-info><session-id>%d</session-id></error-info>"
|
||||
"</rpc-error></rpc-reply>",
|
||||
piddb);
|
||||
cprintf(cbx, "<session-id>%d</session-id>", piddb);
|
||||
if (netconf_lock_denied(cbret, cbuf_get(cbx), "Operation failed, lock is already held") < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
if ((x = xpath_first(xn, "default-operation")) != NULL){
|
||||
if (xml_operation(xml_body(x), &operation) < 0){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>invalid-value</error-tag>"
|
||||
"<error-type>protocol</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"</rpc-error></rpc-reply>");
|
||||
if (netconf_invalid_value(cbret, "protocol", "Wrong operation")< 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
}
|
||||
if ((xc = xpath_first(xn, "config")) != NULL){
|
||||
if ((xc = xpath_first(xn, "config")) == NULL){
|
||||
if (netconf_missing_element(cbret, "protocol", "<bad-element>config</bad-element>", NULL) < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
else{
|
||||
if (xml_apply(xc, CX_ELMNT, xml_spec_populate, yspec) < 0)
|
||||
goto done;
|
||||
if (xml_apply(xc, CX_ELMNT, xml_non_config_data, &non_config) < 0)
|
||||
goto done;
|
||||
if (non_config){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>invalid-value</error-tag>"
|
||||
"<error-type>protocol</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-message>state data not allowed</error-message>"
|
||||
"</rpc-error></rpc-reply>");
|
||||
if (netconf_invalid_value(cbret, "protocol", "State data not allowed")< 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
/* Cant do this earlier since we dont have a yang spec to
|
||||
|
|
@ -408,35 +399,23 @@ from_client_edit_config(clicon_handle h,
|
|||
*/
|
||||
if (xml_child_sort && xml_apply0(xc, CX_ELMNT, xml_sort, NULL) < 0)
|
||||
goto done;
|
||||
if (xmldb_put(h, target, operation, xc) < 0){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>operation-failed</error-tag>"
|
||||
"<error-type>protocol</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-message>%s</error-message>"
|
||||
"</rpc-error></rpc-reply>", clicon_err_reason);
|
||||
if (xmldb_put(h, target, operation, xc, cbret) < 0){
|
||||
clicon_debug(1, "%s ERROR PUT", __FUNCTION__);
|
||||
if (netconf_operation_failed(cbret, "protocol", clicon_err_reason)< 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
}
|
||||
else{
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>missing-element</error-tag>"
|
||||
"<error-type>protocol</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-info><bad-element>config</bad-element></error-info>"
|
||||
"</rpc-error></rpc-reply>");
|
||||
goto ok;
|
||||
}
|
||||
cprintf(cbret, "<rpc-reply><ok/></rpc-reply>");
|
||||
ok:
|
||||
if (!cbuf_len(cbret))
|
||||
cprintf(cbret, "<rpc-reply><ok/></rpc-reply>");
|
||||
retval = 0;
|
||||
done:
|
||||
if (xret)
|
||||
xml_free(xret);
|
||||
if (cb)
|
||||
cbuf_free(cb);
|
||||
if (cbx)
|
||||
cbuf_free(cbx);
|
||||
clicon_debug(1, "%s done cbret:%s", __FUNCTION__, cbuf_get(cbret));
|
||||
return retval;
|
||||
}
|
||||
} /* from_client_edit_config */
|
||||
|
||||
/*! Internal message: Lock database
|
||||
*
|
||||
|
|
@ -454,26 +433,23 @@ from_client_lock(clicon_handle h,
|
|||
int retval = -1;
|
||||
char *db;
|
||||
int piddb;
|
||||
cbuf *cbx = NULL; /* Assist cbuf */
|
||||
|
||||
if ((db = netconf_db_find(xe, "target")) == NULL){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>missing-element</error-tag>"
|
||||
"<error-type>protocol</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-info><bad-element>target</bad-element></error-info>"
|
||||
"</rpc-error></rpc-reply>");
|
||||
if (netconf_missing_element(cbret, "protocol", "<bad-element>target</bad-element>", NULL) < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
if ((cbx = cbuf_new()) == NULL){
|
||||
clicon_err(OE_XML, errno, "cbuf_new");
|
||||
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);
|
||||
cprintf(cbx, "No such database: %s", db);
|
||||
if (netconf_invalid_value(cbret, "protocol", cbuf_get(cbx))< 0)
|
||||
goto done;
|
||||
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.
|
||||
|
|
@ -482,23 +458,21 @@ from_client_lock(clicon_handle h,
|
|||
*/
|
||||
piddb = xmldb_islocked(h, db);
|
||||
if (piddb){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>lock-denied</error-tag>"
|
||||
"<error-type>protocol</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-message>Lock failed, lock is already held</error-message>"
|
||||
"<error-info><session-id>%d</session-id></error-info>"
|
||||
"</rpc-error></rpc-reply>",
|
||||
piddb);
|
||||
cprintf(cbx, "<session-id>%d</session-id>", piddb);
|
||||
if (netconf_lock_denied(cbret, cbuf_get(cbx), "Operation failed, lock is already held") < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
else{
|
||||
xmldb_lock(h, db, pid);
|
||||
if (xmldb_lock(h, db, pid) < 0)
|
||||
goto done;
|
||||
cprintf(cbret, "<rpc-reply><ok/></rpc-reply>");
|
||||
}
|
||||
ok:
|
||||
retval = 0;
|
||||
// done:
|
||||
done:
|
||||
if (cbx)
|
||||
cbuf_free(cbx);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -518,23 +492,21 @@ from_client_unlock(clicon_handle h,
|
|||
int retval = -1;
|
||||
char *db;
|
||||
int piddb;
|
||||
cbuf *cbx = NULL; /* Assist cbuf */
|
||||
|
||||
if ((db = netconf_db_find(xe, "target")) == NULL){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>missing-element</error-tag>"
|
||||
"<error-type>protocol</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-info><bad-element>target</bad-element></error-info>"
|
||||
"</rpc-error></rpc-reply>");
|
||||
if (netconf_missing_element(cbret, "protocol", "<bad-element>target</bad-element>", NULL) < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
if ((cbx = cbuf_new()) == NULL){
|
||||
clicon_err(OE_XML, errno, "cbuf_new");
|
||||
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);
|
||||
cprintf(cbx, "No such database: %s", db);
|
||||
if (netconf_invalid_value(cbret, "protocol", cbuf_get(cbx))< 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
piddb = xmldb_islocked(h, db);
|
||||
|
|
@ -546,14 +518,9 @@ from_client_unlock(clicon_handle h,
|
|||
* session that obtained the lock
|
||||
*/
|
||||
if (piddb==0 || piddb != pid){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>lock-denied</error-tag>"
|
||||
"<error-type>protocol</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-message>Unlock failed, lock is already held</error-message>"
|
||||
"<error-info><session-id>pid=%d piddb=%d</session-id></error-info>"
|
||||
"</rpc-error></rpc-reply>",
|
||||
pid, piddb);
|
||||
cprintf(cbx, "<session-id>pid=%d piddb=%d</session-id>", pid, piddb);
|
||||
if (netconf_lock_denied(cbret, cbuf_get(cbx), "Unlock failed, lock is already held") < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
else{
|
||||
|
|
@ -585,15 +552,11 @@ from_client_kill_session(clicon_handle h,
|
|||
struct client_entry *ce;
|
||||
char *db = "running"; /* XXX */
|
||||
cxobj *x;
|
||||
|
||||
|
||||
if ((x = xml_find(xe, "session-id")) == NULL ||
|
||||
(str = xml_find_value(x, "body")) == NULL){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>missing-element</error-tag>"
|
||||
"<error-type>protocol</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-info><bad-element>session-id</bad-element></error-info>"
|
||||
"</rpc-error></rpc-reply>");
|
||||
if (netconf_missing_element(cbret, "protocol", "<bad-element>session-id</bad-element>", NULL) < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
pid = atoi(str);
|
||||
|
|
@ -618,18 +581,14 @@ from_client_kill_session(clicon_handle h,
|
|||
xmldb_unlock(h, db);
|
||||
}
|
||||
else{ /* failed to kill client */
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>operation-failed</error-tag>"
|
||||
"<error-type>application</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-message>Faile to kill session</error-message>"
|
||||
"</rpc-error></rpc-reply>");
|
||||
if (netconf_operation_failed(cbret, "application", "Failed to kill session")< 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
cprintf(cbret, "<rpc-reply><ok/></rpc-reply>");
|
||||
ok:
|
||||
retval = 0;
|
||||
// done:
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -647,74 +606,57 @@ from_client_copy_config(clicon_handle h,
|
|||
int mypid,
|
||||
cbuf *cbret)
|
||||
{
|
||||
char *source;
|
||||
char *target;
|
||||
int retval = -1;
|
||||
int piddb;
|
||||
|
||||
char *source;
|
||||
char *target;
|
||||
int retval = -1;
|
||||
int piddb;
|
||||
cbuf *cbx = NULL; /* Assist cbuf */
|
||||
|
||||
if ((source = netconf_db_find(xe, "source")) == NULL){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>missing-element</error-tag>"
|
||||
"<error-type>protocol</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-info><bad-element>source</bad-element></error-info>"
|
||||
"</rpc-error></rpc-reply>");
|
||||
if (netconf_missing_element(cbret, "protocol", "<bad-element>source</bad-element>", NULL) < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
if ((cbx = cbuf_new()) == NULL){
|
||||
clicon_err(OE_XML, errno, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
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);
|
||||
cprintf(cbx, "No such database: %s", source);
|
||||
if (netconf_invalid_value(cbret, "protocol", cbuf_get(cbx))< 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
|
||||
if ((target = netconf_db_find(xe, "target")) == NULL){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>missing-element</error-tag>"
|
||||
"<error-type>protocol</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-info><bad-element>target</bad-element></error-info>"
|
||||
"</rpc-error></rpc-reply>");
|
||||
if (netconf_missing_element(cbret, "protocol", "<bad-element>target</bad-element>", NULL) < 0)
|
||||
goto done;
|
||||
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);
|
||||
cprintf(cbx, "No such database: %s", target);
|
||||
if (netconf_invalid_value(cbret, "protocol", cbuf_get(cbx))< 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
/* Check if target locked by other client */
|
||||
piddb = xmldb_islocked(h, target);
|
||||
if (piddb && mypid != piddb){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>lock-denied</error-tag>"
|
||||
"<error-type>protocol</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-message>Operation failed, lock is already held</error-message>"
|
||||
"<error-info><session-id>%d</session-id></error-info>"
|
||||
"</rpc-error></rpc-reply>",
|
||||
piddb);
|
||||
cprintf(cbx, "<session-id>%d</session-id>", piddb);
|
||||
if (netconf_lock_denied(cbret, cbuf_get(cbx), "Copy failed, lock is already held") < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
if (xmldb_copy(h, source, target) < 0){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>operation-failed</error-tag>"
|
||||
"<error-type>application</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-info>read-registry</error-info>"
|
||||
"</rpc-error></rpc-reply>");
|
||||
if (netconf_operation_failed(cbret, "application", clicon_err_reason)< 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
cprintf(cbret, "<rpc-reply><ok/></rpc-reply>");
|
||||
ok:
|
||||
retval = 0;
|
||||
// done:
|
||||
done:
|
||||
if (cbx)
|
||||
cbuf_free(cbx);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -732,67 +674,51 @@ from_client_delete_config(clicon_handle h,
|
|||
int mypid,
|
||||
cbuf *cbret)
|
||||
{
|
||||
int retval = -1;
|
||||
char *target;
|
||||
int piddb;
|
||||
int retval = -1;
|
||||
char *target;
|
||||
int piddb;
|
||||
cbuf *cbx = NULL; /* Assist cbuf */
|
||||
|
||||
if ((target = netconf_db_find(xe, "target")) == NULL||
|
||||
strcmp(target, "running")==0){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>missing-element</error-tag>"
|
||||
"<error-type>protocol</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-info><bad-element>target</bad-element></error-info>"
|
||||
"</rpc-error></rpc-reply>");
|
||||
if (netconf_missing_element(cbret, "protocol", "<bad-element>target</bad-element>", NULL) < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
if ((cbx = cbuf_new()) == NULL){
|
||||
clicon_err(OE_XML, errno, "cbuf_new");
|
||||
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);
|
||||
cprintf(cbx, "No such database: %s", target);
|
||||
if (netconf_invalid_value(cbret, "protocol", cbuf_get(cbx))< 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
|
||||
/* Check if target locked by other client */
|
||||
piddb = xmldb_islocked(h, target);
|
||||
if (piddb && mypid != piddb){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>lock-denied</error-tag>"
|
||||
"<error-type>protocol</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-message>Operation failed, lock is already held</error-message>"
|
||||
"<error-info><session-id>%d</session-id></error-info>"
|
||||
"</rpc-error></rpc-reply>",
|
||||
piddb);
|
||||
cprintf(cbx, "<session-id>%d</session-id>", piddb);
|
||||
if (netconf_lock_denied(cbret, cbuf_get(cbx), "Operation failed, lock is already held") < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
if (xmldb_delete(h, target) < 0){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>operation-failed</error-tag>"
|
||||
"<error-type>protocol</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-info>Internal error</error-info>"
|
||||
"<error-message>%s</error-message>"
|
||||
"</rpc-error></rpc-reply>", clicon_err_reason);
|
||||
if (netconf_operation_failed(cbret, "protocol", clicon_err_reason)< 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
if (xmldb_create(h, target) < 0){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>operation-failed</error-tag>"
|
||||
"<error-type>protocol</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-info>Internal error</error-info>"
|
||||
"<error-message>%s</error-message>"
|
||||
"</rpc-error></rpc-reply>", clicon_err_reason);
|
||||
if (netconf_operation_failed(cbret, "protocol", clicon_err_reason)< 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
cprintf(cbret, "<rpc-reply><ok/></rpc-reply>");
|
||||
ok:
|
||||
retval = 0;
|
||||
// done:
|
||||
done:
|
||||
if (cbx)
|
||||
cbuf_free(cbx);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -829,13 +755,8 @@ from_client_create_subscription(clicon_handle h,
|
|||
if ((ftype = xml_find_value(x, "type")) != NULL){
|
||||
/* Only accept xpath as filter type */
|
||||
if (strcmp(ftype, "xpath") != 0){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>operation-failed</error-tag>"
|
||||
"<error-type>application</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-message>only xpath filter type supported</error-message>"
|
||||
"<error-info>type</error-info>"
|
||||
"</rpc-error></rpc-reply>");
|
||||
if (netconf_operation_failed(cbret, "application", "Only xpath filter type supported")< 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
}
|
||||
|
|
@ -866,12 +787,8 @@ from_client_debug(clicon_handle h,
|
|||
char *valstr;
|
||||
|
||||
if ((valstr = xml_find_body(xe, "level")) == NULL){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>missing-element</error-tag>"
|
||||
"<error-type>protocol</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-info><bad-element>level</bad-element></error-info>"
|
||||
"</rpc-error></rpc-reply>");
|
||||
if (netconf_missing_element(cbret, "application", "<bad-element>level</bad-element>", NULL) < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
level = atoi(valstr);
|
||||
|
|
@ -882,7 +799,7 @@ from_client_debug(clicon_handle h,
|
|||
cprintf(cbret, "<rpc-reply><ok/></rpc-reply>");
|
||||
ok:
|
||||
retval = 0;
|
||||
//done:
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -917,23 +834,13 @@ from_client_msg(clicon_handle h,
|
|||
goto done;
|
||||
}
|
||||
if (clicon_msg_decode(msg, &xt) < 0){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>operation-failed</error-tag>"
|
||||
"<error-type>rpc</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-message>rpc expected</error-message>"
|
||||
"<error-info>Not recognized</error-info>"
|
||||
"</rpc-error></rpc-reply>");
|
||||
if (netconf_malformed_message(cbret, "Not recognized, rpc expected")< 0)
|
||||
goto done;
|
||||
goto reply;
|
||||
}
|
||||
if ((x = xpath_first(xt, "/rpc")) == NULL){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>operation-failed</error-tag>"
|
||||
"<error-type>rpc</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-message>rpc expected</error-message>"
|
||||
"<error-info>Not recognized</error-info>"
|
||||
"</rpc-error></rpc-reply>");
|
||||
if (netconf_malformed_message(cbret, "Not recognized, rpc expected")< 0)
|
||||
goto done;
|
||||
goto reply;
|
||||
}
|
||||
xe = NULL;
|
||||
|
|
@ -977,12 +884,8 @@ from_client_msg(clicon_handle h,
|
|||
}
|
||||
else if (strcmp(name, "validate") == 0){
|
||||
if ((db = netconf_db_find(xe, "source")) == NULL){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>missing-element</error-tag>"
|
||||
"<error-type>protocol</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-info><bad-element>source</bad-element></error-info>"
|
||||
"</rpc-error></rpc-reply>");
|
||||
if (netconf_missing_element(cbret, "protocol", "<bad-element>source</bad-element>", NULL) < 0)
|
||||
goto done;
|
||||
goto reply;
|
||||
}
|
||||
if (from_client_validate(h, db, cbret) < 0)
|
||||
|
|
@ -1007,34 +910,22 @@ from_client_msg(clicon_handle h,
|
|||
else{
|
||||
clicon_err_reset();
|
||||
if ((ret = backend_rpc_cb_call(h, xe, ce, cbret)) < 0){
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>operation-failed</error-tag>"
|
||||
"<error-type>rpc</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-message>Internal error:%s</error-message>"
|
||||
"</rpc-error></rpc-reply>", clicon_err_reason);
|
||||
if (netconf_operation_failed(cbret, "application", clicon_err_reason)< 0)
|
||||
goto done;
|
||||
clicon_log(LOG_NOTICE, "%s Error in backend_rpc_call:%s", __FUNCTION__, xml_name(xe));
|
||||
goto reply; /* Dont quit here on user callbacks */
|
||||
}
|
||||
if (ret == 0) /* not handled by callback */
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>operation-failed</error-tag>"
|
||||
"<error-type>rpc</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-message>%s</error-message>"
|
||||
"<error-info>Not recognized</error-info>"
|
||||
"</rpc-error></rpc-reply>",
|
||||
name);
|
||||
if (ret == 0){ /* not handled by callback */
|
||||
if (netconf_operation_failed(cbret, "application", "Callback not recognized")< 0)
|
||||
goto done;
|
||||
goto reply;
|
||||
}
|
||||
}
|
||||
}
|
||||
reply:
|
||||
if (cbuf_len(cbret) == 0)
|
||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||
"<error-tag>operation-failed</error-tag>"
|
||||
"<error-type>rpc</error-type>"
|
||||
"<error-severity>error</error-severity>"
|
||||
"<error-message>Internal error %s</error-message>"
|
||||
"</rpc-error></rpc-reply>",clicon_err_reason);
|
||||
if (netconf_operation_failed(cbret, "application", clicon_err_reason)< 0)
|
||||
goto done;
|
||||
clicon_debug(1, "%s cbret:%s", __FUNCTION__, cbuf_get(cbret));
|
||||
if (send_msg_reply(ce->ce_s, cbuf_get(cbret), cbuf_len(cbret)+1) < 0){
|
||||
switch (errno){
|
||||
|
|
@ -1055,7 +946,7 @@ from_client_msg(clicon_handle h,
|
|||
}
|
||||
// ok:
|
||||
retval = 0;
|
||||
done:
|
||||
done:
|
||||
if (xt)
|
||||
xml_free(xt);
|
||||
if (cbret)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue