blob: 7a39e69028eb25bc4c44f3ffa6f7e58b6b7d50c8 [file] [log] [blame]
Michal Vasko7bcb48e2016-01-15 10:28:54 +01001/**
2 * \file messages_server.c
3 * \author Michal Vasko <mvasko@cesnet.cz>
4 * \brief libnetconf2 - server NETCONF messages functions
5 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
Radek Krejci9b81f5b2016-02-24 13:14:49 +01008 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
Michal Vaskoafd416b2016-02-25 14:51:46 +010011 *
Radek Krejci9b81f5b2016-02-24 13:14:49 +010012 * https://opensource.org/licenses/BSD-3-Clause
Michal Vasko7bcb48e2016-01-15 10:28:54 +010013 */
14
15#include <ctype.h>
Michal Vaskob83a3fa2021-05-26 09:53:42 +020016#include <inttypes.h>
17#include <stdarg.h>
Michal Vasko7bcb48e2016-01-15 10:28:54 +010018#include <stdlib.h>
19#include <string.h>
Michal Vasko7bcb48e2016-01-15 10:28:54 +010020
21#include <libyang/libyang.h>
22
Michal Vasko9e8ac262020-04-07 13:06:45 +020023#include "compat.h"
Michal Vasko7bcb48e2016-01-15 10:28:54 +010024#include "libnetconf.h"
Radek Krejci93e80222016-10-03 13:34:25 +020025#include "session_server.h"
Michal Vasko1a38c862016-01-15 15:50:07 +010026
27extern struct nc_server_opts server_opts;
Michal Vasko7bcb48e2016-01-15 10:28:54 +010028
29API struct nc_server_reply *
30nc_server_reply_ok(void)
31{
32 struct nc_server_reply *ret;
33
34 ret = malloc(sizeof *ret);
35 if (!ret) {
36 ERRMEM;
37 return NULL;
38 }
39
40 ret->type = NC_RPL_OK;
41 return ret;
42}
43
44API struct nc_server_reply *
Radek Krejci36dfdb32016-09-01 16:56:35 +020045nc_server_reply_data(struct lyd_node *data, NC_WD_MODE wd, NC_PARAMTYPE paramtype)
Michal Vasko7bcb48e2016-01-15 10:28:54 +010046{
47 struct nc_server_reply_data *ret;
48
Michal Vaskob08743b2016-04-13 14:23:49 +020049 if (!data) {
50 ERRARG("data");
51 return NULL;
52 }
53
Michal Vasko7bcb48e2016-01-15 10:28:54 +010054 ret = malloc(sizeof *ret);
55 if (!ret) {
56 ERRMEM;
57 return NULL;
58 }
59
60 ret->type = NC_RPL_DATA;
Radek Krejci36dfdb32016-09-01 16:56:35 +020061 ret->wd = wd;
Michal Vaskob08743b2016-04-13 14:23:49 +020062 if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
Michal Vasko77367452021-02-16 16:32:18 +010063 if (lyd_dup_single(data, NULL, LYD_DUP_RECURSIVE, &ret->data)) {
64 free(ret);
65 return NULL;
66 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +010067 } else {
68 ret->data = data;
69 }
70 if (paramtype != NC_PARAMTYPE_CONST) {
71 ret->free = 1;
72 } else {
73 ret->free = 0;
74 }
75 return (struct nc_server_reply *)ret;
76}
77
78API struct nc_server_reply *
Michal Vasko77367452021-02-16 16:32:18 +010079nc_server_reply_err(struct lyd_node *err)
Michal Vasko7bcb48e2016-01-15 10:28:54 +010080{
81 struct nc_server_reply_error *ret;
82
Michal Vasko1a38c862016-01-15 15:50:07 +010083 if (!err) {
Michal Vasko45e53ae2016-04-07 11:46:03 +020084 ERRARG("err");
Michal Vasko7bcb48e2016-01-15 10:28:54 +010085 return NULL;
86 }
87
88 ret = malloc(sizeof *ret);
89 if (!ret) {
90 ERRMEM;
91 return NULL;
92 }
93
94 ret->type = NC_RPL_ERROR;
Michal Vasko77367452021-02-16 16:32:18 +010095 ret->err = err;
Michal Vasko7bcb48e2016-01-15 10:28:54 +010096 return (struct nc_server_reply *)ret;
97}
98
99API int
Michal Vasko77367452021-02-16 16:32:18 +0100100nc_server_reply_add_err(struct nc_server_reply *reply, struct lyd_node *err)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100101{
102 struct nc_server_reply_error *err_rpl;
103
Michal Vasko45e53ae2016-04-07 11:46:03 +0200104 if (!reply || (reply->type != NC_RPL_ERROR)) {
105 ERRARG("reply");
106 return -1;
107 } else if (!err) {
108 ERRARG("err");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100109 return -1;
110 }
111
112 err_rpl = (struct nc_server_reply_error *)reply;
Michal Vasko77367452021-02-16 16:32:18 +0100113 lyd_insert_sibling(err_rpl->err, err, &err_rpl->err);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100114 return 0;
115}
116
Michal Vasko77367452021-02-16 16:32:18 +0100117API const struct lyd_node *
Michal Vaskoaa2e5a72017-03-16 09:48:44 +0100118nc_server_reply_get_last_err(const struct nc_server_reply *reply)
119{
120 struct nc_server_reply_error *err_rpl;
121
122 if (!reply || (reply->type != NC_RPL_ERROR)) {
123 ERRARG("reply");
124 return NULL;
125 }
126
127 err_rpl = (struct nc_server_reply_error *)reply;
Michal Vasko77367452021-02-16 16:32:18 +0100128 if (!err_rpl->err) {
Michal Vaskoaa2e5a72017-03-16 09:48:44 +0100129 return NULL;
130 }
Michal Vasko77367452021-02-16 16:32:18 +0100131 return err_rpl->err->prev;
Michal Vaskoaa2e5a72017-03-16 09:48:44 +0100132}
133
Michal Vasko77367452021-02-16 16:32:18 +0100134static const char *
135nc_err_tag2str(NC_ERR tag)
136{
137 switch (tag) {
138 case NC_ERR_IN_USE:
139 return "in-use";
140 case NC_ERR_INVALID_VALUE:
141 return "invalid-value";
142 case NC_ERR_ACCESS_DENIED:
143 return "access-denied";
144 case NC_ERR_ROLLBACK_FAILED:
145 return "rollback-failed";
146 case NC_ERR_OP_NOT_SUPPORTED:
147 return "operation-not-supported";
148 case NC_ERR_TOO_BIG:
149 return "too-big";
150 case NC_ERR_RES_DENIED:
151 return "resource-denied";
152 case NC_ERR_MISSING_ATTR:
153 return "missing-attribute";
154 case NC_ERR_BAD_ATTR:
155 return "bad-attribute";
156 case NC_ERR_UNKNOWN_ATTR:
157 return "unknown-attribute";
158 case NC_ERR_MISSING_ELEM:
159 return "missing-element";
160 case NC_ERR_BAD_ELEM:
161 return "bad-element";
162 case NC_ERR_UNKNOWN_ELEM:
163 return "unknown-element";
164 case NC_ERR_UNKNOWN_NS:
165 return "unknown-namespace";
166 case NC_ERR_LOCK_DENIED:
167 return "lock-denied";
168 case NC_ERR_DATA_EXISTS:
169 return "data-exists";
170 case NC_ERR_DATA_MISSING:
171 return "data-missing";
172 case NC_ERR_OP_FAILED:
173 return "operation-failed";
174 case NC_ERR_MALFORMED_MSG:
175 return "malformed-message";
176 default:
177 break;
178 }
179
180 return NULL;
181}
182
183static NC_ERR
184nc_err_str2tag(const char *str)
185{
186 if (!strcmp(str, "in-use")) {
187 return NC_ERR_IN_USE;
188 } else if (!strcmp(str, "invalid-value")) {
189 return NC_ERR_INVALID_VALUE;
190 } else if (!strcmp(str, "access-denied")) {
191 return NC_ERR_ACCESS_DENIED;
192 } else if (!strcmp(str, "rollback-failed")) {
193 return NC_ERR_ROLLBACK_FAILED;
194 } else if (!strcmp(str, "operation-not-supported")) {
195 return NC_ERR_OP_NOT_SUPPORTED;
196 } else if (!strcmp(str, "too-big")) {
197 return NC_ERR_TOO_BIG;
198 } else if (!strcmp(str, "resource-denied")) {
199 return NC_ERR_RES_DENIED;
200 } else if (!strcmp(str, "missing-attribute")) {
201 return NC_ERR_MISSING_ATTR;
202 } else if (!strcmp(str, "bad-attribute")) {
203 return NC_ERR_BAD_ATTR;
204 } else if (!strcmp(str, "unknown-attribute")) {
205 return NC_ERR_UNKNOWN_ATTR;
206 } else if (!strcmp(str, "missing-element")) {
207 return NC_ERR_MISSING_ELEM;
208 } else if (!strcmp(str, "bad-element")) {
209 return NC_ERR_BAD_ELEM;
210 } else if (!strcmp(str, "unknown-element")) {
211 return NC_ERR_UNKNOWN_ELEM;
212 } else if (!strcmp(str, "unknown-namespace")) {
213 return NC_ERR_UNKNOWN_NS;
214 } else if (!strcmp(str, "lock-denied")) {
215 return NC_ERR_LOCK_DENIED;
216 } else if (!strcmp(str, "data-exists")) {
217 return NC_ERR_DATA_EXISTS;
218 } else if (!strcmp(str, "data-missing")) {
219 return NC_ERR_DATA_MISSING;
220 } else if (!strcmp(str, "operation-failed")) {
221 return NC_ERR_OP_FAILED;
222 } else if (!strcmp(str, "malformed-message")) {
223 return NC_ERR_MALFORMED_MSG;
224 }
225
226 return 0;
227}
228
229static const char *
230nc_err_type2str(NC_ERR_TYPE type)
231{
232 switch (type) {
233 case NC_ERR_TYPE_TRAN:
234 return "transport";
235 case NC_ERR_TYPE_RPC:
236 return "rpc";
237 case NC_ERR_TYPE_PROT:
238 return "protocol";
239 case NC_ERR_TYPE_APP:
240 return "application";
241 default:
242 break;
243 }
244
245 return NULL;
246}
247
248static NC_ERR_TYPE
249nc_err_str2type(const char *str)
250{
251 if (!strcmp(str, "transport")) {
252 return NC_ERR_TYPE_TRAN;
253 } else if (!strcmp(str, "rpc")) {
254 return NC_ERR_TYPE_RPC;
255 } else if (!strcmp(str, "protocol")) {
256 return NC_ERR_TYPE_PROT;
257 } else if (!strcmp(str, "application")) {
258 return NC_ERR_TYPE_APP;
259 }
260
261 return 0;
262}
263
264API struct lyd_node *
265nc_err(const struct ly_ctx *ctx, NC_ERR tag, ...)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100266{
267 va_list ap;
Michal Vasko77367452021-02-16 16:32:18 +0100268 struct lyd_node *err = NULL;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100269 NC_ERR_TYPE type;
270 const char *arg1, *arg2;
271 uint32_t sid;
272
Michal Vasko1a38c862016-01-15 15:50:07 +0100273 if (!tag) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200274 ERRARG("tag");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100275 return NULL;
276 }
277
Michal Vasko77367452021-02-16 16:32:18 +0100278 /* rpc-error */
279 if (lyd_new_opaq2(NULL, ctx, "rpc-error", NULL, NULL, NC_NS_BASE, &err)) {
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100280 return NULL;
281 }
282
283 va_start(ap, tag);
284
Michal Vasko77367452021-02-16 16:32:18 +0100285 /* error-type */
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100286 switch (tag) {
287 case NC_ERR_IN_USE:
288 case NC_ERR_INVALID_VALUE:
289 case NC_ERR_ACCESS_DENIED:
290 case NC_ERR_ROLLBACK_FAILED:
291 case NC_ERR_OP_NOT_SUPPORTED:
Radek Krejci127f8952016-10-12 14:57:16 +0200292 type = (NC_ERR_TYPE)va_arg(ap, int); /* NC_ERR_TYPE enum is automatically promoted to int */
Michal Vasko2f923d12016-04-05 11:33:02 +0200293 if ((type != NC_ERR_TYPE_PROT) && (type != NC_ERR_TYPE_APP)) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200294 ERRARG("type");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100295 goto fail;
296 }
297 break;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100298 case NC_ERR_TOO_BIG:
299 case NC_ERR_RES_DENIED:
Michal Vasko77367452021-02-16 16:32:18 +0100300 type = (NC_ERR_TYPE)va_arg(ap, int);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100301 break;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100302 case NC_ERR_MISSING_ATTR:
303 case NC_ERR_BAD_ATTR:
304 case NC_ERR_UNKNOWN_ATTR:
Michal Vasko77367452021-02-16 16:32:18 +0100305 type = (NC_ERR_TYPE)va_arg(ap, int);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100306 if (type == NC_ERR_TYPE_TRAN) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200307 ERRARG("type");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100308 goto fail;
309 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100310 break;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100311 case NC_ERR_MISSING_ELEM:
312 case NC_ERR_BAD_ELEM:
313 case NC_ERR_UNKNOWN_ELEM:
Michal Vasko77367452021-02-16 16:32:18 +0100314 type = (NC_ERR_TYPE)va_arg(ap, int);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100315 if ((type != NC_ERR_TYPE_PROT) && (type != NC_ERR_TYPE_APP)) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200316 ERRARG("type");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100317 goto fail;
318 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100319 break;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100320 case NC_ERR_UNKNOWN_NS:
Michal Vasko77367452021-02-16 16:32:18 +0100321 type = (NC_ERR_TYPE)va_arg(ap, int);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100322 if ((type != NC_ERR_TYPE_PROT) && (type != NC_ERR_TYPE_APP)) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200323 ERRARG("type");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100324 goto fail;
325 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100326 break;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100327 case NC_ERR_LOCK_DENIED:
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100328 type = NC_ERR_TYPE_PROT;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100329 break;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100330 case NC_ERR_DATA_EXISTS:
331 case NC_ERR_DATA_MISSING:
332 type = NC_ERR_TYPE_APP;
333 break;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100334 case NC_ERR_OP_FAILED:
Michal Vasko77367452021-02-16 16:32:18 +0100335 type = (NC_ERR_TYPE)va_arg(ap, int);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100336 if (type == NC_ERR_TYPE_TRAN) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200337 ERRARG("type");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100338 goto fail;
339 }
340 break;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100341 case NC_ERR_MALFORMED_MSG:
342 type = NC_ERR_TYPE_RPC;
343 break;
Michal Vasko77367452021-02-16 16:32:18 +0100344 default:
345 ERRARG("tag");
346 goto fail;
347 }
348 if (lyd_new_opaq2(err, NULL, "error-type", nc_err_type2str(type), NULL, NC_NS_BASE, NULL)) {
349 goto fail;
350 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100351
Michal Vasko77367452021-02-16 16:32:18 +0100352 /* error-tag */
353 if (lyd_new_opaq2(err, NULL, "error-tag", nc_err_tag2str(tag), NULL, NC_NS_BASE, NULL)) {
354 goto fail;
355 }
356
357 /* error-severity */
358 if (lyd_new_opaq2(err, NULL, "error-severity", "error", NULL, NC_NS_BASE, NULL)) {
359 goto fail;
360 }
361
362 /* error-message */
363 switch (tag) {
364 case NC_ERR_IN_USE:
365 nc_err_set_msg(err, "The request requires a resource that already is in use.", "en");
366 break;
367 case NC_ERR_INVALID_VALUE:
368 nc_err_set_msg(err, "The request specifies an unacceptable value for one or more parameters.", "en");
369 break;
370 case NC_ERR_TOO_BIG:
371 nc_err_set_msg(err, "The request or response (that would be generated) is too large for the implementation to handle.", "en");
372 break;
373 case NC_ERR_MISSING_ATTR:
374 nc_err_set_msg(err, "An expected attribute is missing.", "en");
375 break;
376 case NC_ERR_BAD_ATTR:
377 nc_err_set_msg(err, "An attribute value is not correct.", "en");
378 break;
379 case NC_ERR_UNKNOWN_ATTR:
380 nc_err_set_msg(err, "An unexpected attribute is present.", "en");
381 break;
382 case NC_ERR_MISSING_ELEM:
383 nc_err_set_msg(err, "An expected element is missing.", "en");
384 break;
385 case NC_ERR_BAD_ELEM:
386 nc_err_set_msg(err, "An element value is not correct.", "en");
387 break;
388 case NC_ERR_UNKNOWN_ELEM:
389 nc_err_set_msg(err, "An unexpected element is present.", "en");
390 break;
391 case NC_ERR_UNKNOWN_NS:
392 nc_err_set_msg(err, "An unexpected namespace is present.", "en");
393 break;
394 case NC_ERR_ACCESS_DENIED:
395 nc_err_set_msg(err, "Access to the requested protocol operation or data model is denied because authorization failed.", "en");
396 break;
397 case NC_ERR_LOCK_DENIED:
398 nc_err_set_msg(err, "Access to the requested lock is denied because the lock is currently held by another entity.", "en");
399 break;
400 case NC_ERR_RES_DENIED:
401 nc_err_set_msg(err, "Request could not be completed because of insufficient resources.", "en");
402 break;
403 case NC_ERR_ROLLBACK_FAILED:
404 nc_err_set_msg(err, "Request to roll back some configuration change was not completed for some reason.", "en");
405 break;
406 case NC_ERR_DATA_EXISTS:
407 nc_err_set_msg(err, "Request could not be completed because the relevant data model content already exists.", "en");
408 break;
409 case NC_ERR_DATA_MISSING:
410 nc_err_set_msg(err, "Request could not be completed because the relevant data model content does not exist.", "en");
411 break;
412 case NC_ERR_OP_NOT_SUPPORTED:
413 nc_err_set_msg(err, "Request could not be completed because the requested operation is not supported by this implementation.", "en");
414 break;
415 case NC_ERR_OP_FAILED:
416 nc_err_set_msg(err, "Request could not be completed because the requested operation failed for a non-specific reason.", "en");
417 break;
418 case NC_ERR_MALFORMED_MSG:
419 nc_err_set_msg(err, "A message could not be handled because it failed to be parsed correctly.", "en");
420 break;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100421 default:
Michal Vasko45e53ae2016-04-07 11:46:03 +0200422 ERRARG("tag");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100423 goto fail;
424 }
425
Michal Vasko77367452021-02-16 16:32:18 +0100426 /* error-info */
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100427 switch (tag) {
428 case NC_ERR_IN_USE:
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100429 case NC_ERR_INVALID_VALUE:
Michal Vasko77367452021-02-16 16:32:18 +0100430 case NC_ERR_ACCESS_DENIED:
431 case NC_ERR_ROLLBACK_FAILED:
432 case NC_ERR_OP_NOT_SUPPORTED:
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100433 case NC_ERR_TOO_BIG:
Michal Vasko77367452021-02-16 16:32:18 +0100434 case NC_ERR_RES_DENIED:
435 case NC_ERR_DATA_EXISTS:
436 case NC_ERR_DATA_MISSING:
437 case NC_ERR_OP_FAILED:
438 case NC_ERR_MALFORMED_MSG:
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100439 break;
440 case NC_ERR_MISSING_ATTR:
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100441 case NC_ERR_BAD_ATTR:
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100442 case NC_ERR_UNKNOWN_ATTR:
Michal Vasko77367452021-02-16 16:32:18 +0100443 arg1 = va_arg(ap, const char *);
444 arg2 = va_arg(ap, const char *);
445
446 nc_err_add_bad_attr(err, arg1);
447 nc_err_add_bad_elem(err, arg2);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100448 break;
449 case NC_ERR_MISSING_ELEM:
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100450 case NC_ERR_BAD_ELEM:
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100451 case NC_ERR_UNKNOWN_ELEM:
Michal Vasko77367452021-02-16 16:32:18 +0100452 arg1 = va_arg(ap, const char *);
453
454 nc_err_add_bad_elem(err, arg1);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100455 break;
456 case NC_ERR_UNKNOWN_NS:
Michal Vasko77367452021-02-16 16:32:18 +0100457 arg1 = va_arg(ap, const char *);
458 arg2 = va_arg(ap, const char *);
459
460 nc_err_add_bad_elem(err, arg1);
461 nc_err_add_bad_ns(err, arg2);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100462 break;
463 case NC_ERR_LOCK_DENIED:
Michal Vasko77367452021-02-16 16:32:18 +0100464 sid = va_arg(ap, uint32_t);
465
466 nc_err_set_sid(err, sid);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100467 break;
468 default:
Michal Vasko45e53ae2016-04-07 11:46:03 +0200469 ERRARG("tag");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100470 goto fail;
471 }
472
473 va_end(ap);
Michal Vasko77367452021-02-16 16:32:18 +0100474 return err;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100475
476fail:
Michal Vasko11d142a2016-01-19 15:58:24 +0100477 va_end(ap);
Michal Vasko77367452021-02-16 16:32:18 +0100478 lyd_free_siblings(err);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100479 return NULL;
480}
481
Michal Vasko8f3198f2016-05-04 10:45:28 +0200482API NC_ERR_TYPE
Michal Vasko77367452021-02-16 16:32:18 +0100483nc_err_get_type(const struct lyd_node *err)
Michal Vasko8f3198f2016-05-04 10:45:28 +0200484{
Michal Vasko77367452021-02-16 16:32:18 +0100485 struct lyd_node *match;
486
Michal Vasko8f3198f2016-05-04 10:45:28 +0200487 if (!err) {
488 ERRARG("err");
489 return 0;
490 }
491
Michal Vasko77367452021-02-16 16:32:18 +0100492 lyd_find_sibling_opaq_next(lyd_child(err), "error-type", &match);
493 if (match) {
494 return nc_err_str2type(((struct lyd_node_opaq *)match)->value);
495 }
496
497 return 0;
Michal Vasko8f3198f2016-05-04 10:45:28 +0200498}
499
500API NC_ERR
Michal Vasko77367452021-02-16 16:32:18 +0100501nc_err_get_tag(const struct lyd_node *err)
Michal Vasko8f3198f2016-05-04 10:45:28 +0200502{
Michal Vasko77367452021-02-16 16:32:18 +0100503 struct lyd_node *match;
504
Michal Vasko8f3198f2016-05-04 10:45:28 +0200505 if (!err) {
506 ERRARG("err");
507 return 0;
508 }
509
Michal Vasko77367452021-02-16 16:32:18 +0100510 lyd_find_sibling_opaq_next(lyd_child(err), "error-tag", &match);
511 if (match) {
512 return nc_err_str2tag(((struct lyd_node_opaq *)match)->value);
513 }
514
515 return 0;
Michal Vasko8f3198f2016-05-04 10:45:28 +0200516}
517
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100518API int
Michal Vasko77367452021-02-16 16:32:18 +0100519nc_err_set_app_tag(struct lyd_node *err, const char *error_app_tag)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100520{
Michal Vasko77367452021-02-16 16:32:18 +0100521 struct lyd_node *match;
522
Michal Vasko45e53ae2016-04-07 11:46:03 +0200523 if (!err) {
524 ERRARG("err");
525 return -1;
526 } else if (!error_app_tag) {
527 ERRARG("error_app_tag");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100528 return -1;
529 }
530
Michal Vasko77367452021-02-16 16:32:18 +0100531 /* remove previous node */
532 lyd_find_sibling_opaq_next(lyd_child(err), "error-app-tag", &match);
533 if (match) {
534 lyd_free_tree(match);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100535 }
Michal Vasko77367452021-02-16 16:32:18 +0100536
537 if (lyd_new_opaq2(err, NULL, "error-app-tag", error_app_tag, NULL, NC_NS_BASE, NULL)) {
538 return -1;
539 }
Michal Vasko11d142a2016-01-19 15:58:24 +0100540
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100541 return 0;
542}
543
Michal Vasko8f3198f2016-05-04 10:45:28 +0200544API const char *
Michal Vasko77367452021-02-16 16:32:18 +0100545nc_err_get_app_tag(const struct lyd_node *err)
Michal Vasko8f3198f2016-05-04 10:45:28 +0200546{
Michal Vasko77367452021-02-16 16:32:18 +0100547 struct lyd_node *match;
548
Michal Vasko8f3198f2016-05-04 10:45:28 +0200549 if (!err) {
550 ERRARG("err");
551 return NULL;
552 }
553
Michal Vasko77367452021-02-16 16:32:18 +0100554 lyd_find_sibling_opaq_next(lyd_child(err), "error-app-tag", &match);
555 if (match) {
556 return ((struct lyd_node_opaq *)match)->value;
557 }
558
559 return NULL;
Michal Vasko8f3198f2016-05-04 10:45:28 +0200560}
561
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100562API int
Michal Vasko77367452021-02-16 16:32:18 +0100563nc_err_set_path(struct lyd_node *err, const char *error_path)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100564{
Michal Vasko77367452021-02-16 16:32:18 +0100565 struct lyd_node *match;
566
Michal Vasko45e53ae2016-04-07 11:46:03 +0200567 if (!err) {
568 ERRARG("err");
569 return -1;
570 } else if (!error_path) {
571 ERRARG("error_path");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100572 return -1;
573 }
574
Michal Vasko77367452021-02-16 16:32:18 +0100575 /* remove previous node */
576 lyd_find_sibling_opaq_next(lyd_child(err), "error-path", &match);
577 if (match) {
578 lyd_free_tree(match);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100579 }
Michal Vasko77367452021-02-16 16:32:18 +0100580
581 if (lyd_new_opaq2(err, NULL, "error-path", error_path, NULL, NC_NS_BASE, NULL)) {
582 return -1;
583 }
Michal Vasko11d142a2016-01-19 15:58:24 +0100584
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100585 return 0;
586}
587
Michal Vasko8f3198f2016-05-04 10:45:28 +0200588API const char *
Michal Vasko77367452021-02-16 16:32:18 +0100589nc_err_get_path(const struct lyd_node *err)
Michal Vasko8f3198f2016-05-04 10:45:28 +0200590{
Michal Vasko77367452021-02-16 16:32:18 +0100591 struct lyd_node *match;
592
Michal Vasko8f3198f2016-05-04 10:45:28 +0200593 if (!err) {
594 ERRARG("err");
595 return 0;
596 }
597
Michal Vasko77367452021-02-16 16:32:18 +0100598 lyd_find_sibling_opaq_next(lyd_child(err), "error-path", &match);
599 if (match) {
600 return ((struct lyd_node_opaq *)match)->value;
601 }
602
603 return NULL;
Michal Vasko8f3198f2016-05-04 10:45:28 +0200604}
605
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100606API int
Michal Vasko77367452021-02-16 16:32:18 +0100607nc_err_set_msg(struct lyd_node *err, const char *error_message, const char *lang)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100608{
Michal Vasko77367452021-02-16 16:32:18 +0100609 struct lyd_node *match;
610 struct lyd_attr *attr;
611
Michal Vasko45e53ae2016-04-07 11:46:03 +0200612 if (!err) {
613 ERRARG("err");
614 return -1;
615 } else if (!error_message) {
616 ERRARG("error_message");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100617 return -1;
618 }
619
Michal Vasko77367452021-02-16 16:32:18 +0100620 /* remove previous message */
621 lyd_find_sibling_opaq_next(lyd_child(err), "error-message", &match);
622 if (match) {
623 lyd_free_tree(match);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100624 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100625
Michal Vasko77367452021-02-16 16:32:18 +0100626 if (lyd_new_opaq2(err, NULL, "error-message", error_message, NULL, NC_NS_BASE, &match)) {
627 return -1;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100628 }
Michal Vasko77367452021-02-16 16:32:18 +0100629 if (lang && lyd_new_attr(match, NULL, "xml:lang", lang, &attr)) {
630 lyd_free_tree(match);
631 return -1;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100632 }
Michal Vasko11d142a2016-01-19 15:58:24 +0100633
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100634 return 0;
635}
636
Michal Vasko8f3198f2016-05-04 10:45:28 +0200637API const char *
Michal Vasko77367452021-02-16 16:32:18 +0100638nc_err_get_msg(const struct lyd_node *err)
Michal Vasko8f3198f2016-05-04 10:45:28 +0200639{
Michal Vasko77367452021-02-16 16:32:18 +0100640 struct lyd_node *match;
641
Michal Vasko8f3198f2016-05-04 10:45:28 +0200642 if (!err) {
643 ERRARG("err");
Michal Vasko77367452021-02-16 16:32:18 +0100644 return NULL;
Michal Vasko8f3198f2016-05-04 10:45:28 +0200645 }
646
Michal Vasko77367452021-02-16 16:32:18 +0100647 lyd_find_sibling_opaq_next(lyd_child(err), "error-message", &match);
648 if (match) {
649 return ((struct lyd_node_opaq *)match)->value;
650 }
651
652 return NULL;
Michal Vasko8f3198f2016-05-04 10:45:28 +0200653}
654
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100655API int
Michal Vasko77367452021-02-16 16:32:18 +0100656nc_err_set_sid(struct lyd_node *err, uint32_t session_id)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100657{
Michal Vasko77367452021-02-16 16:32:18 +0100658 struct lyd_node *match, *info;
659 char buf[22];
660
Michal Vasko45e53ae2016-04-07 11:46:03 +0200661 if (!err) {
662 ERRARG("err");
663 return -1;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100664 }
665
Michal Vasko77367452021-02-16 16:32:18 +0100666 /* find error-info */
667 lyd_find_sibling_opaq_next(lyd_child(err), "error-info", &info);
668 if (!info && lyd_new_opaq2(err, NULL, "error-info", NULL, NULL, NC_NS_BASE, &info)) {
669 return -1;
670 }
671
672 /* remove previous node */
673 lyd_find_sibling_opaq_next(lyd_child(info), "session-id", &match);
674 if (match) {
675 lyd_free_tree(match);
676 }
677
678 sprintf(buf, "%" PRIu32, session_id);
679 if (lyd_new_opaq2(info, NULL, "session-id", buf, NULL, NC_NS_BASE, NULL)) {
680 return -1;
681 }
682
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100683 return 0;
684}
685
686API int
Michal Vasko77367452021-02-16 16:32:18 +0100687nc_err_add_bad_attr(struct lyd_node *err, const char *attr_name)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100688{
Michal Vasko77367452021-02-16 16:32:18 +0100689 struct lyd_node *info;
690
Michal Vasko45e53ae2016-04-07 11:46:03 +0200691 if (!err) {
692 ERRARG("err");
693 return -1;
694 } else if (!attr_name) {
695 ERRARG("attr_name");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100696 return -1;
697 }
698
Michal Vasko77367452021-02-16 16:32:18 +0100699 /* find error-info */
700 lyd_find_sibling_opaq_next(lyd_child(err), "error-info", &info);
701 if (!info && lyd_new_opaq2(err, NULL, "error-info", NULL, NULL, NC_NS_BASE, &info)) {
Michal Vasko4eb3c312016-03-01 14:09:37 +0100702 return -1;
703 }
Michal Vasko77367452021-02-16 16:32:18 +0100704
705 if (lyd_new_opaq2(info, NULL, "bad-attribute", attr_name, NULL, NC_NS_BASE, NULL)) {
706 return -1;
707 }
Michal Vasko11d142a2016-01-19 15:58:24 +0100708
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100709 return 0;
710}
711
712API int
Michal Vasko77367452021-02-16 16:32:18 +0100713nc_err_add_bad_elem(struct lyd_node *err, const char *elem_name)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100714{
Michal Vasko77367452021-02-16 16:32:18 +0100715 struct lyd_node *info;
716
Michal Vasko45e53ae2016-04-07 11:46:03 +0200717 if (!err) {
718 ERRARG("err");
719 return -1;
720 } else if (!elem_name) {
721 ERRARG("elem_name");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100722 return -1;
723 }
724
Michal Vasko77367452021-02-16 16:32:18 +0100725 /* find error-info */
726 lyd_find_sibling_opaq_next(lyd_child(err), "error-info", &info);
727 if (!info && lyd_new_opaq2(err, NULL, "error-info", NULL, NULL, NC_NS_BASE, &info)) {
Michal Vasko4eb3c312016-03-01 14:09:37 +0100728 return -1;
729 }
Michal Vasko77367452021-02-16 16:32:18 +0100730
731 if (lyd_new_opaq2(info, NULL, "bad-element", elem_name, NULL, NC_NS_BASE, NULL)) {
732 return -1;
733 }
Michal Vasko11d142a2016-01-19 15:58:24 +0100734
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100735 return 0;
736}
737
738API int
Michal Vasko77367452021-02-16 16:32:18 +0100739nc_err_add_bad_ns(struct lyd_node *err, const char *ns_name)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100740{
Michal Vasko77367452021-02-16 16:32:18 +0100741 struct lyd_node *info;
742
Michal Vasko45e53ae2016-04-07 11:46:03 +0200743 if (!err) {
744 ERRARG("err");
745 return -1;
746 } else if (!ns_name) {
747 ERRARG("ns_name");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100748 return -1;
749 }
750
Michal Vasko77367452021-02-16 16:32:18 +0100751 /* find error-info */
752 lyd_find_sibling_opaq_next(lyd_child(err), "error-info", &info);
753 if (!info && lyd_new_opaq2(err, NULL, "error-info", NULL, NULL, NC_NS_BASE, &info)) {
Michal Vasko4eb3c312016-03-01 14:09:37 +0100754 return -1;
755 }
Michal Vasko77367452021-02-16 16:32:18 +0100756
757 if (lyd_new_opaq2(info, NULL, "bad-namespace", ns_name, NULL, NC_NS_BASE, NULL)) {
758 return -1;
759 }
Michal Vasko11d142a2016-01-19 15:58:24 +0100760
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100761 return 0;
762}
763
764API int
Michal Vasko77367452021-02-16 16:32:18 +0100765nc_err_add_info_other(struct lyd_node *err, struct lyd_node *other)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100766{
Michal Vasko77367452021-02-16 16:32:18 +0100767 struct lyd_node *info;
768
Michal Vasko45e53ae2016-04-07 11:46:03 +0200769 if (!err) {
770 ERRARG("err");
771 return -1;
772 } else if (!other) {
773 ERRARG("other");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100774 return -1;
775 }
776
Michal Vasko77367452021-02-16 16:32:18 +0100777 /* find error-info */
778 lyd_find_sibling_opaq_next(lyd_child(err), "error-info", &info);
779 if (!info && lyd_new_opaq2(err, NULL, "error-info", NULL, NULL, NC_NS_BASE, &info)) {
Michal Vasko4eb3c312016-03-01 14:09:37 +0100780 return -1;
781 }
Michal Vasko77367452021-02-16 16:32:18 +0100782
783 lyd_insert_child(info, other);
784
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100785 return 0;
786}
787
788void
Michal Vasko77367452021-02-16 16:32:18 +0100789nc_server_rpc_free(struct nc_server_rpc *rpc)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100790{
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100791 if (!rpc) {
792 return;
793 }
794
Michal Vasko77367452021-02-16 16:32:18 +0100795 lyd_free_tree(rpc->envp);
796 lyd_free_tree(rpc->rpc);
Michal Vasko11d142a2016-01-19 15:58:24 +0100797
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100798 free(rpc);
799}
800
801API void
802nc_server_reply_free(struct nc_server_reply *reply)
803{
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100804 struct nc_server_reply_data *data_rpl;
805 struct nc_server_reply_error *error_rpl;
806
807 if (!reply) {
808 return;
809 }
810
811 switch (reply->type) {
812 case NC_RPL_DATA:
813 data_rpl = (struct nc_server_reply_data *)reply;
814 if (data_rpl->free) {
Michal Vasko77367452021-02-16 16:32:18 +0100815 lyd_free_siblings(data_rpl->data);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100816 }
817 break;
818 case NC_RPL_OK:
819 /* nothing to free */
820 break;
821 case NC_RPL_ERROR:
822 error_rpl = (struct nc_server_reply_error *)reply;
Michal Vasko77367452021-02-16 16:32:18 +0100823 lyd_free_siblings(error_rpl->err);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100824 break;
825 default:
826 break;
827 }
828 free(reply);
829}
830
Radek Krejci93e80222016-10-03 13:34:25 +0200831API struct nc_server_notif *
Michal Vasko77367452021-02-16 16:32:18 +0100832nc_server_notif_new(struct lyd_node *event, char *eventtime, NC_PARAMTYPE paramtype)
Radek Krejci93e80222016-10-03 13:34:25 +0200833{
834 struct nc_server_notif *ntf;
Michal Vasko0b89f3d2018-01-04 10:57:03 +0100835 struct lyd_node *elem;
Michal Vasko77367452021-02-16 16:32:18 +0100836 int found;
Radek Krejci93e80222016-10-03 13:34:25 +0200837
Michal Vasko3106b7b2018-01-04 10:32:42 +0100838 if (!event) {
Radek Krejci93e80222016-10-03 13:34:25 +0200839 ERRARG("event");
840 return NULL;
841 } else if (!eventtime) {
842 ERRARG("eventtime");
843 return NULL;
844 }
845
Michal Vasko0b89f3d2018-01-04 10:57:03 +0100846 /* check that there is a notification */
Michal Vasko77367452021-02-16 16:32:18 +0100847 found = 0;
848 LYD_TREE_DFS_BEGIN(event, elem) {
849 if (elem->schema->nodetype == LYS_NOTIF) {
850 found = 1;
Michal Vasko0b89f3d2018-01-04 10:57:03 +0100851 break;
Michal Vasko0b89f3d2018-01-04 10:57:03 +0100852 }
Michal Vasko77367452021-02-16 16:32:18 +0100853 LYD_TREE_DFS_END(event, elem);
Michal Vasko0b89f3d2018-01-04 10:57:03 +0100854 }
Michal Vasko77367452021-02-16 16:32:18 +0100855 if (!found) {
Michal Vasko0b89f3d2018-01-04 10:57:03 +0100856 ERRARG("event");
857 return NULL;
858 }
859
Radek Krejci93e80222016-10-03 13:34:25 +0200860 ntf = malloc(sizeof *ntf);
Michal Vaskofc9dbdd2017-03-17 09:27:57 +0100861 if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
Radek Krejci93e80222016-10-03 13:34:25 +0200862 ntf->eventtime = strdup(eventtime);
Michal Vasko77367452021-02-16 16:32:18 +0100863 if (lyd_dup_single(event, NULL, LYD_DUP_RECURSIVE, &ntf->ntf)) {
864 free(ntf);
865 return NULL;
866 }
Radek Krejci93e80222016-10-03 13:34:25 +0200867 } else {
868 ntf->eventtime = eventtime;
Michal Vasko77367452021-02-16 16:32:18 +0100869 ntf->ntf = event;
Radek Krejci93e80222016-10-03 13:34:25 +0200870 }
Michal Vaskofc9dbdd2017-03-17 09:27:57 +0100871 ntf->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
Radek Krejci93e80222016-10-03 13:34:25 +0200872
873 return ntf;
874}
875
876API void
877nc_server_notif_free(struct nc_server_notif *notif)
878{
879 if (!notif) {
880 return;
881 }
882
Michal Vaskofc9dbdd2017-03-17 09:27:57 +0100883 if (notif->free) {
Michal Vasko77367452021-02-16 16:32:18 +0100884 lyd_free_tree(notif->ntf);
Michal Vaskofc9dbdd2017-03-17 09:27:57 +0100885 free(notif->eventtime);
886 }
Radek Krejci93e80222016-10-03 13:34:25 +0200887 free(notif);
888}
Michal Vasko9a2e4d22017-03-17 09:44:49 +0100889
890API const char *
891nc_server_notif_get_time(const struct nc_server_notif *notif)
892{
893 if (!notif) {
894 ERRARG("notif");
895 return NULL;
896 }
897
898 return notif->eventtime;
899}