From a38c54e4ccfa26ebc53617bfff6b421df66c6c5e Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Sat, 3 Dec 2022 18:49:39 +0100 Subject: [PATCH] Netconf monitoring: - Announce module capability - Return origin Yang file in get-schema --- CHANGELOG.md | 10 +++++ apps/backend/backend_client.c | 50 +++++++++++++++++------- lib/clixon/clixon_file.h | 3 +- lib/src/clixon_file.c | 49 +++++++++++++++++++++-- lib/src/clixon_netconf_lib.c | 5 +++ test/test_netconf_monitoring.sh | 17 ++++---- test/test_netconf_monitoring_multiple.sh | 4 +- test/test_netconf_ssh_callhome.sh | 2 +- 8 files changed, 108 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1d121eb..e892b8f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # Clixon Changelog +* [6.1.0](#610) Expected: beginning of 2023 * [6.0.0](#600) 29 Nov 2022 * [5.9.0](#590) 24 September 2022 * [5.8.0](#580) 28 July 2022 @@ -37,6 +38,15 @@ * [3.3.2](#332) Aug 27 2017 * [3.3.1](#331) June 7 2017 +## 6.1.0 +Expected: beginning of 2023 + +### Corrected Bugs + +* Fixed [Netconf monitoring](https://github.com/clicon/clixon/issues/370) + - Announce module capability + - Return origin Yang file in get-schema + ## 6.0.0 29 Nov 2022 diff --git a/apps/backend/backend_client.c b/apps/backend/backend_client.c index aa85374e..093b8c3d 100644 --- a/apps/backend/backend_client.c +++ b/apps/backend/backend_client.c @@ -1064,18 +1064,20 @@ from_client_get_schema(clicon_handle h, void *arg, void *regarg) { - int retval = -1; - cxobj *x; /* Generic xml tree */ - cvec *nsc = NULL; - char *identifier = NULL; - char *version = NULL; - char *format = NULL; - yang_stmt *yspec; - yang_stmt *ymod; - yang_stmt *ymatch; - yang_stmt *yrev; - cbuf *cbyang = NULL; - + int retval = -1; + cxobj *x; /* Generic xml tree */ + cvec *nsc = NULL; + char *identifier = NULL; + char *version = NULL; + char *format = NULL; + yang_stmt *yspec; + yang_stmt *ymod; + yang_stmt *ymatch; + yang_stmt *yrev; + cbuf *cbyang = NULL; + cbuf *cbmsg = NULL; + const char *filename; + if ((yspec = clicon_dbspec_yang(h)) == NULL){ clicon_err(OE_YANG, ENOENT, "No yang spec"); goto done; @@ -1121,12 +1123,25 @@ from_client_get_schema(clicon_handle h, ymatch = ymod; } if (ymatch == NULL){ - if (netconf_invalid_value(cbret, "protocol", "No such schema") < 0) + if ((cbmsg = cbuf_new()) == NULL){ + clicon_err(OE_XML, errno, "cbuf_new"); + goto done; + } + if (version) + cprintf(cbmsg, "No schema matching: %s@%s", identifier, version); + else + cprintf(cbmsg, "No schema matching: %s", identifier); + if (netconf_invalid_value(cbret, "protocol", cbuf_get(cbmsg)) < 0) goto done; goto ok; } if (format && strcmp(format, "yang") != 0){ - if (netconf_invalid_value(cbret, "protocol", "Format not supported") < 0) + if ((cbmsg = cbuf_new()) == NULL){ + clicon_err(OE_XML, errno, "cbuf_new"); + goto done; + } + cprintf(cbmsg, "Format not supported: %s", format); + if (netconf_invalid_value(cbret, "protocol", cbuf_get(cbmsg)) < 0) goto done; goto ok; } @@ -1136,12 +1151,17 @@ from_client_get_schema(clicon_handle h, clicon_err(OE_UNIX, errno, "cbuf_new"); goto done; } - yang_print_cbuf(cbyang, ymatch, 0, 0); + if ((filename = yang_filename_get(ymatch)) != NULL){ + if (clicon_file_cbuf(filename, cbyang) < 0) + goto done; + } xml_chardata_cbuf_append(cbret, cbuf_get(cbyang)); cprintf(cbret, ""); ok: retval = 0; done: + if (cbmsg) + cbuf_free(cbmsg); if (cbyang) cbuf_free(cbyang); if (nsc) diff --git a/lib/clixon/clixon_file.h b/lib/clixon/clixon_file.h index 195522ac..62feb2e6 100644 --- a/lib/clixon/clixon_file.h +++ b/lib/clixon/clixon_file.h @@ -42,9 +42,8 @@ int clicon_file_dirent(const char *dir, struct dirent **ent, const char *regexp, mode_t type); - int clicon_files_recursive(const char *dir, const char *regexp, cvec *cvv); - int clicon_file_copy(char *src, char *target); +int clicon_file_cbuf(const char *filename, cbuf *cb); #endif /* _CLIXON_FILE_H_ */ diff --git a/lib/src/clixon_file.c b/lib/src/clixon_file.c index 83731c11..eec717e8 100644 --- a/lib/src/clixon_file.c +++ b/lib/src/clixon_file.c @@ -160,9 +160,9 @@ clicon_files_recursive(const char *dir, } /*! Return alphabetically sorted files from a directory matching regexp + * * @param[in] dir Directory path * @param[out] ent Entries pointer, will be filled in with dir entries. Free - * after use * @param[in] regexp Regexp filename matching * @param[in] type File type matching, see stat(2) * @@ -262,8 +262,11 @@ quit: } /*! Make a copy of file src. Overwrite existing - * @retval 0 OK - * @retval -1 Error + * + * @param[in] src Source filename + * @param[out] target Destination filename + * @retval 0 OK + * @retval -1 Error */ int clicon_file_copy(char *src, @@ -304,3 +307,43 @@ clicon_file_copy(char *src, errno = err; return retval; } + +/*! Read content of file into cbuf + * + * @param[in] filename + * @param[out] cb + * @retval 0 OK + * @retval -1 Error + */ +int +clicon_file_cbuf(const char *filename, + cbuf *cb) +{ + int retval = -1; + int fd = 0; + int err = 0; + char line[512]; + int bytes; + struct stat st; + + if (stat(filename, &st) != 0){ + clicon_err(OE_UNIX, errno, "stat"); + return -1; + } + if ((fd = open(filename, O_RDONLY)) == -1) { + clicon_err(OE_UNIX, errno, "open(%s) for read", filename); + return -1; + } + while((bytes = read(fd, line, sizeof(line))) > 0) + if (cbuf_append_buf(cb, line, bytes) < 0){ + clicon_err(OE_UNIX, errno, "cbuf_append_buf(%s)", filename); + err = errno; + goto error; + } + retval = 0; + error: + close(fd); + if (retval < 0) + errno = err; + return retval; +} diff --git a/lib/src/clixon_netconf_lib.c b/lib/src/clixon_netconf_lib.c index 369e56b9..5fa4b94f 100644 --- a/lib/src/clixon_netconf_lib.c +++ b/lib/src/clixon_netconf_lib.c @@ -1815,6 +1815,11 @@ netconf_capabilites(clicon_handle h, cprintf(cb, ""); /* RFC5277 Notification Capability */ cprintf(cb, "%s", NETCONF_NOTIFICATION_CAPABILITY); + /* RFC6022 YANG Module for NETCONF Monitoring + * This seems non-standard but necessary for most existing boxes and software + */ + if (clicon_option_bool(h, "CLICON_NETCONF_MONITORING")) + cprintf(cb, "%s", NETCONF_MONITORING_NAMESPACE); /* It is somewhat arbitrary why some features/capabilities are hardocded and why some are not * rfc 6241 Sec 8.4 confirmed-commit capabilities */ diff --git a/test/test_netconf_monitoring.sh b/test/test_netconf_monitoring.sh index 297f92ae..e3ffb7bc 100755 --- a/test/test_netconf_monitoring.sh +++ b/test/test_netconf_monitoring.sh @@ -54,7 +54,7 @@ new "wait backend" wait_backend new "Retrieving all state via operation" -expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "urn:ietf:params:netconf:base:1.0urn:ietf:params:netconf:base:1.1.*.*" "" +expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "urn:ietf:params:netconf:base:1.0urn:ietf:params:netconf:base:1.1.*urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring.*.*" # 4.1. Retrieving Schema List via Operation new "Retrieving Schema List via Operation" @@ -63,30 +63,29 @@ expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" " # 4.2. Retrieving Schema Instances # From 2b. bar, version 2008-06-1 in YANG format, via get-schema new "Retrieving clixon-example schema instance using id, version, format" -expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "clixon-example2022-01-01yang" "module clixon-example {yang-version 1.1;namespace urn:example:clixon;prefix ex;revision 2022-01-01;}" +expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "clixon-example2022-01-01yang" "module clixon-example{" new "Retrieving clixon-example schema instance using id, version only" -expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "clixon-example2022-01-01" "module clixon-example {yang-version 1.1;namespace urn:example:clixon;prefix ex;revision 2022-01-01;}" +expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "clixon-example2022-01-01" "module clixon-example{" new "Retrieving clixon-example schema instance using id only" -expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "clixon-example" "module clixon-example {yang-version 1.1;namespace urn:example:clixon;prefix ex;revision 2022-01-01;}" +expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "clixon-example" "module clixon-example{" new "Retrieving ietf-inet-types schema" -expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "ietf-inet-types" "module ietf-inet-types {namespace urn:ietf:params:xml:ns:yang:ietf- -inet-types;prefix inet" +expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "ietf-inet-types" "module ietf-inet-types {" # Negative tests new "get-schema: no id" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "applicationmissing-elementidentifiererrorMandatory variable of get-schema in module ietf-netconf-monitoring" new "get-schema: non-existing schema" -expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "not-found" "protocolinvalid-valueerrorNo such schema" +expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "not-found" "protocolinvalid-valueerrorNo schema matching: not-found" new "get-schema: non-existing format" -expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "clixon-example2022-01-01xsd" "protocolinvalid-valueerrorFormat not supported" +expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "clixon-example2022-01-01xsd" "protocolinvalid-valueerrorFormat not supported: xsd" new "get-schema: non-existing date" -expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "clixon-example2013-01-01yang" "protocolinvalid-valueerrorNo such schema" +expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "clixon-example2013-01-01yang" "protocolinvalid-valueerrorNo schema matching: clixon-example@2013-01-01" if [ $BE -ne 0 ]; then new "Kill backend" diff --git a/test/test_netconf_monitoring_multiple.sh b/test/test_netconf_monitoring_multiple.sh index 79c7c7a2..01b00764 100755 --- a/test/test_netconf_monitoring_multiple.sh +++ b/test/test_netconf_monitoring_multiple.sh @@ -87,10 +87,10 @@ new "get-schema: multiple schemas, fail" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "clixon-example" "applicationoperation-faileddata-not-uniqueerror" new "get-schema: multiple schemas 2000-01-01" -expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "clixon-example2000-01-01" "module clixon-example {yang-version 1.1;namespace urn:example:clixon;prefix ex;revision 2000-01-01;}" +expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "clixon-example2000-01-01" "module clixon-example{" new "get-schema: multiple schemas 2022-01-01" -expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "clixon-example2022-01-01" "module clixon-example {yang-version 1.1;namespace urn:example:clixon;prefix ex;revision 2022-01-01;}" +expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "clixon-example2022-01-01" "module clixon-example{" if [ $BE -ne 0 ]; then new "Kill backend" diff --git a/test/test_netconf_ssh_callhome.sh b/test/test_netconf_ssh_callhome.sh index e25f87f4..050fbcee 100755 --- a/test/test_netconf_ssh_callhome.sh +++ b/test/test_netconf_ssh_callhome.sh @@ -144,7 +144,7 @@ EOF new "Start Listener client" echo "ssh -s -F $sshcfg -v -i $key -o ProxyUseFdpass=yes -o ProxyCommand=\"clixon_netconf_ssh_callhome_client -a 127.0.0.1\" . netconf" #-F $sshcfg -expectpart "$(ssh -s -F $sshcfg -v -i $key -o ProxyUseFdpass=yes -o ProxyCommand="${clixon_netconf_ssh_callhome_client} -a 127.0.0.1" . netconf < $rpccmd)" 0 "urn:ietf:params:netconf:base:1.1urn:ietf:params:netconf:base:1.0urn:ietf:params:netconf:capability:yang-library:1.0?revision=2019-01-04&module-set-id=42urn:ietf:params:netconf:capability:candidate:1.0urn:ietf:params:netconf:capability:validate:1.1urn:ietf:params:netconf:capability:xpath:1.0urn:ietf:params:netconf:capability:with-defaults:1.0?basic-mode=explicit&also-supported=report-all,trim,report-all-taggedurn:ietf:params:netconf:capability:notification:1.02" "" +expectpart "$(ssh -s -F $sshcfg -v -i $key -o ProxyUseFdpass=yes -o ProxyCommand="${clixon_netconf_ssh_callhome_client} -a 127.0.0.1" . netconf < $rpccmd)" 0 "urn:ietf:params:netconf:base:1.1.*2" "" # Wait wait