1 /*
2  * Copyright (C) 2018  NetDEF, Inc.
3  *                     Renato Westphal
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the Free
7  * Software Foundation; either version 2 of the License, or (at your option)
8  * any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; see the file COPYING; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 #ifndef _FRR_NORTHBOUND_H_
21 #define _FRR_NORTHBOUND_H_
22 
23 #include "thread.h"
24 #include "hook.h"
25 #include "linklist.h"
26 #include "openbsd-tree.h"
27 #include "yang.h"
28 #include "yang_translator.h"
29 
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33 
34 /* Forward declaration(s). */
35 struct vty;
36 struct debug;
37 
38 /* Northbound events. */
39 enum nb_event {
40 	/*
41 	 * The configuration callback is supposed to verify that the changes are
42 	 * valid and can be applied.
43 	 */
44 	NB_EV_VALIDATE,
45 
46 	/*
47 	 * The configuration callback is supposed to prepare all resources
48 	 * required to apply the changes.
49 	 */
50 	NB_EV_PREPARE,
51 
52 	/*
53 	 * Transaction has failed, the configuration callback needs to release
54 	 * all resources previously allocated.
55 	 */
56 	NB_EV_ABORT,
57 
58 	/*
59 	 * The configuration changes need to be applied. The changes can't be
60 	 * rejected at this point (errors are logged and ignored).
61 	 */
62 	NB_EV_APPLY,
63 };
64 
65 /*
66  * Northbound operations.
67  *
68  * Refer to the documentation comments of nb_callbacks for more details.
69  */
70 enum nb_operation {
71 	NB_OP_CREATE,
72 	NB_OP_MODIFY,
73 	NB_OP_DESTROY,
74 	NB_OP_MOVE,
75 	NB_OP_PRE_VALIDATE,
76 	NB_OP_APPLY_FINISH,
77 	NB_OP_GET_ELEM,
78 	NB_OP_GET_NEXT,
79 	NB_OP_GET_KEYS,
80 	NB_OP_LOOKUP_ENTRY,
81 	NB_OP_RPC,
82 };
83 
84 union nb_resource {
85 	int fd;
86 	void *ptr;
87 };
88 
89 /*
90  * Northbound callbacks parameters.
91  */
92 
93 struct nb_cb_create_args {
94 	/* Context of the configuration transaction. */
95 	struct nb_context *context;
96 
97 	/*
98 	 * The transaction phase. Refer to the documentation comments of
99 	 * nb_event for more details.
100 	 */
101 	enum nb_event event;
102 
103 	/* libyang data node that is being created. */
104 	const struct lyd_node *dnode;
105 
106 	/*
107 	 * Pointer to store resource(s) allocated during the NB_EV_PREPARE
108 	 * phase. The same pointer can be used during the NB_EV_ABORT and
109 	 * NB_EV_APPLY phases to either release or make use of the allocated
110 	 * resource(s). It's set to NULL when the event is NB_EV_VALIDATE.
111 	 */
112 	union nb_resource *resource;
113 
114 	/* Buffer to store human-readable error message in case of error. */
115 	char *errmsg;
116 
117 	/* Size of errmsg. */
118 	size_t errmsg_len;
119 };
120 
121 struct nb_cb_modify_args {
122 	/* Context of the configuration transaction. */
123 	struct nb_context *context;
124 
125 	/*
126 	 * The transaction phase. Refer to the documentation comments of
127 	 * nb_event for more details.
128 	 */
129 	enum nb_event event;
130 
131 	/* libyang data node that is being modified. */
132 	const struct lyd_node *dnode;
133 
134 	/*
135 	 * Pointer to store resource(s) allocated during the NB_EV_PREPARE
136 	 * phase. The same pointer can be used during the NB_EV_ABORT and
137 	 * NB_EV_APPLY phases to either release or make use of the allocated
138 	 * resource(s). It's set to NULL when the event is NB_EV_VALIDATE.
139 	 */
140 	union nb_resource *resource;
141 
142 	/* Buffer to store human-readable error message in case of error. */
143 	char *errmsg;
144 
145 	/* Size of errmsg. */
146 	size_t errmsg_len;
147 };
148 
149 struct nb_cb_destroy_args {
150 	/* Context of the configuration transaction. */
151 	struct nb_context *context;
152 
153 	/*
154 	 * The transaction phase. Refer to the documentation comments of
155 	 * nb_event for more details.
156 	 */
157 	enum nb_event event;
158 
159 	/* libyang data node that is being deleted. */
160 	const struct lyd_node *dnode;
161 
162 	/* Buffer to store human-readable error message in case of error. */
163 	char *errmsg;
164 
165 	/* Size of errmsg. */
166 	size_t errmsg_len;
167 };
168 
169 struct nb_cb_move_args {
170 	/* Context of the configuration transaction. */
171 	struct nb_context *context;
172 
173 	/*
174 	 * The transaction phase. Refer to the documentation comments of
175 	 * nb_event for more details.
176 	 */
177 	enum nb_event event;
178 
179 	/* libyang data node that is being moved. */
180 	const struct lyd_node *dnode;
181 
182 	/* Buffer to store human-readable error message in case of error. */
183 	char *errmsg;
184 
185 	/* Size of errmsg. */
186 	size_t errmsg_len;
187 };
188 
189 struct nb_cb_pre_validate_args {
190 	/* Context of the configuration transaction. */
191 	struct nb_context *context;
192 
193 	/* libyang data node associated with the 'pre_validate' callback. */
194 	const struct lyd_node *dnode;
195 
196 	/* Buffer to store human-readable error message in case of error. */
197 	char *errmsg;
198 
199 	/* Size of errmsg. */
200 	size_t errmsg_len;
201 };
202 
203 struct nb_cb_apply_finish_args {
204 	/* Context of the configuration transaction. */
205 	struct nb_context *context;
206 
207 	/* libyang data node associated with the 'apply_finish' callback. */
208 	const struct lyd_node *dnode;
209 
210 	/* Buffer to store human-readable error message in case of error. */
211 	char *errmsg;
212 
213 	/* Size of errmsg. */
214 	size_t errmsg_len;
215 };
216 
217 struct nb_cb_get_elem_args {
218 	/* YANG data path of the data we want to get. */
219 	const char *xpath;
220 
221 	/* Pointer to list entry (might be NULL). */
222 	const void *list_entry;
223 };
224 
225 struct nb_cb_get_next_args {
226 	/* Pointer to parent list entry. */
227 	const void *parent_list_entry;
228 
229 	/* Pointer to (leaf-)list entry. */
230 	const void *list_entry;
231 };
232 
233 struct nb_cb_get_keys_args {
234 	/* Pointer to list entry. */
235 	const void *list_entry;
236 
237 	/*
238 	 * Structure to be filled based on the attributes of the provided list
239 	 * entry.
240 	 */
241 	struct yang_list_keys *keys;
242 };
243 
244 struct nb_cb_lookup_entry_args {
245 	/* Pointer to parent list entry. */
246 	const void *parent_list_entry;
247 
248 	/* Structure containing the keys of the list entry. */
249 	const struct yang_list_keys *keys;
250 };
251 
252 struct nb_cb_rpc_args {
253 	/* XPath of the YANG RPC or action. */
254 	const char *xpath;
255 
256 	/* Read-only list of input parameters. */
257 	const struct list *input;
258 
259 	/* List of output parameters to be populated by the callback. */
260 	struct list *output;
261 };
262 
263 /*
264  * Set of configuration callbacks that can be associated to a northbound node.
265  */
266 struct nb_callbacks {
267 	/*
268 	 * Configuration callback.
269 	 *
270 	 * A presence container, list entry, leaf-list entry or leaf of type
271 	 * empty has been created.
272 	 *
273 	 * For presence-containers and list entries, the callback is supposed to
274 	 * initialize the default values of its children (if any) from the YANG
275 	 * models.
276 	 *
277 	 * args
278 	 *    Refer to the documentation comments of nb_cb_create_args for
279 	 *    details.
280 	 *
281 	 * Returns:
282 	 *    - NB_OK on success.
283 	 *    - NB_ERR_VALIDATION when a validation error occurred.
284 	 *    - NB_ERR_RESOURCE when the callback failed to allocate a resource.
285 	 *    - NB_ERR_INCONSISTENCY when an inconsistency was detected.
286 	 *    - NB_ERR for other errors.
287 	 */
288 	int (*create)(struct nb_cb_create_args *args);
289 
290 	/*
291 	 * Configuration callback.
292 	 *
293 	 * The value of a leaf has been modified.
294 	 *
295 	 * List keys don't need to implement this callback. When a list key is
296 	 * modified, the northbound treats this as if the list was deleted and a
297 	 * new one created with the updated key value.
298 	 *
299 	 * args
300 	 *    Refer to the documentation comments of nb_cb_modify_args for
301 	 *    details.
302 	 *
303 	 * Returns:
304 	 *    - NB_OK on success.
305 	 *    - NB_ERR_VALIDATION when a validation error occurred.
306 	 *    - NB_ERR_RESOURCE when the callback failed to allocate a resource.
307 	 *    - NB_ERR_INCONSISTENCY when an inconsistency was detected.
308 	 *    - NB_ERR for other errors.
309 	 */
310 	int (*modify)(struct nb_cb_modify_args *args);
311 
312 	/*
313 	 * Configuration callback.
314 	 *
315 	 * A presence container, list entry, leaf-list entry or optional leaf
316 	 * has been deleted.
317 	 *
318 	 * The callback is supposed to delete the entire configuration object,
319 	 * including its children when they exist.
320 	 *
321 	 * args
322 	 *    Refer to the documentation comments of nb_cb_destroy_args for
323 	 *    details.
324 	 *
325 	 * Returns:
326 	 *    - NB_OK on success.
327 	 *    - NB_ERR_VALIDATION when a validation error occurred.
328 	 *    - NB_ERR_INCONSISTENCY when an inconsistency was detected.
329 	 *    - NB_ERR for other errors.
330 	 */
331 	int (*destroy)(struct nb_cb_destroy_args *args);
332 
333 	/*
334 	 * Configuration callback.
335 	 *
336 	 * A list entry or leaf-list entry has been moved. Only applicable when
337 	 * the "ordered-by user" statement is present.
338 	 *
339 	 * args
340 	 *    Refer to the documentation comments of nb_cb_move_args for
341 	 *    details.
342 	 *
343 	 * Returns:
344 	 *    - NB_OK on success.
345 	 *    - NB_ERR_VALIDATION when a validation error occurred.
346 	 *    - NB_ERR_INCONSISTENCY when an inconsistency was detected.
347 	 *    - NB_ERR for other errors.
348 	 */
349 	int (*move)(struct nb_cb_move_args *args);
350 
351 	/*
352 	 * Optional configuration callback.
353 	 *
354 	 * This callback can be used to validate subsections of the
355 	 * configuration being committed before validating the configuration
356 	 * changes themselves. It's useful to perform more complex validations
357 	 * that depend on the relationship between multiple nodes.
358 	 *
359 	 * args
360 	 *    Refer to the documentation comments of nb_cb_pre_validate_args for
361 	 *    details.
362 	 *
363 	 * Returns:
364 	 *    - NB_OK on success.
365 	 *    - NB_ERR_VALIDATION when a validation error occurred.
366 	 */
367 	int (*pre_validate)(struct nb_cb_pre_validate_args *args);
368 
369 	/*
370 	 * Optional configuration callback.
371 	 *
372 	 * The 'apply_finish' callbacks are called after all other callbacks
373 	 * during the apply phase (NB_EV_APPLY). These callbacks are called only
374 	 * under one of the following two cases:
375 	 * - The data node has been created or modified (but not deleted);
376 	 * - Any change was made within the descendants of the data node (e.g. a
377 	 *   child leaf was modified, created or deleted).
378 	 *
379 	 * In the second case above, the 'apply_finish' callback is called only
380 	 * once even if multiple changes occurred within the descendants of the
381 	 * data node.
382 	 *
383 	 * args
384 	 *    Refer to the documentation comments of nb_cb_apply_finish_args for
385 	 *    details.
386 	 */
387 	void (*apply_finish)(struct nb_cb_apply_finish_args *args);
388 
389 	/*
390 	 * Operational data callback.
391 	 *
392 	 * The callback function should return the value of a specific leaf,
393 	 * leaf-list entry or inform if a typeless value (presence containers or
394 	 * leafs of type empty) exists or not.
395 	 *
396 	 * args
397 	 *    Refer to the documentation comments of nb_cb_get_elem_args for
398 	 *    details.
399 	 *
400 	 * Returns:
401 	 *    Pointer to newly created yang_data structure, or NULL to indicate
402 	 *    the absence of data.
403 	 */
404 	struct yang_data *(*get_elem)(struct nb_cb_get_elem_args *args);
405 
406 	/*
407 	 * Operational data callback for YANG lists and leaf-lists.
408 	 *
409 	 * The callback function should return the next entry in the list or
410 	 * leaf-list. The 'list_entry' parameter will be NULL on the first
411 	 * invocation.
412 	 *
413 	 * args
414 	 *    Refer to the documentation comments of nb_cb_get_next_args for
415 	 *    details.
416 	 *
417 	 * Returns:
418 	 *    Pointer to the next entry in the (leaf-)list, or NULL to signal
419 	 *    that the end of the (leaf-)list was reached.
420 	 */
421 	const void *(*get_next)(struct nb_cb_get_next_args *args);
422 
423 	/*
424 	 * Operational data callback for YANG lists.
425 	 *
426 	 * The callback function should fill the 'keys' parameter based on the
427 	 * given list_entry. Keyless lists don't need to implement this
428 	 * callback.
429 	 *
430 	 * args
431 	 *    Refer to the documentation comments of nb_cb_get_keys_args for
432 	 *    details.
433 	 *
434 	 * Returns:
435 	 *    NB_OK on success, NB_ERR otherwise.
436 	 */
437 	int (*get_keys)(struct nb_cb_get_keys_args *args);
438 
439 	/*
440 	 * Operational data callback for YANG lists.
441 	 *
442 	 * The callback function should return a list entry based on the list
443 	 * keys given as a parameter. Keyless lists don't need to implement this
444 	 * callback.
445 	 *
446 	 * args
447 	 *    Refer to the documentation comments of nb_cb_lookup_entry_args for
448 	 *    details.
449 	 *
450 	 * Returns:
451 	 *    Pointer to the list entry if found, or NULL if not found.
452 	 */
453 	const void *(*lookup_entry)(struct nb_cb_lookup_entry_args *args);
454 
455 	/*
456 	 * RPC and action callback.
457 	 *
458 	 * Both 'input' and 'output' are lists of 'yang_data' structures. The
459 	 * callback should fetch all the input parameters from the 'input' list,
460 	 * and add output parameters to the 'output' list if necessary.
461 	 *
462 	 * args
463 	 *    Refer to the documentation comments of nb_cb_rpc_args for details.
464 	 *
465 	 * Returns:
466 	 *    NB_OK on success, NB_ERR otherwise.
467 	 */
468 	int (*rpc)(struct nb_cb_rpc_args *args);
469 
470 	/*
471 	 * Optional callback to show the CLI command associated to the given
472 	 * YANG data node.
473 	 *
474 	 * vty
475 	 *    The vty terminal to dump the configuration to.
476 	 *
477 	 * dnode
478 	 *    libyang data node that should be shown in the form of a CLI
479 	 *    command.
480 	 *
481 	 * show_defaults
482 	 *    Specify whether to display default configuration values or not.
483 	 *    This parameter can be ignored most of the time since the
484 	 *    northbound doesn't call this callback for default leaves or
485 	 *    non-presence containers that contain only default child nodes.
486 	 *    The exception are commands associated to multiple configuration
487 	 *    nodes, in which case it might be desirable to hide one or more
488 	 *    parts of the command when this parameter is set to false.
489 	 */
490 	void (*cli_show)(struct vty *vty, struct lyd_node *dnode,
491 			 bool show_defaults);
492 
493 	/*
494 	 * Optional callback to show the CLI node end for lists or containers.
495 	 *
496 	 * vty
497 	 *    The vty terminal to dump the configuration to.
498 	 *
499 	 * dnode
500 	 *    libyang data node that should be shown in the form of a CLI
501 	 *    command.
502 	 */
503 	void (*cli_show_end)(struct vty *vty, struct lyd_node *dnode);
504 };
505 
506 struct nb_dependency_callbacks {
507 	void (*get_dependant_xpath)(const struct lyd_node *dnode, char *xpath);
508 	void (*get_dependency_xpath)(const struct lyd_node *dnode, char *xpath);
509 };
510 
511 /*
512  * Northbound-specific data that is allocated for each schema node of the native
513  * YANG modules.
514  */
515 struct nb_node {
516 	/* Back pointer to the libyang schema node. */
517 	const struct lys_node *snode;
518 
519 	/* Data path of this YANG node. */
520 	char xpath[XPATH_MAXLEN];
521 
522 	/* Priority - lower priorities are processed first. */
523 	uint32_t priority;
524 
525 	struct nb_dependency_callbacks dep_cbs;
526 
527 	/* Callbacks implemented for this node. */
528 	struct nb_callbacks cbs;
529 
530 	/*
531 	 * Pointer to the parent node (disconsidering non-presence containers).
532 	 */
533 	struct nb_node *parent;
534 
535 	/* Pointer to the nearest parent list, if any. */
536 	struct nb_node *parent_list;
537 
538 	/* Flags. */
539 	uint8_t flags;
540 
541 #ifdef HAVE_CONFD
542 	/* ConfD hash value corresponding to this YANG path. */
543 	int confd_hash;
544 #endif
545 };
546 /* The YANG container or list contains only config data. */
547 #define F_NB_NODE_CONFIG_ONLY 0x01
548 /* The YANG list doesn't contain key leafs. */
549 #define F_NB_NODE_KEYLESS_LIST 0x02
550 
551 /*
552  * HACK: old gcc versions (< 5.x) have a bug that prevents C99 flexible arrays
553  * from working properly on shared libraries. For those compilers, use a fixed
554  * size array to work around the problem.
555  */
556 #define YANG_MODULE_MAX_NODES 1024
557 
558 struct frr_yang_module_info {
559 	/* YANG module name. */
560 	const char *name;
561 
562 	/* Northbound callbacks. */
563 	const struct {
564 		/* Data path of this YANG node. */
565 		const char *xpath;
566 
567 		/* Callbacks implemented for this node. */
568 		struct nb_callbacks cbs;
569 
570 		/* Priority - lower priorities are processed first. */
571 		uint32_t priority;
572 #if defined(__GNUC__) && ((__GNUC__ - 0) < 5) && !defined(__clang__)
573 	} nodes[YANG_MODULE_MAX_NODES + 1];
574 #else
575 	} nodes[];
576 #endif
577 };
578 
579 /* Northbound error codes. */
580 enum nb_error {
581 	NB_OK = 0,
582 	NB_ERR,
583 	NB_ERR_NO_CHANGES,
584 	NB_ERR_NOT_FOUND,
585 	NB_ERR_LOCKED,
586 	NB_ERR_VALIDATION,
587 	NB_ERR_RESOURCE,
588 	NB_ERR_INCONSISTENCY,
589 };
590 
591 /* Default priority. */
592 #define NB_DFLT_PRIORITY (UINT32_MAX / 2)
593 
594 /* Default maximum of configuration rollbacks to store. */
595 #define NB_DLFT_MAX_CONFIG_ROLLBACKS 20
596 
597 /* Northbound clients. */
598 enum nb_client {
599 	NB_CLIENT_NONE = 0,
600 	NB_CLIENT_CLI,
601 	NB_CLIENT_CONFD,
602 	NB_CLIENT_SYSREPO,
603 	NB_CLIENT_GRPC,
604 };
605 
606 /* Northbound context. */
607 struct nb_context {
608 	/* Northbound client. */
609 	enum nb_client client;
610 
611 	/* Northbound user (can be NULL). */
612 	const void *user;
613 
614 	/* Client-specific data. */
615 #if 0
616 	union {
617 		struct {
618 		} cli;
619 		struct {
620 		} confd;
621 		struct {
622 		} sysrepo;
623 		struct {
624 		} grpc;
625 	} client_data;
626 #endif
627 };
628 
629 /* Northbound configuration. */
630 struct nb_config {
631 	struct lyd_node *dnode;
632 	uint32_t version;
633 };
634 
635 /* Northbound configuration callback. */
636 struct nb_config_cb {
637 	RB_ENTRY(nb_config_cb) entry;
638 	enum nb_operation operation;
639 	uint32_t seq;
640 	const struct nb_node *nb_node;
641 	const struct lyd_node *dnode;
642 };
643 RB_HEAD(nb_config_cbs, nb_config_cb);
644 RB_PROTOTYPE(nb_config_cbs, nb_config_cb, entry, nb_config_cb_compare);
645 
646 /* Northbound configuration change. */
647 struct nb_config_change {
648 	struct nb_config_cb cb;
649 	union nb_resource resource;
650 	bool prepare_ok;
651 };
652 
653 /* Northbound configuration transaction. */
654 struct nb_transaction {
655 	struct nb_context *context;
656 	char comment[80];
657 	struct nb_config *config;
658 	struct nb_config_cbs changes;
659 };
660 
661 /* Callback function used by nb_oper_data_iterate(). */
662 typedef int (*nb_oper_data_cb)(const struct lys_node *snode,
663 			       struct yang_translator *translator,
664 			       struct yang_data *data, void *arg);
665 
666 /* Iterate over direct child nodes only. */
667 #define NB_OPER_DATA_ITER_NORECURSE 0x0001
668 
669 /* Hooks. */
670 DECLARE_HOOK(nb_notification_send, (const char *xpath, struct list *arguments),
671 	     (xpath, arguments))
672 DECLARE_HOOK(nb_client_debug_config_write, (struct vty *vty), (vty))
673 DECLARE_HOOK(nb_client_debug_set_all, (uint32_t flags, bool set), (flags, set))
674 
675 /* Northbound debugging records */
676 extern struct debug nb_dbg_cbs_config;
677 extern struct debug nb_dbg_cbs_state;
678 extern struct debug nb_dbg_cbs_rpc;
679 extern struct debug nb_dbg_notif;
680 extern struct debug nb_dbg_events;
681 
682 /* Global running configuration. */
683 extern struct nb_config *running_config;
684 
685 /* Wrappers for the northbound callbacks. */
686 extern struct yang_data *nb_callback_get_elem(const struct nb_node *nb_node,
687 					      const char *xpath,
688 					      const void *list_entry);
689 extern const void *nb_callback_get_next(const struct nb_node *nb_node,
690 					const void *parent_list_entry,
691 					const void *list_entry);
692 extern int nb_callback_get_keys(const struct nb_node *nb_node,
693 				const void *list_entry,
694 				struct yang_list_keys *keys);
695 extern const void *nb_callback_lookup_entry(const struct nb_node *nb_node,
696 					    const void *parent_list_entry,
697 					    const struct yang_list_keys *keys);
698 extern int nb_callback_rpc(const struct nb_node *nb_node, const char *xpath,
699 			   const struct list *input, struct list *output);
700 
701 /*
702  * Create a northbound node for all YANG schema nodes.
703  */
704 void nb_nodes_create(void);
705 
706 /*
707  * Delete all northbound nodes from all YANG schema nodes.
708  */
709 void nb_nodes_delete(void);
710 
711 /*
712  * Find the northbound node corresponding to a YANG data path.
713  *
714  * xpath
715  *    XPath to search for (with or without predicates).
716  *
717  * Returns:
718  *    Pointer to northbound node if found, NULL otherwise.
719  */
720 extern struct nb_node *nb_node_find(const char *xpath);
721 
722 extern void nb_node_set_dependency_cbs(const char *dependency_xpath,
723 				       const char *dependant_xpath,
724 				       struct nb_dependency_callbacks *cbs);
725 
726 bool nb_node_has_dependency(struct nb_node *node);
727 
728 /*
729  * Create a new northbound configuration.
730  *
731  * dnode
732  *    Pointer to a libyang data node containing the configuration data. If NULL
733  *    is given, an empty configuration will be created.
734  *
735  * Returns:
736  *    Pointer to newly created northbound configuration.
737  */
738 extern struct nb_config *nb_config_new(struct lyd_node *dnode);
739 
740 /*
741  * Delete a northbound configuration.
742  *
743  * config
744  *    Pointer to the config that is going to be deleted.
745  */
746 extern void nb_config_free(struct nb_config *config);
747 
748 /*
749  * Duplicate a northbound configuration.
750  *
751  * config
752  *    Northbound configuration to duplicate.
753  *
754  * Returns:
755  *    Pointer to duplicated configuration.
756  */
757 extern struct nb_config *nb_config_dup(const struct nb_config *config);
758 
759 /*
760  * Merge one configuration into another.
761  *
762  * config_dst
763  *    Configuration to merge to.
764  *
765  * config_src
766  *    Configuration to merge config_dst with.
767  *
768  * preserve_source
769  *    Specify whether config_src should be deleted or not after the merge
770  *    operation.
771  *
772  * Returns:
773  *    NB_OK on success, NB_ERR otherwise.
774  */
775 extern int nb_config_merge(struct nb_config *config_dst,
776 			   struct nb_config *config_src, bool preserve_source);
777 
778 /*
779  * Replace one configuration by another.
780  *
781  * config_dst
782  *    Configuration to be replaced.
783  *
784  * config_src
785  *    Configuration to replace config_dst.
786  *
787  * preserve_source
788  *    Specify whether config_src should be deleted or not after the replace
789  *    operation.
790  */
791 extern void nb_config_replace(struct nb_config *config_dst,
792 			      struct nb_config *config_src,
793 			      bool preserve_source);
794 
795 /*
796  * Edit a candidate configuration.
797  *
798  * candidate
799  *    Candidate configuration to edit.
800  *
801  * nb_node
802  *    Northbound node associated to the configuration being edited.
803  *
804  * operation
805  *    Operation to apply.
806  *
807  * xpath
808  *    XPath of the configuration node being edited.
809  *
810  * previous
811  *    Previous value of the configuration node. Should be used only when the
812  *    operation is NB_OP_MOVE, otherwise this parameter is ignored.
813  *
814  * data
815  *    New value of the configuration node.
816  *
817  * Returns:
818  *    - NB_OK on success.
819  *    - NB_ERR_NOT_FOUND when the element to be deleted was not found.
820  *    - NB_ERR for other errors.
821  */
822 extern int nb_candidate_edit(struct nb_config *candidate,
823 			     const struct nb_node *nb_node,
824 			     enum nb_operation operation, const char *xpath,
825 			     const struct yang_data *previous,
826 			     const struct yang_data *data);
827 
828 /*
829  * Check if a candidate configuration is outdated and needs to be updated.
830  *
831  * candidate
832  *    Candidate configuration to check.
833  *
834  * Returns:
835  *    true if the candidate is outdated, false otherwise.
836  */
837 extern bool nb_candidate_needs_update(const struct nb_config *candidate);
838 
839 /*
840  * Update a candidate configuration by rebasing the changes on top of the latest
841  * running configuration. Resolve conflicts automatically by giving preference
842  * to the changes done in the candidate configuration.
843  *
844  * candidate
845  *    Candidate configuration to update.
846  *
847  * Returns:
848  *    NB_OK on success, NB_ERR otherwise.
849  */
850 extern int nb_candidate_update(struct nb_config *candidate);
851 
852 /*
853  * Validate a candidate configuration. Perform both YANG syntactic/semantic
854  * validation and code-level validation using the northbound callbacks.
855  *
856  * WARNING: the candidate can be modified as part of the validation process
857  * (e.g. add default nodes).
858  *
859  * context
860  *    Context of the northbound transaction.
861  *
862  * candidate
863  *    Candidate configuration to validate.
864  *
865  * errmsg
866  *    Buffer to store human-readable error message in case of error.
867  *
868  * errmsg_len
869  *    Size of errmsg.
870  *
871  * Returns:
872  *    NB_OK on success, NB_ERR_VALIDATION otherwise.
873  */
874 extern int nb_candidate_validate(struct nb_context *context,
875 				 struct nb_config *candidate, char *errmsg,
876 				 size_t errmsg_len);
877 
878 /*
879  * Create a new configuration transaction but do not commit it yet. Only
880  * validate the candidate and prepare all resources required to apply the
881  * configuration changes.
882  *
883  * context
884  *    Context of the northbound transaction.
885  *
886  * candidate
887  *    Candidate configuration to commit.
888  *
889  * comment
890  *    Optional comment describing the commit.
891  *
892  * transaction
893  *    Output parameter providing the created transaction when one is created
894  *    successfully. In this case, it must be either aborted using
895  *    nb_candidate_commit_abort() or committed using
896  *    nb_candidate_commit_apply().
897  *
898  * errmsg
899  *    Buffer to store human-readable error message in case of error.
900  *
901  * errmsg_len
902  *    Size of errmsg.
903  *
904  * Returns:
905  *    - NB_OK on success.
906  *    - NB_ERR_NO_CHANGES when the candidate is identical to the running
907  *      configuration.
908  *    - NB_ERR_LOCKED when there's already another transaction in progress.
909  *    - NB_ERR_VALIDATION when the candidate fails the validation checks.
910  *    - NB_ERR_RESOURCE when the system fails to allocate resources to apply
911  *      the candidate configuration.
912  *    - NB_ERR for other errors.
913  */
914 extern int nb_candidate_commit_prepare(struct nb_context *context,
915 				       struct nb_config *candidate,
916 				       const char *comment,
917 				       struct nb_transaction **transaction,
918 				       char *errmsg, size_t errmsg_len);
919 
920 /*
921  * Abort a previously created configuration transaction, releasing all resources
922  * allocated during the preparation phase.
923  *
924  * transaction
925  *    Candidate configuration to abort. It's consumed by this function.
926  *
927  * errmsg
928  *    Buffer to store human-readable error message in case of error.
929  *
930  * errmsg_len
931  *    Size of errmsg.
932  */
933 extern void nb_candidate_commit_abort(struct nb_transaction *transaction,
934 				      char *errmsg, size_t errmsg_len);
935 
936 /*
937  * Commit a previously created configuration transaction.
938  *
939  * transaction
940  *    Configuration transaction to commit. It's consumed by this function.
941  *
942  * save_transaction
943  *    Specify whether the transaction should be recorded in the transactions log
944  *    or not.
945  *
946  * transaction_id
947  *    Optional output parameter providing the ID of the committed transaction.
948  *
949  * errmsg
950  *    Buffer to store human-readable error message in case of error.
951  *
952  * errmsg_len
953  *    Size of errmsg.
954  */
955 extern void nb_candidate_commit_apply(struct nb_transaction *transaction,
956 				      bool save_transaction,
957 				      uint32_t *transaction_id, char *errmsg,
958 				      size_t errmsg_len);
959 
960 /*
961  * Create a new transaction to commit a candidate configuration. This is a
962  * convenience function that performs the two-phase commit protocol
963  * transparently to the user. The cost is reduced flexibility, since
964  * network-wide and multi-daemon transactions require the network manager to
965  * take into account the results of the preparation phase of multiple managed
966  * entities.
967  *
968  * context
969  *    Context of the northbound transaction.
970  *
971  * candidate
972  *    Candidate configuration to commit. It's preserved regardless if the commit
973  *    operation fails or not.
974  *
975  * save_transaction
976  *    Specify whether the transaction should be recorded in the transactions log
977  *    or not.
978  *
979  * comment
980  *    Optional comment describing the commit.
981  *
982  * transaction_id
983  *    Optional output parameter providing the ID of the committed transaction.
984  *
985  * errmsg
986  *    Buffer to store human-readable error message in case of error.
987  *
988  * errmsg_len
989  *    Size of errmsg.
990  *
991  * Returns:
992  *    - NB_OK on success.
993  *    - NB_ERR_NO_CHANGES when the candidate is identical to the running
994  *      configuration.
995  *    - NB_ERR_LOCKED when there's already another transaction in progress.
996  *    - NB_ERR_VALIDATION when the candidate fails the validation checks.
997  *    - NB_ERR_RESOURCE when the system fails to allocate resources to apply
998  *      the candidate configuration.
999  *    - NB_ERR for other errors.
1000  */
1001 extern int nb_candidate_commit(struct nb_context *context,
1002 			       struct nb_config *candidate,
1003 			       bool save_transaction, const char *comment,
1004 			       uint32_t *transaction_id, char *errmsg,
1005 			       size_t errmsg_len);
1006 
1007 /*
1008  * Lock the running configuration.
1009  *
1010  * client
1011  *    Northbound client.
1012  *
1013  * user
1014  *    Northbound user (can be NULL).
1015  *
1016  * Returns:
1017  *    0 on success, -1 when the running configuration is already locked.
1018  */
1019 extern int nb_running_lock(enum nb_client client, const void *user);
1020 
1021 /*
1022  * Unlock the running configuration.
1023  *
1024  * client
1025  *    Northbound client.
1026  *
1027  * user
1028  *    Northbound user (can be NULL).
1029  *
1030  * Returns:
1031  *    0 on success, -1 when the running configuration is already unlocked or
1032  *    locked by another client/user.
1033  */
1034 extern int nb_running_unlock(enum nb_client client, const void *user);
1035 
1036 /*
1037  * Check if the running configuration is locked or not for the given
1038  * client/user.
1039  *
1040  * client
1041  *    Northbound client.
1042  *
1043  * user
1044  *    Northbound user (can be NULL).
1045  *
1046  * Returns:
1047  *    0 if the running configuration is unlocked or if the client/user owns the
1048  *    lock, -1 otherwise.
1049  */
1050 extern int nb_running_lock_check(enum nb_client client, const void *user);
1051 
1052 /*
1053  * Iterate over operational data.
1054  *
1055  * xpath
1056  *    Data path of the YANG data we want to iterate over.
1057  *
1058  * translator
1059  *    YANG module translator (might be NULL).
1060  *
1061  * flags
1062  *    NB_OPER_DATA_ITER_ flags to control how the iteration is performed.
1063  *
1064  * cb
1065  *    Function to call with each data node.
1066  *
1067  * arg
1068  *    Arbitrary argument passed as the fourth parameter in each call to 'cb'.
1069  *
1070  * Returns:
1071  *    NB_OK on success, NB_ERR otherwise.
1072  */
1073 extern int nb_oper_data_iterate(const char *xpath,
1074 				struct yang_translator *translator,
1075 				uint32_t flags, nb_oper_data_cb cb, void *arg);
1076 
1077 /*
1078  * Validate if the northbound operation is valid for the given node.
1079  *
1080  * operation
1081  *    Operation we want to check.
1082  *
1083  * snode
1084  *    libyang schema node we want to check.
1085  *
1086  * Returns:
1087  *    true if the operation is valid, false otherwise.
1088  */
1089 extern bool nb_operation_is_valid(enum nb_operation operation,
1090 				  const struct lys_node *snode);
1091 
1092 /*
1093  * Send a YANG notification. This is a no-op unless the 'nb_notification_send'
1094  * hook was registered by a northbound plugin.
1095  *
1096  * xpath
1097  *    XPath of the YANG notification.
1098  *
1099  * arguments
1100  *    Linked list containing the arguments that should be sent. This list is
1101  *    deleted after being used.
1102  *
1103  * Returns:
1104  *    NB_OK on success, NB_ERR otherwise.
1105  */
1106 extern int nb_notification_send(const char *xpath, struct list *arguments);
1107 
1108 /*
1109  * Associate a user pointer to a configuration node.
1110  *
1111  * This should be called by northbound 'create' callbacks in the NB_EV_APPLY
1112  * phase only.
1113  *
1114  * dnode
1115  *    libyang data node - only its XPath is used.
1116  *
1117  * entry
1118  *    Arbitrary user-specified pointer.
1119  */
1120 extern void nb_running_set_entry(const struct lyd_node *dnode, void *entry);
1121 
1122 /*
1123  * Move an entire tree of user pointer nodes.
1124  *
1125  * Suppose we have xpath A/B/C/D, with user pointers associated to C and D. We
1126  * need to move B to be under Z, so the new xpath is Z/B/C/D. Because user
1127  * pointers are indexed with their absolute path, We need to move all user
1128  * pointers at and below B to their new absolute paths; this function does
1129  * that.
1130  *
1131  * xpath_from
1132  *    base xpath of tree to move (A/B)
1133  *
1134  * xpath_to
1135  *    base xpath of new location of tree (Z/B)
1136  */
1137 extern void nb_running_move_tree(const char *xpath_from, const char *xpath_to);
1138 
1139 /*
1140  * Unset the user pointer associated to a configuration node.
1141  *
1142  * This should be called by northbound 'destroy' callbacks in the NB_EV_APPLY
1143  * phase only.
1144  *
1145  * dnode
1146  *    libyang data node - only its XPath is used.
1147  *
1148  * Returns:
1149  *    The user pointer that was unset.
1150  */
1151 extern void *nb_running_unset_entry(const struct lyd_node *dnode);
1152 
1153 /*
1154  * Find the user pointer (if any) associated to a configuration node.
1155  *
1156  * The XPath associated to the configuration node can be provided directly or
1157  * indirectly through a libyang data node.
1158  *
1159  * If an user point is not found, this function follows the parent nodes in the
1160  * running configuration until an user pointer is found or until the root node
1161  * is reached.
1162  *
1163  * dnode
1164  *    libyang data node - only its XPath is used (can be NULL if 'xpath' is
1165  *    provided).
1166  *
1167  * xpath
1168  *    XPath of the configuration node (can be NULL if 'dnode' is provided).
1169  *
1170  * abort_if_not_found
1171  *    When set to true, abort the program if no user pointer is found.
1172  *
1173  *    As a rule of thumb, this parameter should be set to true in the following
1174  *    scenarios:
1175  *    - Calling this function from any northbound configuration callback during
1176  *      the NB_EV_APPLY phase.
1177  *    - Calling this function from a 'delete' northbound configuration callback
1178  *      during any phase.
1179  *
1180  *    In both the above cases, the given configuration node should contain an
1181  *    user pointer except when there's a bug in the code, in which case it's
1182  *    better to abort the program right away and eliminate the need for
1183  *    unnecessary NULL checks.
1184  *
1185  *    In all other cases, this parameter should be set to false and the caller
1186  *    should check if the function returned NULL or not.
1187  *
1188  * Returns:
1189  *    User pointer if found, NULL otherwise.
1190  */
1191 extern void *nb_running_get_entry(const struct lyd_node *dnode,
1192 				  const char *xpath, bool abort_if_not_found);
1193 
1194 /*
1195  * Same as 'nb_running_get_entry', but doesn't search within parent nodes
1196  * recursively if an user point is not found.
1197  */
1198 extern void *nb_running_get_entry_non_rec(const struct lyd_node *dnode,
1199 					  const char *xpath,
1200 					  bool abort_if_not_found);
1201 
1202 /*
1203  * Return a human-readable string representing a northbound event.
1204  *
1205  * event
1206  *    Northbound event.
1207  *
1208  * Returns:
1209  *    String representation of the given northbound event.
1210  */
1211 extern const char *nb_event_name(enum nb_event event);
1212 
1213 /*
1214  * Return a human-readable string representing a northbound operation.
1215  *
1216  * operation
1217  *    Northbound operation.
1218  *
1219  * Returns:
1220  *    String representation of the given northbound operation.
1221  */
1222 extern const char *nb_operation_name(enum nb_operation operation);
1223 
1224 /*
1225  * Return a human-readable string representing a northbound error.
1226  *
1227  * error
1228  *    Northbound error.
1229  *
1230  * Returns:
1231  *    String representation of the given northbound error.
1232  */
1233 extern const char *nb_err_name(enum nb_error error);
1234 
1235 /*
1236  * Return a human-readable string representing a northbound client.
1237  *
1238  * client
1239  *    Northbound client.
1240  *
1241  * Returns:
1242  *    String representation of the given northbound client.
1243  */
1244 extern const char *nb_client_name(enum nb_client client);
1245 
1246 /*
1247  * Initialize the northbound layer. Should be called only once during the
1248  * daemon initialization process.
1249  *
1250  * modules
1251  *    Array of YANG modules to parse and initialize.
1252  *
1253  * nmodules
1254  *    Size of the modules array.
1255  *
1256  * db_enabled
1257  *    Set this to record the transactions in the transaction log.
1258  */
1259 extern void nb_init(struct thread_master *tm,
1260 		    const struct frr_yang_module_info *const modules[],
1261 		    size_t nmodules, bool db_enabled);
1262 
1263 /*
1264  * Finish the northbound layer gracefully. Should be called only when the daemon
1265  * is exiting.
1266  */
1267 extern void nb_terminate(void);
1268 
1269 #ifdef __cplusplus
1270 }
1271 #endif
1272 
1273 #endif /* _FRR_NORTHBOUND_H_ */
1274