blob: 04d12beae7448b58b3d84c6799e561378a49c4d6 [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
22#include "libnetconf.h"
Radek Krejci93e80222016-10-03 13:34:25 +020023#include "session_server.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 *
Radek Krejci36dfdb32016-09-01 16:56:35 +020043nc_server_reply_data(struct lyd_node *data, NC_WD_MODE wd, NC_PARAMTYPE paramtype)
Michal Vasko7bcb48e2016-01-15 10:28:54 +010044{
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;
Radek Krejci36dfdb32016-09-01 16:56:35 +020059 ret->wd = wd;
Michal Vaskob08743b2016-04-13 14:23:49 +020060 if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
Michal Vasko7bcb48e2016-01-15 10:28:54 +010061 ret->data = lyd_dup(data, 1);
62 } else {
63 ret->data = data;
64 }
65 if (paramtype != NC_PARAMTYPE_CONST) {
66 ret->free = 1;
67 } else {
68 ret->free = 0;
69 }
70 return (struct nc_server_reply *)ret;
71}
72
73API struct nc_server_reply *
Michal Vasko1a38c862016-01-15 15:50:07 +010074nc_server_reply_err(struct nc_server_error *err)
Michal Vasko7bcb48e2016-01-15 10:28:54 +010075{
76 struct nc_server_reply_error *ret;
77
Michal Vasko1a38c862016-01-15 15:50:07 +010078 if (!err) {
Michal Vasko45e53ae2016-04-07 11:46:03 +020079 ERRARG("err");
Michal Vasko7bcb48e2016-01-15 10:28:54 +010080 return NULL;
81 }
82
83 ret = malloc(sizeof *ret);
84 if (!ret) {
85 ERRMEM;
86 return NULL;
87 }
88
89 ret->type = NC_RPL_ERROR;
Michal Vasko7bcb48e2016-01-15 10:28:54 +010090 ret->err = malloc(sizeof *ret->err);
Michal Vasko4eb3c312016-03-01 14:09:37 +010091 if (!ret->err) {
92 ERRMEM;
93 free(ret);
94 return NULL;
95 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +010096 ret->err[0] = err;
97 ret->count = 1;
98 return (struct nc_server_reply *)ret;
99}
100
101API int
102nc_server_reply_add_err(struct nc_server_reply *reply, struct nc_server_error *err)
103{
104 struct nc_server_reply_error *err_rpl;
105
Michal Vasko45e53ae2016-04-07 11:46:03 +0200106 if (!reply || (reply->type != NC_RPL_ERROR)) {
107 ERRARG("reply");
108 return -1;
109 } else if (!err) {
110 ERRARG("err");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100111 return -1;
112 }
113
114 err_rpl = (struct nc_server_reply_error *)reply;
115 ++err_rpl->count;
Michal Vasko4eb3c312016-03-01 14:09:37 +0100116 err_rpl->err = nc_realloc(err_rpl->err, err_rpl->count * sizeof *err_rpl->err);
117 if (!err_rpl->err) {
118 ERRMEM;
119 return -1;
120 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100121 err_rpl->err[err_rpl->count - 1] = err;
122 return 0;
123}
124
125API struct nc_server_error *
Radek Krejci127f8952016-10-12 14:57:16 +0200126nc_err(int tag, ...)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100127{
128 va_list ap;
129 struct nc_server_error *ret;
130 NC_ERR_TYPE type;
131 const char *arg1, *arg2;
132 uint32_t sid;
133
Michal Vasko1a38c862016-01-15 15:50:07 +0100134 if (!tag) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200135 ERRARG("tag");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100136 return NULL;
137 }
138
139 ret = calloc(1, sizeof *ret);
140 if (!ret) {
141 ERRMEM;
142 return NULL;
143 }
Michal Vasko90920b02016-05-20 14:07:00 +0200144 ret->sid = -1;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100145
146 va_start(ap, tag);
147
148 switch (tag) {
149 case NC_ERR_IN_USE:
150 case NC_ERR_INVALID_VALUE:
151 case NC_ERR_ACCESS_DENIED:
152 case NC_ERR_ROLLBACK_FAILED:
153 case NC_ERR_OP_NOT_SUPPORTED:
Radek Krejci127f8952016-10-12 14:57:16 +0200154 type = (NC_ERR_TYPE)va_arg(ap, int); /* NC_ERR_TYPE enum is automatically promoted to int */
Michal Vasko2f923d12016-04-05 11:33:02 +0200155 if ((type != NC_ERR_TYPE_PROT) && (type != NC_ERR_TYPE_APP)) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200156 ERRARG("type");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100157 goto fail;
158 }
159 break;
160
161 case NC_ERR_TOO_BIG:
162 case NC_ERR_RES_DENIED:
Radek Krejci127f8952016-10-12 14:57:16 +0200163 type = (NC_ERR_TYPE)va_arg(ap, int); /* NC_ERR_TYPE enum is automatically promoted to int */
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100164 /* nothing to check */
165 break;
166
167 case NC_ERR_MISSING_ATTR:
168 case NC_ERR_BAD_ATTR:
169 case NC_ERR_UNKNOWN_ATTR:
Radek Krejci127f8952016-10-12 14:57:16 +0200170 type = (NC_ERR_TYPE)va_arg(ap, int); /* NC_ERR_TYPE enum is automatically promoted to int */
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100171 arg1 = va_arg(ap, const char *);
172 arg2 = va_arg(ap, const char *);
173
174 if (type == NC_ERR_TYPE_TRAN) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200175 ERRARG("type");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100176 goto fail;
177 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100178 nc_err_add_bad_attr(ret, arg1);
179 nc_err_add_bad_elem(ret, arg2);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100180 break;
181
182 case NC_ERR_MISSING_ELEM:
183 case NC_ERR_BAD_ELEM:
184 case NC_ERR_UNKNOWN_ELEM:
Radek Krejci127f8952016-10-12 14:57:16 +0200185 type = (NC_ERR_TYPE)va_arg(ap, int); /* NC_ERR_TYPE enum is automatically promoted to int */
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100186 arg1 = va_arg(ap, const char *);
187
188 if ((type != NC_ERR_TYPE_PROT) && (type != NC_ERR_TYPE_APP)) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200189 ERRARG("type");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100190 goto fail;
191 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100192 nc_err_add_bad_elem(ret, arg1);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100193 break;
194
195 case NC_ERR_UNKNOWN_NS:
Radek Krejci127f8952016-10-12 14:57:16 +0200196 type = (NC_ERR_TYPE)va_arg(ap, int); /* NC_ERR_TYPE enum is automatically promoted to int */
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100197 arg1 = va_arg(ap, const char *);
198 arg2 = va_arg(ap, const char *);
199
200 if ((type != NC_ERR_TYPE_PROT) && (type != NC_ERR_TYPE_APP)) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200201 ERRARG("type");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100202 goto fail;
203 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100204 nc_err_add_bad_elem(ret, arg1);
205 nc_err_add_bad_ns(ret, arg2);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100206 break;
207
208 case NC_ERR_LOCK_DENIED:
209 sid = va_arg(ap, uint32_t);
210
211 type = NC_ERR_TYPE_PROT;
212 nc_err_set_sid(ret, sid);
213 break;
214
215 case NC_ERR_DATA_EXISTS:
216 case NC_ERR_DATA_MISSING:
217 type = NC_ERR_TYPE_APP;
218 break;
219
220 case NC_ERR_OP_FAILED:
Radek Krejci127f8952016-10-12 14:57:16 +0200221 type = (NC_ERR_TYPE)va_arg(ap, int); /* NC_ERR_TYPE enum is automatically promoted to int */
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100222
223 if (type == NC_ERR_TYPE_TRAN) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200224 ERRARG("type");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100225 goto fail;
226 }
227 break;
228
229 case NC_ERR_MALFORMED_MSG:
230 type = NC_ERR_TYPE_RPC;
231 break;
232
233 default:
Michal Vasko45e53ae2016-04-07 11:46:03 +0200234 ERRARG("tag");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100235 goto fail;
236 }
237
238 switch (tag) {
239 case NC_ERR_IN_USE:
Michal Vasko1a38c862016-01-15 15:50:07 +0100240 nc_err_set_msg(ret, "The request requires a resource that already is in use.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100241 break;
242 case NC_ERR_INVALID_VALUE:
Michal Vasko1a38c862016-01-15 15:50:07 +0100243 nc_err_set_msg(ret, "The request specifies an unacceptable value for one or more parameters.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100244 break;
245 case NC_ERR_TOO_BIG:
Michal Vasko1a38c862016-01-15 15:50:07 +0100246 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 +0100247 break;
248 case NC_ERR_MISSING_ATTR:
Michal Vasko1a38c862016-01-15 15:50:07 +0100249 nc_err_set_msg(ret, "An expected attribute is missing.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100250 break;
251 case NC_ERR_BAD_ATTR:
Michal Vasko1a38c862016-01-15 15:50:07 +0100252 nc_err_set_msg(ret, "An attribute value is not correct.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100253 break;
254 case NC_ERR_UNKNOWN_ATTR:
Michal Vasko1a38c862016-01-15 15:50:07 +0100255 nc_err_set_msg(ret, "An unexpected attribute is present.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100256 break;
257 case NC_ERR_MISSING_ELEM:
Michal Vasko1a38c862016-01-15 15:50:07 +0100258 nc_err_set_msg(ret, "An expected element is missing.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100259 break;
260 case NC_ERR_BAD_ELEM:
Michal Vasko1a38c862016-01-15 15:50:07 +0100261 nc_err_set_msg(ret, "An element value is not correct.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100262 break;
263 case NC_ERR_UNKNOWN_ELEM:
Michal Vasko1a38c862016-01-15 15:50:07 +0100264 nc_err_set_msg(ret, "An unexpected element is present.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100265 break;
266 case NC_ERR_UNKNOWN_NS:
Michal Vasko1a38c862016-01-15 15:50:07 +0100267 nc_err_set_msg(ret, "An unexpected namespace is present.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100268 break;
269 case NC_ERR_ACCESS_DENIED:
Michal Vasko1a38c862016-01-15 15:50:07 +0100270 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 +0100271 break;
272 case NC_ERR_LOCK_DENIED:
Michal Vasko1a38c862016-01-15 15:50:07 +0100273 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 +0100274 break;
275 case NC_ERR_RES_DENIED:
Michal Vasko1a38c862016-01-15 15:50:07 +0100276 nc_err_set_msg(ret, "Request could not be completed because of insufficient resources.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100277 break;
278 case NC_ERR_ROLLBACK_FAILED:
Michal Vasko1a38c862016-01-15 15:50:07 +0100279 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 +0100280 break;
281 case NC_ERR_DATA_EXISTS:
Michal Vasko1a38c862016-01-15 15:50:07 +0100282 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 +0100283 break;
284 case NC_ERR_DATA_MISSING:
Michal Vasko1a38c862016-01-15 15:50:07 +0100285 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 +0100286 break;
287 case NC_ERR_OP_NOT_SUPPORTED:
Michal Vasko1a38c862016-01-15 15:50:07 +0100288 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 +0100289 break;
290 case NC_ERR_OP_FAILED:
Michal Vasko1a38c862016-01-15 15:50:07 +0100291 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 +0100292 break;
293 case NC_ERR_MALFORMED_MSG:
Michal Vasko1a38c862016-01-15 15:50:07 +0100294 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 +0100295 break;
296 default:
Michal Vasko45e53ae2016-04-07 11:46:03 +0200297 ERRARG("tag");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100298 goto fail;
299 }
300
301 va_end(ap);
302
303 ret->type = type;
304 ret->tag = tag;
305 return ret;
306
307fail:
Michal Vasko11d142a2016-01-19 15:58:24 +0100308 va_end(ap);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100309 free(ret);
310 return NULL;
311}
312
Michal Vaskoa08e5c02016-04-12 15:12:04 +0200313static struct lyxml_elem *
314nc_err_libyang_other_elem(const char *name, const char *content, int cont_len)
315{
316 struct lyxml_elem *root = NULL;
317 struct lyxml_ns *ns;
318
319 root = calloc(1, sizeof *root);
320 if (!root) {
321 ERRMEM;
322 goto error;
323 }
324 root->prev = root;
325 root->name = lydict_insert(server_opts.ctx, name, 0);
326 root->content = lydict_insert(server_opts.ctx, content, cont_len);
327
328 ns = calloc(1, sizeof *root->ns);
329 if (!ns) {
330 ERRMEM;
331 goto error;
332 }
333 root->attr = (struct lyxml_attr *)ns;
334 ns->type = LYXML_ATTR_NS;
335 ns->parent = root;
336 ns->value = lydict_insert(server_opts.ctx, "urn:ietf:params:xml:ns:yang:1", 0);
337 root->ns = ns;
338
339 return root;
340
341error:
342 lyxml_free(server_opts.ctx, root);
343 return NULL;
344}
345
Radek Krejci877e1822016-04-06 16:37:43 +0200346API struct nc_server_error *
347nc_err_libyang(void)
348{
349 struct nc_server_error *e;
Michal Vaskoa08e5c02016-04-12 15:12:04 +0200350 struct lyxml_elem *elem;
351 const char *str, *stri, *strj, *strk, *strl, *uniqi, *uniqj;
352 char *attr, *path;
353 int len;
Radek Krejci877e1822016-04-06 16:37:43 +0200354
355 if (!ly_errno) {
356 /* LY_SUCCESS */
357 return NULL;
358 } else if (ly_errno == LY_EVALID) {
359 switch (ly_vecode) {
Michal Vaskoa08e5c02016-04-12 15:12:04 +0200360 /* RFC 6020 section 13 errors */
361 case LYVE_NOUNIQ:
362 e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
363 nc_err_set_app_tag(e, "data-not-unique");
364 nc_err_set_path(e, ly_errpath());
365
366 /* parse the message and get all the information we need */
367 str = ly_errmsg();
368 uniqi = strchr(str, '"');
369 uniqi++;
370 uniqj = strchr(uniqi, '"');
371
372 stri = strchr(uniqj + 1, '"');
373 stri++;
374 strj = strchr(stri, '"');
375
376 strk = strchr(strj + 1, '"');
377 ++strk;
378 strl = strchr(strk, '"');
379
380 /* maximum length is the whole unique string with the longer list instance identifier */
381 len = (uniqj - uniqi) + (strj - stri > strl - strk ? strj - stri : strl - strk);
382 path = malloc(len + 1);
383 if (!path) {
384 ERRMEM;
385 return e;
386 }
387
388 /* create non-unique elements, one in 1st list, one in 2nd list, for each unique list */
389 while (1) {
390 uniqj = strpbrk(uniqi, " \"");
391
392 len = sprintf(path, "%.*s/%.*s", (int)(strj - stri), stri, (int)(uniqj - uniqi), uniqi);
393 elem = nc_err_libyang_other_elem("non-unique", path, len);
394 if (!elem) {
395 free(path);
396 return e;
397 }
398 nc_err_add_info_other(e, elem);
399
400 len = sprintf(path, "%.*s/%.*s", (int)(strl - strk), strk, (int)(uniqj - uniqi), uniqi);
401 elem = nc_err_libyang_other_elem("non-unique", path, len);
402 if (!elem) {
403 return e;
404 }
405 nc_err_add_info_other(e, elem);
406
407 if (uniqj[0] == '"') {
408 break;
409 }
410 uniqi = uniqj + 1;
411 }
412 free(path);
413 break;
414 case LYVE_NOMAX:
415 e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
416 nc_err_set_app_tag(e, "too-many-elements");
417 nc_err_set_path(e, ly_errpath());
418 break;
419 case LYVE_NOMIN:
420 e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
421 nc_err_set_app_tag(e, "too-few-elements");
422 nc_err_set_path(e, ly_errpath());
423 break;
424 case LYVE_NOMUST:
425 e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
426 if (ly_errapptag()[0]) {
427 nc_err_set_app_tag(e, ly_errapptag());
428 } else {
429 nc_err_set_app_tag(e, "must-violation");
430 }
431 break;
432 case LYVE_NOREQINS:
433 case LYVE_NOLEAFREF:
434 e = nc_err(NC_ERR_DATA_MISSING);
435 nc_err_set_app_tag(e, "instance-required");
436 nc_err_set_path(e, ly_errpath());
437 break;
438 case LYVE_NOMANDCHOICE:
439 e = nc_err(NC_ERR_DATA_MISSING);
440 nc_err_set_app_tag(e, "missing-choice");
441 nc_err_set_path(e, ly_errpath());
442
443 str = ly_errmsg();
444 stri = strchr(str, '"');
445 stri++;
446 strj = strchr(stri, '"');
447 elem = nc_err_libyang_other_elem("missing-choice", stri, strj - stri);
448 if (elem) {
449 nc_err_add_info_other(e, elem);
450 }
451 break;
Radek Krejci877e1822016-04-06 16:37:43 +0200452 case LYVE_INELEM:
453 str = ly_errpath();
454 if (!strcmp(str, "/")) {
455 e = nc_err(NC_ERR_OP_NOT_SUPPORTED, NC_ERR_TYPE_APP);
456 /* keep default message */
457 return e;
458 } else {
459 e = nc_err(NC_ERR_UNKNOWN_ELEM, NC_ERR_TYPE_PROT, ly_errpath());
460 }
461 break;
462 case LYVE_MISSELEM:
463 case LYVE_INORDER:
464 e = nc_err(NC_ERR_MISSING_ELEM, NC_ERR_TYPE_PROT, ly_errpath());
465 break;
466 case LYVE_INVAL:
467 e = nc_err(NC_ERR_BAD_ELEM, NC_ERR_TYPE_PROT, ly_errpath());
468 break;
469 case LYVE_INATTR:
470 case LYVE_MISSATTR:
Michal Vasko37fdad52017-03-02 11:40:22 +0100471 case LYVE_INMETA:
Radek Krejci877e1822016-04-06 16:37:43 +0200472 str = ly_errmsg();
473 stri = strchr(str, '"');
474 stri++;
475 strj = strchr(stri, '"');
476 strj--;
477 attr = strndup(stri, strj - stri);
Radek Krejci537fb522016-04-07 16:36:25 +0200478 if (ly_vecode == LYVE_INATTR) {
479 e = nc_err(NC_ERR_UNKNOWN_ATTR, NC_ERR_TYPE_PROT, attr, ly_errpath());
480 } else if (ly_vecode == LYVE_MISSATTR) {
481 e = nc_err(NC_ERR_MISSING_ATTR, NC_ERR_TYPE_PROT, attr, ly_errpath());
Michal Vasko37fdad52017-03-02 11:40:22 +0100482 } else { /* LYVE_INMETA */
Radek Krejci537fb522016-04-07 16:36:25 +0200483 e = nc_err(NC_ERR_BAD_ATTR, NC_ERR_TYPE_PROT, attr, ly_errpath());
484 }
Radek Krejci877e1822016-04-06 16:37:43 +0200485 free(attr);
486 break;
Michal Vaskoa08e5c02016-04-12 15:12:04 +0200487 case LYVE_NOCONSTR:
488 case LYVE_NOWHEN:
Radek Krejci877e1822016-04-06 16:37:43 +0200489 e = nc_err(NC_ERR_INVALID_VALUE, NC_ERR_TYPE_PROT);
Michal Vaskoa08e5c02016-04-12 15:12:04 +0200490 /* LYVE_NOCONSTR (length, range, pattern) can have a specific error-app-tag */
491 if (ly_errapptag()[0]) {
492 nc_err_set_app_tag(e, ly_errapptag());
493 }
Radek Krejci877e1822016-04-06 16:37:43 +0200494 break;
495 default:
496 e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
497 break;
498 }
499 } else {
500 /* non-validation (internal) error */
501 e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
502 }
503 nc_err_set_msg(e, ly_errmsg(), "en");
504 return e;
505}
506
Michal Vasko8f3198f2016-05-04 10:45:28 +0200507API NC_ERR_TYPE
508nc_err_get_type(struct nc_server_error *err)
509{
510 if (!err) {
511 ERRARG("err");
512 return 0;
513 }
514
515 return err->type;
516}
517
518API NC_ERR
519nc_err_get_tag(struct nc_server_error *err)
520{
521 if (!err) {
522 ERRARG("err");
523 return 0;
524 }
525
526 return err->tag;
527}
528
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100529API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100530nc_err_set_app_tag(struct nc_server_error *err, const char *error_app_tag)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100531{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200532 if (!err) {
533 ERRARG("err");
534 return -1;
535 } else if (!error_app_tag) {
536 ERRARG("error_app_tag");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100537 return -1;
538 }
539
540 if (err->apptag) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100541 lydict_remove(server_opts.ctx, err->apptag);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100542 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100543 err->apptag = lydict_insert(server_opts.ctx, error_app_tag, 0);
Michal Vasko11d142a2016-01-19 15:58:24 +0100544
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100545 return 0;
546}
547
Michal Vasko8f3198f2016-05-04 10:45:28 +0200548API const char *
549nc_err_get_app_tag(struct nc_server_error *err)
550{
551 if (!err) {
552 ERRARG("err");
553 return NULL;
554 }
555
556 return err->apptag;
557}
558
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100559API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100560nc_err_set_path(struct nc_server_error *err, const char *error_path)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100561{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200562 if (!err) {
563 ERRARG("err");
564 return -1;
565 } else if (!error_path) {
566 ERRARG("error_path");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100567 return -1;
568 }
569
570 if (err->path) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100571 lydict_remove(server_opts.ctx, err->path);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100572 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100573 err->path = lydict_insert(server_opts.ctx, error_path, 0);
Michal Vasko11d142a2016-01-19 15:58:24 +0100574
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100575 return 0;
576}
577
Michal Vasko8f3198f2016-05-04 10:45:28 +0200578API const char *
579nc_err_get_path(struct nc_server_error *err)
580{
581 if (!err) {
582 ERRARG("err");
583 return 0;
584 }
585
586 return err->path;
587}
588
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100589API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100590nc_err_set_msg(struct nc_server_error *err, const char *error_message, const char *lang)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100591{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200592 if (!err) {
593 ERRARG("err");
594 return -1;
595 } else if (!error_message) {
596 ERRARG("error_message");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100597 return -1;
598 }
599
600 if (err->message) {
Michal Vasko092ea742016-04-12 15:08:59 +0200601 lydict_remove(server_opts.ctx, err->message);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100602 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100603 err->message = lydict_insert(server_opts.ctx, error_message, 0);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100604
605 if (err->message_lang) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100606 lydict_remove(server_opts.ctx, err->message_lang);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100607 }
608 if (lang) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100609 err->message_lang = lydict_insert(server_opts.ctx, lang, 0);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100610 } else {
611 lang = NULL;
612 }
Michal Vasko11d142a2016-01-19 15:58:24 +0100613
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100614 return 0;
615}
616
Michal Vasko8f3198f2016-05-04 10:45:28 +0200617API const char *
618nc_err_get_msg(struct nc_server_error *err)
619{
620 if (!err) {
621 ERRARG("err");
622 return 0;
623 }
624
625 return err->message;
626}
627
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100628API int
629nc_err_set_sid(struct nc_server_error *err, uint32_t session_id)
630{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200631 if (!err) {
632 ERRARG("err");
633 return -1;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100634 }
635
636 err->sid = session_id;
637 return 0;
638}
639
640API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100641nc_err_add_bad_attr(struct nc_server_error *err, const char *attr_name)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100642{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200643 if (!err) {
644 ERRARG("err");
645 return -1;
646 } else if (!attr_name) {
647 ERRARG("attr_name");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100648 return -1;
649 }
650
651 ++err->attr_count;
Michal Vasko4eb3c312016-03-01 14:09:37 +0100652 err->attr = nc_realloc(err->attr, err->attr_count * sizeof *err->attr);
653 if (!err->attr) {
654 ERRMEM;
655 return -1;
656 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100657 err->attr[err->attr_count - 1] = lydict_insert(server_opts.ctx, attr_name, 0);
Michal Vasko11d142a2016-01-19 15:58:24 +0100658
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100659 return 0;
660}
661
662API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100663nc_err_add_bad_elem(struct nc_server_error *err, const char *elem_name)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100664{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200665 if (!err) {
666 ERRARG("err");
667 return -1;
668 } else if (!elem_name) {
669 ERRARG("elem_name");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100670 return -1;
671 }
672
673 ++err->elem_count;
Michal Vasko4eb3c312016-03-01 14:09:37 +0100674 err->elem = nc_realloc(err->elem, err->elem_count * sizeof *err->elem);
675 if (!err->elem) {
676 ERRMEM;
677 return -1;
678 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100679 err->elem[err->elem_count - 1] = lydict_insert(server_opts.ctx, elem_name, 0);
Michal Vasko11d142a2016-01-19 15:58:24 +0100680
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100681 return 0;
682}
683
684API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100685nc_err_add_bad_ns(struct nc_server_error *err, const char *ns_name)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100686{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200687 if (!err) {
688 ERRARG("err");
689 return -1;
690 } else if (!ns_name) {
691 ERRARG("ns_name");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100692 return -1;
693 }
694
695 ++err->ns_count;
Michal Vasko4eb3c312016-03-01 14:09:37 +0100696 err->ns = nc_realloc(err->ns, err->ns_count * sizeof *err->ns);
697 if (!err->ns) {
698 ERRMEM;
699 return -1;
700 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100701 err->ns[err->ns_count - 1] = lydict_insert(server_opts.ctx, ns_name, 0);
Michal Vasko11d142a2016-01-19 15:58:24 +0100702
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100703 return 0;
704}
705
706API int
707nc_err_add_info_other(struct nc_server_error *err, struct lyxml_elem *other)
708{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200709 if (!err) {
710 ERRARG("err");
711 return -1;
712 } else if (!other) {
713 ERRARG("other");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100714 return -1;
715 }
716
717 ++err->other_count;
Michal Vasko4eb3c312016-03-01 14:09:37 +0100718 err->other = nc_realloc(err->other, err->other_count * sizeof *err->other);
719 if (!err->other) {
720 ERRMEM;
721 return -1;
722 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100723 err->other[err->other_count - 1] = other;
724 return 0;
725}
726
727void
Michal Vaskoca4a2422016-02-02 12:17:14 +0100728nc_server_rpc_free(struct nc_server_rpc *rpc, struct ly_ctx *ctx)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100729{
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100730 if (!rpc) {
731 return;
732 }
733
Michal Vaskoca4a2422016-02-02 12:17:14 +0100734 lyxml_free(ctx, rpc->root);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100735 lyd_free(rpc->tree);
Michal Vasko11d142a2016-01-19 15:58:24 +0100736
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100737 free(rpc);
738}
739
740API void
741nc_server_reply_free(struct nc_server_reply *reply)
742{
743 uint32_t i;
744 struct nc_server_reply_data *data_rpl;
745 struct nc_server_reply_error *error_rpl;
746
747 if (!reply) {
748 return;
749 }
750
751 switch (reply->type) {
752 case NC_RPL_DATA:
753 data_rpl = (struct nc_server_reply_data *)reply;
754 if (data_rpl->free) {
755 lyd_free_withsiblings(data_rpl->data);
756 }
757 break;
758 case NC_RPL_OK:
759 /* nothing to free */
760 break;
761 case NC_RPL_ERROR:
762 error_rpl = (struct nc_server_reply_error *)reply;
763 for (i = 0; i < error_rpl->count; ++i) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100764 nc_err_free(error_rpl->err[i]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100765 }
766 free(error_rpl->err);
767 break;
768 default:
769 break;
770 }
771 free(reply);
772}
773
774API void
Michal Vasko1a38c862016-01-15 15:50:07 +0100775nc_err_free(struct nc_server_error *err)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100776{
777 uint32_t i;
778
779 if (!err) {
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100780 return;
781 }
782
Michal Vasko1a38c862016-01-15 15:50:07 +0100783 lydict_remove(server_opts.ctx, err->apptag);
784 lydict_remove(server_opts.ctx, err->path);
785 lydict_remove(server_opts.ctx, err->message);
786 lydict_remove(server_opts.ctx, err->message_lang);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100787 for (i = 0; i < err->attr_count; ++i) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100788 lydict_remove(server_opts.ctx, err->attr[i]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100789 }
790 free(err->attr);
791 for (i = 0; i < err->elem_count; ++i) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100792 lydict_remove(server_opts.ctx, err->elem[i]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100793 }
794 free(err->elem);
795 for (i = 0; i < err->ns_count; ++i) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100796 lydict_remove(server_opts.ctx, err->ns[i]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100797 }
798 free(err->ns);
799 for (i = 0; i < err->other_count; ++i) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100800 lyxml_free(server_opts.ctx, err->other[i]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100801 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100802 free(err->other);
803 free(err);
804}
Radek Krejci93e80222016-10-03 13:34:25 +0200805
806API struct nc_server_notif *
807nc_server_notif_new(struct lyd_node* event, char *eventtime, int eventtime_const)
808{
809 struct nc_server_notif *ntf;
810
811 if (!event || event->schema->nodetype != LYS_NOTIF) {
812 ERRARG("event");
813 return NULL;
814 } else if (!eventtime) {
815 ERRARG("eventtime");
816 return NULL;
817 }
818
819 ntf = malloc(sizeof *ntf);
820 if (eventtime_const) {
821 ntf->eventtime = strdup(eventtime);
822 } else {
823 ntf->eventtime = eventtime;
824 }
825 ntf->tree = event;
826
827 return ntf;
828}
829
830API void
831nc_server_notif_free(struct nc_server_notif *notif)
832{
833 if (!notif) {
834 return;
835 }
836
837 lyd_free(notif->tree);
838 free(notif->eventtime);
839 free(notif);
840}