1 /*
2 *
3 ***** BEGIN LICENSE BLOCK *****
4
5 Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
6 Copyright (C) 2017-2019 Olof Hagsand
7 Copyright (C) 2020 Olof Hagsand and Rubicon Communications, LLC(Netgate)
8
9 This file is part of CLIXON.
10
11 Licensed under the Apache License, Version 2.0 (the "License");
12 you may not use this file except in compliance with the License.
13 You may obtain a copy of the License at
14
15 http://www.apache.org/licenses/LICENSE-2.0
16
17 Unless required by applicable law or agreed to in writing, software
18 distributed under the License is distributed on an "AS IS" BASIS,
19 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 See the License for the specific language governing permissions and
21 limitations under the License.
22
23 Alternatively, the contents of this file may be used under the terms of
24 the GNU General Public License Version 3 or later (the "GPL"),
25 in which case the provisions of the GPL are applicable instead
26 of those above. If you wish to allow use of your version of this file only
27 under the terms of the GPL, and not to allow others to
28 use your version of this file under the terms of Apache License version 2, indicate
29 your decision by deleting the provisions above and replace them with the
30 notice and other provisions required by the GPL. If you do not delete
31 the provisions above, a recipient may use your version of this file under
32 the terms of any one of the Apache License version 2 or the GPL.
33
34 ***** END LICENSE BLOCK *****
35
36 *
37 * Access functions for clixon data.
38 * Free-typed values for runtime getting and setting.
39 * Accessed with clicon_data(h).
40 * @see clixon_option.[ch] for clixon options
41 */
42 #ifdef HAVE_CONFIG_H
43 #include "clixon_config.h" /* generated by config & autoconf */
44 #endif
45
46 #include <stdio.h>
47 #include <string.h>
48 #include <fcntl.h>
49 #include <unistd.h>
50 #include <errno.h>
51 #include <stdlib.h>
52 #include <stdint.h>
53 #include <syslog.h>
54 #include <assert.h>
55 #include <sys/types.h>
56 #include <sys/stat.h>
57 #include <sys/param.h>
58 #include <sys/socket.h>
59
60 /* cligen */
61 #include <cligen/cligen.h>
62
63 /* clicon */
64 #include "clixon_err.h"
65 #include "clixon_string.h"
66 #include "clixon_queue.h"
67 #include "clixon_hash.h"
68 #include "clixon_handle.h"
69 #include "clixon_log.h"
70 #include "clixon_yang.h"
71 #include "clixon_xml.h"
72 #include "clixon_xml_sort.h"
73 #include "clixon_yang_module.h"
74 #include "clixon_options.h"
75 #include "clixon_yang_module.h"
76 #include "clixon_plugin.h"
77 #include "clixon_xpath_ctx.h"
78 #include "clixon_xpath.h"
79 #include "clixon_data.h"
80
81 /*! Get generic clixon data on the form <name>=<val> where <val> is string
82 * @param[in] h Clicon handle
83 * @param[in] name Data name
84 * @param[out] val Data value as string
85 * @retval 0 OK
86 * @retval -1 Not found (or error)
87 * @see clicon_option_str
88 */
89 int
clicon_data_get(clicon_handle h,const char * name,char ** val)90 clicon_data_get(clicon_handle h,
91 const char *name,
92 char **val)
93 {
94 clicon_hash_t *cdat = clicon_data(h);
95
96 if (clicon_hash_lookup(cdat, (char*)name) == NULL)
97 return -1;
98 if (val)
99 *val = clicon_hash_value(cdat, (char*)name, NULL);
100 return 0;
101 }
102
103 /*! Set generic clixon data on the form <name>=<val> where <val> is string
104 * @param[in] h Clicon handle
105 * @param[in] name Data name
106 * @param[in] val Data value as null-terminated string
107 * @retval 0 OK
108 * @retval -1 Error
109 * @see clicon_option_str_set
110 */
111 int
clicon_data_set(clicon_handle h,const char * name,char * val)112 clicon_data_set(clicon_handle h,
113 const char *name,
114 char *val)
115 {
116 clicon_hash_t *cdat = clicon_data(h);
117
118 return clicon_hash_add(cdat, (char*)name, val, strlen(val)+1)==NULL?-1:0;
119 }
120
121 /*! Delete generic clixon data
122 * @param[in] h Clicon handle
123 * @param[in] name Data name
124 * @retval 0 OK
125 * @retval -1 Error
126 * @see clicon_option_del
127 */
128 int
clicon_data_del(clicon_handle h,const char * name)129 clicon_data_del(clicon_handle h,
130 const char *name)
131 {
132 clicon_hash_t *cdat = clicon_data(h);
133
134 return clicon_hash_del(cdat, (char*)name);
135 }
136
137 /*! Get generic cligen varaibel vector (cvv) on the form <name>=<val> where <val> is cvv
138 *
139 * @param[in] h Clicon handle
140 * @param[in] name Data name
141 * @retval cvv Data value as cvv
142 * @retval NULL Not found (or error)
143 * @code
144 * cvec *cvv = NULL;
145 * if (clicon_data_cvec_get(h, "mycvv", &cvv) < 0)
146 * err;
147 * @endcode
148 */
149 cvec *
clicon_data_cvec_get(clicon_handle h,const char * name)150 clicon_data_cvec_get(clicon_handle h,
151 const char *name)
152 {
153 clicon_hash_t *cdat = clicon_data(h);
154 size_t len = 0;
155 void *p;
156
157 if ((p = clicon_hash_value(cdat, (char*)name, &len)) != NULL)
158 return *(cvec **)p;
159 return NULL;
160 }
161
162 /*! Set generic cligen varaibel vector (cvv) on the form <name>=<val> where <val> is cvv
163 * @param[in] h Clicon handle
164 * @param[in] name Name
165 * @param[in] cvv CLIgen variable vector (cvv) (malloced)
166 */
167 int
clicon_data_cvec_set(clicon_handle h,const char * name,cvec * cvv)168 clicon_data_cvec_set(clicon_handle h,
169 const char *name,
170 cvec *cvv)
171 {
172 clicon_hash_t *cdat = clicon_data(h);
173 cvec *cvv0;
174
175 /* It is the pointer to cvec that should be copied by hash,
176 so we send a ptr to the ptr to indicate what to copy.
177 */
178 if ((cvv0 = clicon_data_cvec_get(h, name)) != NULL)
179 cvec_free(cvv0);
180 if (clicon_hash_add(cdat, (char*)name, &cvv, sizeof(cvv)) == NULL)
181 return -1;
182 return 0;
183 }
184
185 /*! Delete generic cligen varaibel vector (cvv)
186 * @param[in] h Clicon handle
187 * @param[in] name Name
188 */
189 int
clicon_data_cvec_del(clicon_handle h,const char * name)190 clicon_data_cvec_del(clicon_handle h,
191 const char *name)
192 {
193 clicon_hash_t *cdat = clicon_data(h);
194 cvec *cvv0;
195
196 /* It is the pointer to cvec that should be copied by hash,
197 so we send a ptr to the ptr to indicate what to copy.
198 */
199 if ((cvv0 = clicon_data_cvec_get(h, name)) != NULL)
200 cvec_free(cvv0);
201 return clicon_hash_del(cdat, (char*)name);
202 }
203
204 /*!
205 * @param[in] h Clicon handle
206 * @retval yspec Yang spec
207 * @see clicon_config_yang for the configuration yang
208 */
209 yang_stmt *
clicon_dbspec_yang(clicon_handle h)210 clicon_dbspec_yang(clicon_handle h)
211 {
212 clicon_hash_t *cdat = clicon_data(h);
213 size_t len;
214 void *p;
215
216 if ((p = clicon_hash_value(cdat, "dbspec_yang", &len)) != NULL)
217 return *(yang_stmt **)p;
218 return NULL;
219 }
220
221 /*! Set yang specification for application specifications
222 * @param[in] h Clicon handle
223 * @param[in] yspec Yang spec (malloced pointer)
224 * @see clicon_config_yang_set for the configuration yang
225 */
226 int
clicon_dbspec_yang_set(clicon_handle h,yang_stmt * ys)227 clicon_dbspec_yang_set(clicon_handle h,
228 yang_stmt *ys)
229 {
230 clicon_hash_t *cdat = clicon_data(h);
231
232 /* It is the pointer to ys that should be copied by hash,
233 so we send a ptr to the ptr to indicate what to copy.
234 */
235 if (clicon_hash_add(cdat, "dbspec_yang", &ys, sizeof(ys)) == NULL)
236 return -1;
237 return 0;
238 }
239
240 /*! Get YANG specification for clixon config (separate from application yangs)
241 * @param[in] h Clicon handle
242 * @retval yspec Yang spec
243 * @see clicon_dbspec_yang for the application specs
244 */
245 yang_stmt *
clicon_config_yang(clicon_handle h)246 clicon_config_yang(clicon_handle h)
247 {
248 clicon_hash_t *cdat = clicon_data(h);
249 size_t len;
250 void *p;
251
252 if ((p = clicon_hash_value(cdat, "control_yang", &len)) != NULL)
253 return *(yang_stmt **)p;
254 return NULL;
255 }
256
257 /*! Set yang specification for configuration
258 * @param[in] h Clicon handle
259 * @param[in] yspec Yang spec (malloced pointer)
260 * @see clicon_dbspec_yang_set for the application specs
261 */
262 int
clicon_config_yang_set(clicon_handle h,yang_stmt * ys)263 clicon_config_yang_set(clicon_handle h,
264 yang_stmt *ys)
265 {
266 clicon_hash_t *cdat = clicon_data(h);
267
268 /* It is the pointer to ys that should be copied by hash,
269 so we send a ptr to the ptr to indicate what to copy.
270 */
271 if (clicon_hash_add(cdat, "control_yang", &ys, sizeof(ys)) == NULL)
272 return -1;
273 return 0;
274 }
275
276 /*! Get YANG specification for external NACM (separate from application yangs)
277 * @param[in] h Clicon handle
278 * @retval yspec Yang spec
279 * @see clicon_nacm_ext for external NACM XML
280 */
281 yang_stmt *
clicon_nacm_ext_yang(clicon_handle h)282 clicon_nacm_ext_yang(clicon_handle h)
283 {
284 clicon_hash_t *cdat = clicon_data(h);
285 size_t len;
286 void *p;
287
288 if ((p = clicon_hash_value(cdat, "nacm_ext_yang", &len)) != NULL)
289 return *(yang_stmt **)p;
290 return NULL;
291 }
292
293 /*! Set yang specification for external NACM
294 * @param[in] h Clicon handle
295 * @param[in] yspec Yang spec (malloced pointer)
296 * @see clicon_nacm_ext_set for external NACM XML
297 */
298 int
clicon_nacm_ext_yang_set(clicon_handle h,yang_stmt * ys)299 clicon_nacm_ext_yang_set(clicon_handle h,
300 yang_stmt *ys)
301 {
302 clicon_hash_t *cdat = clicon_data(h);
303
304 /* It is the pointer to ys that should be copied by hash,
305 so we send a ptr to the ptr to indicate what to copy.
306 */
307 if (clicon_hash_add(cdat, "nacm_ext_yang", &ys, sizeof(ys)) == NULL)
308 return -1;
309 return 0;
310 }
311
312 /*! Get Global "canonical" namespace context
313 * Canonical: use prefix and namespace specified in the yang modules.
314 * @param[in] h Clicon handle
315 * @retval nsctx Namespace context (malloced)
316 * @code
317 * cvec *nsctx;
318 * nsctx = clicon_nsctx_global_get(h);
319 * @endcode
320 */
321 cvec *
clicon_nsctx_global_get(clicon_handle h)322 clicon_nsctx_global_get(clicon_handle h)
323 {
324 clicon_hash_t *cdat = clicon_data(h);
325 size_t len;
326 void *p;
327
328 if ((p = clicon_hash_value(cdat, "nsctx_global", &len)) != NULL)
329 return *(cvec **)p;
330 return NULL;
331 }
332
333 /*! Set global "canonical" namespace context
334 * Canonical: use prefix and namespace specified in the yang modules.
335 * @param[in] h Clicon handle
336 * @param[in] nsctx Namespace context (malloced)
337 */
338 int
clicon_nsctx_global_set(clicon_handle h,cvec * nsctx)339 clicon_nsctx_global_set(clicon_handle h,
340 cvec *nsctx)
341 {
342 clicon_hash_t *cdat = clicon_data(h);
343
344 /* It is the pointer to cvec that should be copied by hash,
345 so we send a ptr to the ptr to indicate what to copy.
346 */
347 if (clicon_hash_add(cdat, "nsctx_global", &nsctx, sizeof(nsctx)) == NULL)
348 return -1;
349 return 0;
350 }
351
352 /*! Get NACM (rfc 8341) XML parse tree if external not in std xml config
353 * @param[in] h Clicon handle
354 * @retval xn XML NACM tree, or NULL
355 * @note only used if config option CLICON_NACM_MODE is external
356 * @see clicon_nacm_ext_set
357 */
358 cxobj *
clicon_nacm_ext(clicon_handle h)359 clicon_nacm_ext(clicon_handle h)
360 {
361 clicon_hash_t *cdat = clicon_data(h);
362 size_t len;
363 void *p;
364
365 if ((p = clicon_hash_value(cdat, "nacm_xml", &len)) != NULL)
366 return *(cxobj **)p;
367 return NULL;
368 }
369
370 /*! Set NACM (rfc 8341) external XML parse tree, free old if any
371 * @param[in] h Clicon handle
372 * @param[in] xn XML Nacm tree
373 * @note only used if config option CLICON_NACM_MODE is external
374 * @see clicon_nacm_ext
375 */
376 int
clicon_nacm_ext_set(clicon_handle h,cxobj * xn)377 clicon_nacm_ext_set(clicon_handle h,
378 cxobj *xn)
379 {
380 clicon_hash_t *cdat = clicon_data(h);
381 cxobj *xo;
382
383 if ((xo = clicon_nacm_ext(h)) != NULL)
384 xml_free(xo);
385 /* It is the pointer to xn that should be copied by hash,
386 so we send a ptr to the ptr to indicate what to copy.
387 */
388 if (clicon_hash_add(cdat, "nacm_xml", &xn, sizeof(xn)) == NULL)
389 return -1;
390 return 0;
391 }
392
393 /*! Get NACM (rfc 8341) XML parse tree cache
394 * @param[in] h Clicon handle
395 * @retval xn XML NACM tree, or NULL. Direct pointer, no copying
396 * @note Use with caution, only valid on a stack, direct pointer freed on function return
397 * @see from_client_msg
398 */
399 cxobj *
clicon_nacm_cache(clicon_handle h)400 clicon_nacm_cache(clicon_handle h)
401 {
402 clicon_hash_t *cdat = clicon_data(h);
403 size_t len;
404 void *p;
405
406 if ((p = clicon_hash_value(cdat, "nacm_cache", &len)) != NULL)
407 return *(cxobj **)p;
408 return NULL;
409 }
410
411 /*! Set NACM (rfc 8341) external XML parse tree cache
412 * @param[in] h Clicon handle
413 * @param[in] xn XML Nacm tree direct pointer, no copying
414 * @note Use with caution, only valid on a stack, direct pointer freed on function return
415 * @see from_client_msg
416 */
417 int
clicon_nacm_cache_set(clicon_handle h,cxobj * xn)418 clicon_nacm_cache_set(clicon_handle h,
419 cxobj *xn)
420 {
421 clicon_hash_t *cdat = clicon_data(h);
422
423 /* It is the pointer to xn that should be copied by hash,
424 so we send a ptr to the ptr to indicate what to copy.
425 */
426 if (clicon_hash_add(cdat, "nacm_cache", &xn, sizeof(xn)) == NULL)
427 return -1;
428 return 0;
429 }
430
431 /*! Get YANG specification for Clixon system options and features
432 * Must use hash functions directly since they are not strings.
433 * Example: features are typically accessed directly in the config tree.
434 */
435 cxobj *
clicon_conf_xml(clicon_handle h)436 clicon_conf_xml(clicon_handle h)
437 {
438 clicon_hash_t *cdat = clicon_data(h);
439 size_t len;
440 void *p;
441
442 if ((p = clicon_hash_value(cdat, "clixon_conf", &len)) != NULL)
443 return *(cxobj **)p;
444 return NULL;
445 }
446
447 /*! Set YANG specification for Clixon system options and features
448 * ys must be a malloced pointer
449 */
450 int
clicon_conf_xml_set(clicon_handle h,cxobj * x)451 clicon_conf_xml_set(clicon_handle h,
452 cxobj *x)
453 {
454 clicon_hash_t *cdat = clicon_data(h);
455
456 /* It is the pointer to x that should be copied by hash,
457 * so we send a ptr to the ptr to indicate what to copy.
458 */
459 if (clicon_hash_add(cdat, "clixon_conf", &x, sizeof(x)) == NULL)
460 return -1;
461 return 0;
462 }
463
464 /*! Get authorized user name
465 * @param[in] h Clicon handle
466 * @retval username
467 */
468 char *
clicon_username_get(clicon_handle h)469 clicon_username_get(clicon_handle h)
470 {
471 clicon_hash_t *cdat = clicon_data(h);
472
473 return (char*)clicon_hash_value(cdat, "username", NULL);
474 }
475
476 /*! Set authorized user name
477 * @param[in] h Clicon handle
478 * @param[in] username
479 * @note Just keep note of it, dont allocate it or so.
480 */
481 int
clicon_username_set(clicon_handle h,void * username)482 clicon_username_set(clicon_handle h,
483 void *username)
484 {
485 clicon_hash_t *cdat = clicon_data(h);
486
487 if (username == NULL)
488 return clicon_hash_del(cdat, "username");
489 return clicon_hash_add(cdat, "username", username, strlen(username)+1)==NULL?-1:0;
490 }
491
492 /*! Get backend daemon startup status
493 * @param[in] h Clicon handle
494 * @retval status Startup status
495 */
496 enum startup_status
clicon_startup_status_get(clicon_handle h)497 clicon_startup_status_get(clicon_handle h)
498 {
499 clicon_hash_t *cdat = clicon_data(h);
500 void *p;
501
502 if ((p = clicon_hash_value(cdat, "startup_status", NULL)) != NULL)
503 return *(enum startup_status *)p;
504 return STARTUP_ERR;
505 }
506
507 /*! Set backend daemon startup status
508 * @param[in] h Clicon handle
509 * @param[in] status Startup status
510 * @retval 0 OK
511 * @retval -1 Error (when setting value)
512 */
513 int
clicon_startup_status_set(clicon_handle h,enum startup_status status)514 clicon_startup_status_set(clicon_handle h,
515 enum startup_status status)
516 {
517 clicon_hash_t *cdat = clicon_data(h);
518 if (clicon_hash_add(cdat, "startup_status", &status, sizeof(status))==NULL)
519 return -1;
520 return 0;
521 }
522
523 /*! Get socket fd (ie backend server socket / restconf fcgx socket)
524 * @param[in] h Clicon handle
525 * @retval -1 No open socket
526 * @retval s Socket
527 */
528 int
clicon_socket_get(clicon_handle h)529 clicon_socket_get(clicon_handle h)
530 {
531 clicon_hash_t *cdat = clicon_data(h);
532 void *p;
533
534 if ((p = clicon_hash_value(cdat, "socket", NULL)) == NULL)
535 return -1;
536 return *(int*)p;
537 }
538
539 /*! Set socket fd (ie backend server socket / restconf fcgx socket)
540 * @param[in] h Clicon handle
541 * @param[in] s Open socket (or -1 to close)
542 * @retval 0 OK
543 * @retval -1 Error
544 */
545 int
clicon_socket_set(clicon_handle h,int s)546 clicon_socket_set(clicon_handle h,
547 int s)
548 {
549 clicon_hash_t *cdat = clicon_data(h);
550
551 if (s == -1)
552 return clicon_hash_del(cdat, "socket");
553 return clicon_hash_add(cdat, "socket", &s, sizeof(int))==NULL?-1:0;
554 }
555
556 /*! Get module state cache
557 * @param[in] h Clicon handle
558 * @param[in] brief 0: Full module state tree, 1: Brief tree (datastore)
559 * @retval xms Module state cache XML tree
560 * xms is on the form: <modules-state>...
561 */
562 cxobj *
clicon_modst_cache_get(clicon_handle h,int brief)563 clicon_modst_cache_get(clicon_handle h,
564 int brief)
565 {
566 clicon_hash_t *cdat = clicon_data(h);
567 void *p;
568
569 if ((p = clicon_hash_value(cdat, brief?"modst_brief":"modst_full", NULL)) != NULL)
570 return *(cxobj **)p;
571 return NULL;
572 }
573
574 /*! Set module state cache
575 * @param[in] h Clicon handle
576 * @param[in] brief 0: Full module state tree, 1: Brief tree (datastore)
577 * @param[in] xms Module state cache XML tree
578 * @retval 0 OK
579 * @retval -1 Error
580 */
581 int
clicon_modst_cache_set(clicon_handle h,int brief,cxobj * xms)582 clicon_modst_cache_set(clicon_handle h,
583 int brief,
584 cxobj *xms)
585 {
586 clicon_hash_t *cdat = clicon_data(h);
587 cxobj *x;
588
589 if ((x = clicon_modst_cache_get(h, brief)) != NULL)
590 xml_free(x);
591 if (xms == NULL)
592 goto ok;
593 assert(strcmp(xml_name(xms),"modules-state")==0);
594 if ((x = xml_dup(xms)) == NULL)
595 return -1;
596 if (clicon_hash_add(cdat, brief?"modst_brief":"modst_full", &x, sizeof(x))==NULL)
597 return -1;
598 ok:
599 return 0;
600 }
601
602 /*! Get yang module changelog
603 * @param[in] h Clicon handle
604 * @retval xch Module revision changelog XML tree
605 * @see draft-wang-netmod-module-revision-management-01
606 */
607 cxobj *
clicon_xml_changelog_get(clicon_handle h)608 clicon_xml_changelog_get(clicon_handle h)
609 {
610 clicon_hash_t *cdat = clicon_data(h);
611 void *p;
612
613 if ((p = clicon_hash_value(cdat, "xml-changelog", NULL)) != NULL)
614 return *(cxobj **)p;
615 return NULL;
616 }
617
618 /*! Set xml module changelog
619 * @param[in] h Clicon handle
620 * @param[in] s Module revision changelog XML tree
621 * @retval 0 OK
622 * @retval -1 Error
623 * @see draft-wang-netmod-module-revision-management-01
624 */
625 int
clicon_xml_changelog_set(clicon_handle h,cxobj * xchlog)626 clicon_xml_changelog_set(clicon_handle h,
627 cxobj *xchlog)
628 {
629 clicon_hash_t *cdat = clicon_data(h);
630
631 if (clicon_hash_add(cdat, "xml-changelog", &xchlog, sizeof(xchlog))==NULL)
632 return -1;
633 return 0;
634 }
635
636 /*! Get user clicon command-line options argv, argc (after --)
637 * @param[in] h Clicon handle
638 * @param[out] argc
639 * @param[out] argv
640 * @retval 0 OK
641 * @retval -1 Error
642 */
643 int
clicon_argv_get(clicon_handle h,int * argc,char *** argv)644 clicon_argv_get(clicon_handle h,
645 int *argc,
646 char ***argv)
647
648 {
649 clicon_hash_t *cdat = clicon_data(h);
650 void *p;
651
652 if (argc){
653 if ((p = clicon_hash_value(cdat, "argc", NULL)) == NULL)
654 return -1;
655 *argc = *(int*)p;
656 }
657 if (argv){
658 if ((p = clicon_hash_value(cdat, "argv", NULL)) == NULL)
659 return -1;
660 *argv = (char**)p;
661 }
662 return 0;
663 }
664
665 /*! Set clicon user command-line options argv, argc (after --)
666 * @param[in] h Clicon handle
667 * @param[in] prog argv[0] - the program name
668 * @param[in] argc Length of argv
669 * @param[in] argv Array of command-line options or NULL
670 * @retval 0 OK
671 * @retval -1 Error
672 * @note If argv=NULL deallocate allocated argv vector if exists.
673 */
674 int
clicon_argv_set(clicon_handle h,char * prgm,int argc,char ** argv)675 clicon_argv_set(clicon_handle h,
676 char *prgm,
677 int argc,
678 char **argv)
679 {
680 int retval = -1;
681 clicon_hash_t *cdat = clicon_data(h);
682 char **argvv = NULL;
683 size_t len;
684
685 /* add space for null-termination and argv[0] program name */
686 len = argc+2;
687 if ((argvv = calloc(len, sizeof(char*))) == NULL){
688 clicon_err(OE_UNIX, errno, "calloc");
689 goto done;
690 }
691 memcpy(argvv+1, argv, argc*sizeof(char*));
692 argvv[0] = prgm;
693 /* Note the value is the argv vector (which is copied) */
694 if (clicon_hash_add(cdat, "argv", argvv, len*sizeof(char*))==NULL)
695 goto done;
696 argc += 1;
697 if (clicon_hash_add(cdat, "argc", &argc, sizeof(argc))==NULL)
698 goto done;
699 retval = 0;
700 done:
701 if (argvv)
702 free(argvv);
703 return retval;
704 }
705
706 /*! Get xml database element including id, xml cache, empty on startup and dirty bit
707 * @param[in] h Clicon handle
708 * @param[in] db Name of database
709 * @retval de Database element
710 * @retval NULL None found
711 */
712 db_elmnt *
clicon_db_elmnt_get(clicon_handle h,const char * db)713 clicon_db_elmnt_get(clicon_handle h,
714 const char *db)
715 {
716 clicon_hash_t *cdat = clicon_db_elmnt(h);
717 void *p;
718
719 if ((p = clicon_hash_value(cdat, db, NULL)) != NULL)
720 return (db_elmnt *)p;
721 return NULL;
722 }
723
724 /*! Set xml database element including id, xml cache, empty on startup and dirty bit
725 * @param[in] h Clicon handle
726 * @param[in] db Name of database
727 * @param[in] de Database element
728 * @retval 0 OK
729 * @retval -1 Error
730 * @see xmldb_disconnect
731 */
732 int
clicon_db_elmnt_set(clicon_handle h,const char * db,db_elmnt * de)733 clicon_db_elmnt_set(clicon_handle h,
734 const char *db,
735 db_elmnt *de)
736 {
737 clicon_hash_t *cdat = clicon_db_elmnt(h);
738
739 if (clicon_hash_add(cdat, db, de, sizeof(*de))==NULL)
740 return -1;
741 return 0;
742 }
743
744 /*! Get session id
745 * @param[in] h Clicon handle
746 * @param[out] sid Session identifier
747 * @retval 0 OK
748 * @retval -1 Session id not set
749 * Session-ids survive TCP sessions that are created for each message sent to the backend.
750 * The backend assigns session-id for clients: backend assigns, clients get it from backend.
751 */
752 int
clicon_session_id_get(clicon_handle h,uint32_t * id)753 clicon_session_id_get(clicon_handle h,
754 uint32_t *id)
755 {
756 clicon_hash_t *cdat = clicon_data(h);
757 void *p;
758
759 if ((p = clicon_hash_value(cdat, "session-id", NULL)) == NULL)
760 return -1;
761 *id = *(uint32_t*)p;
762 return 0;
763 }
764
765 /*! Set session id
766 * @param[in] h Clicon handle
767 * @param[in] id Session id
768 * @retval 0 OK
769 * @retval -1 Error
770 * Session-ids survive TCP sessions that are created for each message sent to the backend.
771 */
772 int
clicon_session_id_set(clicon_handle h,uint32_t id)773 clicon_session_id_set(clicon_handle h,
774 uint32_t id)
775 {
776 clicon_hash_t *cdat = clicon_data(h);
777
778 clicon_hash_add(cdat, "session-id", &id, sizeof(uint32_t));
779 return 0;
780 }
781
782 /*! Get quit-after-upgrade flag
783 * @param[in] h Clicon handle
784 * @retval 1 Flag set: quit startup directly after upgrade
785 * @retval 0 Flag not set
786 * If set, quit startup directly after upgrade
787 */
788 int
clicon_quit_upgrade_get(clicon_handle h)789 clicon_quit_upgrade_get(clicon_handle h)
790 {
791 clicon_hash_t *cdat = clicon_data(h);
792 void *p;
793
794 if ((p = clicon_hash_value(cdat, "quit-after-upgrade", NULL)) == NULL)
795 return 0;
796 return *(int*)p;
797 }
798
799 /*! Set quit-after-upgrade flag
800 * @param[in] h Clicon handle
801 * @param[in] val Set or reset flag
802 * @retval 0 OK
803 * @retval -1 Error
804 * If set, quit startup directly after upgrade
805 */
806 int
clicon_quit_upgrade_set(clicon_handle h,int val)807 clicon_quit_upgrade_set(clicon_handle h,
808 int val)
809 {
810 clicon_hash_t *cdat = clicon_data(h);
811
812 clicon_hash_add(cdat, "quit-after-upgrade", &val, sizeof(int));
813 return 0;
814 }
815