1 /*************************************************************************
3 * Copyright 2020 highstreet technologies GmbH and others
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 ***************************************************************************/
20 #include "nc_config.h"
21 #include "utils/log_utils.h"
22 #include "utils/sys_utils.h"
23 #include "utils/http_client.h"
27 #include <libyang/libyang.h>
28 #include "core/session.h"
29 #include "core/framework.h"
31 #define GEN_KEY_SCRIPT "/home/netconf/.ssh/generate-ssh-keys.sh"
32 #define KS_CERT_NAME "melacon_server_cert"
33 #define SERVER_PRIVATE_KEY_PATH "/home/netconf/.ssh/melacon.server.key"
34 #define SERVER_PUBLIC_KEY_PATH "/home/netconf/.ssh/melacon.server.key.pub.pem"
35 #define SERVER_CERT_PATH "/home/netconf/.ssh/melacon.server.crt"
36 #define CLIENT_CERT_PATH "/home/netconf/.ssh/client.crt"
37 #define CA_CERT_PATH "/home/netconf/.ssh/ca.pem"
39 static int nc_config_netconf_port = STANDARD_NETCONF_PORT;
41 static int load_ssh_keys(sr_session_ctx_t *session);
42 static int load_trusted_certificates(sr_session_ctx_t *session);
43 static int remove_nacm(sr_session_ctx_t *session);
44 static int create_ssh_listen_endpoints(struct lyd_node *netconf_node, int ssh_connections);
45 static int create_tls_listen_endpoints(struct lyd_node *netconf_node, int tls_connections);
46 static int configure_endpoints_connections(sr_session_ctx_t *session);
48 int netconf_configure(void) {
51 nc_config_netconf_port = STANDARD_NETCONF_PORT;
53 sr_session_ctx_t *current_session;
54 rc = sr_session_start(session_connection, SR_DS_RUNNING, ¤t_session);
56 log_error("could not start session on running datastore");
57 return NTS_ERR_FAILED;
60 // generate and load private keys
61 log_message(1, "ietf-keystore startup datastore configuration..."); //checkAS e ok aici ?
62 rc = load_ssh_keys(current_session);
64 log_error("could not load SSH keys");
65 return NTS_ERR_FAILED;
67 log_message(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET);
69 // load trusted certificates
70 log_message(1, "ietf-truststore startup datastore configuration...");
71 rc = load_trusted_certificates(current_session);
73 log_error("could not load trusted certificates");
74 return NTS_ERR_FAILED;
76 log_message(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET);
79 log_message(1, "Removing NACM...");
80 rc = remove_nacm(current_session);
82 log_error("could not remove NACM");
83 return NTS_ERR_FAILED;
85 log_message(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET);
87 // configure SSH connections
88 log_message(1, "Configuring connection endpoints...");
89 rc = configure_endpoints_connections(current_session);
91 log_error("could not configure endpoint connections forNETCONF Server");
92 return NTS_ERR_FAILED;
94 log_message(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET);
96 rc = sr_session_stop(current_session);
98 log_error("could not configure stop current sysrepo session");
99 return NTS_ERR_FAILED;
105 static int load_ssh_keys(sr_session_ctx_t *session) {
110 struct lyd_node *rcl = 0;
112 rc = system(GEN_KEY_SCRIPT);
114 log_error("could not generate the SSH keys");
115 return NTS_ERR_FAILED;
118 struct lys_module *module;
119 module = (struct lys_module *)ly_ctx_get_module(session_context, "ietf-keystore", 0, 0);
121 log_error("could not get module %s from context", "ietf-keystore");
122 return NTS_ERR_FAILED;
125 struct lyd_node *keystore_node = 0;
126 keystore_node = lyd_new(NULL, module, "keystore");
127 if(keystore_node == 0) {
128 log_error("could not create a new lyd_node");
129 return NTS_ERR_FAILED;
132 sprintf(xpath, "/ietf-keystore:keystore/asymmetric-keys/asymmetric-key[name='%s']/algorithm", KS_KEY_NAME);
133 rcl = lyd_new_path(keystore_node, 0, xpath, "rsa2048", 0, LYD_PATH_OPT_NOPARENTRET);
135 log_error("could not created yang path");
136 return NTS_ERR_FAILED;
139 char *private_key = read_key(SERVER_PRIVATE_KEY_PATH);
140 if(private_key == 0) {
141 log_error("could not read the private key from path=%s", SERVER_PRIVATE_KEY_PATH);
142 return NTS_ERR_FAILED;
144 log_message(2, "Private Key that was built: \n%s\n", private_key);
146 sprintf(xpath, "/ietf-keystore:keystore/asymmetric-keys/asymmetric-key[name='%s']/private-key", KS_KEY_NAME);
147 rcl = lyd_new_path(keystore_node, 0, xpath, private_key, 0, LYD_PATH_OPT_NOPARENTRET);
149 log_error("could not created yang path");
150 return NTS_ERR_FAILED;
155 char *public_key = read_key(SERVER_PUBLIC_KEY_PATH);
156 if(public_key == 0) {
157 log_error("could not read the public key from path=%s", SERVER_PUBLIC_KEY_PATH);
158 return NTS_ERR_FAILED;
160 log_message(2, "Public Key that was built: \n%s\n", public_key);
162 sprintf(xpath, "/ietf-keystore:keystore/asymmetric-keys/asymmetric-key[name='%s']/public-key", KS_KEY_NAME);
163 rcl = lyd_new_path(keystore_node, 0, xpath, public_key, 0, LYD_PATH_OPT_NOPARENTRET);
165 log_error("could not created yang path");
166 return NTS_ERR_FAILED;
171 char *certificate = read_key(SERVER_CERT_PATH);
172 if(certificate == 0) {
173 log_error("could not read the certificate from path=%s", SERVER_CERT_PATH);
174 return NTS_ERR_FAILED;
176 log_message(2, "Certificate that was built: \n%s\n", certificate);
178 sprintf(xpath, "/ietf-keystore:keystore/asymmetric-keys/asymmetric-key[name='%s']/certificates/certificate[name='%s']/cert", KS_KEY_NAME, KS_CERT_NAME);
179 rcl = lyd_new_path(keystore_node, 0, xpath, certificate, 0, LYD_PATH_OPT_NOPARENTRET);
181 log_error("could not created yang path");
182 return NTS_ERR_FAILED;
187 rc = sr_edit_batch(session, keystore_node, "replace");
188 if(rc != SR_ERR_OK) {
189 log_error("could not edit batch on datastore");
190 return NTS_ERR_FAILED;
193 rc = sr_validate(session, "ietf-keystore", 0);
194 if(rc != SR_ERR_OK) {
195 struct ly_err_item *err = ly_err_first(session_context);
196 log_error("sr_validate issues on STARTUP: %s", err->msg);
200 rc = sr_apply_changes(session, 0, 0);
201 if(rc != SR_ERR_OK) {
202 log_error("could not apply changes on datastore");
203 return NTS_ERR_FAILED;
209 static int load_trusted_certificates(sr_session_ctx_t *session) {
213 struct lyd_node *rcl = 0;
215 struct lyd_node *trusted_certificate_node = 0;
216 struct lys_module *module;
217 module = (struct lys_module *)ly_ctx_get_module(session_context, "ietf-truststore", 0, 0);
219 log_error("could not get module %s from context", "ietf-truststore");
220 return NTS_ERR_FAILED;
223 trusted_certificate_node = lyd_new(NULL, module, "truststore");
224 if(trusted_certificate_node == 0) {
225 log_error("could not create a new lyd_node");
226 return NTS_ERR_FAILED;
231 sprintf(xpath, "/ietf-truststore:truststore/certificates[name='clientcerts']/certificate[name='clientcert']/cert");
232 char *client_cert = read_key(CLIENT_CERT_PATH);
233 rcl = lyd_new_path(trusted_certificate_node, 0, xpath, client_cert, 0, LYD_PATH_OPT_NOPARENTRET);
235 log_error("could not created yang path");
236 return NTS_ERR_FAILED;
240 sprintf(xpath, "/ietf-truststore:truststore/certificates[name='cacerts']/certificate[name='cacert']/cert");
241 char *ca_cert = read_key(CA_CERT_PATH);
242 rcl = lyd_new_path(trusted_certificate_node, 0, xpath, ca_cert, 0, LYD_PATH_OPT_NOPARENTRET);
244 log_error("could not created yang path");
245 return NTS_ERR_FAILED;
249 rc = sr_edit_batch(session, trusted_certificate_node, "replace");
250 if(rc != SR_ERR_OK) {
251 log_error("could not edit batch on datastore");
252 return NTS_ERR_FAILED;
255 rc = sr_validate(session, "ietf-truststore", 0);
256 if(rc != SR_ERR_OK) {
257 struct ly_err_item *err = ly_err_first(session_context);
258 log_error("sr_validate issues on STARTUP: %s", err->msg);
259 return NTS_ERR_FAILED;
262 rc = sr_apply_changes(session, 0, 0);
263 if(rc != SR_ERR_OK) {
264 log_error("could not apply changes on datastore");
265 return NTS_ERR_FAILED;
271 static int remove_nacm(sr_session_ctx_t *session) {
275 struct lyd_node *rcl = 0;
278 struct lys_module *module = 0;
279 module = (struct lys_module *) ly_ctx_get_module(session_context, "ietf-netconf-acm", 0, 0);
281 log_error("could not get module %s from context", "ietf-netconf-acm");
282 return NTS_ERR_FAILED;
285 struct lyd_node *nacm_node = 0;
286 nacm_node = lyd_new(NULL, module, "nacm");
288 log_error("could not create a new lyd_node");
289 return NTS_ERR_FAILED;
292 sprintf(xpath, "/ietf-netconf-acm:nacm/enable-nacm");
293 rcl = lyd_new_path(nacm_node, 0, xpath, "false", 0, LYD_PATH_OPT_NOPARENTRET);
295 log_error("could not created yang path");
296 return NTS_ERR_FAILED;
299 rc = sr_edit_batch(session, nacm_node, "replace");
300 if(rc != SR_ERR_OK) {
301 log_error("could not edit batch on datastore");
302 return NTS_ERR_FAILED;
305 rc = sr_validate(session, "ietf-netconf-acm", 0);
306 if(rc != SR_ERR_OK) {
307 struct ly_err_item *err = ly_err_first(session_context);
308 log_error("sr_validate issues on STARTUP: %s", err->msg);
309 return NTS_ERR_FAILED;
312 rc = sr_apply_changes(session, 0, 0);
313 if(rc != SR_ERR_OK) {
314 log_error("could not apply changes on datastore");
315 return NTS_ERR_FAILED;
321 static int create_ssh_listen_endpoints(struct lyd_node *netconf_node, int ssh_connections) {
322 assert(netconf_node);
326 struct lyd_node *rcl = 0;
329 if(framework_environment.ip_v6_enabled) {
330 sprintf(local_ip, "::");
333 sprintf(local_ip, "0.0.0.0");
336 char *public_ssh_key = read_key(SERVER_PUBLIC_SSH_KEY_PATH);
337 if(public_ssh_key == 0) {
338 log_error("could not read the public ssh key from file %s", SERVER_PUBLIC_SSH_KEY_PATH);
339 return NTS_ERR_FAILED;
342 char *ssh_key_string;
344 ssh_key_string = strtok(public_ssh_key, " ");
345 ssh_key_string = strtok(NULL, " ");
347 for(int i=0; i < ssh_connections; ++i) {
348 char endpoint_name[100];
349 sprintf(endpoint_name, "mng-ssh-%d", i);
351 sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/tcp-server-parameters/local-address", endpoint_name);
352 rcl = lyd_new_path(netconf_node, 0, xpath, local_ip, 0, LYD_PATH_OPT_NOPARENTRET);
354 log_error("could not created yang path");
355 return NTS_ERR_FAILED;
359 sprintf(local_port, "%d", nc_config_netconf_port++);
360 sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/tcp-server-parameters/local-port", endpoint_name);
361 rcl = lyd_new_path(netconf_node, 0, xpath, local_port, 0, LYD_PATH_OPT_NOPARENTRET);
363 log_error("could not created yang path");
364 return NTS_ERR_FAILED;
367 sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/tcp-server-parameters/keepalives/idle-time", endpoint_name);
368 rcl = lyd_new_path(netconf_node, 0, xpath, "1", 0, LYD_PATH_OPT_NOPARENTRET);
370 log_error("could not created yang path");
371 return NTS_ERR_FAILED;
374 sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/tcp-server-parameters/keepalives/max-probes", endpoint_name);
375 rcl = lyd_new_path(netconf_node, 0, xpath, "10", 0, LYD_PATH_OPT_NOPARENTRET);
377 log_error("could not created yang path");
378 return NTS_ERR_FAILED;
381 sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/tcp-server-parameters/keepalives/probe-interval", endpoint_name);
382 rcl = lyd_new_path(netconf_node, 0, xpath, "5", 0, LYD_PATH_OPT_NOPARENTRET);
384 log_error("could not created yang path");
385 return NTS_ERR_FAILED;
388 sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/ssh-server-parameters/server-identity/host-key[name='default-key']/public-key/keystore-reference", endpoint_name);
389 rcl = lyd_new_path(netconf_node, 0, xpath, KS_KEY_NAME, 0, LYD_PATH_OPT_NOPARENTRET);
391 log_error("could not created yang path");
392 return NTS_ERR_FAILED;
395 sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/ssh-server-parameters/client-authentication/supported-authentication-methods/publickey", endpoint_name);
396 rcl = lyd_new_path(netconf_node, 0, xpath, "", 0, LYD_PATH_OPT_NOPARENTRET);
398 log_error("could not created yang path");
399 return NTS_ERR_FAILED;
402 sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/ssh-server-parameters/client-authentication/supported-authentication-methods/passsword", endpoint_name);
403 rcl = lyd_new_path(netconf_node, 0, xpath, "", 0, LYD_PATH_OPT_NOPARENTRET);
405 log_error("could not created yang path");
406 return NTS_ERR_FAILED;
409 sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/ssh-server-parameters/client-authentication/supported-authentication-methods/other", endpoint_name);
410 rcl = lyd_new_path(netconf_node, 0, xpath, "interactive", 0, LYD_PATH_OPT_NOPARENTRET);
412 log_error("could not created yang path");
413 return NTS_ERR_FAILED;
416 sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/ssh-server-parameters/client-authentication/users/user[name='netconf']/authorized-key[name='%s']/algorithm", endpoint_name, KS_KEY_NAME);
417 rcl = lyd_new_path(netconf_node, 0, xpath, "ssh-rsa", 0, LYD_PATH_OPT_NOPARENTRET);
419 log_error("could not created yang path");
420 return NTS_ERR_FAILED;
423 sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/ssh-server-parameters/client-authentication/users/user[name='netconf']/authorized-key[name='%s']/key-data", endpoint_name, KS_KEY_NAME);
424 rcl = lyd_new_path(netconf_node, 0, xpath, ssh_key_string, 0, LYD_PATH_OPT_NOPARENTRET);
426 log_error("could not created yang path");
427 return NTS_ERR_FAILED;
431 free(public_ssh_key);
436 static int create_tls_listen_endpoints(struct lyd_node *netconf_node, int tls_connections) {
437 assert(netconf_node);
439 struct lyd_node *rcl = 0;
443 if(framework_environment.ip_v6_enabled) {
444 sprintf(local_ip, "::");
447 sprintf(local_ip, "0.0.0.0");
450 for(int i=0; i < tls_connections; ++i) {
451 char endpoint_name[100];
452 sprintf(endpoint_name, "mng-tls-%d", i);
454 sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tcp-server-parameters/local-address", endpoint_name);
455 rcl = lyd_new_path(netconf_node, 0, xpath, local_ip, 0, LYD_PATH_OPT_NOPARENTRET);
457 log_error("could not created yang path");
458 return NTS_ERR_FAILED;
462 sprintf(local_port, "%d", nc_config_netconf_port++);
463 sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tcp-server-parameters/local-port", endpoint_name);
464 rcl = lyd_new_path(netconf_node, 0, xpath, local_port, 0, LYD_PATH_OPT_NOPARENTRET);
466 log_error("could not created yang path");
467 return NTS_ERR_FAILED;
470 sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tcp-server-parameters/keepalives/idle-time", endpoint_name);
471 rcl = lyd_new_path(netconf_node, 0, xpath, "1", 0, LYD_PATH_OPT_NOPARENTRET);
473 log_error("could not created yang path");
474 return NTS_ERR_FAILED;
477 sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tcp-server-parameters/keepalives/max-probes", endpoint_name);
478 rcl = lyd_new_path(netconf_node, 0, xpath, "10", 0, LYD_PATH_OPT_NOPARENTRET);
480 log_error("could not created yang path");
481 return NTS_ERR_FAILED;
484 sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tcp-server-parameters/keepalives/probe-interval", endpoint_name);
485 rcl = lyd_new_path(netconf_node, 0, xpath, "5", 0, LYD_PATH_OPT_NOPARENTRET);
487 log_error("could not created yang path");
488 return NTS_ERR_FAILED;
491 sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/server-identity/keystore-reference/asymmetric-key", endpoint_name);
492 rcl = lyd_new_path(netconf_node, 0, xpath, KS_KEY_NAME, 0, LYD_PATH_OPT_NOPARENTRET);
494 log_error("could not created yang path");
495 return NTS_ERR_FAILED;
498 sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/server-identity/keystore-reference/certificate", endpoint_name);
499 rcl = lyd_new_path(netconf_node, 0, xpath, KS_CERT_NAME, 0, LYD_PATH_OPT_NOPARENTRET);
501 log_error("could not created yang path");
502 return NTS_ERR_FAILED;
505 sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/client-authentication/required", endpoint_name);
506 rcl = lyd_new_path(netconf_node, 0, xpath, "", 0, LYD_PATH_OPT_NOPARENTRET);
508 log_error("could not created yang path");
509 return NTS_ERR_FAILED;
512 sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/client-authentication/ca-certs", endpoint_name);
513 rcl = lyd_new_path(netconf_node, 0, xpath, "cacerts", 0, LYD_PATH_OPT_NOPARENTRET);
515 log_error("could not created yang path");
516 return NTS_ERR_FAILED;
519 sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/client-authentication/client-certs", endpoint_name);
520 rcl = lyd_new_path(netconf_node, 0, xpath, "clientcerts", 0, LYD_PATH_OPT_NOPARENTRET);
522 log_error("could not created yang path");
523 return NTS_ERR_FAILED;
526 sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/client-authentication/cert-maps/cert-to-name[id='1']/fingerprint", endpoint_name);
527 rcl = lyd_new_path(netconf_node, 0, xpath, "02:E9:38:1F:F6:8B:62:DE:0A:0B:C5:03:81:A8:03:49:A0:00:7F:8B:F3", 0, LYD_PATH_OPT_NOPARENTRET);
529 log_error("could not created yang path");
530 return NTS_ERR_FAILED;
533 sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/client-authentication/cert-maps/cert-to-name[id='1']/map-type", endpoint_name);
534 rcl = lyd_new_path(netconf_node, session_context, xpath, "ietf-x509-cert-to-name:specified", 0, LYD_PATH_OPT_NOPARENTRET);
536 log_error("could not created yang path");
537 return NTS_ERR_FAILED;
540 sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/client-authentication/cert-maps/cert-to-name[id='1']/name", endpoint_name);
541 rcl = lyd_new_path(netconf_node, 0, xpath, "netconf-tls", 0, LYD_PATH_OPT_NOPARENTRET);
543 log_error("could not created yang path");
544 return NTS_ERR_FAILED;
551 static int configure_endpoints_connections(sr_session_ctx_t *session) {
556 struct lys_module *module = 0;
557 module = (struct lys_module *)ly_ctx_get_module(session_context, "ietf-netconf-server", 0, 0);
559 log_error("could not get module %s from context", "ietf-netconf-server");
560 return NTS_ERR_FAILED;
564 struct lyd_node *netconf_node = 0;
565 netconf_node = lyd_new_path(NULL, session_context, "/ietf-netconf-server:netconf-server", 0, 0, 0);
566 if(netconf_node == 0) {
567 log_error("could not create a new lyd_node");
568 return NTS_ERR_FAILED;
571 // create the SSH endpoints in ietf-netconf-server
572 int ssh_connections = 0;
573 if(framework_arguments.manager) {
577 ssh_connections = framework_environment.ssh_connections;
580 if(ssh_connections == 0) {
581 log_error("ssh_connections must be at least 1");
582 return NTS_ERR_FAILED;
585 rc = create_ssh_listen_endpoints(netconf_node, ssh_connections);
586 if(rc != NTS_ERR_OK) {
587 log_error("could not create %d SSH Listen endpoints on the NETCONF Server", ssh_connections);
588 return NTS_ERR_FAILED;
591 // create the TLS endpoints in ietf-netconf-server
592 if(framework_arguments.manager == false) {
593 rc = create_tls_listen_endpoints(netconf_node, framework_environment.tls_connections);
594 if(rc != NTS_ERR_OK) {
595 log_error("could not create %d TLS Listen endpoints on the NETCONF Server", framework_environment.tls_connections);
596 return NTS_ERR_FAILED;
600 rc = sr_edit_batch(session, netconf_node, "replace");
601 if(rc != SR_ERR_OK) {
602 log_error("could not edit batch on datastore");
603 return NTS_ERR_FAILED;
606 rc = sr_validate(session, "ietf-netconf-server", 0);
607 if(rc != SR_ERR_OK) {
608 struct ly_err_item *err = ly_err_first(session_context);
609 log_error("sr_validate issues on STARTUP: %s", err->msg);
610 return NTS_ERR_FAILED;
613 rc = sr_apply_changes(session, 0, 0);
614 if(rc != SR_ERR_OK) {
615 log_error("could not apply changes on datastore");
616 return NTS_ERR_FAILED;