session CHANGE generalize setting of the session's capabilities

instead of setter for the specific, interleave, capability, allow
to set a generic capbility as a string.
diff --git a/src/session.c b/src/session.c
index 4bdd379..28741db 100644
--- a/src/session.c
+++ b/src/session.c
@@ -534,6 +534,27 @@
 static void
 add_cpblt(struct ly_ctx *ctx, const char *capab, const char ***cpblts, int *size, int *count)
 {
+    size_t len;
+    int i;
+    char *p;
+
+    if (capab) {
+        /*  check if already present */
+        p = strchr(capab, '?');
+        if (p) {
+            len = p - capab;
+        } else {
+            len = strlen(capab);
+        }
+        for (i = 0; i < *count; i++) {
+            if (!strncmp((*cpblts)[i], capab, len)) {
+                /* already present, do not duplicate it */
+                return;
+            }
+        }
+    }
+
+    /* add another capability */
     if (*count == *size) {
         *size += 5;
         *cpblts = nc_realloc(*cpblts, *size * sizeof **cpblts);
@@ -559,6 +580,7 @@
     const char **cpblts;
     const struct lys_module *mod;
     int size = 10, count, feat_count = 0, dev_count = 0, i, str_len;
+    unsigned int u;
 #define NC_CPBLT_BUF_LEN 512
     char str[NC_CPBLT_BUF_LEN];
 
@@ -654,12 +676,9 @@
         }
     }
 
-    mod = ly_ctx_get_module(ctx, "nc-notifications", NULL);
-    if (mod) {
-        add_cpblt(ctx, "urn:ietf:params:netconf:capability:notification:1.0", &cpblts, &size, &count);
-        if (server_opts.interleave_capab) {
-            add_cpblt(ctx, "urn:ietf:params:netconf:capability:interleave:1.0", &cpblts, &size, &count);
-        }
+    /* other capabilities */
+    for (u = 0; u < server_opts.capabilities_count; u++) {
+        add_cpblt(ctx, server_opts.capabilities[u], &cpblts, &size, &count);
     }
 
     /* models */
diff --git a/src/session_p.h b/src/session_p.h
index c4fe1bd..7b135b4 100644
--- a/src/session_p.h
+++ b/src/session_p.h
@@ -141,7 +141,8 @@
     /* ACCESS unlocked */
     NC_WD_MODE wd_basic_mode;
     int wd_also_supported;
-    int interleave_capab;
+    unsigned int capabilities_count;
+    const char **capabilities;
 
     /* ACCESS unlocked */
     uint16_t hello_timeout;
diff --git a/src/session_server.c b/src/session_server.c
index 45d588c..a71242f 100644
--- a/src/session_server.c
+++ b/src/session_server.c
@@ -452,6 +452,12 @@
 API void
 nc_server_destroy(void)
 {
+    unsigned int i;
+
+    for (i = 0; i < server_opts.capabilities_count; i++) {
+        lydict_remove(server_opts.ctx, server_opts.capabilities[i]);
+    }
+    free(server_opts.capabilities);
     pthread_spin_destroy(&server_opts.sid_lock);
 
 #if defined(NC_ENABLED_SSH) || defined(NC_ENABLED_TLS)
@@ -495,20 +501,26 @@
     }
 }
 
-API void
-nc_server_set_capab_interleave(int interleave_support)
-{
-    if (interleave_support) {
-        server_opts.interleave_capab = 1;
-    } else {
-        server_opts.interleave_capab = 0;
-    }
-}
-
 API int
-nc_server_get_capab_interleave(void)
+nc_server_set_capability(const char *value)
 {
-    return server_opts.interleave_capab;
+    const char **new;
+
+    if (!value || !value[0]) {
+        ERRARG("value must not be empty");
+        return EXIT_FAILURE;
+    }
+
+    server_opts.capabilities_count++;
+    new = realloc(server_opts.capabilities, server_opts.capabilities_count * sizeof *server_opts.capabilities);
+    if (!new) {
+        ERRMEM;
+        return EXIT_FAILURE;
+    }
+    server_opts.capabilities = new;
+    server_opts.capabilities[server_opts.capabilities_count - 1] = lydict_insert(server_opts.ctx, value, 0);
+
+    return EXIT_SUCCESS;
 }
 
 API void
diff --git a/src/session_server.h b/src/session_server.h
index a7f3653..45120ac 100644
--- a/src/session_server.h
+++ b/src/session_server.h
@@ -109,24 +109,16 @@
 void nc_server_get_capab_withdefaults(NC_WD_MODE *basic_mode, int *also_supported);
 
 /**
- * @brief Set the interleave capability.
+ * @brief Set capability of the server.
  *
- * For the capability to be actually advertised, the server context must also
- * include the nc-notifications model.
+ * Capability can be used when some behavior or extension of the server is not defined
+ * as a YANG module. The provided value will be advertised in the server's \<hello\>
+ * messages. Note, that libnetconf only checks that the provided value is non-empty
+ * string.
  *
- * Changing this option has the same ill effects as changing capabilities while
- * sessions are already established.
- *
- * @param[in] interleave_support 1 to suport interleave, 0 to not.
+ * @param[in] value Capability string to be advertised in server\s \<hello\> messages.
  */
-void nc_server_set_capab_interleave(int interleave_support);
-
-/**
- * @brief Get the interleave capability state.
- *
- * @return 1 for supported, 0 for not supported.
- */
-int nc_server_get_capab_interleave(void);
+int nc_server_set_capability(const char *value);
 
 /**
  * @brief Set server timeout for receiving a hello message.