struct nc_server_reply * my_get_rpc_clb(struct lyd_node *rpc, struct nc_session *session) { assert_string_equal(rpc->schema->name, "get"); assert_ptr_equal(session, server_session); return nc_server_reply_ok(); }
struct nc_server_reply * op_unlock(struct lyd_node *rpc, struct nc_session *ncs) { struct np2_sessions *sessions; sr_datastore_t ds = 0; struct nc_session **dsl = NULL; time_t *dst; struct ly_set *nodeset; const char *dsname; struct nc_server_error *e; struct nc_server_reply *ereply = NULL; /* get sysrepo connections for this session */ sessions = (struct np2_sessions *)nc_session_get_data(ncs); if (np2srv_sr_check_exec_permission(sessions->srs, "/ietf-netconf:unlock", &ereply)) { goto finish; } /* get know which datastore is being affected */ nodeset = lyd_find_path(rpc, "/ietf-netconf:unlock/target/*"); dsname = nodeset->set.d[0]->schema->name; ly_set_free(nodeset); if (!strcmp(dsname, "running")) { ds = SR_DS_RUNNING; dsl = &dslock.running; dst = &dslock.running_time; } else if (!strcmp(dsname, "startup")) { ds = SR_DS_STARTUP; dsl = &dslock.startup; dst = &dslock.startup_time; } else if (!strcmp(dsname, "candidate")) { ds = SR_DS_CANDIDATE; dsl = &dslock.candidate; dst = &dslock.candidate_time; } else { EINT; e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_PROT); nc_err_set_msg(e, np2log_lasterr(), "en"); ereply = nc_server_reply_err(e); goto finish; } if (ds != sessions->ds) { /* update sysrepo session */ if (np2srv_sr_session_switch_ds(sessions->srs, ds, &ereply)) { goto finish; } sessions->ds = ds; } pthread_rwlock_rdlock(&dslock_rwl); if (!(*dsl)) { /* lock is not held */ pthread_rwlock_unlock(&dslock_rwl); 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"); ereply = nc_server_reply_err(e); goto finish; } else { /* lock is held, but by who? */ if ((*dsl) != ncs) { /* by someone else */ pthread_rwlock_unlock(&dslock_rwl); 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"); ereply = nc_server_reply_err(e); goto finish; } } pthread_rwlock_unlock(&dslock_rwl); pthread_rwlock_wrlock(&dslock_rwl); if (np2srv_sr_unlock_datastore(sessions->srs, &ereply)) { /* lock is held outside Netopeer */ pthread_rwlock_unlock(&dslock_rwl); /* 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_server_reply_add_err(ereply, e); goto finish; } /* according to RFC 6241 8.3.5.2, discard changes */ np2srv_sr_discard_changes(sessions->srs, NULL); /* update local information about locks */ *dsl = NULL; *dst = 0; pthread_rwlock_unlock(&dslock_rwl); /* build positive RPC Reply */ ereply = nc_server_reply_ok(); finish: return ereply; }
struct nc_server_reply * op_lock(struct lyd_node *rpc, struct nc_session *ncs) { struct np2_sessions *sessions; sr_datastore_t ds = 0; struct nc_session **dsl = NULL; time_t *dst; struct ly_set *nodeset; struct nc_server_error *e; struct nc_server_reply *ereply = NULL; const char *dsname; /* get sysrepo connections for this session */ sessions = (struct np2_sessions *)nc_session_get_data(ncs); if (np2srv_sr_check_exec_permission(sessions->srs, "/ietf-netconf:lock", &ereply)) { goto finish; } /* get know which datastore is being affected */ nodeset = lyd_find_path(rpc, "/ietf-netconf:lock/target/*"); dsname = nodeset->set.d[0]->schema->name; ly_set_free(nodeset); if (!strcmp(dsname, "running")) { /* TODO additional requirements in case of supporting confirmed-commit */ ds = SR_DS_RUNNING; dsl = &dslock.running; dst = &dslock.running_time; } else if (!strcmp(dsname, "startup")) { ds = SR_DS_STARTUP; dsl = &dslock.startup; dst = &dslock.startup_time; } else if (!strcmp(dsname, "candidate")) { ds = SR_DS_CANDIDATE; dsl = &dslock.candidate; dst = &dslock.candidate_time; } else { EINT; e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_PROT); nc_err_set_msg(e, np2log_lasterr(), "en"); ereply = nc_server_reply_err(e); goto finish; } if (ds != sessions->ds) { /* update sysrepo session */ if (np2srv_sr_session_switch_ds(sessions->srs, ds, &ereply)) { goto finish; } sessions->ds = ds; } pthread_rwlock_rdlock(&dslock_rwl); if (*dsl) { lock_held: /* lock already held */ pthread_rwlock_unlock(&dslock_rwl); 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"); ereply = nc_server_reply_err(e); goto finish; } pthread_rwlock_unlock(&dslock_rwl); pthread_rwlock_wrlock(&dslock_rwl); /* check again dsl, it could change between unlock and wrlock */ if (*dsl) { goto lock_held; } if (np2srv_sr_lock_datastore(sessions->srs, &ereply)) { /* lock is held outside Netopeer */ pthread_rwlock_unlock(&dslock_rwl); /* 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_server_reply_add_err(ereply, e); goto finish; } /* update local information about locks */ *dsl = ncs; *dst = time(NULL); pthread_rwlock_unlock(&dslock_rwl); /* build positive RPC Reply */ ereply = nc_server_reply_ok(); finish: return ereply; }
struct nc_server_reply * op_validate(struct lyd_node *rpc, struct nc_session *ncs) { struct np2_sessions *sessions; struct ly_set *nodeset; struct nc_server_error *e = NULL; int rc; struct lyd_node *config = NULL; struct lyd_node_anyxml *axml; const char *dsname; sr_datastore_t ds = SR_DS_CANDIDATE; /* get sysrepo connections for this session */ sessions = (struct np2_sessions *)nc_session_get_data(ncs); /* get know which datastore is being affected */ nodeset = lyd_get_node(rpc, "/ietf-netconf:validate/source/*"); dsname = nodeset->set.d[0]->schema->name; axml = (struct lyd_node_anyxml *)nodeset->set.d[0]; ly_set_free(nodeset); if (!strcmp(dsname, "running")) { ds = SR_DS_RUNNING; } else if (!strcmp(dsname, "startup")) { ds = SR_DS_STARTUP; } else if (!strcmp(dsname, "candidate")) { ds = SR_DS_CANDIDATE; } else if (!strcmp(dsname, "config")) { /* get data tree to validate */ config = lyd_parse_xml(rpc->schema->module->ctx, &axml->value.xml, LYD_OPT_CONFIG | LYD_OPT_DESTRUCT); if (ly_errno != LY_SUCCESS) { ly_set_free(nodeset); goto error; } rc = lyd_validate(&config, LYD_OPT_CONFIG, np2srv.ly_ctx); /* cleanup */ lyd_free_withsiblings(config); goto done; } /* TODO support URL */ if (ds != sessions->ds) { /* update sysrepo session */ sr_session_switch_ds(sessions->srs, ds); sessions->ds = ds; } if (ds != SR_DS_CANDIDATE) { /* refresh datastore content */ if (sr_session_refresh(sessions->srs) != SR_ERR_OK) { goto error; } } /* validate sysrepo's datastore */ rc = sr_validate(sessions->srs); if (rc != SR_ERR_OK) { goto error; } done: return nc_server_reply_ok(); error: /* handle error */ if (!e) { e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP); nc_err_set_msg(e, np2log_lasterr(), "en"); } return nc_server_reply_err(e); }