blob: d6f261fe1b66c80959f673d52070ea2de8df74f1 [file] [log] [blame]
Michal Vasko7bcb48e2016-01-15 10:28:54 +01001/**
2 * \file messages.c
3 * \author Radek Krejci <rkrejci@cesnet.cz>
4 * \brief libnetconf2 - 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
Radek Krejci36d2ee42017-10-13 13:55:59 +020015#include <assert.h>
Michal Vasko7bcb48e2016-01-15 10:28:54 +010016#include <ctype.h>
17#include <stdlib.h>
18#include <string.h>
19#include <stdarg.h>
20
21#include <libyang/libyang.h>
22
23#include "libnetconf.h"
Michal Vasko7bcb48e2016-01-15 10:28:54 +010024
25const char *rpcedit_dfltop2str[] = {NULL, "merge", "replace", "none"};
26const char *rpcedit_testopt2str[] = {NULL, "test-then-set", "set", "test-only"};
27const char *rpcedit_erropt2str[] = {NULL, "stop-on-error", "continue-on-error", "rollback-on-error"};
28
29API NC_RPC_TYPE
30nc_rpc_get_type(const struct nc_rpc *rpc)
31{
Michal Vasko7f1c78b2016-01-19 09:52:14 +010032 if (!rpc) {
Michal Vasko45e53ae2016-04-07 11:46:03 +020033 ERRARG("rpc");
Michal Vasko7f1c78b2016-01-19 09:52:14 +010034 return 0;
35 }
36
Michal Vasko7bcb48e2016-01-15 10:28:54 +010037 return rpc->type;
38}
39
40API struct nc_rpc *
Michal Vasko90e8e692016-07-13 12:27:57 +020041nc_rpc_act_generic(const struct lyd_node *data, NC_PARAMTYPE paramtype)
Michal Vasko7bcb48e2016-01-15 10:28:54 +010042{
Michal Vasko90e8e692016-07-13 12:27:57 +020043 struct nc_rpc_act_generic *rpc;
Michal Vasko7bcb48e2016-01-15 10:28:54 +010044
Michal Vasko90e8e692016-07-13 12:27:57 +020045 if (!data || data->next || (data->prev != data)) {
Michal Vasko45e53ae2016-04-07 11:46:03 +020046 ERRARG("data");
Michal Vasko7f1c78b2016-01-19 09:52:14 +010047 return NULL;
48 }
49
Michal Vasko7bcb48e2016-01-15 10:28:54 +010050 rpc = malloc(sizeof *rpc);
51 if (!rpc) {
52 ERRMEM;
53 return NULL;
54 }
55
Michal Vasko90e8e692016-07-13 12:27:57 +020056 rpc->type = NC_RPC_ACT_GENERIC;
Michal Vasko7bcb48e2016-01-15 10:28:54 +010057 rpc->has_data = 1;
58 if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
59 rpc->content.data = lyd_dup(data, 1);
60 } else {
61 rpc->content.data = (struct lyd_node *)data;
62 }
63 rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
64
65 return (struct nc_rpc *)rpc;
66}
67
68API struct nc_rpc *
Michal Vasko90e8e692016-07-13 12:27:57 +020069nc_rpc_act_generic_xml(const char *xml_str, NC_PARAMTYPE paramtype)
Michal Vasko7bcb48e2016-01-15 10:28:54 +010070{
Michal Vasko90e8e692016-07-13 12:27:57 +020071 struct nc_rpc_act_generic *rpc;
Michal Vasko7bcb48e2016-01-15 10:28:54 +010072
Michal Vasko7f1c78b2016-01-19 09:52:14 +010073 if (!xml_str) {
Michal Vasko45e53ae2016-04-07 11:46:03 +020074 ERRARG("xml_str");
Michal Vasko7f1c78b2016-01-19 09:52:14 +010075 return NULL;
76 }
77
Michal Vasko7bcb48e2016-01-15 10:28:54 +010078 rpc = malloc(sizeof *rpc);
79 if (!rpc) {
80 ERRMEM;
81 return NULL;
82 }
83
Michal Vasko90e8e692016-07-13 12:27:57 +020084 rpc->type = NC_RPC_ACT_GENERIC;
Michal Vasko7bcb48e2016-01-15 10:28:54 +010085 rpc->has_data = 0;
86 if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
87 rpc->content.xml_str = strdup(xml_str);
88 } else {
89 rpc->content.xml_str = (char *)xml_str;
90 }
91 rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
92
93 return (struct nc_rpc *)rpc;
94}
95
96API struct nc_rpc *
97nc_rpc_getconfig(NC_DATASTORE source, const char *filter, NC_WD_MODE wd_mode, NC_PARAMTYPE paramtype)
98{
99 struct nc_rpc_getconfig *rpc;
100
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100101 if (!source) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200102 ERRARG("source");
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100103 return NULL;
104 }
105
Michal Vaskof3c647b2016-03-08 12:17:33 +0100106 if (filter && filter[0] && (filter[0] != '<') && (filter[0] != '/') && !isalpha(filter[0])) {
Michal Vasko7793bc62016-09-16 11:58:41 +0200107 ERR("Filter is neither an XML subtree nor an XPath expression (invalid first char '%c').", filter[0]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100108 return NULL;
109 }
110
111 rpc = malloc(sizeof *rpc);
112 if (!rpc) {
113 ERRMEM;
114 return NULL;
115 }
116
117 rpc->type = NC_RPC_GETCONFIG;
118 rpc->source = source;
119 if (filter && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
120 rpc->filter = strdup(filter);
121 } else {
122 rpc->filter = (char *)filter;
123 }
124 rpc->wd_mode = wd_mode;
125 rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
126
127 return (struct nc_rpc *)rpc;
128}
129
130API struct nc_rpc *
131nc_rpc_edit(NC_DATASTORE target, NC_RPC_EDIT_DFLTOP default_op, NC_RPC_EDIT_TESTOPT test_opt,
132 NC_RPC_EDIT_ERROPT error_opt, const char *edit_content, NC_PARAMTYPE paramtype)
133{
134 struct nc_rpc_edit *rpc;
135
Michal Vasko45e53ae2016-04-07 11:46:03 +0200136 if (!target) {
137 ERRARG("target");
138 return NULL;
139 } else if (!edit_content) {
140 ERRARG("edit_content");
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100141 return NULL;
142 }
143
Michal Vasko7793bc62016-09-16 11:58:41 +0200144 if (edit_content[0] && (edit_content[0] != '<') && !isalpha(edit_content[0])) {
145 ERR("<edit-config> content is neither a URL nor an XML config (invalid first char '%c').", edit_content[0]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100146 return NULL;
147 }
148
149 rpc = malloc(sizeof *rpc);
150 if (!rpc) {
151 ERRMEM;
152 return NULL;
153 }
154
155 rpc->type = NC_RPC_EDIT;
156 rpc->target = target;
157 rpc->default_op = default_op;
158 rpc->test_opt = test_opt;
159 rpc->error_opt = error_opt;
160 if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
161 rpc->edit_cont = strdup(edit_content);
162 } else {
163 rpc->edit_cont = (char *)edit_content;
164 }
165 rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
166
167 return (struct nc_rpc *)rpc;
168}
169
170API struct nc_rpc *
171nc_rpc_copy(NC_DATASTORE target, const char *url_trg, NC_DATASTORE source, const char *url_or_config_src,
172 NC_WD_MODE wd_mode, NC_PARAMTYPE paramtype)
173{
174 struct nc_rpc_copy *rpc;
175
Michal Vasko45e53ae2016-04-07 11:46:03 +0200176 if (!target) {
177 ERRARG("target");
178 return NULL;
179 } else if (!source) {
180 ERRARG("source");
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100181 return NULL;
182 }
183
Michal Vasko7793bc62016-09-16 11:58:41 +0200184 if (url_or_config_src && url_or_config_src[0] && (url_or_config_src[0] != '<') && !isalpha(url_or_config_src[0])) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200185 ERR("<copy-config> source is neither a URL nor an XML config (invalid first char '%c').", url_or_config_src[0]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100186 return NULL;
187 }
188
189 rpc = malloc(sizeof *rpc);
190 if (!rpc) {
191 ERRMEM;
192 return NULL;
193 }
194
195 rpc->type = NC_RPC_COPY;
196 rpc->target = target;
197 if (url_trg && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
198 rpc->url_trg = strdup(url_trg);
199 } else {
200 rpc->url_trg = (char *)url_trg;
201 }
202 rpc->source = source;
203 if (url_or_config_src && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
204 rpc->url_config_src = strdup(url_or_config_src);
205 } else {
206 rpc->url_config_src = (char *)url_or_config_src;
207 }
208 rpc->wd_mode = wd_mode;
209 rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
210
211 return (struct nc_rpc *)rpc;
212}
213
214API struct nc_rpc *
215nc_rpc_delete(NC_DATASTORE target, const char *url, NC_PARAMTYPE paramtype)
216{
217 struct nc_rpc_delete *rpc;
218
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100219 if (!target) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200220 ERRARG("target");
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100221 return NULL;
222 }
223
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100224 rpc = malloc(sizeof *rpc);
225 if (!rpc) {
226 ERRMEM;
227 return NULL;
228 }
229
230 rpc->type = NC_RPC_DELETE;
231 rpc->target = target;
232 if (url && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
233 rpc->url = strdup(url);
234 } else {
235 rpc->url = (char *)url;
236 }
237 rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
238
239 return (struct nc_rpc *)rpc;
240}
241
242API struct nc_rpc *
243nc_rpc_lock(NC_DATASTORE target)
244{
245 struct nc_rpc_lock *rpc;
246
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100247 if (!target) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200248 ERRARG("target");
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100249 return NULL;
250 }
251
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100252 rpc = malloc(sizeof *rpc);
253 if (!rpc) {
254 ERRMEM;
255 return NULL;
256 }
257
258 rpc->type = NC_RPC_LOCK;
259 rpc->target = target;
260
261 return (struct nc_rpc *)rpc;
262}
263
264API struct nc_rpc *
265nc_rpc_unlock(NC_DATASTORE target)
266{
267 struct nc_rpc_lock *rpc;
268
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100269 if (!target) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200270 ERRARG("target");
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100271 return NULL;
272 }
273
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100274 rpc = malloc(sizeof *rpc);
275 if (!rpc) {
276 ERRMEM;
277 return NULL;
278 }
279
280 rpc->type = NC_RPC_UNLOCK;
281 rpc->target = target;
282
283 return (struct nc_rpc *)rpc;
284}
285
286API struct nc_rpc *
287nc_rpc_get(const char *filter, NC_WD_MODE wd_mode, NC_PARAMTYPE paramtype)
288{
289 struct nc_rpc_get *rpc;
290
Michal Vaskof3c647b2016-03-08 12:17:33 +0100291 if (filter && filter[0] && (filter[0] != '<') && (filter[0] != '/') && !isalpha(filter[0])) {
Michal Vasko7793bc62016-09-16 11:58:41 +0200292 ERR("Filter is neither an XML subtree nor an XPath expression (invalid first char '%c').", filter[0]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100293 return NULL;
294 }
295
296 rpc = malloc(sizeof *rpc);
297 if (!rpc) {
298 ERRMEM;
299 return NULL;
300 }
301
302 rpc->type = NC_RPC_GET;
303 if (filter && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
304 rpc->filter = strdup(filter);
305 } else {
306 rpc->filter = (char *)filter;
307 }
308 rpc->wd_mode = wd_mode;
309 rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
310
311 return (struct nc_rpc *)rpc;
312}
313
314API struct nc_rpc *
315nc_rpc_kill(uint32_t session_id)
316{
317 struct nc_rpc_kill *rpc;
318
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100319 if (!session_id) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200320 ERRARG("session_id");
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100321 return NULL;
322 }
323
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100324 rpc = malloc(sizeof *rpc);
325 if (!rpc) {
326 ERRMEM;
327 return NULL;
328 }
329
330 rpc->type = NC_RPC_KILL;
331 rpc->sid = session_id;
332
333 return (struct nc_rpc *)rpc;
334}
335
336API struct nc_rpc *
337nc_rpc_commit(int confirmed, uint32_t confirm_timeout, const char *persist, const char *persist_id,
338 NC_PARAMTYPE paramtype)
339{
340 struct nc_rpc_commit *rpc;
341
342 rpc = malloc(sizeof *rpc);
343 if (!rpc) {
344 ERRMEM;
345 return NULL;
346 }
347
348 rpc->type = NC_RPC_COMMIT;
349 rpc->confirmed = confirmed;
350 rpc->confirm_timeout = confirm_timeout;
351 if (persist && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
352 rpc->persist = strdup(persist);
353 } else {
354 rpc->persist = (char *)persist;
355 }
356 if (persist_id && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
357 rpc->persist_id = strdup(persist_id);
358 } else {
359 rpc->persist_id = (char *)persist_id;
360 }
361 rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
362
363 return (struct nc_rpc *)rpc;
364}
365
366API struct nc_rpc *
367nc_rpc_discard(void)
368{
369 struct nc_rpc *rpc;
370
371 rpc = malloc(sizeof *rpc);
372 if (!rpc) {
373 ERRMEM;
374 return NULL;
375 }
376
377 rpc->type = NC_RPC_DISCARD;
378
379 return rpc;
380}
381
382API struct nc_rpc *
383nc_rpc_cancel(const char *persist_id, NC_PARAMTYPE paramtype)
384{
385 struct nc_rpc_cancel *rpc;
386
387 rpc = malloc(sizeof *rpc);
388 if (!rpc) {
389 ERRMEM;
390 return NULL;
391 }
392
393 rpc->type = NC_RPC_CANCEL;
394 if (persist_id && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
395 rpc->persist_id = strdup(persist_id);
396 } else {
397 rpc->persist_id = (char *)persist_id;
398 }
399 rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
400
401 return (struct nc_rpc *)rpc;
402}
403
404API struct nc_rpc *
405nc_rpc_validate(NC_DATASTORE source, const char *url_or_config, NC_PARAMTYPE paramtype)
406{
407 struct nc_rpc_validate *rpc;
408
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100409 if (!source) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200410 ERRARG("source");
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100411 return NULL;
412 }
413
Michal Vasko7793bc62016-09-16 11:58:41 +0200414 if (url_or_config && url_or_config[0] && (url_or_config[0] != '<') && !isalpha(url_or_config[0])) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200415 ERR("<validate> source is neither a URL nor an XML config (invalid first char '%c').", url_or_config[0]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100416 return NULL;
417 }
418
419 rpc = malloc(sizeof *rpc);
420 if (!rpc) {
421 ERRMEM;
422 return NULL;
423 }
424
425 rpc->type = NC_RPC_VALIDATE;
426 rpc->source = source;
427 if (url_or_config && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
428 rpc->url_config_src = strdup(url_or_config);
429 } else {
430 rpc->url_config_src = (char *)url_or_config;
431 }
432 rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
433
434 return (struct nc_rpc *)rpc;
435}
436
437API struct nc_rpc *
438nc_rpc_getschema(const char *identifier, const char *version, const char *format, NC_PARAMTYPE paramtype)
439{
440 struct nc_rpc_getschema *rpc;
441
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100442 if (!identifier) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200443 ERRARG("identifier");
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100444 return NULL;
445 }
446
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100447 rpc = malloc(sizeof *rpc);
448 if (!rpc) {
449 ERRMEM;
450 return NULL;
451 }
452
453 rpc->type = NC_RPC_GETSCHEMA;
454 if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
455 rpc->identifier = strdup(identifier);
456 } else {
457 rpc->identifier = (char *)identifier;
458 }
459 if (version && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
460 rpc->version = strdup(version);
461 } else {
462 rpc->version = (char *)version;
463 }
464 if (format && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
465 rpc->format = strdup(format);
466 } else {
467 rpc->format = (char *)format;
468 }
469 rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
470
471 return (struct nc_rpc *)rpc;
472}
473
474API struct nc_rpc *
475nc_rpc_subscribe(const char *stream_name, const char *filter, const char *start_time, const char *stop_time,
476 NC_PARAMTYPE paramtype)
477{
478 struct nc_rpc_subscribe *rpc;
479
Michal Vaskof3c647b2016-03-08 12:17:33 +0100480 if (filter && filter[0] && (filter[0] != '<') && (filter[0] != '/') && !isalpha(filter[0])) {
Michal Vasko7793bc62016-09-16 11:58:41 +0200481 ERR("Filter is neither an XML subtree nor an XPath expression (invalid first char '%c').", filter[0]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100482 return NULL;
483 }
484
485 rpc = malloc(sizeof *rpc);
486 if (!rpc) {
487 ERRMEM;
488 return NULL;
489 }
490
491 rpc->type = NC_RPC_SUBSCRIBE;
492 if (stream_name && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
493 rpc->stream = strdup(stream_name);
494 } else {
495 rpc->stream = (char *)stream_name;
496 }
497 if (filter && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
498 rpc->filter = strdup(filter);
499 } else {
500 rpc->filter = (char *)filter;
501 }
502 if (start_time && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
503 rpc->start = strdup(start_time);
504 } else {
505 rpc->start = (char *)start_time;
506 }
507 if (stop_time && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
508 rpc->stop = strdup(stop_time);
509 } else {
510 rpc->stop = (char *)stop_time;
511 }
512 rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
513
514 return (struct nc_rpc *)rpc;
515}
516
Michal Vaskoc1171a42019-11-05 12:06:46 +0100517API struct nc_rpc *
518nc_rpc_getdata(const char *datastore, const char *filter, const char *config_filter, char **origin_filter,
519 int origin_filter_count, int negated_origin_filter, uint16_t max_depth, int with_origin,
520 NC_WD_MODE wd_mode, NC_PARAMTYPE paramtype)
521{
522 struct nc_rpc_getdata *rpc = NULL;
523 int i;
524
525 if (filter && filter[0] && (filter[0] != '<') && (filter[0] != '/') && !isalpha(filter[0])) {
526 ERR("Filter is neither an XML subtree nor an XPath expression (invalid first char '%c').", filter[0]);
527 return NULL;
528 } else if (!datastore) {
529 ERRARG("datastore");
530 return NULL;
531 }
532
533 rpc = calloc(1, sizeof *rpc);
534 if (!rpc) {
535 ERRMEM;
536 return NULL;
537 }
538 rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
539
540 rpc->type = NC_RPC_GETDATA;
541 if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
542 rpc->datastore = strdup(datastore);
543 } else {
544 rpc->datastore = (char *)datastore;
545 }
546 if (filter && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
547 rpc->filter = strdup(filter);
548 } else {
549 rpc->filter = (char *)filter;
550 }
551 if (config_filter && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
552 rpc->config_filter = strdup(config_filter);
553 } else {
554 rpc->config_filter = (char *)config_filter;
555 }
556 if (origin_filter && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
557 rpc->origin_filter = malloc(origin_filter_count * sizeof *rpc->origin_filter);
558 if (!rpc->origin_filter) {
559 ERRMEM;
560 goto error;
561 }
562 for (i = 0; i < origin_filter_count; ++i) {
563 rpc->origin_filter[i] = strdup(origin_filter[i]);
564 if (!rpc->origin_filter[i]) {
565 ERRMEM;
566 goto error;
567 }
568 ++rpc->origin_filter_count;
569 }
570 } else {
571 rpc->origin_filter = origin_filter;
572 rpc->origin_filter_count = origin_filter_count;
573 }
574 rpc->negated_origin_filter = negated_origin_filter;
575 rpc->max_depth = max_depth;
576 rpc->with_origin = with_origin;
577 rpc->wd_mode = wd_mode;
578
579 return (struct nc_rpc *)rpc;
580
581error:
582 nc_rpc_free((struct nc_rpc *)rpc);
583 return NULL;
584}
585
586API struct nc_rpc *
587nc_rpc_editdata(const char *datastore, NC_RPC_EDIT_DFLTOP default_op, const char *edit_content, NC_PARAMTYPE paramtype)
588{
589 struct nc_rpc_editdata *rpc;
590
591 if (!datastore) {
592 ERRARG("datastore");
593 return NULL;
594 } else if (!edit_content) {
595 ERRARG("edit_content");
596 return NULL;
597 }
598
599 if (edit_content[0] && (edit_content[0] != '<') && !isalpha(edit_content[0])) {
600 ERR("<edit-data> content is neither a URL nor an XML config (invalid first char '%c').", edit_content[0]);
601 return NULL;
602 }
603
604 rpc = malloc(sizeof *rpc);
605 if (!rpc) {
606 ERRMEM;
607 return NULL;
608 }
609
610 rpc->type = NC_RPC_EDITDATA;
611 if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
612 rpc->datastore = strdup(datastore);
613 } else {
614 rpc->datastore = (char *)datastore;
615 }
616 rpc->default_op = default_op;
617 if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
618 rpc->edit_cont = strdup(edit_content);
619 } else {
620 rpc->edit_cont = (char *)edit_content;
621 }
622 rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
623
624 return (struct nc_rpc *)rpc;
625}
626
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100627API void
628nc_rpc_free(struct nc_rpc *rpc)
629{
Michal Vasko90e8e692016-07-13 12:27:57 +0200630 struct nc_rpc_act_generic *rpc_generic;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100631 struct nc_rpc_getconfig *rpc_getconfig;
632 struct nc_rpc_edit *rpc_edit;
633 struct nc_rpc_copy *rpc_copy;
634 struct nc_rpc_delete *rpc_delete;
635 struct nc_rpc_get *rpc_get;
636 struct nc_rpc_commit *rpc_commit;
637 struct nc_rpc_cancel *rpc_cancel;
638 struct nc_rpc_validate *rpc_validate;
639 struct nc_rpc_getschema *rpc_getschema;
640 struct nc_rpc_subscribe *rpc_subscribe;
Michal Vaskoc1171a42019-11-05 12:06:46 +0100641 struct nc_rpc_getdata *rpc_getdata;
642 struct nc_rpc_editdata *rpc_editdata;
643 int i;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100644
645 if (!rpc) {
646 return;
647 }
648
649 switch (rpc->type) {
Michal Vasko90e8e692016-07-13 12:27:57 +0200650 case NC_RPC_ACT_GENERIC:
651 rpc_generic = (struct nc_rpc_act_generic *)rpc;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100652 if (rpc_generic->free) {
653 if (rpc_generic->has_data) {
654 lyd_free(rpc_generic->content.data);
655 } else {
656 free(rpc_generic->content.xml_str);
657 }
658 }
659 break;
660 case NC_RPC_GETCONFIG:
661 rpc_getconfig = (struct nc_rpc_getconfig *)rpc;
662 if (rpc_getconfig->free) {
663 free(rpc_getconfig->filter);
664 }
665 break;
666 case NC_RPC_EDIT:
667 rpc_edit = (struct nc_rpc_edit *)rpc;
668 if (rpc_edit->free) {
669 free(rpc_edit->edit_cont);
670 }
671 break;
672 case NC_RPC_COPY:
673 rpc_copy = (struct nc_rpc_copy *)rpc;
674 if (rpc_copy->free) {
675 free(rpc_copy->url_config_src);
David Sedlák35419a32018-10-07 23:23:33 +0200676 free(rpc_copy->url_trg);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100677 }
678 break;
679 case NC_RPC_DELETE:
680 rpc_delete = (struct nc_rpc_delete *)rpc;
681 if (rpc_delete->free) {
682 free(rpc_delete->url);
683 }
684 break;
685 case NC_RPC_GET:
686 rpc_get = (struct nc_rpc_get *)rpc;
687 if (rpc_get->free) {
688 free(rpc_get->filter);
689 }
690 break;
691 case NC_RPC_COMMIT:
692 rpc_commit = (struct nc_rpc_commit *)rpc;
693 if (rpc_commit->free) {
694 free(rpc_commit->persist);
695 free(rpc_commit->persist_id);
696 }
697 break;
698 case NC_RPC_CANCEL:
699 rpc_cancel = (struct nc_rpc_cancel *)rpc;
700 if (rpc_cancel->free) {
701 free(rpc_cancel->persist_id);
702 }
703 break;
704 case NC_RPC_VALIDATE:
705 rpc_validate = (struct nc_rpc_validate *)rpc;
706 if (rpc_validate->free) {
707 free(rpc_validate->url_config_src);
708 }
709 break;
710 case NC_RPC_GETSCHEMA:
711 rpc_getschema = (struct nc_rpc_getschema *)rpc;
712 if (rpc_getschema->free) {
713 free(rpc_getschema->identifier);
714 free(rpc_getschema->version);
715 free(rpc_getschema->format);
716 }
717 break;
718 case NC_RPC_SUBSCRIBE:
719 rpc_subscribe = (struct nc_rpc_subscribe *)rpc;
720 if (rpc_subscribe->free) {
721 free(rpc_subscribe->stream);
722 free(rpc_subscribe->filter);
723 free(rpc_subscribe->start);
724 free(rpc_subscribe->stop);
725 }
726 break;
Michal Vaskoc1171a42019-11-05 12:06:46 +0100727 case NC_RPC_GETDATA:
728 rpc_getdata = (struct nc_rpc_getdata *)rpc;
729 if (rpc_getdata->free) {
730 free(rpc_getdata->datastore);
731 free(rpc_getdata->filter);
732 free(rpc_getdata->config_filter);
733 for (i = 0; i < rpc_getdata->origin_filter_count; ++i) {
734 free(rpc_getdata->origin_filter[i]);
735 }
736 free(rpc_getdata->origin_filter);
737 }
738 break;
739 case NC_RPC_EDITDATA:
740 rpc_editdata = (struct nc_rpc_editdata *)rpc;
741 if (rpc_editdata->free) {
742 free(rpc_editdata->datastore);
743 free(rpc_editdata->edit_cont);
744 }
745 break;
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100746 default:
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100747 /* nothing special needed */
748 break;
749 }
750
751 free(rpc);
752}
753
754API void
Radek Krejci36d2ee42017-10-13 13:55:59 +0200755nc_client_err_clean(struct nc_err *err, struct ly_ctx *ctx)
756{
757 int i;
758
759 assert(ctx);
760
761 if (!err) {
762 return;
763 }
764
765 lydict_remove(ctx, err->type);
766 lydict_remove(ctx, err->tag);
767 lydict_remove(ctx, err->severity);
768 lydict_remove(ctx, err->apptag);
769 lydict_remove(ctx, err->path);
770 lydict_remove(ctx, err->message);
771 lydict_remove(ctx, err->message_lang);
772 lydict_remove(ctx, err->sid);
773 for (i = 0; i < err->attr_count; ++i) {
774 lydict_remove(ctx, err->attr[i]);
775 }
776 free(err->attr);
777 for (i = 0; i < err->elem_count; ++i) {
778 lydict_remove(ctx, err->elem[i]);
779 }
780 free(err->elem);
781 for (i = 0; i < err->ns_count; ++i) {
782 lydict_remove(ctx, err->ns[i]);
783 }
784 free(err->ns);
785 for (i = 0; i < err->other_count; ++i) {
786 lyxml_free(ctx, err->other[i]);
787 }
788 free(err->other);
789}
790
791API void
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100792nc_reply_free(struct nc_reply *reply)
793{
Michal Vasko1a38c862016-01-15 15:50:07 +0100794 struct nc_client_reply_error *error;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100795 struct nc_reply_data *data;
Radek Krejci36d2ee42017-10-13 13:55:59 +0200796 uint32_t i;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100797
798 if (!reply) {
799 return;
800 }
801
802 switch (reply->type) {
803 case NC_RPL_DATA:
804 data = (struct nc_reply_data *)reply;
805 lyd_free_withsiblings(data->data);
806 break;
807
808 case NC_RPL_OK:
809 /* nothing to free */
810 break;
811
812 case NC_RPL_ERROR:
Michal Vasko1a38c862016-01-15 15:50:07 +0100813 error = (struct nc_client_reply_error *)reply;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100814 for (i = 0; i < error->count; ++i) {
Radek Krejci36d2ee42017-10-13 13:55:59 +0200815 nc_client_err_clean(&error->err[i], error->ctx);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100816 }
817 free(error->err);
818 break;
819
820 case NC_RPL_NOTIF:
821 nc_notif_free((struct nc_notif *)reply);
Michal Vasko11d142a2016-01-19 15:58:24 +0100822 return;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100823 }
824
825 free(reply);
826}
Michal Vasko495c9462016-01-15 11:27:43 +0100827
828API void
829nc_notif_free(struct nc_notif *notif)
830{
831 if (!notif) {
832 return;
833 }
834
835 lydict_remove(notif->tree->schema->module->ctx, notif->datetime);
836 lyd_free(notif->tree);
837 free(notif);
838}