blob: 0a3894c96f9720e23c1fc81778322014acb7d6b8 [file] [log] [blame]
Michal Vasko7bcb48e2016-01-15 10:28:54 +01001/**
Michal Vasko95ea9ff2021-11-09 12:29:14 +01002 * @file messages_server.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief libnetconf2 - server NETCONF messages functions
Michal Vasko7bcb48e2016-01-15 10:28:54 +01005 *
Michal Vasko95ea9ff2021-11-09 12:29:14 +01006 * @copyright
Michal Vasko7bcb48e2016-01-15 10:28:54 +01007 * Copyright (c) 2015 CESNET, z.s.p.o.
8 *
Radek Krejci9b81f5b2016-02-24 13:14:49 +01009 * This source code is licensed under BSD 3-Clause License (the "License").
10 * You may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
Michal Vaskoafd416b2016-02-25 14:51:46 +010012 *
Radek Krejci9b81f5b2016-02-24 13:14:49 +010013 * https://opensource.org/licenses/BSD-3-Clause
Michal Vasko7bcb48e2016-01-15 10:28:54 +010014 */
15
16#include <ctype.h>
Michal Vaskob83a3fa2021-05-26 09:53:42 +020017#include <inttypes.h>
18#include <stdarg.h>
Michal Vasko7bcb48e2016-01-15 10:28:54 +010019#include <stdlib.h>
20#include <string.h>
Michal Vasko7bcb48e2016-01-15 10:28:54 +010021
22#include <libyang/libyang.h>
23
Michal Vasko9e8ac262020-04-07 13:06:45 +020024#include "compat.h"
Michal Vasko7bcb48e2016-01-15 10:28:54 +010025#include "libnetconf.h"
Radek Krejci93e80222016-10-03 13:34:25 +020026#include "session_server.h"
Michal Vasko1a38c862016-01-15 15:50:07 +010027
28extern struct nc_server_opts server_opts;
Michal Vasko7bcb48e2016-01-15 10:28:54 +010029
30API struct nc_server_reply *
31nc_server_reply_ok(void)
32{
33 struct nc_server_reply *ret;
34
35 ret = malloc(sizeof *ret);
36 if (!ret) {
37 ERRMEM;
38 return NULL;
39 }
40
41 ret->type = NC_RPL_OK;
42 return ret;
43}
44
45API struct nc_server_reply *
Radek Krejci36dfdb32016-09-01 16:56:35 +020046nc_server_reply_data(struct lyd_node *data, NC_WD_MODE wd, NC_PARAMTYPE paramtype)
Michal Vasko7bcb48e2016-01-15 10:28:54 +010047{
48 struct nc_server_reply_data *ret;
49
Michal Vaskob08743b2016-04-13 14:23:49 +020050 if (!data) {
51 ERRARG("data");
52 return NULL;
53 }
54
Michal Vasko7bcb48e2016-01-15 10:28:54 +010055 ret = malloc(sizeof *ret);
56 if (!ret) {
57 ERRMEM;
58 return NULL;
59 }
60
61 ret->type = NC_RPL_DATA;
Radek Krejci36dfdb32016-09-01 16:56:35 +020062 ret->wd = wd;
Michal Vaskob08743b2016-04-13 14:23:49 +020063 if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
Michal Vasko77367452021-02-16 16:32:18 +010064 if (lyd_dup_single(data, NULL, LYD_DUP_RECURSIVE, &ret->data)) {
65 free(ret);
66 return NULL;
67 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +010068 } else {
69 ret->data = data;
70 }
71 if (paramtype != NC_PARAMTYPE_CONST) {
72 ret->free = 1;
73 } else {
74 ret->free = 0;
75 }
76 return (struct nc_server_reply *)ret;
77}
78
79API struct nc_server_reply *
Michal Vasko77367452021-02-16 16:32:18 +010080nc_server_reply_err(struct lyd_node *err)
Michal Vasko7bcb48e2016-01-15 10:28:54 +010081{
82 struct nc_server_reply_error *ret;
83
Michal Vasko1a38c862016-01-15 15:50:07 +010084 if (!err) {
Michal Vasko45e53ae2016-04-07 11:46:03 +020085 ERRARG("err");
Michal Vasko7bcb48e2016-01-15 10:28:54 +010086 return NULL;
87 }
88
89 ret = malloc(sizeof *ret);
90 if (!ret) {
91 ERRMEM;
92 return NULL;
93 }
94
95 ret->type = NC_RPL_ERROR;
Michal Vasko77367452021-02-16 16:32:18 +010096 ret->err = err;
Michal Vasko7bcb48e2016-01-15 10:28:54 +010097 return (struct nc_server_reply *)ret;
98}
99
100API int
Michal Vasko77367452021-02-16 16:32:18 +0100101nc_server_reply_add_err(struct nc_server_reply *reply, struct lyd_node *err)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100102{
103 struct nc_server_reply_error *err_rpl;
104
Michal Vasko45e53ae2016-04-07 11:46:03 +0200105 if (!reply || (reply->type != NC_RPL_ERROR)) {
106 ERRARG("reply");
107 return -1;
108 } else if (!err) {
109 ERRARG("err");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100110 return -1;
111 }
112
113 err_rpl = (struct nc_server_reply_error *)reply;
Michal Vasko77367452021-02-16 16:32:18 +0100114 lyd_insert_sibling(err_rpl->err, err, &err_rpl->err);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100115 return 0;
116}
117
Michal Vasko77367452021-02-16 16:32:18 +0100118API const struct lyd_node *
Michal Vaskoaa2e5a72017-03-16 09:48:44 +0100119nc_server_reply_get_last_err(const struct nc_server_reply *reply)
120{
121 struct nc_server_reply_error *err_rpl;
122
123 if (!reply || (reply->type != NC_RPL_ERROR)) {
124 ERRARG("reply");
125 return NULL;
126 }
127
128 err_rpl = (struct nc_server_reply_error *)reply;
Michal Vasko77367452021-02-16 16:32:18 +0100129 if (!err_rpl->err) {
Michal Vaskoaa2e5a72017-03-16 09:48:44 +0100130 return NULL;
131 }
Michal Vasko77367452021-02-16 16:32:18 +0100132 return err_rpl->err->prev;
Michal Vaskoaa2e5a72017-03-16 09:48:44 +0100133}
134
Michal Vasko77367452021-02-16 16:32:18 +0100135static const char *
136nc_err_tag2str(NC_ERR tag)
137{
138 switch (tag) {
139 case NC_ERR_IN_USE:
140 return "in-use";
141 case NC_ERR_INVALID_VALUE:
142 return "invalid-value";
143 case NC_ERR_ACCESS_DENIED:
144 return "access-denied";
145 case NC_ERR_ROLLBACK_FAILED:
146 return "rollback-failed";
147 case NC_ERR_OP_NOT_SUPPORTED:
148 return "operation-not-supported";
149 case NC_ERR_TOO_BIG:
150 return "too-big";
151 case NC_ERR_RES_DENIED:
152 return "resource-denied";
153 case NC_ERR_MISSING_ATTR:
154 return "missing-attribute";
155 case NC_ERR_BAD_ATTR:
156 return "bad-attribute";
157 case NC_ERR_UNKNOWN_ATTR:
158 return "unknown-attribute";
159 case NC_ERR_MISSING_ELEM:
160 return "missing-element";
161 case NC_ERR_BAD_ELEM:
162 return "bad-element";
163 case NC_ERR_UNKNOWN_ELEM:
164 return "unknown-element";
165 case NC_ERR_UNKNOWN_NS:
166 return "unknown-namespace";
167 case NC_ERR_LOCK_DENIED:
168 return "lock-denied";
169 case NC_ERR_DATA_EXISTS:
170 return "data-exists";
171 case NC_ERR_DATA_MISSING:
172 return "data-missing";
173 case NC_ERR_OP_FAILED:
174 return "operation-failed";
175 case NC_ERR_MALFORMED_MSG:
176 return "malformed-message";
177 default:
178 break;
179 }
180
181 return NULL;
182}
183
184static NC_ERR
185nc_err_str2tag(const char *str)
186{
187 if (!strcmp(str, "in-use")) {
188 return NC_ERR_IN_USE;
189 } else if (!strcmp(str, "invalid-value")) {
190 return NC_ERR_INVALID_VALUE;
191 } else if (!strcmp(str, "access-denied")) {
192 return NC_ERR_ACCESS_DENIED;
193 } else if (!strcmp(str, "rollback-failed")) {
194 return NC_ERR_ROLLBACK_FAILED;
195 } else if (!strcmp(str, "operation-not-supported")) {
196 return NC_ERR_OP_NOT_SUPPORTED;
197 } else if (!strcmp(str, "too-big")) {
198 return NC_ERR_TOO_BIG;
199 } else if (!strcmp(str, "resource-denied")) {
200 return NC_ERR_RES_DENIED;
201 } else if (!strcmp(str, "missing-attribute")) {
202 return NC_ERR_MISSING_ATTR;
203 } else if (!strcmp(str, "bad-attribute")) {
204 return NC_ERR_BAD_ATTR;
205 } else if (!strcmp(str, "unknown-attribute")) {
206 return NC_ERR_UNKNOWN_ATTR;
207 } else if (!strcmp(str, "missing-element")) {
208 return NC_ERR_MISSING_ELEM;
209 } else if (!strcmp(str, "bad-element")) {
210 return NC_ERR_BAD_ELEM;
211 } else if (!strcmp(str, "unknown-element")) {
212 return NC_ERR_UNKNOWN_ELEM;
213 } else if (!strcmp(str, "unknown-namespace")) {
214 return NC_ERR_UNKNOWN_NS;
215 } else if (!strcmp(str, "lock-denied")) {
216 return NC_ERR_LOCK_DENIED;
217 } else if (!strcmp(str, "data-exists")) {
218 return NC_ERR_DATA_EXISTS;
219 } else if (!strcmp(str, "data-missing")) {
220 return NC_ERR_DATA_MISSING;
221 } else if (!strcmp(str, "operation-failed")) {
222 return NC_ERR_OP_FAILED;
223 } else if (!strcmp(str, "malformed-message")) {
224 return NC_ERR_MALFORMED_MSG;
225 }
226
227 return 0;
228}
229
230static const char *
231nc_err_type2str(NC_ERR_TYPE type)
232{
233 switch (type) {
234 case NC_ERR_TYPE_TRAN:
235 return "transport";
236 case NC_ERR_TYPE_RPC:
237 return "rpc";
238 case NC_ERR_TYPE_PROT:
239 return "protocol";
240 case NC_ERR_TYPE_APP:
241 return "application";
242 default:
243 break;
244 }
245
246 return NULL;
247}
248
249static NC_ERR_TYPE
250nc_err_str2type(const char *str)
251{
252 if (!strcmp(str, "transport")) {
253 return NC_ERR_TYPE_TRAN;
254 } else if (!strcmp(str, "rpc")) {
255 return NC_ERR_TYPE_RPC;
256 } else if (!strcmp(str, "protocol")) {
257 return NC_ERR_TYPE_PROT;
258 } else if (!strcmp(str, "application")) {
259 return NC_ERR_TYPE_APP;
260 }
261
262 return 0;
263}
264
265API struct lyd_node *
266nc_err(const struct ly_ctx *ctx, NC_ERR tag, ...)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100267{
268 va_list ap;
Michal Vasko77367452021-02-16 16:32:18 +0100269 struct lyd_node *err = NULL;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100270 NC_ERR_TYPE type;
271 const char *arg1, *arg2;
272 uint32_t sid;
273
Michal Vasko1a38c862016-01-15 15:50:07 +0100274 if (!tag) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200275 ERRARG("tag");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100276 return NULL;
277 }
278
Michal Vasko77367452021-02-16 16:32:18 +0100279 /* rpc-error */
280 if (lyd_new_opaq2(NULL, ctx, "rpc-error", NULL, NULL, NC_NS_BASE, &err)) {
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100281 return NULL;
282 }
283
284 va_start(ap, tag);
285
Michal Vasko77367452021-02-16 16:32:18 +0100286 /* error-type */
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100287 switch (tag) {
288 case NC_ERR_IN_USE:
289 case NC_ERR_INVALID_VALUE:
290 case NC_ERR_ACCESS_DENIED:
291 case NC_ERR_ROLLBACK_FAILED:
292 case NC_ERR_OP_NOT_SUPPORTED:
Radek Krejci127f8952016-10-12 14:57:16 +0200293 type = (NC_ERR_TYPE)va_arg(ap, int); /* NC_ERR_TYPE enum is automatically promoted to int */
Michal Vasko2f923d12016-04-05 11:33:02 +0200294 if ((type != NC_ERR_TYPE_PROT) && (type != NC_ERR_TYPE_APP)) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200295 ERRARG("type");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100296 goto fail;
297 }
298 break;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100299 case NC_ERR_TOO_BIG:
300 case NC_ERR_RES_DENIED:
Michal Vasko77367452021-02-16 16:32:18 +0100301 type = (NC_ERR_TYPE)va_arg(ap, int);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100302 break;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100303 case NC_ERR_MISSING_ATTR:
304 case NC_ERR_BAD_ATTR:
305 case NC_ERR_UNKNOWN_ATTR:
Michal Vasko77367452021-02-16 16:32:18 +0100306 type = (NC_ERR_TYPE)va_arg(ap, int);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100307 if (type == NC_ERR_TYPE_TRAN) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200308 ERRARG("type");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100309 goto fail;
310 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100311 break;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100312 case NC_ERR_MISSING_ELEM:
313 case NC_ERR_BAD_ELEM:
314 case NC_ERR_UNKNOWN_ELEM:
Michal Vasko77367452021-02-16 16:32:18 +0100315 type = (NC_ERR_TYPE)va_arg(ap, int);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100316 if ((type != NC_ERR_TYPE_PROT) && (type != NC_ERR_TYPE_APP)) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200317 ERRARG("type");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100318 goto fail;
319 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100320 break;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100321 case NC_ERR_UNKNOWN_NS:
Michal Vasko77367452021-02-16 16:32:18 +0100322 type = (NC_ERR_TYPE)va_arg(ap, int);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100323 if ((type != NC_ERR_TYPE_PROT) && (type != NC_ERR_TYPE_APP)) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200324 ERRARG("type");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100325 goto fail;
326 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100327 break;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100328 case NC_ERR_LOCK_DENIED:
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100329 type = NC_ERR_TYPE_PROT;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100330 break;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100331 case NC_ERR_DATA_EXISTS:
332 case NC_ERR_DATA_MISSING:
333 type = NC_ERR_TYPE_APP;
334 break;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100335 case NC_ERR_OP_FAILED:
Michal Vasko77367452021-02-16 16:32:18 +0100336 type = (NC_ERR_TYPE)va_arg(ap, int);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100337 if (type == NC_ERR_TYPE_TRAN) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200338 ERRARG("type");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100339 goto fail;
340 }
341 break;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100342 case NC_ERR_MALFORMED_MSG:
343 type = NC_ERR_TYPE_RPC;
344 break;
Michal Vasko77367452021-02-16 16:32:18 +0100345 default:
346 ERRARG("tag");
347 goto fail;
348 }
349 if (lyd_new_opaq2(err, NULL, "error-type", nc_err_type2str(type), NULL, NC_NS_BASE, NULL)) {
350 goto fail;
351 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100352
Michal Vasko77367452021-02-16 16:32:18 +0100353 /* error-tag */
354 if (lyd_new_opaq2(err, NULL, "error-tag", nc_err_tag2str(tag), NULL, NC_NS_BASE, NULL)) {
355 goto fail;
356 }
357
358 /* error-severity */
359 if (lyd_new_opaq2(err, NULL, "error-severity", "error", NULL, NC_NS_BASE, NULL)) {
360 goto fail;
361 }
362
363 /* error-message */
364 switch (tag) {
365 case NC_ERR_IN_USE:
366 nc_err_set_msg(err, "The request requires a resource that already is in use.", "en");
367 break;
368 case NC_ERR_INVALID_VALUE:
369 nc_err_set_msg(err, "The request specifies an unacceptable value for one or more parameters.", "en");
370 break;
371 case NC_ERR_TOO_BIG:
372 nc_err_set_msg(err, "The request or response (that would be generated) is too large for the implementation to handle.", "en");
373 break;
374 case NC_ERR_MISSING_ATTR:
375 nc_err_set_msg(err, "An expected attribute is missing.", "en");
376 break;
377 case NC_ERR_BAD_ATTR:
378 nc_err_set_msg(err, "An attribute value is not correct.", "en");
379 break;
380 case NC_ERR_UNKNOWN_ATTR:
381 nc_err_set_msg(err, "An unexpected attribute is present.", "en");
382 break;
383 case NC_ERR_MISSING_ELEM:
384 nc_err_set_msg(err, "An expected element is missing.", "en");
385 break;
386 case NC_ERR_BAD_ELEM:
387 nc_err_set_msg(err, "An element value is not correct.", "en");
388 break;
389 case NC_ERR_UNKNOWN_ELEM:
390 nc_err_set_msg(err, "An unexpected element is present.", "en");
391 break;
392 case NC_ERR_UNKNOWN_NS:
393 nc_err_set_msg(err, "An unexpected namespace is present.", "en");
394 break;
395 case NC_ERR_ACCESS_DENIED:
396 nc_err_set_msg(err, "Access to the requested protocol operation or data model is denied because authorization failed.", "en");
397 break;
398 case NC_ERR_LOCK_DENIED:
399 nc_err_set_msg(err, "Access to the requested lock is denied because the lock is currently held by another entity.", "en");
400 break;
401 case NC_ERR_RES_DENIED:
402 nc_err_set_msg(err, "Request could not be completed because of insufficient resources.", "en");
403 break;
404 case NC_ERR_ROLLBACK_FAILED:
405 nc_err_set_msg(err, "Request to roll back some configuration change was not completed for some reason.", "en");
406 break;
407 case NC_ERR_DATA_EXISTS:
408 nc_err_set_msg(err, "Request could not be completed because the relevant data model content already exists.", "en");
409 break;
410 case NC_ERR_DATA_MISSING:
411 nc_err_set_msg(err, "Request could not be completed because the relevant data model content does not exist.", "en");
412 break;
413 case NC_ERR_OP_NOT_SUPPORTED:
414 nc_err_set_msg(err, "Request could not be completed because the requested operation is not supported by this implementation.", "en");
415 break;
416 case NC_ERR_OP_FAILED:
417 nc_err_set_msg(err, "Request could not be completed because the requested operation failed for a non-specific reason.", "en");
418 break;
419 case NC_ERR_MALFORMED_MSG:
420 nc_err_set_msg(err, "A message could not be handled because it failed to be parsed correctly.", "en");
421 break;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100422 default:
Michal Vasko45e53ae2016-04-07 11:46:03 +0200423 ERRARG("tag");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100424 goto fail;
425 }
426
Michal Vasko77367452021-02-16 16:32:18 +0100427 /* error-info */
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100428 switch (tag) {
429 case NC_ERR_IN_USE:
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100430 case NC_ERR_INVALID_VALUE:
Michal Vasko77367452021-02-16 16:32:18 +0100431 case NC_ERR_ACCESS_DENIED:
432 case NC_ERR_ROLLBACK_FAILED:
433 case NC_ERR_OP_NOT_SUPPORTED:
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100434 case NC_ERR_TOO_BIG:
Michal Vasko77367452021-02-16 16:32:18 +0100435 case NC_ERR_RES_DENIED:
436 case NC_ERR_DATA_EXISTS:
437 case NC_ERR_DATA_MISSING:
438 case NC_ERR_OP_FAILED:
439 case NC_ERR_MALFORMED_MSG:
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100440 break;
441 case NC_ERR_MISSING_ATTR:
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100442 case NC_ERR_BAD_ATTR:
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100443 case NC_ERR_UNKNOWN_ATTR:
Michal Vasko77367452021-02-16 16:32:18 +0100444 arg1 = va_arg(ap, const char *);
445 arg2 = va_arg(ap, const char *);
446
447 nc_err_add_bad_attr(err, arg1);
448 nc_err_add_bad_elem(err, arg2);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100449 break;
450 case NC_ERR_MISSING_ELEM:
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100451 case NC_ERR_BAD_ELEM:
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100452 case NC_ERR_UNKNOWN_ELEM:
Michal Vasko77367452021-02-16 16:32:18 +0100453 arg1 = va_arg(ap, const char *);
454
455 nc_err_add_bad_elem(err, arg1);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100456 break;
457 case NC_ERR_UNKNOWN_NS:
Michal Vasko77367452021-02-16 16:32:18 +0100458 arg1 = va_arg(ap, const char *);
459 arg2 = va_arg(ap, const char *);
460
461 nc_err_add_bad_elem(err, arg1);
462 nc_err_add_bad_ns(err, arg2);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100463 break;
464 case NC_ERR_LOCK_DENIED:
Michal Vasko77367452021-02-16 16:32:18 +0100465 sid = va_arg(ap, uint32_t);
466
467 nc_err_set_sid(err, sid);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100468 break;
469 default:
Michal Vasko45e53ae2016-04-07 11:46:03 +0200470 ERRARG("tag");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100471 goto fail;
472 }
473
474 va_end(ap);
Michal Vasko77367452021-02-16 16:32:18 +0100475 return err;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100476
477fail:
Michal Vasko11d142a2016-01-19 15:58:24 +0100478 va_end(ap);
Michal Vasko77367452021-02-16 16:32:18 +0100479 lyd_free_siblings(err);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100480 return NULL;
481}
482
Michal Vasko8f3198f2016-05-04 10:45:28 +0200483API NC_ERR_TYPE
Michal Vasko77367452021-02-16 16:32:18 +0100484nc_err_get_type(const struct lyd_node *err)
Michal Vasko8f3198f2016-05-04 10:45:28 +0200485{
Michal Vasko77367452021-02-16 16:32:18 +0100486 struct lyd_node *match;
487
Michal Vasko8f3198f2016-05-04 10:45:28 +0200488 if (!err) {
489 ERRARG("err");
490 return 0;
491 }
492
Michal Vasko77367452021-02-16 16:32:18 +0100493 lyd_find_sibling_opaq_next(lyd_child(err), "error-type", &match);
494 if (match) {
495 return nc_err_str2type(((struct lyd_node_opaq *)match)->value);
496 }
497
498 return 0;
Michal Vasko8f3198f2016-05-04 10:45:28 +0200499}
500
501API NC_ERR
Michal Vasko77367452021-02-16 16:32:18 +0100502nc_err_get_tag(const struct lyd_node *err)
Michal Vasko8f3198f2016-05-04 10:45:28 +0200503{
Michal Vasko77367452021-02-16 16:32:18 +0100504 struct lyd_node *match;
505
Michal Vasko8f3198f2016-05-04 10:45:28 +0200506 if (!err) {
507 ERRARG("err");
508 return 0;
509 }
510
Michal Vasko77367452021-02-16 16:32:18 +0100511 lyd_find_sibling_opaq_next(lyd_child(err), "error-tag", &match);
512 if (match) {
513 return nc_err_str2tag(((struct lyd_node_opaq *)match)->value);
514 }
515
516 return 0;
Michal Vasko8f3198f2016-05-04 10:45:28 +0200517}
518
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100519API int
Michal Vasko77367452021-02-16 16:32:18 +0100520nc_err_set_app_tag(struct lyd_node *err, const char *error_app_tag)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100521{
Michal Vasko77367452021-02-16 16:32:18 +0100522 struct lyd_node *match;
523
Michal Vasko45e53ae2016-04-07 11:46:03 +0200524 if (!err) {
525 ERRARG("err");
526 return -1;
527 } else if (!error_app_tag) {
528 ERRARG("error_app_tag");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100529 return -1;
530 }
531
Michal Vasko77367452021-02-16 16:32:18 +0100532 /* remove previous node */
533 lyd_find_sibling_opaq_next(lyd_child(err), "error-app-tag", &match);
534 if (match) {
535 lyd_free_tree(match);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100536 }
Michal Vasko77367452021-02-16 16:32:18 +0100537
538 if (lyd_new_opaq2(err, NULL, "error-app-tag", error_app_tag, NULL, NC_NS_BASE, NULL)) {
539 return -1;
540 }
Michal Vasko11d142a2016-01-19 15:58:24 +0100541
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100542 return 0;
543}
544
Michal Vasko8f3198f2016-05-04 10:45:28 +0200545API const char *
Michal Vasko77367452021-02-16 16:32:18 +0100546nc_err_get_app_tag(const struct lyd_node *err)
Michal Vasko8f3198f2016-05-04 10:45:28 +0200547{
Michal Vasko77367452021-02-16 16:32:18 +0100548 struct lyd_node *match;
549
Michal Vasko8f3198f2016-05-04 10:45:28 +0200550 if (!err) {
551 ERRARG("err");
552 return NULL;
553 }
554
Michal Vasko77367452021-02-16 16:32:18 +0100555 lyd_find_sibling_opaq_next(lyd_child(err), "error-app-tag", &match);
556 if (match) {
557 return ((struct lyd_node_opaq *)match)->value;
558 }
559
560 return NULL;
Michal Vasko8f3198f2016-05-04 10:45:28 +0200561}
562
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100563API int
Michal Vasko77367452021-02-16 16:32:18 +0100564nc_err_set_path(struct lyd_node *err, const char *error_path)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100565{
Michal Vasko77367452021-02-16 16:32:18 +0100566 struct lyd_node *match;
567
Michal Vasko45e53ae2016-04-07 11:46:03 +0200568 if (!err) {
569 ERRARG("err");
570 return -1;
571 } else if (!error_path) {
572 ERRARG("error_path");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100573 return -1;
574 }
575
Michal Vasko77367452021-02-16 16:32:18 +0100576 /* remove previous node */
577 lyd_find_sibling_opaq_next(lyd_child(err), "error-path", &match);
578 if (match) {
579 lyd_free_tree(match);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100580 }
Michal Vasko77367452021-02-16 16:32:18 +0100581
582 if (lyd_new_opaq2(err, NULL, "error-path", error_path, NULL, NC_NS_BASE, NULL)) {
583 return -1;
584 }
Michal Vasko11d142a2016-01-19 15:58:24 +0100585
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100586 return 0;
587}
588
Michal Vasko8f3198f2016-05-04 10:45:28 +0200589API const char *
Michal Vasko77367452021-02-16 16:32:18 +0100590nc_err_get_path(const struct lyd_node *err)
Michal Vasko8f3198f2016-05-04 10:45:28 +0200591{
Michal Vasko77367452021-02-16 16:32:18 +0100592 struct lyd_node *match;
593
Michal Vasko8f3198f2016-05-04 10:45:28 +0200594 if (!err) {
595 ERRARG("err");
596 return 0;
597 }
598
Michal Vasko77367452021-02-16 16:32:18 +0100599 lyd_find_sibling_opaq_next(lyd_child(err), "error-path", &match);
600 if (match) {
601 return ((struct lyd_node_opaq *)match)->value;
602 }
603
604 return NULL;
Michal Vasko8f3198f2016-05-04 10:45:28 +0200605}
606
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100607API int
Michal Vasko77367452021-02-16 16:32:18 +0100608nc_err_set_msg(struct lyd_node *err, const char *error_message, const char *lang)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100609{
Michal Vasko77367452021-02-16 16:32:18 +0100610 struct lyd_node *match;
611 struct lyd_attr *attr;
612
Michal Vasko45e53ae2016-04-07 11:46:03 +0200613 if (!err) {
614 ERRARG("err");
615 return -1;
616 } else if (!error_message) {
617 ERRARG("error_message");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100618 return -1;
619 }
620
Michal Vasko77367452021-02-16 16:32:18 +0100621 /* remove previous message */
622 lyd_find_sibling_opaq_next(lyd_child(err), "error-message", &match);
623 if (match) {
624 lyd_free_tree(match);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100625 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100626
Michal Vasko77367452021-02-16 16:32:18 +0100627 if (lyd_new_opaq2(err, NULL, "error-message", error_message, NULL, NC_NS_BASE, &match)) {
628 return -1;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100629 }
Michal Vasko77367452021-02-16 16:32:18 +0100630 if (lang && lyd_new_attr(match, NULL, "xml:lang", lang, &attr)) {
631 lyd_free_tree(match);
632 return -1;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100633 }
Michal Vasko11d142a2016-01-19 15:58:24 +0100634
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100635 return 0;
636}
637
Michal Vasko8f3198f2016-05-04 10:45:28 +0200638API const char *
Michal Vasko77367452021-02-16 16:32:18 +0100639nc_err_get_msg(const struct lyd_node *err)
Michal Vasko8f3198f2016-05-04 10:45:28 +0200640{
Michal Vasko77367452021-02-16 16:32:18 +0100641 struct lyd_node *match;
642
Michal Vasko8f3198f2016-05-04 10:45:28 +0200643 if (!err) {
644 ERRARG("err");
Michal Vasko77367452021-02-16 16:32:18 +0100645 return NULL;
Michal Vasko8f3198f2016-05-04 10:45:28 +0200646 }
647
Michal Vasko77367452021-02-16 16:32:18 +0100648 lyd_find_sibling_opaq_next(lyd_child(err), "error-message", &match);
649 if (match) {
650 return ((struct lyd_node_opaq *)match)->value;
651 }
652
653 return NULL;
Michal Vasko8f3198f2016-05-04 10:45:28 +0200654}
655
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100656API int
Michal Vasko77367452021-02-16 16:32:18 +0100657nc_err_set_sid(struct lyd_node *err, uint32_t session_id)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100658{
Michal Vasko77367452021-02-16 16:32:18 +0100659 struct lyd_node *match, *info;
660 char buf[22];
661
Michal Vasko45e53ae2016-04-07 11:46:03 +0200662 if (!err) {
663 ERRARG("err");
664 return -1;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100665 }
666
Michal Vasko77367452021-02-16 16:32:18 +0100667 /* find error-info */
668 lyd_find_sibling_opaq_next(lyd_child(err), "error-info", &info);
669 if (!info && lyd_new_opaq2(err, NULL, "error-info", NULL, NULL, NC_NS_BASE, &info)) {
670 return -1;
671 }
672
673 /* remove previous node */
674 lyd_find_sibling_opaq_next(lyd_child(info), "session-id", &match);
675 if (match) {
676 lyd_free_tree(match);
677 }
678
679 sprintf(buf, "%" PRIu32, session_id);
680 if (lyd_new_opaq2(info, NULL, "session-id", buf, NULL, NC_NS_BASE, NULL)) {
681 return -1;
682 }
683
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100684 return 0;
685}
686
687API int
Michal Vasko77367452021-02-16 16:32:18 +0100688nc_err_add_bad_attr(struct lyd_node *err, const char *attr_name)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100689{
Michal Vasko77367452021-02-16 16:32:18 +0100690 struct lyd_node *info;
691
Michal Vasko45e53ae2016-04-07 11:46:03 +0200692 if (!err) {
693 ERRARG("err");
694 return -1;
695 } else if (!attr_name) {
696 ERRARG("attr_name");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100697 return -1;
698 }
699
Michal Vasko77367452021-02-16 16:32:18 +0100700 /* find error-info */
701 lyd_find_sibling_opaq_next(lyd_child(err), "error-info", &info);
702 if (!info && lyd_new_opaq2(err, NULL, "error-info", NULL, NULL, NC_NS_BASE, &info)) {
Michal Vasko4eb3c312016-03-01 14:09:37 +0100703 return -1;
704 }
Michal Vasko77367452021-02-16 16:32:18 +0100705
706 if (lyd_new_opaq2(info, NULL, "bad-attribute", attr_name, NULL, NC_NS_BASE, NULL)) {
707 return -1;
708 }
Michal Vasko11d142a2016-01-19 15:58:24 +0100709
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100710 return 0;
711}
712
713API int
Michal Vasko77367452021-02-16 16:32:18 +0100714nc_err_add_bad_elem(struct lyd_node *err, const char *elem_name)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100715{
Michal Vasko77367452021-02-16 16:32:18 +0100716 struct lyd_node *info;
717
Michal Vasko45e53ae2016-04-07 11:46:03 +0200718 if (!err) {
719 ERRARG("err");
720 return -1;
721 } else if (!elem_name) {
722 ERRARG("elem_name");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100723 return -1;
724 }
725
Michal Vasko77367452021-02-16 16:32:18 +0100726 /* find error-info */
727 lyd_find_sibling_opaq_next(lyd_child(err), "error-info", &info);
728 if (!info && lyd_new_opaq2(err, NULL, "error-info", NULL, NULL, NC_NS_BASE, &info)) {
Michal Vasko4eb3c312016-03-01 14:09:37 +0100729 return -1;
730 }
Michal Vasko77367452021-02-16 16:32:18 +0100731
732 if (lyd_new_opaq2(info, NULL, "bad-element", elem_name, NULL, NC_NS_BASE, NULL)) {
733 return -1;
734 }
Michal Vasko11d142a2016-01-19 15:58:24 +0100735
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100736 return 0;
737}
738
739API int
Michal Vasko77367452021-02-16 16:32:18 +0100740nc_err_add_bad_ns(struct lyd_node *err, const char *ns_name)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100741{
Michal Vasko77367452021-02-16 16:32:18 +0100742 struct lyd_node *info;
743
Michal Vasko45e53ae2016-04-07 11:46:03 +0200744 if (!err) {
745 ERRARG("err");
746 return -1;
747 } else if (!ns_name) {
748 ERRARG("ns_name");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100749 return -1;
750 }
751
Michal Vasko77367452021-02-16 16:32:18 +0100752 /* find error-info */
753 lyd_find_sibling_opaq_next(lyd_child(err), "error-info", &info);
754 if (!info && lyd_new_opaq2(err, NULL, "error-info", NULL, NULL, NC_NS_BASE, &info)) {
Michal Vasko4eb3c312016-03-01 14:09:37 +0100755 return -1;
756 }
Michal Vasko77367452021-02-16 16:32:18 +0100757
758 if (lyd_new_opaq2(info, NULL, "bad-namespace", ns_name, NULL, NC_NS_BASE, NULL)) {
759 return -1;
760 }
Michal Vasko11d142a2016-01-19 15:58:24 +0100761
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100762 return 0;
763}
764
765API int
Michal Vasko77367452021-02-16 16:32:18 +0100766nc_err_add_info_other(struct lyd_node *err, struct lyd_node *other)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100767{
Michal Vasko77367452021-02-16 16:32:18 +0100768 struct lyd_node *info;
769
Michal Vasko45e53ae2016-04-07 11:46:03 +0200770 if (!err) {
771 ERRARG("err");
772 return -1;
773 } else if (!other) {
774 ERRARG("other");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100775 return -1;
776 }
777
Michal Vasko77367452021-02-16 16:32:18 +0100778 /* find error-info */
779 lyd_find_sibling_opaq_next(lyd_child(err), "error-info", &info);
780 if (!info && lyd_new_opaq2(err, NULL, "error-info", NULL, NULL, NC_NS_BASE, &info)) {
Michal Vasko4eb3c312016-03-01 14:09:37 +0100781 return -1;
782 }
Michal Vasko77367452021-02-16 16:32:18 +0100783
784 lyd_insert_child(info, other);
785
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100786 return 0;
787}
788
789void
Michal Vasko77367452021-02-16 16:32:18 +0100790nc_server_rpc_free(struct nc_server_rpc *rpc)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100791{
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100792 if (!rpc) {
793 return;
794 }
795
Michal Vasko77367452021-02-16 16:32:18 +0100796 lyd_free_tree(rpc->envp);
Michal Vaskod5bfc482021-10-26 10:47:54 +0200797
798 /* may be action */
799 lyd_free_all(rpc->rpc);
Michal Vasko11d142a2016-01-19 15:58:24 +0100800
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100801 free(rpc);
802}
803
804API void
805nc_server_reply_free(struct nc_server_reply *reply)
806{
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100807 struct nc_server_reply_data *data_rpl;
808 struct nc_server_reply_error *error_rpl;
809
810 if (!reply) {
811 return;
812 }
813
814 switch (reply->type) {
815 case NC_RPL_DATA:
816 data_rpl = (struct nc_server_reply_data *)reply;
817 if (data_rpl->free) {
Michal Vasko77367452021-02-16 16:32:18 +0100818 lyd_free_siblings(data_rpl->data);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100819 }
820 break;
821 case NC_RPL_OK:
822 /* nothing to free */
823 break;
824 case NC_RPL_ERROR:
825 error_rpl = (struct nc_server_reply_error *)reply;
Michal Vasko77367452021-02-16 16:32:18 +0100826 lyd_free_siblings(error_rpl->err);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100827 break;
828 default:
829 break;
830 }
831 free(reply);
832}
833
Radek Krejci93e80222016-10-03 13:34:25 +0200834API struct nc_server_notif *
Michal Vasko77367452021-02-16 16:32:18 +0100835nc_server_notif_new(struct lyd_node *event, char *eventtime, NC_PARAMTYPE paramtype)
Radek Krejci93e80222016-10-03 13:34:25 +0200836{
837 struct nc_server_notif *ntf;
Michal Vasko0b89f3d2018-01-04 10:57:03 +0100838 struct lyd_node *elem;
Michal Vasko77367452021-02-16 16:32:18 +0100839 int found;
Radek Krejci93e80222016-10-03 13:34:25 +0200840
Michal Vasko3106b7b2018-01-04 10:32:42 +0100841 if (!event) {
Radek Krejci93e80222016-10-03 13:34:25 +0200842 ERRARG("event");
843 return NULL;
844 } else if (!eventtime) {
845 ERRARG("eventtime");
846 return NULL;
847 }
848
Michal Vasko0b89f3d2018-01-04 10:57:03 +0100849 /* check that there is a notification */
Michal Vasko77367452021-02-16 16:32:18 +0100850 found = 0;
851 LYD_TREE_DFS_BEGIN(event, elem) {
852 if (elem->schema->nodetype == LYS_NOTIF) {
853 found = 1;
Michal Vasko0b89f3d2018-01-04 10:57:03 +0100854 break;
Michal Vasko0b89f3d2018-01-04 10:57:03 +0100855 }
Michal Vasko77367452021-02-16 16:32:18 +0100856 LYD_TREE_DFS_END(event, elem);
Michal Vasko0b89f3d2018-01-04 10:57:03 +0100857 }
Michal Vasko77367452021-02-16 16:32:18 +0100858 if (!found) {
Michal Vasko0b89f3d2018-01-04 10:57:03 +0100859 ERRARG("event");
860 return NULL;
861 }
862
Radek Krejci93e80222016-10-03 13:34:25 +0200863 ntf = malloc(sizeof *ntf);
Michal Vaskofc9dbdd2017-03-17 09:27:57 +0100864 if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
Radek Krejci93e80222016-10-03 13:34:25 +0200865 ntf->eventtime = strdup(eventtime);
Michal Vasko77367452021-02-16 16:32:18 +0100866 if (lyd_dup_single(event, NULL, LYD_DUP_RECURSIVE, &ntf->ntf)) {
867 free(ntf);
868 return NULL;
869 }
Radek Krejci93e80222016-10-03 13:34:25 +0200870 } else {
871 ntf->eventtime = eventtime;
Michal Vasko77367452021-02-16 16:32:18 +0100872 ntf->ntf = event;
Radek Krejci93e80222016-10-03 13:34:25 +0200873 }
Michal Vaskofc9dbdd2017-03-17 09:27:57 +0100874 ntf->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
Radek Krejci93e80222016-10-03 13:34:25 +0200875
876 return ntf;
877}
878
879API void
880nc_server_notif_free(struct nc_server_notif *notif)
881{
882 if (!notif) {
883 return;
884 }
885
Michal Vaskofc9dbdd2017-03-17 09:27:57 +0100886 if (notif->free) {
Michal Vasko77367452021-02-16 16:32:18 +0100887 lyd_free_tree(notif->ntf);
Michal Vaskofc9dbdd2017-03-17 09:27:57 +0100888 free(notif->eventtime);
889 }
Radek Krejci93e80222016-10-03 13:34:25 +0200890 free(notif);
891}
Michal Vasko9a2e4d22017-03-17 09:44:49 +0100892
893API const char *
894nc_server_notif_get_time(const struct nc_server_notif *notif)
895{
896 if (!notif) {
897 ERRARG("notif");
898 return NULL;
899 }
900
901 return notif->eventtime;
902}