blob: b549a02f51e1f2afeddbe5e7112a49d12b6e77a6 [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
47 if (!data) {
48 ERRARG;
49 return NULL;
50 }
51
52 ret = malloc(sizeof *ret);
53 if (!ret) {
54 ERRMEM;
55 return NULL;
56 }
57
58 ret->type = NC_RPL_DATA;
59 if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
60 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 Vasko7bcb48e2016-01-15 10:28:54 +010078 ERRARG;
79 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
105 if (!reply || (reply->type != NC_RPL_ERROR) || !err) {
106 ERRARG;
107 return -1;
108 }
109
110 err_rpl = (struct nc_server_reply_error *)reply;
111 ++err_rpl->count;
Michal Vasko4eb3c312016-03-01 14:09:37 +0100112 err_rpl->err = nc_realloc(err_rpl->err, err_rpl->count * sizeof *err_rpl->err);
113 if (!err_rpl->err) {
114 ERRMEM;
115 return -1;
116 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100117 err_rpl->err[err_rpl->count - 1] = err;
118 return 0;
119}
120
121API struct nc_server_error *
Michal Vasko1a38c862016-01-15 15:50:07 +0100122nc_err(NC_ERR tag, ...)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100123{
124 va_list ap;
125 struct nc_server_error *ret;
126 NC_ERR_TYPE type;
127 const char *arg1, *arg2;
128 uint32_t sid;
129
Michal Vasko1a38c862016-01-15 15:50:07 +0100130 if (!tag) {
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100131 ERRARG;
132 return NULL;
133 }
134
135 ret = calloc(1, sizeof *ret);
136 if (!ret) {
137 ERRMEM;
138 return NULL;
139 }
140
141 va_start(ap, tag);
142
143 switch (tag) {
144 case NC_ERR_IN_USE:
145 case NC_ERR_INVALID_VALUE:
146 case NC_ERR_ACCESS_DENIED:
147 case NC_ERR_ROLLBACK_FAILED:
148 case NC_ERR_OP_NOT_SUPPORTED:
149 type = va_arg(ap, NC_ERR_TYPE);
150 if ((type != NC_ERR_TYPE_PROT) && (type == NC_ERR_TYPE_APP)) {
151 goto fail;
152 }
153 break;
154
155 case NC_ERR_TOO_BIG:
156 case NC_ERR_RES_DENIED:
157 type = va_arg(ap, NC_ERR_TYPE);
158 /* nothing to check */
159 break;
160
161 case NC_ERR_MISSING_ATTR:
162 case NC_ERR_BAD_ATTR:
163 case NC_ERR_UNKNOWN_ATTR:
164 type = va_arg(ap, NC_ERR_TYPE);
165 arg1 = va_arg(ap, const char *);
166 arg2 = va_arg(ap, const char *);
167
168 if (type == NC_ERR_TYPE_TRAN) {
169 goto fail;
170 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100171 nc_err_add_bad_attr(ret, arg1);
172 nc_err_add_bad_elem(ret, arg2);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100173 break;
174
175 case NC_ERR_MISSING_ELEM:
176 case NC_ERR_BAD_ELEM:
177 case NC_ERR_UNKNOWN_ELEM:
178 type = va_arg(ap, NC_ERR_TYPE);
179 arg1 = va_arg(ap, const char *);
180
181 if ((type != NC_ERR_TYPE_PROT) && (type != NC_ERR_TYPE_APP)) {
182 goto fail;
183 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100184 nc_err_add_bad_elem(ret, arg1);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100185 break;
186
187 case NC_ERR_UNKNOWN_NS:
188 type = va_arg(ap, NC_ERR_TYPE);
189 arg1 = va_arg(ap, const char *);
190 arg2 = va_arg(ap, const char *);
191
192 if ((type != NC_ERR_TYPE_PROT) && (type != NC_ERR_TYPE_APP)) {
193 goto fail;
194 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100195 nc_err_add_bad_elem(ret, arg1);
196 nc_err_add_bad_ns(ret, arg2);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100197 break;
198
199 case NC_ERR_LOCK_DENIED:
200 sid = va_arg(ap, uint32_t);
201
202 type = NC_ERR_TYPE_PROT;
203 nc_err_set_sid(ret, sid);
204 break;
205
206 case NC_ERR_DATA_EXISTS:
207 case NC_ERR_DATA_MISSING:
208 type = NC_ERR_TYPE_APP;
209 break;
210
211 case NC_ERR_OP_FAILED:
212 type = va_arg(ap, NC_ERR_TYPE);
213
214 if (type == NC_ERR_TYPE_TRAN) {
215 goto fail;
216 }
217 break;
218
219 case NC_ERR_MALFORMED_MSG:
220 type = NC_ERR_TYPE_RPC;
221 break;
222
223 default:
224 goto fail;
225 }
226
227 switch (tag) {
228 case NC_ERR_IN_USE:
Michal Vasko1a38c862016-01-15 15:50:07 +0100229 nc_err_set_msg(ret, "The request requires a resource that already is in use.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100230 break;
231 case NC_ERR_INVALID_VALUE:
Michal Vasko1a38c862016-01-15 15:50:07 +0100232 nc_err_set_msg(ret, "The request specifies an unacceptable value for one or more parameters.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100233 break;
234 case NC_ERR_TOO_BIG:
Michal Vasko1a38c862016-01-15 15:50:07 +0100235 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 +0100236 break;
237 case NC_ERR_MISSING_ATTR:
Michal Vasko1a38c862016-01-15 15:50:07 +0100238 nc_err_set_msg(ret, "An expected attribute is missing.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100239 break;
240 case NC_ERR_BAD_ATTR:
Michal Vasko1a38c862016-01-15 15:50:07 +0100241 nc_err_set_msg(ret, "An attribute value is not correct.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100242 break;
243 case NC_ERR_UNKNOWN_ATTR:
Michal Vasko1a38c862016-01-15 15:50:07 +0100244 nc_err_set_msg(ret, "An unexpected attribute is present.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100245 break;
246 case NC_ERR_MISSING_ELEM:
Michal Vasko1a38c862016-01-15 15:50:07 +0100247 nc_err_set_msg(ret, "An expected element is missing.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100248 break;
249 case NC_ERR_BAD_ELEM:
Michal Vasko1a38c862016-01-15 15:50:07 +0100250 nc_err_set_msg(ret, "An element value is not correct.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100251 break;
252 case NC_ERR_UNKNOWN_ELEM:
Michal Vasko1a38c862016-01-15 15:50:07 +0100253 nc_err_set_msg(ret, "An unexpected element is present.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100254 break;
255 case NC_ERR_UNKNOWN_NS:
Michal Vasko1a38c862016-01-15 15:50:07 +0100256 nc_err_set_msg(ret, "An unexpected namespace is present.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100257 break;
258 case NC_ERR_ACCESS_DENIED:
Michal Vasko1a38c862016-01-15 15:50:07 +0100259 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 +0100260 break;
261 case NC_ERR_LOCK_DENIED:
Michal Vasko1a38c862016-01-15 15:50:07 +0100262 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 +0100263 break;
264 case NC_ERR_RES_DENIED:
Michal Vasko1a38c862016-01-15 15:50:07 +0100265 nc_err_set_msg(ret, "Request could not be completed because of insufficient resources.", "en");
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100266 break;
267 case NC_ERR_ROLLBACK_FAILED:
Michal Vasko1a38c862016-01-15 15:50:07 +0100268 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 +0100269 break;
270 case NC_ERR_DATA_EXISTS:
Michal Vasko1a38c862016-01-15 15:50:07 +0100271 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 +0100272 break;
273 case NC_ERR_DATA_MISSING:
Michal Vasko1a38c862016-01-15 15:50:07 +0100274 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 +0100275 break;
276 case NC_ERR_OP_NOT_SUPPORTED:
Michal Vasko1a38c862016-01-15 15:50:07 +0100277 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 +0100278 break;
279 case NC_ERR_OP_FAILED:
Michal Vasko1a38c862016-01-15 15:50:07 +0100280 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 +0100281 break;
282 case NC_ERR_MALFORMED_MSG:
Michal Vasko1a38c862016-01-15 15:50:07 +0100283 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 +0100284 break;
285 default:
286 goto fail;
287 }
288
289 va_end(ap);
290
291 ret->type = type;
292 ret->tag = tag;
293 return ret;
294
295fail:
296 ERRARG;
Michal Vasko11d142a2016-01-19 15:58:24 +0100297 va_end(ap);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100298 free(ret);
299 return NULL;
300}
301
302API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100303nc_err_set_app_tag(struct nc_server_error *err, const char *error_app_tag)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100304{
Michal Vasko1a38c862016-01-15 15:50:07 +0100305 if (!err || !error_app_tag) {
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100306 ERRARG;
307 return -1;
308 }
309
310 if (err->apptag) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100311 lydict_remove(server_opts.ctx, err->apptag);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100312 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100313 err->apptag = lydict_insert(server_opts.ctx, error_app_tag, 0);
Michal Vasko11d142a2016-01-19 15:58:24 +0100314
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100315 return 0;
316}
317
318API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100319nc_err_set_path(struct nc_server_error *err, const char *error_path)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100320{
Michal Vasko1a38c862016-01-15 15:50:07 +0100321 if (!err || !error_path) {
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100322 ERRARG;
323 return -1;
324 }
325
326 if (err->path) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100327 lydict_remove(server_opts.ctx, err->path);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100328 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100329 err->path = lydict_insert(server_opts.ctx, error_path, 0);
Michal Vasko11d142a2016-01-19 15:58:24 +0100330
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100331 return 0;
332}
333
334API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100335nc_err_set_msg(struct nc_server_error *err, const char *error_message, const char *lang)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100336{
Michal Vasko1a38c862016-01-15 15:50:07 +0100337 if (!err || !error_message) {
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100338 ERRARG;
339 return -1;
340 }
341
342 if (err->message) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100343 lydict_remove(server_opts.ctx, err->apptag);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100344 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100345 err->message = lydict_insert(server_opts.ctx, error_message, 0);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100346
347 if (err->message_lang) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100348 lydict_remove(server_opts.ctx, err->message_lang);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100349 }
350 if (lang) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100351 err->message_lang = lydict_insert(server_opts.ctx, lang, 0);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100352 } else {
353 lang = NULL;
354 }
Michal Vasko11d142a2016-01-19 15:58:24 +0100355
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100356 return 0;
357}
358
359API int
360nc_err_set_sid(struct nc_server_error *err, uint32_t session_id)
361{
362 if (!err || !session_id) {
363 ERRARG;
364 return -1;
365 }
366
367 err->sid = session_id;
368 return 0;
369}
370
371API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100372nc_err_add_bad_attr(struct nc_server_error *err, const char *attr_name)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100373{
Michal Vasko1a38c862016-01-15 15:50:07 +0100374 if (!err || !attr_name) {
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100375 ERRARG;
376 return -1;
377 }
378
379 ++err->attr_count;
Michal Vasko4eb3c312016-03-01 14:09:37 +0100380 err->attr = nc_realloc(err->attr, err->attr_count * sizeof *err->attr);
381 if (!err->attr) {
382 ERRMEM;
383 return -1;
384 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100385 err->attr[err->attr_count - 1] = lydict_insert(server_opts.ctx, attr_name, 0);
Michal Vasko11d142a2016-01-19 15:58:24 +0100386
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100387 return 0;
388}
389
390API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100391nc_err_add_bad_elem(struct nc_server_error *err, const char *elem_name)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100392{
Michal Vasko1a38c862016-01-15 15:50:07 +0100393 if (!err || !elem_name) {
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100394 ERRARG;
395 return -1;
396 }
397
398 ++err->elem_count;
Michal Vasko4eb3c312016-03-01 14:09:37 +0100399 err->elem = nc_realloc(err->elem, err->elem_count * sizeof *err->elem);
400 if (!err->elem) {
401 ERRMEM;
402 return -1;
403 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100404 err->elem[err->elem_count - 1] = lydict_insert(server_opts.ctx, elem_name, 0);
Michal Vasko11d142a2016-01-19 15:58:24 +0100405
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100406 return 0;
407}
408
409API int
Michal Vasko1a38c862016-01-15 15:50:07 +0100410nc_err_add_bad_ns(struct nc_server_error *err, const char *ns_name)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100411{
Michal Vasko1a38c862016-01-15 15:50:07 +0100412 if (!err || !ns_name) {
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100413 ERRARG;
414 return -1;
415 }
416
417 ++err->ns_count;
Michal Vasko4eb3c312016-03-01 14:09:37 +0100418 err->ns = nc_realloc(err->ns, err->ns_count * sizeof *err->ns);
419 if (!err->ns) {
420 ERRMEM;
421 return -1;
422 }
Michal Vasko1a38c862016-01-15 15:50:07 +0100423 err->ns[err->ns_count - 1] = lydict_insert(server_opts.ctx, ns_name, 0);
Michal Vasko11d142a2016-01-19 15:58:24 +0100424
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100425 return 0;
426}
427
428API int
429nc_err_add_info_other(struct nc_server_error *err, struct lyxml_elem *other)
430{
431 if (!err || !other) {
432 ERRARG;
433 return -1;
434 }
435
436 ++err->other_count;
Michal Vasko4eb3c312016-03-01 14:09:37 +0100437 err->other = nc_realloc(err->other, err->other_count * sizeof *err->other);
438 if (!err->other) {
439 ERRMEM;
440 return -1;
441 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100442 err->other[err->other_count - 1] = other;
443 return 0;
444}
445
446void
Michal Vaskoca4a2422016-02-02 12:17:14 +0100447nc_server_rpc_free(struct nc_server_rpc *rpc, struct ly_ctx *ctx)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100448{
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100449 if (!rpc) {
450 return;
451 }
452
Michal Vaskoca4a2422016-02-02 12:17:14 +0100453 lyxml_free(ctx, rpc->root);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100454 lyd_free(rpc->tree);
Michal Vasko11d142a2016-01-19 15:58:24 +0100455
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100456 free(rpc);
457}
458
459API void
460nc_server_reply_free(struct nc_server_reply *reply)
461{
462 uint32_t i;
463 struct nc_server_reply_data *data_rpl;
464 struct nc_server_reply_error *error_rpl;
465
466 if (!reply) {
467 return;
468 }
469
470 switch (reply->type) {
471 case NC_RPL_DATA:
472 data_rpl = (struct nc_server_reply_data *)reply;
473 if (data_rpl->free) {
474 lyd_free_withsiblings(data_rpl->data);
475 }
476 break;
477 case NC_RPL_OK:
478 /* nothing to free */
479 break;
480 case NC_RPL_ERROR:
481 error_rpl = (struct nc_server_reply_error *)reply;
482 for (i = 0; i < error_rpl->count; ++i) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100483 nc_err_free(error_rpl->err[i]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100484 }
485 free(error_rpl->err);
486 break;
487 default:
488 break;
489 }
490 free(reply);
491}
492
493API void
Michal Vasko1a38c862016-01-15 15:50:07 +0100494nc_err_free(struct nc_server_error *err)
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100495{
496 uint32_t i;
497
498 if (!err) {
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100499 return;
500 }
501
Michal Vasko1a38c862016-01-15 15:50:07 +0100502 lydict_remove(server_opts.ctx, err->apptag);
503 lydict_remove(server_opts.ctx, err->path);
504 lydict_remove(server_opts.ctx, err->message);
505 lydict_remove(server_opts.ctx, err->message_lang);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100506 for (i = 0; i < err->attr_count; ++i) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100507 lydict_remove(server_opts.ctx, err->attr[i]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100508 }
509 free(err->attr);
510 for (i = 0; i < err->elem_count; ++i) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100511 lydict_remove(server_opts.ctx, err->elem[i]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100512 }
513 free(err->elem);
514 for (i = 0; i < err->ns_count; ++i) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100515 lydict_remove(server_opts.ctx, err->ns[i]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100516 }
517 free(err->ns);
518 for (i = 0; i < err->other_count; ++i) {
Michal Vasko1a38c862016-01-15 15:50:07 +0100519 lyxml_free(server_opts.ctx, err->other[i]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100520 }
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100521 free(err->other);
522 free(err);
523}