blob: f24303780d55865b9b489fda3fd2d92d6b0a8a74 [file] [log] [blame]
Radek Krejcie534c132016-11-23 13:32:31 +01001/**
2 * @file extensions.h
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief libyang support for YANG extension implementations.
5 *
6 * Copyright (c) 2016 CESNET, z.s.p.o.
7 *
8 * 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
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
15#ifndef LY_EXTENSIONS_H_
16#define LY_EXTENSIONS_H_
17
Radek Krejcic25fe432017-02-22 16:20:09 +010018#include "libyang.h"
Radek Krejcie534c132016-11-23 13:32:31 +010019
20#ifdef __cplusplus
21extern "C" {
22#endif
23
Radek Krejcie534c132016-11-23 13:32:31 +010024/**
Radek Krejci8d6b7422017-02-03 14:42:13 +010025 * @addtogroup extensions
26 * @{
27 */
28
29/**
Radek Krejcibe336392017-02-07 10:54:24 +010030 * @brief Extension instance structure parent enumeration
31 */
32typedef enum {
33 LYEXT_PAR_MODULE, /**< ::lys_module or ::lys_submodule */
34 LYEXT_PAR_NODE, /**< ::lys_node (and the derived structures) */
35 LYEXT_PAR_TPDF, /**< ::lys_tpdf */
36 LYEXT_PAR_TYPE, /**< ::lys_type */
37 LYEXT_PAR_TYPE_BIT, /**< ::lys_type_bit */
38 LYEXT_PAR_TYPE_ENUM, /**< ::lys_type_enum */
39 LYEXT_PAR_FEATURE, /**< ::lys_feature */
40 LYEXT_PAR_RESTR, /**< ::lys_restr - YANG's must, range, length and pattern statements */
41 LYEXT_PAR_WHEN, /**< ::lys_when */
42 LYEXT_PAR_IDENT, /**< ::lys_ident */
43 LYEXT_PAR_EXT, /**< ::lys_ext */
44 LYEXT_PAR_EXTINST, /**< ::lys_ext_instance */
45 LYEXT_PAR_REFINE, /**< ::lys_refine */
46 LYEXT_PAR_DEVIATION, /**< ::lys_deviation */
47 LYEXT_PAR_DEVIATE, /**< ::lys_deviate */
48 LYEXT_PAR_IMPORT, /**< ::lys_import */
49 LYEXT_PAR_INCLUDE, /**< ::lys_include */
50 LYEXT_PAR_REVISION, /**< ::lys_revision */
51 LYEXT_PAR_IFFEATURE /**< ::lys_iffeature */
52} LYEXT_PAR;
53
54/**
55 * @brief List of substatement without extensions storage. If the module contains extension instances in these
56 * substatements, they are stored with the extensions of the parent statement and flag to show to which substatement
57 * they belongs to.
58 *
59 * For example, if the extension is supposed to be instantiated as a child to the description statement, libyang
60 * stores the description just as its value. So, for example in case of the module's description, the description's
Radek Krejci89db0592017-02-16 15:07:13 +010061 * extension instance is actually stored in the lys_module's extensions list with the ::lys_ext_instance#insubstmt set to
Radek Krejcibe336392017-02-07 10:54:24 +010062 * #LYEXT_SUBSTMT_DESCRIPTION, ::lys_ext_instance#parent_type is LYEXT_PAR_MODULE and the ::lys_ext_instance#parent
63 * points to the ::lys_module structure.
64 *
65 * The values are (convertible) subset of #LY_STMT
66 */
67typedef enum {
68 LYEXT_SUBSTMT_ALL = -1, /**< special value for the lys_ext_iter() */
69 LYEXT_SUBSTMT_SELF = 0, /**< extension of the structure itself, not substatement's */
70 LYEXT_SUBSTMT_ARGUMENT, /**< extension of the argument statement, can appear in lys_ext */
71 LYEXT_SUBSTMT_BASE, /**< extension of the base statement, can appear (repeatedly) in lys_type and lys_ident */
72 LYEXT_SUBSTMT_BELONGSTO, /**< extension of the belongs-to statement, can appear in lys_submodule */
73 LYEXT_SUBSTMT_CONTACT, /**< extension of the contact statement, can appear in lys_module */
74 LYEXT_SUBSTMT_DEFAULT, /**< extension of the default statement, can appear in lys_node_leaf, lys_node_leaflist,
75 lys_node_choice and lys_deviate */
76 LYEXT_SUBSTMT_DESCRIPTION, /**< extension of the description statement, can appear in lys_module, lys_submodule,
77 lys_node, lys_import, lys_include, lys_ext, lys_feature, lys_tpdf, lys_restr,
78 lys_ident, lys_deviation, lys_type_enum, lys_type_bit, lys_when and lys_revision */
79 LYEXT_SUBSTMT_ERRTAG, /**< extension of the error-app-tag statement, can appear in lys_restr */
80 LYEXT_SUBSTMT_ERRMSG, /**< extension of the error-message statement, can appear in lys_restr */
81 LYEXT_SUBSTMT_KEY, /**< extension of the key statement, can appear in lys_node_list */
82 LYEXT_SUBSTMT_NAMESPACE, /**< extension of the namespace statement, can appear in lys_module */
83 LYEXT_SUBSTMT_ORGANIZATION, /**< extension of the organization statement, can appear in lys_module and lys_submodule */
84 LYEXT_SUBSTMT_PATH, /**< extension of the path statement, can appear in lys_type */
85 LYEXT_SUBSTMT_PREFIX, /**< extension of the prefix statement, can appear in lys_module, lys_submodule (for
86 belongs-to's prefix) and lys_import */
87 LYEXT_SUBSTMT_PRESENCE, /**< extension of the presence statement, can appear in lys_node_container */
88 LYEXT_SUBSTMT_REFERENCE, /**< extension of the reference statement, can appear in lys_module, lys_submodule,
89 lys_node, lys_import, lys_include, lys_revision, lys_tpdf, lys_restr, lys_ident,
90 lys_ext, lys_feature, lys_deviation, lys_type_enum, lys_type_bit and lys_when */
91 LYEXT_SUBSTMT_REVISIONDATE, /**< extension of the revision-date statement, can appear in lys_import and lys_include */
92 LYEXT_SUBSTMT_UNITS, /**< extension of the units statement, can appear in lys_tpdf, lys_node_leaf,
93 lys_node_leaflist and lys_deviate */
94 LYEXT_SUBSTMT_VALUE, /**< extension of the value statement, can appear in lys_type_enum */
95 LYEXT_SUBSTMT_VERSION, /**< extension of the yang-version statement, can appear in lys_module and lys_submodule */
96 LYEXT_SUBSTMT_MODIFIER, /**< extension of the modifier statement, can appear in lys_restr */
97 LYEXT_SUBSTMT_REQINSTANCE, /**< extension of the require-instance statement, can appear in lys_type */
98 LYEXT_SUBSTMT_YINELEM, /**< extension of the yin-element statement, can appear in lys_ext */
99 LYEXT_SUBSTMT_CONFIG, /**< extension of the config statement, can appear in lys_node and lys_deviate */
100 LYEXT_SUBSTMT_MANDATORY, /**< extension of the mandatory statement, can appear in lys_node_leaf, lys_node_choice,
101 lys_node_anydata and lys_deviate */
102 LYEXT_SUBSTMT_ORDEREDBY, /**< extension of the ordered-by statement, can appear in lys_node_list and lys_node_leaflist */
103 LYEXT_SUBSTMT_STATUS, /**< extension of the status statement, can appear in lys_tpdf, lys_node, lys_ident,
104 lys_ext, lys_feature, lys_type_enum and lys_type_bit */
105 LYEXT_SUBSTMT_DIGITS, /**< extension of the fraction-digits statement, can appear in lys_type */
106 LYEXT_SUBSTMT_MAX, /**< extension of the max-elements statement, can appear in lys_node_list,
107 lys_node_leaflist and lys_deviate */
108 LYEXT_SUBSTMT_MIN, /**< extension of the min-elements statement, can appear in lys_node_list,
109 lys_node_leaflist and lys_deviate */
110 LYEXT_SUBSTMT_POSITION, /**< extension of the position statement, can appear in lys_type_bit */
111 LYEXT_SUBSTMT_UNIQUE, /**< extension of the unique statement, can appear in lys_node_list and lys_deviate */
112} LYEXT_SUBSTMT;
113
114/**
Radek Krejcie534c132016-11-23 13:32:31 +0100115 * @brief Callback to check that the extension can be instantiated inside the provided node
116 *
Radek Krejci43ce4b72017-01-04 11:02:38 +0100117 * @param[in] parent The parent of the instantiated extension.
118 * @param[in] parent_type The type of the structure provided as \p parent.
119 * @param[in] substmt_type libyang does not store all the extension instances in the structures where they are
120 * instantiated in the module. In some cases (see #LYEXT_SUBSTMT) they are stored in parent
121 * structure and marked with flag to know in which substatement of the parent the extension
122 * was originally instantiated.
123 * @return 0 - yes
124 * 1 - no
125 * 2 - ignore / skip without an error
126 */
127typedef int (*lyext_check_position_clb)(const void *parent, LYEXT_PAR parent_type, LYEXT_SUBSTMT substmt_type);
128
129/**
130 * @brief Callback to check that the extension instance is correct - have
Radek Krejci2b107412017-02-22 15:26:42 +0100131 * the valid argument, cardinality, etc.
Radek Krejci43ce4b72017-01-04 11:02:38 +0100132 *
Radek Krejci80056d52017-01-05 13:13:33 +0100133 * @param[in] ext Extension instance to be checked.
Radek Krejci90db7552017-01-04 16:17:46 +0100134 * @return 0 - ok
135 * 1 - error
Radek Krejcie534c132016-11-23 13:32:31 +0100136 */
Radek Krejci43ce4b72017-01-04 11:02:38 +0100137typedef int (*lyext_check_result_clb)(struct lys_ext_instance *ext);
Radek Krejcie534c132016-11-23 13:32:31 +0100138
Radek Krejci80056d52017-01-05 13:13:33 +0100139/**
140 * @brief Callback to decide whether the extension will be inherited into the provided schema node. The extension
Radek Krejci89db0592017-02-16 15:07:13 +0100141 * instance is always from some of the node's parents. The inherited extension instances are marked with the
142 * #LYEXT_OPT_INHERIT flag.
Radek Krejci80056d52017-01-05 13:13:33 +0100143 *
144 * @param[in] ext Extension instance to be inherited.
145 * @param[in] node Schema node where the node is supposed to be inherited.
146 * @return 0 - yes
147 * 1 - no (do not process the node's children)
148 * 2 - no, but continue with children
149 */
150typedef int (*lyext_check_inherit_clb)(struct lys_ext_instance *ext, struct lys_node *node);
151
PavolVicane9392862018-02-19 17:34:40 +0100152/**
153 * @brief Callback to decide if data is valid towards to schema.
154 *
155 * @param[in] ext Extension instance to be checked.
156 * @param[in] node Data node, which try to valid.
157 *
158 * @return 0 - valid
159 * 1 - invalid
160 */
161typedef int (*lyext_valid_data_clb)(struct lys_ext_instance *ext, struct lyd_node *node);
162
Radek Krejci43ce4b72017-01-04 11:02:38 +0100163struct lyext_plugin {
164 LYEXT_TYPE type; /**< type of the extension, according to it the structure will be casted */
Radek Krejci80056d52017-01-05 13:13:33 +0100165 uint16_t flags; /**< [extension flags](@ref extflags) */
Radek Krejcie534c132016-11-23 13:32:31 +0100166
Radek Krejci80056d52017-01-05 13:13:33 +0100167 lyext_check_position_clb check_position; /**< callbcak for testing that the extension can be instantiated
Radek Krejci43ce4b72017-01-04 11:02:38 +0100168 under the provided parent. Mandatory callback. */
Radek Krejci80056d52017-01-05 13:13:33 +0100169 lyext_check_result_clb check_result; /**< callback for testing if the argument value of the extension instance
Radek Krejci43ce4b72017-01-04 11:02:38 +0100170 is valid. Mandatory if the extension has the argument. */
Radek Krejci80056d52017-01-05 13:13:33 +0100171 lyext_check_inherit_clb check_inherit; /**< callback to decide if the extension is supposed to be inherited into
Radek Krejci89db0592017-02-16 15:07:13 +0100172 the provided node, the callback is used only if the flags contains
173 #LYEXT_OPT_INHERIT flag */
PavolVicane9392862018-02-19 17:34:40 +0100174 lyext_valid_data_clb valid_data; /**< callback to valid if data is valid toward to schema */
Radek Krejcie534c132016-11-23 13:32:31 +0100175};
176
Radek Krejci8d6b7422017-02-03 14:42:13 +0100177struct lyext_plugin_complex {
178 LYEXT_TYPE type; /**< type of the extension, according to it the structure will be casted */
179 uint16_t flags; /**< [extension flags](@ref extflags) */
180
181 lyext_check_position_clb check_position; /**< callbcak for testing that the extension can be instantiated
182 under the provided parent. Mandatory callback. */
183 lyext_check_result_clb check_result; /**< callback for testing if the argument value of the extension instance
184 is valid. Mandatory if the extension has the argument. */
185 lyext_check_inherit_clb check_inherit; /**< callback to decide if the extension is supposed to be inherited into
Radek Krejci89db0592017-02-16 15:07:13 +0100186 the provided node, the callback is used only if the flags contains
187 #LYEXT_OPT_INHERIT flag */
PavolVicane9392862018-02-19 17:34:40 +0100188 lyext_valid_data_clb valid_data; /**< callback to valid if data is valid toward to schema */
Radek Krejci8d6b7422017-02-03 14:42:13 +0100189 struct lyext_substmt *substmt; /**< NULL-terminated array of allowed substatements and restrictions
190 to their instantiation inside the extension instance */
191 size_t instance_size; /**< size of the instance structure to allocate, the structure is
192 is provided as ::lys_ext_instance_complex, but the content array
193 is accessed according to the substmt specification provided by
194 plugin */
195};
196
Radek Krejci43ce4b72017-01-04 11:02:38 +0100197struct lyext_plugin_list {
Radek Krejci3b88c6c2017-01-04 16:12:12 +0100198 const char *module; /**< name of the module where the extension is defined */
199 const char *revision; /**< optional module revision - if not specified, the plugin applies to any revision,
200 which is not an optional approach due to a possible future revisions of the module.
201 Instead, there should be defined multiple items in the plugins list, each with the
202 different revision, but all with the same pointer to the plugin extension. The
203 only valid use case for the NULL revision is the case the module has no revision. */
Radek Krejci43ce4b72017-01-04 11:02:38 +0100204 const char *name; /**< name of the extension */
205 struct lyext_plugin *plugin; /**< plugin for the extension */
Radek Krejcie534c132016-11-23 13:32:31 +0100206};
207
Radek Krejci8d6b7422017-02-03 14:42:13 +0100208/**
Radek Krejcic25fe432017-02-22 16:20:09 +0100209 * @brief Logging function for extension plugins, use #LYEXT_LOG macro instead!
210 */
Michal Vasko53b7da02018-02-13 15:28:42 +0100211void lyext_log(const struct ly_ctx *ctx, LY_LOG_LEVEL level, const char *plugin, const char *function, const char *format, ...);
Radek Krejcic25fe432017-02-22 16:20:09 +0100212
213/**
214 * @brief Logging macro for extension plugins
215 *
Michal Vasko53b7da02018-02-13 15:28:42 +0100216 * @param[in] ctx Context to store the error in.
Radek Krejcic25fe432017-02-22 16:20:09 +0100217 * @param[in] level #LY_LOG_LEVEL value with the message importance.
Radek Krejci24f86902017-02-23 13:07:48 +0100218 * @param[in] plugin Plugin name.
Radek Krejcic25fe432017-02-22 16:20:09 +0100219 * @param[in] str Format string as in case of printf function.
220 * @param[in] args Parameters to expand in format string.
221 */
Michal Vasko53b7da02018-02-13 15:28:42 +0100222#define LYEXT_LOG(ctx, level, plugin, str, args...) \
223 lyext_log(ctx, level, plugin, __func__, str, ##args); \
Radek Krejcic25fe432017-02-22 16:20:09 +0100224
225/**
Michal Vaskoe41dfe62018-11-08 13:28:07 +0100226 * @brief Free iffeature structure. In API only for plugins that want to handle if-feature statements similarly
227 * to libyang.
228 *
229 * @param[in] ctx libyang context.
230 * @param[in] iffeature iffeature array to free.
231 * @param[in] iffeature_size size of array \p iffeature.
232 * @param[in] shallow Whether to make only shallow free.
233 * @param[in] private_destructor Custom destructor for freeing any extension instances.
234 */
235void lys_iffeature_free(struct ly_ctx *ctx, struct lys_iffeature *iffeature, uint8_t iffeature_size, int shallow,
236 void (*private_destructor)(const struct lys_node *node, void *priv));
237
238/**
Radek Krejci8d6b7422017-02-03 14:42:13 +0100239 * @}
240 */
Radek Krejci43ce4b72017-01-04 11:02:38 +0100241
Radek Krejcie534c132016-11-23 13:32:31 +0100242#ifdef __cplusplus
243}
244#endif
245
246#endif /* LY_EXTENSIONS_H_ */