+static int netconf_monitoring_state_schemas_cb(sr_session_ctx_t *session, const char *module_name, const char *path, const char *request_xpath, uint32_t request_id, struct lyd_node **parent, void *private_data) {
+ struct lyd_node *root = 0;
+ root = lyd_new_path(*parent, session_context, IETF_NETCONF_MONITORING_STATE_SCHEMAS_SCHEMA_XPATH, 0, 0, 0);
+
+ struct lyd_node *list = 0;
+ const struct lys_module *mod = 0;
+ const struct lys_submodule *submod = 0;
+ uint32_t i = 0;
+
+ // get all modules from context
+ while ((mod = ly_ctx_get_module_iter(session_context, &i))) {
+ // we skip the internal sysrepo modules
+ if (!strcmp("sysrepo", mod->name) || !strcmp("sysrepo-monitoring", mod->name) || !strcmp("sysrepo-plugind", mod->name)) {
+ continue;
+ }
+
+ list = lyd_new(root, NULL, "schema");
+ lyd_new_leaf(list, NULL, "identifier", mod->name);
+ lyd_new_leaf(list, NULL, "version", (mod->rev ? mod->rev[0].date : NULL));
+ lyd_new_leaf(list, NULL, "format", "yang");
+ lyd_new_leaf(list, NULL, "namespace", lys_main_module(mod)->ns);
+ lyd_new_leaf(list, NULL, "location", "NETCONF");
+
+ // iterate all the submodules included by a module
+ for (int j = 0; j < mod->inc_size; j++) {
+ submod = mod->inc[j].submodule;
+
+ list = lyd_new(root, NULL, "schema");
+ lyd_new_leaf(list, NULL, "identifier", submod->name);
+ lyd_new_leaf(list, NULL, "version", (submod->rev ? submod->rev[0].date : NULL));
+ lyd_new_leaf(list, NULL, "format", "yang");
+ lyd_new_leaf(list, NULL, "namespace", lys_main_module(mod)->ns);
+ lyd_new_leaf(list, NULL, "location", "NETCONF");
+ }
+ }
+
+ return SR_ERR_OK;
+}
+
+static int notifications_streams_cb(sr_session_ctx_t *session, const char *module_name, const char *path, const char *request_xpath, uint32_t request_id, struct lyd_node **parent, void *private_data) {
+ struct lyd_node *root = lyd_new_path(0, session_context, NC_NOTIFICATIONS_STREAMS_SCHEMA_XPATH, 0, 0, 0);
+
+ /* generic stream */
+ struct lyd_node *stream = lyd_new_path(root, 0, NC_NOTIFICATIONS_STREAMS_SCHEMA_XPATH"/stream[name='NETCONF']", NULL, 0, 0);
+ lyd_new_leaf(stream, stream->schema->module, "description", "Default NETCONF stream containing notifications from all the modules. Replays only notifications for modules that support replay.");
+ lyd_new_leaf(stream, stream->schema->module, "replaySupport", "true");
+
+ /* all other streams */
+ struct lyd_node *sr_data;
+ struct lyd_node *sr_mod;
+ /* go through all the sysrepo modules */
+ int rc = sr_get_module_info(session_connection, &sr_data);
+ if(rc != SR_ERR_OK) {
+ log_error("sr_get_module_info failed\n");
+ return SR_ERR_OPERATION_FAILED;
+ }
+
+ LY_TREE_FOR(sr_data->child, sr_mod) {
+ const char *mod_name = ((struct lyd_node_leaf_list *)sr_mod->child)->value_str;
+ const struct lys_module *mod = ly_ctx_get_module(session_context, mod_name, 0, 1);
+ int has_notifications = 0;
+ struct lys_node *data = mod->data;
+ while(data) {
+ if(data->nodetype == LYS_NOTIF) {
+ has_notifications = 1;
+ }
+ data = data->next;
+ }
+
+ if(has_notifications) {
+ /* generate information about the stream/module */
+ stream = lyd_new(root->child, NULL, "stream");
+ lyd_new_leaf(stream, NULL, "name", mod_name);
+ lyd_new_leaf(stream, NULL, "description", "Stream with all notifications of a module.");
+
+ struct lyd_node *rep_sup = 0;
+ struct ly_set *set = lyd_find_path(sr_mod, "replay-support");
+ if(set && (set->number == 1)) {
+ rep_sup = set->set.d[0];
+ }
+ ly_set_free(set);
+
+ lyd_new_leaf(stream, NULL, "replaySupport", rep_sup ? "true" : "false");
+ if(rep_sup) {
+ char buf[26];
+ nc_time2datetime(((struct lyd_node_leaf_list *)rep_sup)->value.uint64, NULL, buf);
+ lyd_new_leaf(stream, NULL, "replayLogCreationTime", buf);
+ }
+ }
+ }
+
+ lyd_free_withsiblings(sr_data);
+ *parent = root;
+
+ return SR_ERR_OK;
+}
+