Skip to content

Commit f3d40c7

Browse files
committed
session BUGFIX store client capabilities as well
1 parent 01a5db6 commit f3d40c7

6 files changed

Lines changed: 81 additions & 76 deletions

File tree

src/session.c

Lines changed: 51 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* @brief libnetconf2 - general session functions
55
*
66
* @copyright
7-
* Copyright (c) 2015 - 2023 CESNET, z.s.p.o.
7+
* Copyright (c) 2015 - 2026 CESNET, z.s.p.o.
88
*
99
* This source code is licensed under BSD 3-Clause License (the "License").
1010
* You may not use this file except in compliance with the License.
@@ -663,6 +663,31 @@ nc_session_get_ctx(const struct nc_session *session)
663663
return session->ctx;
664664
}
665665

666+
API const char * const *
667+
nc_session_get_cpblts(const struct nc_session *session)
668+
{
669+
NC_CHECK_ARG_RET(session, session, NULL);
670+
671+
return (const char * const *)session->cpblts;
672+
}
673+
674+
API const char *
675+
nc_session_cpblt(const struct nc_session *session, const char *capab)
676+
{
677+
int i, len;
678+
679+
NC_CHECK_ARG_RET(session, session, capab, NULL);
680+
681+
len = strlen(capab);
682+
for (i = 0; session->cpblts[i]; ++i) {
683+
if (!strncmp(session->cpblts[i], capab, len)) {
684+
return session->cpblts[i];
685+
}
686+
}
687+
688+
return NULL;
689+
}
690+
666691
API void
667692
nc_session_set_data(struct nc_session *session, void *data)
668693
{
@@ -1106,15 +1131,11 @@ nc_session_free(struct nc_session *session, void (*data_free)(void *))
11061131
free(session->username);
11071132
free(session->host);
11081133
free(session->path);
1109-
1110-
if (session->side == NC_CLIENT) {
1111-
/* list of server's capabilities */
1112-
if (session->opts.client.cpblts) {
1113-
for (i = 0; session->opts.client.cpblts[i]; i++) {
1114-
free(session->opts.client.cpblts[i]);
1115-
}
1116-
free(session->opts.client.cpblts);
1134+
if (session->cpblts) {
1135+
for (i = 0; session->cpblts[i]; i++) {
1136+
free(session->cpblts[i]);
11171137
}
1138+
free(session->cpblts);
11181139
}
11191140

11201141
if (session->data && data_free) {
@@ -1440,24 +1461,30 @@ nc_server_get_cpblts(const struct ly_ctx *ctx)
14401461
return _nc_server_get_cpblts_version(ctx, LYS_VERSION_UNDEF, 0);
14411462
}
14421463

1464+
/**
1465+
* @brief Parse received capabilities.
1466+
*
1467+
* @param[in] capabilities Opaque capability nodes.
1468+
* @param[out] list List of parsed capabilities terminated by NULL.
1469+
* @return NETCONF version;
1470+
* @return -1 on error.
1471+
*/
14431472
static int
1444-
parse_cpblts(struct lyd_node *capabilities, char ***list)
1473+
nc_parse_cpblts(struct lyd_node *capabilities, char ***list)
14451474
{
14461475
struct lyd_node *iter;
14471476
struct lyd_node_opaq *cpblt;
14481477
int ver = -1, i = 0;
14491478
const char *cpb_start, *cpb_end;
14501479

1451-
if (list) {
1452-
/* get the storage for server's capabilities */
1453-
LY_LIST_FOR(lyd_child(capabilities), iter) {
1454-
i++;
1455-
}
1456-
/* last item remains NULL */
1457-
*list = calloc(i + 1, sizeof **list);
1458-
NC_CHECK_ERRMEM_RET(!*list, -1);
1459-
i = 0;
1480+
/* get the storage for capabilities */
1481+
LY_LIST_FOR(lyd_child(capabilities), iter) {
1482+
i++;
14601483
}
1484+
/* last item remains NULL */
1485+
*list = calloc(i + 1, sizeof **list);
1486+
NC_CHECK_ERRMEM_RET(!*list, -1);
1487+
i = 0;
14611488

14621489
LY_LIST_FOR(lyd_child(capabilities), iter) {
14631490
cpblt = (struct lyd_node_opaq *)iter;
@@ -1483,11 +1510,9 @@ parse_cpblts(struct lyd_node *capabilities, char ***list)
14831510
}
14841511

14851512
/* store capabilities */
1486-
if (list) {
1487-
(*list)[i] = strndup(cpb_start, cpb_end - cpb_start);
1488-
NC_CHECK_ERRMEM_RET(!(*list)[i], -1);
1489-
i++;
1490-
}
1513+
(*list)[i] = strndup(cpb_start, cpb_end - cpb_start);
1514+
NC_CHECK_ERRMEM_RET(!(*list)[i], -1);
1515+
i++;
14911516
}
14921517

14931518
if (ver == -1) {
@@ -1644,7 +1669,7 @@ nc_client_recv_hello_io(struct nc_session *session)
16441669
}
16451670
flag = 1;
16461671

1647-
if ((ver = parse_cpblts(&node->node, &session->opts.client.cpblts)) < 0) {
1672+
if ((ver = nc_parse_cpblts(&node->node, &session->cpblts)) < 0) {
16481673
rc = NC_MSG_ERROR;
16491674
goto cleanup;
16501675
}
@@ -1723,7 +1748,7 @@ nc_server_recv_hello_io(struct nc_session *session)
17231748
}
17241749
flag = 1;
17251750

1726-
if ((ver = parse_cpblts(&node->node, NULL)) < 0) {
1751+
if ((ver = nc_parse_cpblts(&node->node, &session->cpblts)) < 0) {
17271752
rc = NC_MSG_BAD_HELLO;
17281753
goto cleanup;
17291754
}

src/session.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,23 @@ const char *nc_session_get_path(const struct nc_session *session);
217217
*/
218218
const struct ly_ctx *nc_session_get_ctx(const struct nc_session *session);
219219

220+
/**
221+
* @brief Get session capabilities.
222+
*
223+
* @param[in] session Session to get the information from.
224+
* @return NULL-terminated array of the @p session capabilities.
225+
*/
226+
const char * const *nc_session_get_cpblts(const struct nc_session *session);
227+
228+
/**
229+
* @brief Check capability presence in a session.
230+
*
231+
* @param[in] session Session to check.
232+
* @param[in] capab Capability to look for, capability with any additional suffix will match.
233+
* @return Matching capability, NULL if none found.
234+
*/
235+
const char *nc_session_cpblt(const struct nc_session *session, const char *capab);
236+
220237
/**
221238
* @brief Assign arbitrary data to a session.
222239
*

src/session_client.c

Lines changed: 7 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,7 +1217,7 @@ nc_ctx_check_and_fill(struct nc_session *session)
12171217
char *revision;
12181218
struct module_info *server_modules = NULL, *sm = NULL;
12191219

1220-
assert(session->opts.client.cpblts && session->ctx);
1220+
assert(session->cpblts && session->ctx);
12211221

12221222
if (client_opts.auto_context_fill_disabled) {
12231223
VRB(session, "Context of the new session is left only with the default YANG modules.");
@@ -1235,12 +1235,12 @@ nc_ctx_check_and_fill(struct nc_session *session)
12351235
ly_ctx_set_module_imp_clb(session->ctx, NULL, NULL);
12361236

12371237
/* check if get-schema and yang-library is supported */
1238-
for (i = 0; session->opts.client.cpblts[i]; ++i) {
1239-
if (!strncmp(session->opts.client.cpblts[i], "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring?", 52)) {
1238+
for (i = 0; session->cpblts[i]; ++i) {
1239+
if (!strncmp(session->cpblts[i], "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring?", 52)) {
12401240
get_schema_support = 1 + i;
1241-
} else if (!strncmp(session->opts.client.cpblts[i], "urn:ietf:params:netconf:capability:yang-library:", 48)) {
1241+
} else if (!strncmp(session->cpblts[i], "urn:ietf:params:netconf:capability:yang-library:", 48)) {
12421242
yanglib_support = 1 + i;
1243-
} else if (!strncmp(session->opts.client.cpblts[i], "urn:ietf:params:netconf:capability:xpath:1.0", 44)) {
1243+
} else if (!strncmp(session->cpblts[i], "urn:ietf:params:netconf:capability:xpath:1.0", 44)) {
12441244
xpath_support = 1 + i;
12451245
}
12461246
/* NMDA is YANG 1.1 module, which is not present in the capabilities */
@@ -1250,7 +1250,7 @@ nc_ctx_check_and_fill(struct nc_session *session)
12501250
VRB(session, "Capability for XPath filter support%s found.", xpath_support ? "" : " not");
12511251

12521252
/* get information about server's modules from capabilities list until we will have yang-library */
1253-
if (build_module_info_cpblts(session->opts.client.cpblts, &server_modules) || !server_modules) {
1253+
if (build_module_info_cpblts(session->cpblts, &server_modules) || !server_modules) {
12541254
ERR(session, "Unable to get server module information from the <hello>'s capabilities.");
12551255
goto cleanup;
12561256
}
@@ -1270,7 +1270,7 @@ nc_ctx_check_and_fill(struct nc_session *session)
12701270
/* get correct version of ietf-yang-library into context */
12711271
if (yanglib_support) {
12721272
/* use get-schema to get server's ietf-yang-library */
1273-
revision = strstr(session->opts.client.cpblts[yanglib_support - 1], "revision=");
1273+
revision = strstr(session->cpblts[yanglib_support - 1], "revision=");
12741274
if (!revision) {
12751275
WRN(session, "Loading NETCONF ietf-yang-library module failed, missing revision in NETCONF <hello> message.");
12761276
WRN(session, "Unable to automatically use <get-schema>.");
@@ -1944,31 +1944,6 @@ nc_accept_callhome(int timeout, struct ly_ctx *ctx, struct nc_session **session)
19441944

19451945
#endif /* NC_ENABLED_SSH_TLS */
19461946

1947-
API const char * const *
1948-
nc_session_get_cpblts(const struct nc_session *session)
1949-
{
1950-
NC_CHECK_ARG_RET(session, session, NULL);
1951-
1952-
return (const char * const *)session->opts.client.cpblts;
1953-
}
1954-
1955-
API const char *
1956-
nc_session_cpblt(const struct nc_session *session, const char *capab)
1957-
{
1958-
int i, len;
1959-
1960-
NC_CHECK_ARG_RET(session, session, capab, NULL);
1961-
1962-
len = strlen(capab);
1963-
for (i = 0; session->opts.client.cpblts[i]; ++i) {
1964-
if (!strncmp(session->opts.client.cpblts[i], capab, len)) {
1965-
return session->opts.client.cpblts[i];
1966-
}
1967-
}
1968-
1969-
return NULL;
1970-
}
1971-
19721947
API int
19731948
nc_session_ntf_thread_running(const struct nc_session *session)
19741949
{

src/session_client.h

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -489,23 +489,6 @@ struct nc_session *nc_connect_tls(const char *host, uint16_t port, struct ly_ctx
489489
* @{
490490
*/
491491

492-
/**
493-
* @brief Get session capabilities.
494-
*
495-
* @param[in] session Session to get the information from.
496-
* @return NULL-terminated array of the @p session capabilities.
497-
*/
498-
const char * const *nc_session_get_cpblts(const struct nc_session *session);
499-
500-
/**
501-
* @brief Check capability presence in a session.
502-
*
503-
* @param[in] session Session to check.
504-
* @param[in] capab Capability to look for, capability with any additional suffix will match.
505-
* @return Matching capability, NULL if none found.
506-
*/
507-
const char *nc_session_cpblt(const struct nc_session *session, const char *capab);
508-
509492
/**
510493
* @brief Check whether the session has a notification thread running.
511494
*

src/session_p.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -876,6 +876,7 @@ struct nc_session {
876876
/* NETCONF data */
877877
uint32_t id; /**< NETCONF session ID (session-id-type) */
878878
NC_PROT_VERSION version; /**< NETCONF protocol version */
879+
char **cpblts; /**< NETCONF capabilities received from the other end */
879880

880881
/* Transport implementation */
881882
NC_TRANSPORT_IMPL ti_type; /**< transport implementation type to select items from ti union */
@@ -936,7 +937,6 @@ struct nc_session {
936937
struct {
937938
/* client side only data */
938939
uint64_t msgid;
939-
char **cpblts; /**< list of server's capabilities on client side */
940940
pthread_mutex_t msgs_lock; /**< lock for the msgs buffer */
941941
struct nc_msg_cont *msgs; /**< queue for messages received of different type than expected */
942942
ATOMIC_T ntf_thread_count; /**< number of running notification threads */

tests/test_client_monitoring.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ server_thread(void *arg)
100100
struct ln2_test_ctx *test_ctx = arg;
101101
int fd;
102102
struct linger ling = {1, 0};
103+
const char *cpb;
103104

104105
ps = nc_ps_new();
105106
assert_non_null(ps);
@@ -111,6 +112,10 @@ server_thread(void *arg)
111112
msgtype = nc_accept(NC_ACCEPT_TIMEOUT, test_ctx->ctx, &session);
112113
assert_int_equal(msgtype, NC_MSG_HELLO);
113114

115+
/* just check capabilities function on the client */
116+
cpb = nc_session_cpblt(session, "urn:ietf:params:netconf:base:1.1");
117+
assert_non_null(cpb);
118+
114119
/* get the session's fd */
115120
fd = ssh_get_fd(session->ti.libssh.session);
116121
assert_int_not_equal(fd, -1);

0 commit comments

Comments
 (0)