session CHANGE option store adjusted for ietf-netconf-server granularity
diff --git a/src/session_server.c b/src/session_server.c
index 4bc841f..608887c 100644
--- a/src/session_server.c
+++ b/src/session_server.c
@@ -40,7 +40,7 @@
extern pthread_mutex_t tls_ch_opts_lock;
struct nc_endpt *
-nc_server_endpt_lock(const char *name, NC_TRANSPORT_IMPL ti)
+nc_server_endpt_lock(const char *name, uint16_t *idx)
{
uint16_t i;
struct nc_endpt *endpt = NULL;
@@ -49,7 +49,7 @@
pthread_rwlock_rdlock(&server_opts.endpt_array_lock);
for (i = 0; i < server_opts.endpt_count; ++i) {
- if ((server_opts.binds[i].ti == ti) && !strcmp(server_opts.endpts[i].name, name)) {
+ if (!strcmp(server_opts.endpts[i].name, name)) {
endpt = &server_opts.endpts[i];
break;
}
@@ -65,6 +65,10 @@
/* ENDPT LOCK */
pthread_mutex_lock(&endpt->endpt_lock);
+ if (idx) {
+ *idx = i;
+ }
+
return endpt;
}
@@ -390,7 +394,7 @@
pthread_spin_destroy(&server_opts.sid_lock);
#if defined(NC_ENABLED_SSH) || defined(NC_ENABLED_TLS)
- nc_server_del_endpt(NULL, 0);
+ nc_server_del_endpt(NULL);
#endif
nc_destroy();
}
@@ -1226,24 +1230,20 @@
#if defined(NC_ENABLED_SSH) || defined(NC_ENABLED_TLS)
-int
-nc_server_add_endpt_listen(const char *name, const char *address, uint16_t port, NC_TRANSPORT_IMPL ti)
+API int
+nc_server_add_endpt(const char *name)
{
- int sock;
uint16_t i;
#ifdef NC_ENABLED_SSH
- struct nc_server_ssh_opts *ssh_opts;
+ uint16_t bind_ssh_idx;
+#endif
+#ifdef NC_ENABLED_TLS
+ uint16_t bind_tls_idx;
#endif
if (!name) {
ERRARG("name");
return -1;
- } else if (!address) {
- ERRARG("address");
- return -1;
- } else if (!port) {
- ERRARG("port");
- return -1;
}
/* WRITE LOCK */
@@ -1251,7 +1251,7 @@
/* check name uniqueness */
for (i = 0; i < server_opts.endpt_count; ++i) {
- if ((server_opts.binds[i].ti == ti) && !strcmp(server_opts.endpts[i].name, name)) {
+ if (!strcmp(server_opts.endpts[i].name, name)) {
ERR("Endpoint \"%s\" already exists.", name);
/* WRITE UNLOCK */
pthread_rwlock_unlock(&server_opts.endpt_array_lock);
@@ -1259,63 +1259,71 @@
}
}
- sock = nc_sock_listen(address, port);
- if (sock == -1) {
- /* WRITE UNLOCK */
- pthread_rwlock_unlock(&server_opts.endpt_array_lock);
- return -1;
- }
-
++server_opts.endpt_count;
- server_opts.binds = nc_realloc(server_opts.binds, server_opts.endpt_count * sizeof *server_opts.binds);
server_opts.endpts = nc_realloc(server_opts.endpts, server_opts.endpt_count * sizeof *server_opts.endpts);
- if (!server_opts.binds || !server_opts.endpts) {
+ if (!server_opts.endpts) {
ERRMEM;
/* WRITE UNLOCK */
pthread_rwlock_unlock(&server_opts.endpt_array_lock);
- close(sock);
+ return -1;
+ }
+ server_opts.endpts[server_opts.endpt_count - 1].name = lydict_insert(server_opts.ctx, name, 0);
+
+#if defined(NC_ENABLED_SSH) && defined(NC_ENABLED_TLS)
+ server_opts.binds = nc_realloc(server_opts.binds, 2 * server_opts.endpt_count * sizeof *server_opts.binds);
+ bind_ssh_idx = (server_opts.endpt_count - 1) * 2;
+ bind_tls_idx = (server_opts.endpt_count - 1) * 2 + 1;
+#else
+ server_opts.binds = nc_realloc(server_opts.binds, server_opts.endpt_count * sizeof *server_opts.binds);
+# ifdef NC_ENABLED_SSH
+ bind_ssh_idx = server_opts.endpt_count - 1;
+# endif
+# ifdef NC_ENABLED_TLS
+ bind_tls_idx = server_opts.endpt_count - 1;
+# endif
+#endif
+ if (!server_opts.binds) {
+ ERRMEM;
+ /* WRITE UNLOCK */
+ pthread_rwlock_unlock(&server_opts.endpt_array_lock);
return -1;
}
- server_opts.endpts[server_opts.endpt_count - 1].name = lydict_insert(server_opts.ctx, name, 0);
- server_opts.binds[server_opts.endpt_count - 1].address = lydict_insert(server_opts.ctx, address, 0);
- server_opts.binds[server_opts.endpt_count - 1].port = port;
- server_opts.binds[server_opts.endpt_count - 1].sock = sock;
- server_opts.binds[server_opts.endpt_count - 1].ti = ti;
- switch (ti) {
#ifdef NC_ENABLED_SSH
- case NC_TI_LIBSSH:
- ssh_opts = calloc(1, sizeof *ssh_opts);
- if (!ssh_opts) {
- ERRMEM;
- /* WRITE UNLOCK */
- pthread_rwlock_unlock(&server_opts.endpt_array_lock);
- return -1;
- }
- /* set default values */
- ssh_opts->auth_methods = NC_SSH_AUTH_PUBLICKEY | NC_SSH_AUTH_PASSWORD | NC_SSH_AUTH_INTERACTIVE;
- ssh_opts->auth_attempts = 3;
- ssh_opts->auth_timeout = 10;
+ server_opts.binds[bind_ssh_idx].address = NULL;
+ server_opts.binds[bind_ssh_idx].port = 0;
+ server_opts.binds[bind_ssh_idx].sock = -1;
+ server_opts.binds[bind_ssh_idx].ti = NC_TI_LIBSSH;
- server_opts.endpts[server_opts.endpt_count - 1].ti_opts = ssh_opts;
- break;
-#endif
-#ifdef NC_ENABLED_TLS
- case NC_TI_OPENSSL:
- server_opts.endpts[server_opts.endpt_count - 1].ti_opts = calloc(1, sizeof(struct nc_server_tls_opts));
- if (!server_opts.endpts[server_opts.endpt_count - 1].ti_opts) {
- ERRMEM;
- /* WRITE UNLOCK */
- pthread_rwlock_unlock(&server_opts.endpt_array_lock);
- return -1;
- }
- break;
-#endif
- default:
- ERRINT;
- server_opts.endpts[server_opts.endpt_count - 1].ti_opts = NULL;
- break;
+ server_opts.endpts[server_opts.endpt_count - 1].ssh_opts = calloc(1, sizeof(struct nc_server_ssh_opts));
+ if (!server_opts.endpts[server_opts.endpt_count - 1].ssh_opts) {
+ ERRMEM;
+ /* WRITE UNLOCK */
+ pthread_rwlock_unlock(&server_opts.endpt_array_lock);
+ return -1;
}
+ /* set default values */
+ server_opts.endpts[server_opts.endpt_count - 1].ssh_opts->auth_methods =
+ NC_SSH_AUTH_PUBLICKEY | NC_SSH_AUTH_PASSWORD | NC_SSH_AUTH_INTERACTIVE;
+ server_opts.endpts[server_opts.endpt_count - 1].ssh_opts->auth_attempts = 3;
+ server_opts.endpts[server_opts.endpt_count - 1].ssh_opts->auth_timeout = 10;
+#endif
+
+#ifdef NC_ENABLED_TLS
+ server_opts.binds[bind_tls_idx].address = NULL;
+ server_opts.binds[bind_tls_idx].port = 0;
+ server_opts.binds[bind_tls_idx].sock = -1;
+ server_opts.binds[bind_tls_idx].ti = NC_TI_OPENSSL;
+
+ server_opts.endpts[server_opts.endpt_count - 1].tls_opts = calloc(1, sizeof(struct nc_server_tls_opts));
+ if (!server_opts.endpts[server_opts.endpt_count - 1].tls_opts) {
+ ERRMEM;
+ /* WRITE UNLOCK */
+ pthread_rwlock_unlock(&server_opts.endpt_array_lock);
+ return -1;
+ }
+#endif
+
pthread_mutex_init(&server_opts.endpts[server_opts.endpt_count - 1].endpt_lock, NULL);
/* WRITE UNLOCK */
@@ -1330,7 +1338,7 @@
struct nc_endpt *endpt;
struct nc_bind *bind = NULL;
uint16_t i;
- int sock;
+ int sock = -1, set_addr;
if (!endpt_name) {
ERRARG("endpt_name");
@@ -1343,42 +1351,70 @@
return -1;
}
+ if (address) {
+ set_addr = 1;
+ } else {
+ set_addr = 0;
+ }
+
/* LOCK */
- endpt = nc_server_endpt_lock(endpt_name, ti);
+ endpt = nc_server_endpt_lock(endpt_name, &i);
if (!endpt) {
return -1;
}
- /* we need to learn the index, to get the bind :-/ */
- for (i = 0; i < server_opts.endpt_count; ++i) {
- if (&server_opts.endpts[i] == endpt) {
- bind = &server_opts.binds[i];
- }
+#if defined(NC_ENABLED_SSH) && defined(NC_ENABLED_TLS)
+ if (ti == NC_TI_LIBSSH) {
+ bind = &server_opts.binds[2 * i];
+ } else {
+ bind = &server_opts.binds[2 * i + 1];
}
+#else
+ bind = &server_opts.binds[i];
+ assert(bind->ti == ti);
+#endif
if (!bind) {
ERRINT;
goto fail;
}
- if (address) {
- sock = nc_sock_listen(address, bind->port);
+ if (set_addr) {
+ port = bind->port;
} else {
- sock = nc_sock_listen(bind->address, port);
- }
- if (sock == -1) {
- goto fail;
+ address = bind->address;
}
- /* close old socket, update parameters */
- close(bind->sock);
- bind->sock = sock;
- if (address) {
+ /* we have all the information we need to create a listening socket */
+ if (address && port) {
+ /* create new socket, close the old one */
+ sock = nc_sock_listen(address, port);
+ if (sock == -1) {
+ goto fail;
+ }
+
+ 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, (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
+ }
+
/* UNLOCK */
nc_server_endpt_unlock(endpt);
return 0;
@@ -1389,8 +1425,8 @@
return -1;
}
-int
-nc_server_del_endpt(const char *name, NC_TRANSPORT_IMPL ti)
+API int
+nc_server_del_endpt(const char *name)
{
uint32_t i;
int ret = -1;
@@ -1398,71 +1434,90 @@
/* WRITE LOCK */
pthread_rwlock_wrlock(&server_opts.endpt_array_lock);
- if (!name && !ti) {
- /* remove all */
+ if (!name) {
+ /* remove all endpoints */
for (i = 0; i < server_opts.endpt_count; ++i) {
lydict_remove(server_opts.ctx, server_opts.endpts[i].name);
- lydict_remove(server_opts.ctx, server_opts.binds[i].address);
-
- close(server_opts.binds[i].sock);
pthread_mutex_destroy(&server_opts.endpts[i].endpt_lock);
- switch (server_opts.binds[i].ti) {
#ifdef NC_ENABLED_SSH
- case NC_TI_LIBSSH:
- nc_server_ssh_clear_opts(server_opts.endpts[i].ti_opts);
- break;
+ nc_server_ssh_clear_opts(server_opts.endpts[i].ssh_opts);
+ free(server_opts.endpts[i].ssh_opts);
#endif
#ifdef NC_ENABLED_TLS
- case NC_TI_OPENSSL:
- nc_server_tls_clear_opts(server_opts.endpts[i].ti_opts);
- break;
+ nc_server_tls_clear_opts(server_opts.endpts[i].tls_opts);
+ free(server_opts.endpts[i].tls_opts);
#endif
- default:
- ERRINT;
- break;
- }
- free(server_opts.endpts[i].ti_opts);
-
ret = 0;
}
- free(server_opts.binds);
- server_opts.binds = NULL;
free(server_opts.endpts);
server_opts.endpts = NULL;
+
+ /* remove all binds */
+ for (i = 0; i < server_opts.endpt_count; ++i) {
+ lydict_remove(server_opts.ctx, server_opts.binds[i].address);
+ if (server_opts.binds[i].sock > -1) {
+ close(server_opts.binds[i].sock);
+ }
+ }
+#if defined(NC_ENABLED_SSH) && defined(NC_ENABLED_TLS)
+ for (; i < 2 * server_opts.endpt_count; ++i) {
+ lydict_remove(server_opts.ctx, server_opts.binds[i].address);
+ if (server_opts.binds[i].sock > -1) {
+ close(server_opts.binds[i].sock);
+ }
+ }
+#endif
+ free(server_opts.binds);
+ server_opts.binds = NULL;
+
server_opts.endpt_count = 0;
} else {
- /* remove one name endpoint or all ti endpoints */
+ /* remove one endpoint with bind(s) */
for (i = 0; i < server_opts.endpt_count; ++i) {
- if ((server_opts.binds[i].ti == ti) &&
- (!name || !strcmp(server_opts.endpts[i].name, name))) {
-
+ if (!strcmp(server_opts.endpts[i].name, name)) {
+ /* remove endpt */
lydict_remove(server_opts.ctx, server_opts.endpts[i].name);
- lydict_remove(server_opts.ctx, server_opts.binds[i].address);
- close(server_opts.binds[i].sock);
pthread_mutex_destroy(&server_opts.endpts[i].endpt_lock);
- switch (server_opts.binds[i].ti) {
#ifdef NC_ENABLED_SSH
- case NC_TI_LIBSSH:
- nc_server_ssh_clear_opts(server_opts.endpts[i].ti_opts);
- break;
+ nc_server_ssh_clear_opts(server_opts.endpts[i].ssh_opts);
+ free(server_opts.endpts[i].ssh_opts);
#endif
#ifdef NC_ENABLED_TLS
- case NC_TI_OPENSSL:
- nc_server_tls_clear_opts(server_opts.endpts[i].ti_opts);
- break;
+ nc_server_tls_clear_opts(server_opts.endpts[i].tls_opts);
+ free(server_opts.endpts[i].tls_opts);
#endif
- default:
- ERRINT;
- break;
- }
- free(server_opts.endpts[i].ti_opts);
+ /* remove bind(s) */
+#if defined(NC_ENABLED_SSH) && defined(NC_ENABLED_TLS)
+ i *= 2;
+ lydict_remove(server_opts.ctx, server_opts.binds[i].address);
+ if (server_opts.binds[i].sock > -1) {
+ close(server_opts.binds[i].sock);
+ }
+ ++i;
+#endif
+ lydict_remove(server_opts.ctx, server_opts.binds[i].address);
+ if (server_opts.binds[i].sock > -1) {
+ close(server_opts.binds[i].sock);
+ }
+
+ /* move last endpt and bind(s) to the empty space */
--server_opts.endpt_count;
+#if defined(NC_ENABLED_SSH) && defined(NC_ENABLED_TLS)
+ --i;
+ i /= 2;
+ if (i < server_opts.endpt_count) {
+ memcpy(&server_opts.binds[2 * i], &server_opts.binds[2 * server_opts.endpt_count], 2 * sizeof *server_opts.binds);
+ memcpy(&server_opts.endpts[i], &server_opts.endpts[server_opts.endpt_count], sizeof *server_opts.endpts);
+ }
+#else
if (i < server_opts.endpt_count) {
memcpy(&server_opts.binds[i], &server_opts.binds[server_opts.endpt_count], sizeof *server_opts.binds);
memcpy(&server_opts.endpts[i], &server_opts.endpts[server_opts.endpt_count], sizeof *server_opts.endpts);
- } else if (!server_opts.endpt_count) {
+ }
+#endif
+ else if (!server_opts.endpt_count) {
free(server_opts.binds);
server_opts.binds = NULL;
free(server_opts.endpts);
@@ -1470,11 +1525,7 @@
}
ret = 0;
-
- if (name) {
- /* one name endpoint removed, they are unique, we're done */
- break;
- }
+ break;
}
}
}
@@ -1491,7 +1542,7 @@
NC_MSG_TYPE msgtype;
int sock, ret;
char *host = NULL;
- uint16_t port, idx;
+ uint16_t port, endpt_idx, bind_idx;
if (!server_opts.ctx) {
ERRINIT;
@@ -1513,7 +1564,7 @@
return NC_MSG_ERROR;
}
- ret = nc_sock_accept_binds(server_opts.binds, server_opts.endpt_count, timeout, &host, &port, &idx);
+ ret = nc_sock_accept_binds(server_opts.binds, server_opts.endpt_count, timeout, &host, &port, &bind_idx);
if (ret < 1) {
/* WRITE UNLOCK */
@@ -1551,11 +1602,19 @@
}
pthread_mutex_init((*session)->ti_lock, NULL);
- (*session)->data = server_opts.endpts[idx].ti_opts;
+ endpt_idx = bind_idx;
+ /* transform index as needed */
+#if defined(NC_ENABLED_SSH) && defined(NC_ENABLED_TLS)
+ if (server_opts.binds[bind_idx].ti == NC_TI_OPENSSL) {
+ --endpt_idx;
+ }
+ endpt_idx /= 2;
+#endif
/* sock gets assigned to session or closed */
#ifdef NC_ENABLED_SSH
- if (server_opts.binds[idx].ti == NC_TI_LIBSSH) {
+ if (server_opts.binds[bind_idx].ti == NC_TI_LIBSSH) {
+ (*session)->data = server_opts.endpts[endpt_idx].ssh_opts;
ret = nc_accept_ssh_session(*session, sock, timeout);
if (ret < 0) {
msgtype = NC_MSG_ERROR;
@@ -1567,7 +1626,8 @@
} else
#endif
#ifdef NC_ENABLED_TLS
- if (server_opts.binds[idx].ti == NC_TI_OPENSSL) {
+ if (server_opts.binds[bind_idx].ti == NC_TI_OPENSSL) {
+ (*session)->data = server_opts.endpts[endpt_idx].tls_opts;
ret = nc_accept_tls_session(*session, sock, timeout);
if (ret < 0) {
msgtype = NC_MSG_ERROR;