Skip to content

Commit e466662

Browse files
committed
Merge branch 'devel'
2 parents febb6bb + 94244c7 commit e466662

13 files changed

Lines changed: 783 additions & 373 deletions

CMakeLists.txt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,15 @@ if(NOT CMAKE_BUILD_TYPE)
2424
set(CMAKE_BUILD_TYPE debug)
2525
endif()
2626

27-
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -fvisibility=hidden")
27+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -fvisibility=hidden -std=gnu11")
2828
set(CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG")
2929
set(CMAKE_C_FLAGS_PACKAGE "-g -O2 -DNDEBUG")
3030
set(CMAKE_C_FLAGS_DEBUG "-g -O0")
3131

3232
# set version
3333
set(LIBNETCONF2_MAJOR_VERSION 0)
34-
set(LIBNETCONF2_MINOR_VERSION 11)
35-
set(LIBNETCONF2_MICRO_VERSION 49)
34+
set(LIBNETCONF2_MINOR_VERSION 12)
35+
set(LIBNETCONF2_MICRO_VERSION 20)
3636
set(LIBNETCONF2_VERSION ${LIBNETCONF2_MAJOR_VERSION}.${LIBNETCONF2_MINOR_VERSION}.${LIBNETCONF2_MICRO_VERSION})
3737
set(LIBNETCONF2_SOVERSION ${LIBNETCONF2_MAJOR_VERSION}.${LIBNETCONF2_MINOR_VERSION})
3838

@@ -189,7 +189,11 @@ endif()
189189
if(ENABLE_SSH)
190190
find_package(LibSSH 0.7.0 REQUIRED)
191191
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNC_ENABLED_SSH")
192-
target_link_libraries(netconf2 "-L${LIBSSH_LIBRARY_DIR}" -lssh -lssh_threads -lcrypt)
192+
if(LibSSH_VERSION VERSION_LESS 0.8.0)
193+
target_link_libraries(netconf2 "-L${LIBSSH_LIBRARY_DIR}" -lssh -lssh_threads -lcrypt)
194+
else()
195+
target_link_libraries(netconf2 "-L${LIBSSH_LIBRARY_DIR}" -lssh -lcrypt)
196+
endif()
193197
include_directories(${LIBSSH_INCLUDE_DIRS})
194198
endif()
195199

python/netconf.c

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ PyObject *libnetconf2ReplyError;
2727
/* syslog usage flag */
2828
static int syslogEnabled = 0;
2929

30+
/* libyang schema callback */
31+
static PyObject *schemaCallback = NULL;
32+
static void *schemaCallbackData = NULL;
33+
3034
static void
3135
clb_print(NC_VERB_LEVEL level, const char* msg)
3236
{
@@ -123,6 +127,68 @@ setSearchpath(PyObject *self, PyObject *args, PyObject *keywds)
123127
Py_RETURN_NONE;
124128
}
125129

130+
char *
131+
schemaCallbackWrapper(const char *mod_name, const char *mod_rev, const char *submod_name, const char *sub_rev,
132+
void *user_data, LYS_INFORMAT *format, void (**free_module_data)(void *model_data))
133+
{
134+
PyObject *arglist, *result, *data = NULL;
135+
char *str = NULL;
136+
137+
arglist = Py_BuildValue("(ssssO)", mod_name, mod_rev, submod_name, sub_rev, schemaCallbackData ? schemaCallbackData : Py_None);
138+
if (!arglist) {
139+
PyErr_Print();
140+
return NULL;
141+
}
142+
result = PyObject_CallObject(schemaCallback, arglist);
143+
Py_DECREF(arglist);
144+
145+
if (result) {
146+
if (!PyArg_ParseTuple(result, "iU", format, &data)) {
147+
Py_DECREF(result);
148+
return NULL;
149+
}
150+
Py_DECREF(result);
151+
*free_module_data = free;
152+
str = strdup(PyUnicode_AsUTF8(data));
153+
Py_DECREF(data);
154+
}
155+
156+
return str;
157+
}
158+
159+
static PyObject *
160+
setSchemaCallback(PyObject *self, PyObject *args, PyObject *keywds)
161+
{
162+
PyObject *clb = NULL, *data = NULL;
163+
static char *kwlist[] = {"func", "priv", NULL};
164+
165+
if (!PyArg_ParseTupleAndKeywords(args, keywds, "O|O:setSchemaCallback", kwlist, &clb, &data)) {
166+
return NULL;
167+
}
168+
169+
if (!clb || clb == Py_None) {
170+
Py_XDECREF(schemaCallback);
171+
Py_XDECREF(schemaCallbackData);
172+
data = NULL;
173+
} else if (!PyCallable_Check(clb)) {
174+
PyErr_SetString(PyExc_TypeError, "The callback must be a function.");
175+
return NULL;
176+
} else {
177+
Py_XDECREF(schemaCallback);
178+
Py_XDECREF(schemaCallbackData);
179+
180+
Py_INCREF(clb);
181+
if (data) {
182+
Py_INCREF(data);
183+
}
184+
}
185+
nc_client_set_schema_callback(schemaCallbackWrapper, NULL);
186+
schemaCallback = clb;
187+
schemaCallbackData = data;
188+
189+
Py_RETURN_NONE;
190+
}
191+
126192
static PyMethodDef netconf2Methods[] = {
127193
{"setVerbosity", (PyCFunction)setVerbosity, METH_VARARGS | METH_KEYWORDS,
128194
"setVerbosity(level)\n--\n\n"
@@ -150,6 +216,11 @@ static PyMethodDef netconf2Methods[] = {
150216
":param path: Search directory.\n"
151217
":type path: string\n"
152218
":returns: None\n"},
219+
{"setSchemaCallback", (PyCFunction)setSchemaCallback, METH_VARARGS | METH_KEYWORDS,
220+
"Set schema search callaback.\n\n"
221+
"setSchemaCallback(func, priv=None)\n"
222+
"with func(str mod_name, str mod_rev, str submod_name, str submod_rev, priv)\n"
223+
"callback returns tuple of format (e.g. LYS_IN_YANG) and string of the schema content.\n"},
153224
{NULL, NULL, 0, NULL}
154225
};
155226

python/session.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,6 @@ auth_interactive_pyclb(const char *auth_name, const char *instruction, const cha
159159
}
160160

161161
return password;
162-
163162
}
164163

165164
char *
@@ -277,6 +276,10 @@ ncSessionInit(ncSessionObject *self, PyObject *args, PyObject *kwds)
277276
return -1;
278277
}
279278

279+
if (PyErr_Occurred()) {
280+
PyErr_PrintEx(0);
281+
}
282+
280283
/* get the internally created context for this session */
281284
self->ctx = nc_session_get_ctx(session);
282285

src/io.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ nc_read_until(struct nc_session *session, const char *endtag, size_t limit, uint
226226
if ((count + (len - matched)) >= size) {
227227
/* get more memory */
228228
size = size + BUFFERSIZE;
229-
chunk = realloc(chunk, (size + 1) * sizeof *chunk);
229+
chunk = nc_realloc(chunk, (size + 1) * sizeof *chunk);
230230
if (!chunk) {
231231
ERRMEM;
232232
return -1;
@@ -357,7 +357,7 @@ nc_read_msg_io(struct nc_session *session, int io_timeout, struct lyxml_elem **d
357357
}
358358

359359
/* realloc message buffer, remember to count terminating null byte */
360-
msg = realloc(msg, len + chunk_len + 1);
360+
msg = nc_realloc(msg, len + chunk_len + 1);
361361
if (!msg) {
362362
ERRMEM;
363363
ret = NC_MSG_ERROR;
@@ -420,6 +420,12 @@ nc_read_msg_io(struct nc_session *session, int io_timeout, struct lyxml_elem **d
420420
/* NETCONF version 1.1 defines sending error reply from the server (RFC 6241 sec. 3) */
421421
reply = nc_server_reply_err(nc_err(NC_ERR_MALFORMED_MSG));
422422

423+
if (io_locked) {
424+
/* nc_write_msg_io locks and unlocks the lock by itself */
425+
nc_session_io_unlock(session, __func__);
426+
io_locked = 0;
427+
}
428+
423429
if (nc_write_msg_io(session, io_timeout, NC_MSG_REPLY, NULL, reply) != NC_MSG_REPLY) {
424430
ERR("Session %u: unable to send a \"Malformed message\" error reply, terminating session.", session->id);
425431
if (session->status != NC_STATUS_INVALID) {

src/libnetconf.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,9 @@
394394
* So, after starting listening on an endpoint you need to set the server
395395
* certificate (nc_server_tls_endpt_set_server_cert()). Its actual content
396396
* together with the matching private key will be loaded using a callback
397-
* from nc_server_tls_set_server_cert_clb().
397+
* from nc_server_tls_set_server_cert_clb(). Additional certificates needed
398+
* for the client to verify the server's certificate chain can be loaded using
399+
* a callback from nc_server_tls_set_server_cert_chain_clb().
398400
*
399401
* To accept client certificates, they must first be considered trusted,
400402
* which you have three ways of achieving. You can add each of their Certificate Authority
@@ -428,6 +430,7 @@
428430
* - nc_server_tls_endpt_get_ctn()
429431
*
430432
* - nc_server_tls_set_server_cert_clb()
433+
* - nc_server_tls_set_server_cert_chain_clb()
431434
* - nc_server_tls_set_trusted_cert_list_clb()
432435
*
433436
* FD

src/messages_server.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#define NC_MESSAGES_SERVER_H_
1717

1818
#include <stdint.h>
19+
#include <libyang/libyang.h>
1920

2021
#include "netconf.h"
2122
#include "session.h"

src/session.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -933,9 +933,10 @@ nc_server_get_cpblts_version(struct ly_ctx *ctx, LYS_VERSION version)
933933
u = module_set_id = 0;
934934
while ((mod = ly_ctx_get_module_iter(ctx, &u))) {
935935
if (!strcmp(mod->name, "ietf-yang-library")) {
936-
/* ietf-yang-library is always part of the list, but it is specific since it is 1.1 schema */
937-
sprintf(str, "%s?%s%s&module-set-id=%u", mod->ns, mod->rev_size ? "revision=" : "",
938-
mod->rev_size ? mod->rev[0].date : "", ly_ctx_get_module_set_id(ctx));
936+
/* Add the yang-library NETCONF capability as defined in RFC 7950 5.6.4 */
937+
sprintf(str, "urn:ietf:params:netconf:capability:yang-library:1.0?%s%s&module-set-id=%u",
938+
mod->rev_size ? "revision=" : "", mod->rev_size ? mod->rev[0].date : "",
939+
ly_ctx_get_module_set_id(ctx));
939940
add_cpblt(ctx, str, &cpblts, &size, &count);
940941
continue;
941942
} else if (mod->type) {
@@ -967,7 +968,7 @@ nc_server_get_cpblts_version(struct ly_ctx *ctx, LYS_VERSION version)
967968
ERRINT;
968969
break;
969970
}
970-
if (i) {
971+
if (features_count) {
971972
strcat(str, ",");
972973
++str_len;
973974
}

0 commit comments

Comments
 (0)