blob: 15ca95b29e6195c6064fdb382a3b7581964148f6 [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
Michal Vaskoaa2e5a72017-03-16 09:48:44 +0100125API const struct nc_server_error *
126nc_server_reply_get_last_err(const struct nc_server_reply *reply)
127{
128 struct nc_server_reply_error *err_rpl;
129
130 if (!reply || (reply->type != NC_RPL_ERROR)) {
131 ERRARG("reply");
132 return NULL;
133 }
134
135 err_rpl = (struct nc_server_reply_error *)reply;
136 if (!err_rpl->count) {
137 return NULL;
138 }
139 return err_rpl->err[err_rpl->count - 1];
140}
141
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100142API struct nc_server_error *
Radek Krejci127f8952016-10-12 14:57:16 +0200143nc_err(int tag, ...)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100144{
145 va_list ap;
146 struct nc_server_error *ret;
147 NC_ERR_TYPE type;
148 const char *arg1, *arg2;
149 uint32_t sid;
150
Michal Vasko1a38c862016-01-15 15:50:07 +0100151 if (!tag) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200152 ERRARG("tag");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100153 return NULL;
154 }
155
156 ret = calloc(1, sizeof *ret);
157 if (!ret) {
158 ERRMEM;
159 return NULL;
160 }
Michal Vasko90920b02016-05-20 14:07:00 +0200161 ret->sid = -1;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100162
163 va_start(ap, tag);
164
165 switch (tag) {
166 case NC_ERR_IN_USE:
167 case NC_ERR_INVALID_VALUE:
168 case NC_ERR_ACCESS_DENIED:
169 case NC_ERR_ROLLBACK_FAILED:
170 case NC_ERR_OP_NOT_SUPPORTED:
Radek Krejci127f8952016-10-12 14:57:16 +0200171 type = (NC_ERR_TYPE)va_arg(ap, int); /* NC_ERR_TYPE enum is automatically promoted to int */
Michal Vasko2f923d12016-04-05 11:33:02 +0200172 if ((type != NC_ERR_TYPE_PROT) && (type != NC_ERR_TYPE_APP)) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200173 ERRARG("type");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100174 goto fail;
175 }
176 break;
177
178 case NC_ERR_TOO_BIG:
179 case NC_ERR_RES_DENIED:
Radek Krejci127f8952016-10-12 14:57:16 +0200180 type = (NC_ERR_TYPE)va_arg(ap, int); /* NC_ERR_TYPE enum is automatically promoted to int */
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100181 /* nothing to check */
182 break;
183
184 case NC_ERR_MISSING_ATTR:
185 case NC_ERR_BAD_ATTR:
186 case NC_ERR_UNKNOWN_ATTR:
Radek Krejci127f8952016-10-12 14:57:16 +0200187 type = (NC_ERR_TYPE)va_arg(ap, int); /* NC_ERR_TYPE enum is automatically promoted to int */
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100188 arg1 = va_arg(ap, const char *);
189 arg2 = va_arg(ap, const char *);
190
191 if (type == NC_ERR_TYPE_TRAN) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200192 ERRARG("type");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100193 goto fail;
194 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100195 nc_err_add_bad_attr(ret, arg1);
196 nc_err_add_bad_elem(ret, arg2);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100197 break;
198
199 case NC_ERR_MISSING_ELEM:
200 case NC_ERR_BAD_ELEM:
201 case NC_ERR_UNKNOWN_ELEM:
Radek Krejci127f8952016-10-12 14:57:16 +0200202 type = (NC_ERR_TYPE)va_arg(ap, int); /* NC_ERR_TYPE enum is automatically promoted to int */
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100203 arg1 = va_arg(ap, const char *);
204
205 if ((type != NC_ERR_TYPE_PROT) && (type != NC_ERR_TYPE_APP)) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200206 ERRARG("type");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100207 goto fail;
208 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100209 nc_err_add_bad_elem(ret, arg1);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100210 break;
211
212 case NC_ERR_UNKNOWN_NS:
Radek Krejci127f8952016-10-12 14:57:16 +0200213 type = (NC_ERR_TYPE)va_arg(ap, int); /* NC_ERR_TYPE enum is automatically promoted to int */
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100214 arg1 = va_arg(ap, const char *);
215 arg2 = va_arg(ap, const char *);
216
217 if ((type != NC_ERR_TYPE_PROT) && (type != NC_ERR_TYPE_APP)) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200218 ERRARG("type");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100219 goto fail;
220 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100221 nc_err_add_bad_elem(ret, arg1);
222 nc_err_add_bad_ns(ret, arg2);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100223 break;
224
225 case NC_ERR_LOCK_DENIED:
226 sid = va_arg(ap, uint32_t);
227
228 type = NC_ERR_TYPE_PROT;
229 nc_err_set_sid(ret, sid);
230 break;
231
232 case NC_ERR_DATA_EXISTS:
233 case NC_ERR_DATA_MISSING:
234 type = NC_ERR_TYPE_APP;
235 break;
236
237 case NC_ERR_OP_FAILED:
Radek Krejci127f8952016-10-12 14:57:16 +0200238 type = (NC_ERR_TYPE)va_arg(ap, int); /* NC_ERR_TYPE enum is automatically promoted to int */
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100239
240 if (type == NC_ERR_TYPE_TRAN) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200241 ERRARG("type");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100242 goto fail;
243 }
244 break;
245
246 case NC_ERR_MALFORMED_MSG:
247 type = NC_ERR_TYPE_RPC;
248 break;
249
250 default:
Michal Vasko45e53ae2016-04-07 11:46:03 +0200251 ERRARG("tag");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100252 goto fail;
253 }
254
255 switch (tag) {
256 case NC_ERR_IN_USE:
Michal Vasko1a38c862016-01-15 15:50:07 +0100257 nc_err_set_msg(ret, "The request requires a resource that already is in use.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100258 break;
259 case NC_ERR_INVALID_VALUE:
Michal Vasko1a38c862016-01-15 15:50:07 +0100260 nc_err_set_msg(ret, "The request specifies an unacceptable value for one or more parameters.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100261 break;
262 case NC_ERR_TOO_BIG:
Michal Vasko1a38c862016-01-15 15:50:07 +0100263 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 +0100264 break;
265 case NC_ERR_MISSING_ATTR:
Michal Vasko1a38c862016-01-15 15:50:07 +0100266 nc_err_set_msg(ret, "An expected attribute is missing.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100267 break;
268 case NC_ERR_BAD_ATTR:
Michal Vasko1a38c862016-01-15 15:50:07 +0100269 nc_err_set_msg(ret, "An attribute value is not correct.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100270 break;
271 case NC_ERR_UNKNOWN_ATTR:
Michal Vasko1a38c862016-01-15 15:50:07 +0100272 nc_err_set_msg(ret, "An unexpected attribute is present.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100273 break;
274 case NC_ERR_MISSING_ELEM:
Michal Vasko1a38c862016-01-15 15:50:07 +0100275 nc_err_set_msg(ret, "An expected element is missing.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100276 break;
277 case NC_ERR_BAD_ELEM:
Michal Vasko1a38c862016-01-15 15:50:07 +0100278 nc_err_set_msg(ret, "An element value is not correct.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100279 break;
280 case NC_ERR_UNKNOWN_ELEM:
Michal Vasko1a38c862016-01-15 15:50:07 +0100281 nc_err_set_msg(ret, "An unexpected element is present.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100282 break;
283 case NC_ERR_UNKNOWN_NS:
Michal Vasko1a38c862016-01-15 15:50:07 +0100284 nc_err_set_msg(ret, "An unexpected namespace is present.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100285 break;
286 case NC_ERR_ACCESS_DENIED:
Michal Vasko1a38c862016-01-15 15:50:07 +0100287 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 +0100288 break;
289 case NC_ERR_LOCK_DENIED:
Michal Vasko1a38c862016-01-15 15:50:07 +0100290 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 +0100291 break;
292 case NC_ERR_RES_DENIED:
Michal Vasko1a38c862016-01-15 15:50:07 +0100293 nc_err_set_msg(ret, "Request could not be completed because of insufficient resources.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100294 break;
295 case NC_ERR_ROLLBACK_FAILED:
Michal Vasko1a38c862016-01-15 15:50:07 +0100296 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 +0100297 break;
298 case NC_ERR_DATA_EXISTS:
Michal Vasko1a38c862016-01-15 15:50:07 +0100299 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 +0100300 break;
301 case NC_ERR_DATA_MISSING:
Michal Vasko1a38c862016-01-15 15:50:07 +0100302 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 +0100303 break;
304 case NC_ERR_OP_NOT_SUPPORTED:
Michal Vasko1a38c862016-01-15 15:50:07 +0100305 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 +0100306 break;
307 case NC_ERR_OP_FAILED:
Michal Vasko1a38c862016-01-15 15:50:07 +0100308 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 +0100309 break;
310 case NC_ERR_MALFORMED_MSG:
Michal Vasko1a38c862016-01-15 15:50:07 +0100311 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 +0100312 break;
313 default:
Michal Vasko45e53ae2016-04-07 11:46:03 +0200314 ERRARG("tag");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100315 goto fail;
316 }
317
318 va_end(ap);
319
320 ret->type = type;
321 ret->tag = tag;
322 return ret;
323
324fail:
Michal Vasko11d142a2016-01-19 15:58:24 +0100325 va_end(ap);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100326 free(ret);
327 return NULL;
328}
329
Michal Vaskoa08e5c02016-04-12 15:12:04 +0200330static struct lyxml_elem *
331nc_err_libyang_other_elem(const char *name, const char *content, int cont_len)
332{
333 struct lyxml_elem *root = NULL;
334 struct lyxml_ns *ns;
335
336 root = calloc(1, sizeof *root);
337 if (!root) {
338 ERRMEM;
339 goto error;
340 }
341 root->prev = root;
342 root->name = lydict_insert(server_opts.ctx, name, 0);
343 root->content = lydict_insert(server_opts.ctx, content, cont_len);
344
345 ns = calloc(1, sizeof *root->ns);
346 if (!ns) {
347 ERRMEM;
348 goto error;
349 }
350 root->attr = (struct lyxml_attr *)ns;
351 ns->type = LYXML_ATTR_NS;
352 ns->parent = root;
353 ns->value = lydict_insert(server_opts.ctx, "urn:ietf:params:xml:ns:yang:1", 0);
354 root->ns = ns;
355
356 return root;
357
358error:
359 lyxml_free(server_opts.ctx, root);
360 return NULL;
361}
362
Radek Krejci877e1822016-04-06 16:37:43 +0200363API struct nc_server_error *
364nc_err_libyang(void)
365{
366 struct nc_server_error *e;
Michal Vaskoa08e5c02016-04-12 15:12:04 +0200367 struct lyxml_elem *elem;
368 const char *str, *stri, *strj, *strk, *strl, *uniqi, *uniqj;
369 char *attr, *path;
370 int len;
Radek Krejci877e1822016-04-06 16:37:43 +0200371
372 if (!ly_errno) {
373 /* LY_SUCCESS */
374 return NULL;
375 } else if (ly_errno == LY_EVALID) {
376 switch (ly_vecode) {
Michal Vaskoa08e5c02016-04-12 15:12:04 +0200377 /* RFC 6020 section 13 errors */
378 case LYVE_NOUNIQ:
379 e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
380 nc_err_set_app_tag(e, "data-not-unique");
381 nc_err_set_path(e, ly_errpath());
382
383 /* parse the message and get all the information we need */
384 str = ly_errmsg();
385 uniqi = strchr(str, '"');
386 uniqi++;
387 uniqj = strchr(uniqi, '"');
388
389 stri = strchr(uniqj + 1, '"');
390 stri++;
391 strj = strchr(stri, '"');
392
393 strk = strchr(strj + 1, '"');
394 ++strk;
395 strl = strchr(strk, '"');
396
397 /* maximum length is the whole unique string with the longer list instance identifier */
398 len = (uniqj - uniqi) + (strj - stri > strl - strk ? strj - stri : strl - strk);
399 path = malloc(len + 1);
400 if (!path) {
401 ERRMEM;
402 return e;
403 }
404
405 /* create non-unique elements, one in 1st list, one in 2nd list, for each unique list */
406 while (1) {
407 uniqj = strpbrk(uniqi, " \"");
408
409 len = sprintf(path, "%.*s/%.*s", (int)(strj - stri), stri, (int)(uniqj - uniqi), uniqi);
410 elem = nc_err_libyang_other_elem("non-unique", path, len);
411 if (!elem) {
412 free(path);
413 return e;
414 }
415 nc_err_add_info_other(e, elem);
416
417 len = sprintf(path, "%.*s/%.*s", (int)(strl - strk), strk, (int)(uniqj - uniqi), uniqi);
418 elem = nc_err_libyang_other_elem("non-unique", path, len);
419 if (!elem) {
420 return e;
421 }
422 nc_err_add_info_other(e, elem);
423
424 if (uniqj[0] == '"') {
425 break;
426 }
427 uniqi = uniqj + 1;
428 }
429 free(path);
430 break;
431 case LYVE_NOMAX:
432 e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
433 nc_err_set_app_tag(e, "too-many-elements");
434 nc_err_set_path(e, ly_errpath());
435 break;
436 case LYVE_NOMIN:
437 e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
438 nc_err_set_app_tag(e, "too-few-elements");
439 nc_err_set_path(e, ly_errpath());
440 break;
441 case LYVE_NOMUST:
442 e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
443 if (ly_errapptag()[0]) {
444 nc_err_set_app_tag(e, ly_errapptag());
445 } else {
446 nc_err_set_app_tag(e, "must-violation");
447 }
448 break;
449 case LYVE_NOREQINS:
450 case LYVE_NOLEAFREF:
451 e = nc_err(NC_ERR_DATA_MISSING);
452 nc_err_set_app_tag(e, "instance-required");
453 nc_err_set_path(e, ly_errpath());
454 break;
455 case LYVE_NOMANDCHOICE:
456 e = nc_err(NC_ERR_DATA_MISSING);
457 nc_err_set_app_tag(e, "missing-choice");
458 nc_err_set_path(e, ly_errpath());
459
460 str = ly_errmsg();
461 stri = strchr(str, '"');
462 stri++;
463 strj = strchr(stri, '"');
464 elem = nc_err_libyang_other_elem("missing-choice", stri, strj - stri);
465 if (elem) {
466 nc_err_add_info_other(e, elem);
467 }
468 break;
Radek Krejci877e1822016-04-06 16:37:43 +0200469 case LYVE_INELEM:
470 str = ly_errpath();
471 if (!strcmp(str, "/")) {
472 e = nc_err(NC_ERR_OP_NOT_SUPPORTED, NC_ERR_TYPE_APP);
473 /* keep default message */
474 return e;
475 } else {
476 e = nc_err(NC_ERR_UNKNOWN_ELEM, NC_ERR_TYPE_PROT, ly_errpath());
477 }
478 break;
479 case LYVE_MISSELEM:
480 case LYVE_INORDER:
481 e = nc_err(NC_ERR_MISSING_ELEM, NC_ERR_TYPE_PROT, ly_errpath());
482 break;
483 case LYVE_INVAL:
484 e = nc_err(NC_ERR_BAD_ELEM, NC_ERR_TYPE_PROT, ly_errpath());
485 break;
486 case LYVE_INATTR:
487 case LYVE_MISSATTR:
Michal Vasko37fdad52017-03-02 11:40:22 +0100488 case LYVE_INMETA:
Radek Krejci877e1822016-04-06 16:37:43 +0200489 str = ly_errmsg();
490 stri = strchr(str, '"');
491 stri++;
492 strj = strchr(stri, '"');
493 strj--;
494 attr = strndup(stri, strj - stri);
Radek Krejci537fb522016-04-07 16:36:25 +0200495 if (ly_vecode == LYVE_INATTR) {
496 e = nc_err(NC_ERR_UNKNOWN_ATTR, NC_ERR_TYPE_PROT, attr, ly_errpath());
497 } else if (ly_vecode == LYVE_MISSATTR) {
498 e = nc_err(NC_ERR_MISSING_ATTR, NC_ERR_TYPE_PROT, attr, ly_errpath());
Michal Vasko37fdad52017-03-02 11:40:22 +0100499 } else { /* LYVE_INMETA */
Radek Krejci537fb522016-04-07 16:36:25 +0200500 e = nc_err(NC_ERR_BAD_ATTR, NC_ERR_TYPE_PROT, attr, ly_errpath());
501 }
Radek Krejci877e1822016-04-06 16:37:43 +0200502 free(attr);
503 break;
Michal Vaskoa08e5c02016-04-12 15:12:04 +0200504 case LYVE_NOCONSTR:
505 case LYVE_NOWHEN:
Radek Krejci877e1822016-04-06 16:37:43 +0200506 e = nc_err(NC_ERR_INVALID_VALUE, NC_ERR_TYPE_PROT);
Michal Vaskoa08e5c02016-04-12 15:12:04 +0200507 /* LYVE_NOCONSTR (length, range, pattern) can have a specific error-app-tag */
508 if (ly_errapptag()[0]) {
509 nc_err_set_app_tag(e, ly_errapptag());
510 }
Radek Krejci877e1822016-04-06 16:37:43 +0200511 break;
512 default:
513 e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
514 break;
515 }
516 } else {
517 /* non-validation (internal) error */
518 e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
519 }
520 nc_err_set_msg(e, ly_errmsg(), "en");
521 return e;
522}
523
Michal Vasko8f3198f2016-05-04 10:45:28 +0200524API NC_ERR_TYPE
Michal Vaskoea201782017-03-16 09:49:54 +0100525nc_err_get_type(const struct nc_server_error *err)
Michal Vasko8f3198f2016-05-04 10:45:28 +0200526{
527 if (!err) {
528 ERRARG("err");
529 return 0;
530 }
531
532 return err->type;
533}
534
535API NC_ERR
Michal Vaskoea201782017-03-16 09:49:54 +0100536nc_err_get_tag(const struct nc_server_error *err)
Michal Vasko8f3198f2016-05-04 10:45:28 +0200537{
538 if (!err) {
539 ERRARG("err");
540 return 0;
541 }
542
543 return err->tag;
544}
545
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100546API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100547nc_err_set_app_tag(struct nc_server_error *err, const char *error_app_tag)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100548{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200549 if (!err) {
550 ERRARG("err");
551 return -1;
552 } else if (!error_app_tag) {
553 ERRARG("error_app_tag");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100554 return -1;
555 }
556
557 if (err->apptag) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100558 lydict_remove(server_opts.ctx, err->apptag);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100559 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100560 err->apptag = lydict_insert(server_opts.ctx, error_app_tag, 0);
Michal Vasko11d142a2016-01-19 15:58:24 +0100561
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100562 return 0;
563}
564
Michal Vasko8f3198f2016-05-04 10:45:28 +0200565API const char *
Michal Vaskoea201782017-03-16 09:49:54 +0100566nc_err_get_app_tag(const struct nc_server_error *err)
Michal Vasko8f3198f2016-05-04 10:45:28 +0200567{
568 if (!err) {
569 ERRARG("err");
570 return NULL;
571 }
572
573 return err->apptag;
574}
575
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100576API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100577nc_err_set_path(struct nc_server_error *err, const char *error_path)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100578{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200579 if (!err) {
580 ERRARG("err");
581 return -1;
582 } else if (!error_path) {
583 ERRARG("error_path");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100584 return -1;
585 }
586
587 if (err->path) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100588 lydict_remove(server_opts.ctx, err->path);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100589 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100590 err->path = lydict_insert(server_opts.ctx, error_path, 0);
Michal Vasko11d142a2016-01-19 15:58:24 +0100591
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100592 return 0;
593}
594
Michal Vasko8f3198f2016-05-04 10:45:28 +0200595API const char *
Michal Vaskoea201782017-03-16 09:49:54 +0100596nc_err_get_path(const struct nc_server_error *err)
Michal Vasko8f3198f2016-05-04 10:45:28 +0200597{
598 if (!err) {
599 ERRARG("err");
600 return 0;
601 }
602
603 return err->path;
604}
605
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100606API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100607nc_err_set_msg(struct nc_server_error *err, const char *error_message, const char *lang)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100608{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200609 if (!err) {
610 ERRARG("err");
611 return -1;
612 } else if (!error_message) {
613 ERRARG("error_message");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100614 return -1;
615 }
616
617 if (err->message) {
Michal Vasko092ea742016-04-12 15:08:59 +0200618 lydict_remove(server_opts.ctx, err->message);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100619 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100620 err->message = lydict_insert(server_opts.ctx, error_message, 0);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100621
622 if (err->message_lang) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100623 lydict_remove(server_opts.ctx, err->message_lang);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100624 }
625 if (lang) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100626 err->message_lang = lydict_insert(server_opts.ctx, lang, 0);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100627 } else {
628 lang = NULL;
629 }
Michal Vasko11d142a2016-01-19 15:58:24 +0100630
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100631 return 0;
632}
633
Michal Vasko8f3198f2016-05-04 10:45:28 +0200634API const char *
Michal Vaskoea201782017-03-16 09:49:54 +0100635nc_err_get_msg(const struct nc_server_error *err)
Michal Vasko8f3198f2016-05-04 10:45:28 +0200636{
637 if (!err) {
638 ERRARG("err");
639 return 0;
640 }
641
642 return err->message;
643}
644
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100645API int
646nc_err_set_sid(struct nc_server_error *err, uint32_t session_id)
647{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200648 if (!err) {
649 ERRARG("err");
650 return -1;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100651 }
652
653 err->sid = session_id;
654 return 0;
655}
656
657API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100658nc_err_add_bad_attr(struct nc_server_error *err, const char *attr_name)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100659{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200660 if (!err) {
661 ERRARG("err");
662 return -1;
663 } else if (!attr_name) {
664 ERRARG("attr_name");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100665 return -1;
666 }
667
668 ++err->attr_count;
Michal Vasko4eb3c312016-03-01 14:09:37 +0100669 err->attr = nc_realloc(err->attr, err->attr_count * sizeof *err->attr);
670 if (!err->attr) {
671 ERRMEM;
672 return -1;
673 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100674 err->attr[err->attr_count - 1] = lydict_insert(server_opts.ctx, attr_name, 0);
Michal Vasko11d142a2016-01-19 15:58:24 +0100675
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100676 return 0;
677}
678
679API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100680nc_err_add_bad_elem(struct nc_server_error *err, const char *elem_name)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100681{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200682 if (!err) {
683 ERRARG("err");
684 return -1;
685 } else if (!elem_name) {
686 ERRARG("elem_name");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100687 return -1;
688 }
689
690 ++err->elem_count;
Michal Vasko4eb3c312016-03-01 14:09:37 +0100691 err->elem = nc_realloc(err->elem, err->elem_count * sizeof *err->elem);
692 if (!err->elem) {
693 ERRMEM;
694 return -1;
695 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100696 err->elem[err->elem_count - 1] = lydict_insert(server_opts.ctx, elem_name, 0);
Michal Vasko11d142a2016-01-19 15:58:24 +0100697
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100698 return 0;
699}
700
701API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100702nc_err_add_bad_ns(struct nc_server_error *err, const char *ns_name)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100703{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200704 if (!err) {
705 ERRARG("err");
706 return -1;
707 } else if (!ns_name) {
708 ERRARG("ns_name");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100709 return -1;
710 }
711
712 ++err->ns_count;
Michal Vasko4eb3c312016-03-01 14:09:37 +0100713 err->ns = nc_realloc(err->ns, err->ns_count * sizeof *err->ns);
714 if (!err->ns) {
715 ERRMEM;
716 return -1;
717 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100718 err->ns[err->ns_count - 1] = lydict_insert(server_opts.ctx, ns_name, 0);
Michal Vasko11d142a2016-01-19 15:58:24 +0100719
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100720 return 0;
721}
722
723API int
724nc_err_add_info_other(struct nc_server_error *err, struct lyxml_elem *other)
725{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200726 if (!err) {
727 ERRARG("err");
728 return -1;
729 } else if (!other) {
730 ERRARG("other");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100731 return -1;
732 }
733
734 ++err->other_count;
Michal Vasko4eb3c312016-03-01 14:09:37 +0100735 err->other = nc_realloc(err->other, err->other_count * sizeof *err->other);
736 if (!err->other) {
737 ERRMEM;
738 return -1;
739 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100740 err->other[err->other_count - 1] = other;
741 return 0;
742}
743
744void
Michal Vaskoca4a2422016-02-02 12:17:14 +0100745nc_server_rpc_free(struct nc_server_rpc *rpc, struct ly_ctx *ctx)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100746{
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100747 if (!rpc) {
748 return;
749 }
750
Michal Vaskoca4a2422016-02-02 12:17:14 +0100751 lyxml_free(ctx, rpc->root);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100752 lyd_free(rpc->tree);
Michal Vasko11d142a2016-01-19 15:58:24 +0100753
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100754 free(rpc);
755}
756
757API void
758nc_server_reply_free(struct nc_server_reply *reply)
759{
760 uint32_t i;
761 struct nc_server_reply_data *data_rpl;
762 struct nc_server_reply_error *error_rpl;
763
764 if (!reply) {
765 return;
766 }
767
768 switch (reply->type) {
769 case NC_RPL_DATA:
770 data_rpl = (struct nc_server_reply_data *)reply;
771 if (data_rpl->free) {
772 lyd_free_withsiblings(data_rpl->data);
773 }
774 break;
775 case NC_RPL_OK:
776 /* nothing to free */
777 break;
778 case NC_RPL_ERROR:
779 error_rpl = (struct nc_server_reply_error *)reply;
780 for (i = 0; i < error_rpl->count; ++i) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100781 nc_err_free(error_rpl->err[i]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100782 }
783 free(error_rpl->err);
784 break;
785 default:
786 break;
787 }
788 free(reply);
789}
790
791API void
Michal Vasko1a38c862016-01-15 15:50:07 +0100792nc_err_free(struct nc_server_error *err)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100793{
794 uint32_t i;
795
796 if (!err) {
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100797 return;
798 }
799
Michal Vasko1a38c862016-01-15 15:50:07 +0100800 lydict_remove(server_opts.ctx, err->apptag);
801 lydict_remove(server_opts.ctx, err->path);
802 lydict_remove(server_opts.ctx, err->message);
803 lydict_remove(server_opts.ctx, err->message_lang);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100804 for (i = 0; i < err->attr_count; ++i) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100805 lydict_remove(server_opts.ctx, err->attr[i]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100806 }
807 free(err->attr);
808 for (i = 0; i < err->elem_count; ++i) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100809 lydict_remove(server_opts.ctx, err->elem[i]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100810 }
811 free(err->elem);
812 for (i = 0; i < err->ns_count; ++i) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100813 lydict_remove(server_opts.ctx, err->ns[i]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100814 }
815 free(err->ns);
816 for (i = 0; i < err->other_count; ++i) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100817 lyxml_free(server_opts.ctx, err->other[i]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100818 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100819 free(err->other);
820 free(err);
821}
Radek Krejci93e80222016-10-03 13:34:25 +0200822
823API struct nc_server_notif *
Michal Vaskofc9dbdd2017-03-17 09:27:57 +0100824nc_server_notif_new(struct lyd_node* event, char *eventtime, NC_PARAMTYPE paramtype)
Radek Krejci93e80222016-10-03 13:34:25 +0200825{
826 struct nc_server_notif *ntf;
827
828 if (!event || event->schema->nodetype != LYS_NOTIF) {
829 ERRARG("event");
830 return NULL;
831 } else if (!eventtime) {
832 ERRARG("eventtime");
833 return NULL;
834 }
835
836 ntf = malloc(sizeof *ntf);
Michal Vaskofc9dbdd2017-03-17 09:27:57 +0100837 if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
Radek Krejci93e80222016-10-03 13:34:25 +0200838 ntf->eventtime = strdup(eventtime);
Michal Vaskofc9dbdd2017-03-17 09:27:57 +0100839 ntf->tree = lyd_dup(event, 1);
Radek Krejci93e80222016-10-03 13:34:25 +0200840 } else {
841 ntf->eventtime = eventtime;
Michal Vaskofc9dbdd2017-03-17 09:27:57 +0100842 ntf->tree = event;
Radek Krejci93e80222016-10-03 13:34:25 +0200843 }
Michal Vaskofc9dbdd2017-03-17 09:27:57 +0100844 ntf->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
Radek Krejci93e80222016-10-03 13:34:25 +0200845
846 return ntf;
847}
848
849API void
850nc_server_notif_free(struct nc_server_notif *notif)
851{
852 if (!notif) {
853 return;
854 }
855
Michal Vaskofc9dbdd2017-03-17 09:27:57 +0100856 if (notif->free) {
857 lyd_free(notif->tree);
858 free(notif->eventtime);
859 }
Radek Krejci93e80222016-10-03 13:34:25 +0200860 free(notif);
861}
Michal Vasko9a2e4d22017-03-17 09:44:49 +0100862
863API const char *
864nc_server_notif_get_time(const struct nc_server_notif *notif)
865{
866 if (!notif) {
867 ERRARG("notif");
868 return NULL;
869 }
870
871 return notif->eventtime;
872}