diff --git a/CHANGELOG.md b/CHANGELOG.md
index f9bfcd38..4584002e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -237,6 +237,7 @@
### Corrected Bugs
+* Fixed a problem with some netconf error messages caused restconf daemon to exit due to no XML encoding
* Check cligen tab mode, dont start if CLICON_CLI_TAB_MODE is undefined
* Startup transactions did not mark added tree with XML_FLAG_ADD as it should.
* Restconf PUT different keys detected (thanks @dcornejo) and fixed
diff --git a/lib/src/clixon_netconf_lib.c b/lib/src/clixon_netconf_lib.c
index 6667b436..bf59a9bb 100644
--- a/lib/src/clixon_netconf_lib.c
+++ b/lib/src/clixon_netconf_lib.c
@@ -74,7 +74,7 @@
* The request requires a resource that already is in use.
* @param[out] cb CLIgen buf. Error XML is written in this buffer
* @param[in] type Error type: "application" or "protocol"
- * @param[in] message Error message
+ * @param[in] message Error message (will be XML encoded)
*/
int
netconf_in_use(cbuf *cb,
@@ -113,7 +113,7 @@ netconf_in_use(cbuf *cb,
* The request specifies an unacceptable value for one or more parameters.
* @param[out] cb CLIgen buf. Error XML is written in this buffer
* @param[in] type Error type: "application" or "protocol"
- * @param[in] message Error message
+ * @param[in] message Error message (will be XML encoded)
*/
int
netconf_invalid_value(cbuf *cb,
@@ -153,7 +153,7 @@ netconf_invalid_value(cbuf *cb,
* too large for the implementation to handle.
* @param[out] cb CLIgen buf. Error XML is written in this buffer
* @param[in] type Error type: "transport", "rpc", "application", "protocol"
- * @param[in] message Error message
+ * @param[in] message Error message (will be XML encoded)
*/
int
netconf_too_big(cbuf *cb,
@@ -193,7 +193,7 @@ netconf_too_big(cbuf *cb,
* @param[out] cb CLIgen buf. Error XML is written in this buffer
* @param[in] type Error type: "rpc", "application" or "protocol"
* @param[in] info bad-attribute or bad-element xml
- * @param[in] message Error message
+ * @param[in] message Error message (will be XML encoded)
*/
int
netconf_missing_attribute(cbuf *cb,
@@ -234,7 +234,7 @@ netconf_missing_attribute(cbuf *cb,
* @param[out] cb CLIgen buf. Error XML is written in this buffer
* @param[in] type Error type: "rpc", "application" or "protocol"
* @param[in] info bad-attribute or bad-element xml
- * @param[in] message Error message
+ * @param[in] message Error message (will be XML encoded)
*/
int
netconf_bad_attribute(cbuf *cb,
@@ -317,7 +317,7 @@ netconf_unknown_attribute(cbuf *cb,
* @param[in] type Error type: "application" or "protocol"
* @param[in] tag Error tag
* @param[in] element bad-element xml
- * @param[in] message Error message
+ * @param[in] message Error message (will be XML encoded)
*/
static int
netconf_common_xml(cxobj **xret,
@@ -327,8 +327,9 @@ netconf_common_xml(cxobj **xret,
char *element,
char *message)
{
- int retval =-1;
+ int retval =-1;
cxobj *xerr;
+ char *encstr = NULL;
if (*xret == NULL){
if ((*xret = xml_new("rpc-reply", NULL, NULL)) == NULL)
@@ -344,11 +345,17 @@ netconf_common_xml(cxobj **xret,
"error",
type, tag, infotag, element, infotag) < 0)
goto done;
- if (message && xml_parse_va(&xerr, NULL, "%s",
- message) < 0)
- goto done;
+ if (message){
+ if (xml_chardata_encode(&encstr, "%s", message) < 0)
+ goto done;
+ if (xml_parse_va(&xerr, NULL, "%s",
+ encstr) < 0)
+ goto done;
+ }
retval = 0;
done:
+ if (encstr)
+ free(encstr);
return retval;
}
@@ -555,7 +562,7 @@ netconf_access_denied(cbuf *cb,
* authorization failed.
* @param[out] xret Error XML tree. Free with xml_free after use
* @param[in] type Error type: "application" or "protocol"
- * @param[in] message Error message
+ * @param[in] message Error message (will be XML encoded)
* @code
* cxobj *xret = NULL;
* if (netconf_access_denied_xml(&xret, "protocol", "Unauthorized") < 0)
@@ -569,9 +576,10 @@ netconf_access_denied_xml(cxobj **xret,
char *type,
char *message)
{
- int retval =-1;
+ int retval =-1;
cxobj *xerr;
-
+ char *encstr = NULL;
+
if (*xret == NULL){
if ((*xret = xml_new("rpc-reply", NULL, NULL)) == NULL)
goto done;
@@ -584,11 +592,17 @@ netconf_access_denied_xml(cxobj **xret,
"access-denied"
"error", type) < 0)
goto done;
- if (message && xml_parse_va(&xerr, NULL, "%s",
- message) < 0)
- goto done;
+ if (message){
+ if (xml_chardata_encode(&encstr, "%s", message) < 0)
+ goto done;
+ if (xml_parse_va(&xerr, NULL, "%s",
+ encstr) < 0)
+ goto done;
+ }
retval = 0;
done:
+ if (encstr)
+ free(encstr);
return retval;
}
@@ -905,7 +919,7 @@ netconf_operation_failed(cbuf *cb,
* some reason not covered by any other error condition.
* @param[out] xret Error XML tree
* @param[in] type Error type: "rpc", "application" or "protocol"
- * @param[in] message Error message
+ * @param[in] message Error message (will be XML encoded)
* @code
* cxobj *xret = NULL;
* if (netconf_operation_failed_xml(&xret, "protocol", "Unauthorized") < 0)
@@ -921,6 +935,7 @@ netconf_operation_failed_xml(cxobj **xret,
{
int retval =-1;
cxobj *xerr;
+ char *encstr = NULL;
if (*xret == NULL){
if ((*xret = xml_new("rpc-reply", NULL, NULL)) == NULL)
@@ -934,11 +949,17 @@ netconf_operation_failed_xml(cxobj **xret,
"operation-failed"
"error", type) < 0)
goto done;
- if (message && xml_parse_va(&xerr, NULL, "%s",
- message) < 0)
+ if (message){
+ if (xml_chardata_encode(&encstr, "%s", message) < 0)
+ goto done;
+ if (xml_parse_va(&xerr, NULL, "%s",
+ encstr) < 0)
goto done;
+ }
retval = 0;
done:
+ if (encstr)
+ free(encstr);
return retval;
}
@@ -976,7 +997,7 @@ netconf_malformed_message(cbuf *cb,
* For example, the message is not well-formed XML or it uses an
* invalid character set.
* @param[out] xret Error XML tree
- * @param[in] message Error message
+ * @param[in] message Error message (will be XML encoded)
* @note New in :base:1.1
* @code
* cxobj *xret = NULL;
@@ -990,8 +1011,9 @@ int
netconf_malformed_message_xml(cxobj **xret,
char *message)
{
- int retval =-1;
+ int retval =-1;
cxobj *xerr;
+ char *encstr = NULL;
if (*xret == NULL){
if ((*xret = xml_new("rpc-reply", NULL, NULL)) == NULL)
@@ -1005,11 +1027,17 @@ netconf_malformed_message_xml(cxobj **xret,
"malformed-message"
"error") < 0)
goto done;
- if (message && xml_parse_va(&xerr, NULL, "%s",
- message) < 0)
- goto done;
+ if (message){
+ if (xml_chardata_encode(&encstr, "%s", message) < 0)
+ goto done;
+ if (xml_parse_va(&xerr, NULL, "%s",
+ encstr) < 0)
+ goto done;
+ }
retval = 0;
done:
+ if (encstr)
+ free(encstr);
return retval;
}
diff --git a/lib/src/clixon_xml_map.c b/lib/src/clixon_xml_map.c
index 04cb8b79..6ef46b70 100644
--- a/lib/src/clixon_xml_map.c
+++ b/lib/src/clixon_xml_map.c
@@ -2212,7 +2212,9 @@ xml_spec_populate_rpc(clicon_handle h,
if (yrpc){
xml_spec_set(x, yrpc);
if ((yi = yang_find(yrpc, Y_INPUT, NULL)) != NULL){
- /* kludge rpc -> input XXX THIS HIDES AN ERROR IN xml_spec_populate */
+ /* xml_spec_populate need to have parent with yang spec for
+ * recursive population to work. Therefore, assign input yang
+ * to rpc level although not 100% intuitive */
xml_spec_set(x, yi);
if (xml_apply(x, CX_ELMNT, xml_spec_populate, yspec) < 0)
goto done;
diff --git a/test/test_nacm_ext.sh b/test/test_nacm_ext.sh
index e2207ea8..9453978a 100755
--- a/test/test_nacm_ext.sh
+++ b/test/test_nacm_ext.sh
@@ -149,7 +149,8 @@ new "start restconf daemon (-a is enable http basic auth)"
start_restconf -f $cfg -- -a
new "waiting"
-sleep $RCWAIT
+wait_backend
+wait_restconf
new "auth get"
expecteq "$(curl -u andy:bar -sS -X GET http://localhost/restconf/data)" 0 '{"data": {"clixon-example:state": {"op": ["42","41","43"]}}}
diff --git a/test/test_netconf.sh b/test/test_netconf.sh
index 6ec9e127..05cfdfe5 100755
--- a/test/test_netconf.sh
+++ b/test/test_netconf.sh
@@ -46,7 +46,7 @@ if [ $BE -ne 0 ]; then
start_backend -s init -f $cfg -- -s
new "waiting"
- sleep $RCWAIT
+ wait_backend
fi
new "netconf hello"
diff --git a/test/test_restconf_listkey.sh b/test/test_restconf_listkey.sh
index 2426e4b9..cb0546e4 100755
--- a/test/test_restconf_listkey.sh
+++ b/test/test_restconf_listkey.sh
@@ -90,6 +90,10 @@ wait_restconf
new "restconf PUT add whole list entry"
expectfn 'curl -s -X PUT http://localhost/restconf/data/list:c/a=x,y -d {"list:a":{"b":"x","c":"y","nonkey":"0"}}' 0 ''
+new "restconf PUT add whole list entry XML"
+expecteq "$(curl -s -X PUT -H 'Content-Type: application/yang-data+xml' -H 'Accept: application/yang-data+xml' -d 'xxxy0' http://localhost/restconf/data/list:c/a=xx,xy)" 0 ''
+
+
new "restconf PUT change whole list entry (same keys)"
expectfn 'curl -s -X PUT http://localhost/restconf/data/list:c/a=x,y -d {"list:a":{"b":"x","c":"y","nonkey":"z"}}' 0 ''
@@ -99,6 +103,9 @@ expectfn 'curl -s -X PUT http://localhost/restconf/data/list:c/a=x,y -d {"a":{"b
new "restconf PUT change list entry (wrong keys)(expect fail)"
expectfn 'curl -s -X PUT http://localhost/restconf/data/list:c/a=x,y -d {"list:a":{"b":"y","c":"x"}}' 0 '{"ietf-restconf:errors" : {"error": {"error-type": "protocol","error-tag": "operation-failed","error-severity": "error","error-message": "api-path keys do not match data keys"}}}'
+new "restconf PUT change list entry (wrong keys)(expect fail) XML"
+expecteq "$(curl -s -X PUT -H 'Content-Type: application/yang-data+xml' -H 'Accept: application/yang-data+xml' -d 'xyxz0' http://localhost/restconf/data/list:c/a=xx,xy)" 0 'protocoloperation-failederrorapi-path keys do not match data keys
'
+
new "restconf PUT change list entry (just one key)(expect fail)"
expectfn 'curl -s -X PUT http://localhost/restconf/data/list:c/a=x -d {"list:a":{"b":"x"}}' 0 '{"ietf-restconf:errors" : {"error": {"error-type": "rpc","error-tag": "malformed-message","error-severity": "error","error-message": "List key a length mismatch"}}}
'
diff --git a/test/test_rpc.sh b/test/test_rpc.sh
index d78ec54e..e39b6847 100755
--- a/test/test_rpc.sh
+++ b/test/test_rpc.sh
@@ -77,11 +77,11 @@ expecteq "$(curl -s -X POST -d '{"clixon-example:input":{"x":"0","y":"99"}}' htt
new "restconf example rpc json/json"
# XXX example:input example:output
-expecteq "$(curl -s -X POST -H 'Content-Type: application/yang-data+json' -H 'Content-Type: application/yang-data+json' -d '{"clixon-example:input":{"x":"0"}}' http://localhost/restconf/operations/clixon-example:example)" 0 '{"clixon-example:output": {"x": "0","y": "42"}}
+expecteq "$(curl -s -X POST -H 'Content-Type: application/yang-data+json' -H 'Accept: application/yang-data+json' -d '{"clixon-example:input":{"x":"0"}}' http://localhost/restconf/operations/clixon-example:example)" 0 '{"clixon-example:output": {"x": "0","y": "42"}}
'
new "restconf example rpc xml/json"
-expecteq "$(curl -s -X POST -H 'Content-Type: application/yang-data+xml' -H 'Content-Type: application/yang-data+json' -d '0' http://localhost/restconf/operations/clixon-example:example)" 0 '{"clixon-example:output": {"x": "0","y": "42"}}
+expecteq "$(curl -s -X POST -H 'Content-Type: application/yang-data+xml' -H 'Accept: application/yang-data+json' -d '0' http://localhost/restconf/operations/clixon-example:example)" 0 '{"clixon-example:output": {"x": "0","y": "42"}}
'
new "restconf example rpc json/xml"