From ee8a8e96d74cb669a3a1b727555cb3d550d01bcd Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Thu, 15 Feb 2018 08:18:06 +0100 Subject: [PATCH 01/87] server CHANGE libyang log API changed --- server/log.c | 4 +- server/log.h | 2 +- server/op_copyconfig.c | 6 +-- server/op_editconfig.c | 7 ++-- server/op_generic.c | 12 +++--- server/op_get_config.c | 2 +- server/op_kill.c | 2 +- server/op_notifications.c | 4 +- server/op_un_lock.c | 14 +++---- server/op_validate.c | 5 ++- server/operations.c | 64 ++++++++++++++--------------- server/tests/test_edit_get_config.c | 4 +- 12 files changed, 64 insertions(+), 62 deletions(-) diff --git a/server/log.c b/server/log.c index 679a35896..42d1a7b51 100644 --- a/server/log.c +++ b/server/log.c @@ -236,7 +236,7 @@ np2log_printf(NC_VERB_LEVEL level, const char *format, ...) } const char * -np2log_lasterr(void) +np2log_lasterr(struct ly_ctx *ctx) { struct np2err *e; @@ -246,7 +246,7 @@ np2log_lasterr(void) } if (e->source == ERRS_LIBYANG) { - return ly_errmsg(); + return ly_errmsg(ctx); } else { return e->msg; } diff --git a/server/log.h b/server/log.h index 9a4c0c538..e125e2a02 100644 --- a/server/log.h +++ b/server/log.h @@ -70,6 +70,6 @@ void np2log_clb_sr(sr_log_level_t level, const char *msg); /** * @brief Get last error message (covers libyang, libnetconf2, sysrepo and netopeer2 in the current thread) */ -const char *np2log_lasterr(void); +const char *np2log_lasterr(struct ly_ctx *ctx); #endif /* NP2SRV_LOG_H_ */ diff --git a/server/op_copyconfig.c b/server/op_copyconfig.c index 678a725df..302eb4d41 100644 --- a/server/op_copyconfig.c +++ b/server/op_copyconfig.c @@ -108,7 +108,7 @@ op_copyconfig(struct lyd_node *rpc, struct nc_session *ncs) EINT; ly_set_free(nodeset); e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); ereply = nc_server_reply_err(e); goto finish; } @@ -116,7 +116,7 @@ op_copyconfig(struct lyd_node *rpc, struct nc_session *ncs) if (ly_errno != LY_SUCCESS) { ly_set_free(nodeset); e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); ereply = nc_server_reply_err(e); goto finish; } else { @@ -217,7 +217,7 @@ op_copyconfig(struct lyd_node *rpc, struct nc_session *ncs) default: ERR("%s: Invalid node to process", __func__); e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); ereply = nc_server_reply_err(e); goto finish; } diff --git a/server/op_editconfig.c b/server/op_editconfig.c index 313bb54a2..fc0e292bc 100644 --- a/server/op_editconfig.c +++ b/server/op_editconfig.c @@ -273,6 +273,7 @@ op_editconfig(struct lyd_node *rpc, struct nc_session *ncs) nodeset = lyd_find_path(rpc, "/ietf-netconf:edit-config/config"); if (nodeset->number) { any = (struct lyd_node_anydata *)nodeset->set.d[0]; + ly_errno = LY_SUCCESS; switch (any->value_type) { case LYD_ANYDATA_CONSTSTRING: case LYD_ANYDATA_STRING: @@ -293,8 +294,8 @@ op_editconfig(struct lyd_node *rpc, struct nc_session *ncs) break; } ly_set_free(nodeset); - if (ly_errno) { - ereply = nc_server_reply_err(nc_err_libyang()); + if (ly_errno != LY_SUCCESS) { + ereply = nc_server_reply_err(nc_err_libyang(np2srv.ly_ctx)); goto cleanup; } else if (!config) { /* nothing to do */ @@ -651,7 +652,7 @@ op_editconfig(struct lyd_node *rpc, struct nc_session *ncs) internalerror: e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (ereply) { nc_server_reply_add_err(ereply, e); } else { diff --git a/server/op_generic.c b/server/op_generic.c index 18009adc2..01dc8dc26 100644 --- a/server/op_generic.c +++ b/server/op_generic.c @@ -40,7 +40,7 @@ build_rpc_act_from_output(struct lyd_node *rpc_act, sr_val_t *output, size_t out node = lyd_new_path(rpc_act, np2srv.ly_ctx, output[i].xpath, op_get_srval(np2srv.ly_ctx, &output[i], buf), (output->type == SR_ANYXML_T || output->type == SR_ANYDATA_T) ? LYD_ANYDATA_SXML : 0, LYD_PATH_OPT_UPDATE | LYD_PATH_OPT_OUTPUT); - if (ly_errno) { + if (ly_errno != LY_SUCCESS) { return -1; } @@ -100,7 +100,7 @@ op_generic(struct lyd_node *rpc, struct nc_session *ncs) act = lyd_dup(rpc, 1); if (!act) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); ereply = nc_server_reply_err(e); goto finish; } @@ -114,7 +114,7 @@ op_generic(struct lyd_node *rpc, struct nc_session *ncs) if (!rpc) { EINT; e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); ereply = nc_server_reply_err(e); goto finish; } @@ -145,7 +145,7 @@ op_generic(struct lyd_node *rpc, struct nc_session *ncs) if (!input || !strs) { EMEM; e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); ereply = nc_server_reply_err(e); goto finish; } @@ -156,7 +156,7 @@ op_generic(struct lyd_node *rpc, struct nc_session *ncs) if (op_set_srval(set->set.d[i], lyd_path(set->set.d[i]), 0, &input[in_idx], &str)) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); ereply = nc_server_reply_err(e); goto finish; } @@ -190,7 +190,7 @@ op_generic(struct lyd_node *rpc, struct nc_session *ncs) if (rc) { lyd_free(reply_data); - e = nc_err_libyang(); + e = nc_err_libyang(np2srv.ly_ctx); ereply = nc_server_reply_err(e); goto finish; } diff --git a/server/op_get_config.c b/server/op_get_config.c index f735c0aae..17ea49f83 100644 --- a/server/op_get_config.c +++ b/server/op_get_config.c @@ -302,7 +302,7 @@ op_get(struct lyd_node *rpc, struct nc_session *ncs) error: if (!ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); ereply = nc_server_reply_err(e); } diff --git a/server/op_kill.c b/server/op_kill.c index 6852b8e5a..7808675d3 100644 --- a/server/op_kill.c +++ b/server/op_kill.c @@ -43,7 +43,7 @@ op_kill(struct lyd_node *rpc, struct nc_session *ncs) if (!set || (set->number != 1) || (set->set.d[0]->schema->nodetype != LYS_LEAF)) { EINT; e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); ereply = nc_server_reply_err(e); goto finish; } diff --git a/server/op_notifications.c b/server/op_notifications.c index 3b33f318b..89f6db60a 100644 --- a/server/op_notifications.c +++ b/server/op_notifications.c @@ -408,7 +408,7 @@ op_ntf_subscribe(struct lyd_node *rpc, struct nc_session *ncs) ret = ntf_module_sr_subscribe(mod, new); if (ret == -1) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); ereply = nc_server_reply_err(e); goto unlock_error; } @@ -446,7 +446,7 @@ op_ntf_subscribe(struct lyd_node *rpc, struct nc_session *ncs) goto unlock_error; } else if (ret == -1) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); ereply = nc_server_reply_err(e); goto unlock_error; } diff --git a/server/op_un_lock.c b/server/op_un_lock.c index 7431e5479..fe0209cb0 100644 --- a/server/op_un_lock.c +++ b/server/op_un_lock.c @@ -68,7 +68,7 @@ op_lock(struct lyd_node *rpc, struct nc_session *ncs) } else { EINT; e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_PROT); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); ereply = nc_server_reply_err(e); goto finish; } @@ -88,7 +88,7 @@ op_lock(struct lyd_node *rpc, struct nc_session *ncs) ERR("Locking datastore %s by session %d failed (datastore is already locked by session %d).", dsname, nc_session_get_id(ncs), nc_session_get_id(*dsl)); e = nc_err(NC_ERR_LOCK_DENIED, nc_session_get_id(*dsl)); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); ereply = nc_server_reply_err(e); goto finish; } @@ -106,7 +106,7 @@ op_lock(struct lyd_node *rpc, struct nc_session *ncs) /* add lock denied error */ ERR("Locking datastore %s by session %d failed.", dsname, nc_session_get_id(ncs)); e = nc_err(NC_ERR_LOCK_DENIED, 0); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); nc_server_reply_add_err(ereply, e); goto finish; } @@ -162,7 +162,7 @@ op_unlock(struct lyd_node *rpc, struct nc_session *ncs) } else { EINT; e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_PROT); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); ereply = nc_server_reply_err(e); goto finish; } @@ -181,7 +181,7 @@ op_unlock(struct lyd_node *rpc, struct nc_session *ncs) ERR("Unlocking datastore %s by session %d failed (lock is not active).", dsname, nc_session_get_id(ncs)); e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_PROT); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); ereply = nc_server_reply_err(e); goto finish; } else { @@ -192,7 +192,7 @@ op_unlock(struct lyd_node *rpc, struct nc_session *ncs) ERR("Unlocking datastore %s by session %d failed (lock is held by session %d).", dsname, nc_session_get_id(ncs), nc_session_get_id(*dsl)); e = nc_err(NC_ERR_LOCK_DENIED, nc_session_get_id(*dsl)); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); ereply = nc_server_reply_err(e); goto finish; } @@ -206,7 +206,7 @@ op_unlock(struct lyd_node *rpc, struct nc_session *ncs) /* add lock denied error */ ERR("Unlocking datastore %s by session %d failed.", dsname, nc_session_get_id(ncs)); e = nc_err(NC_ERR_LOCK_DENIED, 0); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); nc_server_reply_add_err(ereply, e); goto finish; } diff --git a/server/op_validate.c b/server/op_validate.c index 5b4c2e0b6..4dc1ddf6e 100644 --- a/server/op_validate.c +++ b/server/op_validate.c @@ -51,6 +51,7 @@ op_validate(struct lyd_node *rpc, struct nc_session *ncs) } else if (!strcmp(dsname, "config")) { /* get data tree to validate */ any = (struct lyd_node_anydata *)nodeset->set.d[0]; + ly_errno = LY_SUCCESS; switch (any->value_type) { case LYD_ANYDATA_CONSTSTRING: case LYD_ANYDATA_STRING: @@ -70,7 +71,7 @@ op_validate(struct lyd_node *rpc, struct nc_session *ncs) case LYD_ANYDATA_SXMLD: EINT; e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); ereply = nc_server_reply_err(e); goto finish; } @@ -79,7 +80,7 @@ op_validate(struct lyd_node *rpc, struct nc_session *ncs) lyd_free_withsiblings(config); if (ly_errno != LY_SUCCESS) { - e = nc_err_libyang(); + e = nc_err_libyang(np2srv.ly_ctx); ereply = nc_server_reply_err(e); goto finish; } diff --git a/server/operations.c b/server/operations.c index 0a1f3801c..fd410d3d6 100644 --- a/server/operations.c +++ b/server/operations.c @@ -78,7 +78,7 @@ np2srv_sr_session_switch_ds(sr_session_ctx_t *srs, sr_datastore_t ds, struct nc_ if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -129,7 +129,7 @@ np2srv_sr_set_item(sr_session_ctx_t *srs, const char *xpath, const sr_val_t *val if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -210,7 +210,7 @@ np2srv_sr_delete_item(sr_session_ctx_t *srs, const char *xpath, const sr_edit_op if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -291,7 +291,7 @@ np2srv_sr_get_item(sr_session_ctx_t *srs, const char *xpath, sr_val_t **value, s if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -341,7 +341,7 @@ np2srv_sr_get_items(sr_session_ctx_t *srs, const char *xpath, sr_val_t **values, if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -391,7 +391,7 @@ np2srv_sr_get_changes_iter(sr_session_ctx_t *srs, const char *xpath, sr_change_i if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -447,7 +447,7 @@ np2srv_sr_get_change_next(sr_session_ctx_t *srs, sr_change_iter_t *iter, sr_chan if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -502,7 +502,7 @@ np2srv_sr_get_items_iter(sr_session_ctx_t *srs, const char *xpath, sr_val_iter_t if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -558,7 +558,7 @@ np2srv_sr_get_item_next(sr_session_ctx_t *srs, sr_val_iter_t *iter, sr_val_t **v if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -609,7 +609,7 @@ np2srv_sr_move_item(sr_session_ctx_t *srs, const char *xpath, const sr_move_posi if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -660,7 +660,7 @@ np2srv_sr_rpc_send(sr_session_ctx_t *srs, const char *xpath, const sr_val_t *inp if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -725,7 +725,7 @@ np2srv_sr_action_send(sr_session_ctx_t *srs, const char *xpath, const sr_val_t * if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -790,7 +790,7 @@ np2srv_sr_check_exec_permission(sr_session_ctx_t *srs, const char *xpath, struct if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -852,7 +852,7 @@ np2srv_sr_module_change_subscribe(sr_session_ctx_t *srs, const char *module_name if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -903,7 +903,7 @@ np2srv_sr_subtree_change_subscribe(sr_session_ctx_t *srs, const char *xpath, sr_ if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -954,7 +954,7 @@ np2srv_sr_event_notif_subscribe(sr_session_ctx_t *srs, const char *xpath, sr_eve if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -1005,7 +1005,7 @@ np2srv_sr_event_notif_replay(sr_session_ctx_t *srs, sr_subscription_ctx_t *subsc if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -1056,7 +1056,7 @@ np2srv_sr_event_notif_send(sr_session_ctx_t *srs, const char *xpath, const sr_va if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -1108,7 +1108,7 @@ np2srv_sr_session_start_user(const char *user_name, const sr_datastore_t datasto if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -1167,7 +1167,7 @@ np2srv_sr_session_stop(sr_session_ctx_t *srs, struct nc_server_reply **ereply) if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -1217,7 +1217,7 @@ np2srv_sr_session_set_options(sr_session_ctx_t *srs, const sr_sess_options_t opt if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -1267,7 +1267,7 @@ np2srv_sr_session_refresh(sr_session_ctx_t *srs, struct nc_server_reply **ereply if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -1317,7 +1317,7 @@ np2srv_sr_discard_changes(sr_session_ctx_t *srs, struct nc_server_reply **ereply if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -1367,7 +1367,7 @@ np2srv_sr_commit(sr_session_ctx_t *srs, struct nc_server_reply **ereply) if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -1417,7 +1417,7 @@ np2srv_sr_validate(sr_session_ctx_t *srs, struct nc_server_reply **ereply) if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -1468,7 +1468,7 @@ np2srv_sr_copy_config(sr_session_ctx_t *srs, const char *module_name, sr_datasto if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -1518,7 +1518,7 @@ np2srv_sr_lock_datastore(sr_session_ctx_t *srs, struct nc_server_reply **ereply) if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -1568,7 +1568,7 @@ np2srv_sr_unlock_datastore(sr_session_ctx_t *srs, struct nc_server_reply **erepl if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -1618,7 +1618,7 @@ np2srv_sr_unsubscribe(sr_session_ctx_t *srs, sr_subscription_ctx_t *subscription if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -1668,7 +1668,7 @@ np2srv_sr_list_schemas(sr_session_ctx_t *srs, sr_schema_t **schemas, size_t *sch if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -1719,7 +1719,7 @@ np2srv_sr_get_submodule_schema(sr_session_ctx_t *srs, const char *submodule_name if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { @@ -1770,7 +1770,7 @@ np2srv_sr_get_schema(sr_session_ctx_t *srs, const char *module_name, const char if (ereply) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - nc_err_set_msg(e, np2log_lasterr(), "en"); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); if (*ereply) { nc_server_reply_add_err(*ereply, e); } else { diff --git a/server/tests/test_edit_get_config.c b/server/tests/test_edit_get_config.c index 7725b71d0..1c98d5527 100644 --- a/server/tests/test_edit_get_config.c +++ b/server/tests/test_edit_get_config.c @@ -266,7 +266,7 @@ __wrap_sr_set_item(sr_session_ctx_t *session, const char *xpath, const sr_val_t case SR_LEAF_EMPTY_T: ly_errno = LY_SUCCESS; lyd_new_path(data, np2srv.ly_ctx, xpath, NULL, 0, opt); - if ((ly_errno == LY_EVALID) && (ly_vecode == LYVE_PATH_EXISTS)) { + if ((ly_errno == LY_EVALID) && (ly_vecode(np2srv.ly_ctx) == LYVE_PATH_EXISTS)) { return SR_ERR_DATA_EXISTS; } assert_int_equal(ly_errno, LY_SUCCESS); @@ -274,7 +274,7 @@ __wrap_sr_set_item(sr_session_ctx_t *session, const char *xpath, const sr_val_t default: ly_errno = LY_SUCCESS; lyd_new_path(data, np2srv.ly_ctx, xpath, op_get_srval(np2srv.ly_ctx, (sr_val_t *)value, buf), 0, opt); - if ((ly_errno == LY_EVALID) && (ly_vecode == LYVE_PATH_EXISTS)) { + if ((ly_errno == LY_EVALID) && (ly_vecode(np2srv.ly_ctx) == LYVE_PATH_EXISTS)) { return SR_ERR_DATA_EXISTS; } assert_int_equal(ly_errno, LY_SUCCESS); From e127328c3ef3a4373fe7bea2056b507beaaad50a Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Thu, 15 Feb 2018 08:18:38 +0100 Subject: [PATCH 02/87] server VERSION bump to version 0.5.0 --- server/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index d8d3348f1..d513fbc1b 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -13,7 +13,7 @@ if(NOT UNIX) endif() # set version -set(NP2SRV_VERSION 0.4.19) +set(NP2SRV_VERSION 0.5.0) # set default build type if not specified by user if(NOT CMAKE_BUILD_TYPE) From 71989793454124e61de963de33249f9590809683 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Thu, 22 Feb 2018 09:49:54 +0100 Subject: [PATCH 03/87] server BUGFIX always work with main modules Fixes #223 --- server/op_copyconfig.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/op_copyconfig.c b/server/op_copyconfig.c index 302eb4d41..ce224e47c 100644 --- a/server/op_copyconfig.c +++ b/server/op_copyconfig.c @@ -135,7 +135,7 @@ op_copyconfig(struct lyd_node *rpc, struct nc_session *ncs) if (iter->dflt) { continue; } - ly_set_add(nodeset, iter->schema->module, 0); + ly_set_add(nodeset, lyd_node_module(iter), 0); } for (i = 0; i < nodeset->number; i++) { snprintf(path, 1024, "/%s:*", ((struct lys_module *)nodeset->set.g[i])->name); From d4eba8583b80924eef4ad5270d8a80d532e8fdcb Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Thu, 22 Feb 2018 09:51:08 +0100 Subject: [PATCH 04/87] server VERSION bump to version 0.5.1 --- server/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index d513fbc1b..b5fe0ee0c 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -13,7 +13,7 @@ if(NOT UNIX) endif() # set version -set(NP2SRV_VERSION 0.5.0) +set(NP2SRV_VERSION 0.5.1) # set default build type if not specified by user if(NOT CMAKE_BUILD_TYPE) From bd17b66f12272a833f45ec97f583ddf14f1915cb Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Thu, 22 Feb 2018 10:14:55 +0100 Subject: [PATCH 05/87] travis BUGFIX use proper dependency branches --- .travis-install-libs.sh | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.travis-install-libs.sh b/.travis-install-libs.sh index fa1b8349f..2b5c9bf9e 100644 --- a/.travis-install-libs.sh +++ b/.travis-install-libs.sh @@ -1,5 +1,11 @@ #!/bin/sh +if [[ (( "$TRAVIS_BRANCH" == *"master"* )) || (( "$TRAVIS_TAG" =~ "v"[0-9]+"."[0-9]+"."[0-9]+ )) ]]; then + BRANCH="master" +else + BRANCH="devel" +fi + sudo apt-get update -qq sudo apt-get install -y zlib1g-dev libssl-dev sudo apt-get install -y --force-yes libavl-dev libev-dev coreutils acl valgrind @@ -18,7 +24,7 @@ else cd ../.. fi -git clone -b devel https://github.com/CESNET/libyang.git +git clone -b $BRANCH https://github.com/CESNET/libyang.git cd libyang; mkdir build; cd build cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr -DCMAKE_BUILD_TYPE=Release .. make -j2 && sudo make install @@ -38,7 +44,7 @@ else cd ../.. fi -git clone -b devel https://github.com/CESNET/libnetconf2.git +git clone -b $BRANCH https://github.com/CESNET/libnetconf2.git cd libnetconf2; mkdir build; cd build cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr -DCMAKE_BUILD_TYPE=Release .. make -j2 && sudo make install @@ -72,7 +78,7 @@ else cd .. fi -git clone -b devel https://github.com/sysrepo/sysrepo.git +git clone -b $BRANCH https://github.com/sysrepo/sysrepo.git cd sysrepo; mkdir build; cd build cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -DBUILD_EXAMPLES=False -DENABLE_TESTS=False -DGEN_LANGUAGE_BINDINGS=0 -DREPOSITORY_LOC:PATH=/ets/sysrepo .. make -j2 && sudo make install From e91d32824bbe36349ff826c88f5e9485d4ab0f25 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Fri, 23 Feb 2018 12:40:22 +0100 Subject: [PATCH 06/87] server BUGFIX use array of pointers for subscribers Otherwise the subscriber pointers were moved on realloc which caused problems. Fixes #224 --- server/op_notifications.c | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/server/op_notifications.c b/server/op_notifications.c index 89f6db60a..288695bc4 100644 --- a/server/op_notifications.c +++ b/server/op_notifications.c @@ -45,7 +45,9 @@ struct np_subscriber { struct { uint16_t size; uint16_t num; - struct np_subscriber *list; + /* we use an array of pointers to the subscribers so that if we pass individual subscribers to np2srv_ntf_clb + * and then call realloc() on this array, the pointers will remain the same */ + struct np_subscriber **list; pthread_mutex_t lock; } subscribers = {0, 0, NULL, PTHREAD_MUTEX_INITIALIZER}; @@ -275,6 +277,7 @@ np2srv_subscriber_free(struct np_subscriber *subscriber) nc_server_notif_free(subscriber->replay_notifs[i]); } free(subscriber->replay_notifs); + free(subscriber); } struct nc_server_reply * @@ -286,6 +289,7 @@ op_ntf_subscribe(struct lyd_node *rpc, struct nc_session *ncs) time_t now = time(NULL), start = 0, stop = 0; const char *stream; char **filters; + void *mem; struct lyd_node *node; struct np_subscriber *new = NULL; struct nc_server_error *e = NULL; @@ -349,7 +353,7 @@ op_ntf_subscribe(struct lyd_node *rpc, struct nc_session *ncs) /* check that the session is not in the current subscribers list */ for (i = 0; i < subscribers.num; i++) { - if (subscribers.list[i].session == ncs) { + if (subscribers.list[i]->session == ncs) { /* already subscribed */ e = nc_err(NC_ERR_IN_USE, NC_ERR_TYPE_PROT); nc_err_set_msg(e, "Already subscribed.", "en"); @@ -358,21 +362,28 @@ op_ntf_subscribe(struct lyd_node *rpc, struct nc_session *ncs) } } - /* new subscriber, add it into the list */ + /* new subscriber, make place for the pointer */ if (subscribers.num == subscribers.size) { subscribers.size += 4; - new = realloc(subscribers.list, subscribers.size * sizeof *subscribers.list); - if (!new) { + mem = realloc(subscribers.list, subscribers.size * sizeof *subscribers.list); + if (!mem) { /* realloc failed */ + subscribers.size -= 4; EMEM; e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); - subscribers.size -= 4; ereply = nc_server_reply_err(e); goto unlock_error; } - subscribers.list = new; + subscribers.list = mem; + } + /* allocate place for the subscriber structure itself */ + new = subscribers.list[subscribers.num] = malloc(sizeof *new); + if (!new) { + EMEM; + e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); + ereply = nc_server_reply_err(e); + goto unlock_error; } - new = &subscribers.list[subscribers.num]; subscribers.num++; /* store information about the new subscriber */ @@ -485,18 +496,18 @@ op_ntf_unsubscribe(struct nc_session *session) pthread_mutex_lock(&subscribers.lock); for (i = 0; i < subscribers.num; i++) { - if (subscribers.list[i].session == session) { + if (subscribers.list[i]->session == session) { break; } } assert(i < subscribers.num); - np2srv_subscriber_free(&subscribers.list[i]); + np2srv_subscriber_free(subscribers.list[i]); subscribers.num--; if (i < subscribers.num) { - /* move here the subscriber from the end of the list */ - memcpy(&subscribers.list[i], &subscribers.list[subscribers.num], sizeof *subscribers.list); + /* move here the subscriber pointer from the end of the list */ + subscribers.list[i] = subscribers.list[subscribers.num]; } nc_session_set_notif_status(session, 0); @@ -535,8 +546,8 @@ op_ntf_yang_lib_change(const struct lyd_node *ylib_info) /* send notifications */ for (i = 0; i < subscribers.num; ++i) { - if (subscribers.list[i].subscr_ietf_yang_library) { - np2srv_ntf_send(&subscribers.list[i], ntf, time(NULL), SR_EV_NOTIF_T_REALTIME); + if (subscribers.list[i]->subscr_ietf_yang_library) { + np2srv_ntf_send(subscribers.list[i], ntf, time(NULL), SR_EV_NOTIF_T_REALTIME); } } lyd_free(ntf); From 7e5f4a0ac50d0f9aa4db73105108b60a22da476a Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Fri, 23 Feb 2018 12:41:11 +0100 Subject: [PATCH 07/87] server VERSION bump to version 0.5.2 --- server/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index b5fe0ee0c..8df2536c5 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -13,7 +13,7 @@ if(NOT UNIX) endif() # set version -set(NP2SRV_VERSION 0.5.1) +set(NP2SRV_VERSION 0.5.2) # set default build type if not specified by user if(NOT CMAKE_BUILD_TYPE) From adf943e0412d118ea1f8e5e03b700e281b942118 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Fri, 23 Feb 2018 13:57:08 +0100 Subject: [PATCH 08/87] cli CHANGE printing of searchpath --- cli/commands.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/cli/commands.c b/cli/commands.c index dc0449167..e78d96b99 100644 --- a/cli/commands.c +++ b/cli/commands.c @@ -596,7 +596,7 @@ trim_top_elem(char *data, const char *top_elem, const char *top_elem_ns) void cmd_searchpath_help(void) { - printf("searchpath \n"); + printf("searchpath []\n"); } void @@ -2317,18 +2317,20 @@ cmd_searchpath(const char *arg, char **UNUSED(tmp_config_file)) { const char *path; - if (strchr(arg, ' ') == NULL) { - fprintf(stderr, "Missing the search path.\n"); - return 1; + for (arg += 10; isspace(arg[0]); ++arg); + + if (!arg[0]) { + path = nc_client_get_schema_searchpath(); + fprintf(stdout, "%s\n", path[0] ? path : ""); + return 0; } - path = strchr(arg, ' ')+1; - if (!strcmp(path, "-h") || !strcmp(path, "--help")) { + if (!strcmp(arg, "-h") || !strcmp(arg, "--help")) { cmd_searchpath_help(); return 0; } - nc_client_set_schema_searchpath(path); + nc_client_set_schema_searchpath(arg); return 0; } From 946a2570fd7c494cc035cb259ce171dc596650cc Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Fri, 23 Feb 2018 13:57:45 +0100 Subject: [PATCH 09/87] cli VERSION bump to version 2.0.41 --- cli/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt index 3acaec373..bc723ad45 100644 --- a/cli/CMakeLists.txt +++ b/cli/CMakeLists.txt @@ -21,7 +21,7 @@ set(CMAKE_C_FLAGS_RELEASE "-O2") set(CMAKE_C_FLAGS_DEBUG "-g -O0") # set version -set(NP2CLI_VERSION 2.0.40) +set(NP2CLI_VERSION 2.0.41) configure_file("${PROJECT_SOURCE_DIR}/version.h.in" "${PROJECT_SOURCE_DIR}/version.h" ESCAPE_QUOTES @ONLY) # source files From c8e5c25860298339637d0239c3dc51f16798826f Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Thu, 8 Mar 2018 15:36:29 +0100 Subject: [PATCH 10/87] server BUGFIX transform content filter identities from xml to json Fixes cesnet/libyang#449 --- server/operations.c | 56 ++++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/server/operations.c b/server/operations.c index fd410d3d6..7f52b6d8d 100644 --- a/server/operations.c +++ b/server/operations.c @@ -2158,26 +2158,50 @@ filter_xpath_buf_add_attrs(struct ly_ctx *ctx, struct lyxml_attr *attr, char **b return size; } -/* top-level content node with optional namespace and attributes */ -static int -filter_xpath_buf_add_top_content(struct ly_ctx *ctx, struct lyxml_elem *elem, const char *elem_module_name, - char ***filters, int *filter_count) +static char * +filter_xpath_buf_get_content(struct ly_ctx *ctx, struct lyxml_elem *elem) { - int size, len; const char *start; - char *buf; + size_t len; + char *ret; /* skip leading and trailing whitespaces */ for (start = elem->content; isspace(*start); ++start); for (len = strlen(start); isspace(start[len - 1]); --len); - size = 1 + strlen(elem_module_name) + 1 + strlen(elem->name) + 9 + len + 3; + start = lydict_insert(ctx, start, len); + + ly_log_options(0); + ret = ly_path_xml2json(ctx, start, elem); + ly_log_options(LY_LOLOG | LY_LOSTORE_LAST); + + if (!ret) { + ret = strdup(start); + } + lydict_remove(ctx, start); + + return ret; +} + +/* top-level content node with optional namespace and attributes */ +static int +filter_xpath_buf_add_top_content(struct ly_ctx *ctx, struct lyxml_elem *elem, const char *elem_module_name, + char ***filters, int *filter_count) +{ + int size; + char *buf, *content; + + content = filter_xpath_buf_get_content(ctx, elem); + + size = 1 + strlen(elem_module_name) + 1 + strlen(elem->name) + 9 + strlen(content) + 3; buf = malloc(size * sizeof(char)); if (!buf) { EMEM; + free(content); return -1; } - sprintf(buf, "/%s:%s[text()='%.*s']", elem_module_name, elem->name, len, start); + sprintf(buf, "/%s:%s[text()='%s']", elem_module_name, elem->name, content); + free(content); size = filter_xpath_buf_add_attrs(ctx, elem->attr, &buf, size); if (!size) { @@ -2202,9 +2226,8 @@ filter_xpath_buf_add_content(struct ly_ctx *ctx, struct lyxml_elem *elem, const const char **last_ns, char **buf, int size) { const struct lys_module *module; - int new_size, len; - const char *start; - char *buf_new; + int new_size; + char *buf_new, *content; if (!elem_module_name && elem->ns && (elem->ns->value != *last_ns) && strcmp(elem->ns->value, "urn:ietf:params:xml:ns:netconf:base:1.0")) { @@ -2236,18 +2259,19 @@ filter_xpath_buf_add_content(struct ly_ctx *ctx, struct lyxml_elem *elem, const return -1; } - /* skip leading and trailing whitespaces */ - for (start = elem->content; isspace(*start); ++start); - for (len = strlen(start); isspace(start[len - 1]); --len); + content = filter_xpath_buf_get_content(ctx, elem); - new_size = size + 2 + len + 2; + new_size = size + 2 + strlen(content) + 2; buf_new = realloc(*buf, new_size * sizeof(char)); if (!buf_new) { EMEM; + free(content); return -1; } *buf = buf_new; - sprintf((*buf) + (size - 1), "='%.*s']", len, start); + sprintf((*buf) + (size - 1), "='%s']", content); + + free(content); return new_size; } From 881a2dfd7ff51a4c4d0920f2c20b3a33cf670cea Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Thu, 8 Mar 2018 15:38:44 +0100 Subject: [PATCH 11/87] server VERSION bump to version 0.5.3 --- server/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 8df2536c5..ec07462e2 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -13,7 +13,7 @@ if(NOT UNIX) endif() # set version -set(NP2SRV_VERSION 0.5.2) +set(NP2SRV_VERSION 0.5.3) # set default build type if not specified by user if(NOT CMAKE_BUILD_TYPE) From a17f2f3106560e58415e359a03fa716a663dac4b Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Thu, 8 Mar 2018 15:39:05 +0100 Subject: [PATCH 12/87] cli CHANGE create modules directory if it does not exist --- cli/configuration.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/cli/configuration.c b/cli/configuration.c index e2197618c..444836f74 100644 --- a/cli/configuration.c +++ b/cli/configuration.c @@ -309,7 +309,17 @@ load_config(void) config_editor = strdup(child->content); } else if (!strcmp(child->name, "searchpath")) { /* doc -> -> */ - nc_client_set_schema_searchpath(child->content); + errno = 0; + if (eaccess(child->content, R_OK | W_OK | X_OK) && (errno == ENOENT)) { + ERROR(__func__, "Search path \"%s\" does not exist, creating it.", child->content); + if (mkdir(child->content, 00700)) { + ERROR(__func__, "Search path \"%s\" cannot be created: %s", child->content, strerror(errno)); + } else { + nc_client_set_schema_searchpath(child->content); + } + } else { + nc_client_set_schema_searchpath(child->content); + } } else if (!strcmp(child->name, "output-format")) { /* doc -> -> */ if (!strcmp(child->content, "json")) { From f5ecd54e84406a855ba9b2c7f698004de492d37e Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Thu, 8 Mar 2018 15:39:41 +0100 Subject: [PATCH 13/87] cli VERSION bump to version 2.0.42 --- cli/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt index bc723ad45..cff9b7e86 100644 --- a/cli/CMakeLists.txt +++ b/cli/CMakeLists.txt @@ -21,7 +21,7 @@ set(CMAKE_C_FLAGS_RELEASE "-O2") set(CMAKE_C_FLAGS_DEBUG "-g -O0") # set version -set(NP2CLI_VERSION 2.0.41) +set(NP2CLI_VERSION 2.0.42) configure_file("${PROJECT_SOURCE_DIR}/version.h.in" "${PROJECT_SOURCE_DIR}/version.h" ESCAPE_QUOTES @ONLY) # source files From 91d833d5656f52084fb065e0ce027e632b1817ac Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Fri, 9 Mar 2018 15:40:48 +0100 Subject: [PATCH 14/87] cli CHANGE increase timeout for receiving reply So that we wait at least for the server timeout. --- cli/commands.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/commands.c b/cli/commands.c index e78d96b99..4122a027b 100644 --- a/cli/commands.c +++ b/cli/commands.c @@ -254,7 +254,7 @@ cli_send_recv(struct nc_rpc *rpc, FILE *output, NC_WD_MODE wd_mode) } recv_reply: - msgtype = nc_recv_reply(session, rpc, msgid, 10000, + msgtype = nc_recv_reply(session, rpc, msgid, 20000, LYD_OPT_DESTRUCT | LYD_OPT_NOSIBLINGS, &reply); if (msgtype == NC_MSG_ERROR) { ERROR(__func__, "Failed to receive a reply."); From 19f8347a902514a3d5154c76397b111652017cb5 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Fri, 9 Mar 2018 15:41:36 +0100 Subject: [PATCH 15/87] cli VERSION bump to version 2.0.43 --- cli/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt index cff9b7e86..9667655aa 100644 --- a/cli/CMakeLists.txt +++ b/cli/CMakeLists.txt @@ -21,7 +21,7 @@ set(CMAKE_C_FLAGS_RELEASE "-O2") set(CMAKE_C_FLAGS_DEBUG "-g -O0") # set version -set(NP2CLI_VERSION 2.0.42) +set(NP2CLI_VERSION 2.0.43) configure_file("${PROJECT_SOURCE_DIR}/version.h.in" "${PROJECT_SOURCE_DIR}/version.h" ESCAPE_QUOTES @ONLY) # source files From a7a3621af83b66499d79d9b61b7edf167d99094c Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Tue, 27 Mar 2018 14:50:24 +0200 Subject: [PATCH 16/87] server CHANGE libyang api changes --- server/operations.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/server/operations.c b/server/operations.c index 7f52b6d8d..421d81abb 100644 --- a/server/operations.c +++ b/server/operations.c @@ -1869,7 +1869,6 @@ op_set_srval(struct lyd_node *node, char *path, int dup, sr_val_t *val, char **v uint32_t i; struct lyd_node_leaf_list *leaf; const char *str; - LY_DATA_TYPE type; if (!dup) { assert(val_buf); @@ -1891,8 +1890,7 @@ op_set_srval(struct lyd_node *node, char *path, int dup, sr_val_t *val, char **v case LYS_LEAFLIST: leaf = (struct lyd_node_leaf_list *)node; settype: - type = leaf->value_type; - switch (type & LY_DATA_TYPE_MASK) { + switch (leaf->value_type) { case LY_TYPE_BINARY: val->type = SR_BINARY_T; str = leaf->value.binary; From 0e1985ea63ca2d896c552dd6c4c0cdd0e7d6bb39 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Tue, 27 Mar 2018 14:50:44 +0200 Subject: [PATCH 17/87] server VERSION bump to version 0.5.4 --- server/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index ec07462e2..9aeaa07c3 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -13,7 +13,7 @@ if(NOT UNIX) endif() # set version -set(NP2SRV_VERSION 0.5.3) +set(NP2SRV_VERSION 0.5.4) # set default build type if not specified by user if(NOT CMAKE_BUILD_TYPE) From e3ff0fa40f9bdab7943e3b065600538825c5923d Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Tue, 27 Mar 2018 15:26:33 +0200 Subject: [PATCH 18/87] travis CHANGE libyang requires newer gcc --- .travis.yml | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 416304ad5..85caa84a4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,23 @@ -os: linux -sudo: required -dist: trusty +language: c -language: - - c - -compiler: - - gcc - - clang +matrix: + include: + - os: linux + dist: trusty + sudo: required + compiler: clang + - os: linux + dist: trusty + sudo: required + compiler: gcc + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-7 + env: + - MATRIX_EVAL="CC=gcc-7 && CXX=g++-7" branches: only: @@ -22,6 +32,7 @@ cache: - cmocka-1.0.1 before_install: + - eval "${MATRIX_EVAL}" - if [ "$TRAVIS_OS_NAME" == "linux" ]; then bash .travis-install-libs.sh; fi - if [ "$TRAVIS_OS_NAME" = "linux" -a "$CC" = "gcc" ]; then pip install --user codecov; export CFLAGS="-coverage"; fi From 50c023b638a22166dcb0eaa824ceef51c18ceb83 Mon Sep 17 00:00:00 2001 From: Xiao Liang Date: Wed, 28 Mar 2018 23:42:54 +0800 Subject: [PATCH 19/87] cli BUGFIX segfault when get-schema returns empty data Some device returns empty data when schema is not found. Though the device implementation is not correct, segfault should not occur anyway. --- cli/commands.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/cli/commands.c b/cli/commands.c index 4122a027b..178d1040a 100644 --- a/cli/commands.c +++ b/cli/commands.c @@ -284,14 +284,16 @@ cli_send_recv(struct nc_rpc *rpc, FILE *output, NC_WD_MODE wd_mode) /* special case */ if (nc_rpc_get_type(rpc) == NC_RPC_GETSCHEMA) { - if (output == stdout) { - fprintf(output, "MODULE\n"); - } - if ((data_rpl->data->schema->nodetype != LYS_RPC) || (data_rpl->data->child->schema->nodetype != LYS_ANYXML)) { + if ((data_rpl->data->schema->nodetype != LYS_RPC) || + (data_rpl->data->child == NULL) || + (data_rpl->data->child->schema->nodetype != LYS_ANYXML)) { ERROR(__func__, "Unexpected data reply to RPC."); ret = -1; break; } + if (output == stdout) { + fprintf(output, "MODULE\n"); + } any = (struct lyd_node_anydata *)data_rpl->data->child; switch (any->value_type) { case LYD_ANYDATA_CONSTSTRING: From 025550ac0e766daa65911b6816aa535ff2ac182e Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Thu, 29 Mar 2018 09:31:40 +0200 Subject: [PATCH 20/87] cli VERSION bump to version 2.0.44 --- cli/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt index 9667655aa..a6b3fef3f 100644 --- a/cli/CMakeLists.txt +++ b/cli/CMakeLists.txt @@ -21,7 +21,7 @@ set(CMAKE_C_FLAGS_RELEASE "-O2") set(CMAKE_C_FLAGS_DEBUG "-g -O0") # set version -set(NP2CLI_VERSION 2.0.43) +set(NP2CLI_VERSION 2.0.44) configure_file("${PROJECT_SOURCE_DIR}/version.h.in" "${PROJECT_SOURCE_DIR}/version.h" ESCAPE_QUOTES @ONLY) # source files From b80a13dce0d6c2387381e8340b956bd017bb14dc Mon Sep 17 00:00:00 2001 From: Darshana Janakaratne Date: Mon, 9 Apr 2018 22:37:01 +1000 Subject: [PATCH 21/87] server BUGFIX refresh the sysrepo session to prevent returning cached server certificate --- server/ietf_keystore.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/server/ietf_keystore.c b/server/ietf_keystore.c index f0bdea652..ef11cf058 100644 --- a/server/ietf_keystore.c +++ b/server/ietf_keystore.c @@ -56,6 +56,15 @@ np_server_cert_clb(const char *name, void *UNUSED(user_data), char **UNUSED(cert np2srv.sr_sess.ds = SR_DS_RUNNING; } + /* Refresh the session to prevent sysrepo returning cached data + * forthe certificate (if the certificate is changed). + */ + if (np2srv_sr_session_refresh(np2srv.sr_sess.srs, NULL)) { + ERR("%s:%d Failed session refresh", __func__, __LINE__); + free(path); + return 1; + } + if (np2srv_sr_get_item(np2srv.sr_sess.srs, path, &sr_cert, NULL)) { free(path); return 1; @@ -116,6 +125,13 @@ np_trusted_cert_list_clb(const char *name, void *UNUSED(user_data), char ***UNUS np2srv.sr_sess.ds = SR_DS_RUNNING; } + /* Refresh the session to prevent sysrepo returning cached data */ + if (np2srv_sr_session_refresh(np2srv.sr_sess.srs, NULL)) { + ERR("%s:%d Failed session refresh", __func__, __LINE__); + free(path); + return 1; + } + if (np2srv_sr_get_items(np2srv.sr_sess.srs, path, &sr_certs, &sr_cert_count, NULL)) { free(path); return 1; From 6b08a974775a5805ca4baab1d7cc6bad49902120 Mon Sep 17 00:00:00 2001 From: Radek Krejci Date: Wed, 11 Apr 2018 15:42:25 +0200 Subject: [PATCH 22/87] server VERSION bump to version 0.5.5 --- server/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 9aeaa07c3..9abd461d2 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -13,7 +13,7 @@ if(NOT UNIX) endif() # set version -set(NP2SRV_VERSION 0.5.4) +set(NP2SRV_VERSION 0.5.5) # set default build type if not specified by user if(NOT CMAKE_BUILD_TYPE) From af179ff03866975095d76691438fbb13779e30e8 Mon Sep 17 00:00:00 2001 From: Radek Krejci Date: Thu, 19 Apr 2018 10:34:56 +0200 Subject: [PATCH 23/87] server BUGFIX count sent notifications for netconf-monitoring stats Fixes #236 --- server/op_notifications.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server/op_notifications.c b/server/op_notifications.c index 288695bc4..1c2c6baa7 100644 --- a/server/op_notifications.c +++ b/server/op_notifications.c @@ -28,6 +28,7 @@ #include "common.h" #include "operations.h" +#include "netconf_monitoring.h" struct np_subscriber { struct nc_session *session; @@ -81,6 +82,7 @@ np2srv_ntf_replay_sort_send(struct np_subscriber *subscriber) for (i = 0; i < subscriber->replay_notif_count; ++i) { nc_server_notif_send(subscriber->session, subscriber->replay_notifs[i], 5000); nc_server_notif_free(subscriber->replay_notifs[i]); + ncm_session_notification(subscriber->session); } free(subscriber->replay_notifs); @@ -93,6 +95,7 @@ np2srv_ntf_replay_sort_send(struct np_subscriber *subscriber) notif = nc_server_notif_new(event, nc_time2datetime(time(NULL), NULL, NULL), NC_PARAMTYPE_FREE); nc_server_notif_send(subscriber->session, notif, 5000); nc_server_notif_free(notif); + ncm_session_notification(subscriber->session); } static void @@ -129,6 +132,7 @@ np2srv_ntf_send(struct np_subscriber *subscriber, struct lyd_node *ntf, time_t t ntf_msg = nc_server_notif_new(filtered_ntf, nc_time2datetime(time(NULL), NULL, NULL), NC_PARAMTYPE_FREE); nc_server_notif_send(subscriber->session, ntf_msg, 5000); nc_server_notif_free(ntf_msg); + ncm_session_notification(subscriber->session); } else { EINT; } @@ -167,6 +171,7 @@ np2srv_ntf_send(struct np_subscriber *subscriber, struct lyd_node *ntf, time_t t if (notif_type == SR_EV_NOTIF_T_REALTIME) { nc_server_notif_send(subscriber->session, ntf_msg, 5000); nc_server_notif_free(ntf_msg); + ncm_session_notification(subscriber->session); } else { ++subscriber->replay_notif_count; subscriber->replay_notifs = realloc(subscriber->replay_notifs, From 9ef35327de75acaa2494737e0e21bd8c5b18710f Mon Sep 17 00:00:00 2001 From: Radek Krejci Date: Thu, 19 Apr 2018 10:39:45 +0200 Subject: [PATCH 24/87] server BUGFIX possible use of uninitialized variables --- server/op_editconfig.c | 2 +- server/op_notifications.c | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/server/op_editconfig.c b/server/op_editconfig.c index fc0e292bc..6cbf6e4fc 100644 --- a/server/op_editconfig.c +++ b/server/op_editconfig.c @@ -178,7 +178,7 @@ op_editconfig(struct lyd_node *rpc, struct nc_session *ncs) /* default value for error-option is "stop-on-error" */ enum NP2_EDIT_ERROPT erropt = NP2_EDIT_ERROPT_STOP; struct lyd_node *config = NULL, *next, *iter; - char *str, *path, *rel, *valbuf, quot; + char *str, *path = NULL, *rel, *valbuf, quot; const char *cstr; enum NP2_EDIT_OP *op = NULL, *op_new; uint16_t *path_levels = NULL, *path_levels_new; diff --git a/server/op_notifications.c b/server/op_notifications.c index 1c2c6baa7..0a76b0377 100644 --- a/server/op_notifications.c +++ b/server/op_notifications.c @@ -288,12 +288,12 @@ np2srv_subscriber_free(struct np_subscriber *subscriber) struct nc_server_reply * op_ntf_subscribe(struct lyd_node *rpc, struct nc_session *ncs) { - int ret, filter_count; + int ret, filter_count = 0; uint16_t i; uint32_t idx; time_t now = time(NULL), start = 0, stop = 0; const char *stream; - char **filters; + char **filters = NULL; void *mem; struct lyd_node *node; struct np_subscriber *new = NULL; @@ -313,8 +313,6 @@ op_ntf_subscribe(struct lyd_node *rpc, struct nc_session *ncs) stream = ((struct lyd_node_leaf_list *)rpc->child)->value_str; /* get optional parameters */ - filters = NULL; - filter_count = 0; LY_TREE_FOR(rpc->child->next, node) { if (strcmp(node->schema->module->ns, "urn:ietf:params:xml:ns:netconf:notification:1.0")) { /* ignore */ From 0de20765b0a1dfdd7359eb9001f50774f8577692 Mon Sep 17 00:00:00 2001 From: Radek Krejci Date: Thu, 19 Apr 2018 10:57:11 +0200 Subject: [PATCH 25/87] server VERSION bump to version 0.5.6 --- server/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 9abd461d2..3e8ca8f01 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -13,7 +13,7 @@ if(NOT UNIX) endif() # set version -set(NP2SRV_VERSION 0.5.5) +set(NP2SRV_VERSION 0.5.6) # set default build type if not specified by user if(NOT CMAKE_BUILD_TYPE) From bac17e958f67862d145ee4429c0c020a13b261a3 Mon Sep 17 00:00:00 2001 From: Radek Krejci Date: Thu, 19 Apr 2018 11:34:48 +0200 Subject: [PATCH 26/87] server tests BUGFIX missing session in netconf-monitoring structures When testing notifications sending, it is necessary to add the testing session into netconf-monitoring internal structures to allow storing stats about the sent notifications --- server/tests/test_notif.c | 1 + 1 file changed, 1 insertion(+) diff --git a/server/tests/test_notif.c b/server/tests/test_notif.c index abfe66b77..53da41973 100644 --- a/server/tests/test_notif.c +++ b/server/tests/test_notif.c @@ -220,6 +220,7 @@ __wrap_sr_event_notif_subscribe(sr_session_ctx_t *session, const char *xpath, sr printf("test: New subscription to %s\n", xpath); notif_clb = callback; notif_clb_data = private_ctx; + ncm_session_add((struct nc_session *)notif_clb_data); return SR_ERR_OK; } From 45598290db783b997c9bd7af4ce35aabe3662d95 Mon Sep 17 00:00:00 2001 From: Radek Krejci Date: Thu, 19 Apr 2018 11:37:18 +0200 Subject: [PATCH 27/87] server VERSION bump to version 0.5.7 --- server/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 3e8ca8f01..be0a21ac1 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -13,7 +13,7 @@ if(NOT UNIX) endif() # set version -set(NP2SRV_VERSION 0.5.6) +set(NP2SRV_VERSION 0.5.7) # set default build type if not specified by user if(NOT CMAKE_BUILD_TYPE) From 60b934f0dbb2540ef2afe9ed5faef60dd99fd45d Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Mon, 23 Apr 2018 12:47:45 +0200 Subject: [PATCH 28/87] server BUGFIX uninitialized variable Fixes sysrepo/sysrepo#1098 --- server/op_generic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/op_generic.c b/server/op_generic.c index 01dc8dc26..09b92a3d4 100644 --- a/server/op_generic.c +++ b/server/op_generic.c @@ -84,7 +84,7 @@ struct nc_server_reply * op_generic(struct lyd_node *rpc, struct nc_session *ncs) { int rc; - uint32_t i, in_idx; + uint32_t i, in_idx = 0; char *rpc_xpath = NULL, *str; sr_val_t *input = NULL, *output = NULL; size_t out_count = 0; From f07a0340bbe6e3ae1058c07724dcc0d8e5d11d26 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Mon, 23 Apr 2018 12:49:11 +0200 Subject: [PATCH 29/87] server VERSION bump to version 0.5.8 --- server/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index be0a21ac1..1593ff086 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -13,7 +13,7 @@ if(NOT UNIX) endif() # set version -set(NP2SRV_VERSION 0.5.7) +set(NP2SRV_VERSION 0.5.8) # set default build type if not specified by user if(NOT CMAKE_BUILD_TYPE) From 20cbe961f20acbeb6111d46f844d174d242d0f94 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Mon, 23 Apr 2018 15:03:32 +0200 Subject: [PATCH 30/87] server BUGFIX refresh sr sessions before getting data Refs #235 --- server/ietf_netconf_server.c | 4 ++++ server/ietf_system.c | 4 ++++ server/op_get_config.c | 2 ++ 3 files changed, 10 insertions(+) diff --git a/server/ietf_netconf_server.c b/server/ietf_netconf_server.c index 2b3e47765..0f6e6cd12 100644 --- a/server/ietf_netconf_server.c +++ b/server/ietf_netconf_server.c @@ -147,6 +147,8 @@ get_ssh_host_key_public_key(void *arg) char *path, *value; sr_val_t *sr_val = NULL; + np2srv_sr_session_refresh(targ->srs, NULL); + if (targ->listen_or_ch) { asprintf(&path, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/host-keys/host-key[name='%s']/public-key", targ->endpt_client_name, targ->key_name); np2srv_sr_get_item(targ->srs, path, &sr_val, NULL); @@ -1185,6 +1187,8 @@ feature_change_ietf_netconf_server(const char *feature_name, bool enabled) return 0; } + np2srv_sr_session_refresh(np2srv.sr_sess.srs, NULL); + if (np2srv_sr_get_items_iter(np2srv.sr_sess.srs, path, &sr_iter, NULL)) { return -1; } diff --git a/server/ietf_system.c b/server/ietf_system.c index 1a6d78b10..9e2dfdfb9 100644 --- a/server/ietf_system.c +++ b/server/ietf_system.c @@ -129,6 +129,8 @@ subtree_change_resolve(sr_session_ctx_t *srs, sr_change_oper_t sr_oper, sr_val_t /* just store it */ *prev_keytype = keytype; } else { + np2srv_sr_session_refresh(srs, NULL); + /* we must remove the key first, then re-add it */ asprintf(&path, "/ietf-system:system/authentication/user[name='%s']/authorized-key[name='%s']/key-data", list1_key, list2_key); @@ -241,6 +243,8 @@ feature_change_ietf_system(sr_session_ctx_t *srs, const char *feature_name, bool } if (enabled) { + np2srv_sr_session_refresh(srs, NULL); + if (np2srv_sr_get_items_iter(srs, "/ietf-system:system/authentication/user/authorized-key//*", &sr_iter, NULL)) { return -1; diff --git a/server/op_get_config.c b/server/op_get_config.c index 17ea49f83..b6af3bf2a 100644 --- a/server/op_get_config.c +++ b/server/op_get_config.c @@ -44,6 +44,8 @@ opget_build_subtree_from_sysrepo(sr_session_ctx_t *srs, struct lyd_node **root, return -1; } + np2srv_sr_session_refresh(srs, NULL); + rc = np2srv_sr_get_items_iter(srs, full_subtree_xpath, &sriter, NULL); free(full_subtree_xpath); if (rc == 1) { From b42daf039552a5aabf2a0f54fa31a3006350f918 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Mon, 23 Apr 2018 15:04:07 +0200 Subject: [PATCH 31/87] server VERSION bump to version 0.5.9 --- server/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 1593ff086..d5c9b0a35 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -13,7 +13,7 @@ if(NOT UNIX) endif() # set version -set(NP2SRV_VERSION 0.5.8) +set(NP2SRV_VERSION 0.5.9) # set default build type if not specified by user if(NOT CMAKE_BUILD_TYPE) From 32f270dfa55d8df3a515fdb4f184e05540d9efaf Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Wed, 25 Apr 2018 11:02:39 +0200 Subject: [PATCH 32/87] cli CHANGE commands can now be timed ...using new timed command. --- cli/commands.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 98 insertions(+), 1 deletion(-) diff --git a/cli/commands.c b/cli/commands.c index 178d1040a..8f1c6aa57 100644 --- a/cli/commands.c +++ b/cli/commands.c @@ -68,6 +68,7 @@ char *config_editor; struct nc_session *session; volatile pthread_t ntf_tid; volatile int interleave; +int timed; int cmd_disconnect(const char *arg, char **tmp_config_file); @@ -228,11 +229,54 @@ cli_ntf_clb(struct nc_session *session, const struct nc_notif *notif) } } +static int +cli_gettimespec(struct timespec *ts, int *mono) +{ + errno = 0; + +#ifdef CLOCK_MONOTONIC_RAW + *mono = 1; + return clock_gettime(CLOCK_MONOTONIC_RAW, ts); +#elif defined(CLOCK_MONOTONIC) + *mono = 1; + return clock_gettime(CLOCK_MONOTONIC, ts); +#elif defined(CLOCK_REALTIME) + /* no monotonic clock available, return realtime */ + *mono = 0; + return clock_gettime(CLOCK_REALTIME, ts); +#else + *mono = 0; + + int rc; + struct timeval tv; + + rc = gettimeofday(&tv, NULL); + if (!rc) { + ts->tv_sec = (time_t)tv.tv_sec; + ts->tv_nsec = 1000L * (long)tv.tv_usec; + } + return rc; +#endif +} + +/* returns milliseconds */ +static int32_t +cli_difftimespec(const struct timespec *ts1, const struct timespec *ts2) +{ + int64_t nsec_diff = 0; + + nsec_diff += (((int64_t)ts2->tv_sec) - ((int64_t)ts1->tv_sec)) * 1000000000L; + nsec_diff += ((int64_t)ts2->tv_nsec) - ((int64_t)ts1->tv_nsec); + + return (nsec_diff ? nsec_diff / 1000000L : 0); +} + static int cli_send_recv(struct nc_rpc *rpc, FILE *output, NC_WD_MODE wd_mode) { char *str, *model_data; - int ret = 0, ly_wd; + int ret = 0, ly_wd, mono; + int32_t msec; uint16_t i, j; uint64_t msgid; struct lyd_node_anydata *any; @@ -240,6 +284,15 @@ cli_send_recv(struct nc_rpc *rpc, FILE *output, NC_WD_MODE wd_mode) struct nc_reply *reply; struct nc_reply_data *data_rpl; struct nc_reply_error *error; + struct timespec ts_start, ts_stop; + + if (timed) { + ret = cli_gettimespec(&ts_start, &mono); + if (ret) { + ERROR(__func__, "Getting current time failed (%s).", strerror(errno)); + return ret; + } + } msgtype = nc_send_rpc(session, rpc, 1000, &msgid); if (msgtype == NC_MSG_ERROR) { @@ -275,6 +328,15 @@ cli_send_recv(struct nc_rpc *rpc, FILE *output, NC_WD_MODE wd_mode) goto recv_reply; } + if (timed) { + ret = cli_gettimespec(&ts_stop, &mono); + if (ret) { + ERROR(__func__, "Getting current time failed (%s).", strerror(errno)); + nc_reply_free(reply); + return ret; + } + } + switch (reply->type) { case NC_RPL_OK: fprintf(output, "OK\n"); @@ -430,6 +492,11 @@ cli_send_recv(struct nc_rpc *rpc, FILE *output, NC_WD_MODE wd_mode) goto recv_reply; } + if (timed) { + msec = cli_difftimespec(&ts_start, &ts_stop); + fprintf(output, "%s %2dm%d,%03ds\n", mono ? "mono" : "real", msec / 60000, (msec % 60000) / 1000, msec % 1000); + } + return ret; } @@ -1012,6 +1079,12 @@ cmd_userrpc_help(void) printf("user-rpc [--help] [--content ] [--out ]\n"); } +void +cmd_timed_help(void) +{ + printf("timed [--help] [on | off]\n"); +} + #ifdef NC_ENABLED_SSH void @@ -4538,6 +4611,29 @@ cmd_userrpc(const char *arg, char **tmp_config_file) return ret; } +int +cmd_timed(const char *arg, char **UNUSED(tmp_config_file)) +{ + char *args = strdupa(arg); + char *cmd = NULL; + + strtok(args, " "); + if ((cmd = strtok(NULL, " ")) == NULL) { + fprintf(stdout, "All commands will %sbe timed.\n", timed ? "" : "not "); + } else { + if (!strcmp(cmd, "on")) { + timed = 1; + } else if (!strcmp(cmd, "off")) { + timed = 0; + } else { + ERROR(__func__, "Unknown option %s.", cmd); + cmd_timed_help(); + } + } + + return 0; +} + COMMAND commands[] = { #ifdef NC_ENABLED_SSH {"auth", cmd_auth, cmd_auth_help, "Manage SSH authentication options"}, @@ -4573,6 +4669,7 @@ COMMAND commands[] = { {"subscribe", cmd_subscribe, cmd_subscribe_help, "notifications operation"}, {"get-schema", cmd_getschema, cmd_getschema_help, "ietf-netconf-monitoring operation"}, {"user-rpc", cmd_userrpc, cmd_userrpc_help, "Send your own content in an RPC envelope (for DEBUG purposes)"}, + {"timed", cmd_timed, cmd_timed_help, "Time all the commands (that communicate with a server) from issuing a RPC to getting a reply"}, /* synonyms for previous commands */ {"?", cmd_help, NULL, "Display commands description"}, {"exit", cmd_quit, NULL, "Quit the program"}, From d1cd55e25c0a765ac6a68132baffe79146334f50 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Wed, 25 Apr 2018 11:03:18 +0200 Subject: [PATCH 33/87] cli VERSION bump to version 2.0.45 --- cli/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt index a6b3fef3f..e0a2a3d09 100644 --- a/cli/CMakeLists.txt +++ b/cli/CMakeLists.txt @@ -21,7 +21,7 @@ set(CMAKE_C_FLAGS_RELEASE "-O2") set(CMAKE_C_FLAGS_DEBUG "-g -O0") # set version -set(NP2CLI_VERSION 2.0.44) +set(NP2CLI_VERSION 2.0.45) configure_file("${PROJECT_SOURCE_DIR}/version.h.in" "${PROJECT_SOURCE_DIR}/version.h" ESCAPE_QUOTES @ONLY) # source files From 95f3fa0434a3cdcd10a68054e4be05f0e5b6972c Mon Sep 17 00:00:00 2001 From: Peter Feige Date: Mon, 7 May 2018 05:21:39 +0000 Subject: [PATCH 34/87] copy-config with slash in keys --- server/tests/test_copy_config.c | 96 +++++++++++++++++++++++++-------- 1 file changed, 73 insertions(+), 23 deletions(-) diff --git a/server/tests/test_copy_config.c b/server/tests/test_copy_config.c index bbab06a05..4ff2461ff 100644 --- a/server/tests/test_copy_config.c +++ b/server/tests/test_copy_config.c @@ -207,61 +207,91 @@ __wrap_sr_set_item(sr_session_ctx_t *session, const char *xpath, const sr_val_t switch (count) { case 0: - assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1']"); + assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1/1']"); break; case 1: - assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1']/description"); + assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1/1']/description"); break; case 2: - assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1']/type"); + assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1/1']/type"); break; case 3: - assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1']/enabled"); + assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1/1']/enabled"); break; case 4: - assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1']/link-up-down-trap-enable"); + assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1/1']/link-up-down-trap-enable"); break; case 5: - assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1']/ietf-ip:ipv4"); + assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1/1']/ietf-ip:ipv4"); break; case 6: - assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1']/ietf-ip:ipv4/enabled"); + assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1/1']/ietf-ip:ipv4/enabled"); break; case 7: - assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1']/ietf-ip:ipv4/forwarding"); + assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1/1']/ietf-ip:ipv4/forwarding"); break; case 8: - assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1']/ietf-ip:ipv4/mtu"); + assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1/1']/ietf-ip:ipv4/mtu"); break; case 9: - assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1']/ietf-ip:ipv4/neighbor[ip='10.0.0.2']"); + assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1/1']/ietf-ip:ipv4/neighbor[ip='10.0.0.2']"); break; case 10: - assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1']/ietf-ip:ipv4/neighbor[ip='10.0.0.2']/link-layer-address"); + assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1/1']/ietf-ip:ipv4/neighbor[ip='10.0.0.2']/link-layer-address"); break; case 11: - assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1']/ietf-ip:ipv6"); + assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1/1']/ietf-ip:ipv6"); break; case 12: - assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1']/ietf-ip:ipv6/enabled"); + assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1/1']/ietf-ip:ipv6/enabled"); break; case 13: - assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1']/ietf-ip:ipv6/forwarding"); + assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1/1']/ietf-ip:ipv6/forwarding"); break; case 14: - assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1']/ietf-ip:ipv6/dup-addr-detect-transmits"); + assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name=\"'iface1/2'\"]"); break; case 15: - assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1']/ietf-ip:ipv6/autoconf/create-global-addresses"); + assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name=\"'iface1/2'\"]/description"); break; case 16: - assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1']/ietf-ip:ipv6/autoconf/create-temporary-addresses"); + assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name=\"'iface1/2'\"]/type"); break; case 17: - assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1']/ietf-ip:ipv6/autoconf/temporary-valid-lifetime"); + assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name=\"'iface1/2'\"]/enabled"); break; case 18: - assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name='iface1']/ietf-ip:ipv6/autoconf/temporary-preferred-lifetime"); + assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name=\"'iface1/2'\"]/link-up-down-trap-enable"); + break; + case 19: + assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name=\"'iface1/2'\"]/ietf-ip:ipv4"); + break; + case 20: + assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name=\"'iface1/2'\"]/ietf-ip:ipv4/enabled"); + break; + case 21: + assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name=\"'iface1/2'\"]/ietf-ip:ipv4/forwarding"); + break; + case 22: + assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name=\"'iface1/2'\"]/ietf-ip:ipv4/mtu"); + break; + case 23: + assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name=\"'iface1/2'\"]/ietf-ip:ipv4/neighbor[ip='10.0.0.2']"); + break; + case 24: + assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name=\"'iface1/2'\"]/ietf-ip:ipv4/neighbor[ip='10.0.0.2']/link-layer-address"); + break; + case 25: + assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name=\"'iface1/2'\"]/ietf-ip:ipv6"); + break; + case 26: + assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name=\"'iface1/2'\"]/ietf-ip:ipv6/enabled"); + break; + case 27: + assert_string_equal(xpath, "/ietf-interfaces:interfaces/interface[name=\"'iface1/2'\"]/ietf-ip:ipv6/forwarding"); + break; + default: + assert_string_equal(xpath, "too many nodes"); break; } ++count; @@ -514,7 +544,7 @@ np_stop(void **state) } static void -test_edit_config(void **state) +test_copy_config(void **state) { (void)state; /* unused */ const char *copy_rpc = @@ -527,8 +557,28 @@ test_edit_config(void **state) "" "" "" - "iface1" - "iface1 dsc" + "iface1/1" + "iface1/1 dsc" + "ianaift:ethernetCsmacd" + "true" + "disabled" + "" + "true" + "true" + "68" + "" + "10.0.0.2" + "01:34:56:78:9a:bc:de:f0" + "" + "" + "" + "true" + "false" + "" + "" + "" + "'iface1/2'" + "iface1/2 dsc" "ianaift:ethernetCsmacd" "true" "disabled" @@ -573,7 +623,7 @@ main(void) { const struct CMUnitTest tests[] = { cmocka_unit_test_setup(test_startstop, np_start), - cmocka_unit_test(test_edit_config), + cmocka_unit_test(test_copy_config), cmocka_unit_test_teardown(test_startstop, np_stop), }; From 476d304a39376ac80193bc95166126e6a8295f17 Mon Sep 17 00:00:00 2001 From: Peter Feige Date: Mon, 7 May 2018 05:28:10 +0000 Subject: [PATCH 35/87] copy-config with slash in keys solution --- server/op_copyconfig.c | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/server/op_copyconfig.c b/server/op_copyconfig.c index ce224e47c..9a5b11c90 100644 --- a/server/op_copyconfig.c +++ b/server/op_copyconfig.c @@ -28,6 +28,32 @@ #include "common.h" #include "operations.h" + +static char * +find_last_slash(char *string) +{ + char in_quote = '\0'; + char *char_ptr; + char curr_char; + + for (char_ptr = string + strlen(string); char_ptr != string; --char_ptr) { + curr_char = *char_ptr; + if (curr_char == '\'' || curr_char == '"') { + if (in_quote == '\0') + in_quote = curr_char; + else if (in_quote == curr_char) + in_quote = '\0'; + } + else if (curr_char == '/') { + if (in_quote == '\0') + return char_ptr; + } + } + + return NULL; +} + + struct nc_server_reply * op_copyconfig(struct lyd_node *rpc, struct nc_session *ncs) { @@ -43,6 +69,7 @@ op_copyconfig(struct lyd_node *rpc, struct nc_session *ncs) struct nc_server_reply *ereply = NULL; int rc = SR_ERR_OK, path_index = 0, missing_keys = 0, lastkey = 0; unsigned int i; + char quote; /* get sysrepo connections for this session */ sessions = (struct np2_sessions *)nc_session_get_data(ncs); @@ -182,8 +209,13 @@ op_copyconfig(struct lyd_node *rpc, struct nc_session *ncs) /* still processing list keys */ missing_keys--; /* add key predicate into the list's path */ - path_index += sprintf(&path[path_index], "[%s=\'%s\']", iter->schema->name, - ((struct lyd_node_leaf_list *)iter)->value_str); + if (strchr(((struct lyd_node_leaf_list *)iter)->value_str, '\'')) { + quote = '"'; + } else { + quote = '\''; + } + path_index += sprintf(&path[path_index], "[%s=%c%s%c]", iter->schema->name, + quote, ((struct lyd_node_leaf_list *)iter)->value_str, quote); if (!missing_keys) { /* the last key, create the list instance */ lastkey = 1; @@ -247,7 +279,7 @@ op_copyconfig(struct lyd_node *rpc, struct nc_session *ncs) /* maintain "stack" variables */ if (!missing_keys && !lastkey) { - str = strrchr(path, '/'); + str = find_last_slash(path); if (str) { *str = '\0'; path_index = str - path; @@ -269,7 +301,7 @@ op_copyconfig(struct lyd_node *rpc, struct nc_session *ncs) /* maintain "stack" variables */ if (!missing_keys) { - str = strrchr(path, '/'); + str = find_last_slash(path); if (str) { *str = '\0'; path_index = str - path; From bed2f35d7640ca8500a6f5ed4cabd56c1d0b309e Mon Sep 17 00:00:00 2001 From: Radek Krejci Date: Wed, 16 May 2018 16:11:27 +0200 Subject: [PATCH 36/87] server CHANGE do not include YANG 1.1 schemas in ietf-netconf-monitoring data Since YANG 1.1 schemas are not contained in server's capabilities listed in , they are not supposed to be included even in ietf-netconf-monitoring data Fixes CESNET/libnetconf2#59 --- server/netconf_monitoring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/netconf_monitoring.c b/server/netconf_monitoring.c index 329111e92..bc1b644b6 100644 --- a/server/netconf_monitoring.c +++ b/server/netconf_monitoring.c @@ -203,7 +203,7 @@ ncm_get_data(void) /* capabilities */ cont = lyd_new(root, NULL, "capabilities"); - cpblts = nc_server_get_cpblts(np2srv.ly_ctx); + cpblts = nc_server_get_cpblts_version(np2srv.ly_ctx, LYS_VERSION_1); if (!cpblts) { goto error; } From 0cd86bb4eafe6e90b608cbc3224e9d88f5a30be7 Mon Sep 17 00:00:00 2001 From: Radek Krejci Date: Wed, 16 May 2018 16:17:03 +0200 Subject: [PATCH 37/87] server VERSION bump version to 0.5.10 --- server/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index d5c9b0a35..5e678d234 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -13,7 +13,7 @@ if(NOT UNIX) endif() # set version -set(NP2SRV_VERSION 0.5.9) +set(NP2SRV_VERSION 0.5.10) # set default build type if not specified by user if(NOT CMAKE_BUILD_TYPE) From 5db0d39d0aa1f009c9c7fb8792280885f2d2dc67 Mon Sep 17 00:00:00 2001 From: Radek Krejci Date: Thu, 17 May 2018 08:29:56 +0200 Subject: [PATCH 38/87] server tests CHANGE reflect recent changes in libnetconf2 server now sends only YANG 1.0 schemas list in hello and in netconf-state's capabilities list, so ietf-datastore is not present now and ietf-yang-library URI looks differently. --- server/tests/test_get.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server/tests/test_get.c b/server/tests/test_get.c index 8e5a2ecd3..3fae2809a 100644 --- a/server/tests/test_get.c +++ b/server/tests/test_get.c @@ -593,8 +593,7 @@ test_get(void **state) "urn:ietf:params:xml:ns:yang:1?module=yang&revision=2017-02-20" "urn:ietf:params:xml:ns:yang:ietf-inet-types?module=ietf-inet-types&revision=2013-07-15" "urn:ietf:params:xml:ns:yang:ietf-yang-types?module=ietf-yang-types&revision=2013-07-15" - "urn:ietf:params:xml:ns:yang:ietf-datastores?module=ietf-datastores&revision=2017-08-17" - "urn:ietf:params:xml:ns:yang:ietf-yang-library?module=ietf-yang-library&revision=2018-01-17&module-set-id=15" + "urn:ietf:params:xml:ns:yang:ietf-yang-library?revision=2018-01-17&module-set-id=15" "ns?module=ietf-netconf-server" "urn:ietf:params:xml:ns:yang:ietf-netconf-acm?module=ietf-netconf-acm&revision=2012-02-22" "urn:ietf:params:xml:ns:netconf:base:1.0?module=ietf-netconf&revision=2011-06-01&features=writable-running,candidate,rollback-on-error,validate,startup,xpath" From 3dd94fe7d96fde848e5a2d0925337b26b2998d6f Mon Sep 17 00:00:00 2001 From: Radek Krejci Date: Thu, 17 May 2018 09:01:15 +0200 Subject: [PATCH 39/87] travis CHANGE use cmocka 1.1.1 since 1.0.1 has issues with clang --- .travis-install-libs.sh | 10 +++++----- .travis.yml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.travis-install-libs.sh b/.travis-install-libs.sh index 2b5c9bf9e..716293baf 100644 --- a/.travis-install-libs.sh +++ b/.travis-install-libs.sh @@ -10,16 +10,16 @@ sudo apt-get update -qq sudo apt-get install -y zlib1g-dev libssl-dev sudo apt-get install -y --force-yes libavl-dev libev-dev coreutils acl valgrind -if [ ! -d "cmocka-1.0.1/build" ]; then +if [ ! -d "cmocka-1.1.1/build" ]; then echo "Building cmocka from source." - wget https://cmocka.org/files/1.0/cmocka-1.0.1.tar.xz - tar -xJvf cmocka-1.0.1.tar.xz - cd cmocka-1.0.1 && mkdir build && cd build + wget https://cmocka.org/files/1.1/cmocka-1.1.1.tar.xz + tar -xJvf cmocka-1.1.1.tar.xz + cd cmocka-1.1.1 && mkdir build && cd build cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr .. && make -j2 && sudo make install cd ../.. else echo "Using cmocka from cache." - cd cmocka-1.0.1/build + cd cmocka-1.1.1/build sudo make install cd ../.. fi diff --git a/.travis.yml b/.travis.yml index 85caa84a4..469084ecc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,7 +29,7 @@ cache: - libssh-0.7.5 - protobuf - protobuf-c - - cmocka-1.0.1 + - cmocka-1.1.1 before_install: - eval "${MATRIX_EVAL}" From 9e793f1a74325f1b17dba79163cd2e96c7413c96 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Fri, 18 May 2018 09:35:08 +0200 Subject: [PATCH 40/87] server OPTIMIZE do not create list keys They are already created during list instance creation. --- server/op_get_config.c | 64 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/server/op_get_config.c b/server/op_get_config.c index b6af3bf2a..6074bd5f6 100644 --- a/server/op_get_config.c +++ b/server/op_get_config.c @@ -29,6 +29,66 @@ #include "operations.h" #include "netconf_monitoring.h" +static int +opget_build_subtree_from_sysrepo_is_key(const char *xpath) +{ + const char *last_node, *ptr; + char quote; + int key_len; + + ptr = xpath + strlen(xpath); + + do { + if ((--ptr == xpath) || (ptr[0] == ']')) { + return 0; + } + } while (ptr[0] != '/'); + /* last node name found */ + last_node = ptr + 1; + + /* go through all predicates and compare keys with the last node */ + while ((--ptr != xpath) && (ptr[0] == ']')) { + /* value end */ + if ((--ptr == xpath) || ((ptr[0] != '\'') && (ptr[0] != '"'))) { + return 0; + } + quote = ptr[0]; + + /* skip the value */ + do { + if (--ptr == xpath) { + return 0; + } + } while (ptr[0] != quote); + + /* equals */ + if ((--ptr == xpath) || (ptr[0] != '=')) { + return 0; + } + + /* key length must be at least one */ + if ((--ptr == xpath) || (ptr[0] == '[')) { + return 0; + } + + /* predicate start */ + key_len = 0; + do { + if (--ptr == xpath) { + return 0; + } + ++key_len; + } while (ptr[0] != '['); + + /* compare key name with the last node */ + if (!strncmp(last_node, ptr + 1, key_len) && !last_node[key_len]) { + return 1; + } + } + + return 0; +} + /* add whole subtree */ static int opget_build_subtree_from_sysrepo(sr_session_ctx_t *srs, struct lyd_node **root, const char *subtree_xpath) @@ -56,6 +116,10 @@ opget_build_subtree_from_sysrepo(sr_session_ctx_t *srs, struct lyd_node **root, } while ((!np2srv_sr_get_item_next(srs, sriter, &value, NULL))) { + if (opget_build_subtree_from_sysrepo_is_key(value->xpath)) { + continue; + } + if (op_sr_val_to_lyd_node(*root, value, &node)) { sr_free_val(value); sr_free_val_iter(sriter); From 4c94ed1f5eb081e9275b26e3dfadacf05e61c492 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Fri, 18 May 2018 09:35:50 +0200 Subject: [PATCH 41/87] server VERSION bump to version 0.5.11 --- server/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 5e678d234..1ed8fde5b 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -13,7 +13,7 @@ if(NOT UNIX) endif() # set version -set(NP2SRV_VERSION 0.5.10) +set(NP2SRV_VERSION 0.5.11) # set default build type if not specified by user if(NOT CMAKE_BUILD_TYPE) From 6330479dc68bab22fbaff28f175eefb9ca4e2ba5 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Fri, 18 May 2018 10:02:30 +0200 Subject: [PATCH 42/87] server BUGFIX memory leak --- server/op_get_config.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/server/op_get_config.c b/server/op_get_config.c index 6074bd5f6..54357dd33 100644 --- a/server/op_get_config.c +++ b/server/op_get_config.c @@ -116,18 +116,17 @@ opget_build_subtree_from_sysrepo(sr_session_ctx_t *srs, struct lyd_node **root, } while ((!np2srv_sr_get_item_next(srs, sriter, &value, NULL))) { - if (opget_build_subtree_from_sysrepo_is_key(value->xpath)) { - continue; - } - - if (op_sr_val_to_lyd_node(*root, value, &node)) { - sr_free_val(value); - sr_free_val_iter(sriter); - return -1; - } + /* skip list keys, they were created during list instance creation */ + if (!opget_build_subtree_from_sysrepo_is_key(value->xpath)) { + if (op_sr_val_to_lyd_node(*root, value, &node)) { + sr_free_val(value); + sr_free_val_iter(sriter); + return -1; + } - if (!(*root)) { - *root = node; + if (!(*root)) { + *root = node; + } } sr_free_val(value); } From 8ae9fd8a8117175c5c38a0d0298e7dae1fea51a7 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Fri, 18 May 2018 10:02:50 +0200 Subject: [PATCH 43/87] VERSION bump to version 0.5.12 --- server/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 1ed8fde5b..15ba59621 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -13,7 +13,7 @@ if(NOT UNIX) endif() # set version -set(NP2SRV_VERSION 0.5.11) +set(NP2SRV_VERSION 0.5.12) # set default build type if not specified by user if(NOT CMAKE_BUILD_TYPE) From 57a6e2eb3918602455aec9bbdcda4ec5e83c5814 Mon Sep 17 00:00:00 2001 From: Andrew Langefeld Date: Fri, 18 May 2018 19:26:56 -0500 Subject: [PATCH 44/87] Fix enabling feat depending on later schema feat `np2srv_init_schemas()` walks through schemas in the order they are returned from sysrepo via `np2srv_sr_list_schemas()` and attemps to enable features that sysrepo indicates are supposed to be enabled. However, if a feature in schema `n` depends on a feature that is found in schema `n + 1` (or any subsequent schema, for that matter), enabling the feature in schema `n` will fail because the feature in schema `n + 1` has not yet been enabled. The additional unit test included in this commit demonstrates the problem. This commit implements a solution as follows: 1. When walking through the schemas returned from sysrepo, keep a list containing all the features that will need to be enabled. 2. Now walk through all the schemas attempting to enable the recorded features. Some features may fail to enable due to depending on other features that have not yet been enabled. So continue walking through the schemas attempting to enable features as long as (1) we are able to make progress and enable at least one new feature, or (2) there are no more features to enable. This approach should allow us to enable all of the required features regardless of how far apart they are on a dependency graph. --- server/main.c | 86 ++++++++-- server/tests/config.h.in | 4 + server/tests/files/test-feature-consumer.yin | 28 ++++ server/tests/files/test-feature.yin | 20 +++ server/tests/test_edit_get_config.c | 160 ++++++++++++++++++- 5 files changed, 282 insertions(+), 16 deletions(-) mode change 100644 => 100755 server/tests/config.h.in create mode 100755 server/tests/files/test-feature-consumer.yin create mode 100755 server/tests/files/test-feature.yin mode change 100644 => 100755 server/tests/test_edit_get_config.c diff --git a/server/main.c b/server/main.c index a0546e0c7..7e41bfedd 100644 --- a/server/main.c +++ b/server/main.c @@ -754,10 +754,19 @@ np2srv_init_schemas(void) char *data = NULL; const struct lys_module *mod; sr_schema_t *schemas = NULL; - size_t count, i, j; + size_t schema_count, i, j; + + size_t module_feature_count = 0; + struct mod_feat { + const struct lys_module *mod; + const char *enabled_feature; + }; + struct mod_feat *mod_feat_array; + size_t mod_feat_array_index; + bool making_progress; /* get the list of schemas from sysrepo */ - if (np2srv_sr_list_schemas(np2srv.sr_sess.srs, &schemas, &count, NULL)) { + if (np2srv_sr_list_schemas(np2srv.sr_sess.srs, &schemas, &schema_count, NULL)) { return -1; } @@ -805,7 +814,7 @@ np2srv_init_schemas(void) ly_ctx_set_module_imp_clb(np2srv.ly_ctx, np2srv_ly_import_clb, NULL); /* 1) use modules from sysrepo */ - for (i = 0; i < count; i++) { + for (i = 0; i < schema_count; i++) { data = NULL; mod = NULL; VRB("Loading schema \"%s%s%s\" from sysrepo.", schemas[i].module_name, schemas[i].revision.revision ? "@" : "", @@ -824,23 +833,78 @@ np2srv_init_schemas(void) mod = lys_parse_mem(np2srv.ly_ctx, data, LYS_IN_YIN); free(data); } + } - if (!mod) { + /* determine the count of module/features present */ + module_feature_count = 0; + for (i=0; i < schema_count; i++) { + module_feature_count += schemas[i].enabled_feature_cnt; + } + /* prepare data storage to keep module/feature enable status */ + mod_feat_array = calloc(module_feature_count, sizeof (struct mod_feat)); + mod_feat_array_index = 0; + + /* loop back through the modules now that they should be loaded and enable features */ + for (i = 0; i < schema_count; i++) { + if ((mod = ly_ctx_get_module(np2srv.ly_ctx, schemas[i].module_name, schemas[i].revision.revision, 0))) { + /* set features according to sysrepo */ + for (j = 0; j < schemas[i].enabled_feature_cnt; ++j) { + /* if lys_features_enable fail, record the mod_feat for retry otherwise store a null */ + if (lys_features_enable(mod, schemas[i].enabled_features[j]) == EXIT_FAILURE) { + /* store away info related to feature that did not enable on first pass */ + mod_feat_array[mod_feat_array_index].mod = mod; + mod_feat_array[mod_feat_array_index].enabled_feature = schemas[i].enabled_features[j]; + } + mod_feat_array_index++; + } + } else { WRN("Getting %s%s%s schema from sysrepo failed, data from this module won't be available.", schemas[i].module_name, schemas[i].revision.revision ? "@" : "", schemas[i].revision.revision ? schemas[i].revision.revision : ""); - } else { - /* set features according to sysrepo */ - for (j = 0; j < schemas[i].enabled_feature_cnt; ++j) { - lys_features_enable(mod, schemas[i].enabled_features[j]); + } + } + + /* we may be able to get features enabled now that others are enabled so we will + run through our stored module_features and retry the ones on our list + we will continue until a pass through the array doesn't indicate progress */ + making_progress = true; + while(making_progress) { + making_progress = false; + for (i = 0; i < module_feature_count; i++) { + if (mod_feat_array[i].mod != NULL) { + if ((lys_features_enable(mod_feat_array[i].mod, mod_feat_array[i].enabled_feature)) == EXIT_SUCCESS) { + /* feature enabled, remove from list and set making_progress TRUE */ + VRB("Retry feature enable successful for \"%s\" in \"%s\".", + mod_feat_array[i].enabled_feature, mod_feat_array[i].mod->name); + making_progress = true; + mod_feat_array[i].mod = NULL; + mod_feat_array[i].enabled_feature = NULL; + } } + } + } - /* set RPC and Notifications callbacks */ + /* now pass through the mod_feat_array and report ERR on any remaining entries + as they are not enabled */ + for (i = 0; i < module_feature_count; i++) { + if (mod_feat_array[i].mod != NULL) { + /* this module feature never enabled */ + ERR("Retry feature enable failed for \"%s\" in \"%s\".", + mod_feat_array[i].enabled_feature, mod_feat_array[i].mod->name); + } + } + + free(mod_feat_array); + + for (i = 0; i < schema_count; i++) { + if ((mod = ly_ctx_get_module(np2srv.ly_ctx, schemas[i].module_name, schemas[i].revision.revision, 0))) { + /* setRPC and Notifications callbacks */ np2srv_module_assign_clbs(mod); } } + ly_ctx_set_module_imp_clb(np2srv.ly_ctx, np2srv_ly_import_clb, NULL); - sr_free_schemas(schemas, count); + sr_free_schemas(schemas, schema_count); schemas = NULL; /* 2) add internally used schemas: ietf-netconf, ... */ @@ -893,7 +957,7 @@ np2srv_init_schemas(void) error: if (schemas) { - sr_free_schemas(schemas, count); + sr_free_schemas(schemas, schema_count); } ly_ctx_destroy(np2srv.ly_ctx, NULL); return -1; diff --git a/server/tests/config.h.in b/server/tests/config.h.in old mode 100644 new mode 100755 index f40822755..5629b2900 --- a/server/tests/config.h.in +++ b/server/tests/config.h.in @@ -124,6 +124,10 @@ __wrap_sr_get_schema(sr_session_ctx_t *session, const char *module_name, const c fd = open(TESTS_DIR "/files/nc-notifications.yin", O_RDONLY); } else if (!strcmp(module_name, "test-notif")) { fd = open(TESTS_DIR "/files/test-notif.yin", O_RDONLY); + } else if (!strcmp(module_name, "test-feature")) { + fd = open(TESTS_DIR "/files/test-feature.yin", O_RDONLY); + } else if (!strcmp(module_name, "test-feature-consumer")) { + fd = open(TESTS_DIR "/files/test-feature-consumer.yin", O_RDONLY); } else { return SR_ERR_NOT_FOUND; } diff --git a/server/tests/files/test-feature-consumer.yin b/server/tests/files/test-feature-consumer.yin new file mode 100755 index 000000000..406228f2e --- /dev/null +++ b/server/tests/files/test-feature-consumer.yin @@ -0,0 +1,28 @@ + + + + + + + + + + Initial revision. + + + None. + + + + + + + + + + + + diff --git a/server/tests/files/test-feature.yin b/server/tests/files/test-feature.yin new file mode 100755 index 000000000..6a8c0ea33 --- /dev/null +++ b/server/tests/files/test-feature.yin @@ -0,0 +1,20 @@ + + + + + + + Initial revision. + + + None. + + + + + A controlling feature + + + diff --git a/server/tests/test_edit_get_config.c b/server/tests/test_edit_get_config.c old mode 100644 new mode 100755 index 1c98d5527..98bf8cfa5 --- a/server/tests/test_edit_get_config.c +++ b/server/tests/test_edit_get_config.c @@ -72,9 +72,9 @@ __wrap_sr_list_schemas(sr_session_ctx_t *session, sr_schema_t **schemas, size_t { (void)session; - *schema_cnt = 4; + *schema_cnt = 6; - *schemas = calloc(4, sizeof **schemas); + *schemas = calloc(6, sizeof **schemas); (*schemas)[0].module_name = strdup("ietf-netconf-server"); (*schemas)[0].installed = 1; @@ -107,6 +107,26 @@ __wrap_sr_list_schemas(sr_session_ctx_t *session, sr_schema_t **schemas, size_t (*schemas)[3].revision.file_path_yin = strdup(TESTS_DIR"/files/iana-if-type.yin"); (*schemas)[3].installed = 1; + (*schemas)[4].module_name = strdup("test-feature-consumer"); + (*schemas)[4].ns = strdup("urn:ietf:params:xml:ns:yang:test-feature-consumer"); + (*schemas)[4].prefix = strdup("tfc"); + (*schemas)[4].revision.revision = strdup("2018-05-18"); + (*schemas)[4].revision.file_path_yin = strdup(TESTS_DIR"/files/test-feature-consumer.yin"); + (*schemas)[4].enabled_features = malloc(sizeof(char *)); + (*schemas)[4].enabled_features[0] = strdup("dependent-feature"); + (*schemas)[4].enabled_feature_cnt = 1; + (*schemas)[4].installed = 1; + + (*schemas)[5].module_name = strdup("test-feature"); + (*schemas)[5].ns = strdup("urn:ietf:params:xml:ns:yang:test-feature"); + (*schemas)[5].prefix = strdup("tf"); + (*schemas)[5].revision.revision = strdup("2018-05-18"); + (*schemas)[5].revision.file_path_yin = strdup(TESTS_DIR"/files/test-feature.yin"); + (*schemas)[5].enabled_features = malloc(sizeof(char *)); + (*schemas)[5].enabled_features[0] = strdup("controlling-feature"); + (*schemas)[5].enabled_feature_cnt = 1; + (*schemas)[5].installed = 1; + return SR_ERR_OK; } @@ -208,7 +228,7 @@ __wrap_sr_get_item_next(sr_session_ctx_t *session, sr_val_iter_t *iter, sr_val_t char *path; (void)session; - if (!strcmp(xpath, "/ietf-interfaces:*//.")) { + if (!strcmp(xpath, "/ietf-interfaces:*//.") || !strcmp(xpath, "/test-feature-consumer:*//.")) { if (!ietf_if_set) { ietf_if_set = lyd_find_path(data, xpath); } @@ -1110,7 +1130,7 @@ test_edit_create3(void **state) } static void -test_edit_merge(void **state) +test_edit_merge1(void **state) { (void)state; /* unused */ const char *get_config_rpc = @@ -1316,6 +1336,135 @@ test_edit_merge(void **state) test_read(p_in, get_config_rpl, __LINE__); } +static void +test_edit_merge2(void **state) +{ + (void)state; /* unused */ + const char *get_config_rpc = + "" + "" + "" + "" + "" + "" + ""; + const char *get_config_rpl = + "" + "" +"" + "" + "iface2" + "iface2 dsc" + "ianaift:softwareLoopback" + "false" + "disabled" + "" + "
" + "10.0.0.5" + "255.0.0.0" + "
" + "
" + "172.0.0.5" + "16" + "
" + "" + "10.0.0.1" + "01:34:56:78:9a:bc:de:fa" + "" + "
" + "" + "
" + "2001:abcd:ef01:2345:6789:0:1:5" + "64" + "
" + "" + "2001:abcd:ef01:2345:6789:0:1:1" + "01:34:56:78:9a:bc:de:fa" + "" + "100" + "" + "true" + "false" + "600" + "300" + "" + "
" + "
" + "" + "iface1" + "iface1 dsc" + "ianaift:ethernetCsmacd" + "true" + "" + "true" + "true" + "68" + "
" + "10.0.0.1" + "255.0.0.0" + "
" + "
" + "172.0.0.1" + "16" + "
" + "" + "10.0.0.2" + "01:34:56:78:9a:bc:de:f0" + "" + "
" + "" + "true" + "false" + "1280" + "
" + "2001:abcd:ef01:2345:6789:0:1:1" + "64" + "
" + "" + "2001:abcd:ef01:2345:6789:0:1:2" + "01:34:56:78:9a:bc:de:f0" + "" + "52" + "" + "true" + "false" + "600" + "300" + "" + "
" + "disabled" + "
" +"
" +"" + "green" +"" + "
" + "
"; + const char *edit_rpc = + "" + "" + "" + "" + "" + "" +"" + "green" +"" + "" + "" + ""; + const char *edit_rpl = + "" + "" + ""; + + test_write(p_out, edit_rpc, __LINE__); + test_read(p_in, edit_rpl, __LINE__); + + test_write(p_out, get_config_rpc, __LINE__); + test_read(p_in, get_config_rpl, __LINE__); +} + static void test_startstop(void **state) { @@ -1335,7 +1484,8 @@ main(void) cmocka_unit_test(test_edit_create1), cmocka_unit_test(test_edit_create2), cmocka_unit_test(test_edit_create3), - cmocka_unit_test(test_edit_merge), + cmocka_unit_test(test_edit_merge1), + cmocka_unit_test(test_edit_merge2), cmocka_unit_test_teardown(test_startstop, np_stop), }; From e9c40d4282489396ee3801755638713abb3ae29f Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Mon, 21 May 2018 10:03:21 +0200 Subject: [PATCH 45/87] server CHANGE display verb level in stderr messages --- server/log.c | 86 +++++++++++++++++++++++++++++++++++++-------------- server/log.h | 9 ++++-- server/main.c | 5 +-- 3 files changed, 72 insertions(+), 28 deletions(-) diff --git a/server/log.c b/server/log.c index 42d1a7b51..7ce431779 100644 --- a/server/log.c +++ b/server/log.c @@ -11,11 +11,13 @@ * * https://opensource.org/licenses/BSD-3-Clause */ +#define _DEFAULT_SOURCE #include #include #include #include +#include #include #include #include @@ -25,20 +27,10 @@ #include #include -/** - * @brief libnetconf verbose level variable - */ volatile uint8_t np2_verbose_level; - -/** - * @brief libssh verbose level variable - */ -volatile uint8_t np2_libssh_verbose_level; - -/** - * @brief libsysrepo verbose level variable - */ -volatile uint8_t np2_sr_verbose_level; +uint8_t np2_libssh_verbose_level; +uint8_t np2_sr_verbose_level; +uint8_t np2_stderr_log; enum ERR_SOURCE { ERRS_NETOPEER, @@ -107,6 +99,49 @@ np2_err_location(void) return e; } +static void +np2log(int priority, const char *fmt, ...) +{ + char *format; + va_list ap; + + va_start(ap, fmt); + vsyslog(priority, fmt, ap); + va_end(ap); + + if (np2_stderr_log) { + format = malloc(9 + strlen(fmt) + 2); + if (!format) { + fprintf(stderr, "ERROR: Memory allocation failed (%s:%d)", __FILE__, __LINE__); + return; + } + + switch (priority) { + case LOG_ERR: + sprintf(format, "ERROR: %s\n", fmt); + break; + case LOG_WARNING: + sprintf(format, "WARNING: %s\n", fmt); + break; + case LOG_INFO: + sprintf(format, "VERBOSE: %s\n", fmt); + break; + case LOG_DEBUG: + sprintf(format, "DEBUG: %s\n", fmt); + break; + default: + sprintf(format, "UNKNOWN: %s\n", fmt); + break; + } + + va_start(ap, fmt); + vfprintf(stderr, format, ap); + va_end(ap); + + free(format); + } +} + /** * @brief printer callback for libnetconf2 */ @@ -114,6 +149,7 @@ void np2log_clb_nc2(NC_VERB_LEVEL level, const char *msg) { struct np2err *e; + int priority; if (level == NC_VERB_ERROR) { e = np2_err_location(); @@ -125,18 +161,20 @@ np2log_clb_nc2(NC_VERB_LEVEL level, const char *msg) switch (level) { case NC_VERB_ERROR: - syslog(LOG_ERR, "%s", msg); + priority = LOG_ERR;; break; case NC_VERB_WARNING: - syslog(LOG_WARNING, "%s", msg); + priority = LOG_WARNING; break; case NC_VERB_VERBOSE: - syslog(LOG_INFO, "%s", msg); + priority = LOG_INFO; break; case NC_VERB_DEBUG: - syslog(LOG_DEBUG, "%s", msg); + priority = LOG_DEBUG; break; } + + np2log(priority, msg); } /** @@ -145,21 +183,21 @@ np2log_clb_nc2(NC_VERB_LEVEL level, const char *msg) void np2log_clb_ly(LY_LOG_LEVEL level, const char *msg, const char *path) { - int facility; + int priority; struct np2err *e; switch (level) { case LY_LLERR: - facility = LOG_ERR; + priority = LOG_ERR; break; case LY_LLWRN: - facility = LOG_WARNING; + priority = LOG_WARNING; break; case LY_LLVRB: - facility = LOG_INFO; + priority = LOG_INFO; break; case LY_LLDBG: - facility = LOG_DEBUG; + priority = LOG_DEBUG; break; default: /* silent, just to cover enum, shouldn't be here in real world */ @@ -174,9 +212,9 @@ np2log_clb_ly(LY_LOG_LEVEL level, const char *msg, const char *path) } if (path) { - syslog(facility, "%s (%s)", msg, path); + np2log(priority, "%s (%s)", msg, path); } else { - syslog(facility, "%s", msg); + np2log(priority, msg); } } diff --git a/server/log.h b/server/log.h index e125e2a02..c8c2ba3a3 100644 --- a/server/log.h +++ b/server/log.h @@ -27,12 +27,17 @@ extern volatile uint8_t np2_verbose_level; /** * @brief libssh verbose level variable */ -extern volatile uint8_t np2_libssh_verbose_level; +extern uint8_t np2_libssh_verbose_level; /** * @brief libsysrepo verbose level variable */ -extern volatile uint8_t np2_sr_verbose_level; +extern uint8_t np2_sr_verbose_level; + +/** + * @brief netopeer2 flag whether to print messages to stderr (only if not daemon). + */ +uint8_t np2_stderr_log; /** * @brief internal printing function, follows the levels from libnetconf2 diff --git a/server/main.c b/server/main.c index a0546e0c7..68741795b 100644 --- a/server/main.c +++ b/server/main.c @@ -1163,7 +1163,8 @@ main(int argc, char *argv[]) pthread_attr_t thread_attr; /* until daemonized, write messages to both syslog and stderr */ - openlog("netopeer2-server", LOG_PID | LOG_PERROR, LOG_DAEMON); + openlog("netopeer2-server", LOG_PID, LOG_DAEMON); + np2_stderr_log = 1; /* process command line options */ while ((c = getopt(argc, argv, OPTSTRING)) != -1) { @@ -1273,7 +1274,7 @@ main(int argc, char *argv[]) } /* from now print only to syslog, not stderr */ - openlog("netopeer2-server", LOG_PID, LOG_DAEMON); + np2_stderr_log = 0; } /* make sure we are the only instance - lock the PID file and write the PID */ From 6cb1612f612003648b5b9bea90ff9dec8fb6b645 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Mon, 21 May 2018 10:45:13 +0200 Subject: [PATCH 46/87] server OPTIMIZE formatting and optimizations Refs #248 --- server/main.c | 63 ++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/server/main.c b/server/main.c index 14bd0999f..a90512a3f 100644 --- a/server/main.c +++ b/server/main.c @@ -755,6 +755,7 @@ np2srv_init_schemas(void) const struct lys_module *mod; sr_schema_t *schemas = NULL; size_t schema_count, i, j; + int ly_lo; size_t module_feature_count = 0; struct mod_feat { @@ -813,10 +814,18 @@ np2srv_init_schemas(void) } ly_ctx_set_module_imp_clb(np2srv.ly_ctx, np2srv_ly_import_clb, NULL); + /* determine the count of module/features present */ + module_feature_count = 0; + for (i = 0; i < schema_count; i++) { + module_feature_count += schemas[i].enabled_feature_cnt; + } + /* prepare data storage to keep module/feature enable status */ + mod_feat_array = calloc(module_feature_count, sizeof *mod_feat_array); + mod_feat_array_index = 0; + /* 1) use modules from sysrepo */ for (i = 0; i < schema_count; i++) { data = NULL; - mod = NULL; VRB("Loading schema \"%s%s%s\" from sysrepo.", schemas[i].module_name, schemas[i].revision.revision ? "@" : "", schemas[i].revision.revision ? schemas[i].revision.revision : ""); if ((mod = ly_ctx_get_module(np2srv.ly_ctx, schemas[i].module_name, schemas[i].revision.revision, 0))) { @@ -833,30 +842,25 @@ np2srv_init_schemas(void) mod = lys_parse_mem(np2srv.ly_ctx, data, LYS_IN_YIN); free(data); } - } - /* determine the count of module/features present */ - module_feature_count = 0; - for (i=0; i < schema_count; i++) { - module_feature_count += schemas[i].enabled_feature_cnt; - } - /* prepare data storage to keep module/feature enable status */ - mod_feat_array = calloc(module_feature_count, sizeof (struct mod_feat)); - mod_feat_array_index = 0; + if (mod) { + /* set RPC and Notifications callbacks */ + np2srv_module_assign_clbs(mod); - /* loop back through the modules now that they should be loaded and enable features */ - for (i = 0; i < schema_count; i++) { - if ((mod = ly_ctx_get_module(np2srv.ly_ctx, schemas[i].module_name, schemas[i].revision.revision, 0))) { - /* set features according to sysrepo */ + /* set features according to sysrepo (silent errors, there can be some other dependent features not enabled yet) */ + ly_lo = ly_log_options(0); for (j = 0; j < schemas[i].enabled_feature_cnt; ++j) { - /* if lys_features_enable fail, record the mod_feat for retry otherwise store a null */ - if (lys_features_enable(mod, schemas[i].enabled_features[j]) == EXIT_FAILURE) { + /* if lys_features_enable fail (silently), record the mod_feat for retry otherwise store NULL */ + + if (lys_features_enable(mod, schemas[i].enabled_features[j])) { /* store away info related to feature that did not enable on first pass */ mod_feat_array[mod_feat_array_index].mod = mod; mod_feat_array[mod_feat_array_index].enabled_feature = schemas[i].enabled_features[j]; } mod_feat_array_index++; } + /* restore libyang logging */ + ly_log_options(ly_lo); } else { WRN("Getting %s%s%s schema from sysrepo failed, data from this module won't be available.", schemas[i].module_name, schemas[i].revision.revision ? "@" : "", @@ -867,15 +871,14 @@ np2srv_init_schemas(void) /* we may be able to get features enabled now that others are enabled so we will run through our stored module_features and retry the ones on our list we will continue until a pass through the array doesn't indicate progress */ - making_progress = true; - while(making_progress) { + ly_lo = ly_log_options(0); + making_progress = false; + while (making_progress) { making_progress = false; for (i = 0; i < module_feature_count; i++) { - if (mod_feat_array[i].mod != NULL) { - if ((lys_features_enable(mod_feat_array[i].mod, mod_feat_array[i].enabled_feature)) == EXIT_SUCCESS) { + if (mod_feat_array[i].mod) { + if (!lys_features_enable(mod_feat_array[i].mod, mod_feat_array[i].enabled_feature)) { /* feature enabled, remove from list and set making_progress TRUE */ - VRB("Retry feature enable successful for \"%s\" in \"%s\".", - mod_feat_array[i].enabled_feature, mod_feat_array[i].mod->name); making_progress = true; mod_feat_array[i].mod = NULL; mod_feat_array[i].enabled_feature = NULL; @@ -883,26 +886,18 @@ np2srv_init_schemas(void) } } } + ly_log_options(ly_lo); - /* now pass through the mod_feat_array and report ERR on any remaining entries + /* now pass through the mod_feat_array and report errors on any remaining entries as they are not enabled */ for (i = 0; i < module_feature_count; i++) { - if (mod_feat_array[i].mod != NULL) { - /* this module feature never enabled */ - ERR("Retry feature enable failed for \"%s\" in \"%s\".", - mod_feat_array[i].enabled_feature, mod_feat_array[i].mod->name); + if (mod_feat_array[i].mod) { + lys_features_enable(mod_feat_array[i].mod, mod_feat_array[i].enabled_feature); } } free(mod_feat_array); - for (i = 0; i < schema_count; i++) { - if ((mod = ly_ctx_get_module(np2srv.ly_ctx, schemas[i].module_name, schemas[i].revision.revision, 0))) { - /* setRPC and Notifications callbacks */ - np2srv_module_assign_clbs(mod); - } - } - ly_ctx_set_module_imp_clb(np2srv.ly_ctx, np2srv_ly_import_clb, NULL); sr_free_schemas(schemas, schema_count); schemas = NULL; From 3c98c2f88a90f6f276d5aeed536ecc9dc4c9c764 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Mon, 21 May 2018 10:46:00 +0200 Subject: [PATCH 47/87] server VERSION bump to version 0.5.13 --- server/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 15ba59621..64c5c5c0b 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -13,7 +13,7 @@ if(NOT UNIX) endif() # set version -set(NP2SRV_VERSION 0.5.12) +set(NP2SRV_VERSION 0.5.13) # set default build type if not specified by user if(NOT CMAKE_BUILD_TYPE) From 62c408e4fb03082e17a160c7dd9b594b2e2c91b9 Mon Sep 17 00:00:00 2001 From: Andrew Langefeld Date: Mon, 21 May 2018 13:39:40 -0500 Subject: [PATCH 48/87] Fix longer feature dep chains This is a follow-up to pull request #248, which fixed a problem enabling a feature that depended on a feature in a subsequent schema that had not yet been enabled. The follow-up optimizations in commit 6cb1612 inadvertently changed the desired behavior, in that a feature dependency chain more than two features deep will no longer be enabled properly. The problem is that the `making_progress` loop in main.c line 876 is never entered. I've included a change to the unit test from #248 that demonstrates a feature dependency chain three features deep, instead of the original test which was only two features deep. --- server/main.c | 2 +- server/tests/config.h.in | 10 +++-- .../{test-feature.yin => test-feature-a.yin} | 12 +++--- server/tests/files/test-feature-b.yin | 22 +++++++++++ ...eature-consumer.yin => test-feature-c.yin} | 18 ++++----- server/tests/test_edit_get_config.c | 38 ++++++++++++------- 6 files changed, 68 insertions(+), 34 deletions(-) rename server/tests/files/{test-feature.yin => test-feature-a.yin} (56%) create mode 100644 server/tests/files/test-feature-b.yin rename server/tests/files/{test-feature-consumer.yin => test-feature-c.yin} (51%) diff --git a/server/main.c b/server/main.c index a90512a3f..25c57b4e6 100644 --- a/server/main.c +++ b/server/main.c @@ -872,7 +872,7 @@ np2srv_init_schemas(void) run through our stored module_features and retry the ones on our list we will continue until a pass through the array doesn't indicate progress */ ly_lo = ly_log_options(0); - making_progress = false; + making_progress = true; while (making_progress) { making_progress = false; for (i = 0; i < module_feature_count; i++) { diff --git a/server/tests/config.h.in b/server/tests/config.h.in index 5629b2900..e36940b6a 100755 --- a/server/tests/config.h.in +++ b/server/tests/config.h.in @@ -124,10 +124,12 @@ __wrap_sr_get_schema(sr_session_ctx_t *session, const char *module_name, const c fd = open(TESTS_DIR "/files/nc-notifications.yin", O_RDONLY); } else if (!strcmp(module_name, "test-notif")) { fd = open(TESTS_DIR "/files/test-notif.yin", O_RDONLY); - } else if (!strcmp(module_name, "test-feature")) { - fd = open(TESTS_DIR "/files/test-feature.yin", O_RDONLY); - } else if (!strcmp(module_name, "test-feature-consumer")) { - fd = open(TESTS_DIR "/files/test-feature-consumer.yin", O_RDONLY); + } else if (!strcmp(module_name, "test-feature-a")) { + fd = open(TESTS_DIR "/files/test-feature-a.yin", O_RDONLY); + } else if (!strcmp(module_name, "test-feature-b")) { + fd = open(TESTS_DIR "/files/test-feature-b.yin", O_RDONLY); + } else if (!strcmp(module_name, "test-feature-c")) { + fd = open(TESTS_DIR "/files/test-feature-c.yin", O_RDONLY); } else { return SR_ERR_NOT_FOUND; } diff --git a/server/tests/files/test-feature.yin b/server/tests/files/test-feature-a.yin similarity index 56% rename from server/tests/files/test-feature.yin rename to server/tests/files/test-feature-a.yin index 6a8c0ea33..37ecb9a6f 100755 --- a/server/tests/files/test-feature.yin +++ b/server/tests/files/test-feature-a.yin @@ -1,9 +1,9 @@ - - - + xmlns:tfa="urn:ietf:params:xml:ns:yang:test-feature-a"> + + Initial revision. @@ -12,9 +12,9 @@ None. - + - A controlling feature + Test feature A diff --git a/server/tests/files/test-feature-b.yin b/server/tests/files/test-feature-b.yin new file mode 100644 index 000000000..09e4171e5 --- /dev/null +++ b/server/tests/files/test-feature-b.yin @@ -0,0 +1,22 @@ + + + + + + + + + + Initial revision. + + + None. + + + + + + diff --git a/server/tests/files/test-feature-consumer.yin b/server/tests/files/test-feature-c.yin similarity index 51% rename from server/tests/files/test-feature-consumer.yin rename to server/tests/files/test-feature-c.yin index 406228f2e..929d76e7a 100755 --- a/server/tests/files/test-feature-consumer.yin +++ b/server/tests/files/test-feature-c.yin @@ -1,12 +1,12 @@ - - + xmlns:tfc="urn:ietf:params:xml:ns:yang:test-feature-c" + xmlns:tfb="urn:ietf:params:xml:ns:yang:test-feature-b"> + - - + + @@ -16,11 +16,11 @@ None. - - + + - + diff --git a/server/tests/test_edit_get_config.c b/server/tests/test_edit_get_config.c index 98bf8cfa5..75d46b204 100755 --- a/server/tests/test_edit_get_config.c +++ b/server/tests/test_edit_get_config.c @@ -72,9 +72,9 @@ __wrap_sr_list_schemas(sr_session_ctx_t *session, sr_schema_t **schemas, size_t { (void)session; - *schema_cnt = 6; + *schema_cnt = 7; - *schemas = calloc(6, sizeof **schemas); + *schemas = calloc(*schema_cnt, sizeof **schemas); (*schemas)[0].module_name = strdup("ietf-netconf-server"); (*schemas)[0].installed = 1; @@ -107,26 +107,36 @@ __wrap_sr_list_schemas(sr_session_ctx_t *session, sr_schema_t **schemas, size_t (*schemas)[3].revision.file_path_yin = strdup(TESTS_DIR"/files/iana-if-type.yin"); (*schemas)[3].installed = 1; - (*schemas)[4].module_name = strdup("test-feature-consumer"); - (*schemas)[4].ns = strdup("urn:ietf:params:xml:ns:yang:test-feature-consumer"); + (*schemas)[4].module_name = strdup("test-feature-c"); + (*schemas)[4].ns = strdup("urn:ietf:params:xml:ns:yang:test-feature-c"); (*schemas)[4].prefix = strdup("tfc"); (*schemas)[4].revision.revision = strdup("2018-05-18"); - (*schemas)[4].revision.file_path_yin = strdup(TESTS_DIR"/files/test-feature-consumer.yin"); + (*schemas)[4].revision.file_path_yin = strdup(TESTS_DIR"/files/test-feature-c.yin"); (*schemas)[4].enabled_features = malloc(sizeof(char *)); - (*schemas)[4].enabled_features[0] = strdup("dependent-feature"); + (*schemas)[4].enabled_features[0] = strdup("test-feature-c"); (*schemas)[4].enabled_feature_cnt = 1; (*schemas)[4].installed = 1; - (*schemas)[5].module_name = strdup("test-feature"); - (*schemas)[5].ns = strdup("urn:ietf:params:xml:ns:yang:test-feature"); - (*schemas)[5].prefix = strdup("tf"); + (*schemas)[5].module_name = strdup("test-feature-b"); + (*schemas)[5].ns = strdup("urn:ietf:params:xml:ns:yang:test-feature-b"); + (*schemas)[5].prefix = strdup("tfb"); (*schemas)[5].revision.revision = strdup("2018-05-18"); - (*schemas)[5].revision.file_path_yin = strdup(TESTS_DIR"/files/test-feature.yin"); + (*schemas)[5].revision.file_path_yin = strdup(TESTS_DIR"/files/test-feature-b.yin"); (*schemas)[5].enabled_features = malloc(sizeof(char *)); - (*schemas)[5].enabled_features[0] = strdup("controlling-feature"); + (*schemas)[5].enabled_features[0] = strdup("test-feature-b"); (*schemas)[5].enabled_feature_cnt = 1; (*schemas)[5].installed = 1; + (*schemas)[6].module_name = strdup("test-feature-a"); + (*schemas)[6].ns = strdup("urn:ietf:params:xml:ns:yang:test-feature-a"); + (*schemas)[6].prefix = strdup("tfa"); + (*schemas)[6].revision.revision = strdup("2018-05-18"); + (*schemas)[6].revision.file_path_yin = strdup(TESTS_DIR"/files/test-feature-a.yin"); + (*schemas)[6].enabled_features = malloc(sizeof(char *)); + (*schemas)[6].enabled_features[0] = strdup("test-feature-a"); + (*schemas)[6].enabled_feature_cnt = 1; + (*schemas)[6].installed = 1; + return SR_ERR_OK; } @@ -228,7 +238,7 @@ __wrap_sr_get_item_next(sr_session_ctx_t *session, sr_val_iter_t *iter, sr_val_t char *path; (void)session; - if (!strcmp(xpath, "/ietf-interfaces:*//.") || !strcmp(xpath, "/test-feature-consumer:*//.")) { + if (!strcmp(xpath, "/ietf-interfaces:*//.") || !strcmp(xpath, "/test-feature-c:*//.")) { if (!ietf_if_set) { ietf_if_set = lyd_find_path(data, xpath); } @@ -1435,7 +1445,7 @@ test_edit_merge2(void **state) "disabled" "
" "
" -"" +"" "green" "" "" @@ -1447,7 +1457,7 @@ test_edit_merge2(void **state) "" "" "" -"" +"" "green" "" "" From 2d02d332711f9c02845e9ea91b06f817200e8c24 Mon Sep 17 00:00:00 2001 From: Andrew Langefeld Date: Mon, 21 May 2018 13:56:17 -0500 Subject: [PATCH 49/87] Change to do .. while() loop --- server/main.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/server/main.c b/server/main.c index 25c57b4e6..72c72dc3f 100644 --- a/server/main.c +++ b/server/main.c @@ -872,8 +872,7 @@ np2srv_init_schemas(void) run through our stored module_features and retry the ones on our list we will continue until a pass through the array doesn't indicate progress */ ly_lo = ly_log_options(0); - making_progress = true; - while (making_progress) { + do { making_progress = false; for (i = 0; i < module_feature_count; i++) { if (mod_feat_array[i].mod) { @@ -885,7 +884,7 @@ np2srv_init_schemas(void) } } } - } + } while (making_progress); ly_log_options(ly_lo); /* now pass through the mod_feat_array and report errors on any remaining entries From 6b5dda7e69c0a6ee180f8be1f9495cabd1552b61 Mon Sep 17 00:00:00 2001 From: Robin Jarry Date: Fri, 16 Feb 2018 14:29:54 +0100 Subject: [PATCH 50/87] server: ignore if host key not found at build time If /etc/ssh/ssh_host_rsa_key is not found during the cmake config step, there is a fatal error which makes the build fail: -- Server configuration off, default SSH host key will be used. CMake Error at CMakeLists.txt:71 (message): Host key "/etc/ssh/ssh_host_rsa_key" not found, rerun cmake and set DEFAULT_HOST_KEY manually to point to an RSA SSH key. DEFAULT_HOST_KEY is only a default path used at runtime when no other path is specified. If a file actually exists here, it will not be read during the build (moreover, the default path is only readable by root anyway, and building as root is considered bad). The machine where the server will run is not necessarily the one where the build is done. If the file is not found at runtime, there will be an explicit error. Do not check if the file exists at compile time. Signed-off-by: Robin Jarry --- server/CMakeLists.txt | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 64c5c5c0b..d05fd12f6 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -62,14 +62,7 @@ endif() # set default SSH key if (KEYSTORED_KEYS_DIR STREQUAL "none") - message(STATUS "Server configuration off, default SSH host key will be used.") - # if (EXISTS) succeeds only if the file is readable, we do not care about that - execute_process(COMMAND ls "${DEFAULT_HOST_KEY}" RESULT_VARIABLE RET OUTPUT_QUIET ERROR_QUIET) - if (NOT RET) - message(STATUS "Default host key set to \"${DEFAULT_HOST_KEY}\".") - else() - message(FATAL_ERROR "Host key \"${DEFAULT_HOST_KEY}\" not found, rerun cmake and set DEFAULT_HOST_KEY manually to point to an RSA SSH key.") - endif() + message(STATUS "Server configuration off, default SSH host key will be used: \"${DEFAULT_HOST_KEY}\".") endif() # check that lnc2 supports np2srv thread count From d78d1b9e8ac46d7eaf5e2b9344664b3dac947351 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kundr=C3=A1t?= Date: Tue, 22 May 2018 19:43:47 +0200 Subject: [PATCH 51/87] cmake: Do not clutter up the source dir during build As usual, all build artefacts should go outside of the source tree. --- cli/CMakeLists.txt | 3 ++- keystored/CMakeLists.txt | 3 ++- server/CMakeLists.txt | 3 ++- server/tests/CMakeLists.txt | 2 +- server/tests/test_close_session.c | 4 ++-- server/tests/test_copy_config.c | 4 ++-- server/tests/test_edit_get_config.c | 4 ++-- server/tests/test_generic.c | 4 ++-- server/tests/test_get.c | 4 ++-- server/tests/test_kill.c | 4 ++-- server/tests/test_notif.c | 4 ++-- server/tests/test_un_lock.c | 4 ++-- 12 files changed, 23 insertions(+), 20 deletions(-) diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt index e0a2a3d09..f248c45c3 100644 --- a/cli/CMakeLists.txt +++ b/cli/CMakeLists.txt @@ -22,7 +22,8 @@ set(CMAKE_C_FLAGS_DEBUG "-g -O0") # set version set(NP2CLI_VERSION 2.0.45) -configure_file("${PROJECT_SOURCE_DIR}/version.h.in" "${PROJECT_SOURCE_DIR}/version.h" ESCAPE_QUOTES @ONLY) +configure_file("${PROJECT_SOURCE_DIR}/version.h.in" "${PROJECT_BINARY_DIR}/version.h" ESCAPE_QUOTES @ONLY) +include_directories(${PROJECT_BINARY_DIR}) # source files set(srcs diff --git a/keystored/CMakeLists.txt b/keystored/CMakeLists.txt index 48ee2e6de..c7bd183e2 100644 --- a/keystored/CMakeLists.txt +++ b/keystored/CMakeLists.txt @@ -34,7 +34,8 @@ if (NOT OPENSSL_EXECUTABLE) endif() endif() -configure_file("${PROJECT_SOURCE_DIR}/config.h.in" "${PROJECT_SOURCE_DIR}/config.h" ESCAPE_QUOTES @ONLY) +configure_file("${PROJECT_SOURCE_DIR}/config.h.in" "${PROJECT_BINARY_DIR}/config.h" ESCAPE_QUOTES @ONLY) +include_directories(${PROJECT_BINARY_DIR}) # keystored plugin add_library(keystored SHARED keystored.c) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 64c5c5c0b..8dbb9fa8d 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -243,7 +243,8 @@ if (ENABLE_CONFIGURATION) endif()") endif() -configure_file("${PROJECT_SOURCE_DIR}/config.h.in" "${PROJECT_SOURCE_DIR}/config.h" ESCAPE_QUOTES @ONLY) +configure_file("${PROJECT_SOURCE_DIR}/config.h.in" "${PROJECT_BINARY_DIR}/config.h" ESCAPE_QUOTES @ONLY) +include_directories(${PROJECT_BINARY_DIR}) # clean cmake cache add_custom_target(cleancache diff --git a/server/tests/CMakeLists.txt b/server/tests/CMakeLists.txt index 54a441614..78d31806c 100644 --- a/server/tests/CMakeLists.txt +++ b/server/tests/CMakeLists.txt @@ -74,7 +74,7 @@ foreach(test_name IN LISTS tests) add_test(NAME ${test_name} COMMAND $) endforeach(test_name) -configure_file("${PROJECT_SOURCE_DIR}/tests/config.h.in" "${PROJECT_SOURCE_DIR}/tests/config.h" ESCAPE_QUOTES @ONLY) +configure_file("${PROJECT_SOURCE_DIR}/tests/config.h.in" "${PROJECT_BINARY_DIR}/tests/config.h" ESCAPE_QUOTES @ONLY) if(ENABLE_VALGRIND_TESTS) find_program(valgrind_FOUND valgrind) diff --git a/server/tests/test_close_session.c b/server/tests/test_close_session.c index d0c880bb1..a9be228d8 100644 --- a/server/tests/test_close_session.c +++ b/server/tests/test_close_session.c @@ -23,10 +23,10 @@ #include #include -#include "config.h" +#include "tests/config.h" #define main server_main -#include "../config.h" +#include "config.h" #undef NP2SRV_PIDFILE #define NP2SRV_PIDFILE "/tmp/test_np2srv.pid" diff --git a/server/tests/test_copy_config.c b/server/tests/test_copy_config.c index bbab06a05..ab56673af 100644 --- a/server/tests/test_copy_config.c +++ b/server/tests/test_copy_config.c @@ -29,10 +29,10 @@ #include #include -#include "config.h" +#include "tests/config.h" #define main server_main -#include "../config.h" +#include "config.h" #undef NP2SRV_PIDFILE #define NP2SRV_PIDFILE "/tmp/test_np2srv.pid" diff --git a/server/tests/test_edit_get_config.c b/server/tests/test_edit_get_config.c index 75d46b204..a4dbd31b8 100755 --- a/server/tests/test_edit_get_config.c +++ b/server/tests/test_edit_get_config.c @@ -29,10 +29,10 @@ #include #include -#include "config.h" +#include "tests/config.h" #define main server_main -#include "../config.h" +#include "config.h" #undef NP2SRV_PIDFILE #define NP2SRV_PIDFILE "/tmp/test_np2srv.pid" diff --git a/server/tests/test_generic.c b/server/tests/test_generic.c index c730c58c5..7bff062f5 100644 --- a/server/tests/test_generic.c +++ b/server/tests/test_generic.c @@ -24,10 +24,10 @@ #include #include -#include "config.h" +#include "tests/config.h" #define main server_main -#include "../config.h" +#include "config.h" #undef NP2SRV_PIDFILE #define NP2SRV_PIDFILE "/tmp/test_np2srv.pid" diff --git a/server/tests/test_get.c b/server/tests/test_get.c index 3fae2809a..5ab602e87 100644 --- a/server/tests/test_get.c +++ b/server/tests/test_get.c @@ -24,10 +24,10 @@ #include #include -#include "config.h" +#include "tests/config.h" #define main server_main -#include "../config.h" +#include "config.h" #undef NP2SRV_PIDFILE #define NP2SRV_PIDFILE "/tmp/test_np2srv.pid" diff --git a/server/tests/test_kill.c b/server/tests/test_kill.c index 3dda413a5..c3b03a8a0 100644 --- a/server/tests/test_kill.c +++ b/server/tests/test_kill.c @@ -23,10 +23,10 @@ #include #include -#include "config.h" +#include "tests/config.h" #define main server_main -#include "../config.h" +#include "config.h" #undef NP2SRV_PIDFILE #define NP2SRV_PIDFILE "/tmp/test_np2srv.pid" diff --git a/server/tests/test_notif.c b/server/tests/test_notif.c index 53da41973..8b7deb24e 100644 --- a/server/tests/test_notif.c +++ b/server/tests/test_notif.c @@ -27,10 +27,10 @@ #include #include -#include "config.h" +#include "tests/config.h" #define main server_main -#include "../config.h" +#include "config.h" #undef NP2SRV_PIDFILE #define NP2SRV_PIDFILE "/tmp/test_np2srv.pid" diff --git a/server/tests/test_un_lock.c b/server/tests/test_un_lock.c index 699632c9b..a3fe0e624 100644 --- a/server/tests/test_un_lock.c +++ b/server/tests/test_un_lock.c @@ -24,10 +24,10 @@ #include #include -#include "config.h" +#include "tests/config.h" #define main server_main -#include "../config.h" +#include "config.h" #undef NP2SRV_PIDFILE #define NP2SRV_PIDFILE "/tmp/test_np2srv.pid" From f77902020b6a6efe435940c4b2d867bc02ca889e Mon Sep 17 00:00:00 2001 From: Robin Jarry Date: Wed, 23 May 2018 09:49:18 +0200 Subject: [PATCH 52/87] ietf_system: do not error on unsupported fields When modifying ietf-system/authentication/user items on other fields than authorized-key, there is an error: Path "/ietf-system:system/authentication/user[name='root']/password" modified. Internal error (.../server/ietf_system.c:79) Since netopeer does not care about these fields, it should ignore them. Signed-off-by: Robin Jarry --- server/ietf_system.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/server/ietf_system.c b/server/ietf_system.c index 9e2dfdfb9..50cc59b31 100644 --- a/server/ietf_system.c +++ b/server/ietf_system.c @@ -37,8 +37,8 @@ subtree_change_resolve(sr_session_ctx_t *srs, sr_change_oper_t sr_oper, sr_val_t xpath = (sr_old_val ? sr_old_val->xpath : sr_new_val->xpath); if (strncmp(xpath, "/ietf-system:system/authentication/user[name=", 45)) { - EINT; - return -1; + /* we only care about changes on users */ + return 0; } switch (sr_oper) { @@ -70,14 +70,9 @@ subtree_change_resolve(sr_session_ctx_t *srs, sr_change_oper_t sr_oper, sr_val_t list1_key = strndup(xpath, key_end - xpath); xpath = key_end + 1; - if (!strcmp(xpath, "]/name")) { - /* don't care */ - rc = 0; - goto cleanup; - } if (strncmp(xpath, "]/authorized-key[name=", 22)) { - EINT; - rc = -1; + /* other field than authorized-key, don't care */ + rc = 0; goto cleanup; } xpath += 22; From 0cd952202d91d4f000d067bd363411a1621e80ea Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Wed, 23 May 2018 13:25:19 +0200 Subject: [PATCH 53/87] server BUGFIX handle concurrent sysrepo operations When they return SR_ERR_LOCKED, try again. Refs sysrepo/sysrepo#1133 --- server/config.h.in | 8 ++++++++ server/operations.c | 42 ++++++++++++++++++++++++++++++++++-------- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/server/config.h.in b/server/config.h.in index 5239292ff..fbb9f4202 100644 --- a/server/config.h.in +++ b/server/config.h.in @@ -44,4 +44,12 @@ */ #cmakedefine HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP 1 +/** @brief timeout in ms for retrying certain sysrepo operations (subscriptions and commit) in case 2 same operations collide + */ +#define NP2SRV_SR_LOCKED_TIMEOUT 10 + +/** @brief number of retries for certain sysrepo operations in case 2 same operations collide + */ +#define NP2SRV_SR_LOCKED_RETRIES 3 + #endif /* NP2SRV_CONFIG_H_ */ diff --git a/server/operations.c b/server/operations.c index 421d81abb..95f14e5f4 100644 --- a/server/operations.c +++ b/server/operations.c @@ -13,10 +13,12 @@ */ #define _GNU_SOURCE +#define _DEFAULT_SOURCE #include #include #include +#include #include #include #include @@ -834,13 +836,19 @@ int np2srv_sr_module_change_subscribe(sr_session_ctx_t *srs, const char *module_name, sr_module_change_cb callback, void *private_ctx, uint32_t priority, sr_subscr_options_t opts, sr_subscription_ctx_t **subscription, struct nc_server_reply **ereply) { - int rc = SR_ERR_DISCONNECT; + int rc = SR_ERR_DISCONNECT, retries; struct nc_server_error *e; pthread_rwlock_rdlock(&sr_lock); if (!np2srv.disconnected) { - rc = sr_module_change_subscribe(srs, module_name, callback, private_ctx, priority, opts, subscription); + for (retries = 0; retries <= NP2SRV_SR_LOCKED_RETRIES; ++retries) { + rc = sr_module_change_subscribe(srs, module_name, callback, private_ctx, priority, opts, subscription); + if (rc != SR_ERR_LOCKED) { + break; + } + usleep(NP2SRV_SR_LOCKED_TIMEOUT * 1000); + } } if (rc == SR_ERR_DISCONNECT) { @@ -885,13 +893,19 @@ int np2srv_sr_subtree_change_subscribe(sr_session_ctx_t *srs, const char *xpath, sr_subtree_change_cb callback, void *private_ctx, uint32_t priority, sr_subscr_options_t opts, sr_subscription_ctx_t **subscription, struct nc_server_reply **ereply) { - int rc = SR_ERR_DISCONNECT; + int rc = SR_ERR_DISCONNECT, retries; struct nc_server_error *e; pthread_rwlock_rdlock(&sr_lock); if (!np2srv.disconnected) { - rc = sr_subtree_change_subscribe(srs, xpath, callback, private_ctx, priority, opts, subscription); + for (retries = 0; retries <= NP2SRV_SR_LOCKED_RETRIES; ++retries) { + rc = sr_subtree_change_subscribe(srs, xpath, callback, private_ctx, priority, opts, subscription); + if (rc != SR_ERR_LOCKED) { + break; + } + usleep(NP2SRV_SR_LOCKED_TIMEOUT * 1000); + } } if (rc == SR_ERR_DISCONNECT) { @@ -936,13 +950,19 @@ int np2srv_sr_event_notif_subscribe(sr_session_ctx_t *srs, const char *xpath, sr_event_notif_cb callback, void *private_ctx, sr_subscr_options_t opts, sr_subscription_ctx_t **subscription, struct nc_server_reply **ereply) { - int rc = SR_ERR_DISCONNECT; + int rc = SR_ERR_DISCONNECT, retries; struct nc_server_error *e; pthread_rwlock_rdlock(&sr_lock); if (!np2srv.disconnected) { - rc = sr_event_notif_subscribe(srs, xpath, callback, private_ctx, opts, subscription); + for (retries = 0; retries <= NP2SRV_SR_LOCKED_RETRIES; ++retries) { + rc = sr_event_notif_subscribe(srs, xpath, callback, private_ctx, opts, subscription); + if (rc != SR_ERR_LOCKED) { + break; + } + usleep(NP2SRV_SR_LOCKED_TIMEOUT * 1000); + } } if (rc == SR_ERR_DISCONNECT) { @@ -1349,13 +1369,19 @@ np2srv_sr_discard_changes(sr_session_ctx_t *srs, struct nc_server_reply **ereply int np2srv_sr_commit(sr_session_ctx_t *srs, struct nc_server_reply **ereply) { - int rc = SR_ERR_DISCONNECT; + int rc = SR_ERR_DISCONNECT, retries; struct nc_server_error *e; pthread_rwlock_rdlock(&sr_lock); if (!np2srv.disconnected) { - rc = sr_commit(srs); + for (retries = 0; retries <= NP2SRV_SR_LOCKED_RETRIES; ++retries) { + rc = sr_commit(srs); + if (rc != SR_ERR_LOCKED) { + break; + } + usleep(NP2SRV_SR_LOCKED_TIMEOUT * 1000); + } } if (rc == SR_ERR_DISCONNECT) { From 254055367f7537f748d3682b6ca8958083ea0f39 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Wed, 23 May 2018 13:29:14 +0200 Subject: [PATCH 54/87] server VERSION bump to version 0.5.14 --- server/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 64c5c5c0b..88e3a3933 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -13,7 +13,7 @@ if(NOT UNIX) endif() # set version -set(NP2SRV_VERSION 0.5.13) +set(NP2SRV_VERSION 0.5.14) # set default build type if not specified by user if(NOT CMAKE_BUILD_TYPE) From 4eda5a4e1f784d8a111f79fe222915d342f912a8 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Wed, 23 May 2018 13:53:35 +0200 Subject: [PATCH 55/87] server VERSION bump to version 0.5.15 --- server/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index e0ae9ce3e..d03cdedec 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -13,7 +13,7 @@ if(NOT UNIX) endif() # set version -set(NP2SRV_VERSION 0.5.14) +set(NP2SRV_VERSION 0.5.15) # set default build type if not specified by user if(NOT CMAKE_BUILD_TYPE) From e27334afbf50931ce33746eea38aaada045fe9a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kundr=C3=A1t?= Date: Wed, 23 May 2018 13:34:05 +0200 Subject: [PATCH 56/87] Add an option for overriding module permissions The current build hardcodes specific options to be passed to `sysrepoctl` at installation time which in turn requires running as root. This is a problem when cross-building under tools such as Buildroot which handle root access in another way. This patch adds an option to cmake to modify these security settings. A build recipe can enforce the file permission later. I am doing just that in the Buildroot. --- keystored/CMakeLists.txt | 10 ++++++++-- server/CMakeLists.txt | 8 +++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/keystored/CMakeLists.txt b/keystored/CMakeLists.txt index c7bd183e2..b61e16144 100644 --- a/keystored/CMakeLists.txt +++ b/keystored/CMakeLists.txt @@ -102,6 +102,12 @@ if (NOT CHMOD_EXECUTABLE) message(FATAL_ERROR "Unable to find chmod, set CHMOD_EXECUTABLE manually.") endif() +# Command line options to be passed to `sysrepoctl` when working with modules +# which should only be accessible by an administrator +if (NOT SYSREPOCTL_ROOT_PERMS) + set(SYSREPOCTL_ROOT_PERMS "-o root:root -p 600") +endif() + # create the keys directory with correct permissions install(DIRECTORY DESTINATION ${KEYSTORED_KEYS_DIR} DIRECTORY_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE) @@ -118,7 +124,7 @@ install(CODE " if (NOT INSTALLED_MODULE_LINE) message(STATUS \"Importing module ietf-x509-cert-to-name into sysrepo...\") - execute_process(COMMAND ${SYSREPOCTL_EXECUTABLE} -i -g ${CMAKE_SOURCE_DIR}/../modules/ietf-x509-cert-to-name.yang -o root:root -p 600 RESULT_VARIABLE RET OUTPUT_VARIABLE OUT ERROR_VARIABLE OUT) + execute_process(COMMAND ${SYSREPOCTL_EXECUTABLE} -i -g ${CMAKE_SOURCE_DIR}/../modules/ietf-x509-cert-to-name.yang ${SYSREPOCTL_ROOT_PERMS} RESULT_VARIABLE RET OUTPUT_VARIABLE OUT ERROR_VARIABLE OUT) if (RET) string(REPLACE \"\\n\" \"\\n \" OUT \"\${OUT}\") message(FATAL_ERROR \" Command sysrepoctl install failed:\\n \${OUT}\") @@ -132,7 +138,7 @@ install(CODE " if (NOT INSTALLED_MODULE_LINE) message(STATUS \"Importing module ietf-keystore into sysrepo...\") - execute_process(COMMAND ${SYSREPOCTL_EXECUTABLE} -i -g ${CMAKE_SOURCE_DIR}/../modules/ietf-keystore.yang -o root:root -p 600 RESULT_VARIABLE RET OUTPUT_VARIABLE OUT ERROR_VARIABLE OUT) + execute_process(COMMAND ${SYSREPOCTL_EXECUTABLE} -i -g ${CMAKE_SOURCE_DIR}/../modules/ietf-keystore.yang ${SYSREPOCTL_ROOT_PERMS} RESULT_VARIABLE RET OUTPUT_VARIABLE OUT ERROR_VARIABLE OUT) if (RET) string(REPLACE \"\\n\" \"\\n \" OUT \"\${OUT}\") message(FATAL_ERROR \" Command sysrepoctl install failed:\\n \${OUT}\") diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index d03cdedec..f54f40c82 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -161,6 +161,12 @@ if (ENABLE_CONFIGURATION) message(FATAL_ERROR "Unable to find sysrepocfg, set SYSREPOCFG_EXECUTABLE manually.") endif() + # Command line options to be passed to `sysrepoctl` when working with modules + # which should only be accessible by an administrator + if (NOT SYSREPOCTL_ROOT_PERMS) + set(SYSREPOCTL_ROOT_PERMS "-o root:root -p 600") + endif() + # install server configuration module and enable features install(CODE " execute_process(COMMAND ${SYSREPOCTL_EXECUTABLE} -l RESULT_VARIABLE RET OUTPUT_VARIABLE INSTALLED_MODULES ERROR_VARIABLE OUT) @@ -178,7 +184,7 @@ if (ENABLE_CONFIGURATION) string(REGEX MATCH \"\${MODULE_NAME} [^\n]*\" INSTALLED_MODULE_LINE \"\${INSTALLED_MODULES}\") if (NOT INSTALLED_MODULE_LINE) message(STATUS \"Importing module \${MODULE_NAME} into sysrepo...\") - execute_process(COMMAND ${SYSREPOCTL_EXECUTABLE} -i -g ${CMAKE_SOURCE_DIR}/../modules/\${MODULE_NAME}.yang -o root:root -p 600 RESULT_VARIABLE RET OUTPUT_VARIABLE OUT ERROR_VARIABLE OUT) + execute_process(COMMAND ${SYSREPOCTL_EXECUTABLE} -i -g ${CMAKE_SOURCE_DIR}/../modules/\${MODULE_NAME}.yang ${SYSREPOCTL_ROOT_PERMS} RESULT_VARIABLE RET OUTPUT_VARIABLE OUT ERROR_VARIABLE OUT) if (RET) string(REPLACE \"\\n\" \"\\n \" OUT \${OUT}) message(FATAL_ERROR \" Command sysrepoctl install failed:\\n \${OUT}\") From f9dafad1c92b2b2b188b72e1ee995c1ab825066a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kundr=C3=A1t?= Date: Wed, 23 May 2018 14:35:54 +0200 Subject: [PATCH 57/87] keystored: enable SSH key provisioning by an external script Our build scripts (Buildroot) generate a fileysstem image to be used by many devices, which is why they do not contain any key material. This means that by default, netopper2-keystored won't install any keys, and that the netopeer2-server's installation fails because its default configuration refers to a non-existing SSH key: -- Importing module ietf-system into sysrepo... CMake Error at cmake_install.cmake:119 (message): Command sysrepocfg import failed: [ERR] (rp_dt_commit:864) Validation after merging failed [ERR] (sr_commit:2089) Commit operation failed with 1 error(s). [ERR] (srcfg_import_datastore:911) Error returned from sr_commit: Validation of the changes failed. [ERR] (srcfg_import_datastore:914) /ietf-netconf-server:netconf-server/listen/endpoint[name='test_ssh_listen_endpt']/ssh/host-keys/host-key[name='test_ssh_listen_key']/public-key : Leafref "/ietf-keystore:keystore/ietf-keystore:private-keys/ietf-keystore:private-key/ietf-keystore:name" of value "ssh_host_rsa_key" points to a non-existing leaf. Without this patch, I would have to provide full configuration for the NETCONF server and for the keystored daemon. My preference is to avoid duplicating the (ricky) logic which is already available in these cmake installation scripts. Therefore, this patch simply adds yet another flag which means that an external deploy script will provide a PEM-encoded SSH host file at a well-known location. That is pretty easy to provide via a systemd unit file in a similar manner to how the OpenSSH server already pre-generates its keys if they are not available. --- keystored/CMakeLists.txt | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/keystored/CMakeLists.txt b/keystored/CMakeLists.txt index b61e16144..09e1c8d2a 100644 --- a/keystored/CMakeLists.txt +++ b/keystored/CMakeLists.txt @@ -108,6 +108,15 @@ if (NOT SYSREPOCTL_ROOT_PERMS) set(SYSREPOCTL_ROOT_PERMS "-o root:root -p 600") endif() +# Use KEYSTORED_DEFER_SSH_KEY=ON to skip automatic key conversion. +# Some external build/deploy script is then responsible for providing an SSH +# host key in a PEM format at runtime. +if (NOT KEYSTORED_DEFER_SSH_KEY) + set(KEYSTORED_CHECK_SSH_KEY 1) +else() + set(KEYSTORED_CHECK_SSH_KEY 0) +endif() + # create the keys directory with correct permissions install(DIRECTORY DESTINATION ${KEYSTORED_KEYS_DIR} DIRECTORY_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE) @@ -158,17 +167,21 @@ install(CODE " if (OUT) message(STATUS \"Some ietf-keystore configuration set, no keys will be imported.\") - elseif(NOT EXISTS \"/etc/ssh/ssh_host_rsa_key\") + elseif(NOT EXISTS \"/etc/ssh/ssh_host_rsa_key\" AND ${KEYSTORED_CHECK_SSH_KEY}) message(WARNING \"Default OpenSSH RSA host key \\\"/etc/ssh/ssh_host_rsa_key\\\" not found so a key will have to be imported or generated manually for netopeer2-server to use.\") else() - message(STATUS \"Importing stock OpenSSH RSA key.\") - file(READ /etc/ssh/ssh_host_rsa_key RSA_KEY) - file(WRITE ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem \${RSA_KEY}) - execute_process(COMMAND ${CHMOD_EXECUTABLE} go-rw ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem) - execute_process(COMMAND ${OPENSSL_EXECUTABLE} rsa -pubout -in ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem -out ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pub.pem RESULT_VARIABLE RET OUTPUT_VARIABLE OUT ERROR_VARIABLE OUT) - if (RET) - string(REPLACE \"\\n\" \"\\n \" OUT \"\${OUT}\") - message(FATAL_ERROR \" Command openssl generate public key failed:\\n \${OUT}\") + if (${KEYSTORED_CHECK_SSH_KEY}) + message(STATUS \"Importing stock OpenSSH RSA key.\") + file(READ /etc/ssh/ssh_host_rsa_key RSA_KEY) + file(WRITE ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem \${RSA_KEY}) + execute_process(COMMAND ${CHMOD_EXECUTABLE} go-rw ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem) + execute_process(COMMAND ${OPENSSL_EXECUTABLE} rsa -pubout -in ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem -out ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pub.pem RESULT_VARIABLE RET OUTPUT_VARIABLE OUT ERROR_VARIABLE OUT) + if (RET) + string(REPLACE \"\\n\" \"\\n \" OUT \"\${OUT}\") + message(FATAL_ERROR \" Command openssl generate public key failed:\\n \${OUT}\") + endif() + else() + message(STATUS \"Assuming that an external script will provide the SSH key in a PEM format at \\\"${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem\\\".\") endif() execute_process(COMMAND ${SYSREPOCFG_EXECUTABLE} -d startup -i ${CMAKE_SOURCE_DIR}/stock_key_config.xml ietf-keystore RESULT_VARIABLE RET OUTPUT_VARIABLE OUT ERROR_VARIABLE OUT) if (RET) From cf8951974c9f0979a57f95616f3decfa3425e94e Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Thu, 24 May 2018 09:36:09 +0200 Subject: [PATCH 58/87] cli BUGFIX race condition --- cli/configuration.c | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/cli/configuration.c b/cli/configuration.c index 444836f74..7f1b2c5a9 100644 --- a/cli/configuration.c +++ b/cli/configuration.c @@ -67,21 +67,13 @@ get_netconf_dir(void) return NULL; } - ret = eaccess(netconf_dir, R_OK | X_OK); - if (ret == -1) { - if (errno == ENOENT) { - /* directory does not exist */ - ERROR("get_netconf_dir", "Configuration directory \"%s\" does not exist, creating it.", netconf_dir); - if (mkdir(netconf_dir, 00700)) { - ERROR("get_netconf_dir", "Configuration directory \"%s\" cannot be created: %s", netconf_dir, strerror(errno)); - free(netconf_dir); - return NULL; - } - } else { - ERROR("get_netconf_dir", "Configuration directory \"%s\" exists but something else failed: %s", netconf_dir, strerror(errno)); - free(netconf_dir); - return NULL; - } + ret = mkdir(netconf_dir, 00700); + if (!ret) { + ERROR("get_netconf_dir", "Configuration directory \"%s\" did not exist, created.", netconf_dir); + } else if (errno != EEXIST) { + ERROR("get_netconf_dir", "Configuration directory \"%s\" cannot be created: %s", netconf_dir, strerror(errno)); + free(netconf_dir); + return NULL; } return netconf_dir; @@ -310,15 +302,13 @@ load_config(void) } else if (!strcmp(child->name, "searchpath")) { /* doc -> -> */ errno = 0; - if (eaccess(child->content, R_OK | W_OK | X_OK) && (errno == ENOENT)) { - ERROR(__func__, "Search path \"%s\" does not exist, creating it.", child->content); - if (mkdir(child->content, 00700)) { - ERROR(__func__, "Search path \"%s\" cannot be created: %s", child->content, strerror(errno)); - } else { - nc_client_set_schema_searchpath(child->content); + if (!mkdir(child->content, 00700) || (errno == EEXIST)) { + if (errno == 0) { + ERROR(__func__, "Search path \"%s\" did not exist, created.", child->content); } - } else { nc_client_set_schema_searchpath(child->content); + } else { + ERROR(__func__, "Search path \"%s\" cannot be created: %s", child->content, strerror(errno)); } } else if (!strcmp(child->name, "output-format")) { /* doc -> -> */ From 9be12a971d84627fab08c532d48919321fd95559 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Thu, 24 May 2018 09:37:09 +0200 Subject: [PATCH 59/87] cli VERSION bump to version 2.0.46 --- cli/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt index f248c45c3..4d7ee2b52 100644 --- a/cli/CMakeLists.txt +++ b/cli/CMakeLists.txt @@ -21,7 +21,7 @@ set(CMAKE_C_FLAGS_RELEASE "-O2") set(CMAKE_C_FLAGS_DEBUG "-g -O0") # set version -set(NP2CLI_VERSION 2.0.45) +set(NP2CLI_VERSION 2.0.46) configure_file("${PROJECT_SOURCE_DIR}/version.h.in" "${PROJECT_BINARY_DIR}/version.h" ESCAPE_QUOTES @ONLY) include_directories(${PROJECT_BINARY_DIR}) From e21f1eb8d2edeea7ff12186b6f93447dcefd3ec0 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Thu, 24 May 2018 09:37:23 +0200 Subject: [PATCH 60/87] server BUGFIX uninitialized variable --- server/op_validate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/op_validate.c b/server/op_validate.c index 4dc1ddf6e..317f9e15d 100644 --- a/server/op_validate.c +++ b/server/op_validate.c @@ -26,7 +26,7 @@ op_validate(struct lyd_node *rpc, struct nc_session *ncs) struct np2_sessions *sessions; struct ly_set *nodeset = NULL; struct nc_server_error *e = NULL; - struct nc_server_reply *ereply; + struct nc_server_reply *ereply = NULL; struct lyd_node *config = NULL; struct lyd_node_anydata *any; const char *dsname; From bef8713815c5f3ff86433858020a5fa0a4286cc2 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Thu, 24 May 2018 09:37:38 +0200 Subject: [PATCH 61/87] server BUGFIX check return value --- server/op_validate.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/server/op_validate.c b/server/op_validate.c index 317f9e15d..1bb041811 100644 --- a/server/op_validate.c +++ b/server/op_validate.c @@ -61,7 +61,12 @@ op_validate(struct lyd_node *rpc, struct nc_session *ncs) case LYD_ANYDATA_DATATREE: config = any->value.tree; any->value.tree = NULL; /* "unlink" data tree from anydata to have full control */ - lyd_validate(&config, LYD_OPT_CONFIG, np2srv.ly_ctx); + if (lyd_validate(&config, LYD_OPT_CONFIG, np2srv.ly_ctx)) { + e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); + nc_err_set_msg(e, np2log_lasterr(np2srv.ly_ctx), "en"); + ereply = nc_server_reply_err(e); + goto finish; + } break; case LYD_ANYDATA_XML: config = lyd_parse_xml(np2srv.ly_ctx, &any->value.xml, LYD_OPT_CONFIG | LYD_OPT_DESTRUCT | LYD_OPT_STRICT); From 6a413c405930443ef9fd3f198c505b3c0c6d86f1 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Thu, 24 May 2018 09:38:00 +0200 Subject: [PATCH 62/87] server BUGFIX sleeping while holding locks --- server/operations.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/server/operations.c b/server/operations.c index 95f14e5f4..a68d48321 100644 --- a/server/operations.c +++ b/server/operations.c @@ -847,7 +847,9 @@ np2srv_sr_module_change_subscribe(sr_session_ctx_t *srs, const char *module_name if (rc != SR_ERR_LOCKED) { break; } + pthread_rwlock_unlock(&sr_lock); usleep(NP2SRV_SR_LOCKED_TIMEOUT * 1000); + pthread_rwlock_rdlock(&sr_lock); } } @@ -904,7 +906,9 @@ np2srv_sr_subtree_change_subscribe(sr_session_ctx_t *srs, const char *xpath, sr_ if (rc != SR_ERR_LOCKED) { break; } + pthread_rwlock_unlock(&sr_lock); usleep(NP2SRV_SR_LOCKED_TIMEOUT * 1000); + pthread_rwlock_rdlock(&sr_lock); } } @@ -950,19 +954,13 @@ int np2srv_sr_event_notif_subscribe(sr_session_ctx_t *srs, const char *xpath, sr_event_notif_cb callback, void *private_ctx, sr_subscr_options_t opts, sr_subscription_ctx_t **subscription, struct nc_server_reply **ereply) { - int rc = SR_ERR_DISCONNECT, retries; + int rc = SR_ERR_DISCONNECT; struct nc_server_error *e; pthread_rwlock_rdlock(&sr_lock); if (!np2srv.disconnected) { - for (retries = 0; retries <= NP2SRV_SR_LOCKED_RETRIES; ++retries) { - rc = sr_event_notif_subscribe(srs, xpath, callback, private_ctx, opts, subscription); - if (rc != SR_ERR_LOCKED) { - break; - } - usleep(NP2SRV_SR_LOCKED_TIMEOUT * 1000); - } + rc = sr_event_notif_subscribe(srs, xpath, callback, private_ctx, opts, subscription); } if (rc == SR_ERR_DISCONNECT) { @@ -1380,7 +1378,9 @@ np2srv_sr_commit(sr_session_ctx_t *srs, struct nc_server_reply **ereply) if (rc != SR_ERR_LOCKED) { break; } + pthread_rwlock_unlock(&sr_lock); usleep(NP2SRV_SR_LOCKED_TIMEOUT * 1000); + pthread_rwlock_rdlock(&sr_lock); } } From 378ee87df48df1cdaa391d8018b2d823da872134 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Thu, 24 May 2018 09:38:27 +0200 Subject: [PATCH 63/87] server MANITENANCE check all negative values For coverity to be happy. --- server/tests/config.h.in | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/server/tests/config.h.in b/server/tests/config.h.in index e36940b6a..4dfdb39df 100755 --- a/server/tests/config.h.in +++ b/server/tests/config.h.in @@ -133,7 +133,10 @@ __wrap_sr_get_schema(sr_session_ctx_t *session, const char *module_name, const c } else { return SR_ERR_NOT_FOUND; } - assert_int_not_equal(fd, -1); + + if (fd < 0) { + return SR_ERR_INTERNAL; + } assert_int_equal(fstat(fd, &st), 0); From 3927e5fd30075e0667c7a8d904c297d2adb7e447 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Thu, 24 May 2018 09:39:05 +0200 Subject: [PATCH 64/87] server VERSION bump to version 0.5.16 --- server/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index d03cdedec..822db61d8 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -13,7 +13,7 @@ if(NOT UNIX) endif() # set version -set(NP2SRV_VERSION 0.5.15) +set(NP2SRV_VERSION 0.5.16) # set default build type if not specified by user if(NOT CMAKE_BUILD_TYPE) From 8c73c7c005c15a8af56f638cba17212cebbbccec Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Thu, 24 May 2018 10:35:08 +0200 Subject: [PATCH 65/87] server CHANGE do not sleep after last retry --- server/operations.c | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/server/operations.c b/server/operations.c index a68d48321..be83287fd 100644 --- a/server/operations.c +++ b/server/operations.c @@ -842,14 +842,18 @@ np2srv_sr_module_change_subscribe(sr_session_ctx_t *srs, const char *module_name pthread_rwlock_rdlock(&sr_lock); if (!np2srv.disconnected) { - for (retries = 0; retries <= NP2SRV_SR_LOCKED_RETRIES; ++retries) { + retries = 0; + goto exec_func; + while (retries <= NP2SRV_SR_LOCKED_RETRIES) { + pthread_rwlock_unlock(&sr_lock); + usleep(NP2SRV_SR_LOCKED_TIMEOUT * 1000); + pthread_rwlock_rdlock(&sr_lock); +exec_func: rc = sr_module_change_subscribe(srs, module_name, callback, private_ctx, priority, opts, subscription); if (rc != SR_ERR_LOCKED) { break; } - pthread_rwlock_unlock(&sr_lock); - usleep(NP2SRV_SR_LOCKED_TIMEOUT * 1000); - pthread_rwlock_rdlock(&sr_lock); + ++retries; } } @@ -901,14 +905,18 @@ np2srv_sr_subtree_change_subscribe(sr_session_ctx_t *srs, const char *xpath, sr_ pthread_rwlock_rdlock(&sr_lock); if (!np2srv.disconnected) { - for (retries = 0; retries <= NP2SRV_SR_LOCKED_RETRIES; ++retries) { + retries = 0; + goto exec_func; + while (retries <= NP2SRV_SR_LOCKED_RETRIES) { + pthread_rwlock_unlock(&sr_lock); + usleep(NP2SRV_SR_LOCKED_TIMEOUT * 1000); + pthread_rwlock_rdlock(&sr_lock); +exec_func: rc = sr_subtree_change_subscribe(srs, xpath, callback, private_ctx, priority, opts, subscription); if (rc != SR_ERR_LOCKED) { break; } - pthread_rwlock_unlock(&sr_lock); - usleep(NP2SRV_SR_LOCKED_TIMEOUT * 1000); - pthread_rwlock_rdlock(&sr_lock); + ++retries; } } @@ -1373,14 +1381,18 @@ np2srv_sr_commit(sr_session_ctx_t *srs, struct nc_server_reply **ereply) pthread_rwlock_rdlock(&sr_lock); if (!np2srv.disconnected) { - for (retries = 0; retries <= NP2SRV_SR_LOCKED_RETRIES; ++retries) { + retries = 0; + goto exec_func; + while (retries <= NP2SRV_SR_LOCKED_RETRIES) { + pthread_rwlock_unlock(&sr_lock); + usleep(NP2SRV_SR_LOCKED_TIMEOUT * 1000); + pthread_rwlock_rdlock(&sr_lock); +exec_func: rc = sr_commit(srs); if (rc != SR_ERR_LOCKED) { break; } - pthread_rwlock_unlock(&sr_lock); - usleep(NP2SRV_SR_LOCKED_TIMEOUT * 1000); - pthread_rwlock_rdlock(&sr_lock); + ++retries; } } From 45750819f590cffa4333e799f182cd51aea5b56e Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Thu, 24 May 2018 10:35:36 +0200 Subject: [PATCH 66/87] server VERSION bump to version 0.5.17 --- server/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 822db61d8..0bf5205ce 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -13,7 +13,7 @@ if(NOT UNIX) endif() # set version -set(NP2SRV_VERSION 0.5.16) +set(NP2SRV_VERSION 0.5.17) # set default build type if not specified by user if(NOT CMAKE_BUILD_TYPE) From d5ceb16c7bfa0da8659dc5df5760fdf14fdaabfa Mon Sep 17 00:00:00 2001 From: Frank Rimpler Date: Thu, 24 May 2018 15:39:23 +0000 Subject: [PATCH 67/87] make auth keys settings accessible for call home --- cli/commands.c | 6 ++++-- cli/configuration.c | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/cli/commands.c b/cli/commands.c index 8f1c6aa57..8ea4199a7 100644 --- a/cli/commands.c +++ b/cli/commands.c @@ -1207,7 +1207,9 @@ cmd_auth(const char *arg, char **UNUSED(tmp_config_file)) ERROR("auth keys add", "Missing the public key path"); return EXIT_FAILURE; } - if (nc_client_ssh_add_keypair(str, cmd) != EXIT_SUCCESS) { + + if (nc_client_ssh_ch_add_keypair(str, cmd) != EXIT_SUCCESS || + nc_client_ssh_add_keypair(str, cmd) != EXIT_SUCCESS) { ERROR("auth keys add", "Failed to add keys"); return EXIT_FAILURE; } @@ -1227,7 +1229,7 @@ cmd_auth(const char *arg, char **UNUSED(tmp_config_file)) } i = strtol(cmd, &ptr, 10); - if (ptr[0] || nc_client_ssh_del_keypair(i)) { + if (ptr[0] || nc_client_ssh_ch_del_keypair(i) || nc_client_ssh_del_keypair(i)) { ERROR("auth keys remove", "Wrong index"); return EXIT_FAILURE; } diff --git a/cli/configuration.c b/cli/configuration.c index 7f1b2c5a9..1e65cf092 100644 --- a/cli/configuration.c +++ b/cli/configuration.c @@ -350,6 +350,7 @@ load_config(void) } } if (key_pub && key_priv) { + nc_client_ssh_ch_add_keypair(key_pub, key_priv); nc_client_ssh_add_keypair(key_pub, key_priv); } } From afb776547cfdd5e64a0609bbb7d1ea7f61890d83 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Fri, 25 May 2018 08:49:46 +0200 Subject: [PATCH 68/87] server CHANGE adjustable notification send timeout Fixes #256 --- server/CMakeLists.txt | 3 ++- server/config.h.in | 4 ++++ server/op_notifications.c | 8 ++++---- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 0bf5205ce..abd086173 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -33,8 +33,9 @@ else() option(ENABLE_VALGRIND_TESTS "Build tests with valgrind" OFF) endif() option(ENABLE_CONFIGURATION "Enable server configuration" ON) -set(THREAD_COUNT 5 CACHE STRING "Number of threads accepting new sessions and handling requests") +set(THREAD_COUNT 5 CACHE INTEGER "Number of threads accepting new sessions and handling requests") set(DEFAULT_HOST_KEY "/etc/ssh/ssh_host_rsa_key" CACHE STRING "Default server host key (used only if configuration is disabled)") +set(NOTIF_TIMEOUT 5 CACHE INTEGER "Maximum number of seconds that the server will wait for session lock when sending a notification") # set prefix for the PID file if (NOT PIDFILE_PREFIX) diff --git a/server/config.h.in b/server/config.h.in index fbb9f4202..29c789261 100644 --- a/server/config.h.in +++ b/server/config.h.in @@ -44,6 +44,10 @@ */ #cmakedefine HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP 1 +/** @brief timeout in s for waiting for session lock when sending a notification + */ +#define NP2SRV_NOTIF_TIMEOUT @NOTIF_TIMEOUT@ + /** @brief timeout in ms for retrying certain sysrepo operations (subscriptions and commit) in case 2 same operations collide */ #define NP2SRV_SR_LOCKED_TIMEOUT 10 diff --git a/server/op_notifications.c b/server/op_notifications.c index 0a76b0377..0cfbcdce0 100644 --- a/server/op_notifications.c +++ b/server/op_notifications.c @@ -80,7 +80,7 @@ np2srv_ntf_replay_sort_send(struct np_subscriber *subscriber) /* send all the replay notifications */ for (i = 0; i < subscriber->replay_notif_count; ++i) { - nc_server_notif_send(subscriber->session, subscriber->replay_notifs[i], 5000); + nc_server_notif_send(subscriber->session, subscriber->replay_notifs[i], NP2SRV_NOTIF_TIMEOUT * 1000); nc_server_notif_free(subscriber->replay_notifs[i]); ncm_session_notification(subscriber->session); } @@ -93,7 +93,7 @@ np2srv_ntf_replay_sort_send(struct np_subscriber *subscriber) mod = ly_ctx_get_module(np2srv.ly_ctx, "nc-notifications", NULL, 1); event = lyd_new(NULL, mod, "replayComplete"); notif = nc_server_notif_new(event, nc_time2datetime(time(NULL), NULL, NULL), NC_PARAMTYPE_FREE); - nc_server_notif_send(subscriber->session, notif, 5000); + nc_server_notif_send(subscriber->session, notif, NP2SRV_NOTIF_TIMEOUT * 1000); nc_server_notif_free(notif); ncm_session_notification(subscriber->session); } @@ -130,7 +130,7 @@ np2srv_ntf_send(struct np_subscriber *subscriber, struct lyd_node *ntf, time_t t if (mod) { filtered_ntf = lyd_new(NULL, mod, "notificationComplete"); ntf_msg = nc_server_notif_new(filtered_ntf, nc_time2datetime(time(NULL), NULL, NULL), NC_PARAMTYPE_FREE); - nc_server_notif_send(subscriber->session, ntf_msg, 5000); + nc_server_notif_send(subscriber->session, ntf_msg, NP2SRV_NOTIF_TIMEOUT * 1000); nc_server_notif_free(ntf_msg); ncm_session_notification(subscriber->session); } else { @@ -169,7 +169,7 @@ np2srv_ntf_send(struct np_subscriber *subscriber, struct lyd_node *ntf, time_t t } if (notif_type == SR_EV_NOTIF_T_REALTIME) { - nc_server_notif_send(subscriber->session, ntf_msg, 5000); + nc_server_notif_send(subscriber->session, ntf_msg, NP2SRV_NOTIF_TIMEOUT * 1000); nc_server_notif_free(ntf_msg); ncm_session_notification(subscriber->session); } else { From 2aad256655a73aafc65bf1ad419168bd67050069 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Fri, 25 May 2018 08:50:25 +0200 Subject: [PATCH 69/87] server VERSION bump to version 0.5.18 --- server/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index abd086173..a3627223f 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -13,7 +13,7 @@ if(NOT UNIX) endif() # set version -set(NP2SRV_VERSION 0.5.17) +set(NP2SRV_VERSION 0.5.18) # set default build type if not specified by user if(NOT CMAKE_BUILD_TYPE) From c8fc7f1c3d1fc95f9564144bf75faf8df06a3451 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Fri, 25 May 2018 08:58:15 +0200 Subject: [PATCH 70/87] cli VERSION bump to version 2.0.47 --- cli/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt index 4d7ee2b52..c779963d2 100644 --- a/cli/CMakeLists.txt +++ b/cli/CMakeLists.txt @@ -21,7 +21,7 @@ set(CMAKE_C_FLAGS_RELEASE "-O2") set(CMAKE_C_FLAGS_DEBUG "-g -O0") # set version -set(NP2CLI_VERSION 2.0.46) +set(NP2CLI_VERSION 2.0.47) configure_file("${PROJECT_SOURCE_DIR}/version.h.in" "${PROJECT_BINARY_DIR}/version.h" ESCAPE_QUOTES @ONLY) include_directories(${PROJECT_BINARY_DIR}) From 69ac84e9c2c4a069a869f3cd31e3453f57d513ff Mon Sep 17 00:00:00 2001 From: Samuel Gauthier Date: Thu, 24 May 2018 17:15:41 +0200 Subject: [PATCH 71/87] server: don't always override KEYSTORED_KEYS_DIR Give the user a chance to give from cmake commande line. Signed-off-by: Samuel Gauthier --- server/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 189cd55aa..984d7b622 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -58,7 +58,9 @@ if (ENABLE_CONFIGURATION) message(STATUS "keystored keys directory is \"${KEYSTORED_KEYS_DIR}\".") endif() else() - set(KEYSTORED_KEYS_DIR "none") + if (NOT KEYSTORED_KEYS_DIR) + set(KEYSTORED_KEYS_DIR "none") + endif() endif() # set default SSH key From 0970ceac4f889a6ddd594e5c5fa2941fe379a79a Mon Sep 17 00:00:00 2001 From: Samuel Gauthier Date: Fri, 25 May 2018 09:41:36 +0200 Subject: [PATCH 72/87] cmake: split installation tasks into scripts This commit takes all the installation tasks (yang model installation, ssh key import) out of cmake, in separate scripts, and calls those scripts during the install target. It makes the code more readable. MODEL_INSTALL and SSH_KEY_INSTALL options can be set to off to avoid the scripts to be called in keystored makefile. The yang model installation script is only called when ENABLE_CONFIGURATION is set in the server makefile. KEYSTORED_DEFER_SSH_KEY is removed, as it is replaced by SSH_KEY_INSTALL. Signed-off-by: Samuel Gauthier --- keystored/CMakeLists.txt | 92 +++++------------------------ keystored/scripts/model-install.sh | 22 +++++++ keystored/scripts/ssh-key-import.sh | 25 ++++++++ server/CMakeLists.txt | 76 ++---------------------- server/scripts/model-install.sh | 41 +++++++++++++ 5 files changed, 108 insertions(+), 148 deletions(-) create mode 100755 keystored/scripts/model-install.sh create mode 100755 keystored/scripts/ssh-key-import.sh create mode 100755 server/scripts/model-install.sh diff --git a/keystored/CMakeLists.txt b/keystored/CMakeLists.txt index 09e1c8d2a..760e12aae 100644 --- a/keystored/CMakeLists.txt +++ b/keystored/CMakeLists.txt @@ -108,87 +108,27 @@ if (NOT SYSREPOCTL_ROOT_PERMS) set(SYSREPOCTL_ROOT_PERMS "-o root:root -p 600") endif() -# Use KEYSTORED_DEFER_SSH_KEY=ON to skip automatic key conversion. -# Some external build/deploy script is then responsible for providing an SSH -# host key in a PEM format at runtime. -if (NOT KEYSTORED_DEFER_SSH_KEY) - set(KEYSTORED_CHECK_SSH_KEY 1) -else() - set(KEYSTORED_CHECK_SSH_KEY 0) -endif() - # create the keys directory with correct permissions install(DIRECTORY DESTINATION ${KEYSTORED_KEYS_DIR} DIRECTORY_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE) -# install all the required modules and enable features -install(CODE " - execute_process(COMMAND ${SYSREPOCTL_EXECUTABLE} -l RESULT_VARIABLE RET OUTPUT_VARIABLE INSTALLED_MODULES ERROR_VARIABLE OUT) - if (RET) - string(REPLACE \"\\n\" \"\\n \" OUT \"\${OUT}\") - message(FATAL_ERROR \" Command sysrepoctl list failed:\n \${OUT}\") - endif() - - string(REGEX MATCH \"ietf-x509-cert-to-name[^|]*[|][^|]*[|] Installed[^\n]*\" INSTALLED_MODULE_LINE \"\${INSTALLED_MODULES}\") - if (NOT INSTALLED_MODULE_LINE) - message(STATUS \"Importing module ietf-x509-cert-to-name into sysrepo...\") - - execute_process(COMMAND ${SYSREPOCTL_EXECUTABLE} -i -g ${CMAKE_SOURCE_DIR}/../modules/ietf-x509-cert-to-name.yang ${SYSREPOCTL_ROOT_PERMS} RESULT_VARIABLE RET OUTPUT_VARIABLE OUT ERROR_VARIABLE OUT) - if (RET) - string(REPLACE \"\\n\" \"\\n \" OUT \"\${OUT}\") - message(FATAL_ERROR \" Command sysrepoctl install failed:\\n \${OUT}\") - endif() - - else() - message(STATUS \"Module ietf-x509-cert-to-name already in sysrepo.\") - endif() - - string(REGEX MATCH \"ietf-keystore [^\n]*\" INSTALLED_MODULE_LINE \"\${INSTALLED_MODULES}\") - if (NOT INSTALLED_MODULE_LINE) - message(STATUS \"Importing module ietf-keystore into sysrepo...\") - - execute_process(COMMAND ${SYSREPOCTL_EXECUTABLE} -i -g ${CMAKE_SOURCE_DIR}/../modules/ietf-keystore.yang ${SYSREPOCTL_ROOT_PERMS} RESULT_VARIABLE RET OUTPUT_VARIABLE OUT ERROR_VARIABLE OUT) - if (RET) - string(REPLACE \"\\n\" \"\\n \" OUT \"\${OUT}\") - message(FATAL_ERROR \" Command sysrepoctl install failed:\\n \${OUT}\") - endif() - - else() - message(STATUS \"Module ietf-keystore already in sysrepo.\") - endif()") - -# import stock OpenSSH RSA key -install(CODE " - execute_process(COMMAND ${SYSREPOCFG_EXECUTABLE} -d startup --export ietf-keystore RESULT_VARIABLE RET OUTPUT_VARIABLE OUT ERROR_VARIABLE OUT) - if (RET) - string(REPLACE \"\\n\" \"\\n \" OUT \"\${OUT}\") - message(FATAL_ERROR \" Command sysrepocfg export failed:\\n \${OUT}\") - endif() +option(MODEL_INSTALL "Enable yang model installation" ON) +if (MODEL_INSTALL) + install(CODE " + set(ENV{SYSREPOCTL} ${SYSREPOCTL_EXECUTABLE}) + set(ENV{SYSREPOCTL_ROOT_PERMS} SYSREPOCTL_ROOT_PERMS) + execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/scripts/model-install.sh)") +endif() - if (OUT) - message(STATUS \"Some ietf-keystore configuration set, no keys will be imported.\") - elseif(NOT EXISTS \"/etc/ssh/ssh_host_rsa_key\" AND ${KEYSTORED_CHECK_SSH_KEY}) - message(WARNING \"Default OpenSSH RSA host key \\\"/etc/ssh/ssh_host_rsa_key\\\" not found so a key will have to be imported or generated manually for netopeer2-server to use.\") - else() - if (${KEYSTORED_CHECK_SSH_KEY}) - message(STATUS \"Importing stock OpenSSH RSA key.\") - file(READ /etc/ssh/ssh_host_rsa_key RSA_KEY) - file(WRITE ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem \${RSA_KEY}) - execute_process(COMMAND ${CHMOD_EXECUTABLE} go-rw ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem) - execute_process(COMMAND ${OPENSSL_EXECUTABLE} rsa -pubout -in ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem -out ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pub.pem RESULT_VARIABLE RET OUTPUT_VARIABLE OUT ERROR_VARIABLE OUT) - if (RET) - string(REPLACE \"\\n\" \"\\n \" OUT \"\${OUT}\") - message(FATAL_ERROR \" Command openssl generate public key failed:\\n \${OUT}\") - endif() - else() - message(STATUS \"Assuming that an external script will provide the SSH key in a PEM format at \\\"${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem\\\".\") - endif() - execute_process(COMMAND ${SYSREPOCFG_EXECUTABLE} -d startup -i ${CMAKE_SOURCE_DIR}/stock_key_config.xml ietf-keystore RESULT_VARIABLE RET OUTPUT_VARIABLE OUT ERROR_VARIABLE OUT) - if (RET) - string(REPLACE \"\\n\" \"\\n \" OUT \"\${OUT}\") - message(FATAL_ERROR \" Command sysrepocfg import failed:\\n \${OUT}\") - endif() - endif()") +option(SSH_KEY_INSTALL "Enable ssh key import" ON) +if (SSH_KEY_INSTALL) + install(CODE " + set(ENV{SYSREPOCFG} ${SYSREPOCFG_EXECUTABLE}) + set(ENV{CHMOD} ${CHMOD_EXECUTABLE}) + set(ENV{OPENSSL} ${OPENSSL_EXECUTABLE}) + set(ENV{KEYSTORED_KEYS_DIR} ${KEYSTORED_KEYS_DIR}) + execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/scripts/ssh-key-import.sh)") +endif() # plugins should be installed into sysrepo plugins dir install(TARGETS keystored DESTINATION ${SR_PLUGINS_DIR}) diff --git a/keystored/scripts/model-install.sh b/keystored/scripts/model-install.sh new file mode 100755 index 000000000..a409e07f9 --- /dev/null +++ b/keystored/scripts/model-install.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +set -eux -o pipefail + +shopt -s failglob + +local_path=$(dirname $0) + +: ${SYSREPOCTL:=sysrepoctl} +: ${SYSREPOCTL_ROOT_PERMS:=-o root:root -p 600} +: ${YANG_DIR:=$local_path/../../modules} + +install_yang_module() { + module=$1 + + if ! $SYSREPOCTL -l | grep "$module[^|]*|[^|]*| Installed[^\\n]*"; then + $SYSREPOCTL -i -g ${YANG_DIR}/$module.yang $SYSREPOCTL_ROOT_PERMS + fi +} + +install_yang_module ietf-x509-cert-to-name +install_yang_module ietf-keystore diff --git a/keystored/scripts/ssh-key-import.sh b/keystored/scripts/ssh-key-import.sh new file mode 100755 index 000000000..a1761a272 --- /dev/null +++ b/keystored/scripts/ssh-key-import.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +set -eux -o pipefail + +shopt -s failglob + +local_path=$(dirname $0) + +: ${SYSREPOCFG:=sysrepocfg} +: ${CHMOD:=chmod} +: ${OPENSSL:=openssl} +: ${STOCK_KEY_CONFIG:=$local_path/../stock_key_config.xml} +: ${KEYSTORED_KEYS_DIR:=/etc/keystored/keys} + +if [ -n "$($SYSREPOCFG -d startup --export ietf-keystore)" ]; then + exit 0 +fi + +if [ -f /etc/ssh/ssh_host_rsa_key ]; then + cp /etc/ssh/ssh_host_rsa_key ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem + $CHMOD go-rw ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem + $OPENSSL rsa -pubout -in ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem \ + -out ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pub.pem + $SYSREPOCFG -d startup -i ${STOCK_KEY_CONFIG} ietf-keystore +fi diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 984d7b622..a7f3e8fdb 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -170,79 +170,11 @@ if (ENABLE_CONFIGURATION) set(SYSREPOCTL_ROOT_PERMS "-o root:root -p 600") endif() - # install server configuration module and enable features install(CODE " - execute_process(COMMAND ${SYSREPOCTL_EXECUTABLE} -l RESULT_VARIABLE RET OUTPUT_VARIABLE INSTALLED_MODULES ERROR_VARIABLE OUT) - if (RET) - string(REPLACE \"\\n\" \"\\n \" OUT \${OUT}) - message(FATAL_ERROR \" Command sysrepoctl list failed:\\n \${OUT}\") - endif() - - string(REGEX MATCH \"ietf-keystore [^\\n]*\" INSTALLED_MODULE_LINE \"\${INSTALLED_MODULES}\") - if (NOT INSTALLED_MODULE_LINE) - message(STATUS \"Server configuration is disabled because sysrepo does not support ietf-keystore (keystored plugin not installed).\") - else() - set(MODULE_NAMES ietf-netconf-server ietf-system) - foreach(MODULE_NAME IN LISTS MODULE_NAMES) - string(REGEX MATCH \"\${MODULE_NAME} [^\n]*\" INSTALLED_MODULE_LINE \"\${INSTALLED_MODULES}\") - if (NOT INSTALLED_MODULE_LINE) - message(STATUS \"Importing module \${MODULE_NAME} into sysrepo...\") - execute_process(COMMAND ${SYSREPOCTL_EXECUTABLE} -i -g ${CMAKE_SOURCE_DIR}/../modules/\${MODULE_NAME}.yang ${SYSREPOCTL_ROOT_PERMS} RESULT_VARIABLE RET OUTPUT_VARIABLE OUT ERROR_VARIABLE OUT) - if (RET) - string(REPLACE \"\\n\" \"\\n \" OUT \${OUT}) - message(FATAL_ERROR \" Command sysrepoctl install failed:\\n \${OUT}\") - endif() - - if (\${MODULE_NAME} STREQUAL ietf-netconf-server) - set(FEATURES listen ssh-listen tls-listen call-home ssh-call-home tls-call-home) - else() - set(FEATURES authentication local-users) - endif() - foreach(FEATURE IN LISTS FEATURES) - execute_process(COMMAND ${SYSREPOCTL_EXECUTABLE} -m \${MODULE_NAME} -e \${FEATURE} RESULT_VARIABLE RET OUTPUT_VARIABLE OUT ERROR_VARIABLE OUT) - if (RET) - string(REPLACE \"\\n\" \"\\n \" OUT \${OUT}) - message(FATAL_ERROR \" Command sysrepoctl enable feature failed:\\n \${OUT}\") - endif() - endforeach() - - else() - message(STATUS \"Module \${MODULE_NAME} already in sysrepo.\") - if (\${MODULE_NAME} STREQUAL ietf-netconf-server) - set(FEATURES listen ssh-listen tls-listen call-home ssh-call-home tls-call-home) - else() - set(FEATURES authentication local-users) - endif() - foreach(FEATURE IN LISTS FEATURES) - if (NOT \"\${INSTALLED_MODULE_LINE}\" MATCHES \"\${FEATURE}\") - execute_process(COMMAND ${SYSREPOCTL_EXECUTABLE} -m \${MODULE_NAME} -e \${FEATURE} RESULT_VARIABLE RET OUTPUT_VARIABLE OUT ERROR_VARIABLE OUT) - if (RET) - string(REPLACE \"\\n\" \"\\n \" OUT \${OUT}) - message(FATAL_ERROR \" Command sysrepoctl enable feature failed:\\n \${OUT}\") - endif() - endif() - endforeach() - endif() - endforeach() - - execute_process(COMMAND ${SYSREPOCFG_EXECUTABLE} -d startup --export ietf-netconf-server RESULT_VARIABLE RET OUTPUT_VARIABLE OUT ERROR_VARIABLE OUT) - if (RET) - string(REPLACE \"\\n\" \"\\n \" OUT \${OUT}) - message(FATAL_ERROR \" Command sysrepocfg export failed:\\n \${OUT}\") - endif() - - if (OUT) - message(STATUS \"Some NETCONF server configuration set, it will not be changed.\") - else() - execute_process(COMMAND ${SYSREPOCFG_EXECUTABLE} -d startup -i ${CMAKE_SOURCE_DIR}/stock_config.xml ietf-netconf-server RESULT_VARIABLE RET OUTPUT_VARIABLE OUT ERROR_VARIABLE OUT) - if (RET) - string(REPLACE \"\\n\" \"\\n \" OUT \${OUT}) - message(FATAL_ERROR \" Command sysrepocfg import failed:\\n \${OUT}\") - endif() - message(STATUS \"Default NETCONF server configuration imported (SSH listen on 0.0.0.0:830).\") - endif() - - endif()") + set(ENV{SYSREPOCTL} ${SYSREPOCTL_EXECUTABLE}) + set(ENV{SYSREPOCFG} ${SYSREPOCFG_EXECUTABLE}) + set(ENV{SYSREPOCTL_ROOT_PERMS} SYSREPOCTL_ROOT_PERMS) + execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/scripts/model-install.sh)") endif() configure_file("${PROJECT_SOURCE_DIR}/config.h.in" "${PROJECT_BINARY_DIR}/config.h" ESCAPE_QUOTES @ONLY) diff --git a/server/scripts/model-install.sh b/server/scripts/model-install.sh new file mode 100755 index 000000000..1f3890ee5 --- /dev/null +++ b/server/scripts/model-install.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +set -eux -o pipefail + +shopt -s failglob + +local_path=$(dirname $0) + +: ${SYSREPOCTL:=sysrepoctl} +: ${SYSREPOCFG:=sysrepocfg} +: ${SYSREPOCTL_ROOT_PERMS:=-o root:root -p 600} +: ${STOCK_CONFIG:=$local_path/../stock_config.xml} +: ${YANG_DIR:=$local_path/../../modules} + +install_yang_module() { + module=$1 + + if ! $SYSREPOCTL -l | grep "$module[^|]*|[^|]*| Installed[^\\n]*"; then + $SYSREPOCTL -i -g ${YANG_DIR}/$module.yang $SYSREPOCTL_ROOT_PERMS + fi +} + +if ! $SYSREPOCTL -l | grep "ietf-keystore [^\\n]*"; then + exit 0 +fi + +install_yang_module ietf-netconf-server +for f in listen ssh-listen tls-listen call-home ssh-call-home tls-call-home; do + $SYSREPOCTL -m ietf-netconf-server -e $f +done + +install_yang_module ietf-system +for f in authentication local-users; do + $SYSREPOCTL -m ietf-system -e $f +done + +if [ -n "$($SYSREPOCFG -d startup --export ietf-netconf-server)" ]; then + exit 0 +fi + +$SYSREPOCFG -d startup -i $STOCK_CONFIG ietf-netconf-server From edcdcb690449647af80e77a5b80530b928217874 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kundr=C3=A1t?= Date: Mon, 28 May 2018 17:29:33 +0200 Subject: [PATCH 73/87] Enable pre-provisioning of host keys again Commit f9dafad added a method of overriding the heuristics for checking the existing openssh-style host key. This got accidentally removed in 0970cea. This patch restores an option for configuring the NETCONF server so that it expects a particular file in the keystored's directory at runtime. This is handy for e.g. buildroot and for avoiding having to run scripts at the target system. --- keystored/CMakeLists.txt | 10 ++++++++++ keystored/scripts/ssh-key-import.sh | 5 ++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/keystored/CMakeLists.txt b/keystored/CMakeLists.txt index 760e12aae..7239c033a 100644 --- a/keystored/CMakeLists.txt +++ b/keystored/CMakeLists.txt @@ -120,6 +120,15 @@ if (MODEL_INSTALL) execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/scripts/model-install.sh)") endif() +# Use KEYSTORED_DEFER_SSH_KEY=ON to skip automatic key conversion. +# Some external build/deploy script is then responsible for providing an SSH +# host key in a PEM format at runtime. +if (NOT KEYSTORED_DEFER_SSH_KEY) + set(KEYSTORED_CHECK_SSH_KEY 1) +else() + set(KEYSTORED_CHECK_SSH_KEY 0) +endif() + option(SSH_KEY_INSTALL "Enable ssh key import" ON) if (SSH_KEY_INSTALL) install(CODE " @@ -127,6 +136,7 @@ if (SSH_KEY_INSTALL) set(ENV{CHMOD} ${CHMOD_EXECUTABLE}) set(ENV{OPENSSL} ${OPENSSL_EXECUTABLE}) set(ENV{KEYSTORED_KEYS_DIR} ${KEYSTORED_KEYS_DIR}) + set(ENV{KEYSTORED_CHECK_SSH_KEY} ${KEYSTORED_CHECK_SSH_KEY}) execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/scripts/ssh-key-import.sh)") endif() diff --git a/keystored/scripts/ssh-key-import.sh b/keystored/scripts/ssh-key-import.sh index a1761a272..7ea088d28 100755 --- a/keystored/scripts/ssh-key-import.sh +++ b/keystored/scripts/ssh-key-import.sh @@ -16,7 +16,10 @@ if [ -n "$($SYSREPOCFG -d startup --export ietf-keystore)" ]; then exit 0 fi -if [ -f /etc/ssh/ssh_host_rsa_key ]; then +if [ $KEYSTORED_CHECK_SSH_KEY -eq 0 ]; then + echo "Warning: Assuming that an external script will provide the SSH key in a PEM format at \"${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem\"." + $SYSREPOCFG -d startup -i ${STOCK_KEY_CONFIG} ietf-keystore +elif [ -f /etc/ssh/ssh_host_rsa_key ]; then cp /etc/ssh/ssh_host_rsa_key ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem $CHMOD go-rw ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem $OPENSSL rsa -pubout -in ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem \ From e844abdf7f07bf14cb9f627c45f6e86c98301447 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kundr=C3=A1t?= Date: Mon, 28 May 2018 17:30:28 +0200 Subject: [PATCH 74/87] server, keystored: Let IDEs work with the install scripts Some IDEs parse CMake's output and provide an UI way of visiting files which somehow "belong" to a given project. This change makes these files reachable from within WtCreator for example. --- keystored/CMakeLists.txt | 5 +++++ server/CMakeLists.txt | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/keystored/CMakeLists.txt b/keystored/CMakeLists.txt index 7239c033a..db4537af5 100644 --- a/keystored/CMakeLists.txt +++ b/keystored/CMakeLists.txt @@ -140,5 +140,10 @@ if (SSH_KEY_INSTALL) execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/scripts/ssh-key-import.sh)") endif() +add_custom_target(install-scripts-ide + scripts/model-install.sh + scripts/ssh-key-import.sh +) + # plugins should be installed into sysrepo plugins dir install(TARGETS keystored DESTINATION ${SR_PLUGINS_DIR}) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index a7f3e8fdb..ce6ebdf34 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -177,6 +177,10 @@ if (ENABLE_CONFIGURATION) execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/scripts/model-install.sh)") endif() +add_custom_target(install-scripts-ide + scripts/model-install.sh +) + configure_file("${PROJECT_SOURCE_DIR}/config.h.in" "${PROJECT_BINARY_DIR}/config.h" ESCAPE_QUOTES @ONLY) include_directories(${PROJECT_BINARY_DIR}) From ae72fff2df07abd932597dc9529d3c997744da08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kundr=C3=A1t?= Date: Tue, 29 May 2018 09:45:45 +0200 Subject: [PATCH 75/87] keystored: Check the hostkey for readability at install time If the host RSA key file does not exist or if it is not readable, log a warning and do nothing. --- keystored/scripts/ssh-key-import.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/keystored/scripts/ssh-key-import.sh b/keystored/scripts/ssh-key-import.sh index 7ea088d28..ef8e3d2c9 100755 --- a/keystored/scripts/ssh-key-import.sh +++ b/keystored/scripts/ssh-key-import.sh @@ -19,10 +19,12 @@ fi if [ $KEYSTORED_CHECK_SSH_KEY -eq 0 ]; then echo "Warning: Assuming that an external script will provide the SSH key in a PEM format at \"${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem\"." $SYSREPOCFG -d startup -i ${STOCK_KEY_CONFIG} ietf-keystore -elif [ -f /etc/ssh/ssh_host_rsa_key ]; then +elif [ -r /etc/ssh/ssh_host_rsa_key ]; then cp /etc/ssh/ssh_host_rsa_key ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem $CHMOD go-rw ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem $OPENSSL rsa -pubout -in ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem \ -out ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pub.pem $SYSREPOCFG -d startup -i ${STOCK_KEY_CONFIG} ietf-keystore +else + echo "Warning: Cannot read the SSH hostkey at /etc/ssh/ssh_host_rsa_key, skipping" fi From 821383a801290351518f367b9497d00a869a2da0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kundr=C3=A1t?= Date: Thu, 24 May 2018 18:29:44 +0200 Subject: [PATCH 76/87] Better defaults for listening configuration - use more descriptive names of the configuration - nuke the "test" prefixes --- server/stock_config.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/stock_config.xml b/server/stock_config.xml index 4eb91003b..fc9c060af 100644 --- a/server/stock_config.xml +++ b/server/stock_config.xml @@ -1,13 +1,13 @@ - test_ssh_listen_endpt + all-interfaces
0.0.0.0
830 - test_ssh_listen_key + imported SSH key ssh_host_rsa_key From 9dc9dcdc909b0e8f4ad7191940de20a41dce81ec Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Tue, 29 May 2018 15:46:54 +0200 Subject: [PATCH 77/87] server TEST libnetconf2 internally changed --- server/tests/config.h.in | 80 +++++++++++++++++------------ server/tests/test_close_session.c | 26 ++++++---- server/tests/test_copy_config.c | 26 ++++++---- server/tests/test_edit_get_config.c | 26 ++++++---- server/tests/test_generic.c | 26 ++++++---- server/tests/test_get.c | 26 ++++++---- server/tests/test_kill.c | 26 ++++++---- server/tests/test_notif.c | 26 ++++++---- server/tests/test_un_lock.c | 26 ++++++---- 9 files changed, 168 insertions(+), 120 deletions(-) diff --git a/server/tests/config.h.in b/server/tests/config.h.in index 4dfdb39df..175398d82 100755 --- a/server/tests/config.h.in +++ b/server/tests/config.h.in @@ -24,62 +24,78 @@ #include /* taken from libnetconf2 session_p.h private header */ + struct nc_session { - NC_STATUS status; - NC_SESSION_TERM_REASON term_reason; - uint32_t killed_by; - int side; - - uint32_t id; - int version; - - NC_TRANSPORT_IMPL ti_type; - pthread_mutex_t *ti_lock; - pthread_cond_t *ti_cond; - volatile int *ti_inuse; + int status; /**< status of the session */ + NC_SESSION_TERM_REASON term_reason; /**< reason of termination, if status is NC_STATUS_INVALID */ + uint32_t killed_by; /**< session responsible for termination, if term_reason is NC_SESSION_TERM_KILLED */ + int side; /**< side of the session: client or server */ + + /* NETCONF data */ + uint32_t id; /**< NETCONF session ID (session-id-type) */ + int version; /**< NETCONF protocol version */ + + /* Transport implementation */ + NC_TRANSPORT_IMPL ti_type; /**< transport implementation type to select items from ti union */ + pthread_mutex_t *io_lock; /**< input/output lock, note that in case of libssh TI, it will be shared + with other NETCONF sessions on the same SSH session (but different SSH channel) */ + union { struct { - int in; - int out; - } fd; + int in; /**< input file descriptor */ + int out; /**< output file descriptor */ + } fd; /**< NC_TI_FD transport implementation structure */ #ifdef NC_ENABLED_SSH struct { void *channel; void *session; - struct nc_session *next; + struct nc_session *next; /**< pointer to the next NETCONF session on the same + SSH session, but different SSH channel. If no such session exists, it is NULL. + otherwise there is a ring list of the NETCONF sessions */ } libssh; #endif #ifdef NC_ENABLED_TLS - void *tls; + SSL *tls; #endif - } ti; + } ti; /**< transport implementation data */ const char *username; const char *host; uint16_t port; - struct ly_ctx *ctx; - void *data; - uint8_t flags; + /* other */ + struct ly_ctx *ctx; /**< libyang context of the session */ + void *data; /**< arbitrary user data */ + uint8_t flags; /**< various flags of the session - TODO combine with status and/or side */ union { struct { + /* client side only data */ uint64_t msgid; - const char **cpblts; - struct nc_msg_cont *replies; - struct nc_msg_cont *notifs; - volatile pthread_t *ntf_tid; + char **cpblts; /**< list of server's capabilities on client side */ + struct nc_msg_cont *replies; /**< queue for RPC replies received instead of notifications */ + struct nc_msg_cont *notifs; /**< queue for notifications received instead of RPC reply */ + volatile pthread_t *ntf_tid; /**< running notifications receiving thread */ } client; struct { - time_t session_start; - time_t last_rpc; - int ntf_status; - pthread_mutex_t *ch_lock; - pthread_cond_t *ch_cond; + /* server side only data */ + time_t session_start; /**< real time the session was created */ + time_t last_rpc; /**< monotonic time (seconds) the last RPC was received on this session */ + int ntf_status; /**< flag whether the session is subscribed to any stream */ + + pthread_mutex_t *rpc_lock; /**< lock indicating RPC processing, this lock is always locked before io_lock!! */ + pthread_cond_t *rpc_cond; /**< RPC condition (tied with rpc_lock and rpc_inuse) */ + volatile int *rpc_inuse; /**< variable indicating whether there is RPC being processed or not (tied with + rpc_cond and rpc_lock) */ + + pthread_mutex_t *ch_lock; /**< Call Home thread lock */ + pthread_cond_t *ch_cond; /**< Call Home thread condition */ + + /* server flags */ #ifdef NC_ENABLED_SSH - uint16_t ssh_auth_attempts; + uint16_t ssh_auth_attempts; /**< number of failed SSH authentication attempts */ #endif #ifdef NC_ENABLED_TLS - void *client_cert; + X509 *client_cert; /**< TLS client certificate if used for authentication */ #endif } server; } opts; diff --git a/server/tests/test_close_session.c b/server/tests/test_close_session.c index a9be228d8..33a0734cd 100644 --- a/server/tests/test_close_session.c +++ b/server/tests/test_close_session.c @@ -172,12 +172,14 @@ __wrap_nc_accept(int timeout, struct nc_session **session) (*session)->status = NC_STATUS_RUNNING; (*session)->side = 1; (*session)->id = 1; - (*session)->ti_lock = malloc(sizeof *(*session)->ti_lock); - pthread_mutex_init((*session)->ti_lock, NULL); - (*session)->ti_cond = malloc(sizeof *(*session)->ti_cond); - pthread_cond_init((*session)->ti_cond, NULL); - (*session)->ti_inuse = malloc(sizeof *(*session)->ti_inuse); - *(*session)->ti_inuse = 0; + (*session)->io_lock = malloc(sizeof *(*session)->io_lock); + pthread_mutex_init((*session)->io_lock, NULL); + (*session)->opts.server.rpc_lock = malloc(sizeof *(*session)->opts.server.rpc_lock); + pthread_mutex_init((*session)->opts.server.rpc_lock, NULL); + (*session)->opts.server.rpc_cond = malloc(sizeof *(*session)->opts.server.rpc_cond); + pthread_cond_init((*session)->opts.server.rpc_cond, NULL); + (*session)->opts.server.rpc_inuse = malloc(sizeof *(*session)->opts.server.rpc_inuse); + *(*session)->opts.server.rpc_inuse = 0; (*session)->ti_type = NC_TI_FD; (*session)->ti.fd.in = pipes[1][0]; (*session)->ti.fd.out = pipes[0][1]; @@ -203,11 +205,13 @@ __wrap_nc_session_free(struct nc_session *session, void (*data_free)(void *)) if (data_free) { data_free(session->data); } - pthread_mutex_destroy(session->ti_lock); - free(session->ti_lock); - pthread_cond_destroy(session->ti_cond); - free(session->ti_cond); - free((int *)session->ti_inuse); + pthread_mutex_destroy(session->io_lock); + free(session->io_lock); + pthread_mutex_destroy(session->opts.server.rpc_lock); + free(session->opts.server.rpc_lock); + pthread_cond_destroy(session->opts.server.rpc_cond); + free(session->opts.server.rpc_cond); + free((int *)session->opts.server.rpc_inuse); free(session); } diff --git a/server/tests/test_copy_config.c b/server/tests/test_copy_config.c index 53f94e045..c6ed12ff0 100644 --- a/server/tests/test_copy_config.c +++ b/server/tests/test_copy_config.c @@ -361,12 +361,14 @@ __wrap_nc_accept(int timeout, struct nc_session **session) (*session)->status = NC_STATUS_RUNNING; (*session)->side = 1; (*session)->id = 1; - (*session)->ti_lock = malloc(sizeof *(*session)->ti_lock); - pthread_mutex_init((*session)->ti_lock, NULL); - (*session)->ti_cond = malloc(sizeof *(*session)->ti_cond); - pthread_cond_init((*session)->ti_cond, NULL); - (*session)->ti_inuse = malloc(sizeof *(*session)->ti_inuse); - *(*session)->ti_inuse = 0; + (*session)->io_lock = malloc(sizeof *(*session)->io_lock); + pthread_mutex_init((*session)->io_lock, NULL); + (*session)->opts.server.rpc_lock = malloc(sizeof *(*session)->opts.server.rpc_lock); + pthread_mutex_init((*session)->opts.server.rpc_lock, NULL); + (*session)->opts.server.rpc_cond = malloc(sizeof *(*session)->opts.server.rpc_cond); + pthread_cond_init((*session)->opts.server.rpc_cond, NULL); + (*session)->opts.server.rpc_inuse = malloc(sizeof *(*session)->opts.server.rpc_inuse); + *(*session)->opts.server.rpc_inuse = 0; (*session)->ti_type = NC_TI_FD; (*session)->ti.fd.in = pipes[1][0]; (*session)->ti.fd.out = pipes[0][1]; @@ -392,11 +394,13 @@ __wrap_nc_session_free(struct nc_session *session, void (*data_free)(void *)) if (data_free) { data_free(session->data); } - pthread_mutex_destroy(session->ti_lock); - free(session->ti_lock); - pthread_cond_destroy(session->ti_cond); - free(session->ti_cond); - free((int *)session->ti_inuse); + pthread_mutex_destroy(session->io_lock); + free(session->io_lock); + pthread_mutex_destroy(session->opts.server.rpc_lock); + free(session->opts.server.rpc_lock); + pthread_cond_destroy(session->opts.server.rpc_cond); + free(session->opts.server.rpc_cond); + free((int *)session->opts.server.rpc_inuse); free(session); } diff --git a/server/tests/test_edit_get_config.c b/server/tests/test_edit_get_config.c index a4dbd31b8..a9318ded6 100755 --- a/server/tests/test_edit_get_config.c +++ b/server/tests/test_edit_get_config.c @@ -444,12 +444,14 @@ __wrap_nc_accept(int timeout, struct nc_session **session) (*session)->status = NC_STATUS_RUNNING; (*session)->side = 1; (*session)->id = 1; - (*session)->ti_lock = malloc(sizeof *(*session)->ti_lock); - pthread_mutex_init((*session)->ti_lock, NULL); - (*session)->ti_cond = malloc(sizeof *(*session)->ti_cond); - pthread_cond_init((*session)->ti_cond, NULL); - (*session)->ti_inuse = malloc(sizeof *(*session)->ti_inuse); - *(*session)->ti_inuse = 0; + (*session)->io_lock = malloc(sizeof *(*session)->io_lock); + pthread_mutex_init((*session)->io_lock, NULL); + (*session)->opts.server.rpc_lock = malloc(sizeof *(*session)->opts.server.rpc_lock); + pthread_mutex_init((*session)->opts.server.rpc_lock, NULL); + (*session)->opts.server.rpc_cond = malloc(sizeof *(*session)->opts.server.rpc_cond); + pthread_cond_init((*session)->opts.server.rpc_cond, NULL); + (*session)->opts.server.rpc_inuse = malloc(sizeof *(*session)->opts.server.rpc_inuse); + *(*session)->opts.server.rpc_inuse = 0; (*session)->ti_type = NC_TI_FD; (*session)->ti.fd.in = pipes[1][0]; (*session)->ti.fd.out = pipes[0][1]; @@ -475,11 +477,13 @@ __wrap_nc_session_free(struct nc_session *session, void (*data_free)(void *)) if (data_free) { data_free(session->data); } - pthread_mutex_destroy(session->ti_lock); - free(session->ti_lock); - pthread_cond_destroy(session->ti_cond); - free(session->ti_cond); - free((int *)session->ti_inuse); + pthread_mutex_destroy(session->io_lock); + free(session->io_lock); + pthread_mutex_destroy(session->opts.server.rpc_lock); + free(session->opts.server.rpc_lock); + pthread_cond_destroy(session->opts.server.rpc_cond); + free(session->opts.server.rpc_cond); + free((int *)session->opts.server.rpc_inuse); free(session); } diff --git a/server/tests/test_generic.c b/server/tests/test_generic.c index 7bff062f5..9f4a20347 100644 --- a/server/tests/test_generic.c +++ b/server/tests/test_generic.c @@ -231,12 +231,14 @@ __wrap_nc_accept(int timeout, struct nc_session **session) (*session)->status = NC_STATUS_RUNNING; (*session)->side = 1; (*session)->id = 1; - (*session)->ti_lock = malloc(sizeof *(*session)->ti_lock); - pthread_mutex_init((*session)->ti_lock, NULL); - (*session)->ti_cond = malloc(sizeof *(*session)->ti_cond); - pthread_cond_init((*session)->ti_cond, NULL); - (*session)->ti_inuse = malloc(sizeof *(*session)->ti_inuse); - *(*session)->ti_inuse = 0; + (*session)->io_lock = malloc(sizeof *(*session)->io_lock); + pthread_mutex_init((*session)->io_lock, NULL); + (*session)->opts.server.rpc_lock = malloc(sizeof *(*session)->opts.server.rpc_lock); + pthread_mutex_init((*session)->opts.server.rpc_lock, NULL); + (*session)->opts.server.rpc_cond = malloc(sizeof *(*session)->opts.server.rpc_cond); + pthread_cond_init((*session)->opts.server.rpc_cond, NULL); + (*session)->opts.server.rpc_inuse = malloc(sizeof *(*session)->opts.server.rpc_inuse); + *(*session)->opts.server.rpc_inuse = 0; (*session)->ti_type = NC_TI_FD; (*session)->ti.fd.in = pipes[1][0]; (*session)->ti.fd.out = pipes[0][1]; @@ -262,11 +264,13 @@ __wrap_nc_session_free(struct nc_session *session, void (*data_free)(void *)) if (data_free) { data_free(session->data); } - pthread_mutex_destroy(session->ti_lock); - free(session->ti_lock); - pthread_cond_destroy(session->ti_cond); - free(session->ti_cond); - free((int *)session->ti_inuse); + pthread_mutex_destroy(session->io_lock); + free(session->io_lock); + pthread_mutex_destroy(session->opts.server.rpc_lock); + free(session->opts.server.rpc_lock); + pthread_cond_destroy(session->opts.server.rpc_cond); + free(session->opts.server.rpc_cond); + free((int *)session->opts.server.rpc_inuse); free(session); } diff --git a/server/tests/test_get.c b/server/tests/test_get.c index 5ab602e87..b87d285d1 100644 --- a/server/tests/test_get.c +++ b/server/tests/test_get.c @@ -200,12 +200,14 @@ __wrap_nc_accept(int timeout, struct nc_session **session) (*session)->status = NC_STATUS_RUNNING; (*session)->side = 1; (*session)->id = 1; - (*session)->ti_lock = malloc(sizeof *(*session)->ti_lock); - pthread_mutex_init((*session)->ti_lock, NULL); - (*session)->ti_cond = malloc(sizeof *(*session)->ti_cond); - pthread_cond_init((*session)->ti_cond, NULL); - (*session)->ti_inuse = malloc(sizeof *(*session)->ti_inuse); - *(*session)->ti_inuse = 0; + (*session)->io_lock = malloc(sizeof *(*session)->io_lock); + pthread_mutex_init((*session)->io_lock, NULL); + (*session)->opts.server.rpc_lock = malloc(sizeof *(*session)->opts.server.rpc_lock); + pthread_mutex_init((*session)->opts.server.rpc_lock, NULL); + (*session)->opts.server.rpc_cond = malloc(sizeof *(*session)->opts.server.rpc_cond); + pthread_cond_init((*session)->opts.server.rpc_cond, NULL); + (*session)->opts.server.rpc_inuse = malloc(sizeof *(*session)->opts.server.rpc_inuse); + *(*session)->opts.server.rpc_inuse = 0; (*session)->ti_type = NC_TI_FD; (*session)->ti.fd.in = pipes[1][0]; (*session)->ti.fd.out = pipes[0][1]; @@ -231,11 +233,13 @@ __wrap_nc_session_free(struct nc_session *session, void (*data_free)(void *)) if (data_free) { data_free(session->data); } - pthread_mutex_destroy(session->ti_lock); - free(session->ti_lock); - pthread_cond_destroy(session->ti_cond); - free(session->ti_cond); - free((int *)session->ti_inuse); + pthread_mutex_destroy(session->io_lock); + free(session->io_lock); + pthread_mutex_destroy(session->opts.server.rpc_lock); + free(session->opts.server.rpc_lock); + pthread_cond_destroy(session->opts.server.rpc_cond); + free(session->opts.server.rpc_cond); + free((int *)session->opts.server.rpc_inuse); free(session); } diff --git a/server/tests/test_kill.c b/server/tests/test_kill.c index c3b03a8a0..70927e697 100644 --- a/server/tests/test_kill.c +++ b/server/tests/test_kill.c @@ -191,12 +191,14 @@ __wrap_nc_accept(int timeout, struct nc_session **session) (*session)->status = NC_STATUS_RUNNING; (*session)->side = 1; (*session)->id = initialized + 1; - (*session)->ti_lock = malloc(sizeof *(*session)->ti_lock); - pthread_mutex_init((*session)->ti_lock, NULL); - (*session)->ti_cond = malloc(sizeof *(*session)->ti_cond); - pthread_cond_init((*session)->ti_cond, NULL); - (*session)->ti_inuse = malloc(sizeof *(*session)->ti_inuse); - *(*session)->ti_inuse = 0; + (*session)->io_lock = malloc(sizeof *(*session)->io_lock); + pthread_mutex_init((*session)->io_lock, NULL); + (*session)->opts.server.rpc_lock = malloc(sizeof *(*session)->opts.server.rpc_lock); + pthread_mutex_init((*session)->opts.server.rpc_lock, NULL); + (*session)->opts.server.rpc_cond = malloc(sizeof *(*session)->opts.server.rpc_cond); + pthread_cond_init((*session)->opts.server.rpc_cond, NULL); + (*session)->opts.server.rpc_inuse = malloc(sizeof *(*session)->opts.server.rpc_inuse); + *(*session)->opts.server.rpc_inuse = 0; (*session)->ti_type = NC_TI_FD; (*session)->ti.fd.in = pipes[2 * initialized + 1][0]; (*session)->ti.fd.out = pipes[2 * initialized][1]; @@ -222,11 +224,13 @@ __wrap_nc_session_free(struct nc_session *session, void (*data_free)(void *)) if (data_free) { data_free(session->data); } - pthread_mutex_destroy(session->ti_lock); - free(session->ti_lock); - pthread_cond_destroy(session->ti_cond); - free(session->ti_cond); - free((int *)session->ti_inuse); + pthread_mutex_destroy(session->io_lock); + free(session->io_lock); + pthread_mutex_destroy(session->opts.server.rpc_lock); + free(session->opts.server.rpc_lock); + pthread_cond_destroy(session->opts.server.rpc_cond); + free(session->opts.server.rpc_cond); + free((int *)session->opts.server.rpc_inuse); free(session); } diff --git a/server/tests/test_notif.c b/server/tests/test_notif.c index 8b7deb24e..38cb7e80e 100644 --- a/server/tests/test_notif.c +++ b/server/tests/test_notif.c @@ -269,12 +269,14 @@ __wrap_nc_accept(int timeout, struct nc_session **session) (*session)->status = NC_STATUS_RUNNING; (*session)->side = 1; (*session)->id = no; - (*session)->ti_lock = malloc(sizeof *(*session)->ti_lock); - pthread_mutex_init((*session)->ti_lock, NULL); - (*session)->ti_cond = malloc(sizeof *(*session)->ti_cond); - pthread_cond_init((*session)->ti_cond, NULL); - (*session)->ti_inuse = malloc(sizeof *(*session)->ti_inuse); - *(*session)->ti_inuse = 0; + (*session)->io_lock = malloc(sizeof *(*session)->io_lock); + pthread_mutex_init((*session)->io_lock, NULL); + (*session)->opts.server.rpc_lock = malloc(sizeof *(*session)->opts.server.rpc_lock); + pthread_mutex_init((*session)->opts.server.rpc_lock, NULL); + (*session)->opts.server.rpc_cond = malloc(sizeof *(*session)->opts.server.rpc_cond); + pthread_cond_init((*session)->opts.server.rpc_cond, NULL); + (*session)->opts.server.rpc_inuse = malloc(sizeof *(*session)->opts.server.rpc_inuse); + *(*session)->opts.server.rpc_inuse = 0; (*session)->ti_type = NC_TI_FD; (*session)->ti.fd.in = pipes[1][0]; (*session)->ti.fd.out = pipes[0][1]; @@ -300,11 +302,13 @@ __wrap_nc_session_free(struct nc_session *session, void (*data_free)(void *)) if (data_free) { data_free(session->data); } - pthread_mutex_destroy(session->ti_lock); - free(session->ti_lock); - pthread_cond_destroy(session->ti_cond); - free(session->ti_cond); - free((int *)session->ti_inuse); + pthread_mutex_destroy(session->io_lock); + free(session->io_lock); + pthread_mutex_destroy(session->opts.server.rpc_lock); + free(session->opts.server.rpc_lock); + pthread_cond_destroy(session->opts.server.rpc_cond); + free(session->opts.server.rpc_cond); + free((int *)session->opts.server.rpc_inuse); free(session); } diff --git a/server/tests/test_un_lock.c b/server/tests/test_un_lock.c index a3fe0e624..ba28a82eb 100644 --- a/server/tests/test_un_lock.c +++ b/server/tests/test_un_lock.c @@ -246,12 +246,14 @@ __wrap_nc_accept(int timeout, struct nc_session **session) (*session)->status = NC_STATUS_RUNNING; (*session)->side = 1; (*session)->id = 1; - (*session)->ti_lock = malloc(sizeof *(*session)->ti_lock); - pthread_mutex_init((*session)->ti_lock, NULL); - (*session)->ti_cond = malloc(sizeof *(*session)->ti_cond); - pthread_cond_init((*session)->ti_cond, NULL); - (*session)->ti_inuse = malloc(sizeof *(*session)->ti_inuse); - *(*session)->ti_inuse = 0; + (*session)->io_lock = malloc(sizeof *(*session)->io_lock); + pthread_mutex_init((*session)->io_lock, NULL); + (*session)->opts.server.rpc_lock = malloc(sizeof *(*session)->opts.server.rpc_lock); + pthread_mutex_init((*session)->opts.server.rpc_lock, NULL); + (*session)->opts.server.rpc_cond = malloc(sizeof *(*session)->opts.server.rpc_cond); + pthread_cond_init((*session)->opts.server.rpc_cond, NULL); + (*session)->opts.server.rpc_inuse = malloc(sizeof *(*session)->opts.server.rpc_inuse); + *(*session)->opts.server.rpc_inuse = 0; (*session)->ti_type = NC_TI_FD; (*session)->ti.fd.in = pipes[1][0]; (*session)->ti.fd.out = pipes[0][1]; @@ -277,11 +279,13 @@ __wrap_nc_session_free(struct nc_session *session, void (*data_free)(void *)) if (data_free) { data_free(session->data); } - pthread_mutex_destroy(session->ti_lock); - free(session->ti_lock); - pthread_cond_destroy(session->ti_cond); - free(session->ti_cond); - free((int *)session->ti_inuse); + pthread_mutex_destroy(session->io_lock); + free(session->io_lock); + pthread_mutex_destroy(session->opts.server.rpc_lock); + free(session->opts.server.rpc_lock); + pthread_cond_destroy(session->opts.server.rpc_cond); + free(session->opts.server.rpc_cond); + free((int *)session->opts.server.rpc_inuse); free(session); } From 165b4a02b7ba484de0cb31bd6f9c4f56ec02b9f0 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Tue, 29 May 2018 15:51:00 +0200 Subject: [PATCH 78/87] Revert "server CHANGE adjustable notification send timeout" This reverts commit afb776547cfdd5e64a0609bbb7d1ea7f61890d83. --- server/CMakeLists.txt | 3 +-- server/config.h.in | 4 ---- server/op_notifications.c | 8 ++++---- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index ce6ebdf34..e1b6b36de 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -33,9 +33,8 @@ else() option(ENABLE_VALGRIND_TESTS "Build tests with valgrind" OFF) endif() option(ENABLE_CONFIGURATION "Enable server configuration" ON) -set(THREAD_COUNT 5 CACHE INTEGER "Number of threads accepting new sessions and handling requests") +set(THREAD_COUNT 5 CACHE STRING "Number of threads accepting new sessions and handling requests") set(DEFAULT_HOST_KEY "/etc/ssh/ssh_host_rsa_key" CACHE STRING "Default server host key (used only if configuration is disabled)") -set(NOTIF_TIMEOUT 5 CACHE INTEGER "Maximum number of seconds that the server will wait for session lock when sending a notification") # set prefix for the PID file if (NOT PIDFILE_PREFIX) diff --git a/server/config.h.in b/server/config.h.in index 29c789261..fbb9f4202 100644 --- a/server/config.h.in +++ b/server/config.h.in @@ -44,10 +44,6 @@ */ #cmakedefine HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP 1 -/** @brief timeout in s for waiting for session lock when sending a notification - */ -#define NP2SRV_NOTIF_TIMEOUT @NOTIF_TIMEOUT@ - /** @brief timeout in ms for retrying certain sysrepo operations (subscriptions and commit) in case 2 same operations collide */ #define NP2SRV_SR_LOCKED_TIMEOUT 10 diff --git a/server/op_notifications.c b/server/op_notifications.c index 0cfbcdce0..0a76b0377 100644 --- a/server/op_notifications.c +++ b/server/op_notifications.c @@ -80,7 +80,7 @@ np2srv_ntf_replay_sort_send(struct np_subscriber *subscriber) /* send all the replay notifications */ for (i = 0; i < subscriber->replay_notif_count; ++i) { - nc_server_notif_send(subscriber->session, subscriber->replay_notifs[i], NP2SRV_NOTIF_TIMEOUT * 1000); + nc_server_notif_send(subscriber->session, subscriber->replay_notifs[i], 5000); nc_server_notif_free(subscriber->replay_notifs[i]); ncm_session_notification(subscriber->session); } @@ -93,7 +93,7 @@ np2srv_ntf_replay_sort_send(struct np_subscriber *subscriber) mod = ly_ctx_get_module(np2srv.ly_ctx, "nc-notifications", NULL, 1); event = lyd_new(NULL, mod, "replayComplete"); notif = nc_server_notif_new(event, nc_time2datetime(time(NULL), NULL, NULL), NC_PARAMTYPE_FREE); - nc_server_notif_send(subscriber->session, notif, NP2SRV_NOTIF_TIMEOUT * 1000); + nc_server_notif_send(subscriber->session, notif, 5000); nc_server_notif_free(notif); ncm_session_notification(subscriber->session); } @@ -130,7 +130,7 @@ np2srv_ntf_send(struct np_subscriber *subscriber, struct lyd_node *ntf, time_t t if (mod) { filtered_ntf = lyd_new(NULL, mod, "notificationComplete"); ntf_msg = nc_server_notif_new(filtered_ntf, nc_time2datetime(time(NULL), NULL, NULL), NC_PARAMTYPE_FREE); - nc_server_notif_send(subscriber->session, ntf_msg, NP2SRV_NOTIF_TIMEOUT * 1000); + nc_server_notif_send(subscriber->session, ntf_msg, 5000); nc_server_notif_free(ntf_msg); ncm_session_notification(subscriber->session); } else { @@ -169,7 +169,7 @@ np2srv_ntf_send(struct np_subscriber *subscriber, struct lyd_node *ntf, time_t t } if (notif_type == SR_EV_NOTIF_T_REALTIME) { - nc_server_notif_send(subscriber->session, ntf_msg, NP2SRV_NOTIF_TIMEOUT * 1000); + nc_server_notif_send(subscriber->session, ntf_msg, 5000); nc_server_notif_free(ntf_msg); ncm_session_notification(subscriber->session); } else { From a5fdd8daf04cc1fbf3ce74b8e496be1b9b2a1bb9 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Tue, 29 May 2018 15:51:56 +0200 Subject: [PATCH 79/87] server VERSION bump to version 0.5.19 --- server/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index e1b6b36de..7022352c7 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -13,7 +13,7 @@ if(NOT UNIX) endif() # set version -set(NP2SRV_VERSION 0.5.18) +set(NP2SRV_VERSION 0.5.19) # set default build type if not specified by user if(NOT CMAKE_BUILD_TYPE) From af946dcfdc3d4a3e8bd8af764d9d040c74d06c15 Mon Sep 17 00:00:00 2001 From: Andrew Langefeld Date: Wed, 30 May 2018 19:13:33 -0500 Subject: [PATCH 80/87] Unit test for selection node filter on key This commit adds a unit test that demonstrates a selection node subtree filter, where the selection node is a key. In netopeer2@9e793f1, `opget_build_subtree_from_sysrepo()` was modified to call `opget_build_subtree_from_sysrepo_is_key()`. The side-effect is that nodes that are keys are no longer added to the subtree being built up as a response to the get RPC. An empty subtree will be erroneously returned, instead of a subtree with the matching key node(s). --- server/tests/test_edit_get_config.c | 42 ++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/server/tests/test_edit_get_config.c b/server/tests/test_edit_get_config.c index a9318ded6..a2b14cfc4 100755 --- a/server/tests/test_edit_get_config.c +++ b/server/tests/test_edit_get_config.c @@ -236,9 +236,11 @@ __wrap_sr_get_item_next(sr_session_ctx_t *session, sr_val_iter_t *iter, sr_val_t static struct ly_set *ietf_if_set = NULL; const char *xpath = (const char *)iter; char *path; + const char *ietf_interfaces_xpath = "/ietf-interfaces:"; + size_t ietf_interfaces_xpath_len = strlen(ietf_interfaces_xpath); (void)session; - if (!strcmp(xpath, "/ietf-interfaces:*//.") || !strcmp(xpath, "/test-feature-c:*//.")) { + if (!strncmp(xpath, ietf_interfaces_xpath, ietf_interfaces_xpath_len) || !strcmp(xpath, "/test-feature-c:*//.")) { if (!ietf_if_set) { ietf_if_set = lyd_find_path(data, xpath); } @@ -1479,6 +1481,43 @@ test_edit_merge2(void **state) test_read(p_in, get_config_rpl, __LINE__); } +static void +test_get_filter(void **state) +{ + (void)state; /* unused */ + const char *get_config_rpc = + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; + const char *get_config_rpl = + "" + "" + "" + "" + "iface2" + "" + "" + "iface1" + "" + "" + "" + ""; + + test_write(p_out, get_config_rpc, __LINE__); + test_read(p_in, get_config_rpl, __LINE__); +} + static void test_startstop(void **state) { @@ -1500,6 +1539,7 @@ main(void) cmocka_unit_test(test_edit_create3), cmocka_unit_test(test_edit_merge1), cmocka_unit_test(test_edit_merge2), + cmocka_unit_test(test_get_filter), cmocka_unit_test_teardown(test_startstop, np_stop), }; From c3c9711861a16f723f92bcd1ead30c719877a50a Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Thu, 31 May 2018 11:25:14 +0200 Subject: [PATCH 81/87] Revert "server OPTIMIZE do not create list keys" This reverts commit 9e793f1a74325f1b17dba79163cd2e96c7413c96. Fixes #267 --- server/op_get_config.c | 77 ++++-------------------------------------- 1 file changed, 7 insertions(+), 70 deletions(-) diff --git a/server/op_get_config.c b/server/op_get_config.c index 54357dd33..b6af3bf2a 100644 --- a/server/op_get_config.c +++ b/server/op_get_config.c @@ -29,66 +29,6 @@ #include "operations.h" #include "netconf_monitoring.h" -static int -opget_build_subtree_from_sysrepo_is_key(const char *xpath) -{ - const char *last_node, *ptr; - char quote; - int key_len; - - ptr = xpath + strlen(xpath); - - do { - if ((--ptr == xpath) || (ptr[0] == ']')) { - return 0; - } - } while (ptr[0] != '/'); - /* last node name found */ - last_node = ptr + 1; - - /* go through all predicates and compare keys with the last node */ - while ((--ptr != xpath) && (ptr[0] == ']')) { - /* value end */ - if ((--ptr == xpath) || ((ptr[0] != '\'') && (ptr[0] != '"'))) { - return 0; - } - quote = ptr[0]; - - /* skip the value */ - do { - if (--ptr == xpath) { - return 0; - } - } while (ptr[0] != quote); - - /* equals */ - if ((--ptr == xpath) || (ptr[0] != '=')) { - return 0; - } - - /* key length must be at least one */ - if ((--ptr == xpath) || (ptr[0] == '[')) { - return 0; - } - - /* predicate start */ - key_len = 0; - do { - if (--ptr == xpath) { - return 0; - } - ++key_len; - } while (ptr[0] != '['); - - /* compare key name with the last node */ - if (!strncmp(last_node, ptr + 1, key_len) && !last_node[key_len]) { - return 1; - } - } - - return 0; -} - /* add whole subtree */ static int opget_build_subtree_from_sysrepo(sr_session_ctx_t *srs, struct lyd_node **root, const char *subtree_xpath) @@ -116,17 +56,14 @@ opget_build_subtree_from_sysrepo(sr_session_ctx_t *srs, struct lyd_node **root, } while ((!np2srv_sr_get_item_next(srs, sriter, &value, NULL))) { - /* skip list keys, they were created during list instance creation */ - if (!opget_build_subtree_from_sysrepo_is_key(value->xpath)) { - if (op_sr_val_to_lyd_node(*root, value, &node)) { - sr_free_val(value); - sr_free_val_iter(sriter); - return -1; - } + if (op_sr_val_to_lyd_node(*root, value, &node)) { + sr_free_val(value); + sr_free_val_iter(sriter); + return -1; + } - if (!(*root)) { - *root = node; - } + if (!(*root)) { + *root = node; } sr_free_val(value); } From 5bb768d6ef6327af4d7229d2e7a5100e6db34b5f Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Thu, 31 May 2018 11:26:04 +0200 Subject: [PATCH 82/87] server VERSION bump to version 0.5.20 --- server/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 7022352c7..ef77e2cf3 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -13,7 +13,7 @@ if(NOT UNIX) endif() # set version -set(NP2SRV_VERSION 0.5.19) +set(NP2SRV_VERSION 0.5.20) # set default build type if not specified by user if(NOT CMAKE_BUILD_TYPE) From d97b454b72579d6c287c9dc36ed39e5ac0ce27f7 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Fri, 1 Jun 2018 10:24:20 +0200 Subject: [PATCH 83/87] server BUGFIX restart only once Refs #269 --- server/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/server/main.c b/server/main.c index 72c72dc3f..1787503ab 100644 --- a/server/main.c +++ b/server/main.c @@ -1439,6 +1439,7 @@ main(int argc, char *argv[]) /* are we requested to stop or just to restart? */ if (control == LOOP_RESTART) { + control = LOOP_CONTINUE; goto restart; } From c530f393a7c713c66a644f45b63cad1f40092603 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Fri, 1 Jun 2018 10:24:57 +0200 Subject: [PATCH 84/87] server VERSION bump to version 0.5.21 --- server/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index ef77e2cf3..a2b59b52f 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -13,7 +13,7 @@ if(NOT UNIX) endif() # set version -set(NP2SRV_VERSION 0.5.20) +set(NP2SRV_VERSION 0.5.21) # set default build type if not specified by user if(NOT CMAKE_BUILD_TYPE) From 159822332ddd74e2e2437f63ab8b52201d105cc2 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Mon, 4 Jun 2018 09:56:48 +0200 Subject: [PATCH 85/87] server CHANGE do not restart on SIGHUP but terminate This feature required proper init/cleanup of libssh and OpenSSL which was not achieved with all version combinations. System scripts that may need to restart netopeer2 can simply terminate it and start it again. Fixes #269 --- server/main.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/server/main.c b/server/main.c index 1787503ab..36bd77ca8 100644 --- a/server/main.c +++ b/server/main.c @@ -57,8 +57,7 @@ pthread_rwlock_t dslock_rwl = PTHREAD_RWLOCK_INITIALIZER; */ enum LOOPCTRL { LOOP_CONTINUE = 0, /**< Continue processing */ - LOOP_RESTART = 1, /**< restart the process */ - LOOP_STOP = 2 /**< stop the process */ + LOOP_STOP = 1 /**< stop the process */ }; /** @brief flag for main loop */ volatile enum LOOPCTRL control = LOOP_CONTINUE; @@ -207,6 +206,7 @@ signal_handler(int sig) case SIGTERM: case SIGQUIT: case SIGABRT: + case SIGHUP: /* stop the process */ if (quit == 0) { /* first attempt */ @@ -217,11 +217,6 @@ signal_handler(int sig) } control = LOOP_STOP; break; - case SIGHUP: - case SIGUSR1: - /* restart the process */ - control = LOOP_RESTART; - break; #ifdef DEBUG case SIGSEGV: depth = backtrace(stack_buf, STACK_DEPTH); @@ -1369,7 +1364,6 @@ main(int argc, char *argv[]) sigaction(SIGABRT, &action, NULL); sigaction(SIGTERM, &action, NULL); sigaction(SIGHUP, &action, NULL); - sigaction(SIGUSR1, &action, NULL); #ifdef DEBUG sigaction(SIGSEGV, &action, NULL); #endif @@ -1382,7 +1376,6 @@ main(int argc, char *argv[]) ly_set_log_clb(np2log_clb_ly, 1); /* libyang */ sr_log_set_cb(np2log_clb_sr); /* sysrepo, log level is checked by callback */ -restart: /* initiate NETCONF server */ if (server_init()) { ret = EXIT_FAILURE; @@ -1437,11 +1430,5 @@ main(int argc, char *argv[]) /* libyang cleanup */ ly_ctx_destroy(np2srv.ly_ctx, NULL); - /* are we requested to stop or just to restart? */ - if (control == LOOP_RESTART) { - control = LOOP_CONTINUE; - goto restart; - } - return ret; } From 5d55685ba423071b6c219f3ccc6bd8d6d5ad0ab1 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Mon, 4 Jun 2018 09:58:27 +0200 Subject: [PATCH 86/87] server VERSION bump to version 0.5.22 --- server/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index a2b59b52f..cdf606dd4 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -13,7 +13,7 @@ if(NOT UNIX) endif() # set version -set(NP2SRV_VERSION 0.5.21) +set(NP2SRV_VERSION 0.5.22) # set default build type if not specified by user if(NOT CMAKE_BUILD_TYPE) From 948cb7eb4f7b024a4de902597bb8270346ec4ac3 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Wed, 6 Jun 2018 10:07:32 +0200 Subject: [PATCH 87/87] MAINTENANCE release build warnings --- cli/commands.c | 4 ++-- cli/completion.c | 12 +++++++----- server/log.c | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/cli/commands.c b/cli/commands.c index 8ea4199a7..c9d66dd04 100644 --- a/cli/commands.c +++ b/cli/commands.c @@ -201,7 +201,7 @@ static void cli_ntf_clb(struct nc_session *session, const struct nc_notif *notif) { FILE *output = nc_session_get_data(session); - int was_rawmode; + int was_rawmode = 0; if (output == stdout) { if (ls.rawmode) { @@ -504,7 +504,7 @@ static char * trim_top_elem(char *data, const char *top_elem, const char *top_elem_ns) { char *ptr, *prefix = NULL, *buf; - int pref_len, state = 0, quote; + int pref_len = 0, state = 0, quote; /* state: -2 - syntax error, * -1 - top_elem not found, diff --git a/cli/completion.c b/cli/completion.c index 46842e986..e1f14b084 100644 --- a/cli/completion.c +++ b/cli/completion.c @@ -8,7 +8,7 @@ * This source code is licensed under BSD 3-Clause License (the "License"). * You may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * https://opensource.org/licenses/BSD-3-Clause */ @@ -115,9 +115,11 @@ complete_cmd(const char *buf, const char *hint, linenoiseCompletions *lc) char * readinput(const char *instruction, const char *old_tmp, char **new_tmp) { - int tmpfd = -1, ret, size, oldfd; + volatile int tmpfd = -1; + int ret, size, oldfd; pid_t pid, wait_pid; - char* tmpname = NULL, *input = NULL, *old_content = NULL, *ptr, *ptr2; + char* volatile input = NULL, * volatile old_content = NULL; + char *tmpname = NULL, *ptr, *ptr2; /* Create a unique temporary file */ #ifdef HAVE_MKSTEMPS @@ -226,7 +228,7 @@ readinput(const char *instruction, const char *old_tmp, char **new_tmp) lseek(tmpfd, 0, SEEK_SET); /* Read the input */ - input = malloc(size+1); + input = malloc(size + 1); ret = read(tmpfd, input, size); if (ret < size) { ERROR(__func__, "Failed to read from the temporary file (%s).", strerror(errno)); @@ -244,7 +246,7 @@ readinput(const char *instruction, const char *old_tmp, char **new_tmp) /* The user could have deleted or modified the comment, ignore it then */ if (ptr2) { ptr2 += 5; - memmove(ptr, ptr2, strlen(ptr2)+1); + memmove(ptr, ptr2, strlen(ptr2) + 1); /* Save the modified content */ if (ftruncate(tmpfd, 0) == -1) { diff --git a/server/log.c b/server/log.c index 7ce431779..ccd1fc80b 100644 --- a/server/log.c +++ b/server/log.c @@ -149,7 +149,7 @@ void np2log_clb_nc2(NC_VERB_LEVEL level, const char *msg) { struct np2err *e; - int priority; + int priority = LOG_ERR; if (level == NC_VERB_ERROR) { e = np2_err_location();