blob: c3327f5abd62e602b77efdd2a865f976f7d036dd [file] [log] [blame]
Michal Vasko7bcb48e2016-01-15 10:28:54 +01001/**
2 * \file messages_server.c
3 * \author Michal Vasko <mvasko@cesnet.cz>
4 * \brief libnetconf2 - server NETCONF messages functions
5 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
Radek Krejci9b81f5b2016-02-24 13:14:49 +01008 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
Michal Vaskoafd416b2016-02-25 14:51:46 +010011 *
Radek Krejci9b81f5b2016-02-24 13:14:49 +010012 * https://opensource.org/licenses/BSD-3-Clause
Michal Vasko7bcb48e2016-01-15 10:28:54 +010013 */
14
15#include <ctype.h>
16#include <stdlib.h>
17#include <string.h>
18#include <stdarg.h>
19
20#include <libyang/libyang.h>
21
Michal Vasko11d142a2016-01-19 15:58:24 +010022#include "session_server.h"
Michal Vasko7bcb48e2016-01-15 10:28:54 +010023#include "libnetconf.h"
Michal Vasko1a38c862016-01-15 15:50:07 +010024
25extern struct nc_server_opts server_opts;
Michal Vasko7bcb48e2016-01-15 10:28:54 +010026
27API struct nc_server_reply *
28nc_server_reply_ok(void)
29{
30 struct nc_server_reply *ret;
31
32 ret = malloc(sizeof *ret);
33 if (!ret) {
34 ERRMEM;
35 return NULL;
36 }
37
38 ret->type = NC_RPL_OK;
39 return ret;
40}
41
42API struct nc_server_reply *
43nc_server_reply_data(struct lyd_node *data, NC_PARAMTYPE paramtype)
44{
45 struct nc_server_reply_data *ret;
46
Michal Vaskob08743b2016-04-13 14:23:49 +020047 if (!data) {
48 ERRARG("data");
49 return NULL;
50 }
51
Michal Vasko7bcb48e2016-01-15 10:28:54 +010052 ret = malloc(sizeof *ret);
53 if (!ret) {
54 ERRMEM;
55 return NULL;
56 }
57
58 ret->type = NC_RPL_DATA;
Michal Vaskob08743b2016-04-13 14:23:49 +020059 if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
Michal Vasko7bcb48e2016-01-15 10:28:54 +010060 ret->data = lyd_dup(data, 1);
61 } else {
62 ret->data = data;
63 }
64 if (paramtype != NC_PARAMTYPE_CONST) {
65 ret->free = 1;
66 } else {
67 ret->free = 0;
68 }
69 return (struct nc_server_reply *)ret;
70}
71
72API struct nc_server_reply *
Michal Vasko1a38c862016-01-15 15:50:07 +010073nc_server_reply_err(struct nc_server_error *err)
Michal Vasko7bcb48e2016-01-15 10:28:54 +010074{
75 struct nc_server_reply_error *ret;
76
Michal Vasko1a38c862016-01-15 15:50:07 +010077 if (!err) {
Michal Vasko45e53ae2016-04-07 11:46:03 +020078 ERRARG("err");
Michal Vasko7bcb48e2016-01-15 10:28:54 +010079 return NULL;
80 }
81
82 ret = malloc(sizeof *ret);
83 if (!ret) {
84 ERRMEM;
85 return NULL;
86 }
87
88 ret->type = NC_RPL_ERROR;
Michal Vasko7bcb48e2016-01-15 10:28:54 +010089 ret->err = malloc(sizeof *ret->err);
Michal Vasko4eb3c312016-03-01 14:09:37 +010090 if (!ret->err) {
91 ERRMEM;
92 free(ret);
93 return NULL;
94 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +010095 ret->err[0] = err;
96 ret->count = 1;
97 return (struct nc_server_reply *)ret;
98}
99
100API int
101nc_server_reply_add_err(struct nc_server_reply *reply, struct nc_server_error *err)
102{
103 struct nc_server_reply_error *err_rpl;
104
Michal Vasko45e53ae2016-04-07 11:46:03 +0200105 if (!reply || (reply->type != NC_RPL_ERROR)) {
106 ERRARG("reply");
107 return -1;
108 } else if (!err) {
109 ERRARG("err");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100110 return -1;
111 }
112
113 err_rpl = (struct nc_server_reply_error *)reply;
114 ++err_rpl->count;
Michal Vasko4eb3c312016-03-01 14:09:37 +0100115 err_rpl->err = nc_realloc(err_rpl->err, err_rpl->count * sizeof *err_rpl->err);
116 if (!err_rpl->err) {
117 ERRMEM;
118 return -1;
119 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100120 err_rpl->err[err_rpl->count - 1] = err;
121 return 0;
122}
123
124API struct nc_server_error *
Michal Vasko1a38c862016-01-15 15:50:07 +0100125nc_err(NC_ERR tag, ...)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100126{
127 va_list ap;
128 struct nc_server_error *ret;
129 NC_ERR_TYPE type;
130 const char *arg1, *arg2;
131 uint32_t sid;
132
Michal Vasko1a38c862016-01-15 15:50:07 +0100133 if (!tag) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200134 ERRARG("tag");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100135 return NULL;
136 }
137
138 ret = calloc(1, sizeof *ret);
139 if (!ret) {
140 ERRMEM;
141 return NULL;
142 }
143
144 va_start(ap, tag);
145
146 switch (tag) {
147 case NC_ERR_IN_USE:
148 case NC_ERR_INVALID_VALUE:
149 case NC_ERR_ACCESS_DENIED:
150 case NC_ERR_ROLLBACK_FAILED:
151 case NC_ERR_OP_NOT_SUPPORTED:
152 type = va_arg(ap, NC_ERR_TYPE);
Michal Vasko2f923d12016-04-05 11:33:02 +0200153 if ((type != NC_ERR_TYPE_PROT) && (type != NC_ERR_TYPE_APP)) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200154 ERRARG("type");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100155 goto fail;
156 }
157 break;
158
159 case NC_ERR_TOO_BIG:
160 case NC_ERR_RES_DENIED:
161 type = va_arg(ap, NC_ERR_TYPE);
162 /* nothing to check */
163 break;
164
165 case NC_ERR_MISSING_ATTR:
166 case NC_ERR_BAD_ATTR:
167 case NC_ERR_UNKNOWN_ATTR:
168 type = va_arg(ap, NC_ERR_TYPE);
169 arg1 = va_arg(ap, const char *);
170 arg2 = va_arg(ap, const char *);
171
172 if (type == NC_ERR_TYPE_TRAN) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200173 ERRARG("type");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100174 goto fail;
175 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100176 nc_err_add_bad_attr(ret, arg1);
177 nc_err_add_bad_elem(ret, arg2);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100178 break;
179
180 case NC_ERR_MISSING_ELEM:
181 case NC_ERR_BAD_ELEM:
182 case NC_ERR_UNKNOWN_ELEM:
183 type = va_arg(ap, NC_ERR_TYPE);
184 arg1 = va_arg(ap, const char *);
185
186 if ((type != NC_ERR_TYPE_PROT) && (type != NC_ERR_TYPE_APP)) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200187 ERRARG("type");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100188 goto fail;
189 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100190 nc_err_add_bad_elem(ret, arg1);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100191 break;
192
193 case NC_ERR_UNKNOWN_NS:
194 type = va_arg(ap, NC_ERR_TYPE);
195 arg1 = va_arg(ap, const char *);
196 arg2 = va_arg(ap, const char *);
197
198 if ((type != NC_ERR_TYPE_PROT) && (type != NC_ERR_TYPE_APP)) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200199 ERRARG("type");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100200 goto fail;
201 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100202 nc_err_add_bad_elem(ret, arg1);
203 nc_err_add_bad_ns(ret, arg2);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100204 break;
205
206 case NC_ERR_LOCK_DENIED:
207 sid = va_arg(ap, uint32_t);
208
209 type = NC_ERR_TYPE_PROT;
210 nc_err_set_sid(ret, sid);
211 break;
212
213 case NC_ERR_DATA_EXISTS:
214 case NC_ERR_DATA_MISSING:
215 type = NC_ERR_TYPE_APP;
216 break;
217
218 case NC_ERR_OP_FAILED:
219 type = va_arg(ap, NC_ERR_TYPE);
220
221 if (type == NC_ERR_TYPE_TRAN) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200222 ERRARG("type");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100223 goto fail;
224 }
225 break;
226
227 case NC_ERR_MALFORMED_MSG:
228 type = NC_ERR_TYPE_RPC;
229 break;
230
231 default:
Michal Vasko45e53ae2016-04-07 11:46:03 +0200232 ERRARG("tag");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100233 goto fail;
234 }
235
236 switch (tag) {
237 case NC_ERR_IN_USE:
Michal Vasko1a38c862016-01-15 15:50:07 +0100238 nc_err_set_msg(ret, "The request requires a resource that already is in use.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100239 break;
240 case NC_ERR_INVALID_VALUE:
Michal Vasko1a38c862016-01-15 15:50:07 +0100241 nc_err_set_msg(ret, "The request specifies an unacceptable value for one or more parameters.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100242 break;
243 case NC_ERR_TOO_BIG:
Michal Vasko1a38c862016-01-15 15:50:07 +0100244 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 +0100245 break;
246 case NC_ERR_MISSING_ATTR:
Michal Vasko1a38c862016-01-15 15:50:07 +0100247 nc_err_set_msg(ret, "An expected attribute is missing.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100248 break;
249 case NC_ERR_BAD_ATTR:
Michal Vasko1a38c862016-01-15 15:50:07 +0100250 nc_err_set_msg(ret, "An attribute value is not correct.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100251 break;
252 case NC_ERR_UNKNOWN_ATTR:
Michal Vasko1a38c862016-01-15 15:50:07 +0100253 nc_err_set_msg(ret, "An unexpected attribute is present.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100254 break;
255 case NC_ERR_MISSING_ELEM:
Michal Vasko1a38c862016-01-15 15:50:07 +0100256 nc_err_set_msg(ret, "An expected element is missing.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100257 break;
258 case NC_ERR_BAD_ELEM:
Michal Vasko1a38c862016-01-15 15:50:07 +0100259 nc_err_set_msg(ret, "An element value is not correct.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100260 break;
261 case NC_ERR_UNKNOWN_ELEM:
Michal Vasko1a38c862016-01-15 15:50:07 +0100262 nc_err_set_msg(ret, "An unexpected element is present.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100263 break;
264 case NC_ERR_UNKNOWN_NS:
Michal Vasko1a38c862016-01-15 15:50:07 +0100265 nc_err_set_msg(ret, "An unexpected namespace is present.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100266 break;
267 case NC_ERR_ACCESS_DENIED:
Michal Vasko1a38c862016-01-15 15:50:07 +0100268 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 +0100269 break;
270 case NC_ERR_LOCK_DENIED:
Michal Vasko1a38c862016-01-15 15:50:07 +0100271 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 +0100272 break;
273 case NC_ERR_RES_DENIED:
Michal Vasko1a38c862016-01-15 15:50:07 +0100274 nc_err_set_msg(ret, "Request could not be completed because of insufficient resources.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100275 break;
276 case NC_ERR_ROLLBACK_FAILED:
Michal Vasko1a38c862016-01-15 15:50:07 +0100277 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 +0100278 break;
279 case NC_ERR_DATA_EXISTS:
Michal Vasko1a38c862016-01-15 15:50:07 +0100280 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 +0100281 break;
282 case NC_ERR_DATA_MISSING:
Michal Vasko1a38c862016-01-15 15:50:07 +0100283 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 +0100284 break;
285 case NC_ERR_OP_NOT_SUPPORTED:
Michal Vasko1a38c862016-01-15 15:50:07 +0100286 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 +0100287 break;
288 case NC_ERR_OP_FAILED:
Michal Vasko1a38c862016-01-15 15:50:07 +0100289 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 +0100290 break;
291 case NC_ERR_MALFORMED_MSG:
Michal Vasko1a38c862016-01-15 15:50:07 +0100292 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 +0100293 break;
294 default:
Michal Vasko45e53ae2016-04-07 11:46:03 +0200295 ERRARG("tag");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100296 goto fail;
297 }
298
299 va_end(ap);
300
301 ret->type = type;
302 ret->tag = tag;
303 return ret;
304
305fail:
Michal Vasko11d142a2016-01-19 15:58:24 +0100306 va_end(ap);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100307 free(ret);
308 return NULL;
309}
310
Michal Vaskoa08e5c02016-04-12 15:12:04 +0200311static struct lyxml_elem *
312nc_err_libyang_other_elem(const char *name, const char *content, int cont_len)
313{
314 struct lyxml_elem *root = NULL;
315 struct lyxml_ns *ns;
316
317 root = calloc(1, sizeof *root);
318 if (!root) {
319 ERRMEM;
320 goto error;
321 }
322 root->prev = root;
323 root->name = lydict_insert(server_opts.ctx, name, 0);
324 root->content = lydict_insert(server_opts.ctx, content, cont_len);
325
326 ns = calloc(1, sizeof *root->ns);
327 if (!ns) {
328 ERRMEM;
329 goto error;
330 }
331 root->attr = (struct lyxml_attr *)ns;
332 ns->type = LYXML_ATTR_NS;
333 ns->parent = root;
334 ns->value = lydict_insert(server_opts.ctx, "urn:ietf:params:xml:ns:yang:1", 0);
335 root->ns = ns;
336
337 return root;
338
339error:
340 lyxml_free(server_opts.ctx, root);
341 return NULL;
342}
343
Radek Krejci877e1822016-04-06 16:37:43 +0200344API struct nc_server_error *
345nc_err_libyang(void)
346{
347 struct nc_server_error *e;
Michal Vaskoa08e5c02016-04-12 15:12:04 +0200348 struct lyxml_elem *elem;
349 const char *str, *stri, *strj, *strk, *strl, *uniqi, *uniqj;
350 char *attr, *path;
351 int len;
Radek Krejci877e1822016-04-06 16:37:43 +0200352
353 if (!ly_errno) {
354 /* LY_SUCCESS */
355 return NULL;
356 } else if (ly_errno == LY_EVALID) {
357 switch (ly_vecode) {
Michal Vaskoa08e5c02016-04-12 15:12:04 +0200358 /* RFC 6020 section 13 errors */
359 case LYVE_NOUNIQ:
360 e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
361 nc_err_set_app_tag(e, "data-not-unique");
362 nc_err_set_path(e, ly_errpath());
363
364 /* parse the message and get all the information we need */
365 str = ly_errmsg();
366 uniqi = strchr(str, '"');
367 uniqi++;
368 uniqj = strchr(uniqi, '"');
369
370 stri = strchr(uniqj + 1, '"');
371 stri++;
372 strj = strchr(stri, '"');
373
374 strk = strchr(strj + 1, '"');
375 ++strk;
376 strl = strchr(strk, '"');
377
378 /* maximum length is the whole unique string with the longer list instance identifier */
379 len = (uniqj - uniqi) + (strj - stri > strl - strk ? strj - stri : strl - strk);
380 path = malloc(len + 1);
381 if (!path) {
382 ERRMEM;
383 return e;
384 }
385
386 /* create non-unique elements, one in 1st list, one in 2nd list, for each unique list */
387 while (1) {
388 uniqj = strpbrk(uniqi, " \"");
389
390 len = sprintf(path, "%.*s/%.*s", (int)(strj - stri), stri, (int)(uniqj - uniqi), uniqi);
391 elem = nc_err_libyang_other_elem("non-unique", path, len);
392 if (!elem) {
393 free(path);
394 return e;
395 }
396 nc_err_add_info_other(e, elem);
397
398 len = sprintf(path, "%.*s/%.*s", (int)(strl - strk), strk, (int)(uniqj - uniqi), uniqi);
399 elem = nc_err_libyang_other_elem("non-unique", path, len);
400 if (!elem) {
401 return e;
402 }
403 nc_err_add_info_other(e, elem);
404
405 if (uniqj[0] == '"') {
406 break;
407 }
408 uniqi = uniqj + 1;
409 }
410 free(path);
411 break;
412 case LYVE_NOMAX:
413 e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
414 nc_err_set_app_tag(e, "too-many-elements");
415 nc_err_set_path(e, ly_errpath());
416 break;
417 case LYVE_NOMIN:
418 e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
419 nc_err_set_app_tag(e, "too-few-elements");
420 nc_err_set_path(e, ly_errpath());
421 break;
422 case LYVE_NOMUST:
423 e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
424 if (ly_errapptag()[0]) {
425 nc_err_set_app_tag(e, ly_errapptag());
426 } else {
427 nc_err_set_app_tag(e, "must-violation");
428 }
429 break;
430 case LYVE_NOREQINS:
431 case LYVE_NOLEAFREF:
432 e = nc_err(NC_ERR_DATA_MISSING);
433 nc_err_set_app_tag(e, "instance-required");
434 nc_err_set_path(e, ly_errpath());
435 break;
436 case LYVE_NOMANDCHOICE:
437 e = nc_err(NC_ERR_DATA_MISSING);
438 nc_err_set_app_tag(e, "missing-choice");
439 nc_err_set_path(e, ly_errpath());
440
441 str = ly_errmsg();
442 stri = strchr(str, '"');
443 stri++;
444 strj = strchr(stri, '"');
445 elem = nc_err_libyang_other_elem("missing-choice", stri, strj - stri);
446 if (elem) {
447 nc_err_add_info_other(e, elem);
448 }
449 break;
Radek Krejci877e1822016-04-06 16:37:43 +0200450 case LYVE_INELEM:
451 str = ly_errpath();
452 if (!strcmp(str, "/")) {
453 e = nc_err(NC_ERR_OP_NOT_SUPPORTED, NC_ERR_TYPE_APP);
454 /* keep default message */
455 return e;
456 } else {
457 e = nc_err(NC_ERR_UNKNOWN_ELEM, NC_ERR_TYPE_PROT, ly_errpath());
458 }
459 break;
460 case LYVE_MISSELEM:
461 case LYVE_INORDER:
462 e = nc_err(NC_ERR_MISSING_ELEM, NC_ERR_TYPE_PROT, ly_errpath());
463 break;
464 case LYVE_INVAL:
465 e = nc_err(NC_ERR_BAD_ELEM, NC_ERR_TYPE_PROT, ly_errpath());
466 break;
467 case LYVE_INATTR:
468 case LYVE_MISSATTR:
Radek Krejci537fb522016-04-07 16:36:25 +0200469 case LYVE_INVALATTR:
Radek Krejci877e1822016-04-06 16:37:43 +0200470 str = ly_errmsg();
471 stri = strchr(str, '"');
472 stri++;
473 strj = strchr(stri, '"');
474 strj--;
475 attr = strndup(stri, strj - stri);
Radek Krejci537fb522016-04-07 16:36:25 +0200476 if (ly_vecode == LYVE_INATTR) {
477 e = nc_err(NC_ERR_UNKNOWN_ATTR, NC_ERR_TYPE_PROT, attr, ly_errpath());
478 } else if (ly_vecode == LYVE_MISSATTR) {
479 e = nc_err(NC_ERR_MISSING_ATTR, NC_ERR_TYPE_PROT, attr, ly_errpath());
480 } else { /* LYVE_INVALATTR */
481 e = nc_err(NC_ERR_BAD_ATTR, NC_ERR_TYPE_PROT, attr, ly_errpath());
482 }
Radek Krejci877e1822016-04-06 16:37:43 +0200483 free(attr);
484 break;
Michal Vaskoa08e5c02016-04-12 15:12:04 +0200485 case LYVE_NOCONSTR:
486 case LYVE_NOWHEN:
Radek Krejci877e1822016-04-06 16:37:43 +0200487 e = nc_err(NC_ERR_INVALID_VALUE, NC_ERR_TYPE_PROT);
Michal Vaskoa08e5c02016-04-12 15:12:04 +0200488 /* LYVE_NOCONSTR (length, range, pattern) can have a specific error-app-tag */
489 if (ly_errapptag()[0]) {
490 nc_err_set_app_tag(e, ly_errapptag());
491 }
Radek Krejci877e1822016-04-06 16:37:43 +0200492 break;
493 default:
494 e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
495 break;
496 }
497 } else {
498 /* non-validation (internal) error */
499 e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
500 }
501 nc_err_set_msg(e, ly_errmsg(), "en");
502 return e;
503}
504
Michal Vasko8f3198f2016-05-04 10:45:28 +0200505API NC_ERR_TYPE
506nc_err_get_type(struct nc_server_error *err)
507{
508 if (!err) {
509 ERRARG("err");
510 return 0;
511 }
512
513 return err->type;
514}
515
516API NC_ERR
517nc_err_get_tag(struct nc_server_error *err)
518{
519 if (!err) {
520 ERRARG("err");
521 return 0;
522 }
523
524 return err->tag;
525}
526
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100527API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100528nc_err_set_app_tag(struct nc_server_error *err, const char *error_app_tag)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100529{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200530 if (!err) {
531 ERRARG("err");
532 return -1;
533 } else if (!error_app_tag) {
534 ERRARG("error_app_tag");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100535 return -1;
536 }
537
538 if (err->apptag) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100539 lydict_remove(server_opts.ctx, err->apptag);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100540 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100541 err->apptag = lydict_insert(server_opts.ctx, error_app_tag, 0);
Michal Vasko11d142a2016-01-19 15:58:24 +0100542
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100543 return 0;
544}
545
Michal Vasko8f3198f2016-05-04 10:45:28 +0200546API const char *
547nc_err_get_app_tag(struct nc_server_error *err)
548{
549 if (!err) {
550 ERRARG("err");
551 return NULL;
552 }
553
554 return err->apptag;
555}
556
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100557API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100558nc_err_set_path(struct nc_server_error *err, const char *error_path)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100559{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200560 if (!err) {
561 ERRARG("err");
562 return -1;
563 } else if (!error_path) {
564 ERRARG("error_path");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100565 return -1;
566 }
567
568 if (err->path) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100569 lydict_remove(server_opts.ctx, err->path);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100570 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100571 err->path = lydict_insert(server_opts.ctx, error_path, 0);
Michal Vasko11d142a2016-01-19 15:58:24 +0100572
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100573 return 0;
574}
575
Michal Vasko8f3198f2016-05-04 10:45:28 +0200576API const char *
577nc_err_get_path(struct nc_server_error *err)
578{
579 if (!err) {
580 ERRARG("err");
581 return 0;
582 }
583
584 return err->path;
585}
586
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100587API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100588nc_err_set_msg(struct nc_server_error *err, const char *error_message, const char *lang)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100589{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200590 if (!err) {
591 ERRARG("err");
592 return -1;
593 } else if (!error_message) {
594 ERRARG("error_message");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100595 return -1;
596 }
597
598 if (err->message) {
Michal Vasko092ea742016-04-12 15:08:59 +0200599 lydict_remove(server_opts.ctx, err->message);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100600 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100601 err->message = lydict_insert(server_opts.ctx, error_message, 0);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100602
603 if (err->message_lang) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100604 lydict_remove(server_opts.ctx, err->message_lang);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100605 }
606 if (lang) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100607 err->message_lang = lydict_insert(server_opts.ctx, lang, 0);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100608 } else {
609 lang = NULL;
610 }
Michal Vasko11d142a2016-01-19 15:58:24 +0100611
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100612 return 0;
613}
614
Michal Vasko8f3198f2016-05-04 10:45:28 +0200615API const char *
616nc_err_get_msg(struct nc_server_error *err)
617{
618 if (!err) {
619 ERRARG("err");
620 return 0;
621 }
622
623 return err->message;
624}
625
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100626API int
627nc_err_set_sid(struct nc_server_error *err, uint32_t session_id)
628{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200629 if (!err) {
630 ERRARG("err");
631 return -1;
632 } else if (!session_id) {
633 ERRARG("session_id");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100634 return -1;
635 }
636
637 err->sid = session_id;
638 return 0;
639}
640
641API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100642nc_err_add_bad_attr(struct nc_server_error *err, const char *attr_name)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100643{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200644 if (!err) {
645 ERRARG("err");
646 return -1;
647 } else if (!attr_name) {
648 ERRARG("attr_name");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100649 return -1;
650 }
651
652 ++err->attr_count;
Michal Vasko4eb3c312016-03-01 14:09:37 +0100653 err->attr = nc_realloc(err->attr, err->attr_count * sizeof *err->attr);
654 if (!err->attr) {
655 ERRMEM;
656 return -1;
657 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100658 err->attr[err->attr_count - 1] = lydict_insert(server_opts.ctx, attr_name, 0);
Michal Vasko11d142a2016-01-19 15:58:24 +0100659
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100660 return 0;
661}
662
663API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100664nc_err_add_bad_elem(struct nc_server_error *err, const char *elem_name)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100665{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200666 if (!err) {
667 ERRARG("err");
668 return -1;
669 } else if (!elem_name) {
670 ERRARG("elem_name");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100671 return -1;
672 }
673
674 ++err->elem_count;
Michal Vasko4eb3c312016-03-01 14:09:37 +0100675 err->elem = nc_realloc(err->elem, err->elem_count * sizeof *err->elem);
676 if (!err->elem) {
677 ERRMEM;
678 return -1;
679 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100680 err->elem[err->elem_count - 1] = lydict_insert(server_opts.ctx, elem_name, 0);
Michal Vasko11d142a2016-01-19 15:58:24 +0100681
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100682 return 0;
683}
684
685API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100686nc_err_add_bad_ns(struct nc_server_error *err, const char *ns_name)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100687{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200688 if (!err) {
689 ERRARG("err");
690 return -1;
691 } else if (!ns_name) {
692 ERRARG("ns_name");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100693 return -1;
694 }
695
696 ++err->ns_count;
Michal Vasko4eb3c312016-03-01 14:09:37 +0100697 err->ns = nc_realloc(err->ns, err->ns_count * sizeof *err->ns);
698 if (!err->ns) {
699 ERRMEM;
700 return -1;
701 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100702 err->ns[err->ns_count - 1] = lydict_insert(server_opts.ctx, ns_name, 0);
Michal Vasko11d142a2016-01-19 15:58:24 +0100703
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100704 return 0;
705}
706
707API int
708nc_err_add_info_other(struct nc_server_error *err, struct lyxml_elem *other)
709{
Michal Vasko45e53ae2016-04-07 11:46:03 +0200710 if (!err) {
711 ERRARG("err");
712 return -1;
713 } else if (!other) {
714 ERRARG("other");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100715 return -1;
716 }
717
718 ++err->other_count;
Michal Vasko4eb3c312016-03-01 14:09:37 +0100719 err->other = nc_realloc(err->other, err->other_count * sizeof *err->other);
720 if (!err->other) {
721 ERRMEM;
722 return -1;
723 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100724 err->other[err->other_count - 1] = other;
725 return 0;
726}
727
728void
Michal Vaskoca4a2422016-02-02 12:17:14 +0100729nc_server_rpc_free(struct nc_server_rpc *rpc, struct ly_ctx *ctx)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100730{
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100731 if (!rpc) {
732 return;
733 }
734
Michal Vaskoca4a2422016-02-02 12:17:14 +0100735 lyxml_free(ctx, rpc->root);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100736 lyd_free(rpc->tree);
Michal Vasko11d142a2016-01-19 15:58:24 +0100737
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100738 free(rpc);
739}
740
741API void
742nc_server_reply_free(struct nc_server_reply *reply)
743{
744 uint32_t i;
745 struct nc_server_reply_data *data_rpl;
746 struct nc_server_reply_error *error_rpl;
747
748 if (!reply) {
749 return;
750 }
751
752 switch (reply->type) {
753 case NC_RPL_DATA:
754 data_rpl = (struct nc_server_reply_data *)reply;
755 if (data_rpl->free) {
756 lyd_free_withsiblings(data_rpl->data);
757 }
758 break;
759 case NC_RPL_OK:
760 /* nothing to free */
761 break;
762 case NC_RPL_ERROR:
763 error_rpl = (struct nc_server_reply_error *)reply;
764 for (i = 0; i < error_rpl->count; ++i) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100765 nc_err_free(error_rpl->err[i]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100766 }
767 free(error_rpl->err);
768 break;
769 default:
770 break;
771 }
772 free(reply);
773}
774
775API void
Michal Vasko1a38c862016-01-15 15:50:07 +0100776nc_err_free(struct nc_server_error *err)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100777{
778 uint32_t i;
779
780 if (!err) {
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100781 return;
782 }
783
Michal Vasko1a38c862016-01-15 15:50:07 +0100784 lydict_remove(server_opts.ctx, err->apptag);
785 lydict_remove(server_opts.ctx, err->path);
786 lydict_remove(server_opts.ctx, err->message);
787 lydict_remove(server_opts.ctx, err->message_lang);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100788 for (i = 0; i < err->attr_count; ++i) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100789 lydict_remove(server_opts.ctx, err->attr[i]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100790 }
791 free(err->attr);
792 for (i = 0; i < err->elem_count; ++i) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100793 lydict_remove(server_opts.ctx, err->elem[i]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100794 }
795 free(err->elem);
796 for (i = 0; i < err->ns_count; ++i) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100797 lydict_remove(server_opts.ctx, err->ns[i]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100798 }
799 free(err->ns);
800 for (i = 0; i < err->other_count; ++i) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100801 lyxml_free(server_opts.ctx, err->other[i]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100802 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100803 free(err->other);
804 free(err);
805}