blob: 9962af11859c9d659f8fcdff0da2eb6a59c07508 [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++;
Michal Vasko11a0c4f2018-01-03 14:29:06 +0100492 if (!strncmp(stri, "<none>:", 7)) {
493 stri += 7;
494 }
Radek Krejci877e1822016-04-06 16:37:43 +0200495 strj = strchr(stri, '"');
496 strj--;
Michal Vasko630485f2018-01-03 14:28:32 +0100497 attr = strndup(stri, (strj - stri) + 1);
Radek Krejci537fb522016-04-07 16:36:25 +0200498 if (ly_vecode == LYVE_INATTR) {
499 e = nc_err(NC_ERR_UNKNOWN_ATTR, NC_ERR_TYPE_PROT, attr, ly_errpath());
500 } else if (ly_vecode == LYVE_MISSATTR) {
501 e = nc_err(NC_ERR_MISSING_ATTR, NC_ERR_TYPE_PROT, attr, ly_errpath());
Michal Vasko37fdad52017-03-02 11:40:22 +0100502 } else { /* LYVE_INMETA */
Radek Krejci537fb522016-04-07 16:36:25 +0200503 e = nc_err(NC_ERR_BAD_ATTR, NC_ERR_TYPE_PROT, attr, ly_errpath());
504 }
Radek Krejci877e1822016-04-06 16:37:43 +0200505 free(attr);
506 break;
Michal Vaskoa08e5c02016-04-12 15:12:04 +0200507 case LYVE_NOCONSTR:
508 case LYVE_NOWHEN:
Radek Krejci877e1822016-04-06 16:37:43 +0200509 e = nc_err(NC_ERR_INVALID_VALUE, NC_ERR_TYPE_PROT);
Michal Vaskoa08e5c02016-04-12 15:12:04 +0200510 /* LYVE_NOCONSTR (length, range, pattern) can have a specific error-app-tag */
511 if (ly_errapptag()[0]) {
512 nc_err_set_app_tag(e, ly_errapptag());
513 }
Radek Krejci877e1822016-04-06 16:37:43 +0200514 break;
515 default:
516 e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
517 break;
518 }
519 } else {
520 /* non-validation (internal) error */
521 e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
522 }
523 nc_err_set_msg(e, ly_errmsg(), "en");
524 return e;
525}
526
Michal Vasko8f3198f2016-05-04 10:45:28 +0200527API NC_ERR_TYPE
Michal Vaskoea201782017-03-16 09:49:54 +0100528nc_err_get_type(const struct nc_server_error *err)
Michal Vasko8f3198f2016-05-04 10:45:28 +0200529{
530 if (!err) {
531 ERRARG("err");
532 return 0;
533 }
534
535 return err->type;
536}
537
538API NC_ERR
Michal Vaskoea201782017-03-16 09:49:54 +0100539nc_err_get_tag(const struct nc_server_error *err)
Michal Vasko8f3198f2016-05-04 10:45:28 +0200540{
541 if (!err) {
542 ERRARG("err");
543 return 0;
544 }
545
546 return err->tag;
547}
548
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100549API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100550nc_err_set_app_tag(struct nc_server_error *err, const char *error_app_tag)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100551{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200552 if (!err) {
553 ERRARG("err");
554 return -1;
555 } else if (!error_app_tag) {
556 ERRARG("error_app_tag");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100557 return -1;
558 }
559
560 if (err->apptag) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100561 lydict_remove(server_opts.ctx, err->apptag);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100562 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100563 err->apptag = lydict_insert(server_opts.ctx, error_app_tag, 0);
Michal Vasko11d142a2016-01-19 15:58:24 +0100564
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100565 return 0;
566}
567
Michal Vasko8f3198f2016-05-04 10:45:28 +0200568API const char *
Michal Vaskoea201782017-03-16 09:49:54 +0100569nc_err_get_app_tag(const struct nc_server_error *err)
Michal Vasko8f3198f2016-05-04 10:45:28 +0200570{
571 if (!err) {
572 ERRARG("err");
573 return NULL;
574 }
575
576 return err->apptag;
577}
578
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100579API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100580nc_err_set_path(struct nc_server_error *err, const char *error_path)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100581{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200582 if (!err) {
583 ERRARG("err");
584 return -1;
585 } else if (!error_path) {
586 ERRARG("error_path");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100587 return -1;
588 }
589
590 if (err->path) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100591 lydict_remove(server_opts.ctx, err->path);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100592 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100593 err->path = lydict_insert(server_opts.ctx, error_path, 0);
Michal Vasko11d142a2016-01-19 15:58:24 +0100594
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100595 return 0;
596}
597
Michal Vasko8f3198f2016-05-04 10:45:28 +0200598API const char *
Michal Vaskoea201782017-03-16 09:49:54 +0100599nc_err_get_path(const struct nc_server_error *err)
Michal Vasko8f3198f2016-05-04 10:45:28 +0200600{
601 if (!err) {
602 ERRARG("err");
603 return 0;
604 }
605
606 return err->path;
607}
608
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100609API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100610nc_err_set_msg(struct nc_server_error *err, const char *error_message, const char *lang)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100611{
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
620 if (err->message) {
Michal Vasko092ea742016-04-12 15:08:59 +0200621 lydict_remove(server_opts.ctx, err->message);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100622 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100623 err->message = lydict_insert(server_opts.ctx, error_message, 0);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100624
625 if (err->message_lang) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100626 lydict_remove(server_opts.ctx, err->message_lang);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100627 }
628 if (lang) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100629 err->message_lang = lydict_insert(server_opts.ctx, lang, 0);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100630 } else {
631 lang = NULL;
632 }
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 Vaskoea201782017-03-16 09:49:54 +0100638nc_err_get_msg(const struct nc_server_error *err)
Michal Vasko8f3198f2016-05-04 10:45:28 +0200639{
640 if (!err) {
641 ERRARG("err");
642 return 0;
643 }
644
645 return err->message;
646}
647
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100648API int
649nc_err_set_sid(struct nc_server_error *err, uint32_t session_id)
650{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200651 if (!err) {
652 ERRARG("err");
653 return -1;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100654 }
655
656 err->sid = session_id;
657 return 0;
658}
659
660API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100661nc_err_add_bad_attr(struct nc_server_error *err, const char *attr_name)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100662{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200663 if (!err) {
664 ERRARG("err");
665 return -1;
666 } else if (!attr_name) {
667 ERRARG("attr_name");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100668 return -1;
669 }
670
671 ++err->attr_count;
Michal Vasko4eb3c312016-03-01 14:09:37 +0100672 err->attr = nc_realloc(err->attr, err->attr_count * sizeof *err->attr);
673 if (!err->attr) {
674 ERRMEM;
675 return -1;
676 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100677 err->attr[err->attr_count - 1] = lydict_insert(server_opts.ctx, attr_name, 0);
Michal Vasko11d142a2016-01-19 15:58:24 +0100678
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100679 return 0;
680}
681
682API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100683nc_err_add_bad_elem(struct nc_server_error *err, const char *elem_name)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100684{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200685 if (!err) {
686 ERRARG("err");
687 return -1;
688 } else if (!elem_name) {
689 ERRARG("elem_name");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100690 return -1;
691 }
692
693 ++err->elem_count;
Michal Vasko4eb3c312016-03-01 14:09:37 +0100694 err->elem = nc_realloc(err->elem, err->elem_count * sizeof *err->elem);
695 if (!err->elem) {
696 ERRMEM;
697 return -1;
698 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100699 err->elem[err->elem_count - 1] = lydict_insert(server_opts.ctx, elem_name, 0);
Michal Vasko11d142a2016-01-19 15:58:24 +0100700
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100701 return 0;
702}
703
704API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100705nc_err_add_bad_ns(struct nc_server_error *err, const char *ns_name)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100706{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200707 if (!err) {
708 ERRARG("err");
709 return -1;
710 } else if (!ns_name) {
711 ERRARG("ns_name");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100712 return -1;
713 }
714
715 ++err->ns_count;
Michal Vasko4eb3c312016-03-01 14:09:37 +0100716 err->ns = nc_realloc(err->ns, err->ns_count * sizeof *err->ns);
717 if (!err->ns) {
718 ERRMEM;
719 return -1;
720 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100721 err->ns[err->ns_count - 1] = lydict_insert(server_opts.ctx, ns_name, 0);
Michal Vasko11d142a2016-01-19 15:58:24 +0100722
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100723 return 0;
724}
725
726API int
727nc_err_add_info_other(struct nc_server_error *err, struct lyxml_elem *other)
728{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200729 if (!err) {
730 ERRARG("err");
731 return -1;
732 } else if (!other) {
733 ERRARG("other");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100734 return -1;
735 }
736
737 ++err->other_count;
Michal Vasko4eb3c312016-03-01 14:09:37 +0100738 err->other = nc_realloc(err->other, err->other_count * sizeof *err->other);
739 if (!err->other) {
740 ERRMEM;
741 return -1;
742 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100743 err->other[err->other_count - 1] = other;
744 return 0;
745}
746
747void
Michal Vaskoca4a2422016-02-02 12:17:14 +0100748nc_server_rpc_free(struct nc_server_rpc *rpc, struct ly_ctx *ctx)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100749{
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100750 if (!rpc) {
751 return;
752 }
753
Michal Vaskoca4a2422016-02-02 12:17:14 +0100754 lyxml_free(ctx, rpc->root);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100755 lyd_free(rpc->tree);
Michal Vasko11d142a2016-01-19 15:58:24 +0100756
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100757 free(rpc);
758}
759
760API void
761nc_server_reply_free(struct nc_server_reply *reply)
762{
763 uint32_t i;
764 struct nc_server_reply_data *data_rpl;
765 struct nc_server_reply_error *error_rpl;
766
767 if (!reply) {
768 return;
769 }
770
771 switch (reply->type) {
772 case NC_RPL_DATA:
773 data_rpl = (struct nc_server_reply_data *)reply;
774 if (data_rpl->free) {
775 lyd_free_withsiblings(data_rpl->data);
776 }
777 break;
778 case NC_RPL_OK:
779 /* nothing to free */
780 break;
781 case NC_RPL_ERROR:
782 error_rpl = (struct nc_server_reply_error *)reply;
783 for (i = 0; i < error_rpl->count; ++i) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100784 nc_err_free(error_rpl->err[i]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100785 }
786 free(error_rpl->err);
787 break;
788 default:
789 break;
790 }
791 free(reply);
792}
793
794API void
Michal Vasko1a38c862016-01-15 15:50:07 +0100795nc_err_free(struct nc_server_error *err)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100796{
797 uint32_t i;
798
799 if (!err) {
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100800 return;
801 }
802
Michal Vasko1a38c862016-01-15 15:50:07 +0100803 lydict_remove(server_opts.ctx, err->apptag);
804 lydict_remove(server_opts.ctx, err->path);
805 lydict_remove(server_opts.ctx, err->message);
806 lydict_remove(server_opts.ctx, err->message_lang);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100807 for (i = 0; i < err->attr_count; ++i) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100808 lydict_remove(server_opts.ctx, err->attr[i]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100809 }
810 free(err->attr);
811 for (i = 0; i < err->elem_count; ++i) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100812 lydict_remove(server_opts.ctx, err->elem[i]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100813 }
814 free(err->elem);
815 for (i = 0; i < err->ns_count; ++i) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100816 lydict_remove(server_opts.ctx, err->ns[i]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100817 }
818 free(err->ns);
819 for (i = 0; i < err->other_count; ++i) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100820 lyxml_free(server_opts.ctx, err->other[i]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100821 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100822 free(err->other);
823 free(err);
824}
Radek Krejci93e80222016-10-03 13:34:25 +0200825
826API struct nc_server_notif *
Michal Vaskofc9dbdd2017-03-17 09:27:57 +0100827nc_server_notif_new(struct lyd_node* event, char *eventtime, NC_PARAMTYPE paramtype)
Radek Krejci93e80222016-10-03 13:34:25 +0200828{
829 struct nc_server_notif *ntf;
Michal Vasko0b89f3d2018-01-04 10:57:03 +0100830 struct lyd_node *elem;
Radek Krejci93e80222016-10-03 13:34:25 +0200831
Michal Vasko3106b7b2018-01-04 10:32:42 +0100832 if (!event) {
Radek Krejci93e80222016-10-03 13:34:25 +0200833 ERRARG("event");
834 return NULL;
835 } else if (!eventtime) {
836 ERRARG("eventtime");
837 return NULL;
838 }
839
Michal Vasko0b89f3d2018-01-04 10:57:03 +0100840 /* check that there is a notification */
841 for (elem = event; elem && (elem->schema->nodetype != LYS_NOTIF); elem = elem->child) {
842next_node:
843 switch (elem->schema->nodetype) {
844 case LYS_LEAF:
845 /* key, skip it */
846 elem = elem->next;
847 if (!elem) {
848 /* error */
849 break;
850 }
851 goto next_node;
852 case LYS_CONTAINER:
853 case LYS_LIST:
854 case LYS_NOTIF:
855 /* ok */
856 break;
857 default:
858 /* error */
859 elem = NULL;
860 break;
861 }
862 }
863 if (!elem) {
864 ERRARG("event");
865 return NULL;
866 }
867
Radek Krejci93e80222016-10-03 13:34:25 +0200868 ntf = malloc(sizeof *ntf);
Michal Vaskofc9dbdd2017-03-17 09:27:57 +0100869 if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
Radek Krejci93e80222016-10-03 13:34:25 +0200870 ntf->eventtime = strdup(eventtime);
Michal Vaskofc9dbdd2017-03-17 09:27:57 +0100871 ntf->tree = lyd_dup(event, 1);
Radek Krejci93e80222016-10-03 13:34:25 +0200872 } else {
873 ntf->eventtime = eventtime;
Michal Vaskofc9dbdd2017-03-17 09:27:57 +0100874 ntf->tree = event;
Radek Krejci93e80222016-10-03 13:34:25 +0200875 }
Michal Vaskofc9dbdd2017-03-17 09:27:57 +0100876 ntf->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
Radek Krejci93e80222016-10-03 13:34:25 +0200877
878 return ntf;
879}
880
881API void
882nc_server_notif_free(struct nc_server_notif *notif)
883{
884 if (!notif) {
885 return;
886 }
887
Michal Vaskofc9dbdd2017-03-17 09:27:57 +0100888 if (notif->free) {
889 lyd_free(notif->tree);
890 free(notif->eventtime);
891 }
Radek Krejci93e80222016-10-03 13:34:25 +0200892 free(notif);
893}
Michal Vasko9a2e4d22017-03-17 09:44:49 +0100894
895API const char *
896nc_server_notif_get_time(const struct nc_server_notif *notif)
897{
898 if (!notif) {
899 ERRARG("notif");
900 return NULL;
901 }
902
903 return notif->eventtime;
904}