libnetconf CHANGE support for new draft netconf-server nodes
diff --git a/src/netconf.h b/src/netconf.h
index 4022617..ce1642d 100644
--- a/src/netconf.h
+++ b/src/netconf.h
@@ -126,15 +126,6 @@
 } NC_PARAMTYPE;
 
 /**
- * @brief Enumeration of SSH key types.
- */
-typedef enum NC_SSH_KEY {
-    NC_SSH_DSA,               /**< DSA SSH key */
-    NC_SSH_RSA,               /**< RSA SSH key */
-    NC_SSH_ECDSA              /**< ECDSA SSH key */
-} NC_SSH_KEY;
-
-/**
  * @brief Transform given time_t (seconds since the epoch) into the RFC 3339 format
  * accepted by NETCONF functions.
  *
diff --git a/src/session.c b/src/session.c
index 25fc410..5aa1bda 100644
--- a/src/session.c
+++ b/src/session.c
@@ -117,14 +117,14 @@
 }
 
 const char *
-nc_keytype2str(NC_SSH_KEY type)
+nc_keytype2str(NC_SSH_KEY_TYPE type)
 {
     switch (type) {
-    case NC_SSH_DSA:
+    case NC_SSH_KEY_DSA:
         return "DSA";
-    case NC_SSH_RSA:
+    case NC_SSH_KEY_RSA:
         return "RSA";
-    case NC_SSH_ECDSA:
+    case NC_SSH_KEY_ECDSA:
         return "EC";
     default:
         break;
@@ -134,35 +134,38 @@
 }
 
 int
-nc_sock_enable_keepalive(int sock)
+nc_sock_enable_keepalive(int sock, struct nc_keepalives *ka)
 {
     int opt;
 
-    opt = 1;
+    opt = ka->enabled;
     if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof opt) == -1) {
         ERR("Could not set SO_KEEPALIVE option (%s).", strerror(errno));
         return -1;
     }
+    if (!ka->enabled) {
+        return 0;
+    }
 
 #ifdef TCP_KEEPIDLE
-    opt = 1;
+    opt = ka->idle_time;
     if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &opt, sizeof opt) == -1) {
         ERR("Setsockopt failed (%s).", strerror(errno));
         return -1;
     }
 #endif
 
-#ifdef TCP_KEEPINTVL
-    opt = 5;
-    if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &opt, sizeof opt) == -1) {
+#ifdef TCP_KEEPCNT
+    opt = ka->max_probes;
+    if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, &opt, sizeof opt) == -1) {
         ERR("Setsockopt failed (%s).", strerror(errno));
         return -1;
     }
 #endif
 
-#ifdef TCP_KEEPCNT
-    opt = 10;
-    if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, &opt, sizeof opt) == -1) {
+#ifdef TCP_KEEPINTVL
+    opt = ka->probe_interval;
+    if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &opt, sizeof opt) == -1) {
         ERR("Setsockopt failed (%s).", strerror(errno));
         return -1;
     }
diff --git a/src/session.h b/src/session.h
index 6b667bd..2b4fa54 100644
--- a/src/session.h
+++ b/src/session.h
@@ -92,7 +92,8 @@
  */
 typedef enum {
     NC_CH_FIRST_LISTED = 0, //default
-    NC_CH_LAST_CONNECTED
+    NC_CH_LAST_CONNECTED,
+    NC_CH_RANDOM
 } NC_CH_START_WITH;
 
 /**
diff --git a/src/session_client.c b/src/session_client.c
index 2ede355..5cc0d1a 100644
--- a/src/session_client.c
+++ b/src/session_client.c
@@ -51,7 +51,12 @@
 static pthread_key_t nc_client_context_key;
 #ifdef __linux__
 static struct nc_client_context context_main = {
-    /* .opts zeroed */
+    .opts.ka = {
+        .enabled = 1,
+        .idle_time = 1,
+        .max_probes = 10,
+        .probe_interval = 5
+    },
 #ifdef NC_ENABLED_SSH
     .ssh_opts = {
         .auth_pref = {{NC_SSH_AUTH_INTERACTIVE, 3}, {NC_SSH_AUTH_PASSWORD, 2}, {NC_SSH_AUTH_PUBLICKEY, 1}},
@@ -1218,7 +1223,7 @@
    concept for e.g. call home settings). For more details see nc_sock_connect().
  */
 static int
-_non_blocking_connect(int timeout, int* sock_pending, struct addrinfo *res)
+_non_blocking_connect(int timeout, int* sock_pending, struct addrinfo *res, struct nc_keepalives *ka)
 {
     int flags, ret=0;
     int sock = -1;
@@ -1288,7 +1293,7 @@
     }
 
     /* enable keep-alive */
-    if (nc_sock_enable_keepalive(sock)) {
+    if (nc_sock_enable_keepalive(sock, ka)) {
         goto cleanup;
     }
 
@@ -1311,7 +1316,7 @@
    has to be invoked, until it returns a valid socket.
  */
 int
-nc_sock_connect(const char *host, uint16_t port, int timeout, int *sock_pending, char **ip_host)
+nc_sock_connect(const char *host, uint16_t port, int timeout, struct nc_keepalives *ka, int *sock_pending, char **ip_host)
 {
     int i, opt;
     int sock = sock_pending ? *sock_pending : -1;
@@ -1336,7 +1341,7 @@
         }
 
         for (res = res_list; res != NULL; res = res->ai_next) {
-            sock = _non_blocking_connect(timeout, sock_pending, res);
+            sock = _non_blocking_connect(timeout, sock_pending, res, ka);
             if (sock == -1 && (!sock_pending || *sock_pending == -1)) {
                 /* try the next resource */
                 continue;
@@ -1378,7 +1383,7 @@
     } else {
         /* try to get a connection with the pending socket */
         assert(sock_pending);
-        sock = _non_blocking_connect(timeout, sock_pending, NULL);
+        sock = _non_blocking_connect(timeout, sock_pending, NULL, ka);
     }
 
     return sock;
@@ -1838,7 +1843,7 @@
         return -1;
     }
 
-    sock = nc_sock_listen_inet(address, port);
+    sock = nc_sock_listen_inet(address, port, &client_opts.ka);
     if (sock == -1) {
         return -1;
     }
diff --git a/src/session_client_ssh.c b/src/session_client_ssh.c
index a2f3dbf..5b5a2c8 100644
--- a/src/session_client_ssh.c
+++ b/src/session_client_ssh.c
@@ -1487,7 +1487,8 @@
 }
 
 static struct nc_session *
-_nc_connect_libssh(ssh_session ssh_session, struct ly_ctx *ctx, struct nc_client_ssh_opts *opts, int timeout)
+_nc_connect_libssh(ssh_session ssh_session, struct ly_ctx *ctx, struct nc_keepalives *ka,
+        struct nc_client_ssh_opts *opts, int timeout)
 {
     char *host = NULL, *username = NULL, *ip_host;
     unsigned short port = 0;
@@ -1528,7 +1529,7 @@
         ssh_options_set(session->ti.libssh.session, SSH_OPTIONS_HOST, host);
 
         /* create and connect socket */
-        sock = nc_sock_connect(host, port, -1, NULL, &ip_host);
+        sock = nc_sock_connect(host, port, -1, ka, NULL, &ip_host);
         if (sock == -1) {
             ERR("Unable to connect to %s:%u (%s).", host, port, strerror(errno));
             goto fail;
@@ -1684,7 +1685,7 @@
 #endif
 
     /* create and assign communication socket */
-    sock = nc_sock_connect(host, port, -1, NULL, &ip_host);
+    sock = nc_sock_connect(host, port, -1, &client_opts.ka, NULL, &ip_host);
     if (sock == -1) {
         ERR("Unable to connect to %s:%u (%s).", host, port, strerror(errno));
         goto fail;
@@ -1731,7 +1732,7 @@
 API struct nc_session *
 nc_connect_libssh(ssh_session ssh_session, struct ly_ctx *ctx)
 {
-    return _nc_connect_libssh(ssh_session, ctx, &ssh_opts, NC_TRANSPORT_TIMEOUT);
+    return _nc_connect_libssh(ssh_session, ctx, &client_opts.ka, &ssh_opts, NC_TRANSPORT_TIMEOUT);
 }
 
 API struct nc_session *
@@ -1843,7 +1844,7 @@
             "ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-rsa,rsa-sha2-512,rsa-sha2-256,ssh-dss");
 #endif
 
-    session = _nc_connect_libssh(sess, ctx, &ssh_ch_opts, timeout);
+    session = _nc_connect_libssh(sess, ctx, &client_opts.ka, &ssh_ch_opts, timeout);
     if (!session) {
         ssh_free(sess);
         return NULL;
diff --git a/src/session_client_tls.c b/src/session_client_tls.c
index 71bb134..4f67ab0 100644
--- a/src/session_client_tls.c
+++ b/src/session_client_tls.c
@@ -618,7 +618,7 @@
     }
 
     /* create and assign socket */
-    sock = nc_sock_connect(host, port, -1, NULL, &ip_host);
+    sock = nc_sock_connect(host, port, -1, &client_opts.ka, NULL, &ip_host);
     if (sock == -1) {
         ERR("Unable to connect to %s:%u (%s).", host, port, strerror(errno));
         goto fail;
diff --git a/src/session_p.h b/src/session_p.h
index 92daa59..269fa67 100644
--- a/src/session_p.h
+++ b/src/session_p.h
@@ -39,6 +39,14 @@
 #   define NC_SSH_AUTH_COUNT 3
 
 /* ACCESS unlocked */
+struct nc_keepalives {
+    int enabled;
+    uint16_t idle_time;
+    uint16_t max_probes;
+    uint16_t probe_interval;
+};
+
+/* ACCESS unlocked */
 struct nc_client_ssh_opts {
     /* SSH authentication method preferences */
     struct {
@@ -134,6 +142,7 @@
     char *schema_searchpath;
     ly_module_imp_clb schema_clb;
     void *schema_clb_data;
+    struct nc_keepalives ka;
 
     struct nc_bind {
         const char *address;
@@ -189,17 +198,17 @@
     int (*user_verify_clb)(const struct nc_session *session);
 
     int (*server_cert_clb)(const char *name, void *user_data, char **cert_path, char **cert_data,char **privkey_path,
-                           char **privkey_data, NC_SSH_KEY *privkey_type);
+            char **privkey_data, NC_SSH_KEY_TYPE *privkey_type);
     void *server_cert_data;
     void (*server_cert_data_free)(void *data);
 
     int (*server_cert_chain_clb)(const char *name, void *user_data, char ***cert_paths, int *cert_path_count,
-                                 char ***cert_data, int *cert_data_count);
+            char ***cert_data, int *cert_data_count);
     void *server_cert_chain_data;
     void (*server_cert_chain_data_free)(void *data);
 
     int (*trusted_cert_list_clb)(const char *name, void *user_data, char ***cert_paths, int *cert_path_count,
-                                 char ***cert_data, int *cert_data_count);
+            char ***cert_data, int *cert_data_count);
     void *trusted_cert_list_data;
     void (*trusted_cert_list_data_free)(void *data);
 #endif
@@ -215,7 +224,7 @@
     uint16_t authkey_count;
     pthread_mutex_t authkey_lock;
 
-    int (*hostkey_clb)(const char *name, void *user_data, char **privkey_path, char **privkey_data, NC_SSH_KEY *privkey_type);
+    int (*hostkey_clb)(const char *name, void *user_data, char **privkey_path, char **privkey_data, NC_SSH_KEY_TYPE *privkey_type);
     void *hostkey_data;
     void (*hostkey_data_free)(void *data);
 #endif
@@ -229,6 +238,7 @@
     struct nc_endpt {
         const char *name;
         NC_TRANSPORT_IMPL ti;
+        struct nc_keepalives ka;
         union {
 #ifdef NC_ENABLED_SSH
             struct nc_server_ssh_opts *ssh;
@@ -252,6 +262,7 @@
             const char *address;
             uint16_t port;
             int sock_pending;
+            struct nc_keepalives ka;
         } *ch_endpts;
         uint16_t ch_endpt_count;
         union {
@@ -265,13 +276,9 @@
         NC_CH_CONN_TYPE conn_type;
         union {
             struct {
-                uint32_t idle_timeout;
-                uint16_t ka_max_wait;
-                uint8_t ka_max_attempts;
-            } persist;
-            struct {
+                uint16_t period;
+                time_t anchor_time;
                 uint16_t idle_timeout;
-                uint16_t reconnect_timeout;
             } period;
         } conn;
         NC_CH_START_WITH start_with;
@@ -409,7 +416,7 @@
     /* 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 */
+    uint8_t flags;                 /**< various flags of the session */
 #define NC_SESSION_SHAREDCTX 0x01
 #define NC_SESSION_CALLHOME 0x02
 
@@ -505,9 +512,9 @@
 
 void nc_addtimespec(struct timespec *ts, uint32_t msec);
 
-const char *nc_keytype2str(NC_SSH_KEY type);
+const char *nc_keytype2str(NC_SSH_KEY_TYPE type);
 
-int nc_sock_enable_keepalive(int sock);
+int nc_sock_enable_keepalive(int sock, struct nc_keepalives *ka);
 
 struct nc_session *nc_new_session(NC_SIDE side, int shared_ti);
 
@@ -548,11 +555,12 @@
  * @param[in] host Hostname to connect to.
  * @param[in] port Port to connect on.
  * @param[in] timeout for blocking the connect+select call (-1 for infinite).
+ * @param[in] ka Keepalives parameters.
  * @param[in,out] sock_pending for exchanging the pending socket, if the blocking timeout was != -1
  * @param[out] ip_host Optional parameter with string IP address of the connected host.
  * @return Connected socket or -1 on error.
  */
-int nc_sock_connect(const char *host, uint16_t port, int timeout, int* sock_pending, char **ip_host);
+int nc_sock_connect(const char *host, uint16_t port, int timeout, struct nc_keepalives *ka, int *sock_pending, char **ip_host);
 
 /**
  * @brief Accept a new socket connection.
@@ -570,9 +578,10 @@
  *
  * @param[in] address IP address to listen on.
  * @param[in] port Port to listen on.
+ * @param[in] ka Keepalives parameters.
  * @return Listening socket, -1 on error.
  */
-int nc_sock_listen_inet(const char *address, uint16_t port);
+int nc_sock_listen_inet(const char *address, uint16_t port, struct nc_keepalives *ka);
 
 /**
  * @brief Create a listening socket (AF_UNIX).
diff --git a/src/session_server.c b/src/session_server.c
index 9f0ac4b..cf697db 100644
--- a/src/session_server.c
+++ b/src/session_server.c
@@ -174,7 +174,7 @@
 }
 
 int
-nc_sock_listen_inet(const char *address, uint16_t port)
+nc_sock_listen_inet(const char *address, uint16_t port, struct nc_keepalives *ka)
 {
     int opt;
     int is_ipv4, sock;
@@ -207,7 +207,7 @@
         goto fail;
     }
 
-    if (nc_sock_enable_keepalive(sock)) {
+    if (nc_sock_enable_keepalive(sock, ka)) {
         goto fail;
     }
 
@@ -1765,8 +1765,12 @@
         ret = -1;
         goto cleanup;
     }
+    memset(&server_opts.endpts[server_opts.endpt_count - 1], 0, sizeof *server_opts.endpts);
     server_opts.endpts[server_opts.endpt_count - 1].name = lydict_insert(server_opts.ctx, name, 0);
     server_opts.endpts[server_opts.endpt_count - 1].ti = ti;
+    server_opts.endpts[server_opts.endpt_count - 1].ka.idle_time = 1;
+    server_opts.endpts[server_opts.endpt_count - 1].ka.max_probes = 10;
+    server_opts.endpts[server_opts.endpt_count - 1].ka.probe_interval = 5;
 
     server_opts.binds = nc_realloc(server_opts.binds, server_opts.endpt_count * sizeof *server_opts.binds);
     if (!server_opts.binds) {
@@ -1775,10 +1779,8 @@
         goto cleanup;
     }
 
-    server_opts.binds[server_opts.endpt_count - 1].address = NULL;
-    server_opts.binds[server_opts.endpt_count - 1].port = 0;
+    memset(&server_opts.binds[server_opts.endpt_count - 1], 0, sizeof *server_opts.binds);
     server_opts.binds[server_opts.endpt_count - 1].sock = -1;
-    server_opts.binds[server_opts.endpt_count - 1].pollin = 0;
 
     switch (ti) {
 #ifdef NC_ENABLED_SSH
@@ -1832,145 +1834,6 @@
     return ret;
 }
 
-int
-nc_server_endpt_set_address_port(const char *endpt_name, const char *address, uint16_t port)
-{
-    struct nc_endpt *endpt;
-    struct nc_bind *bind = NULL;
-    uint16_t i;
-    int sock = -1, set_addr, ret = 0;
-
-    if (!endpt_name) {
-        ERRARG("endpt_name");
-        return -1;
-    } else if ((!address && !port) || (address && port)) {
-        ERRARG("address and port");
-        return -1;
-    }
-
-    if (address) {
-        set_addr = 1;
-    } else {
-        set_addr = 0;
-    }
-
-    /* BIND LOCK */
-    pthread_mutex_lock(&server_opts.bind_lock);
-
-    /* ENDPT LOCK */
-    endpt = nc_server_endpt_lock_get(endpt_name, 0, &i);
-    if (!endpt) {
-        /* BIND UNLOCK */
-        pthread_mutex_unlock(&server_opts.bind_lock);
-        return -1;
-    }
-
-    bind = &server_opts.binds[i];
-
-    if (set_addr) {
-        port = bind->port;
-    } else {
-        address = bind->address;
-    }
-
-    if (!set_addr && endpt->ti == NC_TI_UNIX) {
-        ret = -1;
-        goto cleanup;
-    }
-
-    /* we have all the information we need to create a listening socket */
-    if (address && (port || endpt->ti == NC_TI_UNIX)) {
-        /* create new socket, close the old one */
-        if (endpt->ti == NC_TI_UNIX)
-            sock = nc_sock_listen_unix(address, endpt->opts.unixsock);
-        else
-            sock = nc_sock_listen_inet(address, port);
-        if (sock == -1) {
-            ret = -1;
-            goto cleanup;
-        }
-
-        if (bind->sock > -1) {
-            close(bind->sock);
-        }
-        bind->sock = sock;
-    } /* else we are just setting address or port */
-
-    if (set_addr) {
-        lydict_remove(server_opts.ctx, bind->address);
-        bind->address = lydict_insert(server_opts.ctx, address, 0);
-    } else {
-        bind->port = port;
-    }
-
-    if (sock > -1) {
-#if defined(NC_ENABLED_SSH) && defined(NC_ENABLED_TLS)
-        VRB("Listening on %s:%u for %s connections.", address, port, (endpt->ti == NC_TI_LIBSSH ? "SSH" : "TLS"));
-#elif defined(NC_ENABLED_SSH)
-        VRB("Listening on %s:%u for SSH connections.", address, port);
-#else
-        VRB("Listening on %s:%u for TLS connections.", address, port);
-#endif
-    }
-
-cleanup:
-    /* ENDPT UNLOCK */
-    pthread_rwlock_unlock(&server_opts.endpt_lock);
-
-    /* BIND UNLOCK */
-    pthread_mutex_unlock(&server_opts.bind_lock);
-
-    return ret;
-}
-
-API int
-nc_server_endpt_set_address(const char *endpt_name, const char *address)
-{
-    return nc_server_endpt_set_address_port(endpt_name, address, 0);
-}
-
-API int
-nc_server_endpt_set_port(const char *endpt_name, uint16_t port)
-{
-    return nc_server_endpt_set_address_port(endpt_name, NULL, port);
-}
-
-API int
-nc_server_endpt_set_perms(const char *endpt_name, mode_t mode, uid_t uid, gid_t gid)
-{
-    struct nc_endpt *endpt;
-    uint16_t i;
-    int ret = 0;
-
-    if (!endpt_name) {
-        ERRARG("endpt_name");
-        return -1;
-    } else if (mode == 0) {
-        ERRARG("mode");
-        return -1;
-    }
-
-    /* ENDPT LOCK */
-    endpt = nc_server_endpt_lock_get(endpt_name, 0, &i);
-    if (!endpt)
-        return -1;
-
-    if (endpt->ti != NC_TI_UNIX) {
-        ret = -1;
-        goto cleanup;
-    }
-
-    endpt->opts.unixsock->mode = mode;
-    endpt->opts.unixsock->uid = uid;
-    endpt->opts.unixsock->gid = gid;
-
-cleanup:
-    /* ENDPT UNLOCK */
-    pthread_rwlock_unlock(&server_opts.endpt_lock);
-
-    return ret;
-}
-
 API int
 nc_server_del_endpt(const char *name, NC_TRANSPORT_IMPL ti)
 {
@@ -2087,6 +1950,209 @@
     return ret;
 }
 
+API int
+nc_server_endpt_count(void)
+{
+    return server_opts.endpt_count;
+}
+
+int
+nc_server_endpt_set_address_port(const char *endpt_name, const char *address, uint16_t port)
+{
+    struct nc_endpt *endpt;
+    struct nc_bind *bind = NULL;
+    uint16_t i;
+    int sock = -1, set_addr, ret = 0;
+
+    if (!endpt_name) {
+        ERRARG("endpt_name");
+        return -1;
+    } else if ((!address && !port) || (address && port)) {
+        ERRARG("address and port");
+        return -1;
+    }
+
+    if (address) {
+        set_addr = 1;
+    } else {
+        set_addr = 0;
+    }
+
+    /* BIND LOCK */
+    pthread_mutex_lock(&server_opts.bind_lock);
+
+    /* ENDPT LOCK */
+    endpt = nc_server_endpt_lock_get(endpt_name, 0, &i);
+    if (!endpt) {
+        /* BIND UNLOCK */
+        pthread_mutex_unlock(&server_opts.bind_lock);
+        return -1;
+    }
+
+    bind = &server_opts.binds[i];
+
+    if (set_addr) {
+        port = bind->port;
+    } else {
+        address = bind->address;
+    }
+
+    if (!set_addr && endpt->ti == NC_TI_UNIX) {
+        ret = -1;
+        goto cleanup;
+    }
+
+    /* we have all the information we need to create a listening socket */
+    if (address && (port || endpt->ti == NC_TI_UNIX)) {
+        /* create new socket, close the old one */
+        if (endpt->ti == NC_TI_UNIX)
+            sock = nc_sock_listen_unix(address, endpt->opts.unixsock);
+        else
+            sock = nc_sock_listen_inet(address, port, &endpt->ka);
+        if (sock == -1) {
+            ret = -1;
+            goto cleanup;
+        }
+
+        if (bind->sock > -1) {
+            close(bind->sock);
+        }
+        bind->sock = sock;
+    } /* else we are just setting address or port */
+
+    if (set_addr) {
+        lydict_remove(server_opts.ctx, bind->address);
+        bind->address = lydict_insert(server_opts.ctx, address, 0);
+    } else {
+        bind->port = port;
+    }
+
+    if (sock > -1) {
+#if defined(NC_ENABLED_SSH) && defined(NC_ENABLED_TLS)
+        VRB("Listening on %s:%u for %s connections.", address, port, (endpt->ti == NC_TI_LIBSSH ? "SSH" : "TLS"));
+#elif defined(NC_ENABLED_SSH)
+        VRB("Listening on %s:%u for SSH connections.", address, port);
+#else
+        VRB("Listening on %s:%u for TLS connections.", address, port);
+#endif
+    }
+
+cleanup:
+    /* ENDPT UNLOCK */
+    pthread_rwlock_unlock(&server_opts.endpt_lock);
+
+    /* BIND UNLOCK */
+    pthread_mutex_unlock(&server_opts.bind_lock);
+
+    return ret;
+}
+
+API int
+nc_server_endpt_set_address(const char *endpt_name, const char *address)
+{
+    return nc_server_endpt_set_address_port(endpt_name, address, 0);
+}
+
+API int
+nc_server_endpt_set_port(const char *endpt_name, uint16_t port)
+{
+    return nc_server_endpt_set_address_port(endpt_name, NULL, port);
+}
+
+API int
+nc_server_endpt_set_perms(const char *endpt_name, mode_t mode, uid_t uid, gid_t gid)
+{
+    struct nc_endpt *endpt;
+    uint16_t i;
+    int ret = 0;
+
+    if (!endpt_name) {
+        ERRARG("endpt_name");
+        return -1;
+    } else if (mode == 0) {
+        ERRARG("mode");
+        return -1;
+    }
+
+    /* ENDPT LOCK */
+    endpt = nc_server_endpt_lock_get(endpt_name, 0, &i);
+    if (!endpt)
+        return -1;
+
+    if (endpt->ti != NC_TI_UNIX) {
+        ret = -1;
+        goto cleanup;
+    }
+
+    endpt->opts.unixsock->mode = mode;
+    endpt->opts.unixsock->uid = uid;
+    endpt->opts.unixsock->gid = gid;
+
+cleanup:
+    /* ENDPT UNLOCK */
+    pthread_rwlock_unlock(&server_opts.endpt_lock);
+
+    return ret;
+}
+
+API int
+nc_server_endpt_enable_keepalives(const char *endpt_name, int enable)
+{
+    struct nc_endpt *endpt;
+    int ret = 0;
+
+    if (!endpt_name) {
+        ERRARG("endpt_name");
+        return -1;
+    }
+
+    /* ENDPT LOCK */
+    endpt = nc_server_endpt_lock_get(endpt_name, 0, NULL);
+    if (!endpt) {
+        return -1;
+    }
+
+    endpt->ka.enabled = (enable ? 1 : 0);
+
+    /* ENDPT UNLOCK */
+    pthread_rwlock_unlock(&server_opts.endpt_lock);
+
+    return ret;
+}
+
+API int
+nc_server_endpt_set_keepalives(const char *endpt_name, int idle_time, int max_probes, int probe_interval)
+{
+    struct nc_endpt *endpt;
+    int ret = 0;
+
+    if (!endpt_name) {
+        ERRARG("endpt_name");
+        return -1;
+    }
+
+    /* ENDPT LOCK */
+    endpt = nc_server_endpt_lock_get(endpt_name, 0, NULL);
+    if (!endpt) {
+        return -1;
+    }
+
+    if (idle_time > -1) {
+        endpt->ka.idle_time = idle_time;
+    }
+    if (max_probes > -1) {
+        endpt->ka.max_probes = max_probes;
+    }
+    if (probe_interval > -1) {
+        endpt->ka.probe_interval = probe_interval;
+    }
+
+    /* ENDPT UNLOCK */
+    pthread_rwlock_unlock(&server_opts.endpt_lock);
+
+    return ret;
+}
+
 API NC_MSG_TYPE
 nc_accept(int timeout, struct nc_session **session)
 {
@@ -2455,10 +2521,12 @@
         return -1;
     }
 
+    memset(&client->ch_endpts[client->ch_endpt_count - 1], 0, sizeof *client->ch_endpts);
     client->ch_endpts[client->ch_endpt_count - 1].name = lydict_insert(server_opts.ctx, endpt_name, 0);
-    client->ch_endpts[client->ch_endpt_count - 1].address = NULL;
-    client->ch_endpts[client->ch_endpt_count - 1].port = 0;
     client->ch_endpts[client->ch_endpt_count - 1].sock_pending = -1;
+    client->ch_endpts[client->ch_endpt_count - 1].ka.idle_time = 1;
+    client->ch_endpts[client->ch_endpt_count - 1].ka.max_probes = 10;
+    client->ch_endpts[client->ch_endpt_count - 1].ka.probe_interval = 5;
 
     /* UNLOCK */
     nc_server_ch_client_unlock(client);
@@ -2613,6 +2681,95 @@
 }
 
 API int
+nc_server_ch_client_endpt_enable_keepalives(const char *client_name, const char *endpt_name, int enable)
+{
+    uint16_t i;
+    int ret = -1;
+    struct nc_ch_client *client;
+
+    if (!client_name) {
+        ERRARG("client_name");
+        return -1;
+    } else if (!endpt_name) {
+        ERRARG("endpt_name");
+        return -1;
+    }
+
+    /* LOCK */
+    client = nc_server_ch_client_lock(client_name, 0, NULL);
+    if (!client) {
+        return -1;
+    }
+
+    for (i = 0; i < client->ch_endpt_count; ++i) {
+        if (!strcmp(client->ch_endpts[i].name, endpt_name)) {
+            client->ch_endpts[i].ka.enabled = (enable ? 1 : 0);
+
+            ret = 0;
+            break;
+        }
+    }
+
+    /* UNLOCK */
+    nc_server_ch_client_unlock(client);
+
+    if (ret == -1) {
+        ERR("Call Home client \"%s\" endpoint \"%s\" not found.", client_name, endpt_name);
+    }
+
+    return ret;
+}
+
+API int
+nc_server_ch_client_endpt_set_keepalives(const char *client_name, const char *endpt_name, int idle_time, int max_probes,
+        int probe_interval)
+{
+    uint16_t i;
+    int ret = -1;
+    struct nc_ch_client *client;
+
+    if (!client_name) {
+        ERRARG("client_name");
+        return -1;
+    } else if (!endpt_name) {
+        ERRARG("endpt_name");
+        return -1;
+    }
+
+    /* LOCK */
+    client = nc_server_ch_client_lock(client_name, 0, NULL);
+    if (!client) {
+        return -1;
+    }
+
+    for (i = 0; i < client->ch_endpt_count; ++i) {
+        if (!strcmp(client->ch_endpts[i].name, endpt_name)) {
+            if (idle_time > -1) {
+                client->ch_endpts[i].ka.idle_time = idle_time;
+            }
+            if (max_probes > -1) {
+                client->ch_endpts[i].ka.max_probes = max_probes;
+            }
+            if (probe_interval > -1) {
+                client->ch_endpts[i].ka.probe_interval = probe_interval;
+            }
+
+            ret = 0;
+            break;
+        }
+    }
+
+    /* UNLOCK */
+    nc_server_ch_client_unlock(client);
+
+    if (ret == -1) {
+        ERR("Call Home client \"%s\" endpoint \"%s\" not found.", client_name, endpt_name);
+    }
+
+    return ret;
+}
+
+API int
 nc_server_ch_client_set_conn_type(const char *client_name, NC_CH_CONN_TYPE conn_type)
 {
     struct nc_ch_client *client;
@@ -2637,13 +2794,12 @@
         /* set default options */
         switch (conn_type) {
         case NC_CH_PERSIST:
-            client->conn.persist.idle_timeout = 86400;
-            client->conn.persist.ka_max_wait = 30;
-            client->conn.persist.ka_max_attempts = 3;
+            /* no options */
             break;
         case NC_CH_PERIOD:
-            client->conn.period.idle_timeout = 300;
-            client->conn.period.reconnect_timeout = 60;
+            client->conn.period.period = 60;
+            client->conn.period.anchor_time = 0;
+            client->conn.period.idle_timeout = 120;
             break;
         default:
             ERRINT;
@@ -2658,7 +2814,41 @@
 }
 
 API int
-nc_server_ch_client_persist_set_idle_timeout(const char *client_name, uint32_t idle_timeout)
+nc_server_ch_client_periodic_set_period(const char *client_name, uint16_t period)
+{
+    struct nc_ch_client *client;
+
+    if (!client_name) {
+        ERRARG("client_name");
+        return -1;
+    } else if (!period) {
+        ERRARG("period");
+        return -1;
+    }
+
+    /* LOCK */
+    client = nc_server_ch_client_lock(client_name, 0, NULL);
+    if (!client) {
+        return -1;
+    }
+
+    if (client->conn_type != NC_CH_PERIOD) {
+        ERR("Call Home client \"%s\" is not of periodic connection type.");
+        /* UNLOCK */
+        nc_server_ch_client_unlock(client);
+        return -1;
+    }
+
+    client->conn.period.period = period;
+
+    /* UNLOCK */
+    nc_server_ch_client_unlock(client);
+
+    return 0;
+}
+
+API int
+nc_server_ch_client_periodic_set_anchor_time(const char *client_name, time_t anchor_time)
 {
     struct nc_ch_client *client;
 
@@ -2673,14 +2863,14 @@
         return -1;
     }
 
-    if (client->conn_type != NC_CH_PERSIST) {
-        ERR("Call Home client \"%s\" is not of persistent connection type.", client_name);
+    if (client->conn_type != NC_CH_PERIOD) {
+        ERR("Call Home client \"%s\" is not of periodic connection type.");
         /* UNLOCK */
         nc_server_ch_client_unlock(client);
         return -1;
     }
 
-    client->conn.persist.idle_timeout = idle_timeout;
+    client->conn.period.anchor_time = anchor_time;
 
     /* UNLOCK */
     nc_server_ch_client_unlock(client);
@@ -2689,72 +2879,7 @@
 }
 
 API int
-nc_server_ch_client_persist_set_keep_alive_max_wait(const char *client_name, uint16_t max_wait)
-{
-    struct nc_ch_client *client;
-
-    if (!client_name) {
-        ERRARG("client_name");
-        return -1;
-    } else if (!max_wait) {
-        ERRARG("max_wait");
-        return -1;
-    }
-
-    /* LOCK */
-    client = nc_server_ch_client_lock(client_name, 0, NULL);
-    if (!client) {
-        return -1;
-    }
-
-    if (client->conn_type != NC_CH_PERSIST) {
-        ERR("Call Home client \"%s\" is not of persistent connection type.", client_name);
-        /* UNLOCK */
-        nc_server_ch_client_unlock(client);
-        return -1;
-    }
-
-    client->conn.persist.ka_max_wait = max_wait;
-
-    /* UNLOCK */
-    nc_server_ch_client_unlock(client);
-
-    return 0;
-}
-
-API int
-nc_server_ch_client_persist_set_keep_alive_max_attempts(const char *client_name, uint8_t max_attempts)
-{
-    struct nc_ch_client *client;
-
-    if (!client_name) {
-        ERRARG("client_name");
-        return -1;
-    }
-
-    /* LOCK */
-    client = nc_server_ch_client_lock(client_name, 0, NULL);
-    if (!client) {
-        return -1;
-    }
-
-    if (client->conn_type != NC_CH_PERSIST) {
-        ERR("Call Home client \"%s\" is not of persistent connection type.", client_name);
-        /* UNLOCK */
-        nc_server_ch_client_unlock(client);
-        return -1;
-    }
-
-    client->conn.persist.ka_max_attempts = max_attempts;
-
-    /* UNLOCK */
-    nc_server_ch_client_unlock(client);
-
-    return 0;
-}
-
-API int
-nc_server_ch_client_period_set_idle_timeout(const char *client_name, uint16_t idle_timeout)
+nc_server_ch_client_periodic_set_idle_timeout(const char *client_name, uint16_t idle_timeout)
 {
     struct nc_ch_client *client;
 
@@ -2785,40 +2910,6 @@
 }
 
 API int
-nc_server_ch_client_period_set_reconnect_timeout(const char *client_name, uint16_t reconnect_timeout)
-{
-    struct nc_ch_client *client;
-
-    if (!client_name) {
-        ERRARG("client_name");
-        return -1;
-    } else if (!reconnect_timeout) {
-        ERRARG("reconnect_timeout");
-        return -1;
-    }
-
-    /* LOCK */
-    client = nc_server_ch_client_lock(client_name, 0, NULL);
-    if (!client) {
-        return -1;
-    }
-
-    if (client->conn_type != NC_CH_PERIOD) {
-        ERR("Call Home client \"%s\" is not of periodic connection type.");
-        /* UNLOCK */
-        nc_server_ch_client_unlock(client);
-        return -1;
-    }
-
-    client->conn.period.reconnect_timeout = reconnect_timeout;
-
-    /* UNLOCK */
-    nc_server_ch_client_unlock(client);
-
-    return 0;
-}
-
-API int
 nc_server_ch_client_set_start_with(const char *client_name, NC_CH_START_WITH start_with)
 {
     struct nc_ch_client *client;
@@ -2878,7 +2969,7 @@
     struct timespec ts_cur;
     char *ip_host;
 
-    sock = nc_sock_connect(endpt->address, endpt->port, 5, &endpt->sock_pending, &ip_host);
+    sock = nc_sock_connect(endpt->address, endpt->port, 5, &endpt->ka, &endpt->sock_pending, &ip_host);
     if (sock < 0) {
         return NC_MSG_ERROR;
     }
@@ -3043,11 +3134,10 @@
             break;
         }
 
-        if (client->conn_type == NC_CH_PERSIST) {
-            /* TODO keep-alives */
-            idle_timeout = client->conn.persist.idle_timeout;
-        } else {
+        if (client->conn_type == NC_CH_PERIOD) {
             idle_timeout = client->conn.period.idle_timeout;
+        } else {
+            idle_timeout = 0;
         }
 
         nc_gettimespec_mono(&ts);
@@ -3085,6 +3175,7 @@
     struct nc_session *session;
     struct nc_ch_client *client;
     uint32_t client_id;
+    time_t reconnect_in;
 
     /* LOCK */
     client = nc_server_ch_client_with_endpt_lock(data->client_name);
@@ -3121,13 +3212,14 @@
             }
 
             /* session changed status -> it was disconnected for whatever reason,
-             * persistent connection immediately tries to reconnect, periodic waits some first */
+             * persistent connection immediately tries to reconnect, periodic connects at specific times */
             if (client->conn_type == NC_CH_PERIOD) {
                 /* UNLOCK */
                 nc_server_ch_client_unlock(client);
 
-                /* TODO wake up sometimes to check for new notifications */
-                usleep(client->conn.period.reconnect_timeout * 60 * 1000000);
+                /* sleep until we should reconnect TODO wake up sometimes to check for new notifications */
+                reconnect_in = (time(NULL) - client->conn.period.anchor_time) % (client->conn.period.period * 60);
+                sleep(reconnect_in);
 
                 /* LOCK */
                 client = nc_server_ch_client_with_endpt_lock(data->client_name);
@@ -3143,7 +3235,7 @@
             /* set next endpoint to try */
             if (client->start_with == NC_CH_FIRST_LISTED) {
                 next_endpt_index = 0;
-            } else {
+            } else if (client->start_with == NC_CH_LAST_CONNECTED) {
                 /* we keep the current one but due to unlock/lock we have to find it again */
                 for (next_endpt_index = 0; next_endpt_index < client->ch_endpt_count; ++next_endpt_index) {
                     if (!strcmp(client->ch_endpts[next_endpt_index].name, cur_endpt_name)) {
@@ -3154,6 +3246,9 @@
                     /* endpoint was removed, start with the first one */
                     next_endpt_index = 0;
                 }
+            } else {
+                /* just get a random index */
+                next_endpt_index = rand() % client->ch_endpt_count;
             }
 
         } else {
@@ -3258,12 +3353,6 @@
 
 #endif /* NC_ENABLED_SSH || NC_ENABLED_TLS */
 
-API int
-nc_server_endpt_count(void)
-{
-    return server_opts.endpt_count;
-}
-
 API time_t
 nc_session_get_start_time(const struct nc_session *session)
 {
diff --git a/src/session_server.h b/src/session_server.h
index 9e20fd2..8f8472c 100644
--- a/src/session_server.h
+++ b/src/session_server.h
@@ -417,6 +417,26 @@
  */
 int nc_server_endpt_set_perms(const char *endpt_name, mode_t mode, uid_t uid, gid_t gid);
 
+/**
+ * @brief Change endpoint keepalives state. Affects only new connections.
+ *
+ * @param[in] endpt_name Existing endpoint name.
+ * @param[in] enable Whether to enable or disable keepalives.
+ * @return 0 on success, -1 on error.
+ */
+int nc_server_endpt_enable_keepalives(const char *endpt_name, int enable);
+
+/**
+ * @brief Change endpoint keepalives parameters. Affects only new connections.
+ *
+ * @param[in] endpt_name Existing endpoint name.
+ * @param[in] idle_time Keepalive idle time in seconds, 1 by default, -1 to keep previous value.
+ * @param[in] max_probes Keepalive max probes sent, 10 by default, -1 to keep previous value.
+ * @param[in] probe_interval Keepalive probe interval in seconds, 5 by default, -1 to keep previous value.
+ * @return 0 on success, -1 on error.
+ */
+int nc_server_endpt_set_keepalives(const char *endpt_name, int idle_time, int max_probes, int probe_interval);
+
 /**@} Server */
 
 /**
@@ -477,7 +497,7 @@
 
 /**
  * @brief Add an authorized client SSH public key. This public key can be used for
- *        publickey authentication (for any SSH connection, even Call Home) afterwards.
+ * publickey authentication (for any SSH connection, even Call Home) afterwards.
  *
  * @param[in] pubkey_base64 Authorized public key binary content encoded in base64.
  * @param[in] type Authorized public key SSH type.
@@ -558,8 +578,7 @@
  * @param[in] free_user_data Optional callback that will be called during cleanup to free any \p user_data.
  */
 void nc_server_ssh_set_hostkey_clb(int (*hostkey_clb)(const char *name, void *user_data, char **privkey_path,
-                                                      char **privkey_data, NC_SSH_KEY *privkey_type),
-                                   void *user_data, void (*free_user_data)(void *user_data));
+        char **privkey_data, NC_SSH_KEY_TYPE *privkey_type), void *user_data, void (*free_user_data)(void *user_data));
 
 /**
  * @brief Add endpoint SSH host keys the server will identify itself with. Only the name is set, the key itself
@@ -677,8 +696,8 @@
  * @param[in] free_user_data Optional callback that will be called during cleanup to free any \p user_data.
  */
 void nc_server_tls_set_server_cert_clb(int (*cert_clb)(const char *name, void *user_data, char **cert_path, char **cert_data,
-                                                       char **privkey_path, char **privkey_data, NC_SSH_KEY *privkey_type),
-                                       void *user_data, void (*free_user_data)(void *user_data));
+        char **privkey_path, char **privkey_data, NC_SSH_KEY_TYPE *privkey_type), void *user_data,
+        void (*free_user_data)(void *user_data));
 
 /**
  * @brief Set the callback for retrieving server certificate chain
@@ -694,8 +713,7 @@
  * @param[in] free_user_data Optional callback that will be called during cleanup to free any \p user_data.
  */
 void nc_server_tls_set_server_cert_chain_clb(int (*cert_chain_clb)(const char *name, void *user_data, char ***cert_paths,
-                                                                   int *cert_path_count, char ***cert_data, int *cert_data_count),
-                                             void *user_data, void (*free_user_data)(void *user_data));
+        int *cert_path_count, char ***cert_data, int *cert_data_count), void *user_data, void (*free_user_data)(void *user_data));
 
 /**
  * @brief Add a trusted certificate list. Can be both a CA or a client one. Can be
@@ -721,8 +739,7 @@
  * @param[in] free_user_data Optional callback that will be called during cleanup to free any \p user_data.
  */
 void nc_server_tls_set_trusted_cert_list_clb(int (*cert_list_clb)(const char *name, void *user_data, char ***cert_paths,
-                                                                  int *cert_path_count, char ***cert_data, int *cert_data_count),
-                                             void *user_data, void (*free_user_data)(void *user_data));
+        int *cert_path_count, char ***cert_data, int *cert_data_count), void *user_data, void (*free_user_data)(void *user_data));
 
 /**
  * @brief Remove a trusted certificate.
diff --git a/src/session_server_ch.h b/src/session_server_ch.h
index 17b4b90..975e845 100644
--- a/src/session_server_ch.h
+++ b/src/session_server_ch.h
@@ -98,6 +98,29 @@
 int nc_server_ch_client_endpt_set_port(const char *client_name, const char *endpt_name, uint16_t port);
 
 /**
+ * @brief Change Call Home client endpoint keepalives state. Affects only new connections.
+ *
+ * @param[in] client_name Existing Call Home client name.
+ * @param[in] endpt_name Existing endpoint name of \p client_name.
+ * @param[in] enable Whether to enable or disable keepalives.
+ * @return 0 on success, -1 on error.
+ */
+int nc_server_ch_client_endpt_enable_keepalives(const char *client_name, const char *endpt_name, int enable);
+
+/**
+ * @brief Change Call Home client endpoint keepalives parameters. Affects only new connections.
+ *
+ * @param[in] client_name Existing Call Home client name.
+ * @param[in] endpt_name Existing endpoint name of \p client_name.
+ * @param[in] idle_time Keepalive idle time in seconds, 1 by default, -1 to keep previous value.
+ * @param[in] max_probes Keepalive max probes sent, 10 by default, -1 to keep previous value.
+ * @param[in] probe_interval Keepalive probe interval in seconds, 5 by default, -1 to keep previous value.
+ * @return 0 on success, -1 on error.
+ */
+int nc_server_ch_client_endpt_set_keepalives(const char *client_name, const char *endpt_name, int idle_time,
+        int max_probes, int probe_interval);
+
+/**
  * @brief Set Call Home client connection type.
  *
  * @param[in] client_name Existing Call Home client name.
@@ -107,31 +130,22 @@
 int nc_server_ch_client_set_conn_type(const char *client_name, NC_CH_CONN_TYPE conn_type);
 
 /**
- * @brief Set Call Home client persistent connection idle timeout.
+ * @brief Set Call Home client periodic connection period for reconnecting.
  *
  * @param[in] client_name Existing Call Home client name.
- * @param[in] idle_timeout Call Home persistent idle timeout.
+ * @param[in] period Call Home periodic connection period in minutes.
  * @return 0 on success, -1 on error.
  */
-int nc_server_ch_client_persist_set_idle_timeout(const char *client_name, uint32_t idle_timeout);
+int nc_server_ch_client_periodic_set_period(const char *client_name, uint16_t period);
 
 /**
- * @brief Set Call Home client persistent connection keep-alive max wait time.
+ * @brief Set Call Home client periodic connection period anchor time.
  *
  * @param[in] client_name Existing Call Home client name.
- * @param[in] max_wait Call Home persistent max wait time for keep-alive reply.
+ * @param[in] anchor_time Call Home periodic connection anchor time for the period.
  * @return 0 on success, -1 on error.
  */
-int nc_server_ch_client_persist_set_keep_alive_max_wait(const char *client_name, uint16_t max_wait);
-
-/**
- * @brief Set Call Home client persistent connection keep-alive max attempts.
- *
- * @param[in] client_name Existing Call Home client name.
- * @param[in] max_attempts Call Home persistent keep-alive maximum contact attempts.
- * @return 0 on success, -1 on error.
- */
-int nc_server_ch_client_persist_set_keep_alive_max_attempts(const char *client_name, uint8_t max_attempts);
+int nc_server_ch_client_periodic_set_anchor_time(const char *client_name, time_t anchor_time);
 
 /**
  * @brief Set Call Home client periodic connection idle timeout.
@@ -140,16 +154,7 @@
  * @param[in] idle_timeout Call Home periodic idle timeout.
  * @return 0 on success, -1 on error.
  */
-int nc_server_ch_client_period_set_idle_timeout(const char *client_name, uint16_t idle_timeout);
-
-/**
- * @brief Set Call Home client periodic reconnect timeout.
- *
- * @param[in] client_name Existing Call Home client name.
- * @param[in] reconnect_timeout Call Home periodic reconnect timeout.
- * @return 0 on success, -1 on error.
- */
-int nc_server_ch_client_period_set_reconnect_timeout(const char *client_name, uint16_t reconnect_timeout);
+int nc_server_ch_client_periodic_set_idle_timeout(const char *client_name, uint16_t idle_timeout);
 
 /**
  * @brief Set Call Home client start-with policy.
diff --git a/src/session_server_ssh.c b/src/session_server_ssh.c
index 73a2ded..f0fd245 100644
--- a/src/session_server_ssh.c
+++ b/src/session_server_ssh.c
@@ -181,8 +181,7 @@
 
 API void
 nc_server_ssh_set_hostkey_clb(int (*hostkey_clb)(const char *name, void *user_data, char **privkey_path,
-                                                 char **privkey_data, NC_SSH_KEY *privkey_type),
-                              void *user_data, void (*free_user_data)(void *user_data))
+        char **privkey_data, NC_SSH_KEY_TYPE *privkey_type), void *user_data, void (*free_user_data)(void *user_data))
 {
     if (!hostkey_clb) {
         ERRARG("hostkey_clb");
@@ -1311,7 +1310,7 @@
     uint8_t i;
     char *privkey_path, *privkey_data;
     int ret;
-    NC_SSH_KEY privkey_type;
+    NC_SSH_KEY_TYPE privkey_type;
 
     if (!server_opts.hostkey_clb) {
         ERR("Callback for retrieving SSH host keys not set.");
diff --git a/src/session_server_tls.c b/src/session_server_tls.c
index 9e2db74..5432418 100644
--- a/src/session_server_tls.c
+++ b/src/session_server_tls.c
@@ -974,8 +974,8 @@
 
 API void
 nc_server_tls_set_server_cert_clb(int (*cert_clb)(const char *name, void *user_data, char **cert_path, char **cert_data,
-                                                  char **privkey_path, char **privkey_data, NC_SSH_KEY *privkey_type),
-                                  void *user_data, void (*free_user_data)(void *user_data))
+        char **privkey_path, char **privkey_data, NC_SSH_KEY_TYPE *privkey_type), void *user_data,
+        void (*free_user_data)(void *user_data))
 {
     if (!cert_clb) {
         ERRARG("cert_clb");
@@ -989,8 +989,7 @@
 
 API void
 nc_server_tls_set_server_cert_chain_clb(int (*cert_chain_clb)(const char *name, void *user_data, char ***cert_paths,
-                                                              int *cert_path_count, char ***cert_data, int *cert_data_count),
-                                        void *user_data, void (*free_user_data)(void *user_data))
+        int *cert_path_count, char ***cert_data, int *cert_data_count), void *user_data, void (*free_user_data)(void *user_data))
 {
     if (!cert_chain_clb) {
         ERRARG("cert_chain_clb");
@@ -1798,7 +1797,7 @@
 {
     char *cert_path = NULL, *cert_data = NULL, *privkey_path = NULL, *privkey_data = NULL;
     int ret = 0;
-    NC_SSH_KEY privkey_type;
+    NC_SSH_KEY_TYPE privkey_type;
     X509 *cert = NULL;
     EVP_PKEY *pkey = NULL;
 
@@ -1811,7 +1810,7 @@
     }
 
     if (server_opts.server_cert_clb(cert_name, server_opts.server_cert_data, &cert_path, &cert_data, &privkey_path,
-                                    &privkey_data, &privkey_type)) {
+                &privkey_data, &privkey_type)) {
         ERR("Server certificate callback failed.");
         return -1;
     }