Added error handling in yang_path_arg triggered by no filter in get paginated

Fixed cornercase of restconf error return when no body
Fixed cornercase when exactly / given as xpath
Better error message when YANG not found: added which YANG file imports it
This commit is contained in:
Olof hagsand 2021-11-09 20:02:40 +01:00
parent a4b4dc97ce
commit 2dcc14a0db
9 changed files with 39 additions and 14 deletions

View file

@ -467,7 +467,7 @@ get_list_pagination(clicon_handle h,
#endif
/* Check if list/leaf-list */
if (yang_path_arg(yspec, xpath, &ylist) < 0)
if (yang_path_arg(yspec, xpath?xpath:"/", &ylist) < 0)
goto done;
if (ylist == NULL){
if ((cbmsg = cbuf_new()) == NULL){

View file

@ -84,7 +84,7 @@ typedef struct {
*/
typedef struct {
uint32_t pd_offset; /* Start of pagination interval */
uint32_t pd_limit; /* Number of elemenents (limit) */
uint32_t pd_limit; /* Number of elements (limit) */
int pd_locked; /* Running datastore is locked by this caller */
cxobj *pd_xstate; /* Returned xml state tree */
} pagination_data_t;

View file

@ -286,7 +286,6 @@ transaction_log(clicon_handle h,
return 0;
}
/*! Get pagination data: offset parameter
*
* @param[in] pd Pagination userdata

View file

@ -487,7 +487,7 @@ http2_exec(restconf_conn *rc,
* (Successful) response to a CONNECT request (Section 4.3.6 of
* [RFC7231]).
*/
if (sd->sd_code != 204 && sd->sd_code > 199)
if (sd->sd_code != 204 && sd->sd_code > 199 && sd->sd_body_len)
if (restconf_reply_header(sd, "Content-Length", "%zu", sd->sd_body_len) < 0)
goto done;
if (sd->sd_code){

View file

@ -526,6 +526,10 @@ xpath_parse(const char *xpath,
clixon_xpath_yacc xpy = {0,};
cbuf *cb = NULL;
if (xpath == NULL){
clicon_err(OE_XML, EINVAL, "XPath is NULL");
goto done;
}
xpy.xpy_parse_string = xpath;
xpy.xpy_name = "xpath parser";
xpy.xpy_linenum = 1;

View file

@ -397,9 +397,15 @@ xp_yang_eval(xp_yang_ctx *xy,
}
}
if (xy0 == NULL && xy1 == NULL && xy2 == NULL){
if (xptree->xs_type == XP_ABSPATH){
if ((*xyr = xy_dup(xy)) == NULL)
goto done;
}
else {
clicon_err(OE_XML, EFAULT, "Internal error: no result produced");
goto done;
}
}
if (xy2){
*xyr = xy2;
xy2 = NULL;
@ -460,6 +466,10 @@ yang_path_arg(yang_stmt *ys,
xp_yang_ctx *xyr = NULL;
xp_yang_ctx *xy = NULL;
if (path_arg == NULL){
clicon_err(OE_XML, EINVAL, "path-arg is NULL");
goto done;
}
if (xpath_parse(path_arg, &xptree) < 0)
goto done;
if ((xy = xy_dup(NULL)) == NULL)

View file

@ -1035,6 +1035,7 @@ yang_parse_filename(const char *filename,
* @param[in] module Module name
* @param[in] revision Revision (or NULL)
* @param[in] yspec Yang statement
* @param[in] origname Name of yang module triggering this parsing, for logging
* @retval 0 OK
* @retval -1 Error
*
@ -1044,7 +1045,8 @@ static yang_stmt *
yang_parse_module(clicon_handle h,
const char *module,
const char *revision,
yang_stmt *yspec)
yang_stmt *yspec,
char *origname)
{
cbuf *fbuf = NULL;
char *filename;
@ -1053,20 +1055,27 @@ yang_parse_module(clicon_handle h,
yang_stmt *yrev; /* yang revision */
uint32_t revf = 0; /* revision in filename */
uint32_t revm = 0; /* revision in parsed new module (should be same as revf) */
cbuf *cb = NULL;
if ((fbuf = cbuf_new()) == NULL){
clicon_err(OE_YANG, errno, "cbuf_new");
clicon_err(OE_UNIX, errno, "cbuf_new");
goto done;
}
/* Match a yang file with or without revision in yang-dir list */
if ((nr = yang_parse_find_match(h, module, revision, &revf, fbuf)) < 0)
goto done;
if (nr == 0){
if ((cb = cbuf_new()) == NULL){
clicon_err(OE_UNIX, errno, "cbuf_new");
goto done;
}
cprintf(cb, "%s", module);
if (revision)
clicon_err(OE_YANG, ENOENT, "No yang files found matching \"%s@%s\" in the list of CLICON_YANG_DIRs",
module, revision);
cprintf(cb, "@%s", revision);
if (origname)
clicon_err(OE_YANG, ENOENT, "No yang files found matching \"%s\" in the list of CLICON_YANG_DIRs when loading %s.yang", cbuf_get(cb), origname);
else
clicon_err(OE_YANG, ENOENT, "No yang files found matching \"%s\" in the list of CLICON_YANG_DIRs", module);
clicon_err(OE_YANG, ENOENT, "No yang files found matching \"%s\" in the list of CLICON_YANG_DIRs", cbuf_get(cb));
goto done;
}
filename = cbuf_get(fbuf);
@ -1099,6 +1108,8 @@ yang_parse_module(clicon_handle h,
goto done;
}
done:
if (cb)
cbuf_free(cb);
if (fbuf)
cbuf_free(fbuf);
return ymod; /* top-level (sub)module */
@ -1149,7 +1160,7 @@ yang_parse_recurse(clicon_handle h,
keyw==Y_IMPORT?Y_MODULE:Y_SUBMODULE,
submodule) == NULL){
/* recursive call */
if ((subymod = yang_parse_module(h, submodule, subrevision, ysp)) == NULL)
if ((subymod = yang_parse_module(h, submodule, subrevision, ysp, yang_argument_get(ymod))) == NULL)
goto done;
/* Sanity check: if submodule, its belongs-to statement shall point to the module */
if (keyw == Y_INCLUDE){
@ -1581,7 +1592,7 @@ yang_spec_parse_module(clicon_handle h,
if (yang_find_module_by_name_revision(yspec, name, revision) != NULL)
goto ok;
/* Find a yang module and parse it and all its submodules */
if (yang_parse_module(h, name, revision, yspec) == NULL)
if (yang_parse_module(h, name, revision, yspec, NULL) == NULL)
goto done;
if (yang_parse_post(h, yspec, modmin) < 0)
goto done;

View file

@ -46,3 +46,4 @@ NADMIN=$(cat <<EOF
EOF
)
DEFAULTNACM='<nacm xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-acm"><enable-nacm>true</enable-nacm><read-default>permit</read-default><write-default>deny</write-default><exec-default>permit</exec-default><enable-external-groups>true</enable-external-groups></nacm>'

View file

@ -315,7 +315,7 @@ new "netconf commit"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><commit/></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
new "netconf get config"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get-config><source><running/></source></get-config></rpc>]]>]]>" "<rpc-reply $DEFAULTNS><data>$XML</data></rpc-reply>]]>]]>"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get-config><source><running/></source><filter type='subtree'><interfaces xmlns=\"urn:ietf:params:xml:ns:yang:ietf-interfaces\"/></filter></get-config></rpc>]]>]]>" "<rpc-reply $DEFAULTNS><data>$XML</data></rpc-reply>]]>]]>"
JSON='{"ietf-interfaces:interfaces":{"example-augment:ports":[{"id":22,"str":"foo"},{"id":44,"str":"bar"}]}}'