Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NETCONF TCP client #476

Merged
4 commits merged into from
Jun 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion sdk/cpp/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,9 @@ set(libydk_src
src/ietf_parser.cpp
src/leaf_data.cpp
src/logging_callback.cpp
src/netconf_client.cpp
src/netconf_client.cpp
src/netconf_ssh_client.cpp
src/netconf_tcp_client.cpp
src/netconf_model_provider.cpp
src/netconf_provider.cpp
src/netconf_service.cpp
Expand Down Expand Up @@ -195,6 +197,7 @@ set(libydk_install_headers
src/logging_callback.hpp
src/netconf_provider.hpp
src/network_topology.hpp
src/netconf_client.hpp
src/netconf_service.hpp
src/opendaylight_parser.hpp
src/opendaylight_provider.hpp
Expand Down
16 changes: 16 additions & 0 deletions sdk/cpp/core/src/ietf_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,18 @@ using namespace std;

namespace ydk
{

static const xmlNodePtr drop_hello_tag(xmlNodePtr root)
{
auto cur = root->xmlChildrenNode;
while (cur != NULL)
{
if ((!xmlStrcmp(cur->name, (const xmlChar *) "capabilities")))
return cur;
cur = cur->next;
}
return root;
}
//////////////////////////////////////////
//// IetfCapabilitiesXmlParser
//////////////////////////////////////////
Expand Down Expand Up @@ -59,6 +71,10 @@ vector<string> IetfCapabilitiesXmlParser::parse(const string & capabilities_buff
YLOG_INFO("Empty capabilities");
return {};
}

// drop hello
cur = drop_hello_tag(cur);

if (xmlStrcmp(cur->name, (const xmlChar *) "capabilities") != 0)
{
YLOG_INFO("Unexpected XML");
Expand Down
195 changes: 3 additions & 192 deletions sdk/cpp/core/src/netconf_client.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/// YANG Development Kit
// Copyright 2016 Cisco Systems. All rights reserved
// Copyright 2017 Cisco Systems. All rights reserved
//
////////////////////////////////////////////////////////////////
// Licensed to the Apache Software Foundation (ASF) under one
Expand All @@ -21,201 +21,12 @@
//
//////////////////////////////////////////////////////////////////


#include <iostream>
#include <sstream>
#include <stdio.h>

#include <libnetconf.h>
#include <libnetconf_ssh.h>

#include "netconf_client.hpp"
#include "types.hpp"
#include "logger.hpp"

using namespace std;
using namespace ydk;
typedef vector<string> StringVec;


namespace ydk
{

map<pair<string, string>, string> NetconfClient::password_lookup;

NetconfClient::NetconfClient(string username, string password,
string hostname, int port) :
username(username), hostname(hostname), port(port)
{
nc_verbosity(NC_VERB_DEBUG);
nc_callback_print(clb_print);
nc_callback_sshauth_password(clb_set_password);
nc_callback_sshauth_interactive(clb_set_interactive);
nc_callback_sshauth_passphrase(clb_set_passphrase);
nc_callback_ssh_host_authenticity_check(clb_ssh_host_authenticity_check);
nc_ssh_pref(NC_SSH_AUTH_PASSWORD, 100);
nc_session_transport(NC_TRANSPORT_SSH);

password_lookup.insert(make_pair(make_pair(username, hostname), password));
session=NULL;
}


int NetconfClient::connect()
{
session = nc_session_connect(hostname.c_str(), port, username.c_str(), NULL);
perform_session_check("Could not connect to " + hostname);
init_capabilities();
return EXIT_SUCCESS;
}

std::string NetconfClient::get_hostname_port()
{
ostringstream os;
os<<hostname<<":"<<port;
return os.str();
}

void NetconfClient::init_capabilities()
{
struct nc_cpblts* capabilities_list;
const char *cap;

capabilities_list = nc_session_get_cpblts(session);
nc_cpblts_iter_start(capabilities_list);

while ((cap = nc_cpblts_iter_next(capabilities_list)) != NULL)
{
capabilities.push_back(cap);
}
}

string NetconfClient::execute_payload(const string & payload)
{
perform_session_check("Could not execute payload. Not connected to " + hostname);

nc_reply *reply;
nc_rpc *rpc = build_rpc_request(payload);

NC_MSG_TYPE reply_type = nc_session_send_recv(session, rpc, &reply);
string reply_payload = process_rpc_reply(reply_type, reply);

nc_reply_free(reply);
nc_rpc_free(rpc);

return reply_payload;
}

NetconfClient::~NetconfClient()
{
nc_session_free(session);
}

nc_rpc* NetconfClient::build_rpc_request(const string & payload)
{
nc_rpc* rpc = nc_rpc_build(payload.c_str(), session);

if (rpc == NULL)
{
YLOG_ERROR("Could not build rpc payload: {}", payload );
throw(YCPPClientError{"Could not build payload"});
}
else if(NC_RPC_UNKNOWN==nc_rpc_get_type(rpc))
{
nc_rpc_free(rpc);
YLOG_ERROR("Rpc type is unknown");
throw(YCPPClientError{"Could not build payload"});
}
return rpc;
}

string NetconfClient::process_rpc_reply(int reply_type, const nc_reply* reply)
{
switch (reply_type)
{
case NC_MSG_REPLY:
return nc_reply_dump(reply);

default:
case NC_MSG_NONE:
case NC_MSG_UNKNOWN:
YLOG_ERROR("RPC error occurred");
throw(YCPPClientError{"RPC error occured"});
}
return {};
}

StringVec NetconfClient::get_capabilities()
{
return capabilities;
}

void NetconfClient::clb_print(NC_VERB_LEVEL level, const char* msg)
{
switch (level)
{
case NC_VERB_ERROR:
YLOG_ERROR("libnetconf ERROR: {}", msg);
break;
case NC_VERB_WARNING:
case NC_VERB_VERBOSE:
case NC_VERB_DEBUG:
YLOG_DEBUG("libnetconf TRACE: {}", msg);
break;
}
}

char* NetconfClient::clb_set_password(const char* user_name,
const char* host_name)
{
string password_string = password_lookup[make_pair(user_name, host_name)];
char* password_buffer = (char*) malloc(
sizeof(char) * (password_string.size() + 1));
snprintf(password_buffer, password_string.size() + 1, "%s",
password_string.c_str());

return password_buffer;
}

char* NetconfClient::clb_set_interactive(const char *name, const char *instruction, const char *prompt, int echo)
{
string password_string{};
for(const auto & entry : password_lookup)
{
password_string = entry.second;
break;
}
char* password_buffer = (char*) malloc(sizeof(char) * (password_string.size() + 1));
snprintf(password_buffer, password_string.size() + 1, "%s", password_string.c_str());

YLOG_DEBUG("looked up password for interactive: {}", password_buffer);
return password_buffer;
}

char* NetconfClient::clb_set_passphrase(const char *user_name, const char *host_name, const char *priv_key_file)
{
string password_string = password_lookup[make_pair(user_name, host_name)];
char* password_buffer = (char*) malloc(sizeof(char) * (password_string.size() + 1));
snprintf(password_buffer, password_string.size() + 1, "%s", password_string.c_str());

YLOG_DEBUG("looked up password for passphrase: {}", password_buffer);
return password_buffer;
}

int NetconfClient::clb_ssh_host_authenticity_check(const char *hostname,
ssh_session session)
{
return EXIT_SUCCESS;
}

void NetconfClient::perform_session_check(string message)
{
if (session == NULL)
{
YLOG_ERROR(message.c_str());
throw(YCPPClientError{message});
}
}

NetconfClient::NetconfClient() {}
NetconfClient::~NetconfClient() {}

}
99 changes: 29 additions & 70 deletions sdk/cpp/core/src/netconf_client.hpp
Original file line number Diff line number Diff line change
@@ -1,89 +1,48 @@
/* ----------------------------------------------------------------
Copyright 2016 Cisco Systems

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.
------------------------------------------------------------------*/
/// YANG Development Kit
// Copyright 2017 Cisco Systems. All rights reserved
//
////////////////////////////////////////////////////////////////
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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.
//
//////////////////////////////////////////////////////////////////

#ifndef _YDK_NETCONF_CLIENT_H_
#define _YDK_NETCONF_CLIENT_H_
#include <map>

#include <string>
#include <vector>

#include <libnetconf/netconf.h>

#include "errors.hpp"

struct nc_session;
typedef struct nc_msg nc_rpc;
typedef struct nc_msg nc_reply;
typedef struct ssh_session_struct* ssh_session;

typedef struct capabilities {
capabilities(std::vector<std::string> cas){caps=cas;}

std::vector<std::string> caps;
} capabilities;

namespace ydk
{

class NetconfClient
{

public:
static std::map<std::pair<std::string, std::string>, std::string> password_lookup;
NetconfClient();
virtual ~NetconfClient();

public:
NetconfClient(std::string username, std::string password,
std::string server_ip, int port);

~NetconfClient();

int connect();
std::string execute_payload(const std::string & payload);
std::vector<std::string> get_capabilities();
std::string get_hostname_port();

private:

static void clb_print(NC_VERB_LEVEL level, const char* msg);
static void clb_error_print(const char* tag, const char* type,
const char* severity, const char* apptag, const char* path,
const char* message, const char* attribute, const char* element,
const char* ns, const char* sid);
static char* clb_set_password(const char* username, const char* hostname);
static char* clb_set_interactive(const char *name, const char *instruction, const char *prompt, int echo);
static char* clb_set_passphrase(const char *username, const char *hostname, const char *priv_key_file);
static int clb_ssh_host_authenticity_check(const char *hostname,
ssh_session session);

nc_rpc* build_rpc_request(const std::string & payload);
std::string process_rpc_reply(int reply_type, const nc_reply* reply);
void init_capabilities();
void perform_session_check(std::string message);

private:
struct nc_session *session;

std::string username;
std::string hostname;
int port;
std::vector<std::string> capabilities;
virtual int connect() = 0;
virtual std::string execute_payload(const std::string & payload) = 0;
virtual std::vector<std::string> get_capabilities() = 0;
virtual std::string get_hostname_port() = 0;
};



}

#endif /* _YDK_NETCONF_CLIENT_H_ */
Loading