blob: f8160f6e14e1da74ba27555530867eec51aba040 [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>
16#include <stdlib.h>
17#include <string.h>
18#include <stdarg.h>
19
20#include <libyang/libyang.h>
21
Michal Vasko11d142a2016-01-19 15:58:24 +010022#include "session_server.h"
Michal Vasko7bcb48e2016-01-15 10:28:54 +010023#include "libnetconf.h"
Michal Vasko1a38c862016-01-15 15:50:07 +010024
25extern struct nc_server_opts server_opts;
Michal Vasko7bcb48e2016-01-15 10:28:54 +010026
27API struct nc_server_reply *
28nc_server_reply_ok(void)
29{
30 struct nc_server_reply *ret;
31
32 ret = malloc(sizeof *ret);
33 if (!ret) {
34 ERRMEM;
35 return NULL;
36 }
37
38 ret->type = NC_RPL_OK;
39 return ret;
40}
41
42API struct nc_server_reply *
43nc_server_reply_data(struct lyd_node *data, NC_PARAMTYPE paramtype)
44{
45 struct nc_server_reply_data *ret;
46
Michal Vaskob08743b2016-04-13 14:23:49 +020047 if (!data) {
48 ERRARG("data");
49 return NULL;
50 }
51
Michal Vasko7bcb48e2016-01-15 10:28:54 +010052 ret = malloc(sizeof *ret);
53 if (!ret) {
54 ERRMEM;
55 return NULL;
56 }
57
58 ret->type = NC_RPL_DATA;
Michal Vaskob08743b2016-04-13 14:23:49 +020059 if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
Michal Vasko7bcb48e2016-01-15 10:28:54 +010060 ret->data = lyd_dup(data, 1);
61 } else {
62 ret->data = data;
63 }
64 if (paramtype != NC_PARAMTYPE_CONST) {
65 ret->free = 1;
66 } else {
67 ret->free = 0;
68 }
69 return (struct nc_server_reply *)ret;
70}
71
72API struct nc_server_reply *
Michal Vasko1a38c862016-01-15 15:50:07 +010073nc_server_reply_err(struct nc_server_error *err)
Michal Vasko7bcb48e2016-01-15 10:28:54 +010074{
75 struct nc_server_reply_error *ret;
76
Michal Vasko1a38c862016-01-15 15:50:07 +010077 if (!err) {
Michal Vasko45e53ae2016-04-07 11:46:03 +020078 ERRARG("err");
Michal Vasko7bcb48e2016-01-15 10:28:54 +010079 return NULL;
80 }
81
82 ret = malloc(sizeof *ret);
83 if (!ret) {
84 ERRMEM;
85 return NULL;
86 }
87
88 ret->type = NC_RPL_ERROR;
Michal Vasko7bcb48e2016-01-15 10:28:54 +010089 ret->err = malloc(sizeof *ret->err);
Michal Vasko4eb3c312016-03-01 14:09:37 +010090 if (!ret->err) {
91 ERRMEM;
92 free(ret);
93 return NULL;
94 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +010095 ret->err[0] = err;
96 ret->count = 1;
97 return (struct nc_server_reply *)ret;
98}
99
100API int
101nc_server_reply_add_err(struct nc_server_reply *reply, struct nc_server_error *err)
102{
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;
114 ++err_rpl->count;
Michal Vasko4eb3c312016-03-01 14:09:37 +0100115 err_rpl->err = nc_realloc(err_rpl->err, err_rpl->count * sizeof *err_rpl->err);
116 if (!err_rpl->err) {
117 ERRMEM;
118 return -1;
119 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100120 err_rpl->err[err_rpl->count - 1] = err;
121 return 0;
122}
123
124API struct nc_server_error *
Michal Vasko1a38c862016-01-15 15:50:07 +0100125nc_err(NC_ERR tag, ...)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100126{
127 va_list ap;
128 struct nc_server_error *ret;
129 NC_ERR_TYPE type;
130 const char *arg1, *arg2;
131 uint32_t sid;
132
Michal Vasko1a38c862016-01-15 15:50:07 +0100133 if (!tag) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200134 ERRARG("tag");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100135 return NULL;
136 }
137
138 ret = calloc(1, sizeof *ret);
139 if (!ret) {
140 ERRMEM;
141 return NULL;
142 }
Michal Vasko90920b02016-05-20 14:07:00 +0200143 ret->sid = -1;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100144
145 va_start(ap, tag);
146
147 switch (tag) {
148 case NC_ERR_IN_USE:
149 case NC_ERR_INVALID_VALUE:
150 case NC_ERR_ACCESS_DENIED:
151 case NC_ERR_ROLLBACK_FAILED:
152 case NC_ERR_OP_NOT_SUPPORTED:
153 type = va_arg(ap, NC_ERR_TYPE);
Michal Vasko2f923d12016-04-05 11:33:02 +0200154 if ((type != NC_ERR_TYPE_PROT) && (type != NC_ERR_TYPE_APP)) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200155 ERRARG("type");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100156 goto fail;
157 }
158 break;
159
160 case NC_ERR_TOO_BIG:
161 case NC_ERR_RES_DENIED:
162 type = va_arg(ap, NC_ERR_TYPE);
163 /* nothing to check */
164 break;
165
166 case NC_ERR_MISSING_ATTR:
167 case NC_ERR_BAD_ATTR:
168 case NC_ERR_UNKNOWN_ATTR:
169 type = va_arg(ap, NC_ERR_TYPE);
170 arg1 = va_arg(ap, const char *);
171 arg2 = va_arg(ap, const char *);
172
173 if (type == NC_ERR_TYPE_TRAN) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200174 ERRARG("type");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100175 goto fail;
176 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100177 nc_err_add_bad_attr(ret, arg1);
178 nc_err_add_bad_elem(ret, arg2);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100179 break;
180
181 case NC_ERR_MISSING_ELEM:
182 case NC_ERR_BAD_ELEM:
183 case NC_ERR_UNKNOWN_ELEM:
184 type = va_arg(ap, NC_ERR_TYPE);
185 arg1 = va_arg(ap, const char *);
186
187 if ((type != NC_ERR_TYPE_PROT) && (type != NC_ERR_TYPE_APP)) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200188 ERRARG("type");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100189 goto fail;
190 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100191 nc_err_add_bad_elem(ret, arg1);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100192 break;
193
194 case NC_ERR_UNKNOWN_NS:
195 type = va_arg(ap, NC_ERR_TYPE);
196 arg1 = va_arg(ap, const char *);
197 arg2 = va_arg(ap, const char *);
198
199 if ((type != NC_ERR_TYPE_PROT) && (type != NC_ERR_TYPE_APP)) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200200 ERRARG("type");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100201 goto fail;
202 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100203 nc_err_add_bad_elem(ret, arg1);
204 nc_err_add_bad_ns(ret, arg2);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100205 break;
206
207 case NC_ERR_LOCK_DENIED:
208 sid = va_arg(ap, uint32_t);
209
210 type = NC_ERR_TYPE_PROT;
211 nc_err_set_sid(ret, sid);
212 break;
213
214 case NC_ERR_DATA_EXISTS:
215 case NC_ERR_DATA_MISSING:
216 type = NC_ERR_TYPE_APP;
217 break;
218
219 case NC_ERR_OP_FAILED:
220 type = va_arg(ap, NC_ERR_TYPE);
221
222 if (type == NC_ERR_TYPE_TRAN) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200223 ERRARG("type");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100224 goto fail;
225 }
226 break;
227
228 case NC_ERR_MALFORMED_MSG:
229 type = NC_ERR_TYPE_RPC;
230 break;
231
232 default:
Michal Vasko45e53ae2016-04-07 11:46:03 +0200233 ERRARG("tag");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100234 goto fail;
235 }
236
237 switch (tag) {
238 case NC_ERR_IN_USE:
Michal Vasko1a38c862016-01-15 15:50:07 +0100239 nc_err_set_msg(ret, "The request requires a resource that already is in use.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100240 break;
241 case NC_ERR_INVALID_VALUE:
Michal Vasko1a38c862016-01-15 15:50:07 +0100242 nc_err_set_msg(ret, "The request specifies an unacceptable value for one or more parameters.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100243 break;
244 case NC_ERR_TOO_BIG:
Michal Vasko1a38c862016-01-15 15:50:07 +0100245 nc_err_set_msg(ret, "The request or response (that would be generated) is too large for the implementation to handle.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100246 break;
247 case NC_ERR_MISSING_ATTR:
Michal Vasko1a38c862016-01-15 15:50:07 +0100248 nc_err_set_msg(ret, "An expected attribute is missing.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100249 break;
250 case NC_ERR_BAD_ATTR:
Michal Vasko1a38c862016-01-15 15:50:07 +0100251 nc_err_set_msg(ret, "An attribute value is not correct.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100252 break;
253 case NC_ERR_UNKNOWN_ATTR:
Michal Vasko1a38c862016-01-15 15:50:07 +0100254 nc_err_set_msg(ret, "An unexpected attribute is present.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100255 break;
256 case NC_ERR_MISSING_ELEM:
Michal Vasko1a38c862016-01-15 15:50:07 +0100257 nc_err_set_msg(ret, "An expected element is missing.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100258 break;
259 case NC_ERR_BAD_ELEM:
Michal Vasko1a38c862016-01-15 15:50:07 +0100260 nc_err_set_msg(ret, "An element value is not correct.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100261 break;
262 case NC_ERR_UNKNOWN_ELEM:
Michal Vasko1a38c862016-01-15 15:50:07 +0100263 nc_err_set_msg(ret, "An unexpected element is present.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100264 break;
265 case NC_ERR_UNKNOWN_NS:
Michal Vasko1a38c862016-01-15 15:50:07 +0100266 nc_err_set_msg(ret, "An unexpected namespace is present.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100267 break;
268 case NC_ERR_ACCESS_DENIED:
Michal Vasko1a38c862016-01-15 15:50:07 +0100269 nc_err_set_msg(ret, "Access to the requested protocol operation or data model is denied because authorization failed.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100270 break;
271 case NC_ERR_LOCK_DENIED:
Michal Vasko1a38c862016-01-15 15:50:07 +0100272 nc_err_set_msg(ret, "Access to the requested lock is denied because the lock is currently held by another entity.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100273 break;
274 case NC_ERR_RES_DENIED:
Michal Vasko1a38c862016-01-15 15:50:07 +0100275 nc_err_set_msg(ret, "Request could not be completed because of insufficient resources.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100276 break;
277 case NC_ERR_ROLLBACK_FAILED:
Michal Vasko1a38c862016-01-15 15:50:07 +0100278 nc_err_set_msg(ret, "Request to roll back some configuration change was not completed for some reason.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100279 break;
280 case NC_ERR_DATA_EXISTS:
Michal Vasko1a38c862016-01-15 15:50:07 +0100281 nc_err_set_msg(ret, "Request could not be completed because the relevant data model content already exists.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100282 break;
283 case NC_ERR_DATA_MISSING:
Michal Vasko1a38c862016-01-15 15:50:07 +0100284 nc_err_set_msg(ret, "Request could not be completed because the relevant data model content does not exist.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100285 break;
286 case NC_ERR_OP_NOT_SUPPORTED:
Michal Vasko1a38c862016-01-15 15:50:07 +0100287 nc_err_set_msg(ret, "Request could not be completed because the requested operation is not supported by this implementation.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100288 break;
289 case NC_ERR_OP_FAILED:
Michal Vasko1a38c862016-01-15 15:50:07 +0100290 nc_err_set_msg(ret, "Request could not be completed because the requested operation failed for a non-specific reason.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100291 break;
292 case NC_ERR_MALFORMED_MSG:
Michal Vasko1a38c862016-01-15 15:50:07 +0100293 nc_err_set_msg(ret, "A message could not be handled because it failed to be parsed correctly.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100294 break;
295 default:
Michal Vasko45e53ae2016-04-07 11:46:03 +0200296 ERRARG("tag");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100297 goto fail;
298 }
299
300 va_end(ap);
301
302 ret->type = type;
303 ret->tag = tag;
304 return ret;
305
306fail:
Michal Vasko11d142a2016-01-19 15:58:24 +0100307 va_end(ap);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100308 free(ret);
309 return NULL;
310}
311
Michal Vaskoa08e5c02016-04-12 15:12:04 +0200312static struct lyxml_elem *
313nc_err_libyang_other_elem(const char *name, const char *content, int cont_len)
314{
315 struct lyxml_elem *root = NULL;
316 struct lyxml_ns *ns;
317
318 root = calloc(1, sizeof *root);
319 if (!root) {
320 ERRMEM;
321 goto error;
322 }
323 root->prev = root;
324 root->name = lydict_insert(server_opts.ctx, name, 0);
325 root->content = lydict_insert(server_opts.ctx, content, cont_len);
326
327 ns = calloc(1, sizeof *root->ns);
328 if (!ns) {
329 ERRMEM;
330 goto error;
331 }
332 root->attr = (struct lyxml_attr *)ns;
333 ns->type = LYXML_ATTR_NS;
334 ns->parent = root;
335 ns->value = lydict_insert(server_opts.ctx, "urn:ietf:params:xml:ns:yang:1", 0);
336 root->ns = ns;
337
338 return root;
339
340error:
341 lyxml_free(server_opts.ctx, root);
342 return NULL;
343}
344
Radek Krejci877e1822016-04-06 16:37:43 +0200345API struct nc_server_error *
346nc_err_libyang(void)
347{
348 struct nc_server_error *e;
Michal Vaskoa08e5c02016-04-12 15:12:04 +0200349 struct lyxml_elem *elem;
350 const char *str, *stri, *strj, *strk, *strl, *uniqi, *uniqj;
351 char *attr, *path;
352 int len;
Radek Krejci877e1822016-04-06 16:37:43 +0200353
354 if (!ly_errno) {
355 /* LY_SUCCESS */
356 return NULL;
357 } else if (ly_errno == LY_EVALID) {
358 switch (ly_vecode) {
Michal Vaskoa08e5c02016-04-12 15:12:04 +0200359 /* RFC 6020 section 13 errors */
360 case LYVE_NOUNIQ:
361 e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
362 nc_err_set_app_tag(e, "data-not-unique");
363 nc_err_set_path(e, ly_errpath());
364
365 /* parse the message and get all the information we need */
366 str = ly_errmsg();
367 uniqi = strchr(str, '"');
368 uniqi++;
369 uniqj = strchr(uniqi, '"');
370
371 stri = strchr(uniqj + 1, '"');
372 stri++;
373 strj = strchr(stri, '"');
374
375 strk = strchr(strj + 1, '"');
376 ++strk;
377 strl = strchr(strk, '"');
378
379 /* maximum length is the whole unique string with the longer list instance identifier */
380 len = (uniqj - uniqi) + (strj - stri > strl - strk ? strj - stri : strl - strk);
381 path = malloc(len + 1);
382 if (!path) {
383 ERRMEM;
384 return e;
385 }
386
387 /* create non-unique elements, one in 1st list, one in 2nd list, for each unique list */
388 while (1) {
389 uniqj = strpbrk(uniqi, " \"");
390
391 len = sprintf(path, "%.*s/%.*s", (int)(strj - stri), stri, (int)(uniqj - uniqi), uniqi);
392 elem = nc_err_libyang_other_elem("non-unique", path, len);
393 if (!elem) {
394 free(path);
395 return e;
396 }
397 nc_err_add_info_other(e, elem);
398
399 len = sprintf(path, "%.*s/%.*s", (int)(strl - strk), strk, (int)(uniqj - uniqi), uniqi);
400 elem = nc_err_libyang_other_elem("non-unique", path, len);
401 if (!elem) {
402 return e;
403 }
404 nc_err_add_info_other(e, elem);
405
406 if (uniqj[0] == '"') {
407 break;
408 }
409 uniqi = uniqj + 1;
410 }
411 free(path);
412 break;
413 case LYVE_NOMAX:
414 e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
415 nc_err_set_app_tag(e, "too-many-elements");
416 nc_err_set_path(e, ly_errpath());
417 break;
418 case LYVE_NOMIN:
419 e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
420 nc_err_set_app_tag(e, "too-few-elements");
421 nc_err_set_path(e, ly_errpath());
422 break;
423 case LYVE_NOMUST:
424 e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
425 if (ly_errapptag()[0]) {
426 nc_err_set_app_tag(e, ly_errapptag());
427 } else {
428 nc_err_set_app_tag(e, "must-violation");
429 }
430 break;
431 case LYVE_NOREQINS:
432 case LYVE_NOLEAFREF:
433 e = nc_err(NC_ERR_DATA_MISSING);
434 nc_err_set_app_tag(e, "instance-required");
435 nc_err_set_path(e, ly_errpath());
436 break;
437 case LYVE_NOMANDCHOICE:
438 e = nc_err(NC_ERR_DATA_MISSING);
439 nc_err_set_app_tag(e, "missing-choice");
440 nc_err_set_path(e, ly_errpath());
441
442 str = ly_errmsg();
443 stri = strchr(str, '"');
444 stri++;
445 strj = strchr(stri, '"');
446 elem = nc_err_libyang_other_elem("missing-choice", stri, strj - stri);
447 if (elem) {
448 nc_err_add_info_other(e, elem);
449 }
450 break;
Radek Krejci877e1822016-04-06 16:37:43 +0200451 case LYVE_INELEM:
452 str = ly_errpath();
453 if (!strcmp(str, "/")) {
454 e = nc_err(NC_ERR_OP_NOT_SUPPORTED, NC_ERR_TYPE_APP);
455 /* keep default message */
456 return e;
457 } else {
458 e = nc_err(NC_ERR_UNKNOWN_ELEM, NC_ERR_TYPE_PROT, ly_errpath());
459 }
460 break;
461 case LYVE_MISSELEM:
462 case LYVE_INORDER:
463 e = nc_err(NC_ERR_MISSING_ELEM, NC_ERR_TYPE_PROT, ly_errpath());
464 break;
465 case LYVE_INVAL:
466 e = nc_err(NC_ERR_BAD_ELEM, NC_ERR_TYPE_PROT, ly_errpath());
467 break;
468 case LYVE_INATTR:
469 case LYVE_MISSATTR:
Radek Krejci537fb522016-04-07 16:36:25 +0200470 case LYVE_INVALATTR:
Radek Krejci877e1822016-04-06 16:37:43 +0200471 str = ly_errmsg();
472 stri = strchr(str, '"');
473 stri++;
474 strj = strchr(stri, '"');
475 strj--;
476 attr = strndup(stri, strj - stri);
Radek Krejci537fb522016-04-07 16:36:25 +0200477 if (ly_vecode == LYVE_INATTR) {
478 e = nc_err(NC_ERR_UNKNOWN_ATTR, NC_ERR_TYPE_PROT, attr, ly_errpath());
479 } else if (ly_vecode == LYVE_MISSATTR) {
480 e = nc_err(NC_ERR_MISSING_ATTR, NC_ERR_TYPE_PROT, attr, ly_errpath());
481 } else { /* LYVE_INVALATTR */
482 e = nc_err(NC_ERR_BAD_ATTR, NC_ERR_TYPE_PROT, attr, ly_errpath());
483 }
Radek Krejci877e1822016-04-06 16:37:43 +0200484 free(attr);
485 break;
Michal Vaskoa08e5c02016-04-12 15:12:04 +0200486 case LYVE_NOCONSTR:
487 case LYVE_NOWHEN:
Radek Krejci877e1822016-04-06 16:37:43 +0200488 e = nc_err(NC_ERR_INVALID_VALUE, NC_ERR_TYPE_PROT);
Michal Vaskoa08e5c02016-04-12 15:12:04 +0200489 /* LYVE_NOCONSTR (length, range, pattern) can have a specific error-app-tag */
490 if (ly_errapptag()[0]) {
491 nc_err_set_app_tag(e, ly_errapptag());
492 }
Radek Krejci877e1822016-04-06 16:37:43 +0200493 break;
494 default:
495 e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
496 break;
497 }
498 } else {
499 /* non-validation (internal) error */
500 e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
501 }
502 nc_err_set_msg(e, ly_errmsg(), "en");
503 return e;
504}
505
Michal Vasko8f3198f2016-05-04 10:45:28 +0200506API NC_ERR_TYPE
507nc_err_get_type(struct nc_server_error *err)
508{
509 if (!err) {
510 ERRARG("err");
511 return 0;
512 }
513
514 return err->type;
515}
516
517API NC_ERR
518nc_err_get_tag(struct nc_server_error *err)
519{
520 if (!err) {
521 ERRARG("err");
522 return 0;
523 }
524
525 return err->tag;
526}
527
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100528API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100529nc_err_set_app_tag(struct nc_server_error *err, const char *error_app_tag)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100530{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200531 if (!err) {
532 ERRARG("err");
533 return -1;
534 } else if (!error_app_tag) {
535 ERRARG("error_app_tag");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100536 return -1;
537 }
538
539 if (err->apptag) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100540 lydict_remove(server_opts.ctx, err->apptag);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100541 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100542 err->apptag = lydict_insert(server_opts.ctx, error_app_tag, 0);
Michal Vasko11d142a2016-01-19 15:58:24 +0100543
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100544 return 0;
545}
546
Michal Vasko8f3198f2016-05-04 10:45:28 +0200547API const char *
548nc_err_get_app_tag(struct nc_server_error *err)
549{
550 if (!err) {
551 ERRARG("err");
552 return NULL;
553 }
554
555 return err->apptag;
556}
557
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100558API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100559nc_err_set_path(struct nc_server_error *err, const char *error_path)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100560{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200561 if (!err) {
562 ERRARG("err");
563 return -1;
564 } else if (!error_path) {
565 ERRARG("error_path");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100566 return -1;
567 }
568
569 if (err->path) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100570 lydict_remove(server_opts.ctx, err->path);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100571 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100572 err->path = lydict_insert(server_opts.ctx, error_path, 0);
Michal Vasko11d142a2016-01-19 15:58:24 +0100573
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100574 return 0;
575}
576
Michal Vasko8f3198f2016-05-04 10:45:28 +0200577API const char *
578nc_err_get_path(struct nc_server_error *err)
579{
580 if (!err) {
581 ERRARG("err");
582 return 0;
583 }
584
585 return err->path;
586}
587
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100588API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100589nc_err_set_msg(struct nc_server_error *err, const char *error_message, const char *lang)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100590{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200591 if (!err) {
592 ERRARG("err");
593 return -1;
594 } else if (!error_message) {
595 ERRARG("error_message");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100596 return -1;
597 }
598
599 if (err->message) {
Michal Vasko092ea742016-04-12 15:08:59 +0200600 lydict_remove(server_opts.ctx, err->message);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100601 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100602 err->message = lydict_insert(server_opts.ctx, error_message, 0);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100603
604 if (err->message_lang) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100605 lydict_remove(server_opts.ctx, err->message_lang);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100606 }
607 if (lang) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100608 err->message_lang = lydict_insert(server_opts.ctx, lang, 0);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100609 } else {
610 lang = NULL;
611 }
Michal Vasko11d142a2016-01-19 15:58:24 +0100612
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100613 return 0;
614}
615
Michal Vasko8f3198f2016-05-04 10:45:28 +0200616API const char *
617nc_err_get_msg(struct nc_server_error *err)
618{
619 if (!err) {
620 ERRARG("err");
621 return 0;
622 }
623
624 return err->message;
625}
626
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100627API int
628nc_err_set_sid(struct nc_server_error *err, uint32_t session_id)
629{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200630 if (!err) {
631 ERRARG("err");
632 return -1;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100633 }
634
635 err->sid = session_id;
636 return 0;
637}
638
639API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100640nc_err_add_bad_attr(struct nc_server_error *err, const char *attr_name)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100641{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200642 if (!err) {
643 ERRARG("err");
644 return -1;
645 } else if (!attr_name) {
646 ERRARG("attr_name");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100647 return -1;
648 }
649
650 ++err->attr_count;
Michal Vasko4eb3c312016-03-01 14:09:37 +0100651 err->attr = nc_realloc(err->attr, err->attr_count * sizeof *err->attr);
652 if (!err->attr) {
653 ERRMEM;
654 return -1;
655 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100656 err->attr[err->attr_count - 1] = lydict_insert(server_opts.ctx, attr_name, 0);
Michal Vasko11d142a2016-01-19 15:58:24 +0100657
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100658 return 0;
659}
660
661API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100662nc_err_add_bad_elem(struct nc_server_error *err, const char *elem_name)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100663{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200664 if (!err) {
665 ERRARG("err");
666 return -1;
667 } else if (!elem_name) {
668 ERRARG("elem_name");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100669 return -1;
670 }
671
672 ++err->elem_count;
Michal Vasko4eb3c312016-03-01 14:09:37 +0100673 err->elem = nc_realloc(err->elem, err->elem_count * sizeof *err->elem);
674 if (!err->elem) {
675 ERRMEM;
676 return -1;
677 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100678 err->elem[err->elem_count - 1] = lydict_insert(server_opts.ctx, elem_name, 0);
Michal Vasko11d142a2016-01-19 15:58:24 +0100679
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100680 return 0;
681}
682
683API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100684nc_err_add_bad_ns(struct nc_server_error *err, const char *ns_name)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100685{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200686 if (!err) {
687 ERRARG("err");
688 return -1;
689 } else if (!ns_name) {
690 ERRARG("ns_name");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100691 return -1;
692 }
693
694 ++err->ns_count;
Michal Vasko4eb3c312016-03-01 14:09:37 +0100695 err->ns = nc_realloc(err->ns, err->ns_count * sizeof *err->ns);
696 if (!err->ns) {
697 ERRMEM;
698 return -1;
699 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100700 err->ns[err->ns_count - 1] = lydict_insert(server_opts.ctx, ns_name, 0);
Michal Vasko11d142a2016-01-19 15:58:24 +0100701
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100702 return 0;
703}
704
705API int
706nc_err_add_info_other(struct nc_server_error *err, struct lyxml_elem *other)
707{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200708 if (!err) {
709 ERRARG("err");
710 return -1;
711 } else if (!other) {
712 ERRARG("other");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100713 return -1;
714 }
715
716 ++err->other_count;
Michal Vasko4eb3c312016-03-01 14:09:37 +0100717 err->other = nc_realloc(err->other, err->other_count * sizeof *err->other);
718 if (!err->other) {
719 ERRMEM;
720 return -1;
721 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100722 err->other[err->other_count - 1] = other;
723 return 0;
724}
725
726void
Michal Vaskoca4a2422016-02-02 12:17:14 +0100727nc_server_rpc_free(struct nc_server_rpc *rpc, struct ly_ctx *ctx)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100728{
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100729 if (!rpc) {
730 return;
731 }
732
Michal Vaskoca4a2422016-02-02 12:17:14 +0100733 lyxml_free(ctx, rpc->root);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100734 lyd_free(rpc->tree);
Michal Vasko11d142a2016-01-19 15:58:24 +0100735
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100736 free(rpc);
737}
738
739API void
740nc_server_reply_free(struct nc_server_reply *reply)
741{
742 uint32_t i;
743 struct nc_server_reply_data *data_rpl;
744 struct nc_server_reply_error *error_rpl;
745
746 if (!reply) {
747 return;
748 }
749
750 switch (reply->type) {
751 case NC_RPL_DATA:
752 data_rpl = (struct nc_server_reply_data *)reply;
753 if (data_rpl->free) {
754 lyd_free_withsiblings(data_rpl->data);
755 }
756 break;
757 case NC_RPL_OK:
758 /* nothing to free */
759 break;
760 case NC_RPL_ERROR:
761 error_rpl = (struct nc_server_reply_error *)reply;
762 for (i = 0; i < error_rpl->count; ++i) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100763 nc_err_free(error_rpl->err[i]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100764 }
765 free(error_rpl->err);
766 break;
767 default:
768 break;
769 }
770 free(reply);
771}
772
773API void
Michal Vasko1a38c862016-01-15 15:50:07 +0100774nc_err_free(struct nc_server_error *err)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100775{
776 uint32_t i;
777
778 if (!err) {
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100779 return;
780 }
781
Michal Vasko1a38c862016-01-15 15:50:07 +0100782 lydict_remove(server_opts.ctx, err->apptag);
783 lydict_remove(server_opts.ctx, err->path);
784 lydict_remove(server_opts.ctx, err->message);
785 lydict_remove(server_opts.ctx, err->message_lang);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100786 for (i = 0; i < err->attr_count; ++i) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100787 lydict_remove(server_opts.ctx, err->attr[i]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100788 }
789 free(err->attr);
790 for (i = 0; i < err->elem_count; ++i) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100791 lydict_remove(server_opts.ctx, err->elem[i]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100792 }
793 free(err->elem);
794 for (i = 0; i < err->ns_count; ++i) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100795 lydict_remove(server_opts.ctx, err->ns[i]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100796 }
797 free(err->ns);
798 for (i = 0; i < err->other_count; ++i) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100799 lyxml_free(server_opts.ctx, err->other[i]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100800 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100801 free(err->other);
802 free(err);
803}