messages CHANGE split to 3 groups of functions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f0b504d..1077da4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -36,6 +36,8 @@
 	src/io.c
 	src/log.c
 	src/messages.c
+	src/messages_client.c
+	src/messages_server.c
 	src/session.c
 	src/session_client.c
 	src/session_server.c
@@ -61,7 +63,9 @@
 	src/session.h
 	src/session_client.h
 	src/session_server.h
-	src/messages.h)
+	src/messages.h
+	src/messages_client.h
+	src/messages_server.h)
 
 # libnetconf2 target
 add_library(netconf2 SHARED ${libsrc})
diff --git a/nc_client.h.in b/nc_client.h.in
index 5d95439..531798c 100644
--- a/nc_client.h.in
+++ b/nc_client.h.in
@@ -29,6 +29,7 @@
 #include <libnetconf2/netconf.h>
 #include <libnetconf2/log.h>
 #include <libnetconf2/messages.h>
+#include <libnetconf2/messages_client.h>
 #include <libnetconf2/session_client.h>
 
 #endif /* NC_CLIENT_H_ */
diff --git a/nc_server.h.in b/nc_server.h.in
index bc18da1..224e3f6 100644
--- a/nc_server.h.in
+++ b/nc_server.h.in
@@ -28,6 +28,8 @@
 
 #include <libnetconf2/netconf.h>
 #include <libnetconf2/log.h>
+#include <libnetconf2/messages.h>
+#include <libnetconf2/messages_server.h>
 #include <libnetconf2/session_server.h>
 
 #endif /* NC_SERVER_H_ */
diff --git a/src/messages.c b/src/messages.c
index 5cd4c0a..7e84e02 100644
--- a/src/messages.c
+++ b/src/messages.c
@@ -27,1070 +27,10 @@
 
 #include <libyang/libyang.h>
 
-#include "libnetconf.h"
+#include "config.h"
+#include "messages.h"
 #include "messages_p.h"
 
-const char *rpcedit_dfltop2str[] = {NULL, "merge", "replace", "none"};
-const char *rpcedit_testopt2str[] = {NULL, "test-then-set", "set", "test-only"};
-const char *rpcedit_erropt2str[] = {NULL, "stop-on-error", "continue-on-error", "rollback-on-error"};
-
-API NC_RPC_TYPE
-nc_rpc_get_type(const struct nc_rpc *rpc)
-{
-    return rpc->type;
-}
-
-API struct nc_rpc *
-nc_rpc_generic(const struct lyd_node *data, NC_PARAMTYPE paramtype)
-{
-    struct nc_rpc_generic *rpc;
-
-    if (data->next || (data->prev != data)) {
-        ERR("Generic RPC must have a single root node.");
-        return NULL;
-    }
-
-    rpc = malloc(sizeof *rpc);
-    if (!rpc) {
-        ERRMEM;
-        return NULL;
-    }
-
-    rpc->type = NC_RPC_GENERIC;
-    rpc->has_data = 1;
-    if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
-        rpc->content.data = lyd_dup(data, 1);
-    } else {
-        rpc->content.data = (struct lyd_node *)data;
-    }
-    rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
-
-    return (struct nc_rpc *)rpc;
-}
-
-API struct nc_rpc *
-nc_rpc_generic_xml(const char *xml_str, NC_PARAMTYPE paramtype)
-{
-    struct nc_rpc_generic *rpc;
-
-    rpc = malloc(sizeof *rpc);
-    if (!rpc) {
-        ERRMEM;
-        return NULL;
-    }
-
-    rpc->type = NC_RPC_GENERIC;
-    rpc->has_data = 0;
-    if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
-        rpc->content.xml_str = strdup(xml_str);
-    } else {
-        rpc->content.xml_str = (char *)xml_str;
-    }
-    rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
-
-    return (struct nc_rpc *)rpc;
-}
-
-API struct nc_rpc *
-nc_rpc_getconfig(NC_DATASTORE source, const char *filter, NC_WD_MODE wd_mode, NC_PARAMTYPE paramtype)
-{
-    struct nc_rpc_getconfig *rpc;
-
-    if (filter && (filter[0] != '<') && (filter[0] != '/') && !isalpha(filter[0])) {
-        ERR("Filter must either be an XML subtree or an XPath expression.");
-        return NULL;
-    }
-
-    rpc = malloc(sizeof *rpc);
-    if (!rpc) {
-        ERRMEM;
-        return NULL;
-    }
-
-    rpc->type = NC_RPC_GETCONFIG;
-    rpc->source = source;
-    if (filter && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
-        rpc->filter = strdup(filter);
-    } else {
-        rpc->filter = (char *)filter;
-    }
-    rpc->wd_mode = wd_mode;
-    rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
-
-    return (struct nc_rpc *)rpc;
-}
-
-API struct nc_rpc *
-nc_rpc_edit(NC_DATASTORE target, NC_RPC_EDIT_DFLTOP default_op, NC_RPC_EDIT_TESTOPT test_opt,
-            NC_RPC_EDIT_ERROPT error_opt, const char *edit_content, NC_PARAMTYPE paramtype)
-{
-    struct nc_rpc_edit *rpc;
-
-    if ((edit_content[0] != '<') && !isalpha(edit_content[0])) {
-        ERR("<edit-config> content must either be a URL or a config (XML).");
-        return NULL;
-    }
-
-    rpc = malloc(sizeof *rpc);
-    if (!rpc) {
-        ERRMEM;
-        return NULL;
-    }
-
-    rpc->type = NC_RPC_EDIT;
-    rpc->target = target;
-    rpc->default_op = default_op;
-    rpc->test_opt = test_opt;
-    rpc->error_opt = error_opt;
-    if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
-        rpc->edit_cont = strdup(edit_content);
-    } else {
-        rpc->edit_cont = (char *)edit_content;
-    }
-    rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
-
-    return (struct nc_rpc *)rpc;
-}
-
-API struct nc_rpc *
-nc_rpc_copy(NC_DATASTORE target, const char *url_trg, NC_DATASTORE source, const char *url_or_config_src,
-            NC_WD_MODE wd_mode, NC_PARAMTYPE paramtype)
-{
-    struct nc_rpc_copy *rpc;
-
-    if (url_or_config_src && (url_or_config_src[0] != '<') && !isalpha(url_or_config_src[0])) {
-        ERR("<copy-config> source is neither a URL nor a config (XML).");
-        return NULL;
-    }
-
-    rpc = malloc(sizeof *rpc);
-    if (!rpc) {
-        ERRMEM;
-        return NULL;
-    }
-
-    rpc->type = NC_RPC_COPY;
-    rpc->target = target;
-    if (url_trg && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
-        rpc->url_trg = strdup(url_trg);
-    } else {
-        rpc->url_trg = (char *)url_trg;
-    }
-    rpc->source = source;
-    if (url_or_config_src && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
-        rpc->url_config_src = strdup(url_or_config_src);
-    } else {
-        rpc->url_config_src = (char *)url_or_config_src;
-    }
-    rpc->wd_mode = wd_mode;
-    rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
-
-    return (struct nc_rpc *)rpc;
-}
-
-API struct nc_rpc *
-nc_rpc_delete(NC_DATASTORE target, const char *url, NC_PARAMTYPE paramtype)
-{
-    struct nc_rpc_delete *rpc;
-
-    rpc = malloc(sizeof *rpc);
-    if (!rpc) {
-        ERRMEM;
-        return NULL;
-    }
-
-    rpc->type = NC_RPC_DELETE;
-    rpc->target = target;
-    if (url && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
-        rpc->url = strdup(url);
-    } else {
-        rpc->url = (char *)url;
-    }
-    rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
-
-    return (struct nc_rpc *)rpc;
-}
-
-API struct nc_rpc *
-nc_rpc_lock(NC_DATASTORE target)
-{
-    struct nc_rpc_lock *rpc;
-
-    rpc = malloc(sizeof *rpc);
-    if (!rpc) {
-        ERRMEM;
-        return NULL;
-    }
-
-    rpc->type = NC_RPC_LOCK;
-    rpc->target = target;
-
-    return (struct nc_rpc *)rpc;
-}
-
-API struct nc_rpc *
-nc_rpc_unlock(NC_DATASTORE target)
-{
-    struct nc_rpc_lock *rpc;
-
-    rpc = malloc(sizeof *rpc);
-    if (!rpc) {
-        ERRMEM;
-        return NULL;
-    }
-
-    rpc->type = NC_RPC_UNLOCK;
-    rpc->target = target;
-
-    return (struct nc_rpc *)rpc;
-}
-
-API struct nc_rpc *
-nc_rpc_get(const char *filter, NC_WD_MODE wd_mode, NC_PARAMTYPE paramtype)
-{
-    struct nc_rpc_get *rpc;
-
-    if (filter && (filter[0] != '<') && (filter[0] != '/') && !isalpha(filter[0])) {
-        ERR("Filter must either be an XML subtree or an XPath expression.");
-        return NULL;
-    }
-
-    rpc = malloc(sizeof *rpc);
-    if (!rpc) {
-        ERRMEM;
-        return NULL;
-    }
-
-    rpc->type = NC_RPC_GET;
-    if (filter && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
-        rpc->filter = strdup(filter);
-    } else {
-        rpc->filter = (char *)filter;
-    }
-    rpc->wd_mode = wd_mode;
-    rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
-
-    return (struct nc_rpc *)rpc;
-}
-
-API struct nc_rpc *
-nc_rpc_kill(uint32_t session_id)
-{
-    struct nc_rpc_kill *rpc;
-
-    rpc = malloc(sizeof *rpc);
-    if (!rpc) {
-        ERRMEM;
-        return NULL;
-    }
-
-    rpc->type = NC_RPC_KILL;
-    rpc->sid = session_id;
-
-    return (struct nc_rpc *)rpc;
-}
-
-API struct nc_rpc *
-nc_rpc_commit(int confirmed, uint32_t confirm_timeout, const char *persist, const char *persist_id,
-              NC_PARAMTYPE paramtype)
-{
-    struct nc_rpc_commit *rpc;
-
-    rpc = malloc(sizeof *rpc);
-    if (!rpc) {
-        ERRMEM;
-        return NULL;
-    }
-
-    rpc->type = NC_RPC_COMMIT;
-    rpc->confirmed = confirmed;
-    rpc->confirm_timeout = confirm_timeout;
-    if (persist && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
-        rpc->persist = strdup(persist);
-    } else {
-        rpc->persist = (char *)persist;
-    }
-    if (persist_id && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
-        rpc->persist_id = strdup(persist_id);
-    } else {
-        rpc->persist_id = (char *)persist_id;
-    }
-    rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
-
-    return (struct nc_rpc *)rpc;
-}
-
-API struct nc_rpc *
-nc_rpc_discard(void)
-{
-    struct nc_rpc *rpc;
-
-    rpc = malloc(sizeof *rpc);
-    if (!rpc) {
-        ERRMEM;
-        return NULL;
-    }
-
-    rpc->type = NC_RPC_DISCARD;
-
-    return rpc;
-}
-
-API struct nc_rpc *
-nc_rpc_cancel(const char *persist_id, NC_PARAMTYPE paramtype)
-{
-    struct nc_rpc_cancel *rpc;
-
-    rpc = malloc(sizeof *rpc);
-    if (!rpc) {
-        ERRMEM;
-        return NULL;
-    }
-
-    rpc->type = NC_RPC_CANCEL;
-    if (persist_id && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
-        rpc->persist_id = strdup(persist_id);
-    } else {
-        rpc->persist_id = (char *)persist_id;
-    }
-    rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
-
-    return (struct nc_rpc *)rpc;
-}
-
-API struct nc_rpc *
-nc_rpc_validate(NC_DATASTORE source, const char *url_or_config, NC_PARAMTYPE paramtype)
-{
-    struct nc_rpc_validate *rpc;
-
-    if (url_or_config && (url_or_config[0] != '<') && !isalpha(url_or_config[0])) {
-        ERR("<validate> source is neither a URL nor a config (XML).");
-        return NULL;
-    }
-
-    rpc = malloc(sizeof *rpc);
-    if (!rpc) {
-        ERRMEM;
-        return NULL;
-    }
-
-    rpc->type = NC_RPC_VALIDATE;
-    rpc->source = source;
-    if (url_or_config && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
-        rpc->url_config_src = strdup(url_or_config);
-    } else {
-        rpc->url_config_src = (char *)url_or_config;
-    }
-    rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
-
-    return (struct nc_rpc *)rpc;
-}
-
-API struct nc_rpc *
-nc_rpc_getschema(const char *identifier, const char *version, const char *format, NC_PARAMTYPE paramtype)
-{
-    struct nc_rpc_getschema *rpc;
-
-    rpc = malloc(sizeof *rpc);
-    if (!rpc) {
-        ERRMEM;
-        return NULL;
-    }
-
-    rpc->type = NC_RPC_GETSCHEMA;
-    if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
-        rpc->identifier = strdup(identifier);
-    } else {
-        rpc->identifier = (char *)identifier;
-    }
-    if (version && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
-        rpc->version = strdup(version);
-    } else {
-        rpc->version = (char *)version;
-    }
-    if (format && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
-        rpc->format = strdup(format);
-    } else {
-        rpc->format = (char *)format;
-    }
-    rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
-
-    return (struct nc_rpc *)rpc;
-}
-
-API struct nc_rpc *
-nc_rpc_subscribe(const char *stream_name, const char *filter, const char *start_time, const char *stop_time,
-                 NC_PARAMTYPE paramtype)
-{
-    struct nc_rpc_subscribe *rpc;
-
-    if (filter && (filter[0] != '<') && (filter[0] != '/') && !isalpha(filter[0])) {
-        ERR("Filter must either be an XML subtree or an XPath expression.");
-        return NULL;
-    }
-
-    rpc = malloc(sizeof *rpc);
-    if (!rpc) {
-        ERRMEM;
-        return NULL;
-    }
-
-    rpc->type = NC_RPC_SUBSCRIBE;
-    if (stream_name && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
-        rpc->stream = strdup(stream_name);
-    } else {
-        rpc->stream = (char *)stream_name;
-    }
-    if (filter && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
-        rpc->filter = strdup(filter);
-    } else {
-        rpc->filter = (char *)filter;
-    }
-    if (start_time && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
-        rpc->start = strdup(start_time);
-    } else {
-        rpc->start = (char *)start_time;
-    }
-    if (stop_time && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
-        rpc->stop = strdup(stop_time);
-    } else {
-        rpc->stop = (char *)stop_time;
-    }
-    rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
-
-    return (struct nc_rpc *)rpc;
-}
-
-API struct nc_server_reply *
-nc_server_reply_ok(void)
-{
-    struct nc_server_reply *ret;
-
-    ret = malloc(sizeof *ret);
-    if (!ret) {
-        ERRMEM;
-        return NULL;
-    }
-
-    ret->type = NC_RPL_OK;
-    return ret;
-}
-
-API struct nc_server_reply *
-nc_server_reply_data(struct lyd_node *data, NC_PARAMTYPE paramtype)
-{
-    struct nc_server_reply_data *ret;
-
-    if (!data) {
-        ERRARG;
-        return NULL;
-    }
-
-    ret = malloc(sizeof *ret);
-    if (!ret) {
-        ERRMEM;
-        return NULL;
-    }
-
-    ret->type = NC_RPL_DATA;
-    if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
-        ret->data = lyd_dup(data, 1);
-    } else {
-        ret->data = data;
-    }
-    if (paramtype != NC_PARAMTYPE_CONST) {
-        ret->free = 1;
-    } else {
-        ret->free = 0;
-    }
-    return (struct nc_server_reply *)ret;
-}
-
-API struct nc_server_reply *
-nc_server_reply_err(struct ly_ctx *ctx, struct nc_server_error *err)
-{
-    struct nc_server_reply_error *ret;
-
-    if (!ctx || !err) {
-        ERRARG;
-        return NULL;
-    }
-
-    ret = malloc(sizeof *ret);
-    if (!ret) {
-        ERRMEM;
-        return NULL;
-    }
-
-    ret->type = NC_RPL_ERROR;
-    ret->ctx = ctx;
-    ret->err = malloc(sizeof *ret->err);
-    ret->err[0] = err;
-    ret->count = 1;
-    return (struct nc_server_reply *)ret;
-}
-
-API int
-nc_server_reply_add_err(struct nc_server_reply *reply, struct nc_server_error *err)
-{
-    struct nc_server_reply_error *err_rpl;
-
-    if (!reply || (reply->type != NC_RPL_ERROR) || !err) {
-        ERRARG;
-        return -1;
-    }
-
-    err_rpl = (struct nc_server_reply_error *)reply;
-    ++err_rpl->count;
-    err_rpl->err = realloc(err_rpl->err, err_rpl->count * sizeof *err_rpl->err);
-    err_rpl->err[err_rpl->count - 1] = err;
-    return 0;
-}
-
-API struct nc_server_error *
-nc_err(struct ly_ctx *ctx, NC_ERR tag, ...)
-{
-    va_list ap;
-    struct nc_server_error *ret;
-    NC_ERR_TYPE type;
-    const char *arg1, *arg2;
-    uint32_t sid;
-
-    if (!ctx || !tag) {
-        ERRARG;
-        return NULL;
-    }
-
-    ret = calloc(1, sizeof *ret);
-    if (!ret) {
-        ERRMEM;
-        return NULL;
-    }
-
-    va_start(ap, tag);
-
-    switch (tag) {
-    case NC_ERR_IN_USE:
-    case NC_ERR_INVALID_VALUE:
-    case NC_ERR_ACCESS_DENIED:
-    case NC_ERR_ROLLBACK_FAILED:
-    case NC_ERR_OP_NOT_SUPPORTED:
-        type = va_arg(ap, NC_ERR_TYPE);
-        if ((type != NC_ERR_TYPE_PROT) && (type == NC_ERR_TYPE_APP)) {
-            goto fail;
-        }
-        break;
-
-    case NC_ERR_TOO_BIG:
-    case NC_ERR_RES_DENIED:
-        type = va_arg(ap, NC_ERR_TYPE);
-        /* nothing to check */
-        break;
-
-    case NC_ERR_MISSING_ATTR:
-    case NC_ERR_BAD_ATTR:
-    case NC_ERR_UNKNOWN_ATTR:
-        type = va_arg(ap, NC_ERR_TYPE);
-        arg1 = va_arg(ap, const char *);
-        arg2 = va_arg(ap, const char *);
-
-        if (type == NC_ERR_TYPE_TRAN) {
-            goto fail;
-        }
-        nc_err_add_bad_attr(ctx, ret, arg1);
-        nc_err_add_bad_elem(ctx, ret, arg2);
-        break;
-
-    case NC_ERR_MISSING_ELEM:
-    case NC_ERR_BAD_ELEM:
-    case NC_ERR_UNKNOWN_ELEM:
-        type = va_arg(ap, NC_ERR_TYPE);
-        arg1 = va_arg(ap, const char *);
-
-        if ((type != NC_ERR_TYPE_PROT) && (type != NC_ERR_TYPE_APP)) {
-            goto fail;
-        }
-        nc_err_add_bad_elem(ctx, ret, arg1);
-        break;
-
-    case NC_ERR_UNKNOWN_NS:
-        type = va_arg(ap, NC_ERR_TYPE);
-        arg1 = va_arg(ap, const char *);
-        arg2 = va_arg(ap, const char *);
-
-        if ((type != NC_ERR_TYPE_PROT) && (type != NC_ERR_TYPE_APP)) {
-            goto fail;
-        }
-        nc_err_add_bad_elem(ctx, ret, arg1);
-        nc_err_add_bad_ns(ctx, ret, arg2);
-        break;
-
-    case NC_ERR_LOCK_DENIED:
-        sid = va_arg(ap, uint32_t);
-
-        type = NC_ERR_TYPE_PROT;
-        nc_err_set_sid(ret, sid);
-        break;
-
-    case NC_ERR_DATA_EXISTS:
-    case NC_ERR_DATA_MISSING:
-        type = NC_ERR_TYPE_APP;
-        break;
-
-    case NC_ERR_OP_FAILED:
-        type = va_arg(ap, NC_ERR_TYPE);
-
-        if (type == NC_ERR_TYPE_TRAN) {
-            goto fail;
-        }
-        break;
-
-    case NC_ERR_MALFORMED_MSG:
-        type = NC_ERR_TYPE_RPC;
-        break;
-
-    default:
-        goto fail;
-    }
-
-    switch (tag) {
-    case NC_ERR_IN_USE:
-        nc_err_set_msg(ctx, ret, "The request requires a resource that already is in use.", "en");
-        break;
-    case NC_ERR_INVALID_VALUE:
-        nc_err_set_msg(ctx, ret, "The request specifies an unacceptable value for one or more parameters.", "en");
-        break;
-    case NC_ERR_TOO_BIG:
-        nc_err_set_msg(ctx, ret, "The request or response (that would be generated) is too large for the implementation to handle.", "en");
-        break;
-    case NC_ERR_MISSING_ATTR:
-        nc_err_set_msg(ctx, ret, "An expected attribute is missing.", "en");
-        break;
-    case NC_ERR_BAD_ATTR:
-        nc_err_set_msg(ctx, ret, "An attribute value is not correct.", "en");
-        break;
-    case NC_ERR_UNKNOWN_ATTR:
-        nc_err_set_msg(ctx, ret, "An unexpected attribute is present.", "en");
-        break;
-    case NC_ERR_MISSING_ELEM:
-        nc_err_set_msg(ctx, ret, "An expected element is missing.", "en");
-        break;
-    case NC_ERR_BAD_ELEM:
-        nc_err_set_msg(ctx, ret, "An element value is not correct.", "en");
-        break;
-    case NC_ERR_UNKNOWN_ELEM:
-        nc_err_set_msg(ctx, ret, "An unexpected element is present.", "en");
-        break;
-    case NC_ERR_UNKNOWN_NS:
-        nc_err_set_msg(ctx, ret, "An unexpected namespace is present.", "en");
-        break;
-    case NC_ERR_ACCESS_DENIED:
-        nc_err_set_msg(ctx, ret, "Access to the requested protocol operation or data model is denied because authorization failed.", "en");
-        break;
-    case NC_ERR_LOCK_DENIED:
-        nc_err_set_msg(ctx, ret, "Access to the requested lock is denied because the lock is currently held by another entity.", "en");
-        break;
-    case NC_ERR_RES_DENIED:
-        nc_err_set_msg(ctx, ret, "Request could not be completed because of insufficient resources.", "en");
-        break;
-    case NC_ERR_ROLLBACK_FAILED:
-        nc_err_set_msg(ctx, ret, "Request to roll back some configuration change was not completed for some reason.", "en");
-        break;
-    case NC_ERR_DATA_EXISTS:
-        nc_err_set_msg(ctx, ret, "Request could not be completed because the relevant data model content already exists.", "en");
-        break;
-    case NC_ERR_DATA_MISSING:
-        nc_err_set_msg(ctx, ret, "Request could not be completed because the relevant data model content does not exist.", "en");
-        break;
-    case NC_ERR_OP_NOT_SUPPORTED:
-        nc_err_set_msg(ctx, ret, "Request could not be completed because the requested operation is not supported by this implementation.", "en");
-        break;
-    case NC_ERR_OP_FAILED:
-        nc_err_set_msg(ctx, ret, "Request could not be completed because the requested operation failed for a non-specific reason.", "en");
-        break;
-    case NC_ERR_MALFORMED_MSG:
-        nc_err_set_msg(ctx, ret, "A message could not be handled because it failed to be parsed correctly.", "en");
-        break;
-    default:
-        goto fail;
-    }
-
-    va_end(ap);
-
-    ret->type = type;
-    ret->tag = tag;
-    return ret;
-
-fail:
-    ERRARG;
-    free(ret);
-    return NULL;
-}
-
-API int
-nc_err_set_app_tag(struct ly_ctx *ctx, struct nc_server_error *err, const char *error_app_tag)
-{
-    if (!ctx || !err || !error_app_tag) {
-        ERRARG;
-        return -1;
-    }
-
-    if (err->apptag) {
-        lydict_remove(ctx, err->apptag);
-    }
-    err->apptag = lydict_insert(ctx, error_app_tag, 0);
-    return 0;
-}
-
-API int
-nc_err_set_path(struct ly_ctx *ctx, struct nc_server_error *err, const char *error_path)
-{
-    if (!ctx || !err || !error_path) {
-        ERRARG;
-        return -1;
-    }
-
-    if (err->path) {
-        lydict_remove(ctx, err->path);
-    }
-    err->path = lydict_insert(ctx, error_path, 0);
-    return 0;
-}
-
-API int
-nc_err_set_msg(struct ly_ctx *ctx, struct nc_server_error *err, const char *error_message, const char *lang)
-{
-    if (!ctx || !err || !error_message) {
-        ERRARG;
-        return -1;
-    }
-
-    if (err->message) {
-        lydict_remove(ctx, err->apptag);
-    }
-    err->message = lydict_insert(ctx, error_message, 0);
-
-    if (err->message_lang) {
-        lydict_remove(ctx, err->message_lang);
-    }
-    if (lang) {
-        err->message_lang = lydict_insert(ctx, lang, 0);
-    } else {
-        lang = NULL;
-    }
-    return 0;
-}
-
-API int
-nc_err_set_sid(struct nc_server_error *err, uint32_t session_id)
-{
-    if (!err) {
-        ERRARG;
-        return -1;
-    }
-
-    err->sid = session_id;
-    return 0;
-}
-
-API int
-nc_err_add_bad_attr(struct ly_ctx *ctx, struct nc_server_error *err, const char *attr_name)
-{
-    if (!ctx || !err || !attr_name) {
-        ERRARG;
-        return -1;
-    }
-
-    ++err->attr_count;
-    err->attr = realloc(err->attr, err->attr_count * sizeof *err->attr);
-    err->attr[err->attr_count - 1] = lydict_insert(ctx, attr_name, 0);
-    return 0;
-}
-
-API int
-nc_err_add_bad_elem(struct ly_ctx *ctx, struct nc_server_error *err, const char *elem_name)
-{
-    if (!ctx || !err || !elem_name) {
-        ERRARG;
-        return -1;
-    }
-
-    ++err->elem_count;
-    err->elem = realloc(err->elem, err->elem_count * sizeof *err->elem);
-    err->elem[err->elem_count - 1] = lydict_insert(ctx, elem_name, 0);
-    return 0;
-}
-
-API int
-nc_err_add_bad_ns(struct ly_ctx *ctx, struct nc_server_error *err, const char *ns_name)
-{
-    if (!ctx || !err || !ns_name) {
-        ERRARG;
-        return -1;
-    }
-
-    ++err->ns_count;
-    err->ns = realloc(err->ns, err->ns_count * sizeof *err->ns);
-    err->ns[err->ns_count - 1] = lydict_insert(ctx, ns_name, 0);
-    return 0;
-}
-
-API int
-nc_err_add_info_other(struct nc_server_error *err, struct lyxml_elem *other)
-{
-    if (!err || !other) {
-        ERRARG;
-        return -1;
-    }
-
-    ++err->other_count;
-    err->other = realloc(err->other, err->other_count * sizeof *err->other);
-    err->other[err->other_count - 1] = other;
-    return 0;
-}
-
-void
-nc_server_rpc_free(struct nc_server_rpc *rpc)
-{
-    lyxml_free(rpc->tree->schema->module->ctx, rpc->root);
-    lyd_free(rpc->tree);
-    free(rpc);
-}
-
-API void
-nc_server_reply_free(struct nc_server_reply *reply)
-{
-    uint32_t i;
-    struct nc_server_reply_data *data_rpl;
-    struct nc_server_reply_error *error_rpl;
-
-    if (!reply) {
-        return;
-    }
-
-    switch (reply->type) {
-    case NC_RPL_DATA:
-        data_rpl = (struct nc_server_reply_data *)reply;
-        if (data_rpl->free) {
-            lyd_free_withsiblings(data_rpl->data);
-        }
-        break;
-    case NC_RPL_OK:
-        /* nothing to free */
-        break;
-    case NC_RPL_ERROR:
-        error_rpl = (struct nc_server_reply_error *)reply;
-        for (i = 0; i < error_rpl->count; ++i) {
-            nc_err_free(error_rpl->ctx, error_rpl->err[i]);
-        }
-        free(error_rpl->err);
-        break;
-    default:
-        break;
-    }
-    free(reply);
-}
-
-API void
-nc_err_free(struct ly_ctx *ctx, struct nc_server_error *err)
-{
-    uint32_t i;
-
-    if (!err) {
-        ERRARG;
-        return;
-    }
-
-    lydict_remove(ctx, err->apptag);
-    lydict_remove(ctx, err->path);
-    lydict_remove(ctx, err->message);
-    lydict_remove(ctx, err->message_lang);
-    for (i = 0; i < err->attr_count; ++i) {
-        lydict_remove(ctx, err->attr[i]);
-    }
-    free(err->attr);
-    for (i = 0; i < err->elem_count; ++i) {
-        lydict_remove(ctx, err->elem[i]);
-    }
-    free(err->elem);
-    for (i = 0; i < err->ns_count; ++i) {
-        lydict_remove(ctx, err->ns[i]);
-    }
-    free(err->ns);
-    for (i = 0; i < err->other_count; ++i) {
-        lyxml_free(ctx, err->other[i]);
-    }
-    free(err->other);
-    free(err);
-}
-
-API void
-nc_rpc_free(struct nc_rpc *rpc)
-{
-    struct nc_rpc_generic *rpc_generic;
-    struct nc_rpc_getconfig *rpc_getconfig;
-    struct nc_rpc_edit *rpc_edit;
-    struct nc_rpc_copy *rpc_copy;
-    struct nc_rpc_delete *rpc_delete;
-    struct nc_rpc_get *rpc_get;
-    struct nc_rpc_commit *rpc_commit;
-    struct nc_rpc_cancel *rpc_cancel;
-    struct nc_rpc_validate *rpc_validate;
-    struct nc_rpc_getschema *rpc_getschema;
-    struct nc_rpc_subscribe *rpc_subscribe;
-
-    if (!rpc) {
-        return;
-    }
-
-    switch (rpc->type) {
-    case NC_RPC_GENERIC:
-        rpc_generic = (struct nc_rpc_generic *)rpc;
-        if (rpc_generic->free) {
-            if (rpc_generic->has_data) {
-                lyd_free(rpc_generic->content.data);
-            } else {
-                free(rpc_generic->content.xml_str);
-            }
-        }
-        break;
-    case NC_RPC_GETCONFIG:
-        rpc_getconfig = (struct nc_rpc_getconfig *)rpc;
-        if (rpc_getconfig->free) {
-            free(rpc_getconfig->filter);
-        }
-        break;
-    case NC_RPC_EDIT:
-        rpc_edit = (struct nc_rpc_edit *)rpc;
-        if (rpc_edit->free) {
-            free(rpc_edit->edit_cont);
-        }
-        break;
-    case NC_RPC_COPY:
-        rpc_copy = (struct nc_rpc_copy *)rpc;
-        if (rpc_copy->free) {
-            free(rpc_copy->url_config_src);
-        }
-        break;
-    case NC_RPC_DELETE:
-        rpc_delete = (struct nc_rpc_delete *)rpc;
-        if (rpc_delete->free) {
-            free(rpc_delete->url);
-        }
-        break;
-    case NC_RPC_GET:
-        rpc_get = (struct nc_rpc_get *)rpc;
-        if (rpc_get->free) {
-            free(rpc_get->filter);
-        }
-        break;
-    case NC_RPC_COMMIT:
-        rpc_commit = (struct nc_rpc_commit *)rpc;
-        if (rpc_commit->free) {
-            free(rpc_commit->persist);
-            free(rpc_commit->persist_id);
-        }
-        break;
-    case NC_RPC_CANCEL:
-        rpc_cancel = (struct nc_rpc_cancel *)rpc;
-        if (rpc_cancel->free) {
-            free(rpc_cancel->persist_id);
-        }
-        break;
-    case NC_RPC_VALIDATE:
-        rpc_validate = (struct nc_rpc_validate *)rpc;
-        if (rpc_validate->free) {
-            free(rpc_validate->url_config_src);
-        }
-        break;
-    case NC_RPC_GETSCHEMA:
-        rpc_getschema = (struct nc_rpc_getschema *)rpc;
-        if (rpc_getschema->free) {
-            free(rpc_getschema->identifier);
-            free(rpc_getschema->version);
-            free(rpc_getschema->format);
-        }
-        break;
-    case NC_RPC_SUBSCRIBE:
-        rpc_subscribe = (struct nc_rpc_subscribe *)rpc;
-        if (rpc_subscribe->free) {
-            free(rpc_subscribe->stream);
-            free(rpc_subscribe->filter);
-            free(rpc_subscribe->start);
-            free(rpc_subscribe->stop);
-        }
-        break;
-    case NC_RPC_KILL:
-    case NC_RPC_DISCARD:
-    case NC_RPC_LOCK:
-    case NC_RPC_UNLOCK:
-        /* nothing special needed */
-        break;
-    }
-
-    free(rpc);
-}
-
-API void
-nc_reply_free(struct nc_reply *reply)
-{
-    struct nc_reply_error *error;
-    struct nc_reply_data *data;
-    uint32_t i, j;
-
-    if (!reply) {
-        return;
-    }
-
-    switch (reply->type) {
-    case NC_RPL_DATA:
-        data = (struct nc_reply_data *)reply;
-        lyd_free_withsiblings(data->data);
-        break;
-
-    case NC_RPL_OK:
-        /* nothing to free */
-        break;
-
-    case NC_RPL_ERROR:
-        error = (struct nc_reply_error *)reply;
-        for (i = 0; i < error->count; ++i) {
-            lydict_remove(error->ctx, error->err[i].type);
-            lydict_remove(error->ctx, error->err[i].tag);
-            lydict_remove(error->ctx, error->err[i].severity);
-            lydict_remove(error->ctx, error->err[i].apptag);
-            lydict_remove(error->ctx, error->err[i].path);
-            lydict_remove(error->ctx, error->err[i].message);
-            lydict_remove(error->ctx, error->err[i].message_lang);
-            lydict_remove(error->ctx, error->err[i].sid);
-            for (j = 0; j < error->err[i].attr_count; ++j) {
-                lydict_remove(error->ctx, error->err[i].attr[j]);
-            }
-            free(error->err[i].attr);
-            for (j = 0; j < error->err[i].elem_count; ++j) {
-                lydict_remove(error->ctx, error->err[i].elem[j]);
-            }
-            free(error->err[i].elem);
-            for (j = 0; j < error->err[i].ns_count; ++j) {
-                lydict_remove(error->ctx, error->err[i].ns[j]);
-            }
-            free(error->err[i].ns);
-            for (j = 0; j < error->err[i].other_count; ++j) {
-                lyxml_free(error->ctx, error->err[i].other[j]);
-            }
-            free(error->err[i].other);
-        }
-        free(error->err);
-        break;
-
-    case NC_RPL_NOTIF:
-        nc_notif_free((struct nc_notif *)reply);
-        break;
-    }
-
-    free(reply);
-}
-
 API void
 nc_notif_free(struct nc_notif *notif)
 {
diff --git a/src/messages.h b/src/messages.h
index 9372944..027461f 100644
--- a/src/messages.h
+++ b/src/messages.h
@@ -1,6 +1,6 @@
 /**
  * \file messages.h
- * \author Radek Krejci <rkrejci@cesnet.cz>
+ * \author Michal Vasko <mvasko@cesnet.cz>
  * \brief libnetconf2's public functions and structures of NETCONF messages.
  *
  * Copyright (c) 2015 CESNET, z.s.p.o.
@@ -23,64 +23,6 @@
 #ifndef NC_MESSAGES_H_
 #define NC_MESSAGES_H_
 
-#include <stdint.h>
-
-#include "netconf.h"
-
-typedef enum {
-    NC_RPC_GENERIC,     /**< user-defined generic RPC. */
-
-    /* ietf-netconf */
-    NC_RPC_GETCONFIG,   /**< \<get-config\> RPC. */
-    NC_RPC_EDIT,        /**< \<edit-config\> RPC. */
-    NC_RPC_COPY,        /**< \<copy-config\> RPC. */
-    NC_RPC_DELETE,      /**< \<delete-config\> RPC. */
-    NC_RPC_LOCK,        /**< \<lock\> RPC. */
-    NC_RPC_UNLOCK,      /**< \<unlock\> RPC. */
-    NC_RPC_GET,         /**< \<get\> RPC. */
-    /* NC_RPC_CLOSE is not defined since sending \<close-session\> is done by nc_session_free() */
-    NC_RPC_KILL,        /**< \<kill-session\> RPC. */
-    NC_RPC_COMMIT,      /**< \<commit\> RPC. */
-    NC_RPC_DISCARD,     /**< \<discard-changes\> RPC. */
-    NC_RPC_CANCEL,      /**< \<cancel-commit\> RPC. */
-    NC_RPC_VALIDATE,    /**< \<validate\> RPC. */
-
-    /* ietf-netconf-monitoring */
-    NC_RPC_GETSCHEMA,   /**< \<get-schema\> RPC. */
-
-    /* notifications */
-    NC_RPC_SUBSCRIBE    /**< \<create-subscription\> RPC. */
-} NC_RPC_TYPE;
-
-typedef enum {
-    NC_RPC_EDIT_DFLTOP_UNKNOWN = 0,
-    NC_RPC_EDIT_DFLTOP_MERGE,
-    NC_RPC_EDIT_DFLTOP_REPLACE,
-    NC_RPC_EDIT_DFLTOP_NONE
-} NC_RPC_EDIT_DFLTOP;
-
-typedef enum {
-    NC_RPC_EDIT_TESTOPT_UNKNOWN = 0,
-    NC_RPC_EDIT_TESTOPT_TESTSET,
-    NC_RPC_EDIT_TESTOPT_SET,
-    NC_RPC_EDIT_TESTOPT_TEST
-} NC_RPC_EDIT_TESTOPT;
-
-typedef enum {
-    NC_RPC_EDIT_ERROPT_UNKNOWN = 0,
-    NC_RPC_EDIT_ERROPT_STOP,
-    NC_RPC_EDIT_ERROPT_CONTINUE,
-    NC_RPC_EDIT_ERROPT_ROLLBACK
-} NC_RPC_EDIT_ERROPT;
-
-typedef enum {
-    NC_WD_UNKNOWN = 0,
-    NC_WD_ALL = 0x01,
-    NC_WD_ALL_TAG = 0x02,
-    NC_WD_TRIM = 0x04,
-    NC_WD_EXPLICIT = 0x08
-} NC_WD_MODE;
-
 typedef enum {
     NC_PARAMTYPE_CONST,
     NC_PARAMTYPE_FREE,
@@ -88,37 +30,6 @@
 } NC_PARAMTYPE;
 
 typedef enum {
-    NC_ERR_UNKNOWN = 0,
-    NC_ERR_IN_USE,
-    NC_ERR_INVALID_VALUE,
-    NC_ERR_TOO_BIG,
-    NC_ERR_MISSING_ATTR,
-    NC_ERR_BAD_ATTR,
-    NC_ERR_UNKNOWN_ATTR,
-    NC_ERR_MISSING_ELEM,
-    NC_ERR_BAD_ELEM,
-    NC_ERR_UNKNOWN_ELEM,
-    NC_ERR_UNKNOWN_NS,
-    NC_ERR_ACCESS_DENIED,
-    NC_ERR_LOCK_DENIED,
-    NC_ERR_RES_DENIED,
-    NC_ERR_ROLLBACK_FAILED,
-    NC_ERR_DATA_EXISTS,
-    NC_ERR_DATA_MISSING,
-    NC_ERR_OP_NOT_SUPPORTED,
-    NC_ERR_OP_FAILED,
-    NC_ERR_MALFORMED_MSG
-} NC_ERR;
-
-typedef enum {
-    NC_ERR_TYPE_UNKNOWN = 0,
-    NC_ERR_TYPE_TRAN,
-    NC_ERR_TYPE_RPC,
-    NC_ERR_TYPE_PROT,
-    NC_ERR_TYPE_APP
-} NC_ERR_TYPE;
-
-typedef enum {
     NC_RPL_OK,
     NC_RPL_DATA,
     NC_RPL_ERROR,
@@ -126,411 +37,11 @@
 } NC_RPL;
 
 /**
- * @brief NETCONF error structure representation
- */
-struct nc_err {
-    /**
-     * @brief \<error-type\>, error layer where the error occurred.
-     */
-    const char *type;
-    /**
-     * @brief \<error-tag\>.
-     */
-    const char *tag;
-    /**
-     * @brief \<error-severity\>.
-     */
-    const char *severity;
-    /**
-     * @brief \<error-app-tag\>, the data-model-specific or implementation-specific error condition, if one exists.
-     */
-    const char *apptag;
-    /**
-     * @brief \<error-path\>, XPATH expression identifying the element with the error.
-     */
-    const char *path;
-    /**
-     * @brief \<error-message\>, Human-readable description of the error.
-     */
-    const char *message;
-    const char *message_lang;
-
-    /* <error-info> */
-
-    /**
-     * @brief \<session-id\>, session ID of the session holding the requested lock.
-     */
-    const char *sid;
-    /**
-     * @brief \<bad-attr\>, the name of the data-model-specific XML attribute that caused the error.
-     */
-    const char **attr;
-    uint16_t attr_count;
-    /**
-     * @brief \<bad-element\>, the name of the data-model-specific XML element that caused the error.
-     */
-    const char **elem;
-    uint16_t elem_count;
-    /**
-     * @brief \<bad-namespace\>, the name of the unexpected XML namespace that caused the error.
-     */
-    const char **ns;
-    uint16_t ns_count;
-    /**
-     * @brief Remaining non-standard elements.
-     */
-    struct lyxml_elem **other;
-    uint16_t other_count;
-};
-
-/**
- * @brief NETCONF client RPC object
- */
-struct nc_rpc;
-
-struct nc_reply {
-    NC_RPL type;
-};
-
-struct nc_reply_data {
-    NC_RPL type;           /**< NC_RPL_DATA */
-    struct lyd_node *data; /**< libyang data tree */
-};
-
-struct nc_reply_error {
-    NC_RPL type;        /**< NC_RPL_ERROR */
-    struct ly_ctx *ctx;
-    struct nc_err *err; /**< errors, any of the values inside can be NULL */
-    uint32_t count;
-};
-
-struct nc_notif {
-    NC_RPL type;           /**< NC_RPL_NOTIF */
-    const char *datetime;  /**< eventTime of the notification */
-    struct lyd_node *tree; /**< libyang data tree of the message */
-};
-
-/**
- * @brief NETCONF server RPC reply object
- */
-struct nc_server_reply;
-
-struct nc_server_error;
-
-/**
  * @brief NETCONF notification object
  */
 struct nc_notif;
 
 /**
- * @brief Get the type of the RPC
- *
- * @param[in] rpc RPC to check the type of.
- * @return Type of \p rpc.
- */
-NC_RPC_TYPE nc_rpc_get_type(const struct nc_rpc *rpc);
-
-/**
- * @brief Create a generic NETCONF RPC
- *
- * Note that created object can be sent via any NETCONF session that shares the context
- * of the \p data.
- *
- * @param[in] data NETCONF RPC data as a data tree.
- * @param[in] paramtype How to further manage data parameters.
- * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
- */
-struct nc_rpc *nc_rpc_generic(const struct lyd_node *data, NC_PARAMTYPE paramtype);
-
-/**
- * @brief Create a generic NETCONF RPC from an XML string
- *
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
- *
- * @param[in] xml_str NETCONF RPC data as an XML string.
- * @param[in] paramtype How to further manage data parameters.
- * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
- */
-struct nc_rpc *nc_rpc_generic_xml(const char *xml_str, NC_PARAMTYPE paramtype);
-
-/**
- * @brief Create NETCONF RPC \<get-config\>
- *
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
- *
- * @param[in] source Source datastore being queried.
- * @param[in] filter Optional filter data, an XML subtree or XPath expression.
- * @param[in] wd_mode Optional with-defaults capability mode.
- * @param[in] paramtype How to further manage data parameters.
- * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
- */
-struct nc_rpc *nc_rpc_getconfig(NC_DATASTORE source, const char *filter, NC_WD_MODE wd_mode,
-                                NC_PARAMTYPE paramtype);
-
-/**
- * @brief Create NETCONF RPC \<edit-config\>
- *
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
- *
- * @param[in] target Target datastore being edited.
- * @param[in] default_op Optional default operation.
- * @param[in] test_opt Optional test option.
- * @param[in] error_opt Optional error option.
- * @param[in] edit_content Config or URL where the config to perform is to be found.
- * @param[in] paramtype How to further manage data parameters.
- * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
- */
-struct nc_rpc *nc_rpc_edit(NC_DATASTORE target, NC_RPC_EDIT_DFLTOP default_op, NC_RPC_EDIT_TESTOPT test_opt,
-                           NC_RPC_EDIT_ERROPT error_opt, const char *edit_content, NC_PARAMTYPE paramtype);
-
-/**
- * @brief Create NETCONF RPC \<copy-config\>
- *
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
- *
- * @param[in] target Target datastore.
- * @param[in] url_trg Used instead \p target if the target is an URL.
- * @param[in] source Source datastore.
- * @param[in] url_or_config_src Used instead \p source if the source is an URL or a config.
- * @param[in] wd_mode Optional with-defaults capability mode.
- * @param[in] paramtype How to further manage data parameters.
- * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
- */
-struct nc_rpc *nc_rpc_copy(NC_DATASTORE target, const char *url_trg, NC_DATASTORE source,
-                           const char *url_or_config_src, NC_WD_MODE wd_mode, NC_PARAMTYPE paramtype);
-
-/**
- * @brief Create NETCONF RPC \<delete-config\>
- *
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
- *
- * @param[in] target Target datastore to delete.
- * @param[in] url Used instead \p target if the target is an URL.
- * @param[in] paramtype How to further manage data parameters.
- * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
- */
-struct nc_rpc *nc_rpc_delete(NC_DATASTORE target, const char *url, NC_PARAMTYPE paramtype);
-
-/**
- * @brief Create NETCONF RPC \<lock\>
- *
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
- *
- * @param[in] target Target datastore of the operation.
- * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
- */
-struct nc_rpc *nc_rpc_lock(NC_DATASTORE target);
-
-/**
- * @brief Create NETCONF RPC \<unlock\>
- *
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
- *
- * @param[in] target Target datastore of the operation.
- * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
- */
-struct nc_rpc *nc_rpc_unlock(NC_DATASTORE target);
-
-/**
- * @brief Create NETCONF RPC \<get\>
- *
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
- *
- * @param[in] filter Optional filter data, an XML subtree or XPath expression.
- * @param[in] wd_mode Optional with-defaults capability mode.
- * @param[in] paramtype How to further manage data parameters.
- * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
- */
-struct nc_rpc *nc_rpc_get(const char *filter, NC_WD_MODE wd_mode, NC_PARAMTYPE paramtype);
-
-/**
- * @brief Create NETCONF RPC \<kill-session\>
- *
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
- *
- * @param[in] session_id Session ID of the session to kill.
- * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
- */
-struct nc_rpc *nc_rpc_kill(uint32_t session_id);
-
-/**
- * @brief Create NETCONF RPC \<commit\>
- *
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
- *
- * @param[in] confirmed Whether the commit is to be confirmed.
- * @param[in] confirm_timeout Optional confirm timeout.
- * @param[in] persist Optional identification string of a new persistent confirmed commit.
- * @param[in] persist_id Optional identification string of a persistent confirmed commit to be commited.
- * @param[in] paramtype How to further manage data parameters.
- * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
- */
-struct nc_rpc *nc_rpc_commit(int confirmed, uint32_t confirm_timeout, const char *persist, const char *persist_id,
-                             NC_PARAMTYPE paramtype);
-
-/**
- * @brief Create NETCONF RPC \<discard-changes\>
- *
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
- *
- * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
- */
-struct nc_rpc *nc_rpc_discard(void);
-
-/**
- * @brief Create NETCONF RPC \<cancel-commit\>
- *
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
- *
- * @param[in] persist_id Optional identification string of a persistent confirmed commit.
- * @param[in] paramtype How to further manage data parameters.
- * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
- */
-struct nc_rpc *nc_rpc_cancel(const char *persist_id, NC_PARAMTYPE paramtype);
-
-/**
- * @brief Create NETCONF RPC \<validate\>
- *
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
- *
- * @param[in] source Source datastore being validated.
- * @param[in] url_or_config Usedn instead \p source if the source is an URL or a config.
- * @param[in] paramtype How to further manage data parameters.
- * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
- */
-struct nc_rpc *nc_rpc_validate(NC_DATASTORE source, const char *url_or_config, NC_PARAMTYPE paramtype);
-
-/**
- * @brief Create NETCONF RPC \<get-schema\>
- *
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
- *
- * @param[in] identifier Requested model identifier.
- * @param[in] version Optional model version, either YANG version (1.0/1.1) or revision date.
- * @param[in] format Optional format of the model (default is YANG).
- * @param[in] paramtype How to further manage data parameters.
- * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
- */
-struct nc_rpc *nc_rpc_getschema(const char *identifier, const char *version, const char *format, NC_PARAMTYPE paramtype);
-
-/**
- * @brief Create NETCONF RPC \<create-subscription\>
- *
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
- *
- * @param[in] stream_name Optional name of a NETCONF stream to subscribe to.
- * @param[in] filter Optional filter data, an XML subtree or XPath expression.
- * @param[in] start_time Optional YANG datetime identifying the start of the subscription.
- * @param[in] stop_time Optional YANG datetime identifying the end of the subscription.
- * @param[in] paramtype How to further manage data parameters.
- * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
- */
-struct nc_rpc *nc_rpc_subscribe(const char *stream_name, const char *filter, const char *start_time,
-								const char *stop_time, NC_PARAMTYPE paramtype);
-
-struct nc_server_reply *nc_server_reply_ok(void);
-
-struct nc_server_reply *nc_server_reply_data(struct lyd_node *data, NC_PARAMTYPE paramtype);
-
-struct nc_server_reply *nc_server_reply_err(struct ly_ctx *ctx, struct nc_server_error *err);
-
-int nc_server_reply_add_err(struct nc_server_reply *reply, struct nc_server_error *err);
-
-struct nc_server_error *nc_err(struct ly_ctx *ctx, NC_ERR tag, ...);
-
-int nc_err_set_app_tag(struct ly_ctx *ctx, struct nc_server_error *err, const char *error_app_tag);
-
-int nc_err_set_path(struct ly_ctx *ctx, struct nc_server_error *err, const char *error_path);
-
-int nc_err_set_msg(struct ly_ctx *ctx, struct nc_server_error *err, const char *error_message, const char *lang);
-
-int nc_err_set_sid(struct nc_server_error *err, uint32_t session_id);
-
-int nc_err_add_bad_attr(struct ly_ctx *ctx, struct nc_server_error *err, const char *attr_name);
-
-int nc_err_add_bad_elem(struct ly_ctx *ctx, struct nc_server_error *err, const char *elem_name);
-
-int nc_err_add_bad_ns(struct ly_ctx *ctx, struct nc_server_error *err, const char *ns_name);
-
-int nc_err_add_info_other(struct nc_server_error *err, struct lyxml_elem *other);
-
-/**
- * @brief Free the NETCONF RPC object.
- * @param[in] rpc Object to free.
- */
-void nc_rpc_free(struct nc_rpc *rpc);
-
-/**
- * @brief Free the NETCONF RPC reply object.
- * @param[in] rpc Object to free.
- */
-void nc_reply_free(struct nc_reply *reply);
-
-void nc_server_reply_free(struct nc_server_reply *reply);
-
-void nc_err_free(struct ly_ctx *ctx, struct nc_server_error *err);
-
-/**
  * @brief Free the NETCONF Notification object.
  * @param[in] rpc Object to free.
  */
diff --git a/src/messages_client.c b/src/messages_client.c
new file mode 100644
index 0000000..dfc7485
--- /dev/null
+++ b/src/messages_client.c
@@ -0,0 +1,629 @@
+/**
+ * \file messages.c
+ * \author Radek Krejci <rkrejci@cesnet.cz>
+ * \brief libnetconf2 - NETCONF messages functions
+ *
+ * Copyright (c) 2015 CESNET, z.s.p.o.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of the Company nor the names of its contributors
+ *    may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include <libyang/libyang.h>
+
+#include "libnetconf.h"
+#include "messages_p.h"
+
+const char *rpcedit_dfltop2str[] = {NULL, "merge", "replace", "none"};
+const char *rpcedit_testopt2str[] = {NULL, "test-then-set", "set", "test-only"};
+const char *rpcedit_erropt2str[] = {NULL, "stop-on-error", "continue-on-error", "rollback-on-error"};
+
+API NC_RPC_TYPE
+nc_rpc_get_type(const struct nc_rpc *rpc)
+{
+    return rpc->type;
+}
+
+API struct nc_rpc *
+nc_rpc_generic(const struct lyd_node *data, NC_PARAMTYPE paramtype)
+{
+    struct nc_rpc_generic *rpc;
+
+    if (data->next || (data->prev != data)) {
+        ERR("Generic RPC must have a single root node.");
+        return NULL;
+    }
+
+    rpc = malloc(sizeof *rpc);
+    if (!rpc) {
+        ERRMEM;
+        return NULL;
+    }
+
+    rpc->type = NC_RPC_GENERIC;
+    rpc->has_data = 1;
+    if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
+        rpc->content.data = lyd_dup(data, 1);
+    } else {
+        rpc->content.data = (struct lyd_node *)data;
+    }
+    rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
+
+    return (struct nc_rpc *)rpc;
+}
+
+API struct nc_rpc *
+nc_rpc_generic_xml(const char *xml_str, NC_PARAMTYPE paramtype)
+{
+    struct nc_rpc_generic *rpc;
+
+    rpc = malloc(sizeof *rpc);
+    if (!rpc) {
+        ERRMEM;
+        return NULL;
+    }
+
+    rpc->type = NC_RPC_GENERIC;
+    rpc->has_data = 0;
+    if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
+        rpc->content.xml_str = strdup(xml_str);
+    } else {
+        rpc->content.xml_str = (char *)xml_str;
+    }
+    rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
+
+    return (struct nc_rpc *)rpc;
+}
+
+API struct nc_rpc *
+nc_rpc_getconfig(NC_DATASTORE source, const char *filter, NC_WD_MODE wd_mode, NC_PARAMTYPE paramtype)
+{
+    struct nc_rpc_getconfig *rpc;
+
+    if (filter && (filter[0] != '<') && (filter[0] != '/') && !isalpha(filter[0])) {
+        ERR("Filter must either be an XML subtree or an XPath expression.");
+        return NULL;
+    }
+
+    rpc = malloc(sizeof *rpc);
+    if (!rpc) {
+        ERRMEM;
+        return NULL;
+    }
+
+    rpc->type = NC_RPC_GETCONFIG;
+    rpc->source = source;
+    if (filter && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+        rpc->filter = strdup(filter);
+    } else {
+        rpc->filter = (char *)filter;
+    }
+    rpc->wd_mode = wd_mode;
+    rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
+
+    return (struct nc_rpc *)rpc;
+}
+
+API struct nc_rpc *
+nc_rpc_edit(NC_DATASTORE target, NC_RPC_EDIT_DFLTOP default_op, NC_RPC_EDIT_TESTOPT test_opt,
+            NC_RPC_EDIT_ERROPT error_opt, const char *edit_content, NC_PARAMTYPE paramtype)
+{
+    struct nc_rpc_edit *rpc;
+
+    if ((edit_content[0] != '<') && !isalpha(edit_content[0])) {
+        ERR("<edit-config> content must either be a URL or a config (XML).");
+        return NULL;
+    }
+
+    rpc = malloc(sizeof *rpc);
+    if (!rpc) {
+        ERRMEM;
+        return NULL;
+    }
+
+    rpc->type = NC_RPC_EDIT;
+    rpc->target = target;
+    rpc->default_op = default_op;
+    rpc->test_opt = test_opt;
+    rpc->error_opt = error_opt;
+    if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
+        rpc->edit_cont = strdup(edit_content);
+    } else {
+        rpc->edit_cont = (char *)edit_content;
+    }
+    rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
+
+    return (struct nc_rpc *)rpc;
+}
+
+API struct nc_rpc *
+nc_rpc_copy(NC_DATASTORE target, const char *url_trg, NC_DATASTORE source, const char *url_or_config_src,
+            NC_WD_MODE wd_mode, NC_PARAMTYPE paramtype)
+{
+    struct nc_rpc_copy *rpc;
+
+    if (url_or_config_src && (url_or_config_src[0] != '<') && !isalpha(url_or_config_src[0])) {
+        ERR("<copy-config> source is neither a URL nor a config (XML).");
+        return NULL;
+    }
+
+    rpc = malloc(sizeof *rpc);
+    if (!rpc) {
+        ERRMEM;
+        return NULL;
+    }
+
+    rpc->type = NC_RPC_COPY;
+    rpc->target = target;
+    if (url_trg && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+        rpc->url_trg = strdup(url_trg);
+    } else {
+        rpc->url_trg = (char *)url_trg;
+    }
+    rpc->source = source;
+    if (url_or_config_src && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+        rpc->url_config_src = strdup(url_or_config_src);
+    } else {
+        rpc->url_config_src = (char *)url_or_config_src;
+    }
+    rpc->wd_mode = wd_mode;
+    rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
+
+    return (struct nc_rpc *)rpc;
+}
+
+API struct nc_rpc *
+nc_rpc_delete(NC_DATASTORE target, const char *url, NC_PARAMTYPE paramtype)
+{
+    struct nc_rpc_delete *rpc;
+
+    rpc = malloc(sizeof *rpc);
+    if (!rpc) {
+        ERRMEM;
+        return NULL;
+    }
+
+    rpc->type = NC_RPC_DELETE;
+    rpc->target = target;
+    if (url && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+        rpc->url = strdup(url);
+    } else {
+        rpc->url = (char *)url;
+    }
+    rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
+
+    return (struct nc_rpc *)rpc;
+}
+
+API struct nc_rpc *
+nc_rpc_lock(NC_DATASTORE target)
+{
+    struct nc_rpc_lock *rpc;
+
+    rpc = malloc(sizeof *rpc);
+    if (!rpc) {
+        ERRMEM;
+        return NULL;
+    }
+
+    rpc->type = NC_RPC_LOCK;
+    rpc->target = target;
+
+    return (struct nc_rpc *)rpc;
+}
+
+API struct nc_rpc *
+nc_rpc_unlock(NC_DATASTORE target)
+{
+    struct nc_rpc_lock *rpc;
+
+    rpc = malloc(sizeof *rpc);
+    if (!rpc) {
+        ERRMEM;
+        return NULL;
+    }
+
+    rpc->type = NC_RPC_UNLOCK;
+    rpc->target = target;
+
+    return (struct nc_rpc *)rpc;
+}
+
+API struct nc_rpc *
+nc_rpc_get(const char *filter, NC_WD_MODE wd_mode, NC_PARAMTYPE paramtype)
+{
+    struct nc_rpc_get *rpc;
+
+    if (filter && (filter[0] != '<') && (filter[0] != '/') && !isalpha(filter[0])) {
+        ERR("Filter must either be an XML subtree or an XPath expression.");
+        return NULL;
+    }
+
+    rpc = malloc(sizeof *rpc);
+    if (!rpc) {
+        ERRMEM;
+        return NULL;
+    }
+
+    rpc->type = NC_RPC_GET;
+    if (filter && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+        rpc->filter = strdup(filter);
+    } else {
+        rpc->filter = (char *)filter;
+    }
+    rpc->wd_mode = wd_mode;
+    rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
+
+    return (struct nc_rpc *)rpc;
+}
+
+API struct nc_rpc *
+nc_rpc_kill(uint32_t session_id)
+{
+    struct nc_rpc_kill *rpc;
+
+    rpc = malloc(sizeof *rpc);
+    if (!rpc) {
+        ERRMEM;
+        return NULL;
+    }
+
+    rpc->type = NC_RPC_KILL;
+    rpc->sid = session_id;
+
+    return (struct nc_rpc *)rpc;
+}
+
+API struct nc_rpc *
+nc_rpc_commit(int confirmed, uint32_t confirm_timeout, const char *persist, const char *persist_id,
+              NC_PARAMTYPE paramtype)
+{
+    struct nc_rpc_commit *rpc;
+
+    rpc = malloc(sizeof *rpc);
+    if (!rpc) {
+        ERRMEM;
+        return NULL;
+    }
+
+    rpc->type = NC_RPC_COMMIT;
+    rpc->confirmed = confirmed;
+    rpc->confirm_timeout = confirm_timeout;
+    if (persist && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+        rpc->persist = strdup(persist);
+    } else {
+        rpc->persist = (char *)persist;
+    }
+    if (persist_id && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+        rpc->persist_id = strdup(persist_id);
+    } else {
+        rpc->persist_id = (char *)persist_id;
+    }
+    rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
+
+    return (struct nc_rpc *)rpc;
+}
+
+API struct nc_rpc *
+nc_rpc_discard(void)
+{
+    struct nc_rpc *rpc;
+
+    rpc = malloc(sizeof *rpc);
+    if (!rpc) {
+        ERRMEM;
+        return NULL;
+    }
+
+    rpc->type = NC_RPC_DISCARD;
+
+    return rpc;
+}
+
+API struct nc_rpc *
+nc_rpc_cancel(const char *persist_id, NC_PARAMTYPE paramtype)
+{
+    struct nc_rpc_cancel *rpc;
+
+    rpc = malloc(sizeof *rpc);
+    if (!rpc) {
+        ERRMEM;
+        return NULL;
+    }
+
+    rpc->type = NC_RPC_CANCEL;
+    if (persist_id && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+        rpc->persist_id = strdup(persist_id);
+    } else {
+        rpc->persist_id = (char *)persist_id;
+    }
+    rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
+
+    return (struct nc_rpc *)rpc;
+}
+
+API struct nc_rpc *
+nc_rpc_validate(NC_DATASTORE source, const char *url_or_config, NC_PARAMTYPE paramtype)
+{
+    struct nc_rpc_validate *rpc;
+
+    if (url_or_config && (url_or_config[0] != '<') && !isalpha(url_or_config[0])) {
+        ERR("<validate> source is neither a URL nor a config (XML).");
+        return NULL;
+    }
+
+    rpc = malloc(sizeof *rpc);
+    if (!rpc) {
+        ERRMEM;
+        return NULL;
+    }
+
+    rpc->type = NC_RPC_VALIDATE;
+    rpc->source = source;
+    if (url_or_config && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+        rpc->url_config_src = strdup(url_or_config);
+    } else {
+        rpc->url_config_src = (char *)url_or_config;
+    }
+    rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
+
+    return (struct nc_rpc *)rpc;
+}
+
+API struct nc_rpc *
+nc_rpc_getschema(const char *identifier, const char *version, const char *format, NC_PARAMTYPE paramtype)
+{
+    struct nc_rpc_getschema *rpc;
+
+    rpc = malloc(sizeof *rpc);
+    if (!rpc) {
+        ERRMEM;
+        return NULL;
+    }
+
+    rpc->type = NC_RPC_GETSCHEMA;
+    if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
+        rpc->identifier = strdup(identifier);
+    } else {
+        rpc->identifier = (char *)identifier;
+    }
+    if (version && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+        rpc->version = strdup(version);
+    } else {
+        rpc->version = (char *)version;
+    }
+    if (format && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+        rpc->format = strdup(format);
+    } else {
+        rpc->format = (char *)format;
+    }
+    rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
+
+    return (struct nc_rpc *)rpc;
+}
+
+API struct nc_rpc *
+nc_rpc_subscribe(const char *stream_name, const char *filter, const char *start_time, const char *stop_time,
+                 NC_PARAMTYPE paramtype)
+{
+    struct nc_rpc_subscribe *rpc;
+
+    if (filter && (filter[0] != '<') && (filter[0] != '/') && !isalpha(filter[0])) {
+        ERR("Filter must either be an XML subtree or an XPath expression.");
+        return NULL;
+    }
+
+    rpc = malloc(sizeof *rpc);
+    if (!rpc) {
+        ERRMEM;
+        return NULL;
+    }
+
+    rpc->type = NC_RPC_SUBSCRIBE;
+    if (stream_name && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+        rpc->stream = strdup(stream_name);
+    } else {
+        rpc->stream = (char *)stream_name;
+    }
+    if (filter && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+        rpc->filter = strdup(filter);
+    } else {
+        rpc->filter = (char *)filter;
+    }
+    if (start_time && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+        rpc->start = strdup(start_time);
+    } else {
+        rpc->start = (char *)start_time;
+    }
+    if (stop_time && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+        rpc->stop = strdup(stop_time);
+    } else {
+        rpc->stop = (char *)stop_time;
+    }
+    rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
+
+    return (struct nc_rpc *)rpc;
+}
+
+API void
+nc_rpc_free(struct nc_rpc *rpc)
+{
+    struct nc_rpc_generic *rpc_generic;
+    struct nc_rpc_getconfig *rpc_getconfig;
+    struct nc_rpc_edit *rpc_edit;
+    struct nc_rpc_copy *rpc_copy;
+    struct nc_rpc_delete *rpc_delete;
+    struct nc_rpc_get *rpc_get;
+    struct nc_rpc_commit *rpc_commit;
+    struct nc_rpc_cancel *rpc_cancel;
+    struct nc_rpc_validate *rpc_validate;
+    struct nc_rpc_getschema *rpc_getschema;
+    struct nc_rpc_subscribe *rpc_subscribe;
+
+    if (!rpc) {
+        return;
+    }
+
+    switch (rpc->type) {
+    case NC_RPC_GENERIC:
+        rpc_generic = (struct nc_rpc_generic *)rpc;
+        if (rpc_generic->free) {
+            if (rpc_generic->has_data) {
+                lyd_free(rpc_generic->content.data);
+            } else {
+                free(rpc_generic->content.xml_str);
+            }
+        }
+        break;
+    case NC_RPC_GETCONFIG:
+        rpc_getconfig = (struct nc_rpc_getconfig *)rpc;
+        if (rpc_getconfig->free) {
+            free(rpc_getconfig->filter);
+        }
+        break;
+    case NC_RPC_EDIT:
+        rpc_edit = (struct nc_rpc_edit *)rpc;
+        if (rpc_edit->free) {
+            free(rpc_edit->edit_cont);
+        }
+        break;
+    case NC_RPC_COPY:
+        rpc_copy = (struct nc_rpc_copy *)rpc;
+        if (rpc_copy->free) {
+            free(rpc_copy->url_config_src);
+        }
+        break;
+    case NC_RPC_DELETE:
+        rpc_delete = (struct nc_rpc_delete *)rpc;
+        if (rpc_delete->free) {
+            free(rpc_delete->url);
+        }
+        break;
+    case NC_RPC_GET:
+        rpc_get = (struct nc_rpc_get *)rpc;
+        if (rpc_get->free) {
+            free(rpc_get->filter);
+        }
+        break;
+    case NC_RPC_COMMIT:
+        rpc_commit = (struct nc_rpc_commit *)rpc;
+        if (rpc_commit->free) {
+            free(rpc_commit->persist);
+            free(rpc_commit->persist_id);
+        }
+        break;
+    case NC_RPC_CANCEL:
+        rpc_cancel = (struct nc_rpc_cancel *)rpc;
+        if (rpc_cancel->free) {
+            free(rpc_cancel->persist_id);
+        }
+        break;
+    case NC_RPC_VALIDATE:
+        rpc_validate = (struct nc_rpc_validate *)rpc;
+        if (rpc_validate->free) {
+            free(rpc_validate->url_config_src);
+        }
+        break;
+    case NC_RPC_GETSCHEMA:
+        rpc_getschema = (struct nc_rpc_getschema *)rpc;
+        if (rpc_getschema->free) {
+            free(rpc_getschema->identifier);
+            free(rpc_getschema->version);
+            free(rpc_getschema->format);
+        }
+        break;
+    case NC_RPC_SUBSCRIBE:
+        rpc_subscribe = (struct nc_rpc_subscribe *)rpc;
+        if (rpc_subscribe->free) {
+            free(rpc_subscribe->stream);
+            free(rpc_subscribe->filter);
+            free(rpc_subscribe->start);
+            free(rpc_subscribe->stop);
+        }
+        break;
+    case NC_RPC_KILL:
+    case NC_RPC_DISCARD:
+    case NC_RPC_LOCK:
+    case NC_RPC_UNLOCK:
+        /* nothing special needed */
+        break;
+    }
+
+    free(rpc);
+}
+
+API void
+nc_reply_free(struct nc_reply *reply)
+{
+    struct nc_reply_error *error;
+    struct nc_reply_data *data;
+    uint32_t i, j;
+
+    if (!reply) {
+        return;
+    }
+
+    switch (reply->type) {
+    case NC_RPL_DATA:
+        data = (struct nc_reply_data *)reply;
+        lyd_free_withsiblings(data->data);
+        break;
+
+    case NC_RPL_OK:
+        /* nothing to free */
+        break;
+
+    case NC_RPL_ERROR:
+        error = (struct nc_reply_error *)reply;
+        for (i = 0; i < error->count; ++i) {
+            lydict_remove(error->ctx, error->err[i].type);
+            lydict_remove(error->ctx, error->err[i].tag);
+            lydict_remove(error->ctx, error->err[i].severity);
+            lydict_remove(error->ctx, error->err[i].apptag);
+            lydict_remove(error->ctx, error->err[i].path);
+            lydict_remove(error->ctx, error->err[i].message);
+            lydict_remove(error->ctx, error->err[i].message_lang);
+            lydict_remove(error->ctx, error->err[i].sid);
+            for (j = 0; j < error->err[i].attr_count; ++j) {
+                lydict_remove(error->ctx, error->err[i].attr[j]);
+            }
+            free(error->err[i].attr);
+            for (j = 0; j < error->err[i].elem_count; ++j) {
+                lydict_remove(error->ctx, error->err[i].elem[j]);
+            }
+            free(error->err[i].elem);
+            for (j = 0; j < error->err[i].ns_count; ++j) {
+                lydict_remove(error->ctx, error->err[i].ns[j]);
+            }
+            free(error->err[i].ns);
+            for (j = 0; j < error->err[i].other_count; ++j) {
+                lyxml_free(error->ctx, error->err[i].other[j]);
+            }
+            free(error->err[i].other);
+        }
+        free(error->err);
+        break;
+
+    case NC_RPL_NOTIF:
+        nc_notif_free((struct nc_notif *)reply);
+        break;
+    }
+
+    free(reply);
+}
diff --git a/src/messages_client.h b/src/messages_client.h
new file mode 100644
index 0000000..517eb3d
--- /dev/null
+++ b/src/messages_client.h
@@ -0,0 +1,440 @@
+/**
+ * \file messages_client.h
+ * \author Radek Krejci <rkrejci@cesnet.cz>
+ * \author Michal Vasko <mvasko@cesnet.cz>
+ * \brief libnetconf2's public functions and structures of NETCONF client messages.
+ *
+ * Copyright (c) 2015 CESNET, z.s.p.o.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of the Company nor the names of its contributors
+ *    may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ */
+
+#ifndef NC_MESSAGES_CLIENT_H_
+#define NC_MESSAGES_CLIENT_H_
+
+#include <stdint.h>
+
+#include "netconf.h"
+
+typedef enum {
+    NC_RPC_GENERIC,     /**< user-defined generic RPC. */
+
+    /* ietf-netconf */
+    NC_RPC_GETCONFIG,   /**< \<get-config\> RPC. */
+    NC_RPC_EDIT,        /**< \<edit-config\> RPC. */
+    NC_RPC_COPY,        /**< \<copy-config\> RPC. */
+    NC_RPC_DELETE,      /**< \<delete-config\> RPC. */
+    NC_RPC_LOCK,        /**< \<lock\> RPC. */
+    NC_RPC_UNLOCK,      /**< \<unlock\> RPC. */
+    NC_RPC_GET,         /**< \<get\> RPC. */
+    /* NC_RPC_CLOSE is not defined since sending \<close-session\> is done by nc_session_free() */
+    NC_RPC_KILL,        /**< \<kill-session\> RPC. */
+    NC_RPC_COMMIT,      /**< \<commit\> RPC. */
+    NC_RPC_DISCARD,     /**< \<discard-changes\> RPC. */
+    NC_RPC_CANCEL,      /**< \<cancel-commit\> RPC. */
+    NC_RPC_VALIDATE,    /**< \<validate\> RPC. */
+
+    /* ietf-netconf-monitoring */
+    NC_RPC_GETSCHEMA,   /**< \<get-schema\> RPC. */
+
+    /* notifications */
+    NC_RPC_SUBSCRIBE    /**< \<create-subscription\> RPC. */
+} NC_RPC_TYPE;
+
+typedef enum {
+    NC_RPC_EDIT_DFLTOP_UNKNOWN = 0,
+    NC_RPC_EDIT_DFLTOP_MERGE,
+    NC_RPC_EDIT_DFLTOP_REPLACE,
+    NC_RPC_EDIT_DFLTOP_NONE
+} NC_RPC_EDIT_DFLTOP;
+
+typedef enum {
+    NC_RPC_EDIT_TESTOPT_UNKNOWN = 0,
+    NC_RPC_EDIT_TESTOPT_TESTSET,
+    NC_RPC_EDIT_TESTOPT_SET,
+    NC_RPC_EDIT_TESTOPT_TEST
+} NC_RPC_EDIT_TESTOPT;
+
+typedef enum {
+    NC_RPC_EDIT_ERROPT_UNKNOWN = 0,
+    NC_RPC_EDIT_ERROPT_STOP,
+    NC_RPC_EDIT_ERROPT_CONTINUE,
+    NC_RPC_EDIT_ERROPT_ROLLBACK
+} NC_RPC_EDIT_ERROPT;
+
+/**
+ * @brief NETCONF error structure representation
+ */
+struct nc_err {
+    /**
+     * @brief \<error-type\>, error layer where the error occurred.
+     */
+    const char *type;
+    /**
+     * @brief \<error-tag\>.
+     */
+    const char *tag;
+    /**
+     * @brief \<error-severity\>.
+     */
+    const char *severity;
+    /**
+     * @brief \<error-app-tag\>, the data-model-specific or implementation-specific error condition, if one exists.
+     */
+    const char *apptag;
+    /**
+     * @brief \<error-path\>, XPATH expression identifying the element with the error.
+     */
+    const char *path;
+    /**
+     * @brief \<error-message\>, Human-readable description of the error.
+     */
+    const char *message;
+    const char *message_lang;
+
+    /* <error-info> */
+
+    /**
+     * @brief \<session-id\>, session ID of the session holding the requested lock.
+     */
+    const char *sid;
+    /**
+     * @brief \<bad-attr\>, the name of the data-model-specific XML attribute that caused the error.
+     */
+    const char **attr;
+    uint16_t attr_count;
+    /**
+     * @brief \<bad-element\>, the name of the data-model-specific XML element that caused the error.
+     */
+    const char **elem;
+    uint16_t elem_count;
+    /**
+     * @brief \<bad-namespace\>, the name of the unexpected XML namespace that caused the error.
+     */
+    const char **ns;
+    uint16_t ns_count;
+    /**
+     * @brief Remaining non-standard elements.
+     */
+    struct lyxml_elem **other;
+    uint16_t other_count;
+};
+
+/**
+ * @brief NETCONF client RPC object
+ */
+struct nc_rpc;
+
+struct nc_reply {
+    NC_RPL type;
+};
+
+struct nc_reply_data {
+    NC_RPL type;           /**< NC_RPL_DATA */
+    struct lyd_node *data; /**< libyang data tree */
+};
+
+struct nc_reply_error {
+    NC_RPL type;        /**< NC_RPL_ERROR */
+    struct ly_ctx *ctx;
+    struct nc_err *err; /**< errors, any of the values inside can be NULL */
+    uint32_t count;
+};
+
+struct nc_notif {
+    NC_RPL type;           /**< NC_RPL_NOTIF */
+    const char *datetime;  /**< eventTime of the notification */
+    struct lyd_node *tree; /**< libyang data tree of the message */
+};
+
+/**
+ * @brief Get the type of the RPC
+ *
+ * @param[in] rpc RPC to check the type of.
+ * @return Type of \p rpc.
+ */
+NC_RPC_TYPE nc_rpc_get_type(const struct nc_rpc *rpc);
+
+/**
+ * @brief Create a generic NETCONF RPC
+ *
+ * Note that created object can be sent via any NETCONF session that shares the context
+ * of the \p data.
+ *
+ * @param[in] data NETCONF RPC data as a data tree.
+ * @param[in] paramtype How to further manage data parameters.
+ * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
+ */
+struct nc_rpc *nc_rpc_generic(const struct lyd_node *data, NC_PARAMTYPE paramtype);
+
+/**
+ * @brief Create a generic NETCONF RPC from an XML string
+ *
+ * Note that functions to create any RPC object do not check validity of the provided
+ * parameters. It is checked later while sending the RPC via a specific NETCONF session
+ * (nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
+ * check. Created object can be sent via any NETCONF session which supports all the
+ * needed NETCONF capabilities for the RPC.
+ *
+ * @param[in] xml_str NETCONF RPC data as an XML string.
+ * @param[in] paramtype How to further manage data parameters.
+ * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
+ */
+struct nc_rpc *nc_rpc_generic_xml(const char *xml_str, NC_PARAMTYPE paramtype);
+
+/**
+ * @brief Create NETCONF RPC \<get-config\>
+ *
+ * Note that functions to create any RPC object do not check validity of the provided
+ * parameters. It is checked later while sending the RPC via a specific NETCONF session
+ * (nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
+ * check. Created object can be sent via any NETCONF session which supports all the
+ * needed NETCONF capabilities for the RPC.
+ *
+ * @param[in] source Source datastore being queried.
+ * @param[in] filter Optional filter data, an XML subtree or XPath expression.
+ * @param[in] wd_mode Optional with-defaults capability mode.
+ * @param[in] paramtype How to further manage data parameters.
+ * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
+ */
+struct nc_rpc *nc_rpc_getconfig(NC_DATASTORE source, const char *filter, NC_WD_MODE wd_mode,
+                                NC_PARAMTYPE paramtype);
+
+/**
+ * @brief Create NETCONF RPC \<edit-config\>
+ *
+ * Note that functions to create any RPC object do not check validity of the provided
+ * parameters. It is checked later while sending the RPC via a specific NETCONF session
+ * (nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
+ * check. Created object can be sent via any NETCONF session which supports all the
+ * needed NETCONF capabilities for the RPC.
+ *
+ * @param[in] target Target datastore being edited.
+ * @param[in] default_op Optional default operation.
+ * @param[in] test_opt Optional test option.
+ * @param[in] error_opt Optional error option.
+ * @param[in] edit_content Config or URL where the config to perform is to be found.
+ * @param[in] paramtype How to further manage data parameters.
+ * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
+ */
+struct nc_rpc *nc_rpc_edit(NC_DATASTORE target, NC_RPC_EDIT_DFLTOP default_op, NC_RPC_EDIT_TESTOPT test_opt,
+                           NC_RPC_EDIT_ERROPT error_opt, const char *edit_content, NC_PARAMTYPE paramtype);
+
+/**
+ * @brief Create NETCONF RPC \<copy-config\>
+ *
+ * Note that functions to create any RPC object do not check validity of the provided
+ * parameters. It is checked later while sending the RPC via a specific NETCONF session
+ * (nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
+ * check. Created object can be sent via any NETCONF session which supports all the
+ * needed NETCONF capabilities for the RPC.
+ *
+ * @param[in] target Target datastore.
+ * @param[in] url_trg Used instead \p target if the target is an URL.
+ * @param[in] source Source datastore.
+ * @param[in] url_or_config_src Used instead \p source if the source is an URL or a config.
+ * @param[in] wd_mode Optional with-defaults capability mode.
+ * @param[in] paramtype How to further manage data parameters.
+ * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
+ */
+struct nc_rpc *nc_rpc_copy(NC_DATASTORE target, const char *url_trg, NC_DATASTORE source,
+                           const char *url_or_config_src, NC_WD_MODE wd_mode, NC_PARAMTYPE paramtype);
+
+/**
+ * @brief Create NETCONF RPC \<delete-config\>
+ *
+ * Note that functions to create any RPC object do not check validity of the provided
+ * parameters. It is checked later while sending the RPC via a specific NETCONF session
+ * (nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
+ * check. Created object can be sent via any NETCONF session which supports all the
+ * needed NETCONF capabilities for the RPC.
+ *
+ * @param[in] target Target datastore to delete.
+ * @param[in] url Used instead \p target if the target is an URL.
+ * @param[in] paramtype How to further manage data parameters.
+ * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
+ */
+struct nc_rpc *nc_rpc_delete(NC_DATASTORE target, const char *url, NC_PARAMTYPE paramtype);
+
+/**
+ * @brief Create NETCONF RPC \<lock\>
+ *
+ * Note that functions to create any RPC object do not check validity of the provided
+ * parameters. It is checked later while sending the RPC via a specific NETCONF session
+ * (nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
+ * check. Created object can be sent via any NETCONF session which supports all the
+ * needed NETCONF capabilities for the RPC.
+ *
+ * @param[in] target Target datastore of the operation.
+ * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
+ */
+struct nc_rpc *nc_rpc_lock(NC_DATASTORE target);
+
+/**
+ * @brief Create NETCONF RPC \<unlock\>
+ *
+ * Note that functions to create any RPC object do not check validity of the provided
+ * parameters. It is checked later while sending the RPC via a specific NETCONF session
+ * (nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
+ * check. Created object can be sent via any NETCONF session which supports all the
+ * needed NETCONF capabilities for the RPC.
+ *
+ * @param[in] target Target datastore of the operation.
+ * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
+ */
+struct nc_rpc *nc_rpc_unlock(NC_DATASTORE target);
+
+/**
+ * @brief Create NETCONF RPC \<get\>
+ *
+ * Note that functions to create any RPC object do not check validity of the provided
+ * parameters. It is checked later while sending the RPC via a specific NETCONF session
+ * (nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
+ * check. Created object can be sent via any NETCONF session which supports all the
+ * needed NETCONF capabilities for the RPC.
+ *
+ * @param[in] filter Optional filter data, an XML subtree or XPath expression.
+ * @param[in] wd_mode Optional with-defaults capability mode.
+ * @param[in] paramtype How to further manage data parameters.
+ * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
+ */
+struct nc_rpc *nc_rpc_get(const char *filter, NC_WD_MODE wd_mode, NC_PARAMTYPE paramtype);
+
+/**
+ * @brief Create NETCONF RPC \<kill-session\>
+ *
+ * Note that functions to create any RPC object do not check validity of the provided
+ * parameters. It is checked later while sending the RPC via a specific NETCONF session
+ * (nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
+ * check. Created object can be sent via any NETCONF session which supports all the
+ * needed NETCONF capabilities for the RPC.
+ *
+ * @param[in] session_id Session ID of the session to kill.
+ * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
+ */
+struct nc_rpc *nc_rpc_kill(uint32_t session_id);
+
+/**
+ * @brief Create NETCONF RPC \<commit\>
+ *
+ * Note that functions to create any RPC object do not check validity of the provided
+ * parameters. It is checked later while sending the RPC via a specific NETCONF session
+ * (nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
+ * check. Created object can be sent via any NETCONF session which supports all the
+ * needed NETCONF capabilities for the RPC.
+ *
+ * @param[in] confirmed Whether the commit is to be confirmed.
+ * @param[in] confirm_timeout Optional confirm timeout.
+ * @param[in] persist Optional identification string of a new persistent confirmed commit.
+ * @param[in] persist_id Optional identification string of a persistent confirmed commit to be commited.
+ * @param[in] paramtype How to further manage data parameters.
+ * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
+ */
+struct nc_rpc *nc_rpc_commit(int confirmed, uint32_t confirm_timeout, const char *persist, const char *persist_id,
+                             NC_PARAMTYPE paramtype);
+
+/**
+ * @brief Create NETCONF RPC \<discard-changes\>
+ *
+ * Note that functions to create any RPC object do not check validity of the provided
+ * parameters. It is checked later while sending the RPC via a specific NETCONF session
+ * (nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
+ * check. Created object can be sent via any NETCONF session which supports all the
+ * needed NETCONF capabilities for the RPC.
+ *
+ * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
+ */
+struct nc_rpc *nc_rpc_discard(void);
+
+/**
+ * @brief Create NETCONF RPC \<cancel-commit\>
+ *
+ * Note that functions to create any RPC object do not check validity of the provided
+ * parameters. It is checked later while sending the RPC via a specific NETCONF session
+ * (nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
+ * check. Created object can be sent via any NETCONF session which supports all the
+ * needed NETCONF capabilities for the RPC.
+ *
+ * @param[in] persist_id Optional identification string of a persistent confirmed commit.
+ * @param[in] paramtype How to further manage data parameters.
+ * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
+ */
+struct nc_rpc *nc_rpc_cancel(const char *persist_id, NC_PARAMTYPE paramtype);
+
+/**
+ * @brief Create NETCONF RPC \<validate\>
+ *
+ * Note that functions to create any RPC object do not check validity of the provided
+ * parameters. It is checked later while sending the RPC via a specific NETCONF session
+ * (nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
+ * check. Created object can be sent via any NETCONF session which supports all the
+ * needed NETCONF capabilities for the RPC.
+ *
+ * @param[in] source Source datastore being validated.
+ * @param[in] url_or_config Usedn instead \p source if the source is an URL or a config.
+ * @param[in] paramtype How to further manage data parameters.
+ * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
+ */
+struct nc_rpc *nc_rpc_validate(NC_DATASTORE source, const char *url_or_config, NC_PARAMTYPE paramtype);
+
+/**
+ * @brief Create NETCONF RPC \<get-schema\>
+ *
+ * Note that functions to create any RPC object do not check validity of the provided
+ * parameters. It is checked later while sending the RPC via a specific NETCONF session
+ * (nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
+ * check. Created object can be sent via any NETCONF session which supports all the
+ * needed NETCONF capabilities for the RPC.
+ *
+ * @param[in] identifier Requested model identifier.
+ * @param[in] version Optional model version, either YANG version (1.0/1.1) or revision date.
+ * @param[in] format Optional format of the model (default is YANG).
+ * @param[in] paramtype How to further manage data parameters.
+ * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
+ */
+struct nc_rpc *nc_rpc_getschema(const char *identifier, const char *version, const char *format, NC_PARAMTYPE paramtype);
+
+/**
+ * @brief Create NETCONF RPC \<create-subscription\>
+ *
+ * Note that functions to create any RPC object do not check validity of the provided
+ * parameters. It is checked later while sending the RPC via a specific NETCONF session
+ * (nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
+ * check. Created object can be sent via any NETCONF session which supports all the
+ * needed NETCONF capabilities for the RPC.
+ *
+ * @param[in] stream_name Optional name of a NETCONF stream to subscribe to.
+ * @param[in] filter Optional filter data, an XML subtree or XPath expression.
+ * @param[in] start_time Optional YANG datetime identifying the start of the subscription.
+ * @param[in] stop_time Optional YANG datetime identifying the end of the subscription.
+ * @param[in] paramtype How to further manage data parameters.
+ * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
+ */
+struct nc_rpc *nc_rpc_subscribe(const char *stream_name, const char *filter, const char *start_time,
+								const char *stop_time, NC_PARAMTYPE paramtype);
+
+/**
+ * @brief Free the NETCONF RPC object.
+ * @param[in] rpc Object to free.
+ */
+void nc_rpc_free(struct nc_rpc *rpc);
+
+/**
+ * @brief Free the NETCONF RPC reply object.
+ * @param[in] rpc Object to free.
+ */
+void nc_reply_free(struct nc_reply *reply);
+
+#endif /* NC_MESSAGES_CLIENT_H_ */
diff --git a/src/messages_p.h b/src/messages_p.h
index 7aef57b..a5c690e 100644
--- a/src/messages_p.h
+++ b/src/messages_p.h
@@ -26,6 +26,8 @@
 #include <libyang/libyang.h>
 
 #include "messages.h"
+#include "messages_server.h"
+#include "messages_client.h"
 
 extern const char *rpcedit_dfltop2str[];
 extern const char *rpcedit_testopt2str[];
diff --git a/src/messages_server.c b/src/messages_server.c
new file mode 100644
index 0000000..0467483
--- /dev/null
+++ b/src/messages_server.c
@@ -0,0 +1,494 @@
+/**
+ * \file messages_server.c
+ * \author Michal Vasko <mvasko@cesnet.cz>
+ * \brief libnetconf2 - server NETCONF messages functions
+ *
+ * Copyright (c) 2015 CESNET, z.s.p.o.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of the Company nor the names of its contributors
+ *    may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include <libyang/libyang.h>
+
+#include "libnetconf.h"
+#include "messages_p.h"
+
+API struct nc_server_reply *
+nc_server_reply_ok(void)
+{
+    struct nc_server_reply *ret;
+
+    ret = malloc(sizeof *ret);
+    if (!ret) {
+        ERRMEM;
+        return NULL;
+    }
+
+    ret->type = NC_RPL_OK;
+    return ret;
+}
+
+API struct nc_server_reply *
+nc_server_reply_data(struct lyd_node *data, NC_PARAMTYPE paramtype)
+{
+    struct nc_server_reply_data *ret;
+
+    if (!data) {
+        ERRARG;
+        return NULL;
+    }
+
+    ret = malloc(sizeof *ret);
+    if (!ret) {
+        ERRMEM;
+        return NULL;
+    }
+
+    ret->type = NC_RPL_DATA;
+    if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
+        ret->data = lyd_dup(data, 1);
+    } else {
+        ret->data = data;
+    }
+    if (paramtype != NC_PARAMTYPE_CONST) {
+        ret->free = 1;
+    } else {
+        ret->free = 0;
+    }
+    return (struct nc_server_reply *)ret;
+}
+
+API struct nc_server_reply *
+nc_server_reply_err(struct ly_ctx *ctx, struct nc_server_error *err)
+{
+    struct nc_server_reply_error *ret;
+
+    if (!ctx || !err) {
+        ERRARG;
+        return NULL;
+    }
+
+    ret = malloc(sizeof *ret);
+    if (!ret) {
+        ERRMEM;
+        return NULL;
+    }
+
+    ret->type = NC_RPL_ERROR;
+    ret->ctx = ctx;
+    ret->err = malloc(sizeof *ret->err);
+    ret->err[0] = err;
+    ret->count = 1;
+    return (struct nc_server_reply *)ret;
+}
+
+API int
+nc_server_reply_add_err(struct nc_server_reply *reply, struct nc_server_error *err)
+{
+    struct nc_server_reply_error *err_rpl;
+
+    if (!reply || (reply->type != NC_RPL_ERROR) || !err) {
+        ERRARG;
+        return -1;
+    }
+
+    err_rpl = (struct nc_server_reply_error *)reply;
+    ++err_rpl->count;
+    err_rpl->err = realloc(err_rpl->err, err_rpl->count * sizeof *err_rpl->err);
+    err_rpl->err[err_rpl->count - 1] = err;
+    return 0;
+}
+
+API struct nc_server_error *
+nc_err(struct ly_ctx *ctx, NC_ERR tag, ...)
+{
+    va_list ap;
+    struct nc_server_error *ret;
+    NC_ERR_TYPE type;
+    const char *arg1, *arg2;
+    uint32_t sid;
+
+    if (!ctx || !tag) {
+        ERRARG;
+        return NULL;
+    }
+
+    ret = calloc(1, sizeof *ret);
+    if (!ret) {
+        ERRMEM;
+        return NULL;
+    }
+
+    va_start(ap, tag);
+
+    switch (tag) {
+    case NC_ERR_IN_USE:
+    case NC_ERR_INVALID_VALUE:
+    case NC_ERR_ACCESS_DENIED:
+    case NC_ERR_ROLLBACK_FAILED:
+    case NC_ERR_OP_NOT_SUPPORTED:
+        type = va_arg(ap, NC_ERR_TYPE);
+        if ((type != NC_ERR_TYPE_PROT) && (type == NC_ERR_TYPE_APP)) {
+            goto fail;
+        }
+        break;
+
+    case NC_ERR_TOO_BIG:
+    case NC_ERR_RES_DENIED:
+        type = va_arg(ap, NC_ERR_TYPE);
+        /* nothing to check */
+        break;
+
+    case NC_ERR_MISSING_ATTR:
+    case NC_ERR_BAD_ATTR:
+    case NC_ERR_UNKNOWN_ATTR:
+        type = va_arg(ap, NC_ERR_TYPE);
+        arg1 = va_arg(ap, const char *);
+        arg2 = va_arg(ap, const char *);
+
+        if (type == NC_ERR_TYPE_TRAN) {
+            goto fail;
+        }
+        nc_err_add_bad_attr(ctx, ret, arg1);
+        nc_err_add_bad_elem(ctx, ret, arg2);
+        break;
+
+    case NC_ERR_MISSING_ELEM:
+    case NC_ERR_BAD_ELEM:
+    case NC_ERR_UNKNOWN_ELEM:
+        type = va_arg(ap, NC_ERR_TYPE);
+        arg1 = va_arg(ap, const char *);
+
+        if ((type != NC_ERR_TYPE_PROT) && (type != NC_ERR_TYPE_APP)) {
+            goto fail;
+        }
+        nc_err_add_bad_elem(ctx, ret, arg1);
+        break;
+
+    case NC_ERR_UNKNOWN_NS:
+        type = va_arg(ap, NC_ERR_TYPE);
+        arg1 = va_arg(ap, const char *);
+        arg2 = va_arg(ap, const char *);
+
+        if ((type != NC_ERR_TYPE_PROT) && (type != NC_ERR_TYPE_APP)) {
+            goto fail;
+        }
+        nc_err_add_bad_elem(ctx, ret, arg1);
+        nc_err_add_bad_ns(ctx, ret, arg2);
+        break;
+
+    case NC_ERR_LOCK_DENIED:
+        sid = va_arg(ap, uint32_t);
+
+        type = NC_ERR_TYPE_PROT;
+        nc_err_set_sid(ret, sid);
+        break;
+
+    case NC_ERR_DATA_EXISTS:
+    case NC_ERR_DATA_MISSING:
+        type = NC_ERR_TYPE_APP;
+        break;
+
+    case NC_ERR_OP_FAILED:
+        type = va_arg(ap, NC_ERR_TYPE);
+
+        if (type == NC_ERR_TYPE_TRAN) {
+            goto fail;
+        }
+        break;
+
+    case NC_ERR_MALFORMED_MSG:
+        type = NC_ERR_TYPE_RPC;
+        break;
+
+    default:
+        goto fail;
+    }
+
+    switch (tag) {
+    case NC_ERR_IN_USE:
+        nc_err_set_msg(ctx, ret, "The request requires a resource that already is in use.", "en");
+        break;
+    case NC_ERR_INVALID_VALUE:
+        nc_err_set_msg(ctx, ret, "The request specifies an unacceptable value for one or more parameters.", "en");
+        break;
+    case NC_ERR_TOO_BIG:
+        nc_err_set_msg(ctx, ret, "The request or response (that would be generated) is too large for the implementation to handle.", "en");
+        break;
+    case NC_ERR_MISSING_ATTR:
+        nc_err_set_msg(ctx, ret, "An expected attribute is missing.", "en");
+        break;
+    case NC_ERR_BAD_ATTR:
+        nc_err_set_msg(ctx, ret, "An attribute value is not correct.", "en");
+        break;
+    case NC_ERR_UNKNOWN_ATTR:
+        nc_err_set_msg(ctx, ret, "An unexpected attribute is present.", "en");
+        break;
+    case NC_ERR_MISSING_ELEM:
+        nc_err_set_msg(ctx, ret, "An expected element is missing.", "en");
+        break;
+    case NC_ERR_BAD_ELEM:
+        nc_err_set_msg(ctx, ret, "An element value is not correct.", "en");
+        break;
+    case NC_ERR_UNKNOWN_ELEM:
+        nc_err_set_msg(ctx, ret, "An unexpected element is present.", "en");
+        break;
+    case NC_ERR_UNKNOWN_NS:
+        nc_err_set_msg(ctx, ret, "An unexpected namespace is present.", "en");
+        break;
+    case NC_ERR_ACCESS_DENIED:
+        nc_err_set_msg(ctx, ret, "Access to the requested protocol operation or data model is denied because authorization failed.", "en");
+        break;
+    case NC_ERR_LOCK_DENIED:
+        nc_err_set_msg(ctx, ret, "Access to the requested lock is denied because the lock is currently held by another entity.", "en");
+        break;
+    case NC_ERR_RES_DENIED:
+        nc_err_set_msg(ctx, ret, "Request could not be completed because of insufficient resources.", "en");
+        break;
+    case NC_ERR_ROLLBACK_FAILED:
+        nc_err_set_msg(ctx, ret, "Request to roll back some configuration change was not completed for some reason.", "en");
+        break;
+    case NC_ERR_DATA_EXISTS:
+        nc_err_set_msg(ctx, ret, "Request could not be completed because the relevant data model content already exists.", "en");
+        break;
+    case NC_ERR_DATA_MISSING:
+        nc_err_set_msg(ctx, ret, "Request could not be completed because the relevant data model content does not exist.", "en");
+        break;
+    case NC_ERR_OP_NOT_SUPPORTED:
+        nc_err_set_msg(ctx, ret, "Request could not be completed because the requested operation is not supported by this implementation.", "en");
+        break;
+    case NC_ERR_OP_FAILED:
+        nc_err_set_msg(ctx, ret, "Request could not be completed because the requested operation failed for a non-specific reason.", "en");
+        break;
+    case NC_ERR_MALFORMED_MSG:
+        nc_err_set_msg(ctx, ret, "A message could not be handled because it failed to be parsed correctly.", "en");
+        break;
+    default:
+        goto fail;
+    }
+
+    va_end(ap);
+
+    ret->type = type;
+    ret->tag = tag;
+    return ret;
+
+fail:
+    ERRARG;
+    free(ret);
+    return NULL;
+}
+
+API int
+nc_err_set_app_tag(struct ly_ctx *ctx, struct nc_server_error *err, const char *error_app_tag)
+{
+    if (!ctx || !err || !error_app_tag) {
+        ERRARG;
+        return -1;
+    }
+
+    if (err->apptag) {
+        lydict_remove(ctx, err->apptag);
+    }
+    err->apptag = lydict_insert(ctx, error_app_tag, 0);
+    return 0;
+}
+
+API int
+nc_err_set_path(struct ly_ctx *ctx, struct nc_server_error *err, const char *error_path)
+{
+    if (!ctx || !err || !error_path) {
+        ERRARG;
+        return -1;
+    }
+
+    if (err->path) {
+        lydict_remove(ctx, err->path);
+    }
+    err->path = lydict_insert(ctx, error_path, 0);
+    return 0;
+}
+
+API int
+nc_err_set_msg(struct ly_ctx *ctx, struct nc_server_error *err, const char *error_message, const char *lang)
+{
+    if (!ctx || !err || !error_message) {
+        ERRARG;
+        return -1;
+    }
+
+    if (err->message) {
+        lydict_remove(ctx, err->apptag);
+    }
+    err->message = lydict_insert(ctx, error_message, 0);
+
+    if (err->message_lang) {
+        lydict_remove(ctx, err->message_lang);
+    }
+    if (lang) {
+        err->message_lang = lydict_insert(ctx, lang, 0);
+    } else {
+        lang = NULL;
+    }
+    return 0;
+}
+
+API int
+nc_err_set_sid(struct nc_server_error *err, uint32_t session_id)
+{
+    if (!err || !session_id) {
+        ERRARG;
+        return -1;
+    }
+
+    err->sid = session_id;
+    return 0;
+}
+
+API int
+nc_err_add_bad_attr(struct ly_ctx *ctx, struct nc_server_error *err, const char *attr_name)
+{
+    if (!ctx || !err || !attr_name) {
+        ERRARG;
+        return -1;
+    }
+
+    ++err->attr_count;
+    err->attr = realloc(err->attr, err->attr_count * sizeof *err->attr);
+    err->attr[err->attr_count - 1] = lydict_insert(ctx, attr_name, 0);
+    return 0;
+}
+
+API int
+nc_err_add_bad_elem(struct ly_ctx *ctx, struct nc_server_error *err, const char *elem_name)
+{
+    if (!ctx || !err || !elem_name) {
+        ERRARG;
+        return -1;
+    }
+
+    ++err->elem_count;
+    err->elem = realloc(err->elem, err->elem_count * sizeof *err->elem);
+    err->elem[err->elem_count - 1] = lydict_insert(ctx, elem_name, 0);
+    return 0;
+}
+
+API int
+nc_err_add_bad_ns(struct ly_ctx *ctx, struct nc_server_error *err, const char *ns_name)
+{
+    if (!ctx || !err || !ns_name) {
+        ERRARG;
+        return -1;
+    }
+
+    ++err->ns_count;
+    err->ns = realloc(err->ns, err->ns_count * sizeof *err->ns);
+    err->ns[err->ns_count - 1] = lydict_insert(ctx, ns_name, 0);
+    return 0;
+}
+
+API int
+nc_err_add_info_other(struct nc_server_error *err, struct lyxml_elem *other)
+{
+    if (!err || !other) {
+        ERRARG;
+        return -1;
+    }
+
+    ++err->other_count;
+    err->other = realloc(err->other, err->other_count * sizeof *err->other);
+    err->other[err->other_count - 1] = other;
+    return 0;
+}
+
+void
+nc_server_rpc_free(struct nc_server_rpc *rpc)
+{
+    lyxml_free(rpc->tree->schema->module->ctx, rpc->root);
+    lyd_free(rpc->tree);
+    free(rpc);
+}
+
+API void
+nc_server_reply_free(struct nc_server_reply *reply)
+{
+    uint32_t i;
+    struct nc_server_reply_data *data_rpl;
+    struct nc_server_reply_error *error_rpl;
+
+    if (!reply) {
+        return;
+    }
+
+    switch (reply->type) {
+    case NC_RPL_DATA:
+        data_rpl = (struct nc_server_reply_data *)reply;
+        if (data_rpl->free) {
+            lyd_free_withsiblings(data_rpl->data);
+        }
+        break;
+    case NC_RPL_OK:
+        /* nothing to free */
+        break;
+    case NC_RPL_ERROR:
+        error_rpl = (struct nc_server_reply_error *)reply;
+        for (i = 0; i < error_rpl->count; ++i) {
+            nc_err_free(error_rpl->ctx, error_rpl->err[i]);
+        }
+        free(error_rpl->err);
+        break;
+    default:
+        break;
+    }
+    free(reply);
+}
+
+API void
+nc_err_free(struct ly_ctx *ctx, struct nc_server_error *err)
+{
+    uint32_t i;
+
+    if (!err) {
+        ERRARG;
+        return;
+    }
+
+    lydict_remove(ctx, err->apptag);
+    lydict_remove(ctx, err->path);
+    lydict_remove(ctx, err->message);
+    lydict_remove(ctx, err->message_lang);
+    for (i = 0; i < err->attr_count; ++i) {
+        lydict_remove(ctx, err->attr[i]);
+    }
+    free(err->attr);
+    for (i = 0; i < err->elem_count; ++i) {
+        lydict_remove(ctx, err->elem[i]);
+    }
+    free(err->elem);
+    for (i = 0; i < err->ns_count; ++i) {
+        lydict_remove(ctx, err->ns[i]);
+    }
+    free(err->ns);
+    for (i = 0; i < err->other_count; ++i) {
+        lyxml_free(ctx, err->other[i]);
+    }
+    free(err->other);
+    free(err);
+}
diff --git a/src/messages_server.h b/src/messages_server.h
new file mode 100644
index 0000000..017ea63
--- /dev/null
+++ b/src/messages_server.h
@@ -0,0 +1,98 @@
+/**
+ * \file messages_server.h
+ * \author Michal Vasko <mvasko@cesnet.cz>
+ * \brief libnetconf2's functions and structures of server NETCONF messages.
+ *
+ * Copyright (c) 2015 CESNET, z.s.p.o.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of the Company nor the names of its contributors
+ *    may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ */
+
+#ifndef NC_MESSAGES_SERVER_H_
+#define NC_MESSAGES_SERVER_H_
+
+#include <stdint.h>
+
+#include "netconf.h"
+
+typedef enum {
+    NC_ERR_UNKNOWN = 0,
+    NC_ERR_IN_USE,
+    NC_ERR_INVALID_VALUE,
+    NC_ERR_TOO_BIG,
+    NC_ERR_MISSING_ATTR,
+    NC_ERR_BAD_ATTR,
+    NC_ERR_UNKNOWN_ATTR,
+    NC_ERR_MISSING_ELEM,
+    NC_ERR_BAD_ELEM,
+    NC_ERR_UNKNOWN_ELEM,
+    NC_ERR_UNKNOWN_NS,
+    NC_ERR_ACCESS_DENIED,
+    NC_ERR_LOCK_DENIED,
+    NC_ERR_RES_DENIED,
+    NC_ERR_ROLLBACK_FAILED,
+    NC_ERR_DATA_EXISTS,
+    NC_ERR_DATA_MISSING,
+    NC_ERR_OP_NOT_SUPPORTED,
+    NC_ERR_OP_FAILED,
+    NC_ERR_MALFORMED_MSG
+} NC_ERR;
+
+typedef enum {
+    NC_ERR_TYPE_UNKNOWN = 0,
+    NC_ERR_TYPE_TRAN,
+    NC_ERR_TYPE_RPC,
+    NC_ERR_TYPE_PROT,
+    NC_ERR_TYPE_APP
+} NC_ERR_TYPE;
+
+/**
+ * @brief NETCONF server RPC reply object
+ */
+struct nc_server_reply;
+
+struct nc_server_error;
+
+struct nc_server_reply *nc_server_reply_ok(void);
+
+struct nc_server_reply *nc_server_reply_data(struct lyd_node *data, NC_PARAMTYPE paramtype);
+
+struct nc_server_reply *nc_server_reply_err(struct ly_ctx *ctx, struct nc_server_error *err);
+
+int nc_server_reply_add_err(struct nc_server_reply *reply, struct nc_server_error *err);
+
+struct nc_server_error *nc_err(struct ly_ctx *ctx, NC_ERR tag, ...);
+
+int nc_err_set_app_tag(struct ly_ctx *ctx, struct nc_server_error *err, const char *error_app_tag);
+
+int nc_err_set_path(struct ly_ctx *ctx, struct nc_server_error *err, const char *error_path);
+
+int nc_err_set_msg(struct ly_ctx *ctx, struct nc_server_error *err, const char *error_message, const char *lang);
+
+int nc_err_set_sid(struct nc_server_error *err, uint32_t session_id);
+
+int nc_err_add_bad_attr(struct ly_ctx *ctx, struct nc_server_error *err, const char *attr_name);
+
+int nc_err_add_bad_elem(struct ly_ctx *ctx, struct nc_server_error *err, const char *elem_name);
+
+int nc_err_add_bad_ns(struct ly_ctx *ctx, struct nc_server_error *err, const char *ns_name);
+
+int nc_err_add_info_other(struct nc_server_error *err, struct lyxml_elem *other);
+
+void nc_server_reply_free(struct nc_server_reply *reply);
+
+void nc_err_free(struct ly_ctx *ctx, struct nc_server_error *err);
+
+#endif /* NC_MESSAGES_SERVER_H_ */
diff --git a/src/netconf.h b/src/netconf.h
index b9cca31..c15d0ec 100644
--- a/src/netconf.h
+++ b/src/netconf.h
@@ -83,6 +83,14 @@
     NC_DATASTORE_CANDIDATE /**< separated working datastore as defined in Candidate Configuration Capability */
 } NC_DATASTORE;
 
+typedef enum NC_WITHDEFAULTS_MODE {
+    NC_WD_UNKNOWN = 0,
+    NC_WD_ALL = 0x01,
+    NC_WD_ALL_TAG = 0x02,
+    NC_WD_TRIM = 0x04,
+    NC_WD_EXPLICIT = 0x08
+} NC_WD_MODE;
+
 /**
  * @brief Transform given time_t (seconds since the epoch) into the RFC 3339 format
  * accepted by NETCONF functions.
diff --git a/src/session_client.c b/src/session_client.c
index 71cd067..5f4fe1e 100644
--- a/src/session_client.c
+++ b/src/session_client.c
@@ -39,6 +39,7 @@
 #include "session_client.h"
 #include "libnetconf.h"
 #include "messages_p.h"
+#include "messages_client.h"
 
 static char *schema_searchpath = NULL;
 
diff --git a/src/session_client.h b/src/session_client.h
index 16a6c3b..f30403e 100644
--- a/src/session_client.h
+++ b/src/session_client.h
@@ -40,6 +40,7 @@
 #include "session.h"
 #include "netconf.h"
 #include "messages.h"
+#include "messages_client.h"
 
 /**
  * @brief Set location where libnetconf tries to search for YANG/YIN schemas.
diff --git a/src/session_p.h b/src/session_p.h
index 466bfbd..ef8de16 100644
--- a/src/session_p.h
+++ b/src/session_p.h
@@ -27,7 +27,9 @@
 #include <pthread.h>
 
 #include <libyang/libyang.h>
+
 #include "libnetconf.h"
+#include "netconf.h"
 #include "session.h"
 #include "messages.h"