Skip to content

Commit e17e029

Browse files
committed
Merge branch 'devel-server'
2 parents d3ae542 + ca0256d commit e17e029

30 files changed

+1043
-756
lines changed

cli/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ set(CMAKE_C_FLAGS_RELEASE "-O2")
2121
set(CMAKE_C_FLAGS_DEBUG "-g -O0")
2222

2323
# set version
24-
set(NP2CLI_VERSION 2.0.48)
24+
set(NP2CLI_VERSION 2.0.49)
2525
configure_file("${PROJECT_SOURCE_DIR}/version.h.in" "${PROJECT_BINARY_DIR}/version.h" ESCAPE_QUOTES @ONLY)
2626
include_directories(${PROJECT_BINARY_DIR})
2727

cli/commands.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2402,7 +2402,7 @@ cmd_searchpath(const char *arg, char **UNUSED(tmp_config_file))
24022402

24032403
if (!arg[0]) {
24042404
path = nc_client_get_schema_searchpath();
2405-
fprintf(stdout, "%s\n", path[0] ? path : "<none>");
2405+
fprintf(stdout, "%s\n", path && path[0] ? path : "<none>");
24062406
return 0;
24072407
}
24082408

keystored/CMakeLists.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ set(CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG")
2121
set(CMAKE_C_FLAGS_DEBUG "-g -O0 -DDEBUG")
2222

2323
# set version
24-
set(KEYSTORED_VERSION 0.1.1)
24+
set(KEYSTORED_VERSION 0.1.2)
2525

2626
# config variables
2727
if (NOT KEYSTORED_KEYS_DIR)
@@ -131,10 +131,17 @@ endif()
131131

132132
option(SSH_KEY_INSTALL "Enable ssh key import" ON)
133133
if (SSH_KEY_INSTALL)
134+
if (NOT SSH_KEYGEN_EXECUTABLE)
135+
find_program(SSH_KEYGEN_EXECUTABLE ssh-keygen)
136+
endif()
137+
if (NOT SSH_KEYGEN_EXECUTABLE)
138+
message(FATAL_ERROR "Unable to find ssh-keygen, set SSH_KEYGEN_EXECUTABLE manually.")
139+
endif()
134140
install(CODE "
135141
set(ENV{SYSREPOCFG} ${SYSREPOCFG_EXECUTABLE})
136142
set(ENV{CHMOD} ${CHMOD_EXECUTABLE})
137143
set(ENV{OPENSSL} ${OPENSSL_EXECUTABLE})
144+
set(ENV{SSH_KEYGEN} ${SSH_KEYGEN_EXECUTABLE})
138145
set(ENV{KEYSTORED_KEYS_DIR} ${KEYSTORED_KEYS_DIR})
139146
set(ENV{KEYSTORED_CHECK_SSH_KEY} ${KEYSTORED_CHECK_SSH_KEY})
140147
execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/scripts/ssh-key-import.sh)")

keystored/keystored.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ ks_cert_change_cb(sr_session_ctx_t *UNUSED(session), const char *UNUSED(module_n
121121
}
122122

123123
static int
124-
ks_privkey_get_cb(const char *xpath, sr_val_t **values, size_t *values_cnt, void *UNUSED(private_ctx))
124+
ks_privkey_get_cb(const char *xpath, sr_val_t **values, size_t *values_cnt, uint64_t UNUSED(request_id), void *UNUSED(private_ctx))
125125
{
126126
int ret;
127127
const char *name;
@@ -137,7 +137,7 @@ ks_privkey_get_cb(const char *xpath, sr_val_t **values, size_t *values_cnt, void
137137
}
138138
name += 18;
139139

140-
if (asprintf(&path, "%s/%.*s.pub.pem", KEYSTORED_KEYS_DIR, (int)(strchr(name, '\'') - name), name) == -1) {
140+
if (asprintf(&path, "%s/%.*s.pem.pub", KEYSTORED_KEYS_DIR, (int)(strchr(name, '\'') - name), name) == -1) {
141141
SRP_LOG_ERR("Memory allocation failed (%s:%d).", __FILE__, __LINE__);
142142
return SR_ERR_NOMEM;
143143
}
@@ -337,7 +337,7 @@ ks_privkey_gen_cb(const char *UNUSED(xpath), const sr_node_t *input, const size_
337337
goto cleanup;
338338
}
339339
sprintf(priv_path, "%s/%s.pem", KEYSTORED_KEYS_DIR, input[0].data.string_val);
340-
sprintf(pub_path, "%s/%s.pub.pem", KEYSTORED_KEYS_DIR, input[0].data.string_val);
340+
sprintf(pub_path, "%s/%s.pem.pub", KEYSTORED_KEYS_DIR, input[0].data.string_val);
341341

342342
if (!(pid = fork())) {
343343
/* child */
@@ -451,7 +451,7 @@ ks_privkey_load_cb(const char *UNUSED(xpath), const sr_node_t *input, const size
451451
goto cleanup;
452452
}
453453
sprintf(priv_path, "%s/%s.pem", KEYSTORED_KEYS_DIR, input[0].data.string_val);
454-
sprintf(pub_path, "%s/%s.pub.pem", KEYSTORED_KEYS_DIR, input[0].data.string_val);
454+
sprintf(pub_path, "%s/%s.pem.pub", KEYSTORED_KEYS_DIR, input[0].data.string_val);
455455

456456
fd = open(priv_path, O_CREAT | O_TRUNC | O_WRONLY, 00600);
457457
if (fd == -1) {

keystored/scripts/ssh-key-import.sh

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ local_path=$(dirname $0)
99
: ${SYSREPOCFG:=sysrepocfg}
1010
: ${CHMOD:=chmod}
1111
: ${OPENSSL:=openssl}
12+
: ${SSH_KEYGEN:=ssh-keygen}
1213
: ${STOCK_KEY_CONFIG:=$local_path/../stock_key_config.xml}
1314
: ${KEYSTORED_KEYS_DIR:=/etc/keystored/keys}
1415

@@ -21,13 +22,14 @@ if [ $KEYSTORED_CHECK_SSH_KEY -eq 0 ]; then
2122
echo "- Warning: Assuming that an external script will provide the SSH key in a PEM format at \"${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem\"."
2223
echo "- Importing ietf-keystore stock key configuration..."
2324
$SYSREPOCFG -d startup -i ${STOCK_KEY_CONFIG} ietf-keystore
24-
elif [ -r /etc/ssh/ssh_host_rsa_key ]; then
25-
cp /etc/ssh/ssh_host_rsa_key ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem
25+
else
26+
if [ -r ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem -a -r ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem.pub ]; then
27+
echo "- SSH hostkey found, no need to generate a new one."
28+
else
29+
echo "- SSH hostkey not found, generating a new one..."
30+
$SSH_KEYGEN -m pem -t rsa -q -N "" -f ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem
31+
fi
2632
$CHMOD go-rw ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem
27-
$OPENSSL rsa -pubout -in ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem \
28-
-out ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pub.pem
2933
echo "- Importing ietf-keystore stock key configuration..."
3034
$SYSREPOCFG -d startup -i ${STOCK_KEY_CONFIG} ietf-keystore
31-
else
32-
echo "- Warning: Cannot read the SSH hostkey at /etc/ssh/ssh_host_rsa_key, skipping."
3335
fi

server/CMakeLists.txt

100644100755
Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@ if(NOT UNIX)
1313
endif()
1414

1515
# set version
16-
set(NP2SRV_VERSION 0.5.31)
16+
set(NP2SRV_VERSION 0.6.15)
1717

1818
# set default build type if not specified by user
1919
if(NOT CMAKE_BUILD_TYPE)
2020
set(CMAKE_BUILD_TYPE debug)
2121
endif()
2222

23-
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra")
23+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -std=gnu11")
2424
set(CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG")
2525
set(CMAKE_C_FLAGS_DEBUG "-g -O0 -DDEBUG")
2626

@@ -36,6 +36,11 @@ option(ENABLE_CONFIGURATION "Enable server configuration" ON)
3636
set(THREAD_COUNT 5 CACHE STRING "Number of threads accepting new sessions and handling requests")
3737
set(DEFAULT_HOST_KEY "/etc/ssh/ssh_host_rsa_key" CACHE STRING "Default server host key (used only if configuration is disabled)")
3838

39+
option(ENABLE_LY_CTX_INFO_CACHE "Enable caching the ly_ctx_info() result; reduces processing at the cost of increased memory usage." ON)
40+
if(ENABLE_LY_CTX_INFO_CACHE)
41+
set(NP2SRV_ENABLED_LY_CTX_INFO_CACHE 1)
42+
endif()
43+
3944
# set prefix for the PID file
4045
if (NOT PIDFILE_PREFIX)
4146
set(PIDFILE_PREFIX "/var/run")

server/KNOWNISSUES.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,11 @@ pthread_rwlockattr_setkind_np() and the number of worker threads is increased
66
(via cmake THREAD_COUNT variable), the thread processing the modules changes in
77
sysrepo (module install/uninstall or feature changes) can starve by waiting
88
for lock to wite changes into the netopeer's context.
9+
10+
XPath filter limitations
11+
------------------------
12+
13+
Correct filter result is guaranteed only when all the filtered nodes
14+
are only from one YANG schema and no unions are used. Otherwise,
15+
the <get> or <get-config> may finish with an error or possibly
16+
less data than would be correct.

server/common.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ struct np2srv {
4949
pthread_t workers[NP2SRV_THREAD_COUNT]; /**< worker threads handling sessions */
5050

5151
struct ly_ctx *ly_ctx; /**< libyang's context */
52+
#ifdef NP2SRV_ENABLED_LY_CTX_INFO_CACHE
53+
uint16_t cached_ly_ctx_module_set_id; /**< module-set-id at the time ly_ctx_info was last cached */
54+
struct lyd_node *ly_ctx_info_cache; /**< a cache of calling ly_ctx_info on the ly_ctx */
55+
#endif
5256
pthread_rwlock_t ly_ctx_lock; /**< libyang's context rwlock */
5357
};
5458
extern struct np2srv np2srv;

server/config.h.in

100644100755
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,8 @@
5252
*/
5353
#define NP2SRV_SR_LOCKED_RETRIES 3
5454

55+
/** @brief Enable caching the ly_ctx_info() result
56+
*/
57+
#cmakedefine NP2SRV_ENABLED_LY_CTX_INFO_CACHE
58+
5559
#endif /* NP2SRV_CONFIG_H_ */

server/ietf_keystore.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,57 @@ np_server_cert_clb(const char *name, void *UNUSED(user_data), char **UNUSED(cert
101101
return 0;
102102
}
103103

104+
int
105+
np_server_cert_chain_clb(const char *name, void *UNUSED(user_data), char ***UNUSED(cert_paths), int *UNUSED(cert_path_count),
106+
char ***cert_data, int *cert_data_count)
107+
{
108+
int ret;
109+
char *path;
110+
sr_val_t *sr_certs;
111+
size_t sr_cert_count, i, used_count;
112+
113+
ret = asprintf(&path, "/ietf-keystore:keystore/private-keys/private-key/certificate-chains/"
114+
"certificate-chain[name='%s']/certificate", name);
115+
if (ret == -1) {
116+
EMEM;
117+
return 1;
118+
}
119+
120+
if (np2srv.sr_sess.ds != SR_DS_RUNNING) {
121+
if (np2srv_sr_session_switch_ds(np2srv.sr_sess.srs, SR_DS_RUNNING, NULL)) {
122+
free(path);
123+
return 1;
124+
}
125+
np2srv.sr_sess.ds = SR_DS_RUNNING;
126+
}
127+
128+
/* Refresh the session to prevent sysrepo returning cached data */
129+
if (np2srv_sr_session_refresh(np2srv.sr_sess.srs, NULL)) {
130+
ERR("%s:%d Failed session refresh", __func__, __LINE__);
131+
free(path);
132+
return 1;
133+
}
134+
135+
if (np2srv_sr_get_items(np2srv.sr_sess.srs, path, &sr_certs, &sr_cert_count, NULL)) {
136+
free(path);
137+
return 1;
138+
}
139+
free(path);
140+
141+
/* Ignore the first cert since it's already loaded */
142+
if (sr_cert_count > 1) {
143+
used_count = sr_cert_count - 1;
144+
*cert_data = calloc(used_count, sizeof **cert_data);
145+
for (i = 0; i < used_count; ++i) {
146+
(*cert_data)[i] = strdup(sr_certs[i + 1].data.binary_val);
147+
}
148+
*cert_data_count = used_count;
149+
}
150+
151+
sr_free_values(sr_certs, sr_cert_count);
152+
return 0;
153+
}
154+
104155
int
105156
np_trusted_cert_list_clb(const char *name, void *UNUSED(user_data), char ***UNUSED(cert_paths), int *UNUSED(cert_path_count),
106157
char ***cert_data, int *cert_data_count)

server/ietf_keystore.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ int np_hostkey_clb(const char *name, void *user_data, char **privkey_path, char
2020
int np_server_cert_clb(const char *name, void *user_data, char **cert_path, char **cert_data, char **privkey_path,
2121
char **privkey_data, int *privkey_data_rsa);
2222

23+
int np_server_cert_chain_clb(const char *name, void *user_data, char ***cert_paths, int *cert_path_count,
24+
char ***cert_data, int *cert_data_count);
25+
2326
int np_trusted_cert_list_clb(const char *name, void *user_data, char ***cert_paths, int *cert_path_count,
2427
char ***cert_data, int *cert_data_count);
2528

server/ietf_netconf_server.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,6 +1241,7 @@ ietf_netconf_server_init(const struct lys_module *module)
12411241
nc_server_ssh_set_hostkey_clb(np_hostkey_clb, NULL, NULL);
12421242
#ifdef NC_ENABLED_TLS
12431243
nc_server_tls_set_server_cert_clb(np_server_cert_clb, NULL, NULL);
1244+
nc_server_tls_set_server_cert_chain_clb(np_server_cert_chain_clb, NULL, NULL);
12441245
nc_server_tls_set_trusted_cert_list_clb(np_trusted_cert_list_clb, NULL, NULL);
12451246
#endif
12461247

server/main.c

Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -222,18 +222,13 @@ signal_handler(int sig)
222222
}
223223
}
224224

225-
static int
226-
np2srv_module_assign_clbs(const struct lys_module *mod)
225+
static void
226+
np2srv_node_assign_clbs(struct lys_node *start)
227227
{
228228
struct lys_node *snode, *next;
229229

230-
if (!strcmp(mod->name, "ietf-netconf-monitoring") || !strcmp(mod->name, "ietf-netconf")) {
231-
/* skip it, use internal implementations from libnetconf2 */
232-
return EXIT_SUCCESS;
233-
}
234-
235230
/* set RPC and Notifications callbacks */
236-
LY_TREE_DFS_BEGIN(mod->data, next, snode) {
231+
LY_TREE_DFS_BEGIN(start, next, snode) {
237232
if (snode->nodetype & (LYS_RPC | LYS_ACTION)) {
238233
nc_set_rpc_callback(snode, op_generic);
239234
goto dfs_nextsibling;
@@ -262,6 +257,24 @@ np2srv_module_assign_clbs(const struct lys_module *mod)
262257
}
263258
}
264259

260+
}
261+
262+
static int
263+
np2srv_module_assign_clbs(const struct lys_module *mod)
264+
{
265+
if (!strcmp(mod->name, "ietf-netconf-monitoring") || !strcmp(mod->name, "ietf-netconf")) {
266+
/* skip it, use internal implementations from libnetconf2 */
267+
return EXIT_SUCCESS;
268+
}
269+
np2srv_node_assign_clbs(mod->data);
270+
for (uint8_t i = 0; i < mod->augment_size; ++i) {
271+
struct lys_node *target = mod->augment[i].target;
272+
if (!strcmp(target->module->name, "ietf-netconf-monitoring") || !strcmp(target->module->name, "ietf-netconf")) {
273+
continue;
274+
}
275+
np2srv_node_assign_clbs(target);
276+
}
277+
265278
return EXIT_SUCCESS;
266279
}
267280

@@ -323,13 +336,19 @@ np2srv_verify_clb(const struct nc_session *session)
323336
return 1;
324337
}
325338

326-
static char *
339+
static void free_with_user_data(void *data, void *user_data)
340+
{
341+
free(data);
342+
(void)user_data;
343+
}
344+
345+
static const char *
327346
np2srv_ly_import_clb(const char *mod_name, const char *mod_rev, const char *submod_name, const char *submod_rev,
328-
void *UNUSED(user_data), LYS_INFORMAT *format, void (**free_module_data)(void *model_data))
347+
void *UNUSED(user_data), LYS_INFORMAT *format, void (**free_module_data)(void *model_data, void *user_data))
329348
{
330349
char *data = NULL;
331350

332-
*free_module_data = free;
351+
*free_module_data = free_with_user_data;
333352
*format = LYS_YIN;
334353
if (submod_rev || (submod_name && !mod_name)) {
335354
np2srv_sr_get_submodule_schema(np2srv.sr_sess.srs, submod_name, submod_rev, SR_SCHEMA_YIN, &data, NULL);
@@ -421,6 +440,18 @@ np2srv_create_capab(const struct lys_module *mod)
421440
return cpb;
422441
}
423442

443+
#ifdef NP2SRV_ENABLED_LY_CTX_INFO_CACHE
444+
static void
445+
np2srv_update_ly_ctx_info_cache(uint16_t module_set_id)
446+
{
447+
if (np2srv.ly_ctx_info_cache) {
448+
lyd_free_withsiblings(np2srv.ly_ctx_info_cache);
449+
}
450+
np2srv.cached_ly_ctx_module_set_id = module_set_id;
451+
np2srv.ly_ctx_info_cache = ly_ctx_info(np2srv.ly_ctx);
452+
}
453+
#endif
454+
424455
static void
425456
np2srv_module_install_clb(const char *module_name, const char *revision, sr_module_state_t state, void *UNUSED(private_ctx))
426457
{
@@ -544,19 +575,30 @@ np2srv_feature_change_clb(const char *module_name, const char *feature_name, boo
544575
}
545576

546577
static int
547-
np2srv_state_data_clb(const char *xpath, sr_val_t **values, size_t *values_cnt, void *UNUSED(private_ctx))
578+
np2srv_state_data_clb(const char *xpath, sr_val_t **values, size_t *values_cnt, uint64_t UNUSED(request_id), void *UNUSED(private_ctx))
548579
{
549580
struct lyd_node *data = NULL, *node, *iter;
550581
struct ly_set *set = NULL;
551582
uint32_t i, j;
583+
bool should_free_data = true;
552584
int ret = SR_ERR_OK;
553585

554586
if (!strncmp(xpath, "/ietf-netconf-monitoring:", 25)) {
555587
data = ncm_get_data();
556588
} else if (!strncmp(xpath, "/nc-notifications:", 18)) {
557589
data = ntf_get_data();
558590
} else if (!strncmp(xpath, "/ietf-yang-library:", 19)) {
591+
#ifdef NP2SRV_ENABLED_LY_CTX_INFO_CACHE
592+
uint16_t module_set_id = ly_ctx_get_module_set_id(np2srv.ly_ctx);
593+
if (module_set_id != np2srv.cached_ly_ctx_module_set_id) {
594+
np2srv_update_ly_ctx_info_cache(module_set_id);
595+
}
596+
597+
data = np2srv.ly_ctx_info_cache;
598+
should_free_data = false;
599+
#else
559600
data = ly_ctx_info(np2srv.ly_ctx);
601+
#endif
560602
} else {
561603
ret = SR_ERR_OPERATION_FAILED;
562604
goto cleanup;
@@ -623,7 +665,9 @@ np2srv_state_data_clb(const char *xpath, sr_val_t **values, size_t *values_cnt,
623665

624666
cleanup:
625667
ly_set_free(set);
626-
lyd_free_withsiblings(data);
668+
if (should_free_data) {
669+
lyd_free_withsiblings(data);
670+
}
627671
if (ret != SR_ERR_OK) {
628672
sr_free_values(*values, *values_cnt);
629673
*values_cnt = 0;
@@ -1573,6 +1617,10 @@ main(int argc, char *argv[])
15731617
}
15741618
nc_ps_free(np2srv.nc_ps);
15751619

1620+
#ifdef NP2SRV_ENABLED_LY_CTX_INFO_CACHE
1621+
lyd_free_withsiblings(np2srv.ly_ctx_info_cache);
1622+
#endif
1623+
15761624
/* clears all the sessions also */
15771625
sr_disconnect(np2srv.sr_conn);
15781626

0 commit comments

Comments
 (0)