X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=ntsimulator%2Fntsim-ng%2Futils%2Fnc_client.c;fp=ntsimulator%2Fntsim-ng%2Futils%2Fnc_client.c;h=f3cb997dd6440b5542265554a85702ce2f9c40d5;hb=f1d5c9198acde7a7ce296490087cad37e008f688;hp=0000000000000000000000000000000000000000;hpb=f2d8f1002fa93848c80a88e5658db4816cba3020;p=sim%2Fo1-interface.git diff --git a/ntsimulator/ntsim-ng/utils/nc_client.c b/ntsimulator/ntsim-ng/utils/nc_client.c new file mode 100644 index 0000000..f3cb997 --- /dev/null +++ b/ntsimulator/ntsim-ng/utils/nc_client.c @@ -0,0 +1,352 @@ +/************************************************************************* +* +* Copyright 2020 highstreet technologies GmbH and others +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +***************************************************************************/ + +#define _GNU_SOURCE + +#include "nc_client.h" +#include "utils/log_utils.h" +#include "utils/sys_utils.h" +#include +#include +#include + +#include "core/session.h" + +#include +#include +#include + +static char *nc_client_pass_cb(const char *username, const char *hostname, void *priv) { + nc_client_t *client = (nc_client_t *)priv; + return strdup(client->password); +} + +static int nc_client_auth_hostkey_check(const char *hostname, ssh_session session, void *priv) { + return 0; //auto-authorize +} + +nc_client_t *nc_client_ssh_connect(const char *host, uint16_t port, const char *username, const char *password) { + assert(host); + assert(port > 20); + assert(username); + assert(password); + + nc_client_t *client = (nc_client_t *)malloc(sizeof(nc_client_t)); + if(client == 0) { + return 0; + } + + client->edit_batch_root = 0; + + nc_client_init(); + + nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, 3); + nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, -1); + nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, -1); + + nc_client_ssh_set_username(username); + client->password = strdup(password); + if(client->password == 0) { + free(client); + } + + nc_client_ssh_set_auth_password_clb(nc_client_pass_cb, client); + nc_client_ssh_set_auth_hostkey_check_clb(nc_client_auth_hostkey_check, 0); + + client->session = nc_connect_ssh(host, port, 0); + if(client->session == 0) { + log_error("nc_connect_ssh failed"); + free(client->password); + free(client); + return 0; + } + + return client; +} + +int nc_client_disconnect(nc_client_t *client) { + assert(client); + + nc_session_free(client->session, 0); + free(client->password); + free(client); + + return NTS_ERR_OK; +} + +struct lyd_node *nc_client_send_rpc(nc_client_t *client, struct lyd_node *data, int timeout) { + assert(client); + assert(data); + + struct nc_rpc *rpc; + struct nc_reply *reply; + NC_MSG_TYPE send_ret; + NC_MSG_TYPE reply_ret; + uint64_t msg_id; + + char *xmldata = 0; + if(lyd_print_mem(&xmldata, data, LYD_XML, 0) != 0) { + log_error("lyd_print_mem failed"); + return 0; + } + + rpc = nc_rpc_act_generic_xml(xmldata, NC_PARAMTYPE_CONST); + if(rpc == 0) { + log_error("could not create rpc"); + free(xmldata); + return 0; + } + + msg_id = 0; + send_ret = nc_send_rpc(client->session, rpc, timeout, &msg_id); + if(send_ret != NC_MSG_RPC) { + log_error("could not send rpc"); + free(xmldata); + nc_rpc_free(rpc); + return 0; + } + + repeat_nc_recv_reply: + reply_ret = nc_recv_reply(client->session, rpc, msg_id, timeout, LYD_OPT_DESTRUCT | LYD_OPT_NOSIBLINGS, &reply); + if(reply_ret != NC_MSG_REPLY) { + if(reply_ret == NC_MSG_NOTIF) { + goto repeat_nc_recv_reply; + } + + log_error("could not get rpc reply"); + free(xmldata); + nc_rpc_free(rpc); + return 0; + } + + if(reply->type != NC_RPL_DATA) { + log_error("reply has no data"); + free(xmldata); + nc_rpc_free(rpc); + nc_reply_free(reply); + return 0; + } + + char *ret_data_xml = strdup(""); //libyang does not support having the parent RPC in XML + struct lyd_node *chd = 0; + LY_TREE_FOR(((struct nc_reply_data *)reply)->data->child, chd) { + char *temp_xml = 0; + if(lyd_print_mem(&temp_xml, chd, LYD_XML, 0) != 0) { + log_error("lyd_print_mem failed"); + free(ret_data_xml); + free(xmldata); + nc_rpc_free(rpc); + nc_reply_free(reply); + return 0; + } + + ret_data_xml = (char *)realloc(ret_data_xml, sizeof(char) * (strlen(ret_data_xml) + strlen(temp_xml) + 1)); + strcat(ret_data_xml, temp_xml); + free(temp_xml); + } + + free(xmldata); + nc_reply_free(reply); + nc_rpc_free(rpc); + + struct lyd_node *ret_data = lyd_parse_mem(session_context, ret_data_xml, LYD_XML, LYD_OPT_RPCREPLY | LYD_OPT_NOEXTDEPS, data, 0); + free(ret_data_xml); + return ret_data; +} + +struct lyd_node *nc_client_get_batch(nc_client_t *client, const char *xpath, int timeout) { + assert(client); + assert(xpath); + + struct nc_rpc *rpc; + struct nc_reply *reply; + NC_MSG_TYPE send_ret; + NC_MSG_TYPE reply_ret; + uint64_t msg_id; + + rpc = nc_rpc_get(xpath, NC_WD_UNKNOWN, NC_PARAMTYPE_CONST); + if(rpc == 0) { + log_error("could not create rpc"); + return 0; + } + + msg_id = 0; + send_ret = nc_send_rpc(client->session, rpc, timeout, &msg_id); + if(send_ret != NC_MSG_RPC) { + log_error("could not send rpc"); + nc_rpc_free(rpc); + return 0; + } + + repeat_nc_recv_reply: + reply_ret = 0; + reply_ret = nc_recv_reply(client->session, rpc, msg_id, timeout, LYD_OPT_DESTRUCT | LYD_OPT_NOSIBLINGS, &reply); + if(reply_ret != NC_MSG_REPLY) { + if(reply_ret == NC_MSG_NOTIF) { + goto repeat_nc_recv_reply; + } + + log_error("could not get rpc reply"); + nc_rpc_free(rpc); + return 0; + } + + if(reply->type != NC_RPL_DATA) { + log_error("reply has no data"); + nc_rpc_free(rpc); + nc_reply_free(reply); + return 0; + } + + char *ret_data_xml = 0; + if(lyd_print_mem(&ret_data_xml, ((struct nc_reply_data *)reply)->data, LYD_XML, 0) != 0) { + log_error("lyd_print_mem failed"); + nc_reply_free(reply); + nc_rpc_free(rpc); + return 0; + } + + nc_reply_free(reply); + nc_rpc_free(rpc); + + struct lyd_node *ret_data = lyd_parse_mem(session_context, ret_data_xml, LYD_XML, LYD_OPT_DATA | LYD_OPT_NOSIBLINGS); + free(ret_data_xml); + return ret_data; +} + +int nc_client_edit_batch(nc_client_t *client, struct lyd_node *data, int timeout) { + assert(client); + assert(data); + + struct nc_rpc *rpc; + struct nc_reply *reply; + NC_MSG_TYPE send_ret; + NC_MSG_TYPE reply_ret; + uint64_t msg_id; + + char *content = 0; + int rc = lyd_print_mem(&content, data, LYD_XML, 0); + if(rc != 0) { + log_error("lyd_print_mem failed"); + return NTS_ERR_FAILED; + } + + rpc = nc_rpc_edit(NC_DATASTORE_RUNNING, NC_RPC_EDIT_DFLTOP_MERGE, NC_RPC_EDIT_TESTOPT_SET, NC_RPC_EDIT_ERROPT_STOP, content, NC_PARAMTYPE_CONST); + if(rpc == 0) { + log_error("could not create rpc"); + free(content); + return NTS_ERR_FAILED; + } + + msg_id = 0; + send_ret = nc_send_rpc(client->session, rpc, timeout, &msg_id); + if(send_ret != NC_MSG_RPC) { + log_error("could not send rpc"); + free(content); + nc_rpc_free(rpc); + return NTS_ERR_FAILED; + } + + reply_ret = nc_recv_reply(client->session, rpc, msg_id, timeout, LYD_OPT_DESTRUCT | LYD_OPT_NOSIBLINGS, &reply); + if((reply_ret != NC_MSG_REPLY) || (reply->type != NC_RPL_OK)) { + log_error("could not get rpc reply"); + + free(content); + nc_rpc_free(rpc); + return NTS_ERR_FAILED; + } + + free(content); + nc_reply_free(reply); + nc_rpc_free(rpc); + + return NTS_ERR_OK; +} + +int nc_client_set_item_str(nc_client_t *client, const char *xpath, const char *value) { + assert(client); + assert(xpath); + assert(value); + + if(client->edit_batch_root) { + struct lyd_node *n = lyd_new_path(client->edit_batch_root, 0, xpath, (void*)value, LYD_ANYDATA_CONSTSTRING, 0); + if(n == 0) { + log_error("lyd_new_path error"); + return NTS_ERR_FAILED; + } + } + else { + client->edit_batch_root = lyd_new_path(0, session_context, xpath, (void*)value, LYD_ANYDATA_CONSTSTRING, 0); + if(client->edit_batch_root == 0) { + log_error("lyd_new_path error"); + return NTS_ERR_FAILED; + } + } + + return NTS_ERR_OK; +} + +int nc_client_edit_apply_changes(nc_client_t *client, int timeout) { + assert(client); + assert(client->edit_batch_root); + + int rc = nc_client_edit_batch(client, client->edit_batch_root, timeout); + lyd_free_withsiblings(client->edit_batch_root); + client->edit_batch_root = 0; + return rc; +} + +int lyd_utils_dup(sr_session_ctx_t *session, const char *xpath_s, const char *xpath_d, struct lyd_node **tree) { + assert(session); + assert(xpath_s); + assert(xpath_d); + assert(tree); + + if(*tree == 0) { + *tree = lyd_new_path(0, session_context, xpath_d, 0, LYD_ANYDATA_CONSTSTRING, 0); + if(*tree == 0) { + return NTS_ERR_FAILED; + } + } + + struct lyd_node *data_s = 0; + int rc = sr_get_data(session, xpath_s, 0, 0, 0, &data_s); + if(rc != SR_ERR_OK) { + log_error("could not get value for xPath=%s from the datastore\n", xpath_s); + lyd_free(*tree); + return NTS_ERR_FAILED; + } + + struct lyd_node *next = 0; + struct lyd_node *snode = 0; + LY_TREE_DFS_BEGIN(data_s, next, snode) { + char *xpath_c = lyd_path(snode); + if((snode->schema->nodetype == LYS_LEAF) || (snode->schema->nodetype == LYS_LEAFLIST)) { + const char *value = ((struct lyd_node_leaf_list*)snode)->value_str; + char *new_xpath = str_replace(xpath_c, xpath_s, xpath_d); + + ly_log_options(0); + lyd_new_path(*tree, 0, new_xpath, (void*)value, LYD_ANYDATA_CONSTSTRING, 0); + free(xpath_c); + free(new_xpath); + } + LY_TREE_DFS_END(data_s, next, snode); + } + + lyd_free(data_s); + return NTS_ERR_OK; +}