From c81776c8e9b6d183c46f8a91c7e666467d935b1a Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Tue, 14 Nov 2023 20:17:24 +0100 Subject: [PATCH] mgmtd: validate candidate yang tree before creating a config diff The candidate yang tree should be validated before `nb_config_diff` is called. `nb_config_diff` ignores all prohibited operations and can provide an empty change list because of this. For example, if a user deletes a mandatory node from the candidate datastore and tries to make a commit, they'll receive the "No changes found to be committed!" error, because such a change is ignored by `nb_config_diff`. Instead, mgmtd should tell the user that their candidate datastore is not valid and can't be commited. Signed-off-by: Igor Ryzhov --- mgmtd/mgmt_txn.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/mgmtd/mgmt_txn.c b/mgmtd/mgmt_txn.c index 53457e8969d5..c2dca2aea18d 100644 --- a/mgmtd/mgmt_txn.c +++ b/mgmtd/mgmt_txn.c @@ -1034,6 +1034,23 @@ static int mgmt_txn_prepare_config(struct mgmt_txn_ctx *txn) goto mgmt_txn_prepare_config_done; } + /* + * Validate YANG contents of the source DS and get the diff + * between source and destination DS contents. + */ + char err_buf[BUFSIZ] = { 0 }; + + ret = nb_candidate_validate_yang(nb_config, true, err_buf, + sizeof(err_buf) - 1); + if (ret != NB_OK) { + if (strncmp(err_buf, " ", strlen(err_buf)) == 0) + strlcpy(err_buf, "Validation failed", sizeof(err_buf)); + (void)mgmt_txn_send_commit_cfg_reply(txn, MGMTD_INVALID_PARAM, + err_buf); + ret = -1; + goto mgmt_txn_prepare_config_done; + } + nb_config_diff(mgmt_ds_get_nb_config(txn->commit_cfg_req->req.commit_cfg .dst_ds_ctx), nb_config, &changes); @@ -1056,29 +1073,13 @@ static int mgmt_txn_prepare_config(struct mgmt_txn_ctx *txn) gettimeofday(&txn->commit_cfg_req->req.commit_cfg.cmt_stats ->validate_start, NULL); - /* - * Validate YANG contents of the source DS and get the diff - * between source and destination DS contents. - */ - char err_buf[1024] = { 0 }; - nb_ctx.client = NB_CLIENT_MGMTD_SERVER; - nb_ctx.user = (void *)txn; - - ret = nb_candidate_validate_yang(nb_config, true, err_buf, - sizeof(err_buf) - 1); - if (ret != NB_OK) { - if (strncmp(err_buf, " ", strlen(err_buf)) == 0) - strlcpy(err_buf, "Validation failed", sizeof(err_buf)); - (void)mgmt_txn_send_commit_cfg_reply(txn, MGMTD_INVALID_PARAM, - err_buf); - ret = -1; - goto mgmt_txn_prepare_config_done; - } /* * Perform application level validations locally on the MGMTD * process by calling application specific validation routines * loaded onto MGMTD process using libraries. */ + nb_ctx.client = NB_CLIENT_MGMTD_SERVER; + nb_ctx.user = (void *)txn; ret = nb_candidate_validate_code(&nb_ctx, nb_config, &changes, err_buf, sizeof(err_buf) - 1); if (ret != NB_OK) {