UNIX socket UPDATE configurable with YANG data
Implemented the ability to create a UNIX socket server with YANG
data. Additionally all new tests timeouts are now unified.
diff --git a/modules/libnetconf2-netconf-server.yang b/modules/libnetconf2-netconf-server.yang
index f9b7625..9d8bbb9 100644
--- a/modules/libnetconf2-netconf-server.yang
+++ b/modules/libnetconf2-netconf-server.yang
@@ -32,4 +32,24 @@
}
}
}
+
+ augment "/ncs:netconf-server/ncs:listen/ncs:endpoint/ncs:transport" {
+ case unix-socket {
+ container unix-socket {
+ leaf path {
+ type string;
+ mandatory true;
+ }
+ leaf mode {
+ type uint16;
+ }
+ leaf uid {
+ type uint16;
+ }
+ leaf gid {
+ type uint16;
+ }
+ }
+ }
+ }
}
diff --git a/src/config_server.c b/src/config_server.c
index 2c41ee0..50e3c1b 100644
--- a/src/config_server.c
+++ b/src/config_server.c
@@ -479,6 +479,35 @@
}
void
+nc_server_del_unix_socket(struct nc_bind *bind, struct nc_server_unix_opts *opts)
+{
+ if (bind->sock > -1) {
+ close(bind->sock);
+ }
+
+ free(bind->address);
+ free(opts->address);
+
+ free(opts);
+ opts = NULL;
+}
+
+void
+nc_server_del_endpt_unix_socket(struct nc_endpt *endpt, struct nc_bind *bind)
+{
+ nc_server_del_endpt_name(endpt);
+ nc_server_del_unix_socket(bind, endpt->opts.unixsock);
+
+ server_opts.endpt_count--;
+ if (!server_opts.endpt_count) {
+ free(server_opts.endpts);
+ free(server_opts.binds);
+ server_opts.endpts = NULL;
+ server_opts.binds = NULL;
+ }
+}
+
+void
nc_server_config_del_keystore(void)
{
int i, j;
@@ -520,7 +549,13 @@
if (op == NC_OP_DELETE) {
for (i = 0; i < server_opts.endpt_count; i++) {
- nc_server_del_endpt_ssh(&server_opts.endpts[i], &server_opts.binds[i]);
+ if (server_opts.endpts[i].ti == NC_TI_LIBSSH) {
+ nc_server_del_endpt_ssh(&server_opts.endpts[i], &server_opts.binds[i]);
+ } else if (server_opts.endpts[i].ti == NC_TI_OPENSSL) {
+ /* todo */
+ } else {
+ nc_server_del_endpt_unix_socket(&server_opts.endpts[i], &server_opts.binds[i]);
+ }
}
}
@@ -676,7 +711,7 @@
{
int sock = -1, set_addr, ret = 0;
- assert((address && !port) || (!address && port));
+ assert((address && !port) || (!address && port) || (endpt->ti == NC_TI_UNIX));
if (address) {
set_addr = 1;
@@ -690,15 +725,15 @@
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) {
+ if ((address && port) || (endpt->ti == NC_TI_UNIX)) {
/* create new socket, close the old one */
- sock = nc_sock_listen_inet(address, port, &endpt->ka);
+ if (endpt->ti == NC_TI_UNIX) {
+ sock = nc_sock_listen_unix(endpt->opts.unixsock);
+ } else {
+ sock = nc_sock_listen_inet(address, port, &endpt->ka);
+ }
+
if (sock == -1) {
ret = 1;
goto cleanup;
@@ -712,6 +747,9 @@
if (sock > -1) {
switch (endpt->ti) {
+ case NC_TI_UNIX:
+ VRB(NULL, "Listening on %s for UNIX connections.", endpt->opts.unixsock->address);
+ break;
#ifdef NC_ENABLED_SSH
case NC_TI_LIBSSH:
VRB(NULL, "Listening on %s:%u for SSH connections.", address, port);
@@ -1911,6 +1949,92 @@
}
static int
+nc_server_create_unix_socket(struct nc_endpt *endpt)
+{
+ endpt->ti = NC_TI_UNIX;
+ endpt->opts.unixsock = calloc(1, sizeof *endpt->opts.unixsock);
+ if (!endpt->opts.unixsock) {
+ ERRMEM;
+ return 1;
+ }
+
+ /* set default values */
+ endpt->opts.unixsock->mode = -1;
+ endpt->opts.unixsock->uid = -1;
+ endpt->opts.unixsock->gid = -1;
+
+ return 0;
+}
+
+static int
+nc_server_configure_unix_socket(const struct lyd_node *node, NC_OPERATION op)
+{
+ int ret = 0;
+ uint32_t prev_lo;
+ struct nc_endpt *endpt;
+ struct nc_bind *bind;
+ struct nc_server_unix_opts *opts;
+ struct lyd_node *data = NULL;
+
+ assert(!strcmp(LYD_NAME(node), "unix-socket"));
+
+ if (nc_server_get_endpt(node, &endpt, &bind)) {
+ ret = 1;
+ goto cleanup;
+ }
+
+ if (op == NC_OP_CREATE) {
+ if (nc_server_create_unix_socket(endpt)) {
+ ret = 1;
+ goto cleanup;
+ }
+
+ opts = endpt->opts.unixsock;
+
+ lyd_find_path(node, "path", 0, &data);
+ assert(data);
+
+ opts->address = strdup(lyd_get_value(data));
+ bind->address = strdup(lyd_get_value(data));
+ if (!opts->address || !bind->address) {
+ ERRMEM;
+ ret = 1;
+ goto cleanup;
+ }
+
+ /* silently search for non-mandatory parameters */
+ prev_lo = ly_log_options(0);
+ ret = lyd_find_path(node, "mode", 0, &data);
+ if (!ret) {
+ opts->mode = strtol(lyd_get_value(data), NULL, 8);
+ }
+
+ ret = lyd_find_path(node, "uid", 0, &data);
+ if (!ret) {
+ opts->uid = strtol(lyd_get_value(data), NULL, 10);
+ }
+
+ ret = lyd_find_path(node, "gid", 0, &data);
+ if (!ret) {
+ opts->gid = strtol(lyd_get_value(data), NULL, 10);
+ }
+
+ /* reset the logging options */
+ ly_log_options(prev_lo);
+
+ ret = nc_server_config_set_address_port(endpt, bind, NULL, 0);
+ if (ret) {
+ goto cleanup;
+ }
+ } else if (op == NC_OP_DELETE) {
+ nc_server_del_unix_socket(bind, endpt->opts.unixsock);
+ }
+
+cleanup:
+ return ret;
+}
+
+static int
nc_server_configure(const struct lyd_node *node, NC_OPERATION op)
{
const char *name = LYD_NAME(node);
@@ -2027,6 +2151,10 @@
if (nc_server_configure_mac_alg(node, op)) {
goto error;
}
+ } else if (!strcmp(name, "unix-socket")) {
+ if (nc_server_configure_unix_socket(node, op)) {
+ goto error;
+ }
} else if (!strcmp(name, "cert-data")) {} else if (!strcmp(name, "expiration-date")) {} else if (!strcmp(name, "asymmetric-key")) {} else if (!strcmp(name, "certificate")) {} else if (!strcmp(name, "key-format")) {} else if (!strcmp(name,
"cleartext-key")) {} else if (!strcmp(name, "hidden-key")) {} else if (!strcmp(name, "id_hint")) {} else if (!strcmp(name, "external-identity")) {} else if (!strcmp(name, "hash")) {} else if (!strcmp(name, "context")) {} else if (!strcmp(name,
"target-protocol")) {} else if (!strcmp(name, "target-kdf")) {} else if (!strcmp(name, "client-authentication")) {} else if (!strcmp(name, "ca-certs")) {} else if (!strcmp(name, "ee-certs")) {} else if (!strcmp(name,
diff --git a/src/session_p.h b/src/session_p.h
index 6818ed1..e75dc34 100644
--- a/src/session_p.h
+++ b/src/session_p.h
@@ -234,6 +234,7 @@
/* ACCESS unlocked */
struct nc_server_unix_opts {
+ char *address;
mode_t mode;
uid_t uid;
gid_t gid;
@@ -756,11 +757,10 @@
/**
* @brief Create a listening socket (AF_UNIX).
*
- * @param[in] address UNIX address to listen on.
- * @param[in] opts The server options (unix permissions).
+ * @param[in] opts The server options (unix permissions and address of the socket).
* @return Listening socket, -1 on error.
*/
-int nc_sock_listen_unix(const char *address, const struct nc_server_unix_opts *opts);
+int nc_sock_listen_unix(const struct nc_server_unix_opts *opts);
/**
* @brief Accept a new connection on a listening socket.
diff --git a/src/session_server.c b/src/session_server.c
index 9f01303..e0514e6 100644
--- a/src/session_server.c
+++ b/src/session_server.c
@@ -282,13 +282,13 @@
}
int
-nc_sock_listen_unix(const char *address, const struct nc_server_unix_opts *opts)
+nc_sock_listen_unix(const struct nc_server_unix_opts *opts)
{
struct sockaddr_un sun;
int sock = -1;
- if (strlen(address) > sizeof(sun.sun_path) - 1) {
- ERR(NULL, "Socket path \"%s\" is longer than maximum length %d.", address, (int)(sizeof(sun.sun_path) - 1));
+ if (strlen(opts->address) > sizeof(sun.sun_path) - 1) {
+ ERR(NULL, "Socket path \"%s\" is longer than maximum length %d.", opts->address, (int)(sizeof(sun.sun_path) - 1));
goto fail;
}
@@ -300,11 +300,11 @@
memset(&sun, 0, sizeof(sun));
sun.sun_family = AF_UNIX;
- snprintf(sun.sun_path, sizeof(sun.sun_path) - 1, "%s", address);
+ snprintf(sun.sun_path, sizeof(sun.sun_path) - 1, "%s", opts->address);
unlink(sun.sun_path);
if (bind(sock, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
- ERR(NULL, "Could not bind \"%s\" (%s).", address, strerror(errno));
+ ERR(NULL, "Could not bind \"%s\" (%s).", opts->address, strerror(errno));
goto fail;
}
@@ -323,7 +323,7 @@
}
if (listen(sock, NC_REVERSE_QUEUE) == -1) {
- ERR(NULL, "Unable to start listening on \"%s\" (%s).", address, strerror(errno));
+ ERR(NULL, "Unable to start listening on \"%s\" (%s).", opts->address, strerror(errno));
goto fail;
}
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index ca85067..2a13145 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -9,7 +9,7 @@
# list of all the tests in each directory
#set(tests test_io test_fd_comm test_init_destroy_client test_init_destroy_server test_client_thread test_thread_messages)
-set(tests test_two_channels test_keystore)
+set(tests test_two_channels test_keystore test_unix_socket)
# only enable PAM tests if the version of PAM is greater than 1.4
if(LIBPAM_HAVE_CONFDIR)
diff --git a/tests/test_auth.c b/tests/test_auth.c
index 29b22b1..5511da9 100644
--- a/tests/test_auth.c
+++ b/tests/test_auth.c
@@ -31,13 +31,12 @@
#include "tests/config.h"
-#define NC_ACCEPT_TIMEOUT 100
-#define NC_PS_POLL_TIMEOUT 100
+#define NC_ACCEPT_TIMEOUT 2000
+#define NC_PS_POLL_TIMEOUT 2000
struct ly_ctx *ctx;
struct test_state {
- // bariera
pthread_barrier_t barrier;
};
diff --git a/tests/test_keystore.c b/tests/test_keystore.c
index 5f583ad..c7e8af8 100644
--- a/tests/test_keystore.c
+++ b/tests/test_keystore.c
@@ -31,13 +31,12 @@
#include "tests/config.h"
-#define NC_ACCEPT_TIMEOUT 100
-#define NC_PS_POLL_TIMEOUT 100
+#define NC_ACCEPT_TIMEOUT 2000
+#define NC_PS_POLL_TIMEOUT 2000
struct ly_ctx *ctx;
struct test_state {
- // bariera
pthread_barrier_t barrier;
};
diff --git a/tests/test_nc3.c b/tests/test_nc3.c
deleted file mode 100644
index f74ab25..0000000
--- a/tests/test_nc3.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/**
- * @file test_pam.c
- * @author Roman Janota <xjanot04@fit.vutbr.cz>
- * @brief libnetconf2 Linux PAM keyboard-interactive authentication test
- *
- * @copyright
- * Copyright (c) 2022 CESNET, z.s.p.o.
- *
- * This source code is licensed under BSD 3-Clause License (the "License").
- * You may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://opensource.org/licenses/BSD-3-Clause
- */
-
-#include <pthread.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <libyang/libyang.h>
-#include <log.h>
-#include <session_client.h>
-#include <session_server.h>
-#include "config_server.h"
-
-#include "tests/config.h"
-
-#define nc_assert(cond) if (!(cond)) { fprintf(stderr, "assert failed (%s:%d)\n", __FILE__, __LINE__); abort(); }
-
-#define NC_ACCEPT_TIMEOUT 5000
-#define NC_PS_POLL_TIMEOUT 5000
-
-const char *data =
- "<netconf-server xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-server\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">"
- "<listen yang:operation=\"create\">"
- "<idle-timeout>10</idle-timeout>"
- "<endpoint>"
- "<name>default-ssh</name>"
- "<ssh>"
- "<tcp-server-parameters>"
- "<local-address>127.0.0.1</local-address>"
- "<local-port>10005</local-port>"
- "</tcp-server-parameters>"
- "<ssh-server-parameters>"
- "<server-identity>"
- "<host-key>"
- "<name>key</name>"
- "<public-key>"
- "<local-definition>"
- "<public-key-format xmlns:ct=\"urn:ietf:params:xml:ns:yang:ietf-crypto-types\">ct:ssh-public-key-format</public-key-format>"
- "<public-key>MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA6ojtjfDmvyQP1ZkIwBpr"
- "97eKDuebvpoglRHRdvVuTpf/gU1VArAQmwGh05i6lm8TkVl1noMlIxLJDcWslaeV"
- "n6KyvsX0HhsQtXwqPqwka5UCv6alwf/ivAvcNpcX1j0t/uIGCI4dSiKnzQCyf0FT"
- "irzQkjrDZUd3meDhNQTruCalGV4gfNWIq3e1oGuwAn1tLlu9oTrE4HzMpgbNEU6w"
- "NmsSqpwGxUhYLoSaM7b0dLmqP+ZczSS0Uac0PFNkehGQ2CYIT80f580o4XGtoLCU"
- "UGkp6YCTL4Z2CeBEaJABWjDIDH+dKYIUBqUpz4Th12gXAP+h+3qI6+9eppeHrfrz"
- "ARDsfLjwUNxQJse1QSArjAytf0FKtGHrORc7W0TiCFvR0zaoUNLTKk7enTiRQ9rf"
- "WZOAu44fUvPCaXDE6zXXeaVgoKCo4VHlho36erUcjlEBM+jk28IykbZGtBb6igKv"
- "Ya1tPSgeYm/zJoFVjQcnr14uci/ft1+Na+hOIEoEEiKxcAPk2b2vBKNlRIW7WLJ3"
- "u7ZiuQEJTNm6+3cE4+lfwaBCBqBToE+dpzvoUXoMyFFReUFd1O5axu4fXgt00jMa"
- "OQxmE0v9OmR/pL/PWIflVF4Zz5yVONYaDVc7l+veY0oEZruEPJ0hlEgxuCzLrcMh"
- "jufl2qE2Q7fQIaav/1NqBVkCAwEAAQ==</public-key>"
- "<private-key-format xmlns:ct=\"urn:ietf:params:xml:ns:yang:ietf-crypto-types\">ct:rsa-private-key-format</private-key-format>"
- "<cleartext-private-key>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</cleartext-private-key>"
- "</local-definition>"
- "</public-key>"
- "</host-key>"
- "</server-identity>"
- "<client-authentication>"
- "<users>"
- "<user>"
- "<name>test</name>"
- "<public-keys>"
- "<local-definition>"
- "<public-key>"
- "<name>client</name>"
- "<public-key-format xmlns:ct=\"urn:ietf:params:xml:ns:yang:ietf-crypto-types\">ct:ssh-public-key-format</public-key-format>"
- "<public-key>MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvpKj6gy/Rm1pqlUIaeKp"
- "WuL2KOJBbodhxuPG+0S6f+Jf4LopOB76tmg1RQ/bAXLNxXkG46Cx9UOHaFK/Ixul"
- "cCbH6LxOUg90/HVS7NnbaVtDsl03HG9CPZTlQzM+n+iFAXv5ub5PFzW3VCCNDSfM"
- "tXUOdVR93u/OAc7uz0nWjGhWnOH5MPJCQPS8ZFpL9hQxQuyAXFY0YLW/9eRMDgx/"
- "OPTuvlTxIF+YHaMzY+Wy+Oaygwb78dCow+3RQRgCB20o5o6exx2nX2Cqr7UJzG/N"
- "30XCusKIcTT978td8AU7UjpbzoNehm/tmQdDq+8IDsNfWbxCHDYLMD8IR32UDXGD"
- "DVSwrtNgUs8HWNNCBKjTNCeQf1v/yiRd7hRf2aj+w9sDu8PI+VC9pabsRe2KxnnD"
- "U9Sq+4IB3ZM3C5XpJDbu8DVigGZSevim7p/D6mW2phlyxtlK9WmQ5Misg/Z8jM7E"
- "Z3gJcTvh20IS6I4plG7DJvsIC/Pc3IS2JC/w0prCZa8gOKob8x2mjjQcOA1eVIUm"
- "yw6WbV1X65/jAJvIS6an/oFAk4bBTfJA6fYfU4Pb9NWovYxm/eNR5BbRmFFh0uXa"
- "0s92S50iOotf8CnW7PZ7PWKgzKqtnN9Ob+Ye7WjDdG+NCrhkiDBOCuHDrHXwqaxW"
- "BmUICo2mnUMK7JuJNSZe5DMCAwEAAQ==</public-key>"
- "</public-key>"
- "</local-definition>"
- "</public-keys>"
- "<none/>"
- "</user>"
- "</users>"
- "</client-authentication>"
- "<transport-params>"
- "<host-key>"
- "<host-key-alg xmlns:sshpka=\"urn:ietf:params:xml:ns:yang:iana-ssh-public-key-algs\">sshpka:ssh-rsa</host-key-alg>"
- "<host-key-alg xmlns:sshpka=\"urn:ietf:params:xml:ns:yang:iana-ssh-public-key-algs\">sshpka:rsa-sha2-512</host-key-alg>"
- "</host-key>"
- "<key-exchange>"
- "<key-exchange-alg xmlns:sshkea=\"urn:ietf:params:xml:ns:yang:iana-ssh-key-exchange-algs\">sshkea:diffie-hellman-group18-sha512</key-exchange-alg>"
- "</key-exchange>"
- "<encryption>"
- "<encryption-alg xmlns:sshea=\"urn:ietf:params:xml:ns:yang:iana-ssh-encryption-algs\">sshea:aes256-cbc</encryption-alg>"
- "</encryption>"
- "<mac>"
- "<mac-alg xmlns:sshma=\"urn:ietf:params:xml:ns:yang:iana-ssh-mac-algs\">sshma:hmac-sha1</mac-alg>"
- "</mac>"
- "</transport-params>"
- "</ssh-server-parameters>"
- "</ssh>"
- "</endpoint>"
- "</listen>"
- "</netconf-server>";
-
-static int
-setup(struct ly_ctx *ctx)
-{
- int i;
- const char *all_features[] = {"*", NULL};
- /* no ssh-x509-certs */
- const char *ssh_common_features[] = {"transport-params", "public-key-generation", NULL};
- /* no ssh-server-keepalives and local-user-auth-hostbased */
- const char *ssh_server_features[] = {"local-users-supported", "local-user-auth-publickey", "local-user-auth-password", "local-user-auth-none", NULL};
- /* no private-key-encryption and csr-generation */
- const char *crypto_types_features[] = {
- "one-symmetric-key-format", "one-asymmetric-key-format", "symmetrically-encrypted-value-format",
- "asymmetrically-encrypted-value-format", "cms-enveloped-data-format", "cms-encrypted-data-format",
- "p10-based-csrs", "certificate-expiration-notification", "hidden-keys", "password-encryption",
- "symmetric-key-encryption", NULL
- };
-
- const char *module_names[] = {
- "ietf-netconf-server", "ietf-tls-common", "ietf-tls-server", "ietf-truststore", "iana-crypt-hash", "ietf-keystore",
- "ietf-tcp-server", "ietf-tcp-common", "ietf-tcp-client", "iana-ssh-public-key-algs",
- "iana-ssh-key-exchange-algs", "iana-ssh-encryption-algs", "iana-ssh-mac-algs", NULL
- };
-
- for (i = 0; module_names[i] != NULL; i++) {
- if (!ly_ctx_load_module(ctx, module_names[i], NULL, all_features)) {
- fprintf(stderr, "Loading module (%s) failed.\n", module_names[i]);
- goto error;
- }
- }
-
- if (!ly_ctx_load_module(ctx, "ietf-ssh-common", NULL, ssh_common_features)) {
- fprintf(stderr, "Loading module (ietf-ssh-common) failed.\n");
- goto error;
- }
- if (!ly_ctx_load_module(ctx, "ietf-ssh-server", NULL, ssh_server_features)) {
- fprintf(stderr, "Loading module (ietf-ssh-server) failed.\n");
- goto error;
- }
- if (!ly_ctx_load_module(ctx, "ietf-crypto-types", NULL, crypto_types_features)) {
- fprintf(stderr, "Loading module (ietf-crypto-types) failed.\n");
- goto error;
- }
-
- return 0;
-
-error:
- return 1;
-}
-
-int
-main(void)
-{
- int ret;
- struct ly_ctx *ctx;
- struct lyd_node *tree;
-
- nc_verbosity(NC_VERB_VERBOSE);
-
- ret = ly_ctx_new("/home/roman/Downloads/yang", 0, &ctx);
- nc_assert(!ret);
-
- ret = setup(ctx);
- nc_assert(!ret);
-
- ret = lyd_parse_data_mem(ctx, data, LYD_XML, LYD_PARSE_NO_STATE | LYD_PARSE_STRICT, LYD_VALIDATE_NO_STATE, &tree);
- nc_assert(!ret);
-
- ret = nc_server_config_setup(tree);
- nc_assert(!ret);
-
- nc_server_init();
-
- nc_server_destroy();
- lyd_free_all(tree);
- ly_ctx_destroy(ctx);
- return 0;
-}
diff --git a/tests/test_two_channels.c b/tests/test_two_channels.c
index 37ac20c..ac7550e 100644
--- a/tests/test_two_channels.c
+++ b/tests/test_two_channels.c
@@ -32,8 +32,8 @@
#include "tests/config.h"
-#define NC_ACCEPT_TIMEOUT 5000
-#define NC_PS_POLL_TIMEOUT 500
+#define NC_ACCEPT_TIMEOUT 2000
+#define NC_PS_POLL_TIMEOUT 2000
#define BACKOFF_TIMEOUT_USECS 100
struct ly_ctx *ctx;
diff --git a/tests/test_unix_socket.c b/tests/test_unix_socket.c
new file mode 100644
index 0000000..56c1f12
--- /dev/null
+++ b/tests/test_unix_socket.c
@@ -0,0 +1,198 @@
+/**
+ * @file test_keystore.c
+ * @author Roman Janota <xjanot04@fit.vutbr.cz>
+ * @brief libnetconf2 Linux PAM keyboard-interactive authentication test
+ *
+ * @copyright
+ * Copyright (c) 2022 CESNET, z.s.p.o.
+ *
+ * This source code is licensed under BSD 3-Clause License (the "License").
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <pthread.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <cmocka.h>
+
+#include <config_server.h>
+#include <libnetconf.h>
+#include <libyang/libyang.h>
+#include <log.h>
+#include <session_client.h>
+#include <session_server.h>
+
+#include "tests/config.h"
+
+#define NC_ACCEPT_TIMEOUT 2000
+#define NC_PS_POLL_TIMEOUT 2000
+
+struct ly_ctx *ctx;
+
+struct test_state {
+ pthread_barrier_t barrier;
+};
+
+const char *data =
+ "<netconf-server xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-server\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">\n"
+ " <listen yang:operation=\"create\">\n"
+ " <idle-timeout>10</idle-timeout>\n"
+ " <endpoint>\n"
+ " <name>default-unix-socket</name>\n"
+ " <unix-socket xmlns=\"urn:cesnet:libnetconf2-netconf-server\">\n"
+ " <path>/tmp/nc2_test_unix_sock</path>\n"
+ " </unix-socket>\n"
+ " </endpoint>\n"
+ " </listen>\n"
+ "</netconf-server>\n";
+
+static void *
+server_thread(void *arg)
+{
+ int ret;
+ NC_MSG_TYPE msgtype;
+ struct nc_session *session;
+ struct nc_pollsession *ps;
+ struct test_state *state = arg;
+
+ ps = nc_ps_new();
+ assert_non_null(ps);
+
+ /* accept a session and add it to the poll session structure */
+ pthread_barrier_wait(&state->barrier);
+ msgtype = nc_accept(NC_ACCEPT_TIMEOUT, ctx, &session);
+ assert_int_equal(msgtype, NC_MSG_HELLO);
+
+ ret = nc_ps_add_session(ps, session);
+ assert_int_equal(ret, 0);
+
+ do {
+ ret = nc_ps_poll(ps, NC_PS_POLL_TIMEOUT, NULL);
+ assert_int_equal(ret & NC_PSPOLL_RPC, NC_PSPOLL_RPC);
+ } while (!(ret & NC_PSPOLL_SESSION_TERM));
+
+ nc_ps_clear(ps, 1, NULL);
+ nc_ps_free(ps);
+ nc_thread_destroy();
+ return NULL;
+}
+
+static void *
+client_thread(void *arg)
+{
+ struct nc_session *session = NULL;
+ struct test_state *state = arg;
+
+ pthread_barrier_wait(&state->barrier);
+ session = nc_connect_unix("/tmp/nc2_test_unix_sock", NULL);
+ assert_non_null(session);
+
+ nc_session_free(session, NULL);
+ nc_thread_destroy();
+ return NULL;
+}
+
+static void
+test_nc_connect_unix_socket(void **state)
+{
+ int ret, i;
+ pthread_t tids[2];
+
+ assert_non_null(state);
+
+ ret = pthread_create(&tids[0], NULL, client_thread, *state);
+ assert_int_equal(ret, 0);
+ ret = pthread_create(&tids[1], NULL, server_thread, *state);
+ assert_int_equal(ret, 0);
+
+ for (i = 0; i < 2; i++) {
+ pthread_join(tids[i], NULL);
+ }
+}
+
+static int
+setup_f(void **state)
+{
+ int ret;
+ struct lyd_node *tree;
+ struct test_state *test_state;
+
+ nc_verbosity(NC_VERB_VERBOSE);
+
+ /* init barrier */
+ test_state = malloc(sizeof *test_state);
+ assert_non_null(test_state);
+
+ ret = pthread_barrier_init(&test_state->barrier, NULL, 2);
+ assert_int_equal(ret, 0);
+
+ *state = test_state;
+
+ ret = ly_ctx_new(MODULES_DIR, 0, &ctx);
+ assert_int_equal(ret, 0);
+
+ /* initialize context */
+ ret = nc_server_init_ctx(&ctx);
+ assert_int_equal(ret, 0);
+
+ /* load ietf-netconf-server module and it's dependencies into context */
+ ret = nc_server_config_load_modules(&ctx);
+ assert_int_equal(ret, 0);
+
+ /* parse yang data */
+ ret = lyd_parse_data_mem(ctx, data, LYD_XML, LYD_PARSE_NO_STATE | LYD_PARSE_STRICT, LYD_VALIDATE_NO_STATE, &tree);
+ assert_int_equal(ret, 0);
+
+ /* configure the server based on the data */
+ ret = nc_server_config_setup(tree);
+ assert_int_equal(ret, 0);
+
+ /* initialize client */
+ nc_client_init();
+
+ /* initialize server */
+ ret = nc_server_init();
+ assert_int_equal(ret, 0);
+
+ lyd_free_all(tree);
+
+ return 0;
+}
+
+static int
+teardown_f(void **state)
+{
+ int ret = 0;
+ struct test_state *test_state;
+
+ assert_non_null(state);
+ test_state = *state;
+
+ ret = pthread_barrier_destroy(&test_state->barrier);
+ assert_int_equal(ret, 0);
+
+ free(*state);
+ nc_client_destroy();
+ nc_server_destroy();
+ ly_ctx_destroy(ctx);
+
+ return 0;
+}
+
+int
+main(void)
+{
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test_setup_teardown(test_nc_connect_unix_socket, setup_f, teardown_f),
+ };
+
+ setenv("CMOCKA_TEST_ABORT", "1", 1);
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}